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 33typedef 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 49extern mep_config_map_struct mep_config_map[]; 50extern int mep_config_index; 51 52extern void init_mep_all_core_isas_mask (void); 53extern void init_mep_all_cop_isas_mask (void); 54extern 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 73extern 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 77extern 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 86extern 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 93extern int mep_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *); 94extern 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 *); 108static const char * parse_signed16 (CGEN_CPU_DESC, const char **, int, long *); 109static const char * parse_signed16_range (CGEN_CPU_DESC, const char **, int, long *) ATTRIBUTE_UNUSED; 110static const char * parse_unsigned16 (CGEN_CPU_DESC, const char **, int, unsigned long *); 111static const char * parse_unsigned16_range (CGEN_CPU_DESC, const char **, int, unsigned long *) ATTRIBUTE_UNUSED; 112static const char * parse_lo16 (CGEN_CPU_DESC, const char **, int, long *, long); 113static const char * parse_unsigned7 (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *); 114static const char * parse_zero (CGEN_CPU_DESC, const char **, int, long *); 115 116const char * 117parse_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 */ 135static const char * 136parse_ivc2_cr (CGEN_CPU_DESC, 137 const char **, 138 CGEN_KEYWORD *, 139 long *) ATTRIBUTE_UNUSED; 140static const char * 141parse_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} 148static const char * 149parse_ivc2_ccr (CGEN_CPU_DESC, 150 const char **, 151 CGEN_KEYWORD *, 152 long *) ATTRIBUTE_UNUSED; 153static const char * 154parse_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 163const char * 164parse_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 177const char * 178parse_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 191const char * 192parse_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 248const char * 249parse_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 259static const char * 260parse_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 268static const char * 269parse_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 357static const char * 358parse_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 366static const char * 367parse_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 386static const char * 387parse_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 408static const char * 409parse_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 510static const char * 511parse_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 553static ATTRIBUTE_UNUSED const char * 554parse_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 617typedef struct 618{ 619 char *name; 620 char *expansion; 621} macro; 622 623typedef struct 624{ 625 const char *start; 626 int len; 627} arg; 628 629static macro const 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 641static char * expand_string (const char *, int); 642 643static const char * 644mep_cgen_expand_macros_and_parse_operand 645 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *); 646 647static char * 648str_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 662static const macro * 663lookup_macro (const char *name) 664{ 665 const 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 674static char * 675expand_macro (arg *args, int narg, const 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 716static char * 717expand_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 const 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 /* Fall through. */ 794 default: 795 args[narg].len++; 796 break; 797 } 798 } 799 else 800 { 801 if (*in == ')') 802 depth--; 803 if (narg > -1) 804 args[narg].len++; 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 823const char * mep_cgen_parse_operand 824 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *); 825 826const char * 827mep_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 free (hold); 858 859 return errmsg; 860} 861 862#define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand); 863 864/* -- dis.c */ 865 866#include "elf/mep.h" 867#include "elf-bfd.h" 868 869#define CGEN_VALIDATE_INSN_SUPPORTED 870 871static void 872print_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, void *dis_info, 873 CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED, 874 unsigned int flags ATTRIBUTE_UNUSED) 875{ 876 disassemble_info *info = (disassemble_info *) dis_info; 877 878 (*info->fprintf_func) (info->stream, "$tp"); 879} 880 881static void 882print_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, void *dis_info, 883 CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED, 884 unsigned int flags ATTRIBUTE_UNUSED) 885{ 886 disassemble_info *info = (disassemble_info *) dis_info; 887 888 (*info->fprintf_func) (info->stream, "$sp"); 889} 890 891/* begin-cop-ip-print-handlers */ 892static void 893print_ivc2_cr (CGEN_CPU_DESC, 894 void *, 895 CGEN_KEYWORD *, 896 long, 897 unsigned int) ATTRIBUTE_UNUSED; 898static void 899print_ivc2_cr (CGEN_CPU_DESC cd, 900 void *dis_info, 901 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED, 902 long value, 903 unsigned int attrs) 904{ 905 print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_ivc2, value, attrs); 906} 907static void 908print_ivc2_ccr (CGEN_CPU_DESC, 909 void *, 910 CGEN_KEYWORD *, 911 long, 912 unsigned int) ATTRIBUTE_UNUSED; 913static void 914print_ivc2_ccr (CGEN_CPU_DESC cd, 915 void *dis_info, 916 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED, 917 long value, 918 unsigned int attrs) 919{ 920 print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_ivc2, value, attrs); 921} 922/* end-cop-ip-print-handlers */ 923 924/************************************************************\ 925*********************** Experimental ************************* 926\************************************************************/ 927 928#undef CGEN_PRINT_INSN 929#define CGEN_PRINT_INSN mep_print_insn 930 931static int 932mep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info, 933 bfd_byte *buf, int corelength, int copro1length, 934 int copro2length ATTRIBUTE_UNUSED) 935{ 936 int i; 937 int status = 0; 938 /* char insnbuf[CGEN_MAX_INSN_SIZE]; */ 939 bfd_byte insnbuf[64]; 940 941 /* If corelength > 0 then there is a core insn present. It 942 will be at the beginning of the buffer. After printing 943 the core insn, we need to print the + on the next line. */ 944 if (corelength > 0) 945 { 946 int my_status = 0; 947 948 for (i = 0; i < corelength; i++ ) 949 insnbuf[i] = buf[i]; 950 cd->isas = & MEP_CORE_ISA; 951 952 my_status = print_insn (cd, pc, info, insnbuf, corelength); 953 if (my_status != corelength) 954 { 955 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); 956 my_status = corelength; 957 } 958 status += my_status; 959 960 /* Print the + to indicate that the following copro insn is 961 part of a vliw group. */ 962 if (copro1length > 0) 963 (*info->fprintf_func) (info->stream, " + "); 964 } 965 966 /* Now all that is left to be processed is the coprocessor insns 967 In vliw mode, there will always be one. Its positioning will 968 be from byte corelength to byte corelength+copro1length -1. 969 No need to check for existence. Also, the first vliw insn, 970 will, as spec'd, always be at least as long as the core insn 971 so we don't need to flush the buffer. */ 972 if (copro1length > 0) 973 { 974 int my_status = 0; 975 976 for (i = corelength; i < corelength + copro1length; i++ ) 977 insnbuf[i - corelength] = buf[i]; 978 979 switch (copro1length) 980 { 981 case 0: 982 break; 983 case 2: 984 cd->isas = & MEP_COP16_ISA; 985 break; 986 case 4: 987 cd->isas = & MEP_COP32_ISA; 988 break; 989 case 6: 990 cd->isas = & MEP_COP48_ISA; 991 break; 992 case 8: 993 cd->isas = & MEP_COP64_ISA; 994 break; 995 default: 996 /* Shouldn't be anything but 16,32,48,64. */ 997 break; 998 } 999 1000 my_status = print_insn (cd, pc, info, insnbuf, copro1length); 1001 1002 if (my_status != copro1length) 1003 { 1004 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); 1005 my_status = copro1length; 1006 } 1007 status += my_status; 1008 } 1009 1010#if 0 1011 /* Now we need to process the second copro insn if it exists. We 1012 have no guarantee that the second copro insn will be longer 1013 than the first, so we have to flush the buffer if we are have 1014 a second copro insn to process. If present, this insn will 1015 be in the position from byte corelength+copro1length to byte 1016 corelength+copro1length+copro2length-1 (which better equal 8 1017 or else we're in big trouble. */ 1018 if (copro2length > 0) 1019 { 1020 int my_status = 0; 1021 1022 for (i = 0; i < 64 ; i++) 1023 insnbuf[i] = 0; 1024 1025 for (i = corelength + copro1length; i < 64; i++) 1026 insnbuf[i - (corelength + copro1length)] = buf[i]; 1027 1028 switch (copro2length) 1029 { 1030 case 2: 1031 cd->isas = 1 << ISA_EXT_COP1_16; 1032 break; 1033 case 4: 1034 cd->isas = 1 << ISA_EXT_COP1_32; 1035 break; 1036 case 6: 1037 cd->isas = 1 << ISA_EXT_COP1_48; 1038 break; 1039 case 8: 1040 cd->isas = 1 << ISA_EXT_COP1_64; 1041 break; 1042 default: 1043 /* Shouldn't be anything but 16,32,48,64. */ 1044 break; 1045 } 1046 1047 my_status = print_insn (cd, pc, info, insnbuf, copro2length); 1048 1049 if (my_status != copro2length) 1050 { 1051 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); 1052 my_status = copro2length; 1053 } 1054 1055 status += my_status; 1056 } 1057#endif 1058 1059 /* Status should now be the number of bytes that were printed 1060 which should be 4 for VLIW32 mode and 64 for VLIW64 mode. */ 1061 1062 if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8))) 1063 return -1; 1064 else 1065 return status; 1066} 1067 1068/* The two functions mep_examine_vliw[32,64]_insns are used find out 1069 which vliw combinaion (16 bit core with 48 bit copro, 32 bit core 1070 with 32 bit copro, etc.) is present. Later on, when internally 1071 parallel coprocessors are handled, only these functions should 1072 need to be changed. 1073 1074 At this time only the following combinations are supported: 1075 1076 VLIW32 Mode: 1077 16 bit core insn (core) and 16 bit coprocessor insn (cop1) 1078 32 bit core insn (core) 1079 32 bit coprocessor insn (cop1) 1080 Note: As of this time, I do not believe we have enough information 1081 to distinguish a 32 bit core insn from a 32 bit cop insn. Also, 1082 no 16 bit coprocessor insns have been specified. 1083 1084 VLIW64 Mode: 1085 16 bit core insn (core) and 48 bit coprocessor insn (cop1) 1086 32 bit core insn (core) and 32 bit coprocessor insn (cop1) 1087 64 bit coprocessor insn (cop1) 1088 1089 The framework for an internally parallel coprocessor is also 1090 present (2nd coprocessor insn is cop2), but at this time it 1091 is not used. This only appears to be valid in VLIW64 mode. */ 1092 1093static int 1094mep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info) 1095{ 1096 int status; 1097 int buflength; 1098 int corebuflength; 1099 int cop1buflength; 1100 int cop2buflength; 1101 bfd_byte buf[CGEN_MAX_INSN_SIZE]; 1102 char indicator16[1]; 1103 char indicatorcop32[2]; 1104 1105 /* At this time we're not supporting internally parallel coprocessors, 1106 so cop2buflength will always be 0. */ 1107 cop2buflength = 0; 1108 1109 /* Read in 32 bits. */ 1110 buflength = 4; /* VLIW insn spans 4 bytes. */ 1111 status = (*info->read_memory_func) (pc, buf, buflength, info); 1112 1113 if (status != 0) 1114 { 1115 (*info->memory_error_func) (status, pc, info); 1116 return -1; 1117 } 1118 1119 /* Put the big endian representation of the bytes to be examined 1120 in the temporary buffers for examination. */ 1121 1122 if (info->endian == BFD_ENDIAN_BIG) 1123 { 1124 indicator16[0] = buf[0]; 1125 indicatorcop32[0] = buf[0]; 1126 indicatorcop32[1] = buf[1]; 1127 } 1128 else 1129 { 1130 indicator16[0] = buf[1]; 1131 indicatorcop32[0] = buf[1]; 1132 indicatorcop32[1] = buf[0]; 1133 } 1134 1135 /* If the two high order bits are 00, 01 or 10, we have a 16 bit 1136 core insn and a 48 bit copro insn. */ 1137 1138 if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40)) 1139 { 1140 if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07) 1141 { 1142 /* We have a 32 bit copro insn. */ 1143 corebuflength = 0; 1144 /* All 4 4ytes are one copro insn. */ 1145 cop1buflength = 4; 1146 } 1147 else 1148 { 1149 /* We have a 32 bit core. */ 1150 corebuflength = 4; 1151 cop1buflength = 0; 1152 } 1153 } 1154 else 1155 { 1156 /* We have a 16 bit core insn and a 16 bit copro insn. */ 1157 corebuflength = 2; 1158 cop1buflength = 2; 1159 } 1160 1161 /* Now we have the distrubution set. Print them out. */ 1162 status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength, 1163 cop1buflength, cop2buflength); 1164 1165 return status; 1166} 1167 1168static int 1169mep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info) 1170{ 1171 int status; 1172 int buflength; 1173 int corebuflength; 1174 int cop1buflength; 1175 int cop2buflength; 1176 bfd_byte buf[CGEN_MAX_INSN_SIZE]; 1177 char indicator16[1]; 1178 char indicator64[4]; 1179 1180 /* At this time we're not supporting internally parallel 1181 coprocessors, so cop2buflength will always be 0. */ 1182 cop2buflength = 0; 1183 1184 /* Read in 64 bits. */ 1185 buflength = 8; /* VLIW insn spans 8 bytes. */ 1186 status = (*info->read_memory_func) (pc, buf, buflength, info); 1187 1188 if (status != 0) 1189 { 1190 (*info->memory_error_func) (status, pc, info); 1191 return -1; 1192 } 1193 1194 /* We have all 64 bits in the buffer now. We have to figure out 1195 what combination of instruction sizes are present. The two 1196 high order bits will indicate whether or not we have a 16 bit 1197 core insn or not. If not, then we have to look at the 7,8th 1198 bytes to tell whether we have 64 bit copro insn or a 32 bit 1199 core insn with a 32 bit copro insn. Endianness will make a 1200 difference here. */ 1201 1202 /* Put the big endian representation of the bytes to be examined 1203 in the temporary buffers for examination. */ 1204 1205 /* indicator16[0] = buf[0]; */ 1206 if (info->endian == BFD_ENDIAN_BIG) 1207 { 1208 indicator16[0] = buf[0]; 1209 indicator64[0] = buf[0]; 1210 indicator64[1] = buf[1]; 1211 indicator64[2] = buf[2]; 1212 indicator64[3] = buf[3]; 1213 } 1214 else 1215 { 1216 indicator16[0] = buf[1]; 1217 indicator64[0] = buf[1]; 1218 indicator64[1] = buf[0]; 1219 indicator64[2] = buf[3]; 1220 indicator64[3] = buf[2]; 1221 } 1222 1223 /* If the two high order bits are 00, 01 or 10, we have a 16 bit 1224 core insn and a 48 bit copro insn. */ 1225 1226 if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40)) 1227 { 1228 if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07 1229 && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0)) 1230 { 1231 /* We have a 64 bit copro insn. */ 1232 corebuflength = 0; 1233 /* All 8 bytes are one copro insn. */ 1234 cop1buflength = 8; 1235 } 1236 else 1237 { 1238 /* We have a 32 bit core insn and a 32 bit copro insn. */ 1239 corebuflength = 4; 1240 cop1buflength = 4; 1241 } 1242 } 1243 else 1244 { 1245 /* We have a 16 bit core insn and a 48 bit copro insn. */ 1246 corebuflength = 2; 1247 cop1buflength = 6; 1248 } 1249 1250 /* Now we have the distrubution set. Print them out. */ 1251 status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength, 1252 cop1buflength, cop2buflength); 1253 1254 return status; 1255} 1256 1257#ifdef MEP_IVC2_SUPPORTED 1258 1259static int 1260print_slot_insn (CGEN_CPU_DESC cd, 1261 bfd_vma pc, 1262 disassemble_info *info, 1263 SLOTS_ATTR slot, 1264 bfd_byte *buf) 1265{ 1266 const CGEN_INSN_LIST *insn_list; 1267 CGEN_INSN_INT insn_value; 1268 CGEN_EXTRACT_INFO ex_info; 1269 1270 insn_value = cgen_get_insn_value (cd, buf, 32, cd->insn_endian); 1271 1272 /* Fill in ex_info fields like read_insn would. Don't actually call 1273 read_insn, since the incoming buffer is already read (and possibly 1274 modified a la m32r). */ 1275 ex_info.valid = (1 << 8) - 1; 1276 ex_info.dis_info = info; 1277 ex_info.insn_bytes = buf; 1278 1279 /* The instructions are stored in hash lists. 1280 Pick the first one and keep trying until we find the right one. */ 1281 1282 insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value); 1283 while (insn_list != NULL) 1284 { 1285 const CGEN_INSN *insn = insn_list->insn; 1286 CGEN_FIELDS fields; 1287 int length; 1288 1289 if ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG) 1290 && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG) != MEP_CONFIG) 1291 || ! (CGEN_ATTR_CGEN_INSN_SLOTS_VALUE (CGEN_INSN_ATTRS (insn)) & (1 << slot))) 1292 { 1293 insn_list = CGEN_DIS_NEXT_INSN (insn_list); 1294 continue; 1295 } 1296 1297 if ((insn_value & CGEN_INSN_BASE_MASK (insn)) 1298 == CGEN_INSN_BASE_VALUE (insn)) 1299 { 1300 /* Printing is handled in two passes. The first pass parses the 1301 machine insn and extracts the fields. The second pass prints 1302 them. */ 1303 1304 length = CGEN_EXTRACT_FN (cd, insn) 1305 (cd, insn, &ex_info, insn_value, &fields, pc); 1306 1307 /* Length < 0 -> error. */ 1308 if (length < 0) 1309 return length; 1310 if (length > 0) 1311 { 1312 CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length); 1313 /* Length is in bits, result is in bytes. */ 1314 return length / 8; 1315 } 1316 } 1317 1318 insn_list = CGEN_DIS_NEXT_INSN (insn_list); 1319 } 1320 1321 if (slot == SLOTS_P0S) 1322 (*info->fprintf_func) (info->stream, "*unknown-p0s*"); 1323 else if (slot == SLOTS_P0) 1324 (*info->fprintf_func) (info->stream, "*unknown-p0*"); 1325 else if (slot == SLOTS_P1) 1326 (*info->fprintf_func) (info->stream, "*unknown-p1*"); 1327 else if (slot == SLOTS_C3) 1328 (*info->fprintf_func) (info->stream, "*unknown-c3*"); 1329 return 0; 1330} 1331 1332static int 1333mep_examine_ivc2_insns (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info ATTRIBUTE_UNUSED) 1334{ 1335 int status; 1336 int buflength; 1337 bfd_byte buf[8]; 1338 bfd_byte insn[8]; 1339 int e; 1340 1341 /* Read in 64 bits. */ 1342 buflength = 8; /* VLIW insn spans 8 bytes. */ 1343 status = (*info->read_memory_func) (pc, buf, buflength, info); 1344 1345 if (status != 0) 1346 { 1347 (*info->memory_error_func) (status, pc, info); 1348 return -1; 1349 } 1350 1351 if (info->endian == BFD_ENDIAN_LITTLE) 1352 e = 1; 1353 else 1354 e = 0; 1355 1356 if (((unsigned char)buf[0^e] & 0xf0) < 0xc0) 1357 { 1358 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */ 1359 /* V1 [-----core-----][--------p0s-------][------------p1------------] */ 1360 1361 print_insn (cd, pc, info, buf, 2); 1362 1363 insn[0^e] = 0; 1364 insn[1^e] = buf[2^e]; 1365 insn[2^e] = buf[3^e]; 1366 insn[3^e] = buf[4^e] & 0xf0; 1367 (*info->fprintf_func) (info->stream, " + "); 1368 print_slot_insn (cd, pc, info, SLOTS_P0S, insn); 1369 1370 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4; 1371 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4; 1372 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4; 1373 insn[3^e] = buf[7^e] << 4; 1374 (*info->fprintf_func) (info->stream, " + "); 1375 print_slot_insn (cd, pc, info, SLOTS_P1, insn); 1376 } 1377 else if ((buf[0^e] & 0xf0) == 0xf0 && (buf[1^e] & 0x0f) == 0x07) 1378 { 1379 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */ 1380 /* V3 1111[--p0--]0111[--------p0--------][------------p1------------] */ 1381 /* 00000000111111112222222233333333 */ 1382 1383 insn[0^e] = buf[0^e] << 4 | buf[1^e] >> 4; 1384 insn[1^e] = buf[2^e]; 1385 insn[2^e] = buf[3^e]; 1386 insn[3^e] = buf[4^e] & 0xf0; 1387 print_slot_insn (cd, pc, info, SLOTS_P0, insn); 1388 1389 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4; 1390 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4; 1391 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4; 1392 insn[3^e] = buf[7^e] << 4; 1393 (*info->fprintf_func) (info->stream, " + "); 1394 print_slot_insn (cd, pc, info, SLOTS_P1, insn); 1395 } 1396 else 1397 { 1398 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */ 1399 /* V2 [-------------core-------------]xxxx[------------p1------------] */ 1400 print_insn (cd, pc, info, buf, 4); 1401 1402 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4; 1403 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4; 1404 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4; 1405 insn[3^e] = buf[7^e] << 4; 1406 (*info->fprintf_func) (info->stream, " + "); 1407 print_slot_insn (cd, pc, info, SLOTS_P1, insn); 1408 } 1409 1410 return 8; 1411} 1412 1413#endif /* MEP_IVC2_SUPPORTED */ 1414 1415/* This is a hack. SID calls this to update the disassembler as the 1416 CPU changes modes. */ 1417static int mep_ivc2_disassemble_p = 0; 1418static int mep_ivc2_vliw_disassemble_p = 0; 1419 1420void 1421mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx); 1422void 1423mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx) 1424{ 1425 mep_ivc2_disassemble_p = ivc2_p; 1426 mep_ivc2_vliw_disassemble_p = vliw_p; 1427 mep_config_index = cfg_idx; 1428} 1429 1430static int 1431mep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info) 1432{ 1433 int status; 1434 int cop_type; 1435 int ivc2 = 0; 1436 static CGEN_ATTR_VALUE_BITSET_TYPE *ivc2_core_isa = NULL; 1437 1438 if (ivc2_core_isa == NULL) 1439 { 1440 /* IVC2 has some core-only coprocessor instructions. We 1441 use COP32 to flag those, and COP64 for the VLIW ones, 1442 since they have the same names. */ 1443 ivc2_core_isa = cgen_bitset_create (MAX_ISAS); 1444 } 1445 1446 /* Extract and adapt to configuration number, if available. */ 1447 if (info->section && info->section->owner) 1448 { 1449 bfd *abfd = info->section->owner; 1450 if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) 1451 { 1452 mep_config_index = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_INDEX_MASK; 1453 /* This instantly redefines MEP_CONFIG, MEP_OMASK, .... MEP_VLIW64 */ 1454 1455 /* mep_config_map is a variable sized array, so we do not know how big it is. 1456 The only safe way to check the index therefore is to iterate over the array. 1457 We do know that the last entry is all null. */ 1458 int i; 1459 for (i = 0; i <= mep_config_index; i++) 1460 if (mep_config_map[i].name == NULL) 1461 break; 1462 1463 if (i < mep_config_index) 1464 { 1465 opcodes_error_handler (_("illegal MEP INDEX setting '%x' in ELF header e_flags field"), mep_config_index); 1466 mep_config_index = 0; 1467 } 1468 1469 cop_type = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_COP_MASK; 1470 if (cop_type == EF_MEP_COP_IVC2) 1471 ivc2 = 1; 1472 } 1473 } 1474 1475 /* Picking the right ISA bitmask for the current context is tricky. */ 1476 if (info->section) 1477 { 1478 if (info->section->flags & SEC_MEP_VLIW) 1479 { 1480#ifdef MEP_IVC2_SUPPORTED 1481 if (ivc2) 1482 { 1483 /* ivc2 has its own way of selecting its functions. */ 1484 cd->isas = & MEP_CORE_ISA; 1485 status = mep_examine_ivc2_insns (cd, pc, info); 1486 } 1487 else 1488#endif 1489 /* Are we in 32 or 64 bit vliw mode? */ 1490 if (MEP_VLIW64) 1491 status = mep_examine_vliw64_insns (cd, pc, info); 1492 else 1493 status = mep_examine_vliw32_insns (cd, pc, info); 1494 /* Both the above branches set their own isa bitmasks. */ 1495 } 1496 else 1497 { 1498 if (ivc2) 1499 { 1500 cgen_bitset_clear (ivc2_core_isa); 1501 cgen_bitset_union (ivc2_core_isa, &MEP_CORE_ISA, ivc2_core_isa); 1502 cgen_bitset_union (ivc2_core_isa, &MEP_COP32_ISA, ivc2_core_isa); 1503 cd->isas = ivc2_core_isa; 1504 } 1505 else 1506 cd->isas = & MEP_CORE_ISA; 1507 status = default_print_insn (cd, pc, info); 1508 } 1509 } 1510 else /* sid or gdb */ 1511 { 1512#ifdef MEP_IVC2_SUPPORTED 1513 if (mep_ivc2_disassemble_p) 1514 { 1515 if (mep_ivc2_vliw_disassemble_p) 1516 { 1517 cd->isas = & MEP_CORE_ISA; 1518 status = mep_examine_ivc2_insns (cd, pc, info); 1519 return status; 1520 } 1521 else 1522 { 1523 if (ivc2) 1524 cd->isas = ivc2_core_isa; 1525 } 1526 } 1527#endif 1528 1529 status = default_print_insn (cd, pc, info); 1530 } 1531 1532 return status; 1533} 1534 1535 1536/* -- opc.c */ 1537#include "elf/mep.h" 1538 1539/* A mask for all ISAs executed by the core. */ 1540CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask = {0, 0}; 1541 1542void 1543init_mep_all_core_isas_mask (void) 1544{ 1545 if (mep_all_core_isas_mask.length != 0) 1546 return; 1547 cgen_bitset_init (& mep_all_core_isas_mask, ISA_MAX); 1548 cgen_bitset_set (& mep_all_core_isas_mask, ISA_MEP); 1549 /* begin-all-core-isas */ 1550 cgen_bitset_add (& mep_all_core_isas_mask, ISA_EXT_CORE1); 1551 /* end-all-core-isas */ 1552} 1553 1554CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask = {0, 0}; 1555 1556void 1557init_mep_all_cop_isas_mask (void) 1558{ 1559 if (mep_all_cop_isas_mask.length != 0) 1560 return; 1561 cgen_bitset_init (& mep_all_cop_isas_mask, ISA_MAX); 1562 /* begin-all-cop-isas */ 1563 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_16); 1564 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_32); 1565 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_48); 1566 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_64); 1567 /* end-all-cop-isas */ 1568} 1569 1570int 1571mep_insn_supported_by_isa (const CGEN_INSN *insn, CGEN_ATTR_VALUE_BITSET_TYPE *isa_mask) 1572{ 1573 CGEN_BITSET insn_isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA); 1574 return cgen_bitset_intersect_p (& insn_isas, isa_mask); 1575} 1576 1577#define OPTION_MASK \ 1578 ( (1 << CGEN_INSN_OPTIONAL_BIT_INSN) \ 1579 | (1 << CGEN_INSN_OPTIONAL_MUL_INSN) \ 1580 | (1 << CGEN_INSN_OPTIONAL_DIV_INSN) \ 1581 | (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN) \ 1582 | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN) \ 1583 | (1 << CGEN_INSN_OPTIONAL_ABS_INSN) \ 1584 | (1 << CGEN_INSN_OPTIONAL_AVE_INSN) \ 1585 | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN) \ 1586 | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN) \ 1587 | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) \ 1588 | (1 << CGEN_INSN_OPTIONAL_UCI_INSN) \ 1589 | (1 << CGEN_INSN_OPTIONAL_DSP_INSN) \ 1590 | (1 << CGEN_INSN_OPTIONAL_CP_INSN) \ 1591 | (1 << CGEN_INSN_OPTIONAL_CP64_INSN) ) 1592 1593 1594mep_config_map_struct mep_config_map[] = 1595{ 1596 /* config-map-start */ 1597 /* Default entry: first module, with all options enabled. */ 1598 { "", 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) }, 1599 { "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" }, 1600 0 1601 | (1 << CGEN_INSN_OPTIONAL_CP_INSN) 1602 | (1 << CGEN_INSN_OPTIONAL_CP64_INSN) 1603 | (1 << CGEN_INSN_OPTIONAL_MUL_INSN) 1604 | (1 << CGEN_INSN_OPTIONAL_DIV_INSN) 1605 | (1 << CGEN_INSN_OPTIONAL_BIT_INSN) 1606 | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN) 1607 | (1 << CGEN_INSN_OPTIONAL_ABS_INSN) 1608 | (1 << CGEN_INSN_OPTIONAL_AVE_INSN) 1609 | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN) 1610 | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN) 1611 | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) }, 1612 /* config-map-end */ 1613 { 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0 } 1614}; 1615 1616int mep_config_index = 0; 1617 1618static int 1619check_configured_mach (int machs) 1620{ 1621 /* All base insns are supported. */ 1622 int mach = 1 << MACH_BASE; 1623 switch (MEP_CPU & EF_MEP_CPU_MASK) 1624 { 1625 case EF_MEP_CPU_C2: 1626 case EF_MEP_CPU_C3: 1627 mach |= (1 << MACH_MEP); 1628 break; 1629 case EF_MEP_CPU_H1: 1630 mach |= (1 << MACH_H1); 1631 break; 1632 case EF_MEP_CPU_C5: 1633 mach |= (1 << MACH_MEP); 1634 mach |= (1 << MACH_C5); 1635 break; 1636 default: 1637 break; 1638 } 1639 return machs & mach; 1640} 1641 1642int 1643mep_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn) 1644{ 1645 int iconfig = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG); 1646 int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH); 1647 CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA); 1648 int ok1; 1649 int ok2; 1650 int ok3; 1651 1652 /* If the insn has an option bit set that we don't want, 1653 reject it. */ 1654 if (CGEN_INSN_ATTRS (insn)->bool_ & OPTION_MASK & ~MEP_OMASK) 1655 return 0; 1656 1657 /* If attributes are absent, assume no restriction. */ 1658 if (machs == 0) 1659 machs = ~0; 1660 1661 ok1 = ((machs & cd->machs) && cgen_bitset_intersect_p (& isas, cd->isas)); 1662 /* If the insn is config-specific, make sure it matches. */ 1663 ok2 = (iconfig == 0 || iconfig == MEP_CONFIG); 1664 /* Make sure the insn is supported by the configured mach */ 1665 ok3 = check_configured_mach (machs); 1666 1667 return (ok1 && ok2 && ok3); 1668} 1669 1670int 1671mep_cgen_insn_supported_asm (CGEN_CPU_DESC cd, const CGEN_INSN *insn) 1672{ 1673#ifdef MEP_IVC2_SUPPORTED 1674 /* If we're assembling VLIW packets, ignore the 12-bit BSR as we 1675 can't relax that. The 24-bit BSR is matched instead. */ 1676 if (insn->base->num == MEP_INSN_BSR12 1677 && cgen_bitset_contains (cd->isas, ISA_EXT_COP1_64)) 1678 return 0; 1679#endif 1680 1681 return mep_cgen_insn_supported (cd, insn); 1682} 1683