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