1883529b6Schristos/* MeP opcode support. -*- C -*- 2883529b6Schristos Copyright 2011 Free Software Foundation, Inc. 3883529b6Schristos 4883529b6Schristos Contributed by Red Hat Inc; 5883529b6Schristos 6883529b6Schristos This file is part of the GNU Binutils. 7883529b6Schristos 8883529b6Schristos This program is free software; you can redistribute it and/or modify 9883529b6Schristos it under the terms of the GNU General Public License as published by 10883529b6Schristos the Free Software Foundation; either version 3 of the License, or 11883529b6Schristos (at your option) any later version. 12883529b6Schristos 13883529b6Schristos This program is distributed in the hope that it will be useful, 14883529b6Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 15883529b6Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16883529b6Schristos GNU General Public License for more details. 17883529b6Schristos 18883529b6Schristos You should have received a copy of the GNU General Public License 19883529b6Schristos along with this program; if not, write to the Free Software 20883529b6Schristos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21883529b6Schristos MA 02110-1301, USA. */ 22883529b6Schristos 23883529b6Schristos/* -- opc.h */ 24883529b6Schristos 25883529b6Schristos#undef CGEN_DIS_HASH_SIZE 26883529b6Schristos#define CGEN_DIS_HASH_SIZE 1 27883529b6Schristos 28883529b6Schristos#undef CGEN_DIS_HASH 29883529b6Schristos#define CGEN_DIS_HASH(buffer, insn) 0 30883529b6Schristos 31883529b6Schristos#define CGEN_VERBOSE_ASSEMBLER_ERRORS 32883529b6Schristos 33883529b6Schristostypedef struct 34883529b6Schristos{ 35883529b6Schristos char * name; 36883529b6Schristos int config_enum; 37883529b6Schristos unsigned cpu_flag; 38883529b6Schristos int big_endian; 39883529b6Schristos int vliw_bits; 40883529b6Schristos CGEN_ATTR_VALUE_BITSET_TYPE cop16_isa; 41883529b6Schristos CGEN_ATTR_VALUE_BITSET_TYPE cop32_isa; 42883529b6Schristos CGEN_ATTR_VALUE_BITSET_TYPE cop48_isa; 43883529b6Schristos CGEN_ATTR_VALUE_BITSET_TYPE cop64_isa; 44883529b6Schristos CGEN_ATTR_VALUE_BITSET_TYPE cop_isa; 45883529b6Schristos CGEN_ATTR_VALUE_BITSET_TYPE core_isa; 46883529b6Schristos unsigned int option_mask; 47883529b6Schristos} mep_config_map_struct; 48883529b6Schristos 49883529b6Schristosextern mep_config_map_struct mep_config_map[]; 50883529b6Schristosextern int mep_config_index; 51883529b6Schristos 52883529b6Schristosextern void init_mep_all_core_isas_mask (void); 53883529b6Schristosextern void init_mep_all_cop_isas_mask (void); 54883529b6Schristosextern CGEN_ATTR_VALUE_BITSET_TYPE mep_cop_isa (void); 55883529b6Schristos 56883529b6Schristos#define MEP_CONFIG (mep_config_map[mep_config_index].config_enum) 57883529b6Schristos#define MEP_CPU (mep_config_map[mep_config_index].cpu_flag) 58883529b6Schristos#define MEP_OMASK (mep_config_map[mep_config_index].option_mask) 59883529b6Schristos#define MEP_VLIW (mep_config_map[mep_config_index].vliw_bits > 0) 60883529b6Schristos#define MEP_VLIW32 (mep_config_map[mep_config_index].vliw_bits == 32) 61883529b6Schristos#define MEP_VLIW64 (mep_config_map[mep_config_index].vliw_bits == 64) 62883529b6Schristos#define MEP_COP16_ISA (mep_config_map[mep_config_index].cop16_isa) 63883529b6Schristos#define MEP_COP32_ISA (mep_config_map[mep_config_index].cop32_isa) 64883529b6Schristos#define MEP_COP48_ISA (mep_config_map[mep_config_index].cop48_isa) 65883529b6Schristos#define MEP_COP64_ISA (mep_config_map[mep_config_index].cop64_isa) 66883529b6Schristos#define MEP_COP_ISA (mep_config_map[mep_config_index].cop_isa) 67883529b6Schristos#define MEP_CORE_ISA (mep_config_map[mep_config_index].core_isa) 68883529b6Schristos 69883529b6Schristos/* begin-cop-ip-supported-defines */ 70883529b6Schristos#define MEP_IVC2_SUPPORTED 1 71883529b6Schristos/* end-cop-ip-supported-defines */ 72883529b6Schristos 73883529b6Schristosextern int mep_insn_supported_by_isa (const CGEN_INSN *, CGEN_ATTR_VALUE_BITSET_TYPE *); 74883529b6Schristos 75883529b6Schristos/* A mask for all ISAs executed by the core. */ 76883529b6Schristos#define MEP_ALL_CORE_ISAS_MASK mep_all_core_isas_mask 77883529b6Schristosextern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask; 78883529b6Schristos 79883529b6Schristos#define MEP_INSN_CORE_P(insn) ( \ 80883529b6Schristos init_mep_all_core_isas_mask (), \ 81883529b6Schristos mep_insn_supported_by_isa (insn, & MEP_ALL_CORE_ISAS_MASK) \ 82883529b6Schristos) 83883529b6Schristos 84883529b6Schristos/* A mask for all ISAs executed by a VLIW coprocessor. */ 85883529b6Schristos#define MEP_ALL_COP_ISAS_MASK mep_all_cop_isas_mask 86883529b6Schristosextern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask; 87883529b6Schristos 88883529b6Schristos#define MEP_INSN_COP_P(insn) ( \ 89883529b6Schristos init_mep_all_cop_isas_mask (), \ 90883529b6Schristos mep_insn_supported_by_isa (insn, & MEP_ALL_COP_ISAS_MASK) \ 91883529b6Schristos) 92883529b6Schristos 93883529b6Schristosextern int mep_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *); 94883529b6Schristosextern int mep_cgen_insn_supported_asm (CGEN_CPU_DESC, const CGEN_INSN *); 95883529b6Schristos 96883529b6Schristos/* -- asm.c */ 97883529b6Schristos 98883529b6Schristos#include "elf/mep.h" 99883529b6Schristos 100883529b6Schristos#define CGEN_VALIDATE_INSN_SUPPORTED 101883529b6Schristos#define mep_cgen_insn_supported mep_cgen_insn_supported_asm 102883529b6Schristos 103883529b6Schristos const char * parse_csrn (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *); 104883529b6Schristos const char * parse_tpreg (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *); 105883529b6Schristos const char * parse_spreg (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *); 106883529b6Schristos const char * parse_mep_align (CGEN_CPU_DESC, const char **, enum cgen_operand_type, long *); 107883529b6Schristos const char * parse_mep_alignu (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *); 108883529b6Schristosstatic const char * parse_signed16 (CGEN_CPU_DESC, const char **, int, long *); 109883529b6Schristosstatic const char * parse_signed16_range (CGEN_CPU_DESC, const char **, int, long *) ATTRIBUTE_UNUSED; 110883529b6Schristosstatic const char * parse_unsigned16 (CGEN_CPU_DESC, const char **, int, unsigned long *); 111883529b6Schristosstatic const char * parse_unsigned16_range (CGEN_CPU_DESC, const char **, int, unsigned long *) ATTRIBUTE_UNUSED; 112883529b6Schristosstatic const char * parse_lo16 (CGEN_CPU_DESC, const char **, int, long *, long); 113883529b6Schristosstatic const char * parse_unsigned7 (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *); 114883529b6Schristosstatic const char * parse_zero (CGEN_CPU_DESC, const char **, int, long *); 115883529b6Schristos 116883529b6Schristosconst char * 117883529b6Schristosparse_csrn (CGEN_CPU_DESC cd, const char **strp, 118883529b6Schristos CGEN_KEYWORD *keyword_table, long *field) 119883529b6Schristos{ 120883529b6Schristos const char *err; 121883529b6Schristos unsigned long value; 122883529b6Schristos 123883529b6Schristos err = cgen_parse_keyword (cd, strp, keyword_table, field); 124883529b6Schristos if (!err) 125883529b6Schristos return NULL; 126883529b6Schristos 127883529b6Schristos err = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CSRN_IDX, & value); 128883529b6Schristos if (err) 129883529b6Schristos return err; 130883529b6Schristos *field = value; 131883529b6Schristos return NULL; 132883529b6Schristos} 133883529b6Schristos 134883529b6Schristos/* begin-cop-ip-parse-handlers */ 135883529b6Schristosstatic const char * 136883529b6Schristosparse_ivc2_cr (CGEN_CPU_DESC, 137883529b6Schristos const char **, 138883529b6Schristos CGEN_KEYWORD *, 139883529b6Schristos long *) ATTRIBUTE_UNUSED; 140883529b6Schristosstatic const char * 141883529b6Schristosparse_ivc2_cr (CGEN_CPU_DESC cd, 142883529b6Schristos const char **strp, 143883529b6Schristos CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED, 144883529b6Schristos long *field) 145883529b6Schristos{ 146883529b6Schristos return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr_ivc2, field); 147883529b6Schristos} 148883529b6Schristosstatic const char * 149883529b6Schristosparse_ivc2_ccr (CGEN_CPU_DESC, 150883529b6Schristos const char **, 151883529b6Schristos CGEN_KEYWORD *, 152883529b6Schristos long *) ATTRIBUTE_UNUSED; 153883529b6Schristosstatic const char * 154883529b6Schristosparse_ivc2_ccr (CGEN_CPU_DESC cd, 155883529b6Schristos const char **strp, 156883529b6Schristos CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED, 157883529b6Schristos long *field) 158883529b6Schristos{ 159883529b6Schristos return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr_ivc2, field); 160883529b6Schristos} 161883529b6Schristos/* end-cop-ip-parse-handlers */ 162883529b6Schristos 163883529b6Schristosconst char * 164883529b6Schristosparse_tpreg (CGEN_CPU_DESC cd, const char ** strp, 165883529b6Schristos CGEN_KEYWORD *keyword_table, long *field) 166883529b6Schristos{ 167883529b6Schristos const char *err; 168883529b6Schristos 169883529b6Schristos err = cgen_parse_keyword (cd, strp, keyword_table, field); 170883529b6Schristos if (err) 171883529b6Schristos return err; 172883529b6Schristos if (*field != 13) 173883529b6Schristos return _("Only $tp or $13 allowed for this opcode"); 174883529b6Schristos return NULL; 175883529b6Schristos} 176883529b6Schristos 177883529b6Schristosconst char * 178883529b6Schristosparse_spreg (CGEN_CPU_DESC cd, const char ** strp, 179883529b6Schristos CGEN_KEYWORD *keyword_table, long *field) 180883529b6Schristos{ 181883529b6Schristos const char *err; 182883529b6Schristos 183883529b6Schristos err = cgen_parse_keyword (cd, strp, keyword_table, field); 184883529b6Schristos if (err) 185883529b6Schristos return err; 186883529b6Schristos if (*field != 15) 187883529b6Schristos return _("Only $sp or $15 allowed for this opcode"); 188883529b6Schristos return NULL; 189883529b6Schristos} 190883529b6Schristos 191883529b6Schristosconst char * 192883529b6Schristosparse_mep_align (CGEN_CPU_DESC cd, const char ** strp, 193883529b6Schristos enum cgen_operand_type type, long *field) 194883529b6Schristos{ 195883529b6Schristos long lsbs = 0; 196883529b6Schristos const char *err; 197883529b6Schristos 198883529b6Schristos switch (type) 199883529b6Schristos { 200883529b6Schristos case MEP_OPERAND_PCREL8A2: 201883529b6Schristos case MEP_OPERAND_PCREL12A2: 202883529b6Schristos case MEP_OPERAND_PCREL17A2: 203883529b6Schristos case MEP_OPERAND_PCREL24A2: 204883529b6Schristos err = cgen_parse_signed_integer (cd, strp, type, field); 205883529b6Schristos break; 206883529b6Schristos case MEP_OPERAND_PCABS24A2: 207883529b6Schristos case MEP_OPERAND_UDISP7: 208883529b6Schristos case MEP_OPERAND_UDISP7A2: 209883529b6Schristos case MEP_OPERAND_UDISP7A4: 210883529b6Schristos case MEP_OPERAND_UIMM7A4: 211883529b6Schristos case MEP_OPERAND_ADDR24A4: 212883529b6Schristos err = cgen_parse_unsigned_integer (cd, strp, type, (unsigned long *) field); 213883529b6Schristos break; 214883529b6Schristos default: 215883529b6Schristos abort(); 216883529b6Schristos } 217883529b6Schristos if (err) 218883529b6Schristos return err; 219883529b6Schristos switch (type) 220883529b6Schristos { 221883529b6Schristos case MEP_OPERAND_UDISP7: 222883529b6Schristos lsbs = 0; 223883529b6Schristos break; 224883529b6Schristos case MEP_OPERAND_PCREL8A2: 225883529b6Schristos case MEP_OPERAND_PCREL12A2: 226883529b6Schristos case MEP_OPERAND_PCREL17A2: 227883529b6Schristos case MEP_OPERAND_PCREL24A2: 228883529b6Schristos case MEP_OPERAND_PCABS24A2: 229883529b6Schristos case MEP_OPERAND_UDISP7A2: 230883529b6Schristos lsbs = *field & 1; 231883529b6Schristos break; 232883529b6Schristos case MEP_OPERAND_UDISP7A4: 233883529b6Schristos case MEP_OPERAND_UIMM7A4: 234883529b6Schristos case MEP_OPERAND_ADDR24A4: 235883529b6Schristos lsbs = *field & 3; 236883529b6Schristos break; 237883529b6Schristos lsbs = *field & 7; 238883529b6Schristos break; 239883529b6Schristos default: 240883529b6Schristos /* Safe assumption? */ 241883529b6Schristos abort (); 242883529b6Schristos } 243883529b6Schristos if (lsbs) 244883529b6Schristos return "Value is not aligned enough"; 245883529b6Schristos return NULL; 246883529b6Schristos} 247883529b6Schristos 248883529b6Schristosconst char * 249883529b6Schristosparse_mep_alignu (CGEN_CPU_DESC cd, const char ** strp, 250883529b6Schristos enum cgen_operand_type type, unsigned long *field) 251883529b6Schristos{ 252883529b6Schristos return parse_mep_align (cd, strp, type, (long *) field); 253883529b6Schristos} 254883529b6Schristos 255883529b6Schristos 256883529b6Schristos/* Handle %lo(), %tpoff(), %sdaoff(), %hi(), and other signed 257883529b6Schristos constants in a signed context. */ 258883529b6Schristos 259883529b6Schristosstatic const char * 260883529b6Schristosparse_signed16 (CGEN_CPU_DESC cd, 261883529b6Schristos const char **strp, 262883529b6Schristos int opindex, 263883529b6Schristos long *valuep) 264883529b6Schristos{ 265883529b6Schristos return parse_lo16 (cd, strp, opindex, valuep, 1); 266883529b6Schristos} 267883529b6Schristos 268883529b6Schristosstatic const char * 269883529b6Schristosparse_lo16 (CGEN_CPU_DESC cd, 270883529b6Schristos const char **strp, 271883529b6Schristos int opindex, 272883529b6Schristos long *valuep, 273883529b6Schristos long signedp) 274883529b6Schristos{ 275883529b6Schristos const char *errmsg; 276883529b6Schristos enum cgen_parse_operand_result result_type; 277883529b6Schristos bfd_vma value; 278883529b6Schristos 279883529b6Schristos if (strncasecmp (*strp, "%lo(", 4) == 0) 280883529b6Schristos { 281883529b6Schristos *strp += 4; 282883529b6Schristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16, 283883529b6Schristos & result_type, & value); 284883529b6Schristos if (**strp != ')') 285883529b6Schristos return _("missing `)'"); 286883529b6Schristos ++*strp; 287883529b6Schristos if (errmsg == NULL 288883529b6Schristos && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 289883529b6Schristos value &= 0xffff; 290883529b6Schristos if (signedp) 291883529b6Schristos *valuep = (long)(short) value; 292883529b6Schristos else 293883529b6Schristos *valuep = value; 294883529b6Schristos return errmsg; 295883529b6Schristos } 296883529b6Schristos 297883529b6Schristos if (strncasecmp (*strp, "%hi(", 4) == 0) 298883529b6Schristos { 299883529b6Schristos *strp += 4; 300883529b6Schristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S, 301883529b6Schristos & result_type, & value); 302883529b6Schristos if (**strp != ')') 303883529b6Schristos return _("missing `)'"); 304883529b6Schristos ++*strp; 305883529b6Schristos if (errmsg == NULL 306883529b6Schristos && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 307883529b6Schristos value = (value + 0x8000) >> 16; 308883529b6Schristos *valuep = value; 309883529b6Schristos return errmsg; 310883529b6Schristos } 311883529b6Schristos 312883529b6Schristos if (strncasecmp (*strp, "%uhi(", 5) == 0) 313883529b6Schristos { 314883529b6Schristos *strp += 5; 315883529b6Schristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U, 316883529b6Schristos & result_type, & value); 317883529b6Schristos if (**strp != ')') 318883529b6Schristos return _("missing `)'"); 319883529b6Schristos ++*strp; 320883529b6Schristos if (errmsg == NULL 321883529b6Schristos && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 322883529b6Schristos value = value >> 16; 323883529b6Schristos *valuep = value; 324883529b6Schristos return errmsg; 325883529b6Schristos } 326883529b6Schristos 327883529b6Schristos if (strncasecmp (*strp, "%sdaoff(", 8) == 0) 328883529b6Schristos { 329883529b6Schristos *strp += 8; 330883529b6Schristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL, 331883529b6Schristos NULL, & value); 332883529b6Schristos if (**strp != ')') 333883529b6Schristos return _("missing `)'"); 334883529b6Schristos ++*strp; 335883529b6Schristos *valuep = value; 336883529b6Schristos return errmsg; 337883529b6Schristos } 338883529b6Schristos 339883529b6Schristos if (strncasecmp (*strp, "%tpoff(", 7) == 0) 340883529b6Schristos { 341883529b6Schristos *strp += 7; 342883529b6Schristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL, 343883529b6Schristos NULL, & value); 344883529b6Schristos if (**strp != ')') 345883529b6Schristos return _("missing `)'"); 346883529b6Schristos ++*strp; 347883529b6Schristos *valuep = value; 348883529b6Schristos return errmsg; 349883529b6Schristos } 350883529b6Schristos 351883529b6Schristos if (**strp == '%') 352883529b6Schristos return _("invalid %function() here"); 353883529b6Schristos 354883529b6Schristos return cgen_parse_signed_integer (cd, strp, opindex, valuep); 355883529b6Schristos} 356883529b6Schristos 357883529b6Schristosstatic const char * 358883529b6Schristosparse_unsigned16 (CGEN_CPU_DESC cd, 359883529b6Schristos const char **strp, 360883529b6Schristos int opindex, 361883529b6Schristos unsigned long *valuep) 362883529b6Schristos{ 363883529b6Schristos return parse_lo16 (cd, strp, opindex, (long *) valuep, 0); 364883529b6Schristos} 365883529b6Schristos 366883529b6Schristosstatic const char * 367883529b6Schristosparse_signed16_range (CGEN_CPU_DESC cd, 368883529b6Schristos const char **strp, 369883529b6Schristos int opindex, 370883529b6Schristos signed long *valuep) 371883529b6Schristos{ 372883529b6Schristos const char *errmsg = 0; 373883529b6Schristos signed long value; 374883529b6Schristos 375883529b6Schristos errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); 376883529b6Schristos if (errmsg) 377883529b6Schristos return errmsg; 378883529b6Schristos 379883529b6Schristos if (value < -32768 || value > 32767) 380883529b6Schristos return _("Immediate is out of range -32768 to 32767"); 381883529b6Schristos 382883529b6Schristos *valuep = value; 383883529b6Schristos return 0; 384883529b6Schristos} 385883529b6Schristos 386883529b6Schristosstatic const char * 387883529b6Schristosparse_unsigned16_range (CGEN_CPU_DESC cd, 388883529b6Schristos const char **strp, 389883529b6Schristos int opindex, 390883529b6Schristos unsigned long *valuep) 391883529b6Schristos{ 392883529b6Schristos const char *errmsg = 0; 393883529b6Schristos unsigned long value; 394883529b6Schristos 395883529b6Schristos errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value); 396883529b6Schristos if (errmsg) 397883529b6Schristos return errmsg; 398883529b6Schristos 399883529b6Schristos if (value > 65535) 400883529b6Schristos return _("Immediate is out of range 0 to 65535"); 401883529b6Schristos 402883529b6Schristos *valuep = value; 403883529b6Schristos return 0; 404883529b6Schristos} 405883529b6Schristos 406883529b6Schristos/* A special case of parse_signed16 which accepts only the value zero. */ 407883529b6Schristos 408883529b6Schristosstatic const char * 409883529b6Schristosparse_zero (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep) 410883529b6Schristos{ 411883529b6Schristos const char *errmsg; 412883529b6Schristos enum cgen_parse_operand_result result_type; 413883529b6Schristos bfd_vma value; 414883529b6Schristos 415883529b6Schristos /*fprintf(stderr, "dj: signed parse opindex `%s'\n", *strp);*/ 416883529b6Schristos 417883529b6Schristos /* Prevent ($ry) from being attempted as an expression on 'sw $rx,($ry)'. 418883529b6Schristos It will fail and cause ry to be listed as an undefined symbol in the 419883529b6Schristos listing. */ 420883529b6Schristos if (strncmp (*strp, "($", 2) == 0) 421883529b6Schristos return "not zero"; /* any string will do -- will never be seen. */ 422883529b6Schristos 423883529b6Schristos if (strncasecmp (*strp, "%lo(", 4) == 0) 424883529b6Schristos { 425883529b6Schristos *strp += 4; 426883529b6Schristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16, 427883529b6Schristos &result_type, &value); 428883529b6Schristos if (**strp != ')') 429883529b6Schristos return "missing `)'"; 430883529b6Schristos ++*strp; 431883529b6Schristos if (errmsg == NULL 432883529b6Schristos && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 433883529b6Schristos return "not zero"; /* any string will do -- will never be seen. */ 434883529b6Schristos *valuep = value; 435883529b6Schristos return errmsg; 436883529b6Schristos } 437883529b6Schristos 438883529b6Schristos if (strncasecmp (*strp, "%hi(", 4) == 0) 439883529b6Schristos { 440883529b6Schristos *strp += 4; 441883529b6Schristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S, 442883529b6Schristos &result_type, &value); 443883529b6Schristos if (**strp != ')') 444883529b6Schristos return "missing `)'"; 445883529b6Schristos ++*strp; 446883529b6Schristos if (errmsg == NULL 447883529b6Schristos && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 448883529b6Schristos return "not zero"; /* any string will do -- will never be seen. */ 449883529b6Schristos *valuep = value; 450883529b6Schristos return errmsg; 451883529b6Schristos } 452883529b6Schristos 453883529b6Schristos if (strncasecmp (*strp, "%uhi(", 5) == 0) 454883529b6Schristos { 455883529b6Schristos *strp += 5; 456883529b6Schristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U, 457883529b6Schristos &result_type, &value); 458883529b6Schristos if (**strp != ')') 459883529b6Schristos return "missing `)'"; 460883529b6Schristos ++*strp; 461883529b6Schristos if (errmsg == NULL 462883529b6Schristos && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 463883529b6Schristos return "not zero"; /* any string will do -- will never be seen. */ 464883529b6Schristos *valuep = value; 465883529b6Schristos return errmsg; 466883529b6Schristos } 467883529b6Schristos 468883529b6Schristos if (strncasecmp (*strp, "%sdaoff(", 8) == 0) 469883529b6Schristos { 470883529b6Schristos *strp += 8; 471883529b6Schristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL, 472883529b6Schristos &result_type, &value); 473883529b6Schristos if (**strp != ')') 474883529b6Schristos return "missing `)'"; 475883529b6Schristos ++*strp; 476883529b6Schristos if (errmsg == NULL 477883529b6Schristos && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 478883529b6Schristos return "not zero"; /* any string will do -- will never be seen. */ 479883529b6Schristos *valuep = value; 480883529b6Schristos return errmsg; 481883529b6Schristos } 482883529b6Schristos 483883529b6Schristos if (strncasecmp (*strp, "%tpoff(", 7) == 0) 484883529b6Schristos { 485883529b6Schristos *strp += 7; 486883529b6Schristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL, 487883529b6Schristos &result_type, &value); 488883529b6Schristos if (**strp != ')') 489883529b6Schristos return "missing `)'"; 490883529b6Schristos ++*strp; 491883529b6Schristos if (errmsg == NULL 492883529b6Schristos && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 493883529b6Schristos return "not zero"; /* any string will do -- will never be seen. */ 494883529b6Schristos *valuep = value; 495883529b6Schristos return errmsg; 496883529b6Schristos } 497883529b6Schristos 498883529b6Schristos if (**strp == '%') 499883529b6Schristos return "invalid %function() here"; 500883529b6Schristos 501883529b6Schristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_NONE, 502883529b6Schristos &result_type, &value); 503883529b6Schristos if (errmsg == NULL 504883529b6Schristos && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 505883529b6Schristos return "not zero"; /* any string will do -- will never be seen. */ 506883529b6Schristos 507883529b6Schristos return errmsg; 508883529b6Schristos} 509883529b6Schristos 510883529b6Schristosstatic const char * 511883529b6Schristosparse_unsigned7 (CGEN_CPU_DESC cd, const char **strp, 512883529b6Schristos enum cgen_operand_type opindex, unsigned long *valuep) 513883529b6Schristos{ 514883529b6Schristos const char *errmsg; 515883529b6Schristos bfd_vma value; 516883529b6Schristos 517883529b6Schristos /* fprintf(stderr, "dj: unsigned7 parse `%s'\n", *strp); */ 518883529b6Schristos 519883529b6Schristos if (strncasecmp (*strp, "%tpoff(", 7) == 0) 520883529b6Schristos { 521883529b6Schristos int reloc; 522883529b6Schristos *strp += 7; 523883529b6Schristos switch (opindex) 524883529b6Schristos { 525883529b6Schristos case MEP_OPERAND_UDISP7: 526883529b6Schristos reloc = BFD_RELOC_MEP_TPREL7; 527883529b6Schristos break; 528883529b6Schristos case MEP_OPERAND_UDISP7A2: 529883529b6Schristos reloc = BFD_RELOC_MEP_TPREL7A2; 530883529b6Schristos break; 531883529b6Schristos case MEP_OPERAND_UDISP7A4: 532883529b6Schristos reloc = BFD_RELOC_MEP_TPREL7A4; 533883529b6Schristos break; 534883529b6Schristos default: 535883529b6Schristos /* Safe assumption? */ 536883529b6Schristos abort (); 537883529b6Schristos } 538883529b6Schristos errmsg = cgen_parse_address (cd, strp, opindex, reloc, 539883529b6Schristos NULL, &value); 540883529b6Schristos if (**strp != ')') 541883529b6Schristos return "missing `)'"; 542883529b6Schristos ++*strp; 543883529b6Schristos *valuep = value; 544883529b6Schristos return errmsg; 545883529b6Schristos } 546883529b6Schristos 547883529b6Schristos if (**strp == '%') 548883529b6Schristos return _("invalid %function() here"); 549883529b6Schristos 550883529b6Schristos return parse_mep_alignu (cd, strp, opindex, valuep); 551883529b6Schristos} 552883529b6Schristos 553883529b6Schristosstatic ATTRIBUTE_UNUSED const char * 554883529b6Schristosparse_cdisp10 (CGEN_CPU_DESC cd, 555883529b6Schristos const char **strp, 556883529b6Schristos int opindex, 557883529b6Schristos long *valuep) 558883529b6Schristos{ 559883529b6Schristos const char *errmsg = 0; 560883529b6Schristos signed long value; 561883529b6Schristos long have_zero = 0; 562883529b6Schristos int wide = 0; 563883529b6Schristos int alignment; 564883529b6Schristos 565883529b6Schristos switch (opindex) 566883529b6Schristos { 567883529b6Schristos case MEP_OPERAND_CDISP10A4: 568883529b6Schristos alignment = 2; 569883529b6Schristos break; 570883529b6Schristos case MEP_OPERAND_CDISP10A2: 571883529b6Schristos alignment = 1; 572883529b6Schristos break; 573883529b6Schristos case MEP_OPERAND_CDISP10: 574883529b6Schristos default: 575883529b6Schristos alignment = 0; 576883529b6Schristos break; 577883529b6Schristos } 578883529b6Schristos 579883529b6Schristos if ((MEP_CPU & EF_MEP_CPU_MASK) == EF_MEP_CPU_C5) 580883529b6Schristos wide = 1; 581883529b6Schristos 582883529b6Schristos if (strncmp (*strp, "0x0", 3) == 0 583883529b6Schristos || (**strp == '0' && *(*strp + 1) != 'x')) 584883529b6Schristos have_zero = 1; 585883529b6Schristos 586883529b6Schristos errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); 587883529b6Schristos if (errmsg) 588883529b6Schristos return errmsg; 589883529b6Schristos 590883529b6Schristos if (wide) 591883529b6Schristos { 592883529b6Schristos if (value < -512 || value > 511) 593883529b6Schristos return _("Immediate is out of range -512 to 511"); 594883529b6Schristos } 595883529b6Schristos else 596883529b6Schristos { 597883529b6Schristos if (value < -128 || value > 127) 598883529b6Schristos return _("Immediate is out of range -128 to 127"); 599883529b6Schristos } 600883529b6Schristos 601883529b6Schristos if (value & ((1<<alignment)-1)) 602883529b6Schristos return _("Value is not aligned enough"); 603883529b6Schristos 604883529b6Schristos /* If this field may require a relocation then use larger dsp16. */ 605883529b6Schristos if (! have_zero && value == 0) 606883529b6Schristos return (wide ? _("Immediate is out of range -512 to 511") 607883529b6Schristos : _("Immediate is out of range -128 to 127")); 608883529b6Schristos 609883529b6Schristos *valuep = value; 610883529b6Schristos return 0; 611883529b6Schristos} 612883529b6Schristos 613883529b6Schristos/* BEGIN LIGHTWEIGHT MACRO PROCESSOR. */ 614883529b6Schristos 615883529b6Schristos#define MAXARGS 9 616883529b6Schristos 617883529b6Schristostypedef struct 618883529b6Schristos{ 619883529b6Schristos char *name; 620883529b6Schristos char *expansion; 621883529b6Schristos} macro; 622883529b6Schristos 623883529b6Schristostypedef struct 624883529b6Schristos{ 625883529b6Schristos const char *start; 626883529b6Schristos int len; 627883529b6Schristos} arg; 628883529b6Schristos 6294f645668Schristosstatic macro const macros[] = 630883529b6Schristos{ 631883529b6Schristos { "sizeof", "(`1.end + (- `1))"}, 632883529b6Schristos { "startof", "(`1 | 0)" }, 633883529b6Schristos { "align4", "(`1&(~3))"}, 634883529b6Schristos/*{ "hi", "(((`1+0x8000)>>16) & 0xffff)" }, */ 635883529b6Schristos/*{ "lo", "(`1 & 0xffff)" }, */ 636883529b6Schristos/*{ "sdaoff", "((`1-__sdabase) & 0x7f)"}, */ 637883529b6Schristos/*{ "tpoff", "((`1-__tpbase) & 0x7f)"}, */ 638883529b6Schristos { 0,0 } 639883529b6Schristos}; 640883529b6Schristos 641883529b6Schristosstatic char * expand_string (const char *, int); 642883529b6Schristos 643883529b6Schristosstatic const char * 644883529b6Schristosmep_cgen_expand_macros_and_parse_operand 645883529b6Schristos (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *); 646883529b6Schristos 647883529b6Schristosstatic char * 648883529b6Schristosstr_append (char *dest, const char *input, int len) 649883529b6Schristos{ 650883529b6Schristos char *new_dest; 651883529b6Schristos int oldlen; 652883529b6Schristos 653883529b6Schristos if (len == 0) 654883529b6Schristos return dest; 655883529b6Schristos /* printf("str_append: <<%s>>, <<%s>>, %d\n", dest, input, len); */ 656883529b6Schristos oldlen = (dest ? strlen(dest) : 0); 657883529b6Schristos new_dest = realloc (dest, oldlen + len + 1); 658883529b6Schristos memset (new_dest + oldlen, 0, len + 1); 659883529b6Schristos return strncat (new_dest, input, len); 660883529b6Schristos} 661883529b6Schristos 6624f645668Schristosstatic const macro * 663883529b6Schristoslookup_macro (const char *name) 664883529b6Schristos{ 6654f645668Schristos const macro *m; 666883529b6Schristos 667883529b6Schristos for (m = macros; m->name; ++m) 668883529b6Schristos if (strncmp (m->name, name, strlen(m->name)) == 0) 669883529b6Schristos return m; 670883529b6Schristos 671883529b6Schristos return 0; 672883529b6Schristos} 673883529b6Schristos 674883529b6Schristosstatic char * 6754f645668Schristosexpand_macro (arg *args, int narg, const macro *mac) 676883529b6Schristos{ 677883529b6Schristos char *result = 0, *rescanned_result = 0; 678883529b6Schristos char *e = mac->expansion; 679883529b6Schristos char *mark = e; 680883529b6Schristos int mac_arg = 0; 681883529b6Schristos 682883529b6Schristos /* printf("expanding macro %s with %d args\n", mac->name, narg + 1); */ 683883529b6Schristos while (*e) 684883529b6Schristos { 685*cb63e24eSchristos if (*e == '`' 686*cb63e24eSchristos && (*e+1) 687*cb63e24eSchristos && ((*(e + 1) - '1') <= MAXARGS) 688*cb63e24eSchristos && ((*(e + 1) - '1') <= narg)) 689883529b6Schristos { 690883529b6Schristos result = str_append (result, mark, e - mark); 691883529b6Schristos mac_arg = (*(e + 1) - '1'); 692883529b6Schristos /* printf("replacing `%d with %s\n", mac_arg+1, args[mac_arg].start); */ 693883529b6Schristos result = str_append (result, args[mac_arg].start, args[mac_arg].len); 694883529b6Schristos ++e; 695883529b6Schristos mark = e+1; 696883529b6Schristos } 697883529b6Schristos ++e; 698883529b6Schristos } 699883529b6Schristos 700883529b6Schristos if (mark != e) 701883529b6Schristos result = str_append (result, mark, e - mark); 702883529b6Schristos 703883529b6Schristos if (result) 704883529b6Schristos { 705883529b6Schristos rescanned_result = expand_string (result, 0); 706883529b6Schristos free (result); 707883529b6Schristos return rescanned_result; 708883529b6Schristos } 709883529b6Schristos else 710883529b6Schristos return result; 711883529b6Schristos} 712883529b6Schristos 713883529b6Schristos#define IN_TEXT 0 714883529b6Schristos#define IN_ARGS 1 715883529b6Schristos 716883529b6Schristosstatic char * 717883529b6Schristosexpand_string (const char *in, int first_only) 718883529b6Schristos{ 719883529b6Schristos int num_expansions = 0; 720883529b6Schristos int depth = 0; 721883529b6Schristos int narg = -1; 722883529b6Schristos arg args[MAXARGS]; 723883529b6Schristos int state = IN_TEXT; 724883529b6Schristos const char *mark = in; 7254f645668Schristos const macro *pmacro = NULL; 726883529b6Schristos char *expansion = 0; 727883529b6Schristos char *result = 0; 728883529b6Schristos 729883529b6Schristos while (*in) 730883529b6Schristos { 731883529b6Schristos switch (state) 732883529b6Schristos { 733883529b6Schristos case IN_TEXT: 734883529b6Schristos if (*in == '%' && *(in + 1) && (!first_only || num_expansions == 0)) 735883529b6Schristos { 736883529b6Schristos pmacro = lookup_macro (in + 1); 737883529b6Schristos if (pmacro) 738883529b6Schristos { 739883529b6Schristos /* printf("entering state %d at '%s'...\n", state, in); */ 740883529b6Schristos result = str_append (result, mark, in - mark); 741883529b6Schristos mark = in; 742883529b6Schristos in += 1 + strlen (pmacro->name); 743883529b6Schristos while (*in == ' ') ++in; 744883529b6Schristos if (*in != '(') 745883529b6Schristos { 746883529b6Schristos state = IN_TEXT; 747883529b6Schristos pmacro = NULL; 748883529b6Schristos } 749883529b6Schristos else 750883529b6Schristos { 751883529b6Schristos state = IN_ARGS; 752883529b6Schristos narg = 0; 753883529b6Schristos args[narg].start = in + 1; 754883529b6Schristos args[narg].len = 0; 755883529b6Schristos mark = in + 1; 756883529b6Schristos } 757883529b6Schristos } 758883529b6Schristos } 759883529b6Schristos break; 760883529b6Schristos case IN_ARGS: 761883529b6Schristos if (depth == 0) 762883529b6Schristos { 763883529b6Schristos switch (*in) 764883529b6Schristos { 765883529b6Schristos case ',': 766883529b6Schristos narg++; 767883529b6Schristos args[narg].start = (in + 1); 768883529b6Schristos args[narg].len = 0; 769883529b6Schristos break; 770883529b6Schristos case ')': 771883529b6Schristos state = IN_TEXT; 772883529b6Schristos /* printf("entering state %d at '%s'...\n", state, in); */ 773883529b6Schristos if (pmacro) 774883529b6Schristos { 775883529b6Schristos expansion = 0; 776883529b6Schristos expansion = expand_macro (args, narg, pmacro); 777883529b6Schristos num_expansions++; 778883529b6Schristos if (expansion) 779883529b6Schristos { 780883529b6Schristos result = str_append (result, expansion, strlen (expansion)); 781883529b6Schristos free (expansion); 782883529b6Schristos } 783883529b6Schristos } 784883529b6Schristos else 785883529b6Schristos { 786883529b6Schristos result = str_append (result, mark, in - mark); 787883529b6Schristos } 788883529b6Schristos pmacro = NULL; 789883529b6Schristos mark = in + 1; 790883529b6Schristos break; 791883529b6Schristos case '(': 792883529b6Schristos depth++; 793fc4f4269Schristos /* Fall through. */ 794883529b6Schristos default: 795883529b6Schristos args[narg].len++; 796883529b6Schristos break; 797883529b6Schristos } 798883529b6Schristos } 799883529b6Schristos else 800883529b6Schristos { 801883529b6Schristos if (*in == ')') 802883529b6Schristos depth--; 803883529b6Schristos if (narg > -1) 804883529b6Schristos args[narg].len++; 805883529b6Schristos } 806883529b6Schristos } 807883529b6Schristos ++in; 808883529b6Schristos } 809883529b6Schristos 810883529b6Schristos if (mark != in) 811883529b6Schristos result = str_append (result, mark, in - mark); 812883529b6Schristos 813883529b6Schristos return result; 814883529b6Schristos} 815883529b6Schristos 816883529b6Schristos#undef IN_ARGS 817883529b6Schristos#undef IN_TEXT 818883529b6Schristos#undef MAXARGS 819883529b6Schristos 820883529b6Schristos 821883529b6Schristos/* END LIGHTWEIGHT MACRO PROCESSOR. */ 822883529b6Schristos 823883529b6Schristosconst char * mep_cgen_parse_operand 824883529b6Schristos (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *); 825883529b6Schristos 826883529b6Schristosconst char * 827883529b6Schristosmep_cgen_expand_macros_and_parse_operand (CGEN_CPU_DESC cd, int opindex, 828883529b6Schristos const char ** strp_in, CGEN_FIELDS * fields) 829883529b6Schristos{ 830883529b6Schristos const char * errmsg = NULL; 831883529b6Schristos char *str = 0, *hold = 0; 832883529b6Schristos const char **strp = 0; 833883529b6Schristos 834883529b6Schristos /* Set up a new pointer to macro-expanded string. */ 835883529b6Schristos str = expand_string (*strp_in, 1); 836883529b6Schristos /* fprintf (stderr, " expanded <<%s>> to <<%s>>\n", *strp_in, str); */ 837883529b6Schristos 838883529b6Schristos hold = str; 839883529b6Schristos strp = (const char **)(&str); 840883529b6Schristos 841883529b6Schristos errmsg = mep_cgen_parse_operand (cd, opindex, strp, fields); 842883529b6Schristos 843883529b6Schristos /* Now work out the advance. */ 844883529b6Schristos if (strlen (str) == 0) 845883529b6Schristos *strp_in += strlen (*strp_in); 846883529b6Schristos 847883529b6Schristos else 848883529b6Schristos { 849883529b6Schristos if (strstr (*strp_in, str)) 850883529b6Schristos /* A macro-expansion was pulled off the front. */ 851883529b6Schristos *strp_in = strstr (*strp_in, str); 852883529b6Schristos else 853883529b6Schristos /* A non-macro-expansion was pulled off the front. */ 854883529b6Schristos *strp_in += (str - hold); 855883529b6Schristos } 856883529b6Schristos 857883529b6Schristos free (hold); 858883529b6Schristos 859883529b6Schristos return errmsg; 860883529b6Schristos} 861883529b6Schristos 862883529b6Schristos#define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand); 863883529b6Schristos 864883529b6Schristos/* -- dis.c */ 865883529b6Schristos 866883529b6Schristos#include "elf/mep.h" 867883529b6Schristos#include "elf-bfd.h" 868883529b6Schristos 869883529b6Schristos#define CGEN_VALIDATE_INSN_SUPPORTED 870883529b6Schristos 871883529b6Schristosstatic void 8724f645668Schristosprint_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, void *dis_info, 873883529b6Schristos CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED, 874883529b6Schristos unsigned int flags ATTRIBUTE_UNUSED) 875883529b6Schristos{ 876883529b6Schristos disassemble_info *info = (disassemble_info *) dis_info; 877883529b6Schristos 878883529b6Schristos (*info->fprintf_func) (info->stream, "$tp"); 879883529b6Schristos} 880883529b6Schristos 881883529b6Schristosstatic void 8824f645668Schristosprint_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, void *dis_info, 883883529b6Schristos CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED, 884883529b6Schristos unsigned int flags ATTRIBUTE_UNUSED) 885883529b6Schristos{ 886883529b6Schristos disassemble_info *info = (disassemble_info *) dis_info; 887883529b6Schristos 888883529b6Schristos (*info->fprintf_func) (info->stream, "$sp"); 889883529b6Schristos} 890883529b6Schristos 891883529b6Schristos/* begin-cop-ip-print-handlers */ 892883529b6Schristosstatic void 893883529b6Schristosprint_ivc2_cr (CGEN_CPU_DESC, 894883529b6Schristos void *, 895883529b6Schristos CGEN_KEYWORD *, 896883529b6Schristos long, 897883529b6Schristos unsigned int) ATTRIBUTE_UNUSED; 898883529b6Schristosstatic void 899883529b6Schristosprint_ivc2_cr (CGEN_CPU_DESC cd, 900883529b6Schristos void *dis_info, 901883529b6Schristos CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED, 902883529b6Schristos long value, 903883529b6Schristos unsigned int attrs) 904883529b6Schristos{ 905883529b6Schristos print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_ivc2, value, attrs); 906883529b6Schristos} 907883529b6Schristosstatic void 908883529b6Schristosprint_ivc2_ccr (CGEN_CPU_DESC, 909883529b6Schristos void *, 910883529b6Schristos CGEN_KEYWORD *, 911883529b6Schristos long, 912883529b6Schristos unsigned int) ATTRIBUTE_UNUSED; 913883529b6Schristosstatic void 914883529b6Schristosprint_ivc2_ccr (CGEN_CPU_DESC cd, 915883529b6Schristos void *dis_info, 916883529b6Schristos CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED, 917883529b6Schristos long value, 918883529b6Schristos unsigned int attrs) 919883529b6Schristos{ 920883529b6Schristos print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_ivc2, value, attrs); 921883529b6Schristos} 922883529b6Schristos/* end-cop-ip-print-handlers */ 923883529b6Schristos 924883529b6Schristos/************************************************************\ 925883529b6Schristos*********************** Experimental ************************* 926883529b6Schristos\************************************************************/ 927883529b6Schristos 928883529b6Schristos#undef CGEN_PRINT_INSN 929883529b6Schristos#define CGEN_PRINT_INSN mep_print_insn 930883529b6Schristos 931883529b6Schristosstatic int 932883529b6Schristosmep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info, 933883529b6Schristos bfd_byte *buf, int corelength, int copro1length, 934883529b6Schristos int copro2length ATTRIBUTE_UNUSED) 935883529b6Schristos{ 936883529b6Schristos int i; 937883529b6Schristos int status = 0; 938883529b6Schristos /* char insnbuf[CGEN_MAX_INSN_SIZE]; */ 939883529b6Schristos bfd_byte insnbuf[64]; 940883529b6Schristos 941883529b6Schristos /* If corelength > 0 then there is a core insn present. It 942883529b6Schristos will be at the beginning of the buffer. After printing 943883529b6Schristos the core insn, we need to print the + on the next line. */ 944883529b6Schristos if (corelength > 0) 945883529b6Schristos { 946883529b6Schristos int my_status = 0; 947883529b6Schristos 948883529b6Schristos for (i = 0; i < corelength; i++ ) 949883529b6Schristos insnbuf[i] = buf[i]; 950883529b6Schristos cd->isas = & MEP_CORE_ISA; 951883529b6Schristos 952883529b6Schristos my_status = print_insn (cd, pc, info, insnbuf, corelength); 953883529b6Schristos if (my_status != corelength) 954883529b6Schristos { 955883529b6Schristos (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); 956883529b6Schristos my_status = corelength; 957883529b6Schristos } 958883529b6Schristos status += my_status; 959883529b6Schristos 960*cb63e24eSchristos /* Print the + to indicate that the following copro insn is 961*cb63e24eSchristos part of a vliw group. */ 962883529b6Schristos if (copro1length > 0) 963883529b6Schristos (*info->fprintf_func) (info->stream, " + "); 964883529b6Schristos } 965883529b6Schristos 966883529b6Schristos /* Now all that is left to be processed is the coprocessor insns 967883529b6Schristos In vliw mode, there will always be one. Its positioning will 968883529b6Schristos be from byte corelength to byte corelength+copro1length -1. 969883529b6Schristos No need to check for existence. Also, the first vliw insn, 970883529b6Schristos will, as spec'd, always be at least as long as the core insn 971883529b6Schristos so we don't need to flush the buffer. */ 972883529b6Schristos if (copro1length > 0) 973883529b6Schristos { 974883529b6Schristos int my_status = 0; 975883529b6Schristos 976883529b6Schristos for (i = corelength; i < corelength + copro1length; i++ ) 977883529b6Schristos insnbuf[i - corelength] = buf[i]; 978883529b6Schristos 979883529b6Schristos switch (copro1length) 980883529b6Schristos { 981883529b6Schristos case 0: 982883529b6Schristos break; 983883529b6Schristos case 2: 984883529b6Schristos cd->isas = & MEP_COP16_ISA; 985883529b6Schristos break; 986883529b6Schristos case 4: 987883529b6Schristos cd->isas = & MEP_COP32_ISA; 988883529b6Schristos break; 989883529b6Schristos case 6: 990883529b6Schristos cd->isas = & MEP_COP48_ISA; 991883529b6Schristos break; 992883529b6Schristos case 8: 993883529b6Schristos cd->isas = & MEP_COP64_ISA; 994883529b6Schristos break; 995883529b6Schristos default: 996883529b6Schristos /* Shouldn't be anything but 16,32,48,64. */ 997883529b6Schristos break; 998883529b6Schristos } 999883529b6Schristos 1000883529b6Schristos my_status = print_insn (cd, pc, info, insnbuf, copro1length); 1001883529b6Schristos 1002883529b6Schristos if (my_status != copro1length) 1003883529b6Schristos { 1004883529b6Schristos (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); 1005883529b6Schristos my_status = copro1length; 1006883529b6Schristos } 1007883529b6Schristos status += my_status; 1008883529b6Schristos } 1009883529b6Schristos 1010883529b6Schristos#if 0 1011883529b6Schristos /* Now we need to process the second copro insn if it exists. We 1012883529b6Schristos have no guarantee that the second copro insn will be longer 1013883529b6Schristos than the first, so we have to flush the buffer if we are have 1014883529b6Schristos a second copro insn to process. If present, this insn will 1015883529b6Schristos be in the position from byte corelength+copro1length to byte 1016883529b6Schristos corelength+copro1length+copro2length-1 (which better equal 8 1017883529b6Schristos or else we're in big trouble. */ 1018883529b6Schristos if (copro2length > 0) 1019883529b6Schristos { 1020883529b6Schristos int my_status = 0; 1021883529b6Schristos 1022883529b6Schristos for (i = 0; i < 64 ; i++) 1023883529b6Schristos insnbuf[i] = 0; 1024883529b6Schristos 1025883529b6Schristos for (i = corelength + copro1length; i < 64; i++) 1026883529b6Schristos insnbuf[i - (corelength + copro1length)] = buf[i]; 1027883529b6Schristos 1028883529b6Schristos switch (copro2length) 1029883529b6Schristos { 1030883529b6Schristos case 2: 1031883529b6Schristos cd->isas = 1 << ISA_EXT_COP1_16; 1032883529b6Schristos break; 1033883529b6Schristos case 4: 1034883529b6Schristos cd->isas = 1 << ISA_EXT_COP1_32; 1035883529b6Schristos break; 1036883529b6Schristos case 6: 1037883529b6Schristos cd->isas = 1 << ISA_EXT_COP1_48; 1038883529b6Schristos break; 1039883529b6Schristos case 8: 1040883529b6Schristos cd->isas = 1 << ISA_EXT_COP1_64; 1041883529b6Schristos break; 1042883529b6Schristos default: 1043883529b6Schristos /* Shouldn't be anything but 16,32,48,64. */ 1044883529b6Schristos break; 1045883529b6Schristos } 1046883529b6Schristos 1047883529b6Schristos my_status = print_insn (cd, pc, info, insnbuf, copro2length); 1048883529b6Schristos 1049883529b6Schristos if (my_status != copro2length) 1050883529b6Schristos { 1051883529b6Schristos (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); 1052883529b6Schristos my_status = copro2length; 1053883529b6Schristos } 1054883529b6Schristos 1055883529b6Schristos status += my_status; 1056883529b6Schristos } 1057883529b6Schristos#endif 1058883529b6Schristos 1059883529b6Schristos /* Status should now be the number of bytes that were printed 1060883529b6Schristos which should be 4 for VLIW32 mode and 64 for VLIW64 mode. */ 1061883529b6Schristos 1062883529b6Schristos if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8))) 1063883529b6Schristos return -1; 1064883529b6Schristos else 1065883529b6Schristos return status; 1066883529b6Schristos} 1067883529b6Schristos 1068883529b6Schristos/* The two functions mep_examine_vliw[32,64]_insns are used find out 1069883529b6Schristos which vliw combinaion (16 bit core with 48 bit copro, 32 bit core 1070883529b6Schristos with 32 bit copro, etc.) is present. Later on, when internally 1071883529b6Schristos parallel coprocessors are handled, only these functions should 1072883529b6Schristos need to be changed. 1073883529b6Schristos 1074883529b6Schristos At this time only the following combinations are supported: 1075883529b6Schristos 1076883529b6Schristos VLIW32 Mode: 1077883529b6Schristos 16 bit core insn (core) and 16 bit coprocessor insn (cop1) 1078883529b6Schristos 32 bit core insn (core) 1079883529b6Schristos 32 bit coprocessor insn (cop1) 1080883529b6Schristos Note: As of this time, I do not believe we have enough information 1081883529b6Schristos to distinguish a 32 bit core insn from a 32 bit cop insn. Also, 1082883529b6Schristos no 16 bit coprocessor insns have been specified. 1083883529b6Schristos 1084883529b6Schristos VLIW64 Mode: 1085883529b6Schristos 16 bit core insn (core) and 48 bit coprocessor insn (cop1) 1086883529b6Schristos 32 bit core insn (core) and 32 bit coprocessor insn (cop1) 1087883529b6Schristos 64 bit coprocessor insn (cop1) 1088883529b6Schristos 1089883529b6Schristos The framework for an internally parallel coprocessor is also 1090883529b6Schristos present (2nd coprocessor insn is cop2), but at this time it 1091883529b6Schristos is not used. This only appears to be valid in VLIW64 mode. */ 1092883529b6Schristos 1093883529b6Schristosstatic int 1094883529b6Schristosmep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info) 1095883529b6Schristos{ 1096883529b6Schristos int status; 1097883529b6Schristos int buflength; 1098883529b6Schristos int corebuflength; 1099883529b6Schristos int cop1buflength; 1100883529b6Schristos int cop2buflength; 1101883529b6Schristos bfd_byte buf[CGEN_MAX_INSN_SIZE]; 1102883529b6Schristos char indicator16[1]; 1103883529b6Schristos char indicatorcop32[2]; 1104883529b6Schristos 1105883529b6Schristos /* At this time we're not supporting internally parallel coprocessors, 1106883529b6Schristos so cop2buflength will always be 0. */ 1107883529b6Schristos cop2buflength = 0; 1108883529b6Schristos 1109883529b6Schristos /* Read in 32 bits. */ 1110883529b6Schristos buflength = 4; /* VLIW insn spans 4 bytes. */ 1111883529b6Schristos status = (*info->read_memory_func) (pc, buf, buflength, info); 1112883529b6Schristos 1113883529b6Schristos if (status != 0) 1114883529b6Schristos { 1115883529b6Schristos (*info->memory_error_func) (status, pc, info); 1116883529b6Schristos return -1; 1117883529b6Schristos } 1118883529b6Schristos 1119883529b6Schristos /* Put the big endian representation of the bytes to be examined 1120883529b6Schristos in the temporary buffers for examination. */ 1121883529b6Schristos 1122883529b6Schristos if (info->endian == BFD_ENDIAN_BIG) 1123883529b6Schristos { 1124883529b6Schristos indicator16[0] = buf[0]; 1125883529b6Schristos indicatorcop32[0] = buf[0]; 1126883529b6Schristos indicatorcop32[1] = buf[1]; 1127883529b6Schristos } 1128883529b6Schristos else 1129883529b6Schristos { 1130883529b6Schristos indicator16[0] = buf[1]; 1131883529b6Schristos indicatorcop32[0] = buf[1]; 1132883529b6Schristos indicatorcop32[1] = buf[0]; 1133883529b6Schristos } 1134883529b6Schristos 1135883529b6Schristos /* If the two high order bits are 00, 01 or 10, we have a 16 bit 1136883529b6Schristos core insn and a 48 bit copro insn. */ 1137883529b6Schristos 1138883529b6Schristos if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40)) 1139883529b6Schristos { 1140883529b6Schristos if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07) 1141883529b6Schristos { 1142883529b6Schristos /* We have a 32 bit copro insn. */ 1143883529b6Schristos corebuflength = 0; 1144883529b6Schristos /* All 4 4ytes are one copro insn. */ 1145883529b6Schristos cop1buflength = 4; 1146883529b6Schristos } 1147883529b6Schristos else 1148883529b6Schristos { 1149883529b6Schristos /* We have a 32 bit core. */ 1150883529b6Schristos corebuflength = 4; 1151883529b6Schristos cop1buflength = 0; 1152883529b6Schristos } 1153883529b6Schristos } 1154883529b6Schristos else 1155883529b6Schristos { 1156883529b6Schristos /* We have a 16 bit core insn and a 16 bit copro insn. */ 1157883529b6Schristos corebuflength = 2; 1158883529b6Schristos cop1buflength = 2; 1159883529b6Schristos } 1160883529b6Schristos 1161883529b6Schristos /* Now we have the distrubution set. Print them out. */ 1162883529b6Schristos status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength, 1163883529b6Schristos cop1buflength, cop2buflength); 1164883529b6Schristos 1165883529b6Schristos return status; 1166883529b6Schristos} 1167883529b6Schristos 1168883529b6Schristosstatic int 1169883529b6Schristosmep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info) 1170883529b6Schristos{ 1171883529b6Schristos int status; 1172883529b6Schristos int buflength; 1173883529b6Schristos int corebuflength; 1174883529b6Schristos int cop1buflength; 1175883529b6Schristos int cop2buflength; 1176883529b6Schristos bfd_byte buf[CGEN_MAX_INSN_SIZE]; 1177883529b6Schristos char indicator16[1]; 1178883529b6Schristos char indicator64[4]; 1179883529b6Schristos 1180883529b6Schristos /* At this time we're not supporting internally parallel 1181883529b6Schristos coprocessors, so cop2buflength will always be 0. */ 1182883529b6Schristos cop2buflength = 0; 1183883529b6Schristos 1184883529b6Schristos /* Read in 64 bits. */ 1185883529b6Schristos buflength = 8; /* VLIW insn spans 8 bytes. */ 1186883529b6Schristos status = (*info->read_memory_func) (pc, buf, buflength, info); 1187883529b6Schristos 1188883529b6Schristos if (status != 0) 1189883529b6Schristos { 1190883529b6Schristos (*info->memory_error_func) (status, pc, info); 1191883529b6Schristos return -1; 1192883529b6Schristos } 1193883529b6Schristos 1194883529b6Schristos /* We have all 64 bits in the buffer now. We have to figure out 1195883529b6Schristos what combination of instruction sizes are present. The two 1196883529b6Schristos high order bits will indicate whether or not we have a 16 bit 1197883529b6Schristos core insn or not. If not, then we have to look at the 7,8th 1198883529b6Schristos bytes to tell whether we have 64 bit copro insn or a 32 bit 1199883529b6Schristos core insn with a 32 bit copro insn. Endianness will make a 1200883529b6Schristos difference here. */ 1201883529b6Schristos 1202883529b6Schristos /* Put the big endian representation of the bytes to be examined 1203883529b6Schristos in the temporary buffers for examination. */ 1204883529b6Schristos 1205883529b6Schristos /* indicator16[0] = buf[0]; */ 1206883529b6Schristos if (info->endian == BFD_ENDIAN_BIG) 1207883529b6Schristos { 1208883529b6Schristos indicator16[0] = buf[0]; 1209883529b6Schristos indicator64[0] = buf[0]; 1210883529b6Schristos indicator64[1] = buf[1]; 1211883529b6Schristos indicator64[2] = buf[2]; 1212883529b6Schristos indicator64[3] = buf[3]; 1213883529b6Schristos } 1214883529b6Schristos else 1215883529b6Schristos { 1216883529b6Schristos indicator16[0] = buf[1]; 1217883529b6Schristos indicator64[0] = buf[1]; 1218883529b6Schristos indicator64[1] = buf[0]; 1219883529b6Schristos indicator64[2] = buf[3]; 1220883529b6Schristos indicator64[3] = buf[2]; 1221883529b6Schristos } 1222883529b6Schristos 1223883529b6Schristos /* If the two high order bits are 00, 01 or 10, we have a 16 bit 1224883529b6Schristos core insn and a 48 bit copro insn. */ 1225883529b6Schristos 1226883529b6Schristos if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40)) 1227883529b6Schristos { 1228883529b6Schristos if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07 1229883529b6Schristos && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0)) 1230883529b6Schristos { 1231883529b6Schristos /* We have a 64 bit copro insn. */ 1232883529b6Schristos corebuflength = 0; 1233883529b6Schristos /* All 8 bytes are one copro insn. */ 1234883529b6Schristos cop1buflength = 8; 1235883529b6Schristos } 1236883529b6Schristos else 1237883529b6Schristos { 1238883529b6Schristos /* We have a 32 bit core insn and a 32 bit copro insn. */ 1239883529b6Schristos corebuflength = 4; 1240883529b6Schristos cop1buflength = 4; 1241883529b6Schristos } 1242883529b6Schristos } 1243883529b6Schristos else 1244883529b6Schristos { 1245883529b6Schristos /* We have a 16 bit core insn and a 48 bit copro insn. */ 1246883529b6Schristos corebuflength = 2; 1247883529b6Schristos cop1buflength = 6; 1248883529b6Schristos } 1249883529b6Schristos 1250883529b6Schristos /* Now we have the distrubution set. Print them out. */ 1251883529b6Schristos status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength, 1252883529b6Schristos cop1buflength, cop2buflength); 1253883529b6Schristos 1254883529b6Schristos return status; 1255883529b6Schristos} 1256883529b6Schristos 1257883529b6Schristos#ifdef MEP_IVC2_SUPPORTED 1258883529b6Schristos 1259883529b6Schristosstatic int 1260883529b6Schristosprint_slot_insn (CGEN_CPU_DESC cd, 1261883529b6Schristos bfd_vma pc, 1262883529b6Schristos disassemble_info *info, 1263883529b6Schristos SLOTS_ATTR slot, 1264883529b6Schristos bfd_byte *buf) 1265883529b6Schristos{ 1266883529b6Schristos const CGEN_INSN_LIST *insn_list; 1267883529b6Schristos CGEN_INSN_INT insn_value; 1268883529b6Schristos CGEN_EXTRACT_INFO ex_info; 1269883529b6Schristos 12704f645668Schristos insn_value = cgen_get_insn_value (cd, buf, 32, cd->insn_endian); 1271883529b6Schristos 1272883529b6Schristos /* Fill in ex_info fields like read_insn would. Don't actually call 1273883529b6Schristos read_insn, since the incoming buffer is already read (and possibly 1274883529b6Schristos modified a la m32r). */ 1275883529b6Schristos ex_info.valid = (1 << 8) - 1; 1276883529b6Schristos ex_info.dis_info = info; 1277883529b6Schristos ex_info.insn_bytes = buf; 1278883529b6Schristos 1279883529b6Schristos /* The instructions are stored in hash lists. 1280883529b6Schristos Pick the first one and keep trying until we find the right one. */ 1281883529b6Schristos 1282883529b6Schristos insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value); 1283883529b6Schristos while (insn_list != NULL) 1284883529b6Schristos { 1285883529b6Schristos const CGEN_INSN *insn = insn_list->insn; 1286883529b6Schristos CGEN_FIELDS fields; 1287883529b6Schristos int length; 1288883529b6Schristos 1289883529b6Schristos if ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG) 1290883529b6Schristos && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG) != MEP_CONFIG) 1291883529b6Schristos || ! (CGEN_ATTR_CGEN_INSN_SLOTS_VALUE (CGEN_INSN_ATTRS (insn)) & (1 << slot))) 1292883529b6Schristos { 1293883529b6Schristos insn_list = CGEN_DIS_NEXT_INSN (insn_list); 1294883529b6Schristos continue; 1295883529b6Schristos } 1296883529b6Schristos 1297883529b6Schristos if ((insn_value & CGEN_INSN_BASE_MASK (insn)) 1298883529b6Schristos == CGEN_INSN_BASE_VALUE (insn)) 1299883529b6Schristos { 1300883529b6Schristos /* Printing is handled in two passes. The first pass parses the 1301883529b6Schristos machine insn and extracts the fields. The second pass prints 1302883529b6Schristos them. */ 1303883529b6Schristos 1304883529b6Schristos length = CGEN_EXTRACT_FN (cd, insn) 1305883529b6Schristos (cd, insn, &ex_info, insn_value, &fields, pc); 1306883529b6Schristos 1307883529b6Schristos /* Length < 0 -> error. */ 1308883529b6Schristos if (length < 0) 1309883529b6Schristos return length; 1310883529b6Schristos if (length > 0) 1311883529b6Schristos { 1312883529b6Schristos CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length); 1313883529b6Schristos /* Length is in bits, result is in bytes. */ 1314883529b6Schristos return length / 8; 1315883529b6Schristos } 1316883529b6Schristos } 1317883529b6Schristos 1318883529b6Schristos insn_list = CGEN_DIS_NEXT_INSN (insn_list); 1319883529b6Schristos } 1320883529b6Schristos 1321883529b6Schristos if (slot == SLOTS_P0S) 1322883529b6Schristos (*info->fprintf_func) (info->stream, "*unknown-p0s*"); 1323883529b6Schristos else if (slot == SLOTS_P0) 1324883529b6Schristos (*info->fprintf_func) (info->stream, "*unknown-p0*"); 1325883529b6Schristos else if (slot == SLOTS_P1) 1326883529b6Schristos (*info->fprintf_func) (info->stream, "*unknown-p1*"); 1327883529b6Schristos else if (slot == SLOTS_C3) 1328883529b6Schristos (*info->fprintf_func) (info->stream, "*unknown-c3*"); 1329883529b6Schristos return 0; 1330883529b6Schristos} 1331883529b6Schristos 1332883529b6Schristosstatic int 1333883529b6Schristosmep_examine_ivc2_insns (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info ATTRIBUTE_UNUSED) 1334883529b6Schristos{ 1335883529b6Schristos int status; 1336883529b6Schristos int buflength; 1337883529b6Schristos bfd_byte buf[8]; 1338883529b6Schristos bfd_byte insn[8]; 1339883529b6Schristos int e; 1340883529b6Schristos 1341883529b6Schristos /* Read in 64 bits. */ 1342883529b6Schristos buflength = 8; /* VLIW insn spans 8 bytes. */ 1343883529b6Schristos status = (*info->read_memory_func) (pc, buf, buflength, info); 1344883529b6Schristos 1345883529b6Schristos if (status != 0) 1346883529b6Schristos { 1347883529b6Schristos (*info->memory_error_func) (status, pc, info); 1348883529b6Schristos return -1; 1349883529b6Schristos } 1350883529b6Schristos 1351883529b6Schristos if (info->endian == BFD_ENDIAN_LITTLE) 1352883529b6Schristos e = 1; 1353883529b6Schristos else 1354883529b6Schristos e = 0; 1355883529b6Schristos 1356883529b6Schristos if (((unsigned char)buf[0^e] & 0xf0) < 0xc0) 1357883529b6Schristos { 1358883529b6Schristos /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */ 1359883529b6Schristos /* V1 [-----core-----][--------p0s-------][------------p1------------] */ 1360883529b6Schristos 1361883529b6Schristos print_insn (cd, pc, info, buf, 2); 1362883529b6Schristos 1363883529b6Schristos insn[0^e] = 0; 1364883529b6Schristos insn[1^e] = buf[2^e]; 1365883529b6Schristos insn[2^e] = buf[3^e]; 1366883529b6Schristos insn[3^e] = buf[4^e] & 0xf0; 1367883529b6Schristos (*info->fprintf_func) (info->stream, " + "); 1368883529b6Schristos print_slot_insn (cd, pc, info, SLOTS_P0S, insn); 1369883529b6Schristos 1370883529b6Schristos insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4; 1371883529b6Schristos insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4; 1372883529b6Schristos insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4; 1373883529b6Schristos insn[3^e] = buf[7^e] << 4; 1374883529b6Schristos (*info->fprintf_func) (info->stream, " + "); 1375883529b6Schristos print_slot_insn (cd, pc, info, SLOTS_P1, insn); 1376883529b6Schristos } 1377883529b6Schristos else if ((buf[0^e] & 0xf0) == 0xf0 && (buf[1^e] & 0x0f) == 0x07) 1378883529b6Schristos { 1379883529b6Schristos /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */ 1380883529b6Schristos /* V3 1111[--p0--]0111[--------p0--------][------------p1------------] */ 1381883529b6Schristos /* 00000000111111112222222233333333 */ 1382883529b6Schristos 1383883529b6Schristos insn[0^e] = buf[0^e] << 4 | buf[1^e] >> 4; 1384883529b6Schristos insn[1^e] = buf[2^e]; 1385883529b6Schristos insn[2^e] = buf[3^e]; 1386883529b6Schristos insn[3^e] = buf[4^e] & 0xf0; 1387883529b6Schristos print_slot_insn (cd, pc, info, SLOTS_P0, insn); 1388883529b6Schristos 1389883529b6Schristos insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4; 1390883529b6Schristos insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4; 1391883529b6Schristos insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4; 1392883529b6Schristos insn[3^e] = buf[7^e] << 4; 1393883529b6Schristos (*info->fprintf_func) (info->stream, " + "); 1394883529b6Schristos print_slot_insn (cd, pc, info, SLOTS_P1, insn); 1395883529b6Schristos } 1396883529b6Schristos else 1397883529b6Schristos { 1398883529b6Schristos /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */ 1399883529b6Schristos /* V2 [-------------core-------------]xxxx[------------p1------------] */ 1400883529b6Schristos print_insn (cd, pc, info, buf, 4); 1401883529b6Schristos 1402883529b6Schristos insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4; 1403883529b6Schristos insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4; 1404883529b6Schristos insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4; 1405883529b6Schristos insn[3^e] = buf[7^e] << 4; 1406883529b6Schristos (*info->fprintf_func) (info->stream, " + "); 1407883529b6Schristos print_slot_insn (cd, pc, info, SLOTS_P1, insn); 1408883529b6Schristos } 1409883529b6Schristos 1410883529b6Schristos return 8; 1411883529b6Schristos} 1412883529b6Schristos 1413883529b6Schristos#endif /* MEP_IVC2_SUPPORTED */ 1414883529b6Schristos 1415883529b6Schristos/* This is a hack. SID calls this to update the disassembler as the 1416883529b6Schristos CPU changes modes. */ 1417883529b6Schristosstatic int mep_ivc2_disassemble_p = 0; 1418883529b6Schristosstatic int mep_ivc2_vliw_disassemble_p = 0; 1419883529b6Schristos 1420883529b6Schristosvoid 1421883529b6Schristosmep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx); 1422883529b6Schristosvoid 1423883529b6Schristosmep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx) 1424883529b6Schristos{ 1425883529b6Schristos mep_ivc2_disassemble_p = ivc2_p; 1426883529b6Schristos mep_ivc2_vliw_disassemble_p = vliw_p; 1427883529b6Schristos mep_config_index = cfg_idx; 1428883529b6Schristos} 1429883529b6Schristos 1430883529b6Schristosstatic int 1431883529b6Schristosmep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info) 1432883529b6Schristos{ 1433883529b6Schristos int status; 1434883529b6Schristos int cop_type; 1435883529b6Schristos int ivc2 = 0; 1436883529b6Schristos static CGEN_ATTR_VALUE_BITSET_TYPE *ivc2_core_isa = NULL; 1437883529b6Schristos 1438883529b6Schristos if (ivc2_core_isa == NULL) 1439883529b6Schristos { 1440883529b6Schristos /* IVC2 has some core-only coprocessor instructions. We 1441883529b6Schristos use COP32 to flag those, and COP64 for the VLIW ones, 1442883529b6Schristos since they have the same names. */ 1443883529b6Schristos ivc2_core_isa = cgen_bitset_create (MAX_ISAS); 1444883529b6Schristos } 1445883529b6Schristos 1446883529b6Schristos /* Extract and adapt to configuration number, if available. */ 1447883529b6Schristos if (info->section && info->section->owner) 1448883529b6Schristos { 1449883529b6Schristos bfd *abfd = info->section->owner; 14504f645668Schristos if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) 14514f645668Schristos { 1452883529b6Schristos mep_config_index = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_INDEX_MASK; 1453883529b6Schristos /* This instantly redefines MEP_CONFIG, MEP_OMASK, .... MEP_VLIW64 */ 1454883529b6Schristos 1455*cb63e24eSchristos /* mep_config_map is a variable sized array, so we do not know how big it is. 1456*cb63e24eSchristos The only safe way to check the index therefore is to iterate over the array. 1457*cb63e24eSchristos We do know that the last entry is all null. */ 1458*cb63e24eSchristos int i; 1459*cb63e24eSchristos for (i = 0; i <= mep_config_index; i++) 1460*cb63e24eSchristos if (mep_config_map[i].name == NULL) 1461*cb63e24eSchristos break; 1462*cb63e24eSchristos 1463*cb63e24eSchristos if (i < mep_config_index) 1464*cb63e24eSchristos { 1465*cb63e24eSchristos opcodes_error_handler (_("illegal MEP INDEX setting '%x' in ELF header e_flags field"), mep_config_index); 1466*cb63e24eSchristos mep_config_index = 0; 1467*cb63e24eSchristos } 1468*cb63e24eSchristos 1469883529b6Schristos cop_type = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_COP_MASK; 1470883529b6Schristos if (cop_type == EF_MEP_COP_IVC2) 1471883529b6Schristos ivc2 = 1; 1472883529b6Schristos } 14734f645668Schristos } 1474883529b6Schristos 1475883529b6Schristos /* Picking the right ISA bitmask for the current context is tricky. */ 1476883529b6Schristos if (info->section) 1477883529b6Schristos { 1478883529b6Schristos if (info->section->flags & SEC_MEP_VLIW) 1479883529b6Schristos { 1480883529b6Schristos#ifdef MEP_IVC2_SUPPORTED 1481883529b6Schristos if (ivc2) 1482883529b6Schristos { 1483883529b6Schristos /* ivc2 has its own way of selecting its functions. */ 1484883529b6Schristos cd->isas = & MEP_CORE_ISA; 1485883529b6Schristos status = mep_examine_ivc2_insns (cd, pc, info); 1486883529b6Schristos } 1487883529b6Schristos else 1488883529b6Schristos#endif 1489883529b6Schristos /* Are we in 32 or 64 bit vliw mode? */ 1490883529b6Schristos if (MEP_VLIW64) 1491883529b6Schristos status = mep_examine_vliw64_insns (cd, pc, info); 1492883529b6Schristos else 1493883529b6Schristos status = mep_examine_vliw32_insns (cd, pc, info); 1494883529b6Schristos /* Both the above branches set their own isa bitmasks. */ 1495883529b6Schristos } 1496883529b6Schristos else 1497883529b6Schristos { 1498883529b6Schristos if (ivc2) 1499883529b6Schristos { 1500883529b6Schristos cgen_bitset_clear (ivc2_core_isa); 1501883529b6Schristos cgen_bitset_union (ivc2_core_isa, &MEP_CORE_ISA, ivc2_core_isa); 1502883529b6Schristos cgen_bitset_union (ivc2_core_isa, &MEP_COP32_ISA, ivc2_core_isa); 1503883529b6Schristos cd->isas = ivc2_core_isa; 1504883529b6Schristos } 1505883529b6Schristos else 1506883529b6Schristos cd->isas = & MEP_CORE_ISA; 1507883529b6Schristos status = default_print_insn (cd, pc, info); 1508883529b6Schristos } 1509883529b6Schristos } 1510883529b6Schristos else /* sid or gdb */ 1511883529b6Schristos { 1512883529b6Schristos#ifdef MEP_IVC2_SUPPORTED 1513883529b6Schristos if (mep_ivc2_disassemble_p) 1514883529b6Schristos { 1515883529b6Schristos if (mep_ivc2_vliw_disassemble_p) 1516883529b6Schristos { 1517883529b6Schristos cd->isas = & MEP_CORE_ISA; 1518883529b6Schristos status = mep_examine_ivc2_insns (cd, pc, info); 1519883529b6Schristos return status; 1520883529b6Schristos } 1521883529b6Schristos else 1522883529b6Schristos { 1523883529b6Schristos if (ivc2) 1524883529b6Schristos cd->isas = ivc2_core_isa; 1525883529b6Schristos } 1526883529b6Schristos } 1527883529b6Schristos#endif 1528883529b6Schristos 1529883529b6Schristos status = default_print_insn (cd, pc, info); 1530883529b6Schristos } 1531883529b6Schristos 1532883529b6Schristos return status; 1533883529b6Schristos} 1534883529b6Schristos 1535883529b6Schristos 1536883529b6Schristos/* -- opc.c */ 1537883529b6Schristos#include "elf/mep.h" 1538883529b6Schristos 1539883529b6Schristos/* A mask for all ISAs executed by the core. */ 1540883529b6SchristosCGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask = {0, 0}; 1541883529b6Schristos 1542883529b6Schristosvoid 1543883529b6Schristosinit_mep_all_core_isas_mask (void) 1544883529b6Schristos{ 1545883529b6Schristos if (mep_all_core_isas_mask.length != 0) 1546883529b6Schristos return; 1547883529b6Schristos cgen_bitset_init (& mep_all_core_isas_mask, ISA_MAX); 1548883529b6Schristos cgen_bitset_set (& mep_all_core_isas_mask, ISA_MEP); 1549883529b6Schristos /* begin-all-core-isas */ 1550883529b6Schristos cgen_bitset_add (& mep_all_core_isas_mask, ISA_EXT_CORE1); 1551883529b6Schristos /* end-all-core-isas */ 1552883529b6Schristos} 1553883529b6Schristos 1554883529b6SchristosCGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask = {0, 0}; 1555883529b6Schristos 1556883529b6Schristosvoid 1557883529b6Schristosinit_mep_all_cop_isas_mask (void) 1558883529b6Schristos{ 1559883529b6Schristos if (mep_all_cop_isas_mask.length != 0) 1560883529b6Schristos return; 1561883529b6Schristos cgen_bitset_init (& mep_all_cop_isas_mask, ISA_MAX); 1562883529b6Schristos /* begin-all-cop-isas */ 1563883529b6Schristos cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_16); 1564883529b6Schristos cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_32); 1565883529b6Schristos cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_48); 1566883529b6Schristos cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_64); 1567883529b6Schristos /* end-all-cop-isas */ 1568883529b6Schristos} 1569883529b6Schristos 1570883529b6Schristosint 1571883529b6Schristosmep_insn_supported_by_isa (const CGEN_INSN *insn, CGEN_ATTR_VALUE_BITSET_TYPE *isa_mask) 1572883529b6Schristos{ 1573883529b6Schristos CGEN_BITSET insn_isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA); 1574883529b6Schristos return cgen_bitset_intersect_p (& insn_isas, isa_mask); 1575883529b6Schristos} 1576883529b6Schristos 1577883529b6Schristos#define OPTION_MASK \ 1578883529b6Schristos ( (1 << CGEN_INSN_OPTIONAL_BIT_INSN) \ 1579883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_MUL_INSN) \ 1580883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_DIV_INSN) \ 1581883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN) \ 1582883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN) \ 1583883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_ABS_INSN) \ 1584883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_AVE_INSN) \ 1585883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN) \ 1586883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN) \ 1587883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) \ 1588883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_UCI_INSN) \ 1589883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_DSP_INSN) \ 1590883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_CP_INSN) \ 1591883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_CP64_INSN) ) 1592883529b6Schristos 1593883529b6Schristos 1594883529b6Schristosmep_config_map_struct mep_config_map[] = 1595883529b6Schristos{ 1596883529b6Schristos /* config-map-start */ 1597883529b6Schristos /* Default entry: first module, with all options enabled. */ 1598883529b6Schristos { "", 0, EF_MEP_COP_IVC2 | EF_MEP_CPU_C5,0, 64, { 1, "\x20" }, { 1, "\x10" }, { 1, "\x8" }, { 1, "\x4" }, { 1, "\x3c" }, { 1, "\xc0" }, OPTION_MASK | (1 << CGEN_INSN_OPTIONAL_DSP_INSN) | (1 << CGEN_INSN_OPTIONAL_UCI_INSN) }, 1599883529b6Schristos { "default", CONFIG_DEFAULT, EF_MEP_COP_IVC2 | EF_MEP_CPU_C5, 0, 64, { 1, "\x20" }, { 1, "\x10" }, { 1, "\x8" }, { 1, "\x4" }, { 1, "\x3c" }, { 1, "\xc0" }, 1600883529b6Schristos 0 1601883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_CP_INSN) 1602883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_CP64_INSN) 1603883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_MUL_INSN) 1604883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_DIV_INSN) 1605883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_BIT_INSN) 1606883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN) 1607883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_ABS_INSN) 1608883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_AVE_INSN) 1609883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN) 1610883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN) 1611883529b6Schristos | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) }, 1612883529b6Schristos /* config-map-end */ 1613883529b6Schristos { 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0 } 1614883529b6Schristos}; 1615883529b6Schristos 1616883529b6Schristosint mep_config_index = 0; 1617883529b6Schristos 1618883529b6Schristosstatic int 1619883529b6Schristoscheck_configured_mach (int machs) 1620883529b6Schristos{ 1621883529b6Schristos /* All base insns are supported. */ 1622883529b6Schristos int mach = 1 << MACH_BASE; 1623883529b6Schristos switch (MEP_CPU & EF_MEP_CPU_MASK) 1624883529b6Schristos { 1625883529b6Schristos case EF_MEP_CPU_C2: 1626883529b6Schristos case EF_MEP_CPU_C3: 1627883529b6Schristos mach |= (1 << MACH_MEP); 1628883529b6Schristos break; 1629883529b6Schristos case EF_MEP_CPU_H1: 1630883529b6Schristos mach |= (1 << MACH_H1); 1631883529b6Schristos break; 1632883529b6Schristos case EF_MEP_CPU_C5: 1633883529b6Schristos mach |= (1 << MACH_MEP); 1634883529b6Schristos mach |= (1 << MACH_C5); 1635883529b6Schristos break; 1636883529b6Schristos default: 1637883529b6Schristos break; 1638883529b6Schristos } 1639883529b6Schristos return machs & mach; 1640883529b6Schristos} 1641883529b6Schristos 1642883529b6Schristosint 1643883529b6Schristosmep_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn) 1644883529b6Schristos{ 1645883529b6Schristos int iconfig = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG); 1646883529b6Schristos int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH); 1647883529b6Schristos CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA); 1648883529b6Schristos int ok1; 1649883529b6Schristos int ok2; 1650883529b6Schristos int ok3; 1651883529b6Schristos 1652883529b6Schristos /* If the insn has an option bit set that we don't want, 1653883529b6Schristos reject it. */ 1654883529b6Schristos if (CGEN_INSN_ATTRS (insn)->bool_ & OPTION_MASK & ~MEP_OMASK) 1655883529b6Schristos return 0; 1656883529b6Schristos 1657883529b6Schristos /* If attributes are absent, assume no restriction. */ 1658883529b6Schristos if (machs == 0) 1659883529b6Schristos machs = ~0; 1660883529b6Schristos 1661883529b6Schristos ok1 = ((machs & cd->machs) && cgen_bitset_intersect_p (& isas, cd->isas)); 1662883529b6Schristos /* If the insn is config-specific, make sure it matches. */ 1663883529b6Schristos ok2 = (iconfig == 0 || iconfig == MEP_CONFIG); 1664883529b6Schristos /* Make sure the insn is supported by the configured mach */ 1665883529b6Schristos ok3 = check_configured_mach (machs); 1666883529b6Schristos 1667883529b6Schristos return (ok1 && ok2 && ok3); 1668883529b6Schristos} 1669883529b6Schristos 1670883529b6Schristosint 1671883529b6Schristosmep_cgen_insn_supported_asm (CGEN_CPU_DESC cd, const CGEN_INSN *insn) 1672883529b6Schristos{ 1673883529b6Schristos#ifdef MEP_IVC2_SUPPORTED 1674883529b6Schristos /* If we're assembling VLIW packets, ignore the 12-bit BSR as we 1675883529b6Schristos can't relax that. The 24-bit BSR is matched instead. */ 1676883529b6Schristos if (insn->base->num == MEP_INSN_BSR12 1677883529b6Schristos && cgen_bitset_contains (cd->isas, ISA_EXT_COP1_64)) 1678883529b6Schristos return 0; 1679883529b6Schristos#endif 1680883529b6Schristos 1681883529b6Schristos return mep_cgen_insn_supported (cd, insn); 1682883529b6Schristos} 1683