1 /* MeP opcode support. -*- C -*- 2 Copyright 2011 Free Software Foundation, Inc. 3 4 Contributed by Red Hat Inc; 5 6 This file is part of the GNU Binutils. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21 MA 02110-1301, USA. */ 22 23 /* -- opc.h */ 24 25 #undef CGEN_DIS_HASH_SIZE 26 #define CGEN_DIS_HASH_SIZE 1 27 28 #undef CGEN_DIS_HASH 29 #define CGEN_DIS_HASH(buffer, insn) 0 30 31 #define CGEN_VERBOSE_ASSEMBLER_ERRORS 32 33 typedef struct 34 { 35 char * name; 36 int config_enum; 37 unsigned cpu_flag; 38 int big_endian; 39 int vliw_bits; 40 CGEN_ATTR_VALUE_BITSET_TYPE cop16_isa; 41 CGEN_ATTR_VALUE_BITSET_TYPE cop32_isa; 42 CGEN_ATTR_VALUE_BITSET_TYPE cop48_isa; 43 CGEN_ATTR_VALUE_BITSET_TYPE cop64_isa; 44 CGEN_ATTR_VALUE_BITSET_TYPE cop_isa; 45 CGEN_ATTR_VALUE_BITSET_TYPE core_isa; 46 unsigned int option_mask; 47 } mep_config_map_struct; 48 49 extern mep_config_map_struct mep_config_map[]; 50 extern int mep_config_index; 51 52 extern void init_mep_all_core_isas_mask (void); 53 extern void init_mep_all_cop_isas_mask (void); 54 extern CGEN_ATTR_VALUE_BITSET_TYPE mep_cop_isa (void); 55 56 #define MEP_CONFIG (mep_config_map[mep_config_index].config_enum) 57 #define MEP_CPU (mep_config_map[mep_config_index].cpu_flag) 58 #define MEP_OMASK (mep_config_map[mep_config_index].option_mask) 59 #define MEP_VLIW (mep_config_map[mep_config_index].vliw_bits > 0) 60 #define MEP_VLIW32 (mep_config_map[mep_config_index].vliw_bits == 32) 61 #define MEP_VLIW64 (mep_config_map[mep_config_index].vliw_bits == 64) 62 #define MEP_COP16_ISA (mep_config_map[mep_config_index].cop16_isa) 63 #define MEP_COP32_ISA (mep_config_map[mep_config_index].cop32_isa) 64 #define MEP_COP48_ISA (mep_config_map[mep_config_index].cop48_isa) 65 #define MEP_COP64_ISA (mep_config_map[mep_config_index].cop64_isa) 66 #define MEP_COP_ISA (mep_config_map[mep_config_index].cop_isa) 67 #define MEP_CORE_ISA (mep_config_map[mep_config_index].core_isa) 68 69 /* begin-cop-ip-supported-defines */ 70 #define MEP_IVC2_SUPPORTED 1 71 /* end-cop-ip-supported-defines */ 72 73 extern int mep_insn_supported_by_isa (const CGEN_INSN *, CGEN_ATTR_VALUE_BITSET_TYPE *); 74 75 /* A mask for all ISAs executed by the core. */ 76 #define MEP_ALL_CORE_ISAS_MASK mep_all_core_isas_mask 77 extern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask; 78 79 #define MEP_INSN_CORE_P(insn) ( \ 80 init_mep_all_core_isas_mask (), \ 81 mep_insn_supported_by_isa (insn, & MEP_ALL_CORE_ISAS_MASK) \ 82 ) 83 84 /* A mask for all ISAs executed by a VLIW coprocessor. */ 85 #define MEP_ALL_COP_ISAS_MASK mep_all_cop_isas_mask 86 extern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask; 87 88 #define MEP_INSN_COP_P(insn) ( \ 89 init_mep_all_cop_isas_mask (), \ 90 mep_insn_supported_by_isa (insn, & MEP_ALL_COP_ISAS_MASK) \ 91 ) 92 93 extern int mep_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *); 94 extern int mep_cgen_insn_supported_asm (CGEN_CPU_DESC, const CGEN_INSN *); 95 96 /* -- asm.c */ 97 98 #include "elf/mep.h" 99 100 #define CGEN_VALIDATE_INSN_SUPPORTED 101 #define mep_cgen_insn_supported mep_cgen_insn_supported_asm 102 103 const char * parse_csrn (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *); 104 const char * parse_tpreg (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *); 105 const char * parse_spreg (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *); 106 const char * parse_mep_align (CGEN_CPU_DESC, const char **, enum cgen_operand_type, long *); 107 const char * parse_mep_alignu (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *); 108 static const char * parse_signed16 (CGEN_CPU_DESC, const char **, int, long *); 109 static const char * parse_signed16_range (CGEN_CPU_DESC, const char **, int, long *) ATTRIBUTE_UNUSED; 110 static const char * parse_unsigned16 (CGEN_CPU_DESC, const char **, int, unsigned long *); 111 static const char * parse_unsigned16_range (CGEN_CPU_DESC, const char **, int, unsigned long *) ATTRIBUTE_UNUSED; 112 static const char * parse_lo16 (CGEN_CPU_DESC, const char **, int, long *, long); 113 static const char * parse_unsigned7 (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *); 114 static const char * parse_zero (CGEN_CPU_DESC, const char **, int, long *); 115 116 const char * 117 parse_csrn (CGEN_CPU_DESC cd, const char **strp, 118 CGEN_KEYWORD *keyword_table, long *field) 119 { 120 const char *err; 121 unsigned long value; 122 123 err = cgen_parse_keyword (cd, strp, keyword_table, field); 124 if (!err) 125 return NULL; 126 127 err = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CSRN_IDX, & value); 128 if (err) 129 return err; 130 *field = value; 131 return NULL; 132 } 133 134 /* begin-cop-ip-parse-handlers */ 135 static const char * 136 parse_ivc2_cr (CGEN_CPU_DESC, 137 const char **, 138 CGEN_KEYWORD *, 139 long *) ATTRIBUTE_UNUSED; 140 static const char * 141 parse_ivc2_cr (CGEN_CPU_DESC cd, 142 const char **strp, 143 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED, 144 long *field) 145 { 146 return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr_ivc2, field); 147 } 148 static const char * 149 parse_ivc2_ccr (CGEN_CPU_DESC, 150 const char **, 151 CGEN_KEYWORD *, 152 long *) ATTRIBUTE_UNUSED; 153 static const char * 154 parse_ivc2_ccr (CGEN_CPU_DESC cd, 155 const char **strp, 156 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED, 157 long *field) 158 { 159 return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr_ivc2, field); 160 } 161 /* end-cop-ip-parse-handlers */ 162 163 const char * 164 parse_tpreg (CGEN_CPU_DESC cd, const char ** strp, 165 CGEN_KEYWORD *keyword_table, long *field) 166 { 167 const char *err; 168 169 err = cgen_parse_keyword (cd, strp, keyword_table, field); 170 if (err) 171 return err; 172 if (*field != 13) 173 return _("Only $tp or $13 allowed for this opcode"); 174 return NULL; 175 } 176 177 const char * 178 parse_spreg (CGEN_CPU_DESC cd, const char ** strp, 179 CGEN_KEYWORD *keyword_table, long *field) 180 { 181 const char *err; 182 183 err = cgen_parse_keyword (cd, strp, keyword_table, field); 184 if (err) 185 return err; 186 if (*field != 15) 187 return _("Only $sp or $15 allowed for this opcode"); 188 return NULL; 189 } 190 191 const char * 192 parse_mep_align (CGEN_CPU_DESC cd, const char ** strp, 193 enum cgen_operand_type type, long *field) 194 { 195 long lsbs = 0; 196 const char *err; 197 198 switch (type) 199 { 200 case MEP_OPERAND_PCREL8A2: 201 case MEP_OPERAND_PCREL12A2: 202 case MEP_OPERAND_PCREL17A2: 203 case MEP_OPERAND_PCREL24A2: 204 err = cgen_parse_signed_integer (cd, strp, type, field); 205 break; 206 case MEP_OPERAND_PCABS24A2: 207 case MEP_OPERAND_UDISP7: 208 case MEP_OPERAND_UDISP7A2: 209 case MEP_OPERAND_UDISP7A4: 210 case MEP_OPERAND_UIMM7A4: 211 case MEP_OPERAND_ADDR24A4: 212 err = cgen_parse_unsigned_integer (cd, strp, type, (unsigned long *) field); 213 break; 214 default: 215 abort(); 216 } 217 if (err) 218 return err; 219 switch (type) 220 { 221 case MEP_OPERAND_UDISP7: 222 lsbs = 0; 223 break; 224 case MEP_OPERAND_PCREL8A2: 225 case MEP_OPERAND_PCREL12A2: 226 case MEP_OPERAND_PCREL17A2: 227 case MEP_OPERAND_PCREL24A2: 228 case MEP_OPERAND_PCABS24A2: 229 case MEP_OPERAND_UDISP7A2: 230 lsbs = *field & 1; 231 break; 232 case MEP_OPERAND_UDISP7A4: 233 case MEP_OPERAND_UIMM7A4: 234 case MEP_OPERAND_ADDR24A4: 235 lsbs = *field & 3; 236 break; 237 lsbs = *field & 7; 238 break; 239 default: 240 /* Safe assumption? */ 241 abort (); 242 } 243 if (lsbs) 244 return "Value is not aligned enough"; 245 return NULL; 246 } 247 248 const char * 249 parse_mep_alignu (CGEN_CPU_DESC cd, const char ** strp, 250 enum cgen_operand_type type, unsigned long *field) 251 { 252 return parse_mep_align (cd, strp, type, (long *) field); 253 } 254 255 256 /* Handle %lo(), %tpoff(), %sdaoff(), %hi(), and other signed 257 constants in a signed context. */ 258 259 static const char * 260 parse_signed16 (CGEN_CPU_DESC cd, 261 const char **strp, 262 int opindex, 263 long *valuep) 264 { 265 return parse_lo16 (cd, strp, opindex, valuep, 1); 266 } 267 268 static const char * 269 parse_lo16 (CGEN_CPU_DESC cd, 270 const char **strp, 271 int opindex, 272 long *valuep, 273 long signedp) 274 { 275 const char *errmsg; 276 enum cgen_parse_operand_result result_type; 277 bfd_vma value; 278 279 if (strncasecmp (*strp, "%lo(", 4) == 0) 280 { 281 *strp += 4; 282 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16, 283 & result_type, & value); 284 if (**strp != ')') 285 return _("missing `)'"); 286 ++*strp; 287 if (errmsg == NULL 288 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 289 value &= 0xffff; 290 if (signedp) 291 *valuep = (long)(short) value; 292 else 293 *valuep = value; 294 return errmsg; 295 } 296 297 if (strncasecmp (*strp, "%hi(", 4) == 0) 298 { 299 *strp += 4; 300 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S, 301 & result_type, & value); 302 if (**strp != ')') 303 return _("missing `)'"); 304 ++*strp; 305 if (errmsg == NULL 306 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 307 value = (value + 0x8000) >> 16; 308 *valuep = value; 309 return errmsg; 310 } 311 312 if (strncasecmp (*strp, "%uhi(", 5) == 0) 313 { 314 *strp += 5; 315 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U, 316 & result_type, & value); 317 if (**strp != ')') 318 return _("missing `)'"); 319 ++*strp; 320 if (errmsg == NULL 321 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 322 value = value >> 16; 323 *valuep = value; 324 return errmsg; 325 } 326 327 if (strncasecmp (*strp, "%sdaoff(", 8) == 0) 328 { 329 *strp += 8; 330 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL, 331 NULL, & value); 332 if (**strp != ')') 333 return _("missing `)'"); 334 ++*strp; 335 *valuep = value; 336 return errmsg; 337 } 338 339 if (strncasecmp (*strp, "%tpoff(", 7) == 0) 340 { 341 *strp += 7; 342 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL, 343 NULL, & value); 344 if (**strp != ')') 345 return _("missing `)'"); 346 ++*strp; 347 *valuep = value; 348 return errmsg; 349 } 350 351 if (**strp == '%') 352 return _("invalid %function() here"); 353 354 return cgen_parse_signed_integer (cd, strp, opindex, valuep); 355 } 356 357 static const char * 358 parse_unsigned16 (CGEN_CPU_DESC cd, 359 const char **strp, 360 int opindex, 361 unsigned long *valuep) 362 { 363 return parse_lo16 (cd, strp, opindex, (long *) valuep, 0); 364 } 365 366 static const char * 367 parse_signed16_range (CGEN_CPU_DESC cd, 368 const char **strp, 369 int opindex, 370 signed long *valuep) 371 { 372 const char *errmsg = 0; 373 signed long value; 374 375 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); 376 if (errmsg) 377 return errmsg; 378 379 if (value < -32768 || value > 32767) 380 return _("Immediate is out of range -32768 to 32767"); 381 382 *valuep = value; 383 return 0; 384 } 385 386 static const char * 387 parse_unsigned16_range (CGEN_CPU_DESC cd, 388 const char **strp, 389 int opindex, 390 unsigned long *valuep) 391 { 392 const char *errmsg = 0; 393 unsigned long value; 394 395 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value); 396 if (errmsg) 397 return errmsg; 398 399 if (value > 65535) 400 return _("Immediate is out of range 0 to 65535"); 401 402 *valuep = value; 403 return 0; 404 } 405 406 /* A special case of parse_signed16 which accepts only the value zero. */ 407 408 static const char * 409 parse_zero (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep) 410 { 411 const char *errmsg; 412 enum cgen_parse_operand_result result_type; 413 bfd_vma value; 414 415 /*fprintf(stderr, "dj: signed parse opindex `%s'\n", *strp);*/ 416 417 /* Prevent ($ry) from being attempted as an expression on 'sw $rx,($ry)'. 418 It will fail and cause ry to be listed as an undefined symbol in the 419 listing. */ 420 if (strncmp (*strp, "($", 2) == 0) 421 return "not zero"; /* any string will do -- will never be seen. */ 422 423 if (strncasecmp (*strp, "%lo(", 4) == 0) 424 { 425 *strp += 4; 426 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16, 427 &result_type, &value); 428 if (**strp != ')') 429 return "missing `)'"; 430 ++*strp; 431 if (errmsg == NULL 432 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 433 return "not zero"; /* any string will do -- will never be seen. */ 434 *valuep = value; 435 return errmsg; 436 } 437 438 if (strncasecmp (*strp, "%hi(", 4) == 0) 439 { 440 *strp += 4; 441 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S, 442 &result_type, &value); 443 if (**strp != ')') 444 return "missing `)'"; 445 ++*strp; 446 if (errmsg == NULL 447 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 448 return "not zero"; /* any string will do -- will never be seen. */ 449 *valuep = value; 450 return errmsg; 451 } 452 453 if (strncasecmp (*strp, "%uhi(", 5) == 0) 454 { 455 *strp += 5; 456 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U, 457 &result_type, &value); 458 if (**strp != ')') 459 return "missing `)'"; 460 ++*strp; 461 if (errmsg == NULL 462 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 463 return "not zero"; /* any string will do -- will never be seen. */ 464 *valuep = value; 465 return errmsg; 466 } 467 468 if (strncasecmp (*strp, "%sdaoff(", 8) == 0) 469 { 470 *strp += 8; 471 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL, 472 &result_type, &value); 473 if (**strp != ')') 474 return "missing `)'"; 475 ++*strp; 476 if (errmsg == NULL 477 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 478 return "not zero"; /* any string will do -- will never be seen. */ 479 *valuep = value; 480 return errmsg; 481 } 482 483 if (strncasecmp (*strp, "%tpoff(", 7) == 0) 484 { 485 *strp += 7; 486 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL, 487 &result_type, &value); 488 if (**strp != ')') 489 return "missing `)'"; 490 ++*strp; 491 if (errmsg == NULL 492 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 493 return "not zero"; /* any string will do -- will never be seen. */ 494 *valuep = value; 495 return errmsg; 496 } 497 498 if (**strp == '%') 499 return "invalid %function() here"; 500 501 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_NONE, 502 &result_type, &value); 503 if (errmsg == NULL 504 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 505 return "not zero"; /* any string will do -- will never be seen. */ 506 507 return errmsg; 508 } 509 510 static const char * 511 parse_unsigned7 (CGEN_CPU_DESC cd, const char **strp, 512 enum cgen_operand_type opindex, unsigned long *valuep) 513 { 514 const char *errmsg; 515 bfd_vma value; 516 517 /* fprintf(stderr, "dj: unsigned7 parse `%s'\n", *strp); */ 518 519 if (strncasecmp (*strp, "%tpoff(", 7) == 0) 520 { 521 int reloc; 522 *strp += 7; 523 switch (opindex) 524 { 525 case MEP_OPERAND_UDISP7: 526 reloc = BFD_RELOC_MEP_TPREL7; 527 break; 528 case MEP_OPERAND_UDISP7A2: 529 reloc = BFD_RELOC_MEP_TPREL7A2; 530 break; 531 case MEP_OPERAND_UDISP7A4: 532 reloc = BFD_RELOC_MEP_TPREL7A4; 533 break; 534 default: 535 /* Safe assumption? */ 536 abort (); 537 } 538 errmsg = cgen_parse_address (cd, strp, opindex, reloc, 539 NULL, &value); 540 if (**strp != ')') 541 return "missing `)'"; 542 ++*strp; 543 *valuep = value; 544 return errmsg; 545 } 546 547 if (**strp == '%') 548 return _("invalid %function() here"); 549 550 return parse_mep_alignu (cd, strp, opindex, valuep); 551 } 552 553 static ATTRIBUTE_UNUSED const char * 554 parse_cdisp10 (CGEN_CPU_DESC cd, 555 const char **strp, 556 int opindex, 557 long *valuep) 558 { 559 const char *errmsg = 0; 560 signed long value; 561 long have_zero = 0; 562 int wide = 0; 563 int alignment; 564 565 switch (opindex) 566 { 567 case MEP_OPERAND_CDISP10A4: 568 alignment = 2; 569 break; 570 case MEP_OPERAND_CDISP10A2: 571 alignment = 1; 572 break; 573 case MEP_OPERAND_CDISP10: 574 default: 575 alignment = 0; 576 break; 577 } 578 579 if ((MEP_CPU & EF_MEP_CPU_MASK) == EF_MEP_CPU_C5) 580 wide = 1; 581 582 if (strncmp (*strp, "0x0", 3) == 0 583 || (**strp == '0' && *(*strp + 1) != 'x')) 584 have_zero = 1; 585 586 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); 587 if (errmsg) 588 return errmsg; 589 590 if (wide) 591 { 592 if (value < -512 || value > 511) 593 return _("Immediate is out of range -512 to 511"); 594 } 595 else 596 { 597 if (value < -128 || value > 127) 598 return _("Immediate is out of range -128 to 127"); 599 } 600 601 if (value & ((1<<alignment)-1)) 602 return _("Value is not aligned enough"); 603 604 /* If this field may require a relocation then use larger dsp16. */ 605 if (! have_zero && value == 0) 606 return (wide ? _("Immediate is out of range -512 to 511") 607 : _("Immediate is out of range -128 to 127")); 608 609 *valuep = value; 610 return 0; 611 } 612 613 /* BEGIN LIGHTWEIGHT MACRO PROCESSOR. */ 614 615 #define MAXARGS 9 616 617 typedef struct 618 { 619 char *name; 620 char *expansion; 621 } macro; 622 623 typedef struct 624 { 625 const char *start; 626 int len; 627 } arg; 628 629 macro macros[] = 630 { 631 { "sizeof", "(`1.end + (- `1))"}, 632 { "startof", "(`1 | 0)" }, 633 { "align4", "(`1&(~3))"}, 634 /*{ "hi", "(((`1+0x8000)>>16) & 0xffff)" }, */ 635 /*{ "lo", "(`1 & 0xffff)" }, */ 636 /*{ "sdaoff", "((`1-__sdabase) & 0x7f)"}, */ 637 /*{ "tpoff", "((`1-__tpbase) & 0x7f)"}, */ 638 { 0,0 } 639 }; 640 641 static char * expand_string (const char *, int); 642 643 static const char * 644 mep_cgen_expand_macros_and_parse_operand 645 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *); 646 647 static char * 648 str_append (char *dest, const char *input, int len) 649 { 650 char *new_dest; 651 int oldlen; 652 653 if (len == 0) 654 return dest; 655 /* printf("str_append: <<%s>>, <<%s>>, %d\n", dest, input, len); */ 656 oldlen = (dest ? strlen(dest) : 0); 657 new_dest = realloc (dest, oldlen + len + 1); 658 memset (new_dest + oldlen, 0, len + 1); 659 return strncat (new_dest, input, len); 660 } 661 662 static macro * 663 lookup_macro (const char *name) 664 { 665 macro *m; 666 667 for (m = macros; m->name; ++m) 668 if (strncmp (m->name, name, strlen(m->name)) == 0) 669 return m; 670 671 return 0; 672 } 673 674 static char * 675 expand_macro (arg *args, int narg, macro *mac) 676 { 677 char *result = 0, *rescanned_result = 0; 678 char *e = mac->expansion; 679 char *mark = e; 680 int mac_arg = 0; 681 682 /* printf("expanding macro %s with %d args\n", mac->name, narg + 1); */ 683 while (*e) 684 { 685 if (*e == '`' && 686 (*e+1) && 687 ((*(e + 1) - '1') <= MAXARGS) && 688 ((*(e + 1) - '1') <= narg)) 689 { 690 result = str_append (result, mark, e - mark); 691 mac_arg = (*(e + 1) - '1'); 692 /* printf("replacing `%d with %s\n", mac_arg+1, args[mac_arg].start); */ 693 result = str_append (result, args[mac_arg].start, args[mac_arg].len); 694 ++e; 695 mark = e+1; 696 } 697 ++e; 698 } 699 700 if (mark != e) 701 result = str_append (result, mark, e - mark); 702 703 if (result) 704 { 705 rescanned_result = expand_string (result, 0); 706 free (result); 707 return rescanned_result; 708 } 709 else 710 return result; 711 } 712 713 #define IN_TEXT 0 714 #define IN_ARGS 1 715 716 static char * 717 expand_string (const char *in, int first_only) 718 { 719 int num_expansions = 0; 720 int depth = 0; 721 int narg = -1; 722 arg args[MAXARGS]; 723 int state = IN_TEXT; 724 const char *mark = in; 725 macro *pmacro = NULL; 726 char *expansion = 0; 727 char *result = 0; 728 729 while (*in) 730 { 731 switch (state) 732 { 733 case IN_TEXT: 734 if (*in == '%' && *(in + 1) && (!first_only || num_expansions == 0)) 735 { 736 pmacro = lookup_macro (in + 1); 737 if (pmacro) 738 { 739 /* printf("entering state %d at '%s'...\n", state, in); */ 740 result = str_append (result, mark, in - mark); 741 mark = in; 742 in += 1 + strlen (pmacro->name); 743 while (*in == ' ') ++in; 744 if (*in != '(') 745 { 746 state = IN_TEXT; 747 pmacro = NULL; 748 } 749 else 750 { 751 state = IN_ARGS; 752 narg = 0; 753 args[narg].start = in + 1; 754 args[narg].len = 0; 755 mark = in + 1; 756 } 757 } 758 } 759 break; 760 case IN_ARGS: 761 if (depth == 0) 762 { 763 switch (*in) 764 { 765 case ',': 766 narg++; 767 args[narg].start = (in + 1); 768 args[narg].len = 0; 769 break; 770 case ')': 771 state = IN_TEXT; 772 /* printf("entering state %d at '%s'...\n", state, in); */ 773 if (pmacro) 774 { 775 expansion = 0; 776 expansion = expand_macro (args, narg, pmacro); 777 num_expansions++; 778 if (expansion) 779 { 780 result = str_append (result, expansion, strlen (expansion)); 781 free (expansion); 782 } 783 } 784 else 785 { 786 result = str_append (result, mark, in - mark); 787 } 788 pmacro = NULL; 789 mark = in + 1; 790 break; 791 case '(': 792 depth++; 793 default: 794 args[narg].len++; 795 break; 796 } 797 } 798 else 799 { 800 if (*in == ')') 801 depth--; 802 if (narg > -1) 803 args[narg].len++; 804 } 805 806 } 807 ++in; 808 } 809 810 if (mark != in) 811 result = str_append (result, mark, in - mark); 812 813 return result; 814 } 815 816 #undef IN_ARGS 817 #undef IN_TEXT 818 #undef MAXARGS 819 820 821 /* END LIGHTWEIGHT MACRO PROCESSOR. */ 822 823 const char * mep_cgen_parse_operand 824 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *); 825 826 const char * 827 mep_cgen_expand_macros_and_parse_operand (CGEN_CPU_DESC cd, int opindex, 828 const char ** strp_in, CGEN_FIELDS * fields) 829 { 830 const char * errmsg = NULL; 831 char *str = 0, *hold = 0; 832 const char **strp = 0; 833 834 /* Set up a new pointer to macro-expanded string. */ 835 str = expand_string (*strp_in, 1); 836 /* fprintf (stderr, " expanded <<%s>> to <<%s>>\n", *strp_in, str); */ 837 838 hold = str; 839 strp = (const char **)(&str); 840 841 errmsg = mep_cgen_parse_operand (cd, opindex, strp, fields); 842 843 /* Now work out the advance. */ 844 if (strlen (str) == 0) 845 *strp_in += strlen (*strp_in); 846 847 else 848 { 849 if (strstr (*strp_in, str)) 850 /* A macro-expansion was pulled off the front. */ 851 *strp_in = strstr (*strp_in, str); 852 else 853 /* A non-macro-expansion was pulled off the front. */ 854 *strp_in += (str - hold); 855 } 856 857 if (hold) 858 free (hold); 859 860 return errmsg; 861 } 862 863 #define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand); 864 865 /* -- dis.c */ 866 867 #include "elf/mep.h" 868 #include "elf-bfd.h" 869 870 #define CGEN_VALIDATE_INSN_SUPPORTED 871 872 static void print_tpreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int); 873 static void print_spreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int); 874 875 static void 876 print_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info, 877 CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED, 878 unsigned int flags ATTRIBUTE_UNUSED) 879 { 880 disassemble_info *info = (disassemble_info *) dis_info; 881 882 (*info->fprintf_func) (info->stream, "$tp"); 883 } 884 885 static void 886 print_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info, 887 CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED, 888 unsigned int flags ATTRIBUTE_UNUSED) 889 { 890 disassemble_info *info = (disassemble_info *) dis_info; 891 892 (*info->fprintf_func) (info->stream, "$sp"); 893 } 894 895 /* begin-cop-ip-print-handlers */ 896 static void 897 print_ivc2_cr (CGEN_CPU_DESC, 898 void *, 899 CGEN_KEYWORD *, 900 long, 901 unsigned int) ATTRIBUTE_UNUSED; 902 static void 903 print_ivc2_cr (CGEN_CPU_DESC cd, 904 void *dis_info, 905 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED, 906 long value, 907 unsigned int attrs) 908 { 909 print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_ivc2, value, attrs); 910 } 911 static void 912 print_ivc2_ccr (CGEN_CPU_DESC, 913 void *, 914 CGEN_KEYWORD *, 915 long, 916 unsigned int) ATTRIBUTE_UNUSED; 917 static void 918 print_ivc2_ccr (CGEN_CPU_DESC cd, 919 void *dis_info, 920 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED, 921 long value, 922 unsigned int attrs) 923 { 924 print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_ivc2, value, attrs); 925 } 926 /* end-cop-ip-print-handlers */ 927 928 /************************************************************\ 929 *********************** Experimental ************************* 930 \************************************************************/ 931 932 #undef CGEN_PRINT_INSN 933 #define CGEN_PRINT_INSN mep_print_insn 934 935 static int 936 mep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info, 937 bfd_byte *buf, int corelength, int copro1length, 938 int copro2length ATTRIBUTE_UNUSED) 939 { 940 int i; 941 int status = 0; 942 /* char insnbuf[CGEN_MAX_INSN_SIZE]; */ 943 bfd_byte insnbuf[64]; 944 945 /* If corelength > 0 then there is a core insn present. It 946 will be at the beginning of the buffer. After printing 947 the core insn, we need to print the + on the next line. */ 948 if (corelength > 0) 949 { 950 int my_status = 0; 951 952 for (i = 0; i < corelength; i++ ) 953 insnbuf[i] = buf[i]; 954 cd->isas = & MEP_CORE_ISA; 955 956 my_status = print_insn (cd, pc, info, insnbuf, corelength); 957 if (my_status != corelength) 958 { 959 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); 960 my_status = corelength; 961 } 962 status += my_status; 963 964 /* Print the + to indicate that the following copro insn is */ 965 /* part of a vliw group. */ 966 if (copro1length > 0) 967 (*info->fprintf_func) (info->stream, " + "); 968 } 969 970 /* Now all that is left to be processed is the coprocessor insns 971 In vliw mode, there will always be one. Its positioning will 972 be from byte corelength to byte corelength+copro1length -1. 973 No need to check for existence. Also, the first vliw insn, 974 will, as spec'd, always be at least as long as the core insn 975 so we don't need to flush the buffer. */ 976 if (copro1length > 0) 977 { 978 int my_status = 0; 979 980 for (i = corelength; i < corelength + copro1length; i++ ) 981 insnbuf[i - corelength] = buf[i]; 982 983 switch (copro1length) 984 { 985 case 0: 986 break; 987 case 2: 988 cd->isas = & MEP_COP16_ISA; 989 break; 990 case 4: 991 cd->isas = & MEP_COP32_ISA; 992 break; 993 case 6: 994 cd->isas = & MEP_COP48_ISA; 995 break; 996 case 8: 997 cd->isas = & MEP_COP64_ISA; 998 break; 999 default: 1000 /* Shouldn't be anything but 16,32,48,64. */ 1001 break; 1002 } 1003 1004 my_status = print_insn (cd, pc, info, insnbuf, copro1length); 1005 1006 if (my_status != copro1length) 1007 { 1008 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); 1009 my_status = copro1length; 1010 } 1011 status += my_status; 1012 } 1013 1014 #if 0 1015 /* Now we need to process the second copro insn if it exists. We 1016 have no guarantee that the second copro insn will be longer 1017 than the first, so we have to flush the buffer if we are have 1018 a second copro insn to process. If present, this insn will 1019 be in the position from byte corelength+copro1length to byte 1020 corelength+copro1length+copro2length-1 (which better equal 8 1021 or else we're in big trouble. */ 1022 if (copro2length > 0) 1023 { 1024 int my_status = 0; 1025 1026 for (i = 0; i < 64 ; i++) 1027 insnbuf[i] = 0; 1028 1029 for (i = corelength + copro1length; i < 64; i++) 1030 insnbuf[i - (corelength + copro1length)] = buf[i]; 1031 1032 switch (copro2length) 1033 { 1034 case 2: 1035 cd->isas = 1 << ISA_EXT_COP1_16; 1036 break; 1037 case 4: 1038 cd->isas = 1 << ISA_EXT_COP1_32; 1039 break; 1040 case 6: 1041 cd->isas = 1 << ISA_EXT_COP1_48; 1042 break; 1043 case 8: 1044 cd->isas = 1 << ISA_EXT_COP1_64; 1045 break; 1046 default: 1047 /* Shouldn't be anything but 16,32,48,64. */ 1048 break; 1049 } 1050 1051 my_status = print_insn (cd, pc, info, insnbuf, copro2length); 1052 1053 if (my_status != copro2length) 1054 { 1055 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); 1056 my_status = copro2length; 1057 } 1058 1059 status += my_status; 1060 } 1061 #endif 1062 1063 /* Status should now be the number of bytes that were printed 1064 which should be 4 for VLIW32 mode and 64 for VLIW64 mode. */ 1065 1066 if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8))) 1067 return -1; 1068 else 1069 return status; 1070 } 1071 1072 /* The two functions mep_examine_vliw[32,64]_insns are used find out 1073 which vliw combinaion (16 bit core with 48 bit copro, 32 bit core 1074 with 32 bit copro, etc.) is present. Later on, when internally 1075 parallel coprocessors are handled, only these functions should 1076 need to be changed. 1077 1078 At this time only the following combinations are supported: 1079 1080 VLIW32 Mode: 1081 16 bit core insn (core) and 16 bit coprocessor insn (cop1) 1082 32 bit core insn (core) 1083 32 bit coprocessor insn (cop1) 1084 Note: As of this time, I do not believe we have enough information 1085 to distinguish a 32 bit core insn from a 32 bit cop insn. Also, 1086 no 16 bit coprocessor insns have been specified. 1087 1088 VLIW64 Mode: 1089 16 bit core insn (core) and 48 bit coprocessor insn (cop1) 1090 32 bit core insn (core) and 32 bit coprocessor insn (cop1) 1091 64 bit coprocessor insn (cop1) 1092 1093 The framework for an internally parallel coprocessor is also 1094 present (2nd coprocessor insn is cop2), but at this time it 1095 is not used. This only appears to be valid in VLIW64 mode. */ 1096 1097 static int 1098 mep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info) 1099 { 1100 int status; 1101 int buflength; 1102 int corebuflength; 1103 int cop1buflength; 1104 int cop2buflength; 1105 bfd_byte buf[CGEN_MAX_INSN_SIZE]; 1106 char indicator16[1]; 1107 char indicatorcop32[2]; 1108 1109 /* At this time we're not supporting internally parallel coprocessors, 1110 so cop2buflength will always be 0. */ 1111 cop2buflength = 0; 1112 1113 /* Read in 32 bits. */ 1114 buflength = 4; /* VLIW insn spans 4 bytes. */ 1115 status = (*info->read_memory_func) (pc, buf, buflength, info); 1116 1117 if (status != 0) 1118 { 1119 (*info->memory_error_func) (status, pc, info); 1120 return -1; 1121 } 1122 1123 /* Put the big endian representation of the bytes to be examined 1124 in the temporary buffers for examination. */ 1125 1126 if (info->endian == BFD_ENDIAN_BIG) 1127 { 1128 indicator16[0] = buf[0]; 1129 indicatorcop32[0] = buf[0]; 1130 indicatorcop32[1] = buf[1]; 1131 } 1132 else 1133 { 1134 indicator16[0] = buf[1]; 1135 indicatorcop32[0] = buf[1]; 1136 indicatorcop32[1] = buf[0]; 1137 } 1138 1139 /* If the two high order bits are 00, 01 or 10, we have a 16 bit 1140 core insn and a 48 bit copro insn. */ 1141 1142 if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40)) 1143 { 1144 if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07) 1145 { 1146 /* We have a 32 bit copro insn. */ 1147 corebuflength = 0; 1148 /* All 4 4ytes are one copro insn. */ 1149 cop1buflength = 4; 1150 } 1151 else 1152 { 1153 /* We have a 32 bit core. */ 1154 corebuflength = 4; 1155 cop1buflength = 0; 1156 } 1157 } 1158 else 1159 { 1160 /* We have a 16 bit core insn and a 16 bit copro insn. */ 1161 corebuflength = 2; 1162 cop1buflength = 2; 1163 } 1164 1165 /* Now we have the distrubution set. Print them out. */ 1166 status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength, 1167 cop1buflength, cop2buflength); 1168 1169 return status; 1170 } 1171 1172 static int 1173 mep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info) 1174 { 1175 int status; 1176 int buflength; 1177 int corebuflength; 1178 int cop1buflength; 1179 int cop2buflength; 1180 bfd_byte buf[CGEN_MAX_INSN_SIZE]; 1181 char indicator16[1]; 1182 char indicator64[4]; 1183 1184 /* At this time we're not supporting internally parallel 1185 coprocessors, so cop2buflength will always be 0. */ 1186 cop2buflength = 0; 1187 1188 /* Read in 64 bits. */ 1189 buflength = 8; /* VLIW insn spans 8 bytes. */ 1190 status = (*info->read_memory_func) (pc, buf, buflength, info); 1191 1192 if (status != 0) 1193 { 1194 (*info->memory_error_func) (status, pc, info); 1195 return -1; 1196 } 1197 1198 /* We have all 64 bits in the buffer now. We have to figure out 1199 what combination of instruction sizes are present. The two 1200 high order bits will indicate whether or not we have a 16 bit 1201 core insn or not. If not, then we have to look at the 7,8th 1202 bytes to tell whether we have 64 bit copro insn or a 32 bit 1203 core insn with a 32 bit copro insn. Endianness will make a 1204 difference here. */ 1205 1206 /* Put the big endian representation of the bytes to be examined 1207 in the temporary buffers for examination. */ 1208 1209 /* indicator16[0] = buf[0]; */ 1210 if (info->endian == BFD_ENDIAN_BIG) 1211 { 1212 indicator16[0] = buf[0]; 1213 indicator64[0] = buf[0]; 1214 indicator64[1] = buf[1]; 1215 indicator64[2] = buf[2]; 1216 indicator64[3] = buf[3]; 1217 } 1218 else 1219 { 1220 indicator16[0] = buf[1]; 1221 indicator64[0] = buf[1]; 1222 indicator64[1] = buf[0]; 1223 indicator64[2] = buf[3]; 1224 indicator64[3] = buf[2]; 1225 } 1226 1227 /* If the two high order bits are 00, 01 or 10, we have a 16 bit 1228 core insn and a 48 bit copro insn. */ 1229 1230 if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40)) 1231 { 1232 if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07 1233 && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0)) 1234 { 1235 /* We have a 64 bit copro insn. */ 1236 corebuflength = 0; 1237 /* All 8 bytes are one copro insn. */ 1238 cop1buflength = 8; 1239 } 1240 else 1241 { 1242 /* We have a 32 bit core insn and a 32 bit copro insn. */ 1243 corebuflength = 4; 1244 cop1buflength = 4; 1245 } 1246 } 1247 else 1248 { 1249 /* We have a 16 bit core insn and a 48 bit copro insn. */ 1250 corebuflength = 2; 1251 cop1buflength = 6; 1252 } 1253 1254 /* Now we have the distrubution set. Print them out. */ 1255 status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength, 1256 cop1buflength, cop2buflength); 1257 1258 return status; 1259 } 1260 1261 #ifdef MEP_IVC2_SUPPORTED 1262 1263 static int 1264 print_slot_insn (CGEN_CPU_DESC cd, 1265 bfd_vma pc, 1266 disassemble_info *info, 1267 SLOTS_ATTR slot, 1268 bfd_byte *buf) 1269 { 1270 const CGEN_INSN_LIST *insn_list; 1271 CGEN_INSN_INT insn_value; 1272 CGEN_EXTRACT_INFO ex_info; 1273 1274 insn_value = cgen_get_insn_value (cd, buf, 32); 1275 1276 /* Fill in ex_info fields like read_insn would. Don't actually call 1277 read_insn, since the incoming buffer is already read (and possibly 1278 modified a la m32r). */ 1279 ex_info.valid = (1 << 8) - 1; 1280 ex_info.dis_info = info; 1281 ex_info.insn_bytes = buf; 1282 1283 /* The instructions are stored in hash lists. 1284 Pick the first one and keep trying until we find the right one. */ 1285 1286 insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value); 1287 while (insn_list != NULL) 1288 { 1289 const CGEN_INSN *insn = insn_list->insn; 1290 CGEN_FIELDS fields; 1291 int length; 1292 1293 if ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG) 1294 && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG) != MEP_CONFIG) 1295 || ! (CGEN_ATTR_CGEN_INSN_SLOTS_VALUE (CGEN_INSN_ATTRS (insn)) & (1 << slot))) 1296 { 1297 insn_list = CGEN_DIS_NEXT_INSN (insn_list); 1298 continue; 1299 } 1300 1301 if ((insn_value & CGEN_INSN_BASE_MASK (insn)) 1302 == CGEN_INSN_BASE_VALUE (insn)) 1303 { 1304 /* Printing is handled in two passes. The first pass parses the 1305 machine insn and extracts the fields. The second pass prints 1306 them. */ 1307 1308 length = CGEN_EXTRACT_FN (cd, insn) 1309 (cd, insn, &ex_info, insn_value, &fields, pc); 1310 1311 /* Length < 0 -> error. */ 1312 if (length < 0) 1313 return length; 1314 if (length > 0) 1315 { 1316 CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length); 1317 /* Length is in bits, result is in bytes. */ 1318 return length / 8; 1319 } 1320 } 1321 1322 insn_list = CGEN_DIS_NEXT_INSN (insn_list); 1323 } 1324 1325 if (slot == SLOTS_P0S) 1326 (*info->fprintf_func) (info->stream, "*unknown-p0s*"); 1327 else if (slot == SLOTS_P0) 1328 (*info->fprintf_func) (info->stream, "*unknown-p0*"); 1329 else if (slot == SLOTS_P1) 1330 (*info->fprintf_func) (info->stream, "*unknown-p1*"); 1331 else if (slot == SLOTS_C3) 1332 (*info->fprintf_func) (info->stream, "*unknown-c3*"); 1333 return 0; 1334 } 1335 1336 static int 1337 mep_examine_ivc2_insns (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info ATTRIBUTE_UNUSED) 1338 { 1339 int status; 1340 int buflength; 1341 bfd_byte buf[8]; 1342 bfd_byte insn[8]; 1343 int e; 1344 1345 /* Read in 64 bits. */ 1346 buflength = 8; /* VLIW insn spans 8 bytes. */ 1347 status = (*info->read_memory_func) (pc, buf, buflength, info); 1348 1349 if (status != 0) 1350 { 1351 (*info->memory_error_func) (status, pc, info); 1352 return -1; 1353 } 1354 1355 if (info->endian == BFD_ENDIAN_LITTLE) 1356 e = 1; 1357 else 1358 e = 0; 1359 1360 if (((unsigned char)buf[0^e] & 0xf0) < 0xc0) 1361 { 1362 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */ 1363 /* V1 [-----core-----][--------p0s-------][------------p1------------] */ 1364 1365 print_insn (cd, pc, info, buf, 2); 1366 1367 insn[0^e] = 0; 1368 insn[1^e] = buf[2^e]; 1369 insn[2^e] = buf[3^e]; 1370 insn[3^e] = buf[4^e] & 0xf0; 1371 (*info->fprintf_func) (info->stream, " + "); 1372 print_slot_insn (cd, pc, info, SLOTS_P0S, insn); 1373 1374 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4; 1375 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4; 1376 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4; 1377 insn[3^e] = buf[7^e] << 4; 1378 (*info->fprintf_func) (info->stream, " + "); 1379 print_slot_insn (cd, pc, info, SLOTS_P1, insn); 1380 } 1381 else if ((buf[0^e] & 0xf0) == 0xf0 && (buf[1^e] & 0x0f) == 0x07) 1382 { 1383 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */ 1384 /* V3 1111[--p0--]0111[--------p0--------][------------p1------------] */ 1385 /* 00000000111111112222222233333333 */ 1386 1387 insn[0^e] = buf[0^e] << 4 | buf[1^e] >> 4; 1388 insn[1^e] = buf[2^e]; 1389 insn[2^e] = buf[3^e]; 1390 insn[3^e] = buf[4^e] & 0xf0; 1391 print_slot_insn (cd, pc, info, SLOTS_P0, insn); 1392 1393 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4; 1394 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4; 1395 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4; 1396 insn[3^e] = buf[7^e] << 4; 1397 (*info->fprintf_func) (info->stream, " + "); 1398 print_slot_insn (cd, pc, info, SLOTS_P1, insn); 1399 } 1400 else 1401 { 1402 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */ 1403 /* V2 [-------------core-------------]xxxx[------------p1------------] */ 1404 print_insn (cd, pc, info, buf, 4); 1405 1406 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4; 1407 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4; 1408 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4; 1409 insn[3^e] = buf[7^e] << 4; 1410 (*info->fprintf_func) (info->stream, " + "); 1411 print_slot_insn (cd, pc, info, SLOTS_P1, insn); 1412 } 1413 1414 return 8; 1415 } 1416 1417 #endif /* MEP_IVC2_SUPPORTED */ 1418 1419 /* This is a hack. SID calls this to update the disassembler as the 1420 CPU changes modes. */ 1421 static int mep_ivc2_disassemble_p = 0; 1422 static int mep_ivc2_vliw_disassemble_p = 0; 1423 1424 void 1425 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx); 1426 void 1427 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx) 1428 { 1429 mep_ivc2_disassemble_p = ivc2_p; 1430 mep_ivc2_vliw_disassemble_p = vliw_p; 1431 mep_config_index = cfg_idx; 1432 } 1433 1434 static int 1435 mep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info) 1436 { 1437 int status; 1438 int cop_type; 1439 int ivc2 = 0; 1440 static CGEN_ATTR_VALUE_BITSET_TYPE *ivc2_core_isa = NULL; 1441 1442 if (ivc2_core_isa == NULL) 1443 { 1444 /* IVC2 has some core-only coprocessor instructions. We 1445 use COP32 to flag those, and COP64 for the VLIW ones, 1446 since they have the same names. */ 1447 ivc2_core_isa = cgen_bitset_create (MAX_ISAS); 1448 } 1449 1450 /* Extract and adapt to configuration number, if available. */ 1451 if (info->section && info->section->owner) 1452 { 1453 bfd *abfd = info->section->owner; 1454 mep_config_index = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_INDEX_MASK; 1455 /* This instantly redefines MEP_CONFIG, MEP_OMASK, .... MEP_VLIW64 */ 1456 1457 cop_type = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_COP_MASK; 1458 if (cop_type == EF_MEP_COP_IVC2) 1459 ivc2 = 1; 1460 } 1461 1462 /* Picking the right ISA bitmask for the current context is tricky. */ 1463 if (info->section) 1464 { 1465 if (info->section->flags & SEC_MEP_VLIW) 1466 { 1467 #ifdef MEP_IVC2_SUPPORTED 1468 if (ivc2) 1469 { 1470 /* ivc2 has its own way of selecting its functions. */ 1471 cd->isas = & MEP_CORE_ISA; 1472 status = mep_examine_ivc2_insns (cd, pc, info); 1473 } 1474 else 1475 #endif 1476 /* Are we in 32 or 64 bit vliw mode? */ 1477 if (MEP_VLIW64) 1478 status = mep_examine_vliw64_insns (cd, pc, info); 1479 else 1480 status = mep_examine_vliw32_insns (cd, pc, info); 1481 /* Both the above branches set their own isa bitmasks. */ 1482 } 1483 else 1484 { 1485 if (ivc2) 1486 { 1487 cgen_bitset_clear (ivc2_core_isa); 1488 cgen_bitset_union (ivc2_core_isa, &MEP_CORE_ISA, ivc2_core_isa); 1489 cgen_bitset_union (ivc2_core_isa, &MEP_COP32_ISA, ivc2_core_isa); 1490 cd->isas = ivc2_core_isa; 1491 } 1492 else 1493 cd->isas = & MEP_CORE_ISA; 1494 status = default_print_insn (cd, pc, info); 1495 } 1496 } 1497 else /* sid or gdb */ 1498 { 1499 #ifdef MEP_IVC2_SUPPORTED 1500 if (mep_ivc2_disassemble_p) 1501 { 1502 if (mep_ivc2_vliw_disassemble_p) 1503 { 1504 cd->isas = & MEP_CORE_ISA; 1505 status = mep_examine_ivc2_insns (cd, pc, info); 1506 return status; 1507 } 1508 else 1509 { 1510 if (ivc2) 1511 cd->isas = ivc2_core_isa; 1512 } 1513 } 1514 #endif 1515 1516 status = default_print_insn (cd, pc, info); 1517 } 1518 1519 return status; 1520 } 1521 1522 1523 /* -- opc.c */ 1524 #include "elf/mep.h" 1525 1526 /* A mask for all ISAs executed by the core. */ 1527 CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask = {0, 0}; 1528 1529 void 1530 init_mep_all_core_isas_mask (void) 1531 { 1532 if (mep_all_core_isas_mask.length != 0) 1533 return; 1534 cgen_bitset_init (& mep_all_core_isas_mask, ISA_MAX); 1535 cgen_bitset_set (& mep_all_core_isas_mask, ISA_MEP); 1536 /* begin-all-core-isas */ 1537 cgen_bitset_add (& mep_all_core_isas_mask, ISA_EXT_CORE1); 1538 /* end-all-core-isas */ 1539 } 1540 1541 CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask = {0, 0}; 1542 1543 void 1544 init_mep_all_cop_isas_mask (void) 1545 { 1546 if (mep_all_cop_isas_mask.length != 0) 1547 return; 1548 cgen_bitset_init (& mep_all_cop_isas_mask, ISA_MAX); 1549 /* begin-all-cop-isas */ 1550 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_16); 1551 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_32); 1552 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_48); 1553 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_64); 1554 /* end-all-cop-isas */ 1555 } 1556 1557 int 1558 mep_insn_supported_by_isa (const CGEN_INSN *insn, CGEN_ATTR_VALUE_BITSET_TYPE *isa_mask) 1559 { 1560 CGEN_BITSET insn_isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA); 1561 return cgen_bitset_intersect_p (& insn_isas, isa_mask); 1562 } 1563 1564 #define OPTION_MASK \ 1565 ( (1 << CGEN_INSN_OPTIONAL_BIT_INSN) \ 1566 | (1 << CGEN_INSN_OPTIONAL_MUL_INSN) \ 1567 | (1 << CGEN_INSN_OPTIONAL_DIV_INSN) \ 1568 | (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN) \ 1569 | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN) \ 1570 | (1 << CGEN_INSN_OPTIONAL_ABS_INSN) \ 1571 | (1 << CGEN_INSN_OPTIONAL_AVE_INSN) \ 1572 | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN) \ 1573 | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN) \ 1574 | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) \ 1575 | (1 << CGEN_INSN_OPTIONAL_UCI_INSN) \ 1576 | (1 << CGEN_INSN_OPTIONAL_DSP_INSN) \ 1577 | (1 << CGEN_INSN_OPTIONAL_CP_INSN) \ 1578 | (1 << CGEN_INSN_OPTIONAL_CP64_INSN) ) 1579 1580 1581 mep_config_map_struct mep_config_map[] = 1582 { 1583 /* config-map-start */ 1584 /* Default entry: first module, with all options enabled. */ 1585 { "", 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) }, 1586 { "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" }, 1587 0 1588 | (1 << CGEN_INSN_OPTIONAL_CP_INSN) 1589 | (1 << CGEN_INSN_OPTIONAL_CP64_INSN) 1590 | (1 << CGEN_INSN_OPTIONAL_MUL_INSN) 1591 | (1 << CGEN_INSN_OPTIONAL_DIV_INSN) 1592 | (1 << CGEN_INSN_OPTIONAL_BIT_INSN) 1593 | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN) 1594 | (1 << CGEN_INSN_OPTIONAL_ABS_INSN) 1595 | (1 << CGEN_INSN_OPTIONAL_AVE_INSN) 1596 | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN) 1597 | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN) 1598 | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) }, 1599 /* config-map-end */ 1600 { 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0 } 1601 }; 1602 1603 int mep_config_index = 0; 1604 1605 static int 1606 check_configured_mach (int machs) 1607 { 1608 /* All base insns are supported. */ 1609 int mach = 1 << MACH_BASE; 1610 switch (MEP_CPU & EF_MEP_CPU_MASK) 1611 { 1612 case EF_MEP_CPU_C2: 1613 case EF_MEP_CPU_C3: 1614 mach |= (1 << MACH_MEP); 1615 break; 1616 case EF_MEP_CPU_H1: 1617 mach |= (1 << MACH_H1); 1618 break; 1619 case EF_MEP_CPU_C5: 1620 mach |= (1 << MACH_MEP); 1621 mach |= (1 << MACH_C5); 1622 break; 1623 default: 1624 break; 1625 } 1626 return machs & mach; 1627 } 1628 1629 int 1630 mep_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn) 1631 { 1632 int iconfig = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG); 1633 int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH); 1634 CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA); 1635 int ok1; 1636 int ok2; 1637 int ok3; 1638 1639 /* If the insn has an option bit set that we don't want, 1640 reject it. */ 1641 if (CGEN_INSN_ATTRS (insn)->bool_ & OPTION_MASK & ~MEP_OMASK) 1642 return 0; 1643 1644 /* If attributes are absent, assume no restriction. */ 1645 if (machs == 0) 1646 machs = ~0; 1647 1648 ok1 = ((machs & cd->machs) && cgen_bitset_intersect_p (& isas, cd->isas)); 1649 /* If the insn is config-specific, make sure it matches. */ 1650 ok2 = (iconfig == 0 || iconfig == MEP_CONFIG); 1651 /* Make sure the insn is supported by the configured mach */ 1652 ok3 = check_configured_mach (machs); 1653 1654 return (ok1 && ok2 && ok3); 1655 } 1656 1657 int 1658 mep_cgen_insn_supported_asm (CGEN_CPU_DESC cd, const CGEN_INSN *insn) 1659 { 1660 #ifdef MEP_IVC2_SUPPORTED 1661 /* If we're assembling VLIW packets, ignore the 12-bit BSR as we 1662 can't relax that. The 24-bit BSR is matched instead. */ 1663 if (insn->base->num == MEP_INSN_BSR12 1664 && cgen_bitset_contains (cd->isas, ISA_EXT_COP1_64)) 1665 return 0; 1666 #endif 1667 1668 return mep_cgen_insn_supported (cd, insn); 1669 } 1670