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