1 /* m32c opcode support. -*- C -*- 2 3 Copyright 2005, 2007, 2009, 2010 Free Software Foundation, Inc. 4 5 Contributed by Red Hat Inc; developed under contract from Renesas 6 7 This file is part of the GNU Binutils. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 22 MA 02110-1301, USA. */ 23 24 25 /* This file is an addendum to m32c.cpu. Heavy use of C code isn't 26 appropriate in .cpu files, so it resides here. This especially applies 27 to assembly/disassembly where parsing/printing can be quite involved. 28 Such things aren't really part of the specification of the cpu, per se, 29 so .cpu files provide the general framework and .opc files handle the 30 nitty-gritty details as necessary. 31 32 Each section is delimited with start and end markers. 33 34 <arch>-opc.h additions use: "-- opc.h" 35 <arch>-opc.c additions use: "-- opc.c" 36 <arch>-asm.c additions use: "-- asm.c" 37 <arch>-dis.c additions use: "-- dis.c" 38 <arch>-ibd.h additions use: "-- ibd.h". */ 39 40 /* -- opc.h */ 42 43 /* Needed for RTL's 'ext' and 'trunc' operators. */ 44 #include "cgen/basic-modes.h" 45 #include "cgen/basic-ops.h" 46 47 /* We can't use the default hash size because many bits are used by 48 operands. */ 49 #define CGEN_DIS_HASH_SIZE 1 50 #define CGEN_DIS_HASH(buf, value) 0 51 #define CGEN_VERBOSE_ASSEMBLER_ERRORS 52 #define CGEN_VALIDATE_INSN_SUPPORTED 53 54 extern int m32c_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *); 55 56 #define CGEN_ASM_HASH_SIZE 0xffff 57 #define CGEN_ASM_HASH(mnem) m32c_asm_hash ((mnem)) 58 59 /* -- */ 60 61 /* -- opc.c */ 63 static unsigned int 64 m32c_asm_hash (const char *mnem) 65 { 66 unsigned int h; 67 68 /* The length of the mnemonic for the Jcnd insns is 1. Hash jsri. */ 69 if (mnem[0] == 'j' && mnem[1] != 's') 70 return 'j'; 71 72 /* Don't hash scCND */ 73 if (mnem[0] == 's' && mnem[1] == 'c') 74 return 's'; 75 76 /* Don't hash bmCND */ 77 if (mnem[0] == 'b' && mnem[1] == 'm') 78 return 'b'; 79 80 for (h = 0; *mnem && *mnem != ' ' && *mnem != ':'; ++mnem) 81 h += *mnem; 82 return h % CGEN_ASM_HASH_SIZE; 83 } 84 85 /* -- asm.c */ 87 #include "safe-ctype.h" 88 89 #define MACH_M32C 5 /* Must match md_begin. */ 90 91 static int 92 m32c_cgen_isa_register (const char **strp) 93 { 94 int u; 95 const char *s = *strp; 96 static char * m32c_register_names [] = 97 { 98 "r0", "r1", "r2", "r3", "r0l", "r0h", "r1l", "r1h", 99 "a0", "a1", "r2r0", "r3r1", "sp", "fb", "dct0", "dct1", "flg", "svf", 100 "drc0", "drc1", "dmd0", "dmd1", "intb", "svp", "vct", "isp", "dma0", 101 "dma1", "dra0", "dra1", "dsa0", "dsa1", 0 102 }; 103 104 for (u = 0; m32c_register_names[u]; u++) 105 { 106 int len = strlen (m32c_register_names[u]); 107 108 if (memcmp (m32c_register_names[u], s, len) == 0 109 && (s[len] == 0 || ! ISALNUM (s[len]))) 110 return 1; 111 } 112 return 0; 113 } 114 115 #define PARSE_UNSIGNED \ 116 do \ 117 { \ 118 /* Don't successfully parse literals beginning with '['. */ \ 119 if (**strp == '[') \ 120 return "Invalid literal"; /* Anything -- will not be seen. */ \ 121 \ 122 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);\ 123 if (errmsg) \ 124 return errmsg; \ 125 } \ 126 while (0) 127 128 #define PARSE_SIGNED \ 129 do \ 130 { \ 131 /* Don't successfully parse literals beginning with '['. */ \ 132 if (**strp == '[') \ 133 return "Invalid literal"; /* Anything -- will not be seen. */ \ 134 \ 135 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); \ 136 if (errmsg) \ 137 return errmsg; \ 138 } \ 139 while (0) 140 141 static const char * 142 parse_unsigned6 (CGEN_CPU_DESC cd, const char **strp, 143 int opindex, unsigned long *valuep) 144 { 145 const char *errmsg = 0; 146 unsigned long value; 147 148 PARSE_UNSIGNED; 149 150 if (value > 0x3f) 151 return _("imm:6 immediate is out of range"); 152 153 *valuep = value; 154 return 0; 155 } 156 157 static const char * 158 parse_unsigned8 (CGEN_CPU_DESC cd, const char **strp, 159 int opindex, unsigned long *valuep) 160 { 161 const char *errmsg = 0; 162 unsigned long value = 0; 163 long have_zero = 0; 164 165 if (strncasecmp (*strp, "%dsp8(", 6) == 0) 166 { 167 enum cgen_parse_operand_result result_type; 168 bfd_vma val; 169 170 *strp += 6; 171 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_8, 172 & result_type, & val); 173 if (**strp != ')') 174 return _("missing `)'"); 175 (*strp) ++; 176 177 if (errmsg == NULL 178 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 179 return _("%dsp8() takes a symbolic address, not a number"); 180 181 value = val; 182 *valuep = value; 183 return errmsg; 184 } 185 186 if (strncmp (*strp, "0x0", 3) == 0 187 || (**strp == '0' && *(*strp + 1) != 'x')) 188 have_zero = 1; 189 190 PARSE_UNSIGNED; 191 192 if (value > 0xff) 193 return _("dsp:8 immediate is out of range"); 194 195 /* If this field may require a relocation then use larger dsp16. */ 196 if (! have_zero && value == 0) 197 return _("dsp:8 immediate is out of range"); 198 199 *valuep = value; 200 return 0; 201 } 202 203 static const char * 204 parse_signed4 (CGEN_CPU_DESC cd, const char **strp, 205 int opindex, signed long *valuep) 206 { 207 const char *errmsg = 0; 208 signed long value; 209 long have_zero = 0; 210 211 if (strncmp (*strp, "0x0", 3) == 0 212 || (**strp == '0' && *(*strp + 1) != 'x')) 213 have_zero = 1; 214 215 PARSE_SIGNED; 216 217 if (value < -8 || value > 7) 218 return _("Immediate is out of range -8 to 7"); 219 220 /* If this field may require a relocation then use larger dsp16. */ 221 if (! have_zero && value == 0) 222 return _("Immediate is out of range -8 to 7"); 223 224 *valuep = value; 225 return 0; 226 } 227 228 static const char * 229 parse_signed4n (CGEN_CPU_DESC cd, const char **strp, 230 int opindex, signed long *valuep) 231 { 232 const char *errmsg = 0; 233 signed long value; 234 long have_zero = 0; 235 236 if (strncmp (*strp, "0x0", 3) == 0 237 || (**strp == '0' && *(*strp + 1) != 'x')) 238 have_zero = 1; 239 240 PARSE_SIGNED; 241 242 if (value < -7 || value > 8) 243 return _("Immediate is out of range -7 to 8"); 244 245 /* If this field may require a relocation then use larger dsp16. */ 246 if (! have_zero && value == 0) 247 return _("Immediate is out of range -7 to 8"); 248 249 *valuep = -value; 250 return 0; 251 } 252 253 static const char * 254 parse_signed8 (CGEN_CPU_DESC cd, const char **strp, 255 int opindex, signed long *valuep) 256 { 257 const char *errmsg = 0; 258 signed long value = 0; 259 260 if (strncasecmp (*strp, "%hi8(", 5) == 0) 261 { 262 enum cgen_parse_operand_result result_type; 263 bfd_vma val; 264 265 *strp += 5; 266 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32C_HI8, 267 & result_type, & val); 268 if (**strp != ')') 269 return _("missing `)'"); 270 (*strp) ++; 271 272 if (errmsg == NULL 273 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 274 val >>= 16; 275 276 value = val; 277 *valuep = value; 278 return errmsg; 279 } 280 281 PARSE_SIGNED; 282 283 if (value <= 255 && value > 127) 284 value -= 0x100; 285 286 if (value < -128 || value > 127) 287 return _("dsp:8 immediate is out of range"); 288 289 *valuep = value; 290 return 0; 291 } 292 293 static const char * 294 parse_unsigned16 (CGEN_CPU_DESC cd, const char **strp, 295 int opindex, unsigned long *valuep) 296 { 297 const char *errmsg = 0; 298 unsigned long value = 0; 299 long have_zero = 0; 300 301 if (strncasecmp (*strp, "%dsp16(", 7) == 0) 302 { 303 enum cgen_parse_operand_result result_type; 304 bfd_vma val; 305 306 *strp += 7; 307 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_16, 308 & result_type, & val); 309 if (**strp != ')') 310 return _("missing `)'"); 311 (*strp) ++; 312 313 if (errmsg == NULL 314 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 315 return _("%dsp16() takes a symbolic address, not a number"); 316 317 value = val; 318 *valuep = value; 319 return errmsg; 320 } 321 322 /* Don't successfully parse literals beginning with '['. */ 323 if (**strp == '[') 324 return "Invalid literal"; /* Anything -- will not be seen. */ 325 326 /* Don't successfully parse register names. */ 327 if (m32c_cgen_isa_register (strp)) 328 return "Invalid literal"; /* Anything -- will not be seen. */ 329 330 if (strncmp (*strp, "0x0", 3) == 0 331 || (**strp == '0' && *(*strp + 1) != 'x')) 332 have_zero = 1; 333 334 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value); 335 if (errmsg) 336 return errmsg; 337 338 if (value > 0xffff) 339 return _("dsp:16 immediate is out of range"); 340 341 /* If this field may require a relocation then use larger dsp24. */ 342 if (cd->machs == MACH_M32C && ! have_zero && value == 0 343 && (strncmp (*strp, "[a", 2) == 0 344 || **strp == ',' 345 || **strp == 0)) 346 return _("dsp:16 immediate is out of range"); 347 348 *valuep = value; 349 return 0; 350 } 351 352 static const char * 353 parse_signed16 (CGEN_CPU_DESC cd, const char **strp, 354 int opindex, signed long *valuep) 355 { 356 const char *errmsg = 0; 357 signed long value = 0; 358 359 if (strncasecmp (*strp, "%lo16(", 6) == 0) 360 { 361 enum cgen_parse_operand_result result_type; 362 bfd_vma val; 363 364 *strp += 6; 365 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16, 366 & result_type, & val); 367 if (**strp != ')') 368 return _("missing `)'"); 369 (*strp) ++; 370 371 if (errmsg == NULL 372 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 373 val &= 0xffff; 374 375 value = val; 376 *valuep = value; 377 return errmsg; 378 } 379 380 if (strncasecmp (*strp, "%hi16(", 6) == 0) 381 { 382 enum cgen_parse_operand_result result_type; 383 bfd_vma val; 384 385 *strp += 6; 386 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16, 387 & result_type, & val); 388 if (**strp != ')') 389 return _("missing `)'"); 390 (*strp) ++; 391 392 if (errmsg == NULL 393 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 394 val >>= 16; 395 396 value = val; 397 *valuep = value; 398 return errmsg; 399 } 400 401 PARSE_SIGNED; 402 403 if (value <= 65535 && value > 32767) 404 value -= 0x10000; 405 406 if (value < -32768 || value > 32767) 407 return _("dsp:16 immediate is out of range"); 408 409 *valuep = value; 410 return 0; 411 } 412 413 static const char * 414 parse_unsigned20 (CGEN_CPU_DESC cd, const char **strp, 415 int opindex, unsigned long *valuep) 416 { 417 const char *errmsg = 0; 418 unsigned long value; 419 420 /* Don't successfully parse literals beginning with '['. */ 421 if (**strp == '[') 422 return "Invalid literal"; /* Anything -- will not be seen. */ 423 424 /* Don't successfully parse register names. */ 425 if (m32c_cgen_isa_register (strp)) 426 return "Invalid literal"; /* Anything -- will not be seen. */ 427 428 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value); 429 if (errmsg) 430 return errmsg; 431 432 if (value > 0xfffff) 433 return _("dsp:20 immediate is out of range"); 434 435 *valuep = value; 436 return 0; 437 } 438 439 static const char * 440 parse_unsigned24 (CGEN_CPU_DESC cd, const char **strp, 441 int opindex, unsigned long *valuep) 442 { 443 const char *errmsg = 0; 444 unsigned long value; 445 446 /* Don't successfully parse literals beginning with '['. */ 447 if (**strp == '[') 448 return "Invalid literal"; /* Anything -- will not be seen. */ 449 450 /* Don't successfully parse register names. */ 451 if (m32c_cgen_isa_register (strp)) 452 return "Invalid literal"; /* Anything -- will not be seen. */ 453 454 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value); 455 if (errmsg) 456 return errmsg; 457 458 if (value > 0xffffff) 459 return _("dsp:24 immediate is out of range"); 460 461 *valuep = value; 462 return 0; 463 } 464 465 /* This should only be used for #imm->reg. */ 466 static const char * 467 parse_signed24 (CGEN_CPU_DESC cd, const char **strp, 468 int opindex, signed long *valuep) 469 { 470 const char *errmsg = 0; 471 signed long value; 472 473 PARSE_SIGNED; 474 475 if (value <= 0xffffff && value > 0x7fffff) 476 value -= 0x1000000; 477 478 if (value > 0xffffff) 479 return _("dsp:24 immediate is out of range"); 480 481 *valuep = value; 482 return 0; 483 } 484 485 static const char * 486 parse_signed32 (CGEN_CPU_DESC cd, const char **strp, 487 int opindex, signed long *valuep) 488 { 489 const char *errmsg = 0; 490 signed long value; 491 492 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); 493 if (errmsg) 494 return errmsg; 495 496 *valuep = value; 497 return 0; 498 } 499 500 static const char * 501 parse_imm1_S (CGEN_CPU_DESC cd, const char **strp, 502 int opindex, signed long *valuep) 503 { 504 const char *errmsg = 0; 505 signed long value; 506 507 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); 508 if (errmsg) 509 return errmsg; 510 511 if (value < 1 || value > 2) 512 return _("immediate is out of range 1-2"); 513 514 *valuep = value; 515 return 0; 516 } 517 518 static const char * 519 parse_imm3_S (CGEN_CPU_DESC cd, const char **strp, 520 int opindex, signed long *valuep) 521 { 522 const char *errmsg = 0; 523 signed long value; 524 525 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); 526 if (errmsg) 527 return errmsg; 528 529 if (value < 1 || value > 8) 530 return _("immediate is out of range 1-8"); 531 532 *valuep = value; 533 return 0; 534 } 535 536 static const char * 537 parse_bit3_S (CGEN_CPU_DESC cd, const char **strp, 538 int opindex, signed long *valuep) 539 { 540 const char *errmsg = 0; 541 signed long value; 542 543 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); 544 if (errmsg) 545 return errmsg; 546 547 if (value < 0 || value > 7) 548 return _("immediate is out of range 0-7"); 549 550 *valuep = value; 551 return 0; 552 } 553 554 static const char * 555 parse_lab_5_3 (CGEN_CPU_DESC cd, 556 const char **strp, 557 int opindex ATTRIBUTE_UNUSED, 558 int opinfo, 559 enum cgen_parse_operand_result *type_addr, 560 bfd_vma *valuep) 561 { 562 const char *errmsg = 0; 563 bfd_vma value; 564 enum cgen_parse_operand_result op_res; 565 566 errmsg = cgen_parse_address (cd, strp, M32C_OPERAND_LAB_5_3, 567 opinfo, & op_res, & value); 568 569 if (type_addr) 570 *type_addr = op_res; 571 572 if (op_res == CGEN_PARSE_OPERAND_RESULT_QUEUED) 573 { 574 /* This is a hack; the field cannot handle near-zero signed 575 offsets that CGEN wants to put in to indicate an "empty" 576 operand at first. */ 577 *valuep = 2; 578 return 0; 579 } 580 if (errmsg) 581 return errmsg; 582 583 if (value < 2 || value > 9) 584 return _("immediate is out of range 2-9"); 585 586 *valuep = value; 587 return 0; 588 } 589 590 static const char * 591 parse_Bitno16R (CGEN_CPU_DESC cd, const char **strp, 592 int opindex, unsigned long *valuep) 593 { 594 const char *errmsg = 0; 595 unsigned long value; 596 597 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value); 598 if (errmsg) 599 return errmsg; 600 601 if (value > 15) 602 return _("Bit number for indexing general register is out of range 0-15"); 603 604 *valuep = value; 605 return 0; 606 } 607 608 static const char * 609 parse_unsigned_bitbase (CGEN_CPU_DESC cd, const char **strp, 610 int opindex, unsigned long *valuep, 611 unsigned bits, int allow_syms) 612 { 613 const char *errmsg = 0; 614 unsigned long bit; 615 unsigned long base; 616 const char *newp = *strp; 617 unsigned long long bitbase; 618 long have_zero = 0; 619 620 errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit); 621 if (errmsg) 622 return errmsg; 623 624 if (*newp != ',') 625 return "Missing base for bit,base:8"; 626 627 ++newp; 628 629 if (strncmp (newp, "0x0", 3) == 0 630 || (newp[0] == '0' && newp[1] != 'x')) 631 have_zero = 1; 632 633 errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & base); 634 if (errmsg) 635 return errmsg; 636 637 bitbase = (unsigned long long) bit + ((unsigned long long) base * 8); 638 639 if (bitbase >= (1ull << bits)) 640 return _("bit,base is out of range"); 641 642 /* If this field may require a relocation then use larger displacement. */ 643 if (! have_zero && base == 0) 644 { 645 switch (allow_syms) { 646 case 0: 647 return _("bit,base out of range for symbol"); 648 case 1: 649 break; 650 case 2: 651 if (strncmp (newp, "[sb]", 4) != 0) 652 return _("bit,base out of range for symbol"); 653 break; 654 } 655 } 656 657 *valuep = bitbase; 658 *strp = newp; 659 return 0; 660 } 661 662 static const char * 663 parse_signed_bitbase (CGEN_CPU_DESC cd, const char **strp, 664 int opindex, signed long *valuep, 665 unsigned bits, int allow_syms) 666 { 667 const char *errmsg = 0; 668 unsigned long bit; 669 signed long base; 670 const char *newp = *strp; 671 long long bitbase; 672 long long limit; 673 long have_zero = 0; 674 675 errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit); 676 if (errmsg) 677 return errmsg; 678 679 if (*newp != ',') 680 return "Missing base for bit,base:8"; 681 682 ++newp; 683 684 if (strncmp (newp, "0x0", 3) == 0 685 || (newp[0] == '0' && newp[1] != 'x')) 686 have_zero = 1; 687 688 errmsg = cgen_parse_signed_integer (cd, & newp, opindex, & base); 689 if (errmsg) 690 return errmsg; 691 692 bitbase = (long long)bit + ((long long)base * 8); 693 694 limit = 1ll << (bits - 1); 695 if (bitbase < -limit || bitbase >= limit) 696 return _("bit,base is out of range"); 697 698 /* If this field may require a relocation then use larger displacement. */ 699 if (! have_zero && base == 0 && ! allow_syms) 700 return _("bit,base out of range for symbol"); 701 702 *valuep = bitbase; 703 *strp = newp; 704 return 0; 705 } 706 707 static const char * 708 parse_unsigned_bitbase8 (CGEN_CPU_DESC cd, const char **strp, 709 int opindex, unsigned long *valuep) 710 { 711 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 8, 0); 712 } 713 714 static const char * 715 parse_unsigned_bitbase11 (CGEN_CPU_DESC cd, const char **strp, 716 int opindex, unsigned long *valuep) 717 { 718 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 11, 0); 719 } 720 721 static const char * 722 parse_unsigned_bitbase16 (CGEN_CPU_DESC cd, const char **strp, 723 int opindex, unsigned long *valuep) 724 { 725 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 16, 1); 726 } 727 728 static const char * 729 parse_unsigned_bitbase19 (CGEN_CPU_DESC cd, const char **strp, 730 int opindex, unsigned long *valuep) 731 { 732 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 19, 2); 733 } 734 735 static const char * 736 parse_unsigned_bitbase27 (CGEN_CPU_DESC cd, const char **strp, 737 int opindex, unsigned long *valuep) 738 { 739 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 27, 1); 740 } 741 742 static const char * 743 parse_signed_bitbase8 (CGEN_CPU_DESC cd, const char **strp, 744 int opindex, signed long *valuep) 745 { 746 return parse_signed_bitbase (cd, strp, opindex, valuep, 8, 1); 747 } 748 749 static const char * 750 parse_signed_bitbase11 (CGEN_CPU_DESC cd, const char **strp, 751 int opindex, signed long *valuep) 752 { 753 return parse_signed_bitbase (cd, strp, opindex, valuep, 11, 0); 754 } 755 756 static const char * 757 parse_signed_bitbase19 (CGEN_CPU_DESC cd, const char **strp, 758 int opindex, signed long *valuep) 759 { 760 return parse_signed_bitbase (cd, strp, opindex, valuep, 19, 1); 761 } 762 763 /* Parse the suffix as :<char> or as nothing followed by a whitespace. */ 764 765 static const char * 766 parse_suffix (const char **strp, char suffix) 767 { 768 const char *newp = *strp; 769 770 if (**strp == ':' && TOLOWER (*(*strp + 1)) == suffix) 771 newp = *strp + 2; 772 773 if (ISSPACE (*newp)) 774 { 775 *strp = newp; 776 return 0; 777 } 778 779 return "Invalid suffix"; /* Anything -- will not be seen. */ 780 } 781 782 static const char * 783 parse_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp, 784 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED) 785 { 786 return parse_suffix (strp, 's'); 787 } 788 789 static const char * 790 parse_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp, 791 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED) 792 { 793 return parse_suffix (strp, 'g'); 794 } 795 796 static const char * 797 parse_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp, 798 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED) 799 { 800 return parse_suffix (strp, 'q'); 801 } 802 803 static const char * 804 parse_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp, 805 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED) 806 { 807 return parse_suffix (strp, 'z'); 808 } 809 810 /* Parse an empty suffix. Fail if the next char is ':'. */ 811 812 static const char * 813 parse_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp, 814 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED) 815 { 816 if (**strp == ':') 817 return "Unexpected suffix"; 818 return 0; 819 } 820 821 static const char * 822 parse_r0l_r0h (CGEN_CPU_DESC cd, const char **strp, 823 int opindex ATTRIBUTE_UNUSED, signed long *valuep) 824 { 825 const char *errmsg; 826 signed long value; 827 signed long junk; 828 const char *newp = *strp; 829 830 /* Parse r0[hl]. */ 831 errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l_r0h, & value); 832 if (errmsg) 833 return errmsg; 834 835 if (*newp != ',') 836 return _("not a valid r0l/r0h pair"); 837 ++newp; 838 839 /* Parse the second register in the pair. */ 840 if (value == 0) /* r0l */ 841 errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0h, & junk); 842 else 843 errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l, & junk); 844 if (errmsg) 845 return errmsg; 846 847 *strp = newp; 848 *valuep = ! value; 849 return 0; 850 } 851 852 /* Accept .b or .w in any case. */ 853 854 static const char * 855 parse_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp, 856 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED) 857 { 858 if (**strp == '.' 859 && (*(*strp + 1) == 'b' || *(*strp + 1) == 'B' 860 || *(*strp + 1) == 'w' || *(*strp + 1) == 'W')) 861 { 862 *strp += 2; 863 return NULL; 864 } 865 866 return _("Invalid size specifier"); 867 } 868 869 /* Special check to ensure that instruction exists for given machine. */ 870 871 int 872 m32c_cgen_insn_supported (CGEN_CPU_DESC cd, 873 const CGEN_INSN *insn) 874 { 875 int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH); 876 CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA); 877 878 /* If attributes are absent, assume no restriction. */ 879 if (machs == 0) 880 machs = ~0; 881 882 return ((machs & cd->machs) 883 && cgen_bitset_intersect_p (& isas, cd->isas)); 884 } 885 886 /* Parse a set of registers, R0,R1,A0,A1,SB,FB. */ 887 888 static const char * 889 parse_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 890 const char **strp, 891 int opindex ATTRIBUTE_UNUSED, 892 unsigned long *valuep, 893 int push) 894 { 895 const char *errmsg = 0; 896 int regno = 0; 897 898 *valuep = 0; 899 while (**strp && **strp != ')') 900 { 901 if (**strp == 'r' || **strp == 'R') 902 { 903 ++*strp; 904 regno = **strp - '0'; 905 if (regno > 4) 906 errmsg = _("Register number is not valid"); 907 } 908 else if (**strp == 'a' || **strp == 'A') 909 { 910 ++*strp; 911 regno = **strp - '0'; 912 if (regno > 2) 913 errmsg = _("Register number is not valid"); 914 regno = **strp - '0' + 4; 915 } 916 917 else if (strncasecmp (*strp, "sb", 2) == 0 || strncasecmp (*strp, "SB", 2) == 0) 918 { 919 regno = 6; 920 ++*strp; 921 } 922 923 else if (strncasecmp (*strp, "fb", 2) == 0 || strncasecmp (*strp, "FB", 2) == 0) 924 { 925 regno = 7; 926 ++*strp; 927 } 928 929 if (push) /* Mask is reversed for push. */ 930 *valuep |= 0x80 >> regno; 931 else 932 *valuep |= 1 << regno; 933 934 ++*strp; 935 if (**strp == ',') 936 { 937 if (*(*strp + 1) == ')') 938 break; 939 ++*strp; 940 } 941 } 942 943 if (!*strp) 944 errmsg = _("Register list is not valid"); 945 946 return errmsg; 947 } 948 949 #define POP 0 950 #define PUSH 1 951 952 static const char * 953 parse_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 954 const char **strp, 955 int opindex ATTRIBUTE_UNUSED, 956 unsigned long *valuep) 957 { 958 return parse_regset (cd, strp, opindex, valuep, POP); 959 } 960 961 static const char * 962 parse_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 963 const char **strp, 964 int opindex ATTRIBUTE_UNUSED, 965 unsigned long *valuep) 966 { 967 return parse_regset (cd, strp, opindex, valuep, PUSH); 968 } 969 970 /* -- dis.c */ 971 972 #include "elf/m32c.h" 973 #include "elf-bfd.h" 974 975 /* Always print the short insn format suffix as ':<char>'. */ 976 977 static void 978 print_suffix (void * dis_info, char suffix) 979 { 980 disassemble_info *info = dis_info; 981 982 (*info->fprintf_func) (info->stream, ":%c", suffix); 983 } 984 985 static void 986 print_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 987 void * dis_info, 988 long value ATTRIBUTE_UNUSED, 989 unsigned int attrs ATTRIBUTE_UNUSED, 990 bfd_vma pc ATTRIBUTE_UNUSED, 991 int length ATTRIBUTE_UNUSED) 992 { 993 print_suffix (dis_info, 's'); 994 } 995 996 997 static void 998 print_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 999 void * dis_info, 1000 long value ATTRIBUTE_UNUSED, 1001 unsigned int attrs ATTRIBUTE_UNUSED, 1002 bfd_vma pc ATTRIBUTE_UNUSED, 1003 int length ATTRIBUTE_UNUSED) 1004 { 1005 print_suffix (dis_info, 'g'); 1006 } 1007 1008 static void 1009 print_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 1010 void * dis_info, 1011 long value ATTRIBUTE_UNUSED, 1012 unsigned int attrs ATTRIBUTE_UNUSED, 1013 bfd_vma pc ATTRIBUTE_UNUSED, 1014 int length ATTRIBUTE_UNUSED) 1015 { 1016 print_suffix (dis_info, 'q'); 1017 } 1018 1019 static void 1020 print_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 1021 void * dis_info, 1022 long value ATTRIBUTE_UNUSED, 1023 unsigned int attrs ATTRIBUTE_UNUSED, 1024 bfd_vma pc ATTRIBUTE_UNUSED, 1025 int length ATTRIBUTE_UNUSED) 1026 { 1027 print_suffix (dis_info, 'z'); 1028 } 1029 1030 /* Print the empty suffix. */ 1031 1032 static void 1033 print_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 1034 void * dis_info ATTRIBUTE_UNUSED, 1035 long value ATTRIBUTE_UNUSED, 1036 unsigned int attrs ATTRIBUTE_UNUSED, 1037 bfd_vma pc ATTRIBUTE_UNUSED, 1038 int length ATTRIBUTE_UNUSED) 1039 { 1040 return; 1041 } 1042 1043 static void 1044 print_r0l_r0h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 1045 void * dis_info, 1046 long value, 1047 unsigned int attrs ATTRIBUTE_UNUSED, 1048 bfd_vma pc ATTRIBUTE_UNUSED, 1049 int length ATTRIBUTE_UNUSED) 1050 { 1051 disassemble_info *info = dis_info; 1052 1053 if (value == 0) 1054 (*info->fprintf_func) (info->stream, "r0h,r0l"); 1055 else 1056 (*info->fprintf_func) (info->stream, "r0l,r0h"); 1057 } 1058 1059 static void 1060 print_unsigned_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 1061 void * dis_info, 1062 unsigned long value, 1063 unsigned int attrs ATTRIBUTE_UNUSED, 1064 bfd_vma pc ATTRIBUTE_UNUSED, 1065 int length ATTRIBUTE_UNUSED) 1066 { 1067 disassemble_info *info = dis_info; 1068 1069 (*info->fprintf_func) (info->stream, "%ld,0x%lx", value & 0x7, value >> 3); 1070 } 1071 1072 static void 1073 print_signed_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 1074 void * dis_info, 1075 signed long value, 1076 unsigned int attrs ATTRIBUTE_UNUSED, 1077 bfd_vma pc ATTRIBUTE_UNUSED, 1078 int length ATTRIBUTE_UNUSED) 1079 { 1080 disassemble_info *info = dis_info; 1081 1082 (*info->fprintf_func) (info->stream, "%ld,%ld", value & 0x7, value >> 3); 1083 } 1084 1085 static void 1086 print_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 1087 void * dis_info, 1088 long value ATTRIBUTE_UNUSED, 1089 unsigned int attrs ATTRIBUTE_UNUSED, 1090 bfd_vma pc ATTRIBUTE_UNUSED, 1091 int length ATTRIBUTE_UNUSED) 1092 { 1093 /* Always print the size as '.w'. */ 1094 disassemble_info *info = dis_info; 1095 1096 (*info->fprintf_func) (info->stream, ".w"); 1097 } 1098 1099 #define POP 0 1100 #define PUSH 1 1101 1102 static void print_pop_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int); 1103 static void print_push_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int); 1104 1105 /* Print a set of registers, R0,R1,A0,A1,SB,FB. */ 1106 1107 static void 1108 print_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 1109 void * dis_info, 1110 long value, 1111 unsigned int attrs ATTRIBUTE_UNUSED, 1112 bfd_vma pc ATTRIBUTE_UNUSED, 1113 int length ATTRIBUTE_UNUSED, 1114 int push) 1115 { 1116 static char * m16c_register_names [] = 1117 { 1118 "r0", "r1", "r2", "r3", "a0", "a1", "sb", "fb" 1119 }; 1120 disassemble_info *info = dis_info; 1121 int mask; 1122 int reg_index = 0; 1123 char* comma = ""; 1124 1125 if (push) 1126 mask = 0x80; 1127 else 1128 mask = 1; 1129 1130 if (value & mask) 1131 { 1132 (*info->fprintf_func) (info->stream, "%s", m16c_register_names [0]); 1133 comma = ","; 1134 } 1135 1136 for (reg_index = 1; reg_index <= 7; ++reg_index) 1137 { 1138 if (push) 1139 mask >>= 1; 1140 else 1141 mask <<= 1; 1142 1143 if (value & mask) 1144 { 1145 (*info->fprintf_func) (info->stream, "%s%s", comma, 1146 m16c_register_names [reg_index]); 1147 comma = ","; 1148 } 1149 } 1150 } 1151 1152 static void 1153 print_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 1154 void * dis_info, 1155 long value, 1156 unsigned int attrs ATTRIBUTE_UNUSED, 1157 bfd_vma pc ATTRIBUTE_UNUSED, 1158 int length ATTRIBUTE_UNUSED) 1159 { 1160 print_regset (cd, dis_info, value, attrs, pc, length, POP); 1161 } 1162 1163 static void 1164 print_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 1165 void * dis_info, 1166 long value, 1167 unsigned int attrs ATTRIBUTE_UNUSED, 1168 bfd_vma pc ATTRIBUTE_UNUSED, 1169 int length ATTRIBUTE_UNUSED) 1170 { 1171 print_regset (cd, dis_info, value, attrs, pc, length, PUSH); 1172 } 1173 1174 static void 1175 print_signed4n (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 1176 void * dis_info, 1177 signed long value, 1178 unsigned int attrs ATTRIBUTE_UNUSED, 1179 bfd_vma pc ATTRIBUTE_UNUSED, 1180 int length ATTRIBUTE_UNUSED) 1181 { 1182 disassemble_info *info = dis_info; 1183 1184 (*info->fprintf_func) (info->stream, "%ld", -value); 1185 } 1186