1 /* tc-s12z.c -- Assembler code for the Freescale S12Z 2 Copyright (C) 2018-2024 Free Software Foundation, Inc. 3 4 This file is part of GAS, the GNU Assembler. 5 6 GAS is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 GAS is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GAS; see the file COPYING. If not, write to 18 the Free Software Foundation, 51 Franklin Street - Fifth Floor, 19 Boston, MA 02110-1301, USA. */ 20 21 #include "as.h" 22 #include "safe-ctype.h" 23 #include "subsegs.h" 24 #include "dwarf2dbg.h" 25 #include "opcode/s12z.h" 26 #include <limits.h> 27 28 const char comment_chars[] = ";"; 29 30 const char line_comment_chars[] = "#*"; 31 const char line_separator_chars[] = ""; 32 33 static char * register_prefix = NULL; 34 35 const char EXP_CHARS[] = "eE"; 36 const char FLT_CHARS[] = "dD"; 37 38 static char *fail_line_pointer; 39 40 /* A wrapper around the standard library's strtol. 41 It converts STR into an integral value. 42 This wrapper deals with literal_prefix_dollar_hex. */ 43 static long 44 s12z_strtol (const char *str, char ** endptr) 45 { 46 int base = 0; 47 bool negative = false; 48 49 long result = 0; 50 51 char *start = (char *) str; 52 53 /* In the case where literal_prefix_dollar_hex is TRUE the sign has 54 to be handled explicitly. Otherwise the string will not be 55 recognised as an integer. */ 56 if (str[0] == '-') 57 { 58 negative = true; 59 ++str; 60 } 61 else if (str[0] == '+') 62 { 63 ++str; 64 } 65 66 if (literal_prefix_dollar_hex && (str[0] == '$')) 67 { 68 base = 16; 69 str++; 70 } 71 72 result = strtol (str, endptr, base); 73 if (*endptr == str) 74 { 75 *endptr = start; 76 } 77 if (negative) 78 result = -result; 79 80 return result; 81 } 82 83 84 85 /* Options and initialization. */ 86 87 const char *md_shortopts = ""; 88 89 struct option md_longopts[] = 90 { 91 #define OPTION_REG_PREFIX (OPTION_MD_BASE) 92 {"mreg-prefix", required_argument, NULL, OPTION_REG_PREFIX}, 93 #define OPTION_DOLLAR_HEX (OPTION_MD_BASE + 1) 94 {"mdollar-hex", no_argument, NULL, OPTION_DOLLAR_HEX}, 95 {NULL, no_argument, NULL, 0} 96 }; 97 98 size_t md_longopts_size = sizeof (md_longopts); 99 100 101 relax_typeS md_relax_table[] = 102 { 103 104 }; 105 106 /* This table describes all the machine specific pseudo-ops the assembler 107 has to support. The fields are: 108 pseudo-op name without dot 109 function to call to execute this pseudo-op 110 Integer arg to pass to the function. */ 111 const pseudo_typeS md_pseudo_table[] = 112 { 113 {0, 0, 0} 114 }; 115 116 117 /* Get the target cpu for the assembler. */ 118 const char * 119 s12z_arch_format (void) 120 { 121 return "elf32-s12z"; 122 } 123 124 enum bfd_architecture 125 s12z_arch (void) 126 { 127 return bfd_arch_s12z; 128 } 129 130 int 131 s12z_mach (void) 132 { 133 return 0; 134 } 135 136 /* Listing header selected according to cpu. */ 137 const char * 138 s12z_listing_header (void) 139 { 140 return "S12Z GAS "; 141 } 142 143 void 144 md_show_usage (FILE *stream) 145 { 146 fputs (_("\ns12z options:\n"), stream); 147 fputs (_(" -mreg-prefix=PREFIX set a prefix used to indicate register names (default none)\n"), stream); 148 fputs (_(" -mdollar-hex the prefix '$' instead of '0x' is used to indicate literal hexadecimal constants\n"), stream); 149 } 150 151 void 152 s12z_print_statistics (FILE *file ATTRIBUTE_UNUSED) 153 { 154 } 155 156 int 157 md_parse_option (int c, const char *arg) 158 { 159 switch (c) 160 { 161 case OPTION_REG_PREFIX: 162 register_prefix = xstrdup (arg); 163 break; 164 case OPTION_DOLLAR_HEX: 165 literal_prefix_dollar_hex = true; 166 break; 167 default: 168 return 0; 169 } 170 return 1; 171 } 172 173 symbolS * 174 md_undefined_symbol (char *name ATTRIBUTE_UNUSED) 175 { 176 return 0; 177 } 178 179 const char * 180 md_atof (int type, char *litP, int *sizeP) 181 { 182 return ieee_md_atof (type, litP, sizeP, true); 183 } 184 185 valueT 186 md_section_align (asection *seg, valueT addr) 187 { 188 int align = bfd_section_alignment (seg); 189 return ((addr + (1 << align) - 1) & -(1 << align)); 190 } 191 192 void 193 md_begin (void) 194 { 195 } 196 197 void 198 s12z_init_after_args (void) 199 { 200 if (flag_traditional_format) 201 literal_prefix_dollar_hex = true; 202 } 203 204 /* Builtin help. */ 205 206 207 static char * 208 skip_whites (char *p) 209 { 210 while (*p == ' ' || *p == '\t') 211 p++; 212 213 return p; 214 } 215 216 217 218 /* Start a new insn that contains at least 'size' bytes. Record the 219 line information of that insn in the dwarf2 debug sections. */ 220 static char * 221 s12z_new_insn (int size) 222 { 223 char *f = frag_more (size); 224 225 dwarf2_emit_insn (size); 226 227 return f; 228 } 229 230 231 232 static bool lex_reg_name (uint16_t which, int *reg); 233 234 static bool 235 lex_constant (long *v) 236 { 237 char *end = NULL; 238 char *p = input_line_pointer; 239 240 /* A constant may not have the same value as a register 241 eg: "d6" */ 242 int dummy; 243 if (lex_reg_name (~0, &dummy)) 244 { 245 input_line_pointer = p; 246 return false; 247 } 248 249 errno = 0; 250 *v = s12z_strtol (p, &end); 251 if (errno == 0 && end != p) 252 { 253 input_line_pointer = end; 254 return true; 255 } 256 257 return false; 258 } 259 260 static bool 261 lex_match (char x) 262 { 263 char *p = input_line_pointer; 264 if (*p != x) 265 return false; 266 267 input_line_pointer++; 268 return true; 269 } 270 271 272 static bool 273 lex_expression (expressionS *exp) 274 { 275 char *ilp = input_line_pointer; 276 int dummy; 277 exp->X_op = O_absent; 278 279 if (lex_match ('#')) 280 goto fail; 281 282 if (lex_reg_name (~0, &dummy)) 283 goto fail; 284 285 expression (exp); 286 if (exp->X_op != O_absent) 287 return true; 288 289 fail: 290 fail_line_pointer = input_line_pointer; 291 input_line_pointer = ilp; 292 return false; 293 } 294 295 /* Immediate operand. 296 If EXP_O is non-null, then a symbolic expression is permitted, 297 in which case, EXP_O will be populated with the parsed expression. 298 */ 299 static bool 300 lex_imm (long *v, expressionS *exp_o) 301 { 302 char *ilp = input_line_pointer; 303 304 if (*input_line_pointer != '#') 305 goto fail; 306 307 input_line_pointer++; 308 expressionS exp; 309 if (!lex_expression (&exp)) 310 goto fail; 311 312 if (exp.X_op != O_constant) 313 { 314 if (!exp_o) 315 as_bad (_("A non-constant expression is not permitted here")); 316 else 317 *exp_o = exp; 318 } 319 320 *v = exp.X_add_number; 321 return true; 322 323 fail: 324 fail_line_pointer = input_line_pointer; 325 input_line_pointer = ilp; 326 return false; 327 } 328 329 /* Short mmediate operand */ 330 static bool 331 lex_imm_e4 (long *val) 332 { 333 char *ilp = input_line_pointer; 334 if ((lex_imm (val, NULL))) 335 { 336 if ((*val == -1) || (*val > 0 && *val <= 15)) 337 { 338 return true; 339 } 340 } 341 fail_line_pointer = input_line_pointer; 342 input_line_pointer = ilp; 343 return false; 344 } 345 346 static bool 347 lex_match_string (const char *s) 348 { 349 char *p = input_line_pointer; 350 while (p != 0 && *p != '\t' && *p != ' ' && *p != '\0') 351 { 352 p++; 353 } 354 355 size_t len = p - input_line_pointer; 356 if (len != strlen (s)) 357 return false; 358 359 if (0 == strncasecmp (s, input_line_pointer, len)) 360 { 361 input_line_pointer = p; 362 return true; 363 } 364 365 return false; 366 } 367 368 /* Parse a register name. 369 WHICH is a ORwise combination of the registers which are accepted. 370 ~0 accepts all. 371 On success, REG will be filled with the index of the register which 372 was successfully scanned. 373 */ 374 static bool 375 lex_reg_name (uint16_t which, int *reg) 376 { 377 char *p = input_line_pointer; 378 379 if (p == 0) 380 return false; 381 382 /* Scan (and ignore) the register prefix. */ 383 if (register_prefix) 384 { 385 int len = strlen (register_prefix); 386 if (0 == strncmp (register_prefix, p, len)) 387 p += len; 388 else 389 return false; 390 } 391 392 char *start_of_reg_name = p; 393 394 while ((*p >= 'a' && *p <='z') 395 || (*p >= '0' && *p <= '9') 396 || (*p >= 'A' && *p <='Z')) 397 { 398 p++; 399 } 400 401 size_t len = p - start_of_reg_name; 402 403 if (len <= 0) 404 return false; 405 406 int i; 407 for (i = 0; i < S12Z_N_REGISTERS; ++i) 408 { 409 gas_assert (registers[i].name); 410 411 if (len == strlen (registers[i].name) 412 && 0 == strncasecmp (registers[i].name, start_of_reg_name, len)) 413 { 414 if ((0x1U << i) & which) 415 { 416 input_line_pointer = p; 417 *reg = i; 418 return true; 419 } 420 } 421 } 422 423 return false; 424 } 425 426 static bool 427 lex_force_match (char x) 428 { 429 char *p = input_line_pointer; 430 if (*p != x) 431 { 432 as_bad (_("Expecting '%c'"), x); 433 return false; 434 } 435 436 input_line_pointer++; 437 return true; 438 } 439 440 static bool 441 lex_opr (uint8_t *buffer, int *n_bytes, expressionS *exp, 442 bool immediate_ok) 443 { 444 char *ilp = input_line_pointer; 445 uint8_t *xb = buffer; 446 int reg; 447 long imm; 448 exp->X_op = O_absent; 449 *n_bytes = 0; 450 *xb = 0; 451 if (lex_imm_e4 (&imm)) 452 { 453 if (!immediate_ok) 454 { 455 as_bad (_("An immediate value in a source operand is inappropriate")); 456 return false; 457 } 458 if (imm > 0) 459 *xb = imm; 460 else 461 *xb = 0; 462 *xb |= 0x70; 463 *n_bytes = 1; 464 return true; 465 } 466 else if (lex_reg_name (REG_BIT_Dn, ®)) 467 { 468 *xb = reg; 469 *xb |= 0xb8; 470 *n_bytes = 1; 471 return true; 472 } 473 else if (lex_match ('[')) 474 { 475 if (lex_expression (exp)) 476 { 477 long c = exp->X_add_number; 478 if (lex_match (',')) 479 { 480 if (lex_reg_name (REG_BIT_XYSP, ®)) 481 { 482 int i; 483 if (c <= 255 && c >= -256) 484 { 485 *n_bytes = 2; 486 *xb |= 0xc4; 487 } 488 else 489 { 490 *n_bytes = 4; 491 *xb |= 0xc6; 492 } 493 *xb |= (reg - REG_X) << 4; 494 495 if (c < 0) 496 *xb |= 0x01; 497 for (i = 1; i < *n_bytes ; ++i) 498 { 499 buffer[i] = c >> (8 * (*n_bytes - i - 1)); 500 } 501 } 502 else 503 { 504 as_bad (_("Bad operand for constant offset")); 505 goto fail; 506 } 507 } 508 else 509 { 510 *xb = 0xfe; 511 *n_bytes = 4; 512 buffer[1] = c >> 16; 513 buffer[2] = c >> 8; 514 buffer[3] = c; 515 } 516 } 517 else if (lex_reg_name (REG_BIT_Dn, ®)) 518 { 519 if (!lex_force_match (',')) 520 goto fail; 521 522 int reg2; 523 if (lex_reg_name (REG_BIT_XY, ®2)) 524 { 525 *n_bytes = 1; 526 *xb = reg; 527 *xb |= (reg2 - REG_X) << 4; 528 *xb |= 0xc8; 529 } 530 else 531 { 532 as_bad (_("Invalid operand for register offset")); 533 goto fail; 534 } 535 } 536 else 537 { 538 goto fail; 539 } 540 if (!lex_force_match (']')) 541 goto fail; 542 return true; 543 } 544 else if (lex_match ('(')) 545 { 546 long c; 547 if (lex_constant (&c)) 548 { 549 if (!lex_force_match (',')) 550 goto fail; 551 int reg2; 552 if (lex_reg_name (REG_BIT_XYSP, ®2)) 553 { 554 if (reg2 != REG_P && c >= 0 && c <= 15) 555 { 556 *n_bytes = 1; 557 *xb = 0x40; 558 *xb |= (reg2 - REG_X) << 4; 559 *xb |= c; 560 } 561 else if (c >= -256 && c <= 255) 562 { 563 *n_bytes = 2; 564 *xb = 0xc0; 565 *xb |= (reg2 - REG_X) << 4; 566 if (c < 0) 567 *xb |= 0x01; 568 buffer[1] = c; 569 } 570 else 571 { 572 *n_bytes = 4; 573 *xb = 0xc2; 574 *xb |= (reg2 - REG_X) << 4; 575 buffer[1] = c >> 16; 576 buffer[2] = c >> 8; 577 buffer[3] = c; 578 } 579 } 580 else if (lex_reg_name (REG_BIT_Dn, ®2)) 581 { 582 if (c >= -1 * (long) (0x1u << 17) 583 && 584 c < (long) (0x1u << 17) - 1) 585 { 586 *n_bytes = 3; 587 *xb = 0x80; 588 *xb |= reg2; 589 *xb |= ((c >> 16) & 0x03) << 4; 590 buffer[1] = c >> 8; 591 buffer[2] = c; 592 } 593 else 594 { 595 *n_bytes = 4; 596 *xb = 0xe8; 597 *xb |= reg2; 598 buffer[1] = c >> 16; 599 buffer[2] = c >> 8; 600 buffer[3] = c; 601 } 602 } 603 else 604 { 605 as_bad (_("Bad operand for constant offset")); 606 goto fail; 607 } 608 } 609 else if (lex_reg_name (REG_BIT_Dn, ®)) 610 { 611 if (lex_match (',')) 612 { 613 int reg2; 614 if (lex_reg_name (REG_BIT_XYS, ®2)) 615 { 616 *n_bytes = 1; 617 *xb = 0x88; 618 *xb |= (reg2 - REG_X) << 4; 619 *xb |= reg; 620 } 621 else 622 { 623 as_bad (_("Invalid operand for register offset")); 624 goto fail; 625 } 626 } 627 else 628 { 629 goto fail; 630 } 631 } 632 else if (lex_reg_name (REG_BIT_XYS, ®)) 633 { 634 if (lex_match ('-')) 635 { 636 if (reg == REG_S) 637 { 638 as_bad (_("Invalid register for postdecrement operation")); 639 goto fail; 640 } 641 *n_bytes = 1; 642 if (reg == REG_X) 643 *xb = 0xc7; 644 else if (reg == REG_Y) 645 *xb = 0xd7; 646 } 647 else if (lex_match ('+')) 648 { 649 *n_bytes = 1; 650 if (reg == REG_X) 651 *xb = 0xe7; 652 else if (reg == REG_Y) 653 *xb = 0xf7; 654 else if (reg == REG_S) 655 *xb = 0xff; 656 } 657 else 658 { 659 goto fail; 660 } 661 } 662 else if (lex_match ('+')) 663 { 664 if (lex_reg_name (REG_BIT_XY, ®)) 665 { 666 *n_bytes = 1; 667 if (reg == REG_X) 668 *xb = 0xe3; 669 else if (reg == REG_Y) 670 *xb = 0xf3; 671 } 672 else 673 { 674 as_bad (_("Invalid register for preincrement operation")); 675 goto fail; 676 } 677 } 678 else if (lex_match ('-')) 679 { 680 if (lex_reg_name (REG_BIT_XYS, ®)) 681 { 682 *n_bytes = 1; 683 if (reg == REG_X) 684 *xb = 0xc3; 685 else if (reg == REG_Y) 686 *xb = 0xd3; 687 else if (reg == REG_S) 688 *xb = 0xfb; 689 } 690 else 691 { 692 as_bad (_("Invalid register for predecrement operation")); 693 goto fail; 694 } 695 } 696 else 697 { 698 goto fail; 699 } 700 701 if (! lex_match (')')) 702 goto fail; 703 return true; 704 } 705 else if (lex_expression (exp)) 706 { 707 *xb = 0xfa; 708 *n_bytes = 4; 709 buffer[1] = 0; 710 buffer[2] = 0; 711 buffer[3] = 0; 712 if (exp->X_op == O_constant) 713 { 714 valueT value = exp->X_add_number; 715 716 if (value < (0x1U << 14)) 717 { 718 *xb = 0x00; 719 *n_bytes = 2; 720 *xb |= value >> 8; 721 buffer[1] = value; 722 } 723 else if (value < (0x1U << 19)) 724 { 725 *xb = 0xf8; 726 if (value & (0x1U << 17)) 727 *xb |= 0x04; 728 if (value & (0x1U << 16)) 729 *xb |= 0x01; 730 *n_bytes = 3; 731 buffer[1] = value >> 8; 732 buffer[2] = value; 733 } 734 else 735 { 736 *xb = 0xfa; 737 *n_bytes = 4; 738 buffer[1] = value >> 16; 739 buffer[2] = value >> 8; 740 buffer[3] = value; 741 } 742 } 743 return true; 744 } 745 746 fail: 747 fail_line_pointer = input_line_pointer; 748 input_line_pointer = ilp; 749 return false; 750 } 751 752 static bool 753 lex_offset (long *val) 754 { 755 char *end = NULL; 756 char *p = input_line_pointer; 757 758 if (*p++ != '*') 759 return false; 760 761 if (*p != '+' && *p != '-') 762 return false; 763 764 bool negative = (*p == '-'); 765 p++; 766 767 errno = 0; 768 *val = s12z_strtol (p, &end); 769 if (errno == 0) 770 { 771 if (negative) 772 *val *= -1; 773 input_line_pointer = end; 774 return true; 775 } 776 777 return false; 778 } 779 780 781 782 struct instruction; 783 784 typedef bool (*parse_operand_func) (const struct instruction *); 785 786 struct instruction 787 { 788 const char *name; 789 790 /* The "page" to which the instruction belongs. 791 This is also only a hint. Some instructions might have modes in both 792 pages... */ 793 char page; 794 795 /* This is a hint - and only a hint - about the opcode of the instruction. 796 The parse_operand_func is free to ignore it. 797 */ 798 uint8_t opc; 799 800 parse_operand_func parse_operands; 801 802 /* Some instructions can be encoded with a different opcode */ 803 uint8_t alt_opc; 804 }; 805 806 static bool 807 no_operands (const struct instruction *insn) 808 { 809 if (*input_line_pointer != '\0') 810 { 811 as_bad (_("Garbage at end of instruction")); 812 return false; 813 } 814 815 char *f = s12z_new_insn (insn->page); 816 if (insn->page == 2) 817 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1); 818 819 number_to_chars_bigendian (f++, insn->opc, 1); 820 821 return true; 822 } 823 824 825 static void 826 emit_reloc (expressionS *exp, char *f, int size, enum bfd_reloc_code_real reloc) 827 { 828 if (exp->X_op != O_absent && exp->X_op != O_constant) 829 { 830 fixS *fix = fix_new_exp (frag_now, 831 f - frag_now->fr_literal, 832 size, 833 exp, 834 false, 835 reloc); 836 /* Some third party tools seem to use the lower bits 837 of this addend for flags. They don't get added 838 to the final location. The purpose of these flags 839 is not known. We simply set it to zero. */ 840 fix->fx_addnumber = 0x00; 841 } 842 } 843 844 /* Emit the code for an OPR address mode operand */ 845 static char * 846 emit_opr (char *f, const uint8_t *buffer, int n_bytes, expressionS *exp) 847 { 848 int i; 849 number_to_chars_bigendian (f++, buffer[0], 1); 850 851 emit_reloc (exp, f, 3, BFD_RELOC_S12Z_OPR); 852 853 for (i = 1; i < n_bytes; ++i) 854 number_to_chars_bigendian (f++, buffer[i], 1); 855 856 return f; 857 } 858 859 /* Emit the code for a 24 bit direct address operand */ 860 static char * 861 emit_ext24 (char *f, long v) 862 { 863 number_to_chars_bigendian (f, v, 3); 864 865 return f + 3; 866 } 867 868 static bool 869 opr (const struct instruction *insn) 870 { 871 uint8_t buffer[4]; 872 int n_bytes; 873 expressionS exp; 874 if (lex_opr (buffer, &n_bytes, &exp, false)) 875 { 876 /* Large constant direct values are more efficiently encoded as ext24 mode. 877 Otherwise a decision has to be deferred to a relax. */ 878 if (exp.X_op == O_constant 879 && buffer[0] == 0xFA 880 && insn->alt_opc != 0) 881 { 882 char *f = s12z_new_insn (4); 883 884 /* I don't think there are any instances of page 2 opcodes in this case */ 885 gas_assert (insn->page == 1); 886 887 number_to_chars_bigendian (f++, insn->alt_opc, 1); 888 889 emit_ext24 (f, exp.X_add_number); 890 } 891 else 892 { 893 char *f = s12z_new_insn (n_bytes + 1); 894 number_to_chars_bigendian (f++, insn->opc, 1); 895 896 emit_opr (f, buffer, n_bytes, &exp); 897 } 898 return true; 899 } 900 901 return false; 902 } 903 904 /* Parse a 15 bit offset, as an expression. 905 LONG_DISPLACEMENT will be set to true if the offset is wider than 7 bits. 906 */ 907 static bool 908 lex_15_bit_offset (bool *long_displacement, expressionS *exp) 909 { 910 char *ilp = input_line_pointer; 911 912 long val; 913 if (lex_offset (&val)) 914 { 915 exp->X_op = O_absent; 916 exp->X_add_number = val; 917 } 918 else if (lex_expression (exp)) 919 { 920 if (exp->X_op == O_constant) 921 { 922 val = exp->X_add_number; 923 } 924 else 925 { 926 /* If a symbol was parsed we don't know the displacement. 927 We have to assume it is long, and relax it later if possible. */ 928 *long_displacement = true; 929 return true; 930 } 931 } 932 else 933 { 934 exp->X_op = O_absent; 935 goto fail; 936 } 937 938 if (val > 0x3FFF || val < -0x4000) 939 { 940 as_fatal (_("Offset is outside of 15 bit range")); 941 return false; 942 } 943 944 *long_displacement = (val > 63 || val < -64); 945 946 return true; 947 948 fail: 949 fail_line_pointer = input_line_pointer; 950 input_line_pointer = ilp; 951 return false; 952 } 953 954 static void 955 emit_15_bit_offset (char *f, int where, expressionS *exp) 956 { 957 gas_assert (exp); 958 if (exp->X_op != O_absent && exp->X_op != O_constant) 959 { 960 exp->X_add_number += where; 961 fixS *fix = fix_new_exp (frag_now, 962 f - frag_now->fr_literal, 963 2, 964 exp, 965 true, 966 BFD_RELOC_16_PCREL); 967 fix->fx_addnumber = where - 2; 968 } 969 else 970 { 971 long val = exp->X_add_number; 972 bool long_displacement = (val > 63 || val < -64); 973 if (long_displacement) 974 val |= 0x8000; 975 else 976 val &= 0x7F; 977 978 number_to_chars_bigendian (f++, val, long_displacement ? 2 : 1); 979 } 980 } 981 982 static bool 983 rel (const struct instruction *insn) 984 { 985 bool long_displacement; 986 987 expressionS exp; 988 if (! lex_15_bit_offset (&long_displacement, &exp)) 989 return false; 990 991 char *f = s12z_new_insn (long_displacement ? 3 : 2); 992 number_to_chars_bigendian (f++, insn->opc, 1); 993 emit_15_bit_offset (f, 3, &exp); 994 return true; 995 } 996 997 static bool 998 reg_inh (const struct instruction *insn) 999 { 1000 int reg; 1001 if (lex_reg_name (REG_BIT_Dn, ®)) 1002 { 1003 char *f = s12z_new_insn (insn->page); 1004 if (insn->page == 2) 1005 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1); 1006 1007 number_to_chars_bigendian (f++, insn->opc + reg, 1); 1008 return true; 1009 } 1010 1011 return false; 1012 } 1013 1014 1015 /* Special case for CLR X and CLR Y */ 1016 static bool 1017 clr_xy (const struct instruction *insn ATTRIBUTE_UNUSED) 1018 { 1019 int reg; 1020 if (lex_reg_name (REG_BIT_XY, ®)) 1021 { 1022 char *f = s12z_new_insn (1); 1023 number_to_chars_bigendian (f, 0x9a + reg - REG_X, 1); 1024 return true; 1025 } 1026 1027 return false; 1028 } 1029 1030 /* Some instructions have a suffix like ".l", ".b", ".w" etc 1031 which indicates the size of the operands. */ 1032 static int 1033 size_from_suffix (const struct instruction *insn, int idx) 1034 { 1035 const char *dot = strchr (insn->name, '.'); 1036 1037 if (dot == NULL) 1038 return -3; 1039 1040 int size = -2; 1041 switch (dot[1 + idx]) 1042 { 1043 case 'b': 1044 size = 1; 1045 break; 1046 case 'w': 1047 size = 2; 1048 break; 1049 case 'p': 1050 size = 3; 1051 break; 1052 case 'l': 1053 size = 4; 1054 break; 1055 default: 1056 as_fatal (_("Bad size")); 1057 }; 1058 1059 return size; 1060 } 1061 1062 static bool 1063 mul_reg_reg_reg (const struct instruction *insn) 1064 { 1065 char *ilp = input_line_pointer; 1066 1067 int Dd; 1068 if (!lex_reg_name (REG_BIT_Dn, &Dd)) 1069 goto fail; 1070 1071 if (!lex_match (',')) 1072 goto fail; 1073 1074 int Dj; 1075 if (!lex_reg_name (REG_BIT_Dn, &Dj)) 1076 goto fail; 1077 1078 if (!lex_match (',')) 1079 goto fail; 1080 1081 int Dk; 1082 if (!lex_reg_name (REG_BIT_Dn, &Dk)) 1083 goto fail; 1084 1085 char *f = s12z_new_insn (insn->page + 1); 1086 if (insn->page == 2) 1087 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1); 1088 1089 number_to_chars_bigendian (f++, insn->opc + Dd, 1); 1090 const char *dot = strchrnul (insn->name, '.'); 1091 uint8_t mb ; 1092 switch (dot[-1]) 1093 { 1094 case 's': 1095 mb = 0x80; 1096 break; 1097 case 'u': 1098 mb = 0x00; 1099 break; 1100 default: 1101 as_fatal (_("BAD MUL")); 1102 break; 1103 } 1104 1105 mb |= Dj << 3; 1106 mb |= Dk; 1107 1108 number_to_chars_bigendian (f++, mb, 1); 1109 1110 return true; 1111 1112 fail: 1113 fail_line_pointer = input_line_pointer; 1114 input_line_pointer = ilp; 1115 return false; 1116 } 1117 1118 1119 static bool 1120 mul_reg_reg_imm (const struct instruction *insn) 1121 { 1122 char *ilp = input_line_pointer; 1123 1124 int Dd; 1125 if (!lex_reg_name (REG_BIT_Dn, &Dd)) 1126 goto fail; 1127 1128 if (!lex_match (',')) 1129 goto fail; 1130 1131 int Dj; 1132 if (!lex_reg_name (REG_BIT_Dn, &Dj)) 1133 goto fail; 1134 1135 if (!lex_match (',')) 1136 goto fail; 1137 1138 long imm; 1139 if (!lex_imm (&imm, NULL)) 1140 goto fail; 1141 1142 1143 int size = size_from_suffix (insn, 0); 1144 1145 char *f = s12z_new_insn (insn->page + 1 + size); 1146 if (insn->page == 2) 1147 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1); 1148 1149 number_to_chars_bigendian (f++, insn->opc + Dd, 1); 1150 uint8_t mb = 0x44; 1151 const char *dot = strchrnul (insn->name, '.'); 1152 switch (dot[-1]) 1153 { 1154 case 's': 1155 mb |= 0x80; 1156 break; 1157 case 'u': 1158 mb |= 0x00; 1159 break; 1160 default: 1161 as_fatal (_("BAD MUL")); 1162 break; 1163 } 1164 1165 mb |= Dj << 3; 1166 mb |= size - 1; 1167 1168 number_to_chars_bigendian (f++, mb, 1); 1169 number_to_chars_bigendian (f++, imm, size); 1170 1171 return true; 1172 1173 fail: 1174 fail_line_pointer = input_line_pointer; 1175 input_line_pointer = ilp; 1176 return false; 1177 } 1178 1179 1180 static bool 1181 mul_reg_reg_opr (const struct instruction *insn) 1182 { 1183 char *ilp = input_line_pointer; 1184 1185 int Dd; 1186 if (!lex_reg_name (REG_BIT_Dn, &Dd)) 1187 goto fail; 1188 1189 if (!lex_match (',')) 1190 goto fail; 1191 1192 int Dj; 1193 if (!lex_reg_name (REG_BIT_Dn, &Dj)) 1194 goto fail; 1195 1196 if (!lex_match (',')) 1197 goto fail; 1198 1199 uint8_t buffer[4]; 1200 int n_bytes; 1201 expressionS exp; 1202 if (!lex_opr (buffer, &n_bytes, &exp, true)) 1203 goto fail; 1204 1205 int size = size_from_suffix (insn, 0); 1206 1207 char *f = s12z_new_insn (insn->page + 1 + n_bytes); 1208 if (insn->page == 2) 1209 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1); 1210 1211 number_to_chars_bigendian (f++, insn->opc + Dd, 1); 1212 uint8_t mb = 0x40; 1213 const char *dot = strchrnul (insn->name, '.'); 1214 switch (dot[-1]) 1215 { 1216 case 's': 1217 mb |= 0x80; 1218 break; 1219 case 'u': 1220 mb |= 0x00; 1221 break; 1222 default: 1223 as_fatal (_("BAD MUL")); 1224 break; 1225 } 1226 1227 mb |= Dj << 3; 1228 mb |= size - 1; 1229 1230 number_to_chars_bigendian (f++, mb, 1); 1231 1232 emit_opr (f, buffer, n_bytes, &exp); 1233 1234 return true; 1235 1236 fail: 1237 fail_line_pointer = input_line_pointer; 1238 input_line_pointer = ilp; 1239 return false; 1240 } 1241 1242 static bool 1243 mul_reg_opr_opr (const struct instruction *insn) 1244 { 1245 char *ilp = input_line_pointer; 1246 1247 int Dd; 1248 if (!lex_reg_name (REG_BIT_Dn, &Dd)) 1249 goto fail; 1250 1251 if (!lex_match (',')) 1252 goto fail; 1253 1254 uint8_t buffer1[4]; 1255 int n_bytes1; 1256 expressionS exp1; 1257 if (!lex_opr (buffer1, &n_bytes1, &exp1, false)) 1258 goto fail; 1259 1260 if (!lex_match (',')) 1261 goto fail; 1262 1263 uint8_t buffer2[4]; 1264 int n_bytes2; 1265 expressionS exp2; 1266 if (!lex_opr (buffer2, &n_bytes2, &exp2, false)) 1267 goto fail; 1268 1269 int size1 = size_from_suffix (insn, 0); 1270 int size2 = size_from_suffix (insn, 1); 1271 1272 char *f = s12z_new_insn (insn->page + 1 + n_bytes1 + n_bytes2); 1273 if (insn->page == 2) 1274 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1); 1275 1276 number_to_chars_bigendian (f++, insn->opc + Dd, 1); 1277 uint8_t mb = 0x42; 1278 const char *dot = strchrnul (insn->name, '.'); 1279 switch (dot[-1]) 1280 { 1281 case 's': 1282 mb |= 0x80; 1283 break; 1284 case 'u': 1285 mb |= 0x00; 1286 break; 1287 default: 1288 as_fatal (_("BAD MUL")); 1289 break; 1290 } 1291 1292 mb |= (size1 - 1) << 4; 1293 mb |= (size2 - 1) << 2; 1294 number_to_chars_bigendian (f++, mb, 1); 1295 1296 f = emit_opr (f, buffer1, n_bytes1, &exp1); 1297 f = emit_opr (f, buffer2, n_bytes2, &exp2); 1298 1299 return true; 1300 1301 fail: 1302 fail_line_pointer = input_line_pointer; 1303 input_line_pointer = ilp; 1304 return false; 1305 } 1306 1307 1308 #define REG_BIT_GRP0 \ 1309 ((0x1U << REG_D2) | \ 1310 (0x1U << REG_D3) | \ 1311 (0x1U << REG_CCH) | \ 1312 (0x1U << REG_CCL) | \ 1313 (0x1U << REG_D0) | \ 1314 (0x1U << REG_D1)) 1315 1316 #define REG_BIT_GRP1 \ 1317 ((0x1U << REG_D4) | \ 1318 (0x1U << REG_D5) | \ 1319 (0x1U << REG_D6) | \ 1320 (0x1U << REG_D7) | \ 1321 (0x1U << REG_X) | \ 1322 (0x1U << REG_Y)) 1323 1324 static const uint8_t reg_map [] = 1325 { 1326 0x02, /* D2 */ 1327 0x01, /* D3 */ 1328 0x20, 1329 0x10, /* D5 */ 1330 0x08, /* D0 */ 1331 0x04, /* D1 */ 1332 0x08, /* D6 */ 1333 0x04, /* D7 */ 1334 0x02, 1335 0x01, /* Y */ 1336 0x00, 1337 0x00, 1338 0x20, /* CCH */ 1339 0x10, /* CCL */ 1340 0x00 1341 }; 1342 1343 static bool 1344 lex_reg_list (uint16_t grp, uint16_t *reg_bits) 1345 { 1346 if (lex_match (',')) 1347 { 1348 int reg; 1349 if (!lex_reg_name (grp, ®)) 1350 return false; 1351 *reg_bits |= 0x1u << reg; 1352 lex_reg_list (grp, reg_bits); 1353 } 1354 1355 /* Empty list */ 1356 return true; 1357 } 1358 1359 static bool 1360 psh_pull (const struct instruction *insn) 1361 { 1362 uint8_t pb = 1363 (0 == strcmp ("pul", insn->name)) ? 0x80: 0x00; 1364 1365 if (lex_match_string ("all16b")) 1366 { 1367 pb |= 0x40; 1368 } 1369 else if (lex_match_string ("all")) 1370 { 1371 /* Nothing to do */ 1372 } 1373 else 1374 { 1375 int reg1; 1376 if (!lex_reg_name (REG_BIT_GRP1 | REG_BIT_GRP0, ®1)) 1377 goto fail; 1378 uint16_t admitted_group = 0; 1379 1380 if ((0x1U << reg1) & REG_BIT_GRP1) 1381 admitted_group = REG_BIT_GRP1; 1382 else if ((0x1U << reg1) & REG_BIT_GRP0) 1383 admitted_group = REG_BIT_GRP0; 1384 1385 uint16_t reg_bits = 0x1 << reg1; 1386 if (!lex_reg_list (admitted_group, ®_bits)) 1387 goto fail; 1388 1389 if (reg_bits & REG_BIT_GRP1) 1390 pb |= 0x40; 1391 1392 int i; 1393 for (i = 0; i < 16; ++i) 1394 { 1395 if (reg_bits & (0x1u << i)) 1396 pb |= reg_map[i]; 1397 } 1398 } 1399 1400 char *f = s12z_new_insn (2); 1401 number_to_chars_bigendian (f++, insn->opc, 1); 1402 number_to_chars_bigendian (f++, pb, 1); 1403 return true; 1404 1405 fail: 1406 fail_line_pointer = input_line_pointer; 1407 return false; 1408 } 1409 1410 1411 static bool 1412 tfr (const struct instruction *insn) 1413 { 1414 int reg1; 1415 if (!lex_reg_name (~0, ®1)) 1416 goto fail; 1417 1418 if (!lex_match (',')) 1419 goto fail; 1420 1421 int reg2; 1422 if (!lex_reg_name (~0, ®2)) 1423 goto fail; 1424 1425 if ( ((0 == strcasecmp ("sex", insn->name)) 1426 || (0 == strcasecmp ("zex", insn->name))) 1427 && (registers[reg2].bytes <= registers[reg1].bytes)) 1428 as_warn (_("Source register for %s is no larger than the destination register"), 1429 insn->name); 1430 else if (reg1 == reg2) 1431 as_warn (_("The destination and source registers are identical")); 1432 1433 char *f = s12z_new_insn (1 + insn->page); 1434 if (insn->page == 2) 1435 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1); 1436 1437 number_to_chars_bigendian (f++, insn->opc, 1); 1438 number_to_chars_bigendian (f++, reg1 << 4 | reg2, 1); 1439 1440 return true; 1441 1442 fail: 1443 fail_line_pointer = input_line_pointer; 1444 return false; 1445 } 1446 1447 static bool 1448 imm8 (const struct instruction *insn) 1449 { 1450 long imm; 1451 if (! lex_imm (&imm, NULL)) 1452 return false; 1453 if (imm > 127 || imm < -128) 1454 { 1455 as_bad (_("Immediate value %ld is out of range for instruction %s"), 1456 imm, insn->name); 1457 } 1458 1459 char *f = s12z_new_insn (2); 1460 number_to_chars_bigendian (f++, insn->opc, 1); 1461 number_to_chars_bigendian (f++, imm, 1); 1462 1463 return true; 1464 } 1465 1466 static bool 1467 reg_imm (const struct instruction *insn, int allowed_reg) 1468 { 1469 char *ilp = input_line_pointer; 1470 int reg; 1471 if (lex_reg_name (allowed_reg, ®)) 1472 { 1473 if (!lex_force_match (',')) 1474 goto fail; 1475 long imm; 1476 if (! lex_imm (&imm, NULL)) 1477 goto fail; 1478 1479 short size = registers[reg].bytes; 1480 char *f = s12z_new_insn (insn->page + size); 1481 if (insn->page == 2) 1482 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1); 1483 1484 number_to_chars_bigendian (f++, insn->opc + reg, 1); 1485 number_to_chars_bigendian (f++, imm, size); 1486 return true; 1487 } 1488 1489 fail: 1490 fail_line_pointer = input_line_pointer; 1491 input_line_pointer = ilp; 1492 return false; 1493 } 1494 1495 1496 static bool 1497 regd_imm (const struct instruction *insn) 1498 { 1499 return reg_imm (insn, REG_BIT_Dn); 1500 } 1501 1502 static bool 1503 regdxy_imm (const struct instruction *insn) 1504 { 1505 return reg_imm (insn, REG_BIT_Dn | REG_BIT_XY); 1506 } 1507 1508 1509 static bool 1510 regs_imm (const struct instruction *insn) 1511 { 1512 return reg_imm (insn, 0x1U << REG_S); 1513 } 1514 1515 static bool 1516 trap_imm (const struct instruction *insn ATTRIBUTE_UNUSED) 1517 { 1518 long imm = -1; 1519 if (! lex_imm (&imm, NULL)) 1520 goto fail; 1521 1522 if (imm < 0x92 || imm > 0xFF || 1523 (imm >= 0xA0 && imm <= 0xA7) || 1524 (imm >= 0xB0 && imm <= 0xB7)) 1525 { 1526 as_bad (_("trap value %ld is not valid"), imm); 1527 return false; 1528 } 1529 else 1530 { 1531 char *f = s12z_new_insn (2); 1532 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1); 1533 number_to_chars_bigendian (f++, imm & 0xFF, 1); 1534 return true; 1535 } 1536 1537 return true; 1538 1539 fail: 1540 fail_line_pointer = input_line_pointer; 1541 return false; 1542 } 1543 1544 1545 1546 /* Special one byte instruction CMP X, Y */ 1547 static bool 1548 regx_regy (const struct instruction *insn) 1549 { 1550 int reg; 1551 if (lex_reg_name (0x1U << REG_X, ®)) 1552 { 1553 if (lex_force_match (',')) 1554 { 1555 if (lex_reg_name (0x1U << REG_Y, ®)) 1556 { 1557 char *f = s12z_new_insn (1); 1558 number_to_chars_bigendian (f, insn->opc, 1); 1559 return true; 1560 } 1561 } 1562 } 1563 return false; 1564 } 1565 1566 /* Special one byte instruction SUB D6, X, Y */ 1567 static bool 1568 regd6_regx_regy (const struct instruction *insn) 1569 { 1570 char *ilp = input_line_pointer; 1571 int reg; 1572 if (!lex_reg_name (0x1U << REG_D6, ®)) 1573 goto fail; 1574 1575 if (!lex_match (',')) 1576 goto fail; 1577 1578 if (!lex_reg_name (0x1U << REG_X, ®)) 1579 goto fail; 1580 1581 if (!lex_match (',')) 1582 goto fail; 1583 1584 if (!lex_reg_name (0x1U << REG_Y, ®)) 1585 goto fail; 1586 1587 char *f = s12z_new_insn (1); 1588 number_to_chars_bigendian (f, insn->opc, 1); 1589 return true; 1590 1591 fail: 1592 fail_line_pointer = input_line_pointer; 1593 input_line_pointer = ilp; 1594 return false; 1595 } 1596 1597 /* Special one byte instruction SUB D6, Y, X */ 1598 static bool 1599 regd6_regy_regx (const struct instruction *insn) 1600 { 1601 char *ilp = input_line_pointer; 1602 int reg; 1603 if (!lex_reg_name (0x1U << REG_D6, ®)) 1604 goto fail; 1605 1606 if (!lex_match (',')) 1607 goto fail; 1608 1609 if (!lex_reg_name (0x1U << REG_Y, ®)) 1610 goto fail; 1611 1612 if (!lex_match (',')) 1613 goto fail; 1614 1615 if (!lex_reg_name (0x1U << REG_X, ®)) 1616 goto fail; 1617 1618 char *f = s12z_new_insn (1); 1619 number_to_chars_bigendian (f, insn->opc, 1); 1620 return true; 1621 1622 fail: 1623 fail_line_pointer = input_line_pointer; 1624 input_line_pointer = ilp; 1625 return false; 1626 } 1627 1628 static bool 1629 reg_opr (const struct instruction *insn, int allowed_regs, 1630 bool immediate_ok) 1631 { 1632 char *ilp = input_line_pointer; 1633 int reg; 1634 if (lex_reg_name (allowed_regs, ®)) 1635 { 1636 if (!lex_force_match (',')) 1637 goto fail; 1638 1639 uint8_t buffer[4]; 1640 int n_bytes; 1641 expressionS exp; 1642 if (lex_opr (buffer, &n_bytes, &exp, immediate_ok)) 1643 { 1644 /* Large constant direct values are more efficiently encoded as ext24 mode. 1645 Otherwise a decision has to be deferred to a relax. */ 1646 if (exp.X_op == O_constant 1647 && buffer[0] == 0xFA 1648 && insn->alt_opc != 0) 1649 { 1650 char *f = s12z_new_insn (4); 1651 1652 /* I don't think there are any instances of page 2 opcodes in this case */ 1653 gas_assert (insn->page == 1); 1654 1655 number_to_chars_bigendian (f++, insn->alt_opc + reg, 1); 1656 1657 emit_ext24 (f, exp.X_add_number); 1658 } 1659 else 1660 { 1661 char *f = s12z_new_insn (n_bytes + insn->page); 1662 1663 if (insn->page == 2) 1664 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1); 1665 1666 number_to_chars_bigendian (f++, insn->opc + reg, 1); 1667 1668 emit_opr (f, buffer, n_bytes, &exp); 1669 } 1670 1671 return true; 1672 } 1673 } 1674 1675 fail: 1676 fail_line_pointer = input_line_pointer; 1677 input_line_pointer = ilp; 1678 return false; 1679 } 1680 1681 1682 static bool 1683 regdxy_opr_dest (const struct instruction *insn) 1684 { 1685 return reg_opr (insn, REG_BIT_Dn | REG_BIT_XY, false); 1686 } 1687 1688 static bool 1689 regdxy_opr_src (const struct instruction *insn) 1690 { 1691 return reg_opr (insn, REG_BIT_Dn | REG_BIT_XY, true); 1692 } 1693 1694 1695 static bool 1696 regd_opr (const struct instruction *insn) 1697 { 1698 return reg_opr (insn, REG_BIT_Dn, true); 1699 } 1700 1701 1702 /* OP0: S; OP1: destination OPR */ 1703 static bool 1704 regs_opr_dest (const struct instruction *insn) 1705 { 1706 return reg_opr (insn, 0x1U << REG_S, false); 1707 } 1708 1709 /* OP0: S; OP1: source OPR */ 1710 static bool 1711 regs_opr_src (const struct instruction *insn) 1712 { 1713 return reg_opr (insn, 0x1U << REG_S, true); 1714 } 1715 1716 static bool 1717 imm_opr (const struct instruction *insn) 1718 { 1719 char *ilp = input_line_pointer; 1720 long imm; 1721 expressionS exp0; 1722 int size = size_from_suffix (insn, 0); 1723 exp0.X_op = O_absent; 1724 1725 /* Note: The ternary expression below means that "MOV.x #symbol, 1726 mem-expr" is accepted when x is a member of {'w', 'p', 'l'} but 1727 not when it is 'b'. 1728 The Freescale assembler accepts "MOV.b #symbol, mem-expr" but 1729 produces obviously incorrect code. Since such an instruction 1730 would require an 8-bit reloc (which we don't have) and some 1731 non-optimal kludges in the OPR encoding, it seems sensible that 1732 such instructions should be rejected. */ 1733 if (!lex_imm (&imm, size > 1 ? &exp0 : NULL)) 1734 goto fail; 1735 1736 if (!lex_match (',')) 1737 goto fail; 1738 1739 uint8_t buffer[4]; 1740 int n_bytes; 1741 expressionS exp1; 1742 if (!lex_opr (buffer, &n_bytes, &exp1, false)) 1743 goto fail; 1744 1745 char *f = s12z_new_insn (1 + n_bytes + size); 1746 number_to_chars_bigendian (f++, insn->opc, 1); 1747 1748 emit_reloc (&exp0, f, size, size == 4 ? BFD_RELOC_32 : BFD_RELOC_S12Z_OPR); 1749 1750 int i; 1751 for (i = 0; i < size; ++i) 1752 number_to_chars_bigendian (f++, imm >> (CHAR_BIT * (size - i - 1)), 1); 1753 1754 emit_opr (f, buffer, n_bytes, &exp1); 1755 1756 return true; 1757 1758 fail: 1759 fail_line_pointer = input_line_pointer; 1760 input_line_pointer = ilp; 1761 return false; 1762 } 1763 1764 static bool 1765 opr_opr (const struct instruction *insn) 1766 { 1767 char *ilp = input_line_pointer; 1768 1769 uint8_t buffer1[4]; 1770 int n_bytes1; 1771 expressionS exp1; 1772 if (!lex_opr (buffer1, &n_bytes1, &exp1, false)) 1773 goto fail; 1774 1775 1776 if (!lex_match (',')) 1777 goto fail; 1778 1779 uint8_t buffer2[4]; 1780 int n_bytes2; 1781 expressionS exp2; 1782 if (!lex_opr (buffer2, &n_bytes2, &exp2, false)) 1783 goto fail; 1784 1785 char *f = s12z_new_insn (1 + n_bytes1 + n_bytes2); 1786 number_to_chars_bigendian (f++, insn->opc, 1); 1787 1788 f = emit_opr (f, buffer1, n_bytes1, &exp1); 1789 f = emit_opr (f, buffer2, n_bytes2, &exp2); 1790 1791 return true; 1792 1793 fail: 1794 fail_line_pointer = input_line_pointer; 1795 input_line_pointer = ilp; 1796 return false; 1797 } 1798 1799 static bool 1800 reg67sxy_opr (const struct instruction *insn) 1801 { 1802 int reg; 1803 if (!lex_reg_name (REG_BIT_XYS | (0x1U << REG_D6) | (0x1U << REG_D7), ®)) 1804 return false; 1805 1806 if (!lex_match (',')) 1807 return false; 1808 1809 uint8_t buffer[4]; 1810 int n_bytes; 1811 expressionS exp; 1812 if (!lex_opr (buffer, &n_bytes, &exp, false)) 1813 return false; 1814 1815 char *f = s12z_new_insn (1 + n_bytes); 1816 number_to_chars_bigendian (f++, insn->opc + reg - REG_D6, 1); 1817 emit_opr (f, buffer, n_bytes, &exp); 1818 1819 return true; 1820 } 1821 1822 static bool 1823 rotate (const struct instruction *insn, short dir) 1824 { 1825 uint8_t buffer[4]; 1826 int n_bytes; 1827 expressionS exp; 1828 if (lex_opr (buffer, &n_bytes, &exp, false)) 1829 { 1830 char *f = s12z_new_insn (n_bytes + 2); 1831 number_to_chars_bigendian (f++, insn->opc, 1); 1832 int size = size_from_suffix (insn, 0); 1833 if (size < 0) 1834 size = 1; 1835 uint8_t sb = 0x24; 1836 sb |= size - 1; 1837 if (dir) 1838 sb |= 0x40; 1839 number_to_chars_bigendian (f++, sb, 1); 1840 emit_opr (f, buffer, n_bytes, &exp); 1841 1842 return true; 1843 } 1844 1845 return false; 1846 } 1847 1848 static bool 1849 rol (const struct instruction *insn) 1850 { 1851 return rotate (insn, 1); 1852 } 1853 1854 static bool 1855 ror (const struct instruction *insn) 1856 { 1857 return rotate (insn, 0); 1858 } 1859 1860 1861 /* Shift instruction with a register operand and an immediate #1 or #2 1862 left = 1; right = 0; 1863 logical = 0; arithmetic = 1; 1864 */ 1865 static bool 1866 lex_shift_reg_imm1 (const struct instruction *insn, short type, short dir) 1867 { 1868 /* 1869 This function is highly unusual and a bit wierd! 1870 It first matches the input against a register {d0, d1, ... d7} followed by an immediate 1871 {#1, #2}. 1872 Then, it rewinds the input and parses it again as a OPR. 1873 */ 1874 char *ilp = input_line_pointer; 1875 1876 int Dd; 1877 if (!lex_reg_name (REG_BIT_Dn, &Dd)) 1878 { 1879 goto fail; 1880 } 1881 1882 if (!lex_match (',')) 1883 goto fail; 1884 1885 long imm = -1; 1886 if (!lex_imm (&imm, NULL)) 1887 goto fail; 1888 1889 if (imm != 1 && imm != 2) 1890 goto fail; 1891 input_line_pointer = ilp; 1892 1893 /* Now parse the first operand again */ 1894 1895 uint8_t buffer[4]; 1896 int n_bytes; 1897 1898 expressionS exp; 1899 if (!lex_opr (buffer, &n_bytes, &exp, false)) 1900 goto fail; 1901 1902 gas_assert (n_bytes == 1); 1903 1904 uint8_t sb = 0x34; 1905 sb |= dir << 6; 1906 sb |= type << 7; 1907 if (imm == 2) 1908 sb |= 0x08; 1909 1910 char *f = s12z_new_insn (3); 1911 number_to_chars_bigendian (f++, insn->opc, 1); 1912 number_to_chars_bigendian (f++, sb, 1); 1913 emit_opr (f, buffer, n_bytes, &exp); 1914 1915 return true; 1916 1917 fail: 1918 fail_line_pointer = input_line_pointer; 1919 input_line_pointer = ilp; 1920 return false; 1921 } 1922 1923 /* Shift instruction with a register operand. 1924 left = 1; right = 0; 1925 logical = 0; arithmetic = 1; */ 1926 static bool 1927 lex_shift_reg (const struct instruction *insn, short type, short dir) 1928 { 1929 int Dd, Ds, Dn; 1930 if (!lex_reg_name (REG_BIT_Dn, &Dd)) 1931 { 1932 goto fail; 1933 } 1934 1935 if (!lex_match (',')) 1936 goto fail; 1937 1938 if (!lex_reg_name (REG_BIT_Dn, &Ds)) 1939 { 1940 goto fail; 1941 } 1942 1943 if (!lex_match (',')) 1944 goto fail; 1945 1946 uint8_t sb = 0x10; 1947 sb |= Ds; 1948 sb |= dir << 6; 1949 sb |= type << 7; 1950 long imm; 1951 if (lex_reg_name (REG_BIT_Dn, &Dn)) 1952 { 1953 char *f = s12z_new_insn (3); 1954 number_to_chars_bigendian (f++, insn->opc | Dd, 1); 1955 number_to_chars_bigendian (f++, sb, 1); 1956 uint8_t xb = 0xb8; 1957 xb |= Dn; 1958 number_to_chars_bigendian (f++, xb, 1); 1959 1960 return true; 1961 } 1962 else if (lex_imm (&imm, NULL)) 1963 { 1964 if (imm < 0 || imm > 31) 1965 { 1966 as_bad (_("Shift value should be in the range [0,31]")); 1967 goto fail; 1968 } 1969 1970 int n_bytes = 3; 1971 if (imm == 1 || imm == 2) 1972 { 1973 n_bytes = 2; 1974 sb &= ~0x10; 1975 } 1976 else 1977 { 1978 sb |= (imm & 0x01) << 3; 1979 } 1980 1981 char *f = s12z_new_insn (n_bytes); 1982 number_to_chars_bigendian (f++, insn->opc | Dd, 1); 1983 number_to_chars_bigendian (f++, sb, 1); 1984 if (n_bytes > 2) 1985 { 1986 uint8_t xb = 0x70; 1987 xb |= imm >> 1; 1988 number_to_chars_bigendian (f++, xb, 1); 1989 } 1990 1991 return true; 1992 } 1993 1994 fail: 1995 fail_line_pointer = input_line_pointer; 1996 return false; 1997 } 1998 1999 static void 2000 impute_shift_dir_and_type (const struct instruction *insn, short *type, short *dir) 2001 { 2002 *dir = -1; 2003 *type = -1; 2004 switch (insn->name[0]) 2005 { 2006 case 'l': 2007 *type = 0; 2008 break; 2009 case 'a': 2010 *type = 1; 2011 break; 2012 default: 2013 as_fatal (_("Bad shift mode")); 2014 break; 2015 } 2016 2017 switch (insn->name[2]) 2018 { 2019 case 'l': 2020 *dir = 1; 2021 break; 2022 case 'r': 2023 *dir = 0; 2024 break; 2025 default: 2026 as_fatal (_("Bad shift *direction")); 2027 break; 2028 } 2029 } 2030 2031 /* Shift instruction with a OPR operand */ 2032 static bool 2033 shift_two_operand (const struct instruction *insn) 2034 { 2035 uint8_t sb = 0x34; 2036 char *ilp = input_line_pointer; 2037 2038 short dir = -1; 2039 short type = -1; 2040 impute_shift_dir_and_type (insn, &type, &dir); 2041 sb |= dir << 6; 2042 sb |= type << 7; 2043 2044 int size = size_from_suffix (insn, 0); 2045 sb |= size - 1; 2046 2047 uint8_t buffer[4]; 2048 int n_opr_bytes; 2049 expressionS exp; 2050 if (!lex_opr (buffer, &n_opr_bytes, &exp, false)) 2051 goto fail; 2052 2053 if (!lex_match (',')) 2054 goto fail; 2055 2056 long imm = -1; 2057 if (!lex_imm (&imm, NULL)) 2058 goto fail; 2059 2060 if (imm != 1 && imm != 2) 2061 goto fail; 2062 2063 if (imm == 2) 2064 sb |= 0x08; 2065 2066 char *f = s12z_new_insn (2 + n_opr_bytes); 2067 number_to_chars_bigendian (f++, insn->opc, 1); 2068 number_to_chars_bigendian (f++, sb, 1); 2069 emit_opr (f, buffer, n_opr_bytes, &exp); 2070 2071 return true; 2072 2073 fail: 2074 fail_line_pointer = input_line_pointer; 2075 input_line_pointer = ilp; 2076 return false; 2077 } 2078 2079 /* Shift instruction with a OPR operand */ 2080 static bool 2081 shift_opr_imm (const struct instruction *insn) 2082 { 2083 char *ilp = input_line_pointer; 2084 2085 short dir = -1; 2086 short type = -1; 2087 impute_shift_dir_and_type (insn, &type, &dir); 2088 2089 int Dd = 0; 2090 if (!lex_reg_name (REG_BIT_Dn, &Dd)) 2091 goto fail; 2092 2093 if (!lex_match (',')) 2094 goto fail; 2095 2096 int n_bytes = 2; 2097 2098 uint8_t buffer1[4]; 2099 int n_opr_bytes1; 2100 2101 expressionS exp1; 2102 if (!lex_opr (buffer1, &n_opr_bytes1, &exp1, false)) 2103 goto fail; 2104 2105 n_bytes += n_opr_bytes1; 2106 if (!lex_match (',')) 2107 goto fail; 2108 2109 uint8_t buffer2[4]; 2110 int n_opr_bytes2 = 0; 2111 expressionS exp2; 2112 long imm; 2113 bool immediate = false; 2114 if (lex_imm (&imm, NULL)) 2115 { 2116 immediate = true; 2117 } 2118 else if (!lex_opr (buffer2, &n_opr_bytes2, &exp2, false)) 2119 goto fail; 2120 2121 uint8_t sb = 0x20; 2122 2123 int size = size_from_suffix (insn, 0); 2124 2125 if (size != -1) 2126 sb |= size - 1; 2127 2128 sb |= dir << 6; 2129 sb |= type << 7; 2130 2131 if (immediate) 2132 { 2133 if (imm == 2 || imm == 1) 2134 { 2135 if (imm == 2) 2136 sb |= 0x08; 2137 } 2138 else 2139 { 2140 n_bytes++; 2141 sb |= 0x10; 2142 if (imm % 2) 2143 sb |= 0x08; 2144 } 2145 } 2146 else 2147 { 2148 n_bytes += n_opr_bytes2; 2149 sb |= 0x10; 2150 } 2151 2152 char *f = s12z_new_insn (n_bytes); 2153 number_to_chars_bigendian (f++, insn->opc | Dd, 1); 2154 number_to_chars_bigendian (f++, sb, 1); 2155 f = emit_opr (f, buffer1, n_opr_bytes1, &exp1); 2156 if (immediate) 2157 { 2158 if (imm != 1 && imm != 2) 2159 { 2160 number_to_chars_bigendian (f++, 0x70 | (imm >> 1), 1); 2161 } 2162 } 2163 else 2164 { 2165 f = emit_opr (f, buffer2, n_opr_bytes2, &exp2); 2166 } 2167 2168 return true; 2169 2170 fail: 2171 fail_line_pointer = input_line_pointer; 2172 input_line_pointer = ilp; 2173 return false; 2174 } 2175 2176 /* Shift instruction with a register operand */ 2177 static bool 2178 shift_reg (const struct instruction *insn) 2179 { 2180 short dir = -1; 2181 short type = -1; 2182 impute_shift_dir_and_type (insn, &type, &dir); 2183 2184 if (lex_shift_reg_imm1 (insn, type, dir)) 2185 return true; 2186 2187 return lex_shift_reg (insn, type, dir); 2188 } 2189 2190 static bool 2191 bm_regd_imm (const struct instruction *insn) 2192 { 2193 char *ilp = input_line_pointer; 2194 int Di = 0; 2195 if (!lex_reg_name (REG_BIT_Dn, &Di)) 2196 goto fail; 2197 2198 if (!lex_match (',')) 2199 goto fail; 2200 2201 long imm; 2202 if (!lex_imm (&imm, NULL)) 2203 goto fail; 2204 2205 2206 uint8_t bm = imm << 3; 2207 bm |= Di; 2208 2209 char *f = s12z_new_insn (2); 2210 number_to_chars_bigendian (f++, insn->opc, 1); 2211 number_to_chars_bigendian (f++, bm, 1); 2212 2213 return true; 2214 2215 fail: 2216 fail_line_pointer = input_line_pointer; 2217 input_line_pointer = ilp; 2218 return false; 2219 } 2220 2221 static bool 2222 bm_opr_reg (const struct instruction *insn) 2223 { 2224 char *ilp = input_line_pointer; 2225 2226 uint8_t buffer[4]; 2227 int n_opr_bytes; 2228 2229 expressionS exp; 2230 if (!lex_opr (buffer, &n_opr_bytes, &exp, false)) 2231 goto fail; 2232 2233 if (!lex_match (',')) 2234 goto fail; 2235 2236 int Dn = 0; 2237 if (!lex_reg_name (REG_BIT_Dn, &Dn)) 2238 goto fail; 2239 2240 uint8_t bm = Dn << 4; 2241 int size = size_from_suffix (insn, 0); 2242 bm |= (size - 1) << 2; 2243 bm |= 0x81; 2244 2245 char *f = s12z_new_insn (2 + n_opr_bytes); 2246 number_to_chars_bigendian (f++, insn->opc, 1); 2247 number_to_chars_bigendian (f++, bm, 1); 2248 2249 emit_opr (f, buffer, n_opr_bytes, &exp); 2250 2251 return true; 2252 2253 fail: 2254 fail_line_pointer = input_line_pointer; 2255 input_line_pointer = ilp; 2256 return false; 2257 } 2258 2259 2260 static bool 2261 bm_opr_imm (const struct instruction *insn) 2262 { 2263 char *ilp = input_line_pointer; 2264 2265 uint8_t buffer[4]; 2266 int n_opr_bytes; 2267 2268 expressionS exp; 2269 if (!lex_opr (buffer, &n_opr_bytes, &exp, false)) 2270 goto fail; 2271 2272 if (!lex_match (',')) 2273 goto fail; 2274 2275 2276 long imm; 2277 if (!lex_imm (&imm, NULL)) 2278 goto fail; 2279 2280 int size = size_from_suffix (insn, 0); 2281 2282 if (imm < 0 || imm >= size * 8) 2283 { 2284 as_bad (_("Immediate operand %ld is inappropriate for size of instruction"), imm); 2285 goto fail; 2286 } 2287 2288 uint8_t bm = 0x80; 2289 if (size == 2) 2290 bm |= 0x02; 2291 else if (size == 4) 2292 bm |= 0x08; 2293 bm |= (imm & 0x07) << 4; 2294 bm |= (imm >> 3); 2295 2296 2297 char *f = s12z_new_insn (2 + n_opr_bytes); 2298 number_to_chars_bigendian (f++, insn->opc, 1); 2299 number_to_chars_bigendian (f++, bm, 1); 2300 emit_opr (f, buffer, n_opr_bytes, &exp); 2301 2302 return true; 2303 2304 fail: 2305 fail_line_pointer = input_line_pointer; 2306 input_line_pointer = ilp; 2307 return false; 2308 } 2309 2310 2311 static bool 2312 bm_regd_reg (const struct instruction *insn) 2313 { 2314 char *ilp = input_line_pointer; 2315 int Di = 0; 2316 if (!lex_reg_name (REG_BIT_Dn, &Di)) 2317 goto fail; 2318 2319 if (!lex_match (',')) 2320 goto fail; 2321 2322 int Dn = 0; 2323 if (!lex_reg_name (REG_BIT_Dn, &Dn)) 2324 goto fail; 2325 2326 uint8_t bm = Dn << 4; 2327 bm |= 0x81; 2328 2329 uint8_t xb = Di | 0xb8; 2330 2331 char *f = s12z_new_insn (3); 2332 number_to_chars_bigendian (f++, insn->opc, 1); 2333 number_to_chars_bigendian (f++, bm, 1); 2334 number_to_chars_bigendian (f++, xb, 1); 2335 2336 return true; 2337 2338 fail: 2339 fail_line_pointer = input_line_pointer; 2340 input_line_pointer = ilp; 2341 return false; 2342 } 2343 2344 2345 2346 2347 2348 static bool 2349 bf_reg_opr_imm (const struct instruction *insn, short ie) 2350 { 2351 char *ilp = input_line_pointer; 2352 int Dd = 0; 2353 if (!lex_reg_name (REG_BIT_Dn, &Dd)) 2354 goto fail; 2355 2356 if (!lex_match (',')) 2357 goto fail; 2358 2359 uint8_t buffer[4]; 2360 int n_bytes; 2361 2362 expressionS exp; 2363 if (!lex_opr (buffer, &n_bytes, &exp, false)) 2364 goto fail; 2365 2366 if (!lex_match (',')) 2367 goto fail; 2368 2369 long width; 2370 if (!lex_imm (&width, NULL)) 2371 goto fail; 2372 2373 if (width < 0 || width > 31) 2374 { 2375 as_bad (_("Invalid width value for %s"), insn->name); 2376 goto fail; 2377 } 2378 2379 if (!lex_match (':')) 2380 goto fail; 2381 2382 long offset; 2383 if (!lex_constant (&offset)) 2384 goto fail; 2385 2386 if (offset < 0 || offset > 31) 2387 { 2388 as_bad (_("Invalid offset value for %s"), insn->name); 2389 goto fail; 2390 } 2391 2392 uint8_t i1 = width << 5; 2393 i1 |= offset; 2394 2395 int size = size_from_suffix (insn, 0); 2396 uint8_t bb = ie ? 0x80 : 0x00; 2397 bb |= 0x60; 2398 bb |= (size - 1) << 2; 2399 bb |= width >> 3; 2400 2401 char *f = s12z_new_insn (4 + n_bytes); 2402 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1); 2403 number_to_chars_bigendian (f++, 0x08 | Dd, 1); 2404 number_to_chars_bigendian (f++, bb, 1); 2405 number_to_chars_bigendian (f++, i1, 1); 2406 2407 emit_opr (f, buffer, n_bytes, &exp); 2408 2409 return true; 2410 2411 fail: 2412 fail_line_pointer = input_line_pointer; 2413 input_line_pointer = ilp; 2414 return false; 2415 } 2416 2417 2418 static bool 2419 bf_opr_reg_imm (const struct instruction *insn, short ie) 2420 { 2421 char *ilp = input_line_pointer; 2422 uint8_t buffer[4]; 2423 int n_bytes; 2424 expressionS exp; 2425 if (!lex_opr (buffer, &n_bytes, &exp, false)) 2426 goto fail; 2427 2428 if (!lex_match (',')) 2429 goto fail; 2430 2431 int Ds = 0; 2432 if (!lex_reg_name (REG_BIT_Dn, &Ds)) 2433 goto fail; 2434 2435 if (!lex_match (',')) 2436 goto fail; 2437 2438 long width; 2439 if (!lex_imm (&width, NULL)) 2440 goto fail; 2441 2442 if (width < 0 || width > 31) 2443 { 2444 as_bad (_("Invalid width value for %s"), insn->name); 2445 goto fail; 2446 } 2447 2448 if (!lex_match (':')) 2449 goto fail; 2450 2451 long offset; 2452 if (!lex_constant (&offset)) 2453 goto fail; 2454 2455 if (offset < 0 || offset > 31) 2456 { 2457 as_bad (_("Invalid offset value for %s"), insn->name); 2458 goto fail; 2459 } 2460 2461 uint8_t i1 = width << 5; 2462 i1 |= offset; 2463 2464 int size = size_from_suffix (insn, 0); 2465 uint8_t bb = ie ? 0x80 : 0x00; 2466 bb |= 0x70; 2467 bb |= (size - 1) << 2; 2468 bb |= width >> 3; 2469 2470 char *f = s12z_new_insn (4 + n_bytes); 2471 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1); 2472 number_to_chars_bigendian (f++, 0x08 | Ds, 1); 2473 number_to_chars_bigendian (f++, bb, 1); 2474 number_to_chars_bigendian (f++, i1, 1); 2475 2476 emit_opr (f, buffer, n_bytes, &exp); 2477 2478 return true; 2479 2480 fail: 2481 fail_line_pointer = input_line_pointer; 2482 input_line_pointer = ilp; 2483 return false; 2484 } 2485 2486 2487 2488 static bool 2489 bf_reg_reg_imm (const struct instruction *insn, short ie) 2490 { 2491 char *ilp = input_line_pointer; 2492 int Dd = 0; 2493 if (!lex_reg_name (REG_BIT_Dn, &Dd)) 2494 goto fail; 2495 2496 if (!lex_match (',')) 2497 goto fail; 2498 2499 int Ds = 0; 2500 if (!lex_reg_name (REG_BIT_Dn, &Ds)) 2501 goto fail; 2502 2503 if (!lex_match (',')) 2504 goto fail; 2505 2506 long width; 2507 if (!lex_imm (&width, NULL)) 2508 goto fail; 2509 2510 if (width < 0 || width > 31) 2511 { 2512 as_bad (_("Invalid width value for %s"), insn->name); 2513 goto fail; 2514 } 2515 2516 if (!lex_match (':')) 2517 goto fail; 2518 2519 long offset; 2520 if (!lex_constant (&offset)) 2521 goto fail; 2522 2523 if (offset < 0 || offset > 31) 2524 { 2525 as_bad (_("Invalid offset value for %s"), insn->name); 2526 goto fail; 2527 } 2528 2529 uint8_t bb = ie ? 0x80 : 0x00; 2530 bb |= 0x20; 2531 bb |= Ds << 2; 2532 bb |= width >> 3; 2533 2534 uint8_t i1 = width << 5; 2535 i1 |= offset; 2536 2537 char *f = s12z_new_insn (4); 2538 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1); 2539 number_to_chars_bigendian (f++, 0x08 | Dd, 1); 2540 number_to_chars_bigendian (f++, bb, 1); 2541 number_to_chars_bigendian (f++, i1, 1); 2542 2543 return true; 2544 2545 fail: 2546 fail_line_pointer = input_line_pointer; 2547 input_line_pointer = ilp; 2548 return false; 2549 } 2550 2551 static bool 2552 bf_reg_reg_reg (const struct instruction *insn ATTRIBUTE_UNUSED, short ie) 2553 { 2554 char *ilp = input_line_pointer; 2555 int Dd = 0; 2556 if (!lex_reg_name (REG_BIT_Dn, &Dd)) 2557 goto fail; 2558 2559 if (!lex_match (',')) 2560 goto fail; 2561 2562 int Ds = 0; 2563 if (!lex_reg_name (REG_BIT_Dn, &Ds)) 2564 goto fail; 2565 2566 if (!lex_match (',')) 2567 goto fail; 2568 2569 int Dp = 0; 2570 if (!lex_reg_name ((0x01u << REG_D2) | 2571 (0x01u << REG_D3) | 2572 (0x01u << REG_D4) | 2573 (0x01u << REG_D5), 2574 &Dp)) 2575 goto fail; 2576 2577 uint8_t bb = ie ? 0x80 : 0x00; 2578 bb |= Ds << 2; 2579 bb |= Dp; 2580 2581 char *f = s12z_new_insn (3); 2582 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1); 2583 number_to_chars_bigendian (f++, 0x08 | Dd, 1); 2584 number_to_chars_bigendian (f++, bb , 1); 2585 2586 return true; 2587 2588 fail: 2589 fail_line_pointer = input_line_pointer; 2590 input_line_pointer = ilp; 2591 return false; 2592 } 2593 2594 static bool 2595 bf_opr_reg_reg (const struct instruction *insn, short ie) 2596 { 2597 char *ilp = input_line_pointer; 2598 2599 uint8_t buffer[4]; 2600 int n_bytes; 2601 expressionS exp; 2602 if (!lex_opr (buffer, &n_bytes, &exp, false)) 2603 goto fail; 2604 2605 if (!lex_match (',')) 2606 goto fail; 2607 2608 2609 int Ds = 0; 2610 if (!lex_reg_name (REG_BIT_Dn, &Ds)) 2611 goto fail; 2612 2613 if (!lex_match (',')) 2614 goto fail; 2615 2616 2617 int Dp = 0; 2618 if (!lex_reg_name ((0x01u << REG_D2) | 2619 (0x01u << REG_D3) | 2620 (0x01u << REG_D4) | 2621 (0x01u << REG_D5), 2622 &Dp)) 2623 goto fail; 2624 2625 int size = size_from_suffix (insn, 0); 2626 uint8_t bb = ie ? 0x80 : 0x00; 2627 bb |= 0x50; 2628 bb |= Dp; 2629 bb |= (size - 1) << 2; 2630 2631 char *f = s12z_new_insn (3 + n_bytes); 2632 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1); 2633 number_to_chars_bigendian (f++, 0x08 | Ds, 1); 2634 number_to_chars_bigendian (f++, bb , 1); 2635 2636 emit_opr (f, buffer, n_bytes, &exp); 2637 2638 return true; 2639 2640 fail: 2641 fail_line_pointer = input_line_pointer; 2642 input_line_pointer = ilp; 2643 return false; 2644 } 2645 2646 2647 static bool 2648 bf_reg_opr_reg (const struct instruction *insn, short ie) 2649 { 2650 char *ilp = input_line_pointer; 2651 int Dd = 0; 2652 if (!lex_reg_name (REG_BIT_Dn, &Dd)) 2653 goto fail; 2654 2655 if (!lex_match (',')) 2656 goto fail; 2657 2658 2659 uint8_t buffer[4]; 2660 int n_bytes; 2661 expressionS exp; 2662 if (!lex_opr (buffer, &n_bytes, &exp, false)) 2663 goto fail; 2664 2665 if (!lex_match (',')) 2666 goto fail; 2667 2668 int Dp = 0; 2669 if (!lex_reg_name ((0x01u << REG_D2) | 2670 (0x01u << REG_D3) | 2671 (0x01u << REG_D4) | 2672 (0x01u << REG_D5), 2673 &Dp)) 2674 goto fail; 2675 2676 int size = size_from_suffix (insn, 0); 2677 uint8_t bb = ie ? 0x80 : 0x00; 2678 bb |= 0x40; 2679 bb |= Dp; 2680 bb |= (size - 1) << 2; 2681 2682 char *f = s12z_new_insn (3 + n_bytes); 2683 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1); 2684 number_to_chars_bigendian (f++, 0x08 | Dd, 1); 2685 number_to_chars_bigendian (f++, bb , 1); 2686 2687 emit_opr (f, buffer, n_bytes, &exp); 2688 2689 return true; 2690 2691 fail: 2692 fail_line_pointer = input_line_pointer; 2693 input_line_pointer = ilp; 2694 return false; 2695 } 2696 2697 2698 2699 static bool 2700 bfe_reg_reg_reg (const struct instruction *insn) 2701 { 2702 return bf_reg_reg_reg (insn, 0); 2703 } 2704 2705 static bool 2706 bfi_reg_reg_reg (const struct instruction *insn) 2707 { 2708 return bf_reg_reg_reg (insn, 1); 2709 } 2710 2711 static bool 2712 bfe_reg_reg_imm (const struct instruction *insn) 2713 { 2714 return bf_reg_reg_imm (insn, 0); 2715 } 2716 2717 static bool 2718 bfi_reg_reg_imm (const struct instruction *insn) 2719 { 2720 return bf_reg_reg_imm (insn, 1); 2721 } 2722 2723 2724 static bool 2725 bfe_reg_opr_reg (const struct instruction *insn) 2726 { 2727 return bf_reg_opr_reg (insn, 0); 2728 } 2729 2730 static bool 2731 bfi_reg_opr_reg (const struct instruction *insn) 2732 { 2733 return bf_reg_opr_reg (insn, 1); 2734 } 2735 2736 2737 static bool 2738 bfe_opr_reg_reg (const struct instruction *insn) 2739 { 2740 return bf_opr_reg_reg (insn, 0); 2741 } 2742 2743 static bool 2744 bfi_opr_reg_reg (const struct instruction *insn) 2745 { 2746 return bf_opr_reg_reg (insn, 1); 2747 } 2748 2749 static bool 2750 bfe_reg_opr_imm (const struct instruction *insn) 2751 { 2752 return bf_reg_opr_imm (insn, 0); 2753 } 2754 2755 static bool 2756 bfi_reg_opr_imm (const struct instruction *insn) 2757 { 2758 return bf_reg_opr_imm (insn, 1); 2759 } 2760 2761 static bool 2762 bfe_opr_reg_imm (const struct instruction *insn) 2763 { 2764 return bf_opr_reg_imm (insn, 0); 2765 } 2766 2767 static bool 2768 bfi_opr_reg_imm (const struct instruction *insn) 2769 { 2770 return bf_opr_reg_imm (insn, 1); 2771 } 2772 2773 2774 2775 2776 static bool 2777 tb_reg_rel (const struct instruction *insn) 2778 { 2779 char *ilp = input_line_pointer; 2780 2781 int reg; 2782 if (!lex_reg_name (REG_BIT_Dn | REG_BIT_XY, ®)) 2783 goto fail; 2784 2785 if (!lex_match (',')) 2786 goto fail; 2787 2788 bool long_displacement; 2789 expressionS exp; 2790 if (! lex_15_bit_offset (&long_displacement, &exp)) 2791 goto fail; 2792 2793 uint8_t lb = 0x00; 2794 if (reg == REG_X || reg == REG_Y) 2795 { 2796 lb |= 0x08; 2797 } 2798 else 2799 { 2800 lb |= reg; 2801 } 2802 if (reg == REG_Y) 2803 lb |= 0x01; 2804 2805 if (startswith (insn->name + 2, "ne")) 2806 lb |= 0x00 << 4; 2807 else if (startswith (insn->name + 2, "eq")) 2808 lb |= 0x01 << 4; 2809 else if (startswith (insn->name + 2, "pl")) 2810 lb |= 0x02 << 4; 2811 else if (startswith (insn->name + 2, "mi")) 2812 lb |= 0x03 << 4; 2813 else if (startswith (insn->name + 2, "gt")) 2814 lb |= 0x04 << 4; 2815 else if (startswith (insn->name + 2, "le")) 2816 lb |= 0x05 << 4; 2817 2818 switch (insn->name[0]) 2819 { 2820 case 'd': 2821 lb |= 0x80; 2822 break; 2823 case 't': 2824 break; 2825 default: 2826 gas_assert (0); 2827 break; 2828 }; 2829 2830 char *f = s12z_new_insn (long_displacement ? 4 : 3); 2831 number_to_chars_bigendian (f++, insn->opc, 1); 2832 number_to_chars_bigendian (f++, lb, 1); 2833 2834 emit_15_bit_offset (f, 4, &exp); 2835 2836 return true; 2837 2838 fail: 2839 fail_line_pointer = input_line_pointer; 2840 input_line_pointer = ilp; 2841 return false; 2842 } 2843 2844 2845 static bool 2846 tb_opr_rel (const struct instruction *insn) 2847 { 2848 char *ilp = input_line_pointer; 2849 2850 uint8_t buffer[4]; 2851 int n_bytes; 2852 expressionS exp; 2853 if (!lex_opr (buffer, &n_bytes, &exp, false)) 2854 goto fail; 2855 2856 if (!lex_match (',')) 2857 goto fail; 2858 2859 bool long_displacement; 2860 expressionS exp2; 2861 if (! lex_15_bit_offset (&long_displacement, &exp2)) 2862 goto fail; 2863 2864 uint8_t lb = 0x0C; 2865 2866 if (startswith (insn->name + 2, "ne")) 2867 lb |= 0x00 << 4; 2868 else if (startswith (insn->name + 2, "eq")) 2869 lb |= 0x01 << 4; 2870 else if (startswith (insn->name + 2, "pl")) 2871 lb |= 0x02 << 4; 2872 else if (startswith (insn->name + 2, "mi")) 2873 lb |= 0x03 << 4; 2874 else if (startswith (insn->name + 2, "gt")) 2875 lb |= 0x04 << 4; 2876 else if (startswith (insn->name + 2, "le")) 2877 lb |= 0x05 << 4; 2878 2879 switch (insn->name[0]) 2880 { 2881 case 'd': 2882 lb |= 0x80; 2883 break; 2884 case 't': 2885 break; 2886 default: 2887 gas_assert (0); 2888 break; 2889 }; 2890 2891 int size = size_from_suffix (insn, 0); 2892 2893 lb |= size -1; 2894 2895 char *f = s12z_new_insn (n_bytes + (long_displacement ? 4 : 3)); 2896 number_to_chars_bigendian (f++, insn->opc, 1); 2897 number_to_chars_bigendian (f++, lb, 1); 2898 f = emit_opr (f, buffer, n_bytes, &exp); 2899 2900 emit_15_bit_offset (f, n_bytes + 4, &exp2); 2901 2902 return true; 2903 2904 fail: 2905 fail_line_pointer = input_line_pointer; 2906 input_line_pointer = ilp; 2907 return false; 2908 } 2909 2910 2911 2912 2913 static bool 2914 test_br_reg_reg_rel (const struct instruction *insn) 2915 { 2916 char *ilp = input_line_pointer; 2917 2918 int Di = 0; 2919 if (!lex_reg_name (REG_BIT_Dn, &Di)) 2920 goto fail; 2921 2922 if (!lex_match (',')) 2923 goto fail; 2924 2925 2926 int Dn = 0; 2927 if (!lex_reg_name (REG_BIT_Dn, &Dn)) 2928 goto fail; 2929 2930 if (!lex_match (',')) 2931 goto fail; 2932 2933 2934 bool long_displacement; 2935 expressionS exp; 2936 if (! lex_15_bit_offset (&long_displacement, &exp)) 2937 goto fail; 2938 2939 uint8_t bm = 0x81; 2940 uint8_t xb = 0xb8; 2941 2942 bm |= Dn << 4; 2943 xb |= Di; 2944 2945 char *f = s12z_new_insn (long_displacement ? 5 : 4); 2946 number_to_chars_bigendian (f++, insn->opc, 1); 2947 number_to_chars_bigendian (f++, bm, 1); 2948 number_to_chars_bigendian (f++, xb, 1); 2949 2950 emit_15_bit_offset (f, 5, &exp); 2951 2952 return true; 2953 2954 fail: 2955 fail_line_pointer = input_line_pointer; 2956 input_line_pointer = ilp; 2957 return false; 2958 } 2959 2960 static bool 2961 test_br_opr_reg_rel (const struct instruction *insn) 2962 { 2963 char *ilp = input_line_pointer; 2964 2965 uint8_t buffer[4]; 2966 int n_bytes; 2967 expressionS exp; 2968 if (!lex_opr (buffer, &n_bytes, &exp, false)) 2969 goto fail; 2970 2971 if (!lex_match (',')) 2972 goto fail; 2973 2974 int Dn = 0; 2975 if (!lex_reg_name (REG_BIT_Dn, &Dn)) 2976 goto fail; 2977 2978 if (!lex_match (',')) 2979 goto fail; 2980 2981 uint8_t bm = 0x81; 2982 bm |= Dn << 4; 2983 int size = size_from_suffix (insn, 0); 2984 bm |= (size -1) << 2; 2985 2986 bool long_displacement; 2987 2988 expressionS exp2; 2989 if (! lex_15_bit_offset (&long_displacement, &exp2)) 2990 goto fail; 2991 2992 int n = n_bytes + (long_displacement ? 4 : 3); 2993 char *f = s12z_new_insn (n); 2994 number_to_chars_bigendian (f++, insn->opc, 1); 2995 number_to_chars_bigendian (f++, bm, 1); 2996 f = emit_opr (f, buffer, n_bytes, &exp); 2997 2998 emit_15_bit_offset (f, n, &exp2); 2999 3000 return true; 3001 3002 fail: 3003 fail_line_pointer = input_line_pointer; 3004 input_line_pointer = ilp; 3005 return false; 3006 } 3007 3008 3009 static bool 3010 test_br_opr_imm_rel (const struct instruction *insn) 3011 { 3012 char *ilp = input_line_pointer; 3013 3014 uint8_t buffer[4]; 3015 int n_bytes; 3016 expressionS exp; 3017 if (!lex_opr (buffer, &n_bytes, &exp, false)) 3018 goto fail; 3019 3020 if (!lex_match (',')) 3021 goto fail; 3022 3023 long imm; 3024 if (!lex_imm (&imm, NULL)) 3025 goto fail; 3026 3027 if (imm < 0 || imm > 31) 3028 goto fail; 3029 3030 if (!lex_match (',')) 3031 goto fail; 3032 3033 bool long_displacement; 3034 expressionS exp2; 3035 if (! lex_15_bit_offset (&long_displacement, &exp2)) 3036 goto fail; 3037 3038 int size = size_from_suffix (insn, 0); 3039 3040 uint8_t bm = 0x80; 3041 bm |= (imm & 0x07) << 4; 3042 bm |= (imm >> 3) & 0x03; 3043 if (size == 4) 3044 bm |= 0x08; 3045 else if (size == 2) 3046 bm |= 0x02; 3047 3048 char *f = s12z_new_insn (n_bytes + (long_displacement ? 4 : 3)); 3049 number_to_chars_bigendian (f++, insn->opc, 1); 3050 number_to_chars_bigendian (f++, bm, 1); 3051 f = emit_opr (f, buffer, n_bytes, &exp); 3052 3053 emit_15_bit_offset (f, n_bytes + 4, &exp2); 3054 3055 return true; 3056 3057 fail: 3058 fail_line_pointer = input_line_pointer; 3059 input_line_pointer = ilp; 3060 return false; 3061 } 3062 3063 3064 static bool 3065 test_br_reg_imm_rel (const struct instruction *insn) 3066 { 3067 char *ilp = input_line_pointer; 3068 3069 int Di = 0; 3070 if (!lex_reg_name (REG_BIT_Dn, &Di)) 3071 goto fail; 3072 3073 if (!lex_match (',')) 3074 goto fail; 3075 3076 long imm; 3077 if (!lex_imm (&imm, NULL)) 3078 goto fail; 3079 3080 if (imm < 0 || imm > 31) 3081 goto fail; 3082 3083 3084 if (!lex_match (',')) 3085 goto fail; 3086 3087 bool long_displacement; 3088 expressionS exp; 3089 if (! lex_15_bit_offset (&long_displacement, &exp)) 3090 goto fail; 3091 3092 uint8_t bm = Di; 3093 bm |= imm << 3; 3094 3095 char *f = s12z_new_insn (long_displacement ? 4 : 3); 3096 number_to_chars_bigendian (f++, insn->opc, 1); 3097 number_to_chars_bigendian (f++, bm, 1); 3098 3099 emit_15_bit_offset (f, 4, &exp); 3100 3101 return true; 3102 3103 fail: 3104 fail_line_pointer = input_line_pointer; 3105 input_line_pointer = ilp; 3106 return false; 3107 } 3108 3109 3110 3111 3112 static const struct instruction opcodes[] = { 3113 {"bgnd", 1, 0x00, no_operands, 0}, 3114 {"nop", 1, 0x01, no_operands, 0}, 3115 3116 {"brclr", 1, 0x02, test_br_reg_reg_rel, 0}, 3117 {"brset", 1, 0x03, test_br_reg_reg_rel, 0}, 3118 3119 {"brclr", 1, 0x02, test_br_reg_imm_rel, 0}, 3120 {"brset", 1, 0x03, test_br_reg_imm_rel, 0}, 3121 3122 {"brclr.b", 1, 0x02, test_br_opr_reg_rel, 0}, 3123 {"brclr.w", 1, 0x02, test_br_opr_reg_rel, 0}, 3124 {"brclr.l", 1, 0x02, test_br_opr_reg_rel, 0}, 3125 3126 {"brset.b", 1, 0x03, test_br_opr_reg_rel, 0}, 3127 {"brset.w", 1, 0x03, test_br_opr_reg_rel, 0}, 3128 {"brset.l", 1, 0x03, test_br_opr_reg_rel, 0}, 3129 3130 {"brclr.b", 1, 0x02, test_br_opr_imm_rel, 0}, 3131 {"brclr.w", 1, 0x02, test_br_opr_imm_rel, 0}, 3132 {"brclr.l", 1, 0x02, test_br_opr_imm_rel, 0}, 3133 3134 {"brset.b", 1, 0x03, test_br_opr_imm_rel, 0}, 3135 {"brset.w", 1, 0x03, test_br_opr_imm_rel, 0}, 3136 {"brset.l", 1, 0x03, test_br_opr_imm_rel, 0}, 3137 3138 {"psh", 1, 0x04, psh_pull, 0}, 3139 {"pul", 1, 0x04, psh_pull, 0}, 3140 3141 {"rts", 1, 0x05, no_operands, 0}, 3142 {"lea", 1, 0x06, reg67sxy_opr, 0}, 3143 3144 {"dbne", 1, 0x0b, tb_reg_rel, 0}, 3145 {"dbeq", 1, 0x0b, tb_reg_rel, 0}, 3146 {"dbpl", 1, 0x0b, tb_reg_rel, 0}, 3147 {"dbmi", 1, 0x0b, tb_reg_rel, 0}, 3148 {"dbgt", 1, 0x0b, tb_reg_rel, 0}, 3149 {"dble", 1, 0x0b, tb_reg_rel, 0}, 3150 3151 {"dbne.b", 1, 0x0b, tb_opr_rel, 0}, 3152 {"dbeq.b", 1, 0x0b, tb_opr_rel, 0}, 3153 {"dbpl.b", 1, 0x0b, tb_opr_rel, 0}, 3154 {"dbmi.b", 1, 0x0b, tb_opr_rel, 0}, 3155 {"dbgt.b", 1, 0x0b, tb_opr_rel, 0}, 3156 {"dble.b", 1, 0x0b, tb_opr_rel, 0}, 3157 3158 {"dbne.w", 1, 0x0b, tb_opr_rel, 0}, 3159 {"dbeq.w", 1, 0x0b, tb_opr_rel, 0}, 3160 {"dbpl.w", 1, 0x0b, tb_opr_rel, 0}, 3161 {"dbmi.w", 1, 0x0b, tb_opr_rel, 0}, 3162 {"dbgt.w", 1, 0x0b, tb_opr_rel, 0}, 3163 {"dble.w", 1, 0x0b, tb_opr_rel, 0}, 3164 3165 {"dbne.p", 1, 0x0b, tb_opr_rel, 0}, 3166 {"dbeq.p", 1, 0x0b, tb_opr_rel, 0}, 3167 {"dbpl.p", 1, 0x0b, tb_opr_rel, 0}, 3168 {"dbmi.p", 1, 0x0b, tb_opr_rel, 0}, 3169 {"dbgt.p", 1, 0x0b, tb_opr_rel, 0}, 3170 {"dble.p", 1, 0x0b, tb_opr_rel, 0}, 3171 3172 {"dbne.l", 1, 0x0b, tb_opr_rel, 0}, 3173 {"dbeq.l", 1, 0x0b, tb_opr_rel, 0}, 3174 {"dbpl.l", 1, 0x0b, tb_opr_rel, 0}, 3175 {"dbmi.l", 1, 0x0b, tb_opr_rel, 0}, 3176 {"dbgt.l", 1, 0x0b, tb_opr_rel, 0}, 3177 {"dble.l", 1, 0x0b, tb_opr_rel, 0}, 3178 3179 {"tbne", 1, 0x0b, tb_reg_rel, 0}, 3180 {"tbeq", 1, 0x0b, tb_reg_rel, 0}, 3181 {"tbpl", 1, 0x0b, tb_reg_rel, 0}, 3182 {"tbmi", 1, 0x0b, tb_reg_rel, 0}, 3183 {"tbgt", 1, 0x0b, tb_reg_rel, 0}, 3184 {"tble", 1, 0x0b, tb_reg_rel, 0}, 3185 3186 {"tbne.b", 1, 0x0b, tb_opr_rel, 0}, 3187 {"tbeq.b", 1, 0x0b, tb_opr_rel, 0}, 3188 {"tbpl.b", 1, 0x0b, tb_opr_rel, 0}, 3189 {"tbmi.b", 1, 0x0b, tb_opr_rel, 0}, 3190 {"tbgt.b", 1, 0x0b, tb_opr_rel, 0}, 3191 {"tble.b", 1, 0x0b, tb_opr_rel, 0}, 3192 3193 {"tbne.w", 1, 0x0b, tb_opr_rel, 0}, 3194 {"tbeq.w", 1, 0x0b, tb_opr_rel, 0}, 3195 {"tbpl.w", 1, 0x0b, tb_opr_rel, 0}, 3196 {"tbmi.w", 1, 0x0b, tb_opr_rel, 0}, 3197 {"tbgt.w", 1, 0x0b, tb_opr_rel, 0}, 3198 {"tble.w", 1, 0x0b, tb_opr_rel, 0}, 3199 3200 {"tbne.p", 1, 0x0b, tb_opr_rel, 0}, 3201 {"tbeq.p", 1, 0x0b, tb_opr_rel, 0}, 3202 {"tbpl.p", 1, 0x0b, tb_opr_rel, 0}, 3203 {"tbmi.p", 1, 0x0b, tb_opr_rel, 0}, 3204 {"tbgt.p", 1, 0x0b, tb_opr_rel, 0}, 3205 {"tble.p", 1, 0x0b, tb_opr_rel, 0}, 3206 3207 {"tbne.l", 1, 0x0b, tb_opr_rel, 0}, 3208 {"tbeq.l", 1, 0x0b, tb_opr_rel, 0}, 3209 {"tbpl.l", 1, 0x0b, tb_opr_rel, 0}, 3210 {"tbmi.l", 1, 0x0b, tb_opr_rel, 0}, 3211 {"tbgt.l", 1, 0x0b, tb_opr_rel, 0}, 3212 {"tble.l", 1, 0x0b, tb_opr_rel, 0}, 3213 3214 {"mov.b", 1, 0x0c, imm_opr, 0}, 3215 {"mov.w", 1, 0x0d, imm_opr, 0}, 3216 {"mov.p", 1, 0x0e, imm_opr, 0}, 3217 {"mov.l", 1, 0x0f, imm_opr, 0}, 3218 3219 {"rol", 1, 0x10, rol, 0}, 3220 {"rol.b", 1, 0x10, rol, 0}, 3221 {"rol.w", 1, 0x10, rol, 0}, 3222 {"rol.p", 1, 0x10, rol, 0}, 3223 {"rol.l", 1, 0x10, rol, 0}, 3224 3225 {"ror", 1, 0x10, ror, 0}, 3226 {"ror.b", 1, 0x10, ror, 0}, 3227 {"ror.w", 1, 0x10, ror, 0}, 3228 {"ror.p", 1, 0x10, ror, 0}, 3229 {"ror.l", 1, 0x10, ror, 0}, 3230 3231 {"lsl", 1, 0x10, shift_reg, 0}, 3232 {"lsr", 1, 0x10, shift_reg, 0}, 3233 {"asl", 1, 0x10, shift_reg, 0}, 3234 {"asr", 1, 0x10, shift_reg, 0}, 3235 3236 {"lsl.b", 1, 0x10, shift_two_operand, 0}, 3237 {"lsl.w", 1, 0x10, shift_two_operand, 0}, 3238 {"lsl.p", 1, 0x10, shift_two_operand, 0}, 3239 {"lsl.l", 1, 0x10, shift_two_operand, 0}, 3240 {"asl.b", 1, 0x10, shift_two_operand, 0}, 3241 {"asl.w", 1, 0x10, shift_two_operand, 0}, 3242 {"asl.p", 1, 0x10, shift_two_operand, 0}, 3243 {"asl.l", 1, 0x10, shift_two_operand, 0}, 3244 3245 {"lsr.b", 1, 0x10, shift_two_operand, 0}, 3246 {"lsr.w", 1, 0x10, shift_two_operand, 0}, 3247 {"lsr.p", 1, 0x10, shift_two_operand, 0}, 3248 {"lsr.l", 1, 0x10, shift_two_operand, 0}, 3249 {"asr.b", 1, 0x10, shift_two_operand, 0}, 3250 {"asr.w", 1, 0x10, shift_two_operand, 0}, 3251 {"asr.p", 1, 0x10, shift_two_operand, 0}, 3252 {"asr.l", 1, 0x10, shift_two_operand, 0}, 3253 3254 {"lsl.b", 1, 0x10, shift_opr_imm, 0}, 3255 {"lsl.w", 1, 0x10, shift_opr_imm, 0}, 3256 {"lsl.p", 1, 0x10, shift_opr_imm, 0}, 3257 {"lsl.l", 1, 0x10, shift_opr_imm, 0}, 3258 {"asl.b", 1, 0x10, shift_opr_imm, 0}, 3259 {"asl.w", 1, 0x10, shift_opr_imm, 0}, 3260 {"asl.p", 1, 0x10, shift_opr_imm, 0}, 3261 {"asl.l", 1, 0x10, shift_opr_imm, 0}, 3262 3263 {"lsr.b", 1, 0x10, shift_opr_imm, 0}, 3264 {"lsr.w", 1, 0x10, shift_opr_imm, 0}, 3265 {"lsr.p", 1, 0x10, shift_opr_imm, 0}, 3266 {"lsr.l", 1, 0x10, shift_opr_imm, 0}, 3267 {"asr.b", 1, 0x10, shift_opr_imm, 0}, 3268 {"asr.w", 1, 0x10, shift_opr_imm, 0}, 3269 {"asr.p", 1, 0x10, shift_opr_imm, 0}, 3270 {"asr.l", 1, 0x10, shift_opr_imm, 0}, 3271 3272 {"mov.b", 1, 0x1c, opr_opr, 0}, 3273 {"mov.w", 1, 0x1d, opr_opr, 0}, 3274 {"mov.p", 1, 0x1e, opr_opr, 0}, 3275 {"mov.l", 1, 0x1f, opr_opr, 0}, 3276 3277 {"bra", 1, 0x20, rel, 0}, 3278 {"bsr", 1, 0x21, rel, 0}, 3279 {"bhi", 1, 0x22, rel, 0}, 3280 {"bls", 1, 0x23, rel, 0}, 3281 {"bcc", 1, 0x24, rel, 0}, 3282 {"bhs", 1, 0x24, rel, 0}, /* Alias for bcc */ 3283 {"bcs", 1, 0x25, rel, 0}, 3284 {"blo", 1, 0x25, rel, 0}, /* Alias for bcs */ 3285 {"bne", 1, 0x26, rel, 0}, 3286 {"beq", 1, 0x27, rel, 0}, 3287 {"bvc", 1, 0x28, rel, 0}, 3288 {"bvs", 1, 0x29, rel, 0}, 3289 {"bpl", 1, 0x2a, rel, 0}, 3290 {"bmi", 1, 0x2b, rel, 0}, 3291 {"bge", 1, 0x2c, rel, 0}, 3292 {"blt", 1, 0x2d, rel, 0}, 3293 {"bgt", 1, 0x2e, rel, 0}, 3294 {"ble", 1, 0x2f, rel, 0}, 3295 3296 {"inc", 1, 0x30, reg_inh, 0}, 3297 {"clr", 1, 0x38, reg_inh, 0}, 3298 {"dec", 1, 0x40, reg_inh, 0}, 3299 3300 {"muls", 1, 0x48, mul_reg_reg_reg, 0}, 3301 {"mulu", 1, 0x48, mul_reg_reg_reg, 0}, 3302 3303 {"muls.b", 1, 0x48, mul_reg_reg_opr, 0}, 3304 {"muls.w", 1, 0x48, mul_reg_reg_opr, 0}, 3305 {"muls.l", 1, 0x48, mul_reg_reg_opr, 0}, 3306 3307 {"mulu.b", 1, 0x48, mul_reg_reg_opr, 0}, 3308 {"mulu.w", 1, 0x48, mul_reg_reg_opr, 0}, 3309 {"mulu.l", 1, 0x48, mul_reg_reg_opr, 0}, 3310 3311 {"muls.b", 1, 0x48, mul_reg_reg_imm, 0}, 3312 {"muls.w", 1, 0x48, mul_reg_reg_imm, 0}, 3313 {"muls.l", 1, 0x48, mul_reg_reg_imm, 0}, 3314 3315 {"mulu.b", 1, 0x48, mul_reg_reg_imm, 0}, 3316 {"mulu.w", 1, 0x48, mul_reg_reg_imm, 0}, 3317 {"mulu.l", 1, 0x48, mul_reg_reg_imm, 0}, 3318 3319 {"muls.bb", 1, 0x48, mul_reg_opr_opr, 0}, 3320 {"muls.bw", 1, 0x48, mul_reg_opr_opr, 0}, 3321 {"muls.bp", 1, 0x48, mul_reg_opr_opr, 0}, 3322 {"muls.bl", 1, 0x48, mul_reg_opr_opr, 0}, 3323 3324 {"muls.wb", 1, 0x48, mul_reg_opr_opr, 0}, 3325 {"muls.ww", 1, 0x48, mul_reg_opr_opr, 0}, 3326 {"muls.wp", 1, 0x48, mul_reg_opr_opr, 0}, 3327 {"muls.wl", 1, 0x48, mul_reg_opr_opr, 0}, 3328 3329 {"muls.pb", 1, 0x48, mul_reg_opr_opr, 0}, 3330 {"muls.pw", 1, 0x48, mul_reg_opr_opr, 0}, 3331 {"muls.pp", 1, 0x48, mul_reg_opr_opr, 0}, 3332 {"muls.pl", 1, 0x48, mul_reg_opr_opr, 0}, 3333 3334 {"muls.lb", 1, 0x48, mul_reg_opr_opr, 0}, 3335 {"muls.lw", 1, 0x48, mul_reg_opr_opr, 0}, 3336 {"muls.lp", 1, 0x48, mul_reg_opr_opr, 0}, 3337 {"muls.ll", 1, 0x48, mul_reg_opr_opr, 0}, 3338 3339 {"mulu.bb", 1, 0x48, mul_reg_opr_opr, 0}, 3340 {"mulu.bw", 1, 0x48, mul_reg_opr_opr, 0}, 3341 {"mulu.bp", 1, 0x48, mul_reg_opr_opr, 0}, 3342 {"mulu.bl", 1, 0x48, mul_reg_opr_opr, 0}, 3343 3344 {"mulu.wb", 1, 0x48, mul_reg_opr_opr, 0}, 3345 {"mulu.ww", 1, 0x48, mul_reg_opr_opr, 0}, 3346 {"mulu.wp", 1, 0x48, mul_reg_opr_opr, 0}, 3347 {"mulu.wl", 1, 0x48, mul_reg_opr_opr, 0}, 3348 3349 {"mulu.pb", 1, 0x48, mul_reg_opr_opr, 0}, 3350 {"mulu.pw", 1, 0x48, mul_reg_opr_opr, 0}, 3351 {"mulu.pp", 1, 0x48, mul_reg_opr_opr, 0}, 3352 {"mulu.pl", 1, 0x48, mul_reg_opr_opr, 0}, 3353 3354 {"mulu.lb", 1, 0x48, mul_reg_opr_opr, 0}, 3355 {"mulu.lw", 1, 0x48, mul_reg_opr_opr, 0}, 3356 {"mulu.lp", 1, 0x48, mul_reg_opr_opr, 0}, 3357 {"mulu.ll", 1, 0x48, mul_reg_opr_opr, 0}, 3358 3359 {"add", 1, 0x50, regd_imm, 0}, 3360 {"and", 1, 0x58, regd_imm, 0}, 3361 3362 {"add", 1, 0x60, regd_opr, 0}, 3363 {"and", 1, 0x68, regd_opr, 0}, 3364 3365 {"sub", 1, 0x70, regd_imm, 0}, 3366 {"or", 1, 0x78, regd_imm, 0}, 3367 3368 {"sub", 1, 0x80, regd_opr, 0}, 3369 {"or", 1, 0x88, regd_opr, 0}, 3370 3371 {"ld", 1, 0x90, regdxy_imm, 0}, 3372 3373 {"clr", 1, 0x9a, clr_xy, 0}, 3374 {"tfr", 1, 0x9e, tfr, 0}, 3375 {"zex", 1, 0x9e, tfr, 0}, 3376 3377 {"ld", 1, 0xa0, regdxy_opr_src, 0xb0}, 3378 3379 {"jmp", 1, 0xaa, opr, 0xba}, 3380 {"jsr", 1, 0xab, opr, 0xbb}, 3381 3382 {"exg", 1, 0xae, tfr, 0}, 3383 {"sex", 1, 0xae, tfr, 0}, 3384 3385 {"st", 1, 0xc0, regdxy_opr_dest, 0xd0}, 3386 3387 {"andcc", 1, 0xce, imm8, 0}, 3388 {"orcc", 1, 0xde, imm8, 0}, 3389 3390 {"inc.b", 1, 0x9c, opr, 0}, 3391 {"inc.w", 1, 0x9d, opr, 0}, 3392 {"inc.l", 1, 0x9f, opr, 0}, 3393 3394 {"dec.b", 1, 0xac, opr, 0}, 3395 {"dec.w", 1, 0xad, opr, 0}, 3396 {"dec.l", 1, 0xaf, opr, 0}, 3397 3398 {"clr.b", 1, 0xbc, opr, 0}, 3399 {"clr.w", 1, 0xbd, opr, 0}, 3400 {"clr.p", 1, 0xbe, opr, 0}, 3401 {"clr.l", 1, 0xbf, opr, 0}, 3402 3403 {"com.b", 1, 0xcc, opr, 0}, 3404 {"com.w", 1, 0xcd, opr, 0}, 3405 {"com.l", 1, 0xcf, opr, 0}, 3406 3407 {"neg.b", 1, 0xdc, opr, 0}, 3408 {"neg.w", 1, 0xdd, opr, 0}, 3409 {"neg.l", 1, 0xdf, opr, 0}, 3410 3411 {"bclr", 1, 0xec, bm_regd_imm, 0}, 3412 {"bset", 1, 0xed, bm_regd_imm, 0}, 3413 {"btgl", 1, 0xee, bm_regd_imm, 0}, 3414 3415 {"bclr", 1, 0xec, bm_regd_reg, 0}, 3416 {"bset", 1, 0xed, bm_regd_reg, 0}, 3417 {"btgl", 1, 0xee, bm_regd_reg, 0}, 3418 3419 {"bclr.b", 1, 0xec, bm_opr_imm, 0}, 3420 {"bclr.w", 1, 0xec, bm_opr_imm, 0}, 3421 {"bclr.l", 1, 0xec, bm_opr_imm, 0}, 3422 3423 {"bset.b", 1, 0xed, bm_opr_imm, 0}, 3424 {"bset.w", 1, 0xed, bm_opr_imm, 0}, 3425 {"bset.l", 1, 0xed, bm_opr_imm, 0}, 3426 3427 {"btgl.b", 1, 0xee, bm_opr_imm, 0}, 3428 {"btgl.w", 1, 0xee, bm_opr_imm, 0}, 3429 {"btgl.l", 1, 0xee, bm_opr_imm, 0}, 3430 3431 {"bclr.b", 1, 0xec, bm_opr_reg, 0}, 3432 {"bclr.w", 1, 0xec, bm_opr_reg, 0}, 3433 {"bclr.l", 1, 0xec, bm_opr_reg, 0}, 3434 3435 {"bset.b", 1, 0xed, bm_opr_reg, 0}, 3436 {"bset.w", 1, 0xed, bm_opr_reg, 0}, 3437 {"bset.l", 1, 0xed, bm_opr_reg, 0}, 3438 3439 {"btgl.b", 1, 0xee, bm_opr_reg, 0}, 3440 {"btgl.w", 1, 0xee, bm_opr_reg, 0}, 3441 {"btgl.l", 1, 0xee, bm_opr_reg, 0}, 3442 3443 {"cmp", 1, 0xe0, regdxy_imm, 0}, 3444 {"cmp", 1, 0xf0, regdxy_opr_src, 0}, 3445 3446 {"cmp", 1, 0xfc, regx_regy, 0}, 3447 {"sub", 1, 0xfd, regd6_regx_regy, 0}, 3448 {"sub", 1, 0xfe, regd6_regy_regx, 0}, 3449 3450 {"swi", 1, 0xff, no_operands, 0}, 3451 3452 /* Page 2 */ 3453 3454 /* The -10 below is a kludge. The opcode is in fact 0x00 */ 3455 {"ld", 2, -10, regs_opr_src, 0}, 3456 3457 /* The -9 below is a kludge. The opcode is in fact 0x01 */ 3458 {"st", 2, -9, regs_opr_dest, 0}, 3459 3460 /* The -8 below is a kludge. The opcode is in fact 0x02 */ 3461 {"cmp", 2, -8, regs_opr_src, 0}, 3462 3463 /* The -7 below is a kludge. The opcode is in fact 0x03 */ 3464 {"ld", 2, -7, regs_imm, 0}, 3465 3466 /* The -6 below is a kludge. The opcode is in fact 0x04 */ 3467 {"cmp", 2, -6, regs_imm, 0}, 3468 3469 {"bfext", 2, 0x08, bfe_reg_reg_reg, 0}, 3470 {"bfext", 2, 0x08, bfe_reg_reg_imm, 0}, 3471 {"bfext.b", 2, 0x08, bfe_reg_opr_reg, 0}, 3472 {"bfext.w", 2, 0x08, bfe_reg_opr_reg, 0}, 3473 {"bfext.p", 2, 0x08, bfe_reg_opr_reg, 0}, 3474 {"bfext.l", 2, 0x08, bfe_reg_opr_reg, 0}, 3475 {"bfext.b", 2, 0x08, bfe_opr_reg_reg, 0}, 3476 {"bfext.w", 2, 0x08, bfe_opr_reg_reg, 0}, 3477 {"bfext.p", 2, 0x08, bfe_opr_reg_reg, 0}, 3478 {"bfext.l", 2, 0x08, bfe_opr_reg_reg, 0}, 3479 {"bfext.b", 2, 0x08, bfe_reg_opr_imm, 0}, 3480 {"bfext.w", 2, 0x08, bfe_reg_opr_imm, 0}, 3481 {"bfext.p", 2, 0x08, bfe_reg_opr_imm, 0}, 3482 {"bfext.l", 2, 0x08, bfe_reg_opr_imm, 0}, 3483 {"bfext.b", 2, 0x08, bfe_opr_reg_imm, 0}, 3484 {"bfext.w", 2, 0x08, bfe_opr_reg_imm, 0}, 3485 {"bfext.p", 2, 0x08, bfe_opr_reg_imm, 0}, 3486 {"bfext.l", 2, 0x08, bfe_opr_reg_imm, 0}, 3487 3488 3489 {"bfins", 2, 0x08, bfi_reg_reg_reg, 0}, 3490 {"bfins", 2, 0x08, bfi_reg_reg_imm, 0}, 3491 {"bfins.b", 2, 0x08, bfi_reg_opr_reg, 0}, 3492 {"bfins.w", 2, 0x08, bfi_reg_opr_reg, 0}, 3493 {"bfins.p", 2, 0x08, bfi_reg_opr_reg, 0}, 3494 {"bfins.l", 2, 0x08, bfi_reg_opr_reg, 0}, 3495 {"bfins.b", 2, 0x08, bfi_opr_reg_reg, 0}, 3496 {"bfins.w", 2, 0x08, bfi_opr_reg_reg, 0}, 3497 {"bfins.p", 2, 0x08, bfi_opr_reg_reg, 0}, 3498 {"bfins.l", 2, 0x08, bfi_opr_reg_reg, 0}, 3499 {"bfins.b", 2, 0x08, bfi_reg_opr_imm, 0}, 3500 {"bfins.w", 2, 0x08, bfi_reg_opr_imm, 0}, 3501 {"bfins.p", 2, 0x08, bfi_reg_opr_imm, 0}, 3502 {"bfins.l", 2, 0x08, bfi_reg_opr_imm, 0}, 3503 {"bfins.b", 2, 0x08, bfi_opr_reg_imm, 0}, 3504 {"bfins.w", 2, 0x08, bfi_opr_reg_imm, 0}, 3505 {"bfins.p", 2, 0x08, bfi_opr_reg_imm, 0}, 3506 {"bfins.l", 2, 0x08, bfi_opr_reg_imm, 0}, 3507 3508 3509 {"minu", 2, 0x10, regd_opr, 0}, 3510 {"maxu", 2, 0x18, regd_opr, 0}, 3511 {"mins", 2, 0x20, regd_opr, 0}, 3512 {"maxs", 2, 0x28, regd_opr, 0}, 3513 3514 {"clb", 2, 0x91, tfr, 0}, 3515 3516 {"trap", 2, 0x00, trap_imm, 0}, 3517 {"abs", 2, 0x40, reg_inh, 0}, 3518 {"sat", 2, 0xa0, reg_inh, 0}, 3519 3520 {"rti", 2, 0x90, no_operands, 0}, 3521 {"stop", 2, 0x05, no_operands, 0}, 3522 {"wai", 2, 0x06, no_operands, 0}, 3523 {"sys", 2, 0x07, no_operands, 0}, 3524 3525 {"bit", 2, 0x58, regd_imm, 0}, 3526 {"bit", 2, 0x68, regd_opr, 0}, 3527 3528 {"adc", 2, 0x50, regd_imm, 0}, 3529 {"adc", 2, 0x60, regd_opr, 0}, 3530 3531 {"sbc", 2, 0x70, regd_imm, 0}, 3532 {"eor", 2, 0x78, regd_imm, 0}, 3533 3534 {"sbc", 2, 0x80, regd_opr, 0}, 3535 {"eor", 2, 0x88, regd_opr, 0}, 3536 3537 {"divs", 2, 0x30, mul_reg_reg_reg, 0}, 3538 {"divu", 2, 0x30, mul_reg_reg_reg, 0}, 3539 3540 {"divs.b", 2, 0x30, mul_reg_reg_opr, 0}, 3541 {"divs.w", 2, 0x30, mul_reg_reg_opr, 0}, 3542 {"divs.l", 2, 0x30, mul_reg_reg_opr, 0}, 3543 3544 {"divu.b", 2, 0x30, mul_reg_reg_opr, 0}, 3545 {"divu.w", 2, 0x30, mul_reg_reg_opr, 0}, 3546 {"divu.l", 2, 0x30, mul_reg_reg_opr, 0}, 3547 3548 {"divs.b", 2, 0x30, mul_reg_reg_imm, 0}, 3549 {"divs.w", 2, 0x30, mul_reg_reg_imm, 0}, 3550 {"divs.l", 2, 0x30, mul_reg_reg_imm, 0}, 3551 3552 {"divu.b", 2, 0x30, mul_reg_reg_imm, 0}, 3553 {"divu.w", 2, 0x30, mul_reg_reg_imm, 0}, 3554 {"divu.l", 2, 0x30, mul_reg_reg_imm, 0}, 3555 3556 {"divs.bb", 2, 0x30, mul_reg_opr_opr, 0}, 3557 {"divs.bw", 2, 0x30, mul_reg_opr_opr, 0}, 3558 {"divs.bp", 2, 0x30, mul_reg_opr_opr, 0}, 3559 {"divs.bl", 2, 0x30, mul_reg_opr_opr, 0}, 3560 3561 {"divs.wb", 2, 0x30, mul_reg_opr_opr, 0}, 3562 {"divs.ww", 2, 0x30, mul_reg_opr_opr, 0}, 3563 {"divs.wp", 2, 0x30, mul_reg_opr_opr, 0}, 3564 {"divs.wl", 2, 0x30, mul_reg_opr_opr, 0}, 3565 3566 {"divs.pb", 2, 0x30, mul_reg_opr_opr, 0}, 3567 {"divs.pw", 2, 0x30, mul_reg_opr_opr, 0}, 3568 {"divs.pp", 2, 0x30, mul_reg_opr_opr, 0}, 3569 {"divs.pl", 2, 0x30, mul_reg_opr_opr, 0}, 3570 3571 {"divs.lb", 2, 0x30, mul_reg_opr_opr, 0}, 3572 {"divs.lw", 2, 0x30, mul_reg_opr_opr, 0}, 3573 {"divs.lp", 2, 0x30, mul_reg_opr_opr, 0}, 3574 {"divs.ll", 2, 0x30, mul_reg_opr_opr, 0}, 3575 3576 {"divu.bb", 2, 0x30, mul_reg_opr_opr, 0}, 3577 {"divu.bw", 2, 0x30, mul_reg_opr_opr, 0}, 3578 {"divu.bp", 2, 0x30, mul_reg_opr_opr, 0}, 3579 {"divu.bl", 2, 0x30, mul_reg_opr_opr, 0}, 3580 3581 {"divu.wb", 2, 0x30, mul_reg_opr_opr, 0}, 3582 {"divu.ww", 2, 0x30, mul_reg_opr_opr, 0}, 3583 {"divu.wp", 2, 0x30, mul_reg_opr_opr, 0}, 3584 {"divu.wl", 2, 0x30, mul_reg_opr_opr, 0}, 3585 3586 {"divu.pb", 2, 0x30, mul_reg_opr_opr, 0}, 3587 {"divu.pw", 2, 0x30, mul_reg_opr_opr, 0}, 3588 {"divu.pp", 2, 0x30, mul_reg_opr_opr, 0}, 3589 {"divu.pl", 2, 0x30, mul_reg_opr_opr, 0}, 3590 3591 {"divu.lb", 2, 0x30, mul_reg_opr_opr, 0}, 3592 {"divu.lw", 2, 0x30, mul_reg_opr_opr, 0}, 3593 {"divu.lp", 2, 0x30, mul_reg_opr_opr, 0}, 3594 {"divu.ll", 2, 0x30, mul_reg_opr_opr, 0}, 3595 3596 {"qmuls", 2, 0xb0, mul_reg_reg_reg, 0}, 3597 {"qmulu", 2, 0xb0, mul_reg_reg_reg, 0}, 3598 3599 {"qmuls.b", 2, 0xb0, mul_reg_reg_opr, 0}, 3600 {"qmuls.w", 2, 0xb0, mul_reg_reg_opr, 0}, 3601 {"qmuls.l", 2, 0xb0, mul_reg_reg_opr, 0}, 3602 3603 {"qmulu.b", 2, 0xb0, mul_reg_reg_opr, 0}, 3604 {"qmulu.w", 2, 0xb0, mul_reg_reg_opr, 0}, 3605 {"qmulu.l", 2, 0xb0, mul_reg_reg_opr, 0}, 3606 3607 {"qmuls.b", 2, 0xb0, mul_reg_reg_imm, 0}, 3608 {"qmuls.w", 2, 0xb0, mul_reg_reg_imm, 0}, 3609 {"qmuls.l", 2, 0xb0, mul_reg_reg_imm, 0}, 3610 3611 {"qmulu.b", 2, 0xb0, mul_reg_reg_imm, 0}, 3612 {"qmulu.w", 2, 0xb0, mul_reg_reg_imm, 0}, 3613 {"qmulu.l", 2, 0xb0, mul_reg_reg_imm, 0}, 3614 3615 {"qmuls.bb", 2, 0xb0, mul_reg_opr_opr, 0}, 3616 {"qmuls.bw", 2, 0xb0, mul_reg_opr_opr, 0}, 3617 {"qmuls.bp", 2, 0xb0, mul_reg_opr_opr, 0}, 3618 {"qmuls.bl", 2, 0xb0, mul_reg_opr_opr, 0}, 3619 3620 {"qmuls.wb", 2, 0xb0, mul_reg_opr_opr, 0}, 3621 {"qmuls.ww", 2, 0xb0, mul_reg_opr_opr, 0}, 3622 {"qmuls.wp", 2, 0xb0, mul_reg_opr_opr, 0}, 3623 {"qmuls.wl", 2, 0xb0, mul_reg_opr_opr, 0}, 3624 3625 {"qmuls.pb", 2, 0xb0, mul_reg_opr_opr, 0}, 3626 {"qmuls.pw", 2, 0xb0, mul_reg_opr_opr, 0}, 3627 {"qmuls.pp", 2, 0xb0, mul_reg_opr_opr, 0}, 3628 {"qmuls.pl", 2, 0xb0, mul_reg_opr_opr, 0}, 3629 3630 {"qmuls.lb", 2, 0xb0, mul_reg_opr_opr, 0}, 3631 {"qmuls.lw", 2, 0xb0, mul_reg_opr_opr, 0}, 3632 {"qmuls.lp", 2, 0xb0, mul_reg_opr_opr, 0}, 3633 {"qmuls.ll", 2, 0xb0, mul_reg_opr_opr, 0}, 3634 3635 {"qmulu.bb", 2, 0xb0, mul_reg_opr_opr, 0}, 3636 {"qmulu.bw", 2, 0xb0, mul_reg_opr_opr, 0}, 3637 {"qmulu.bp", 2, 0xb0, mul_reg_opr_opr, 0}, 3638 {"qmulu.bl", 2, 0xb0, mul_reg_opr_opr, 0}, 3639 3640 {"qmulu.wb", 2, 0xb0, mul_reg_opr_opr, 0}, 3641 {"qmulu.ww", 2, 0xb0, mul_reg_opr_opr, 0}, 3642 {"qmulu.wp", 2, 0xb0, mul_reg_opr_opr, 0}, 3643 {"qmulu.wl", 2, 0xb0, mul_reg_opr_opr, 0}, 3644 3645 {"qmulu.pb", 2, 0xb0, mul_reg_opr_opr, 0}, 3646 {"qmulu.pw", 2, 0xb0, mul_reg_opr_opr, 0}, 3647 {"qmulu.pp", 2, 0xb0, mul_reg_opr_opr, 0}, 3648 {"qmulu.pl", 2, 0xb0, mul_reg_opr_opr, 0}, 3649 3650 {"qmulu.lb", 2, 0xb0, mul_reg_opr_opr, 0}, 3651 {"qmulu.lw", 2, 0xb0, mul_reg_opr_opr, 0}, 3652 {"qmulu.lp", 2, 0xb0, mul_reg_opr_opr, 0}, 3653 {"qmulu.ll", 2, 0xb0, mul_reg_opr_opr, 0}, 3654 3655 {"macs", 2, 0x48, mul_reg_reg_reg, 0}, 3656 {"macu", 2, 0x48, mul_reg_reg_reg, 0}, 3657 3658 {"macs.b", 2, 0x48, mul_reg_reg_opr, 0}, 3659 {"macs.w", 2, 0x48, mul_reg_reg_opr, 0}, 3660 {"macs.l", 2, 0x48, mul_reg_reg_opr, 0}, 3661 3662 {"macu.b", 2, 0x48, mul_reg_reg_opr, 0}, 3663 {"macu.w", 2, 0x48, mul_reg_reg_opr, 0}, 3664 {"macu.l", 2, 0x48, mul_reg_reg_opr, 0}, 3665 3666 {"macs.b", 2, 0x48, mul_reg_reg_imm, 0}, 3667 {"macs.w", 2, 0x48, mul_reg_reg_imm, 0}, 3668 {"macs.l", 2, 0x48, mul_reg_reg_imm, 0}, 3669 3670 {"macu.b", 2, 0x48, mul_reg_reg_imm, 0}, 3671 {"macu.w", 2, 0x48, mul_reg_reg_imm, 0}, 3672 {"macu.l", 2, 0x48, mul_reg_reg_imm, 0}, 3673 3674 {"macs.bb", 2, 0x48, mul_reg_opr_opr, 0}, 3675 {"macs.bw", 2, 0x48, mul_reg_opr_opr, 0}, 3676 {"macs.bp", 2, 0x48, mul_reg_opr_opr, 0}, 3677 {"macs.bl", 2, 0x48, mul_reg_opr_opr, 0}, 3678 3679 {"macs.wb", 2, 0x48, mul_reg_opr_opr, 0}, 3680 {"macs.ww", 2, 0x48, mul_reg_opr_opr, 0}, 3681 {"macs.wp", 2, 0x48, mul_reg_opr_opr, 0}, 3682 {"macs.wl", 2, 0x48, mul_reg_opr_opr, 0}, 3683 3684 {"macs.pb", 2, 0x48, mul_reg_opr_opr, 0}, 3685 {"macs.pw", 2, 0x48, mul_reg_opr_opr, 0}, 3686 {"macs.pp", 2, 0x48, mul_reg_opr_opr, 0}, 3687 {"macs.pl", 2, 0x48, mul_reg_opr_opr, 0}, 3688 3689 {"macs.lb", 2, 0x48, mul_reg_opr_opr, 0}, 3690 {"macs.lw", 2, 0x48, mul_reg_opr_opr, 0}, 3691 {"macs.lp", 2, 0x48, mul_reg_opr_opr, 0}, 3692 {"macs.ll", 2, 0x48, mul_reg_opr_opr, 0}, 3693 3694 {"macu.bb", 2, 0x48, mul_reg_opr_opr, 0}, 3695 {"macu.bw", 2, 0x48, mul_reg_opr_opr, 0}, 3696 {"macu.bp", 2, 0x48, mul_reg_opr_opr, 0}, 3697 {"macu.bl", 2, 0x48, mul_reg_opr_opr, 0}, 3698 3699 {"macu.wb", 2, 0x48, mul_reg_opr_opr, 0}, 3700 {"macu.ww", 2, 0x48, mul_reg_opr_opr, 0}, 3701 {"macu.wp", 2, 0x48, mul_reg_opr_opr, 0}, 3702 {"macu.wl", 2, 0x48, mul_reg_opr_opr, 0}, 3703 3704 {"macu.pb", 2, 0x48, mul_reg_opr_opr, 0}, 3705 {"macu.pw", 2, 0x48, mul_reg_opr_opr, 0}, 3706 {"macu.pp", 2, 0x48, mul_reg_opr_opr, 0}, 3707 {"macu.pl", 2, 0x48, mul_reg_opr_opr, 0}, 3708 3709 {"macu.lb", 2, 0x48, mul_reg_opr_opr, 0}, 3710 {"macu.lw", 2, 0x48, mul_reg_opr_opr, 0}, 3711 {"macu.lp", 2, 0x48, mul_reg_opr_opr, 0}, 3712 {"macu.ll", 2, 0x48, mul_reg_opr_opr, 0}, 3713 3714 {"mods", 2, 0x38, mul_reg_reg_reg, 0}, 3715 {"modu", 2, 0x38, mul_reg_reg_reg, 0}, 3716 3717 {"mods.b", 2, 0x38, mul_reg_reg_opr, 0}, 3718 {"mods.w", 2, 0x38, mul_reg_reg_opr, 0}, 3719 {"mods.l", 2, 0x38, mul_reg_reg_opr, 0}, 3720 3721 {"modu.b", 2, 0x38, mul_reg_reg_opr, 0}, 3722 {"modu.w", 2, 0x38, mul_reg_reg_opr, 0}, 3723 {"modu.l", 2, 0x38, mul_reg_reg_opr, 0}, 3724 3725 {"mods.b", 2, 0x38, mul_reg_reg_imm, 0}, 3726 {"mods.w", 2, 0x38, mul_reg_reg_imm, 0}, 3727 {"mods.l", 2, 0x38, mul_reg_reg_imm, 0}, 3728 3729 {"modu.b", 2, 0x38, mul_reg_reg_imm, 0}, 3730 {"modu.w", 2, 0x38, mul_reg_reg_imm, 0}, 3731 {"modu.l", 2, 0x38, mul_reg_reg_imm, 0}, 3732 3733 {"mods.bb", 2, 0x38, mul_reg_opr_opr, 0}, 3734 {"mods.bw", 2, 0x38, mul_reg_opr_opr, 0}, 3735 {"mods.bp", 2, 0x38, mul_reg_opr_opr, 0}, 3736 {"mods.bl", 2, 0x38, mul_reg_opr_opr, 0}, 3737 3738 {"mods.wb", 2, 0x38, mul_reg_opr_opr, 0}, 3739 {"mods.ww", 2, 0x38, mul_reg_opr_opr, 0}, 3740 {"mods.wp", 2, 0x38, mul_reg_opr_opr, 0}, 3741 {"mods.wl", 2, 0x38, mul_reg_opr_opr, 0}, 3742 3743 {"mods.pb", 2, 0x38, mul_reg_opr_opr, 0}, 3744 {"mods.pw", 2, 0x38, mul_reg_opr_opr, 0}, 3745 {"mods.pp", 2, 0x38, mul_reg_opr_opr, 0}, 3746 {"mods.pl", 2, 0x38, mul_reg_opr_opr, 0}, 3747 3748 {"mods.lb", 2, 0x38, mul_reg_opr_opr, 0}, 3749 {"mods.lw", 2, 0x38, mul_reg_opr_opr, 0}, 3750 {"mods.lp", 2, 0x38, mul_reg_opr_opr, 0}, 3751 {"mods.ll", 2, 0x38, mul_reg_opr_opr, 0}, 3752 3753 {"modu.bb", 2, 0x38, mul_reg_opr_opr, 0}, 3754 {"modu.bw", 2, 0x38, mul_reg_opr_opr, 0}, 3755 {"modu.bp", 2, 0x38, mul_reg_opr_opr, 0}, 3756 {"modu.bl", 2, 0x38, mul_reg_opr_opr, 0}, 3757 3758 {"modu.wb", 2, 0x38, mul_reg_opr_opr, 0}, 3759 {"modu.ww", 2, 0x38, mul_reg_opr_opr, 0}, 3760 {"modu.wp", 2, 0x38, mul_reg_opr_opr, 0}, 3761 {"modu.wl", 2, 0x38, mul_reg_opr_opr, 0}, 3762 3763 {"modu.pb", 2, 0x38, mul_reg_opr_opr, 0}, 3764 {"modu.pw", 2, 0x38, mul_reg_opr_opr, 0}, 3765 {"modu.pp", 2, 0x38, mul_reg_opr_opr, 0}, 3766 {"modu.pl", 2, 0x38, mul_reg_opr_opr, 0}, 3767 3768 {"modu.lb", 2, 0x38, mul_reg_opr_opr, 0}, 3769 {"modu.lw", 2, 0x38, mul_reg_opr_opr, 0}, 3770 {"modu.lp", 2, 0x38, mul_reg_opr_opr, 0}, 3771 {"modu.ll", 2, 0x38, mul_reg_opr_opr, 0} 3772 }; 3773 3774 3775 /* Gas line assembler entry point. */ 3776 3777 /* This is the main entry point for the machine-dependent assembler. str 3778 points to a machine-dependent instruction. This function is supposed to 3779 emit the frags/bytes it assembles to. */ 3780 void 3781 md_assemble (char *str) 3782 { 3783 char *op_start; 3784 char *op_end; 3785 char name[20]; 3786 size_t nlen = 0; 3787 3788 fail_line_pointer = NULL; 3789 3790 /* Find the opcode end and get the opcode in 'name'. The opcode is forced 3791 lower case (the opcode table only has lower case op-codes). */ 3792 for (op_start = op_end = str; 3793 *op_end && !is_end_of_line[(int)*op_end] && *op_end != ' '; 3794 op_end++) 3795 { 3796 name[nlen] = TOLOWER (op_start[nlen]); 3797 nlen++; 3798 gas_assert (nlen < sizeof (name) - 1); 3799 } 3800 name[nlen] = 0; 3801 3802 if (nlen == 0) 3803 { 3804 as_bad (_("No instruction or missing opcode.")); 3805 return; 3806 } 3807 3808 input_line_pointer = skip_whites (op_end); 3809 3810 size_t i; 3811 for (i = 0; i < sizeof (opcodes) / sizeof (opcodes[0]); ++i) 3812 { 3813 const struct instruction *opc = opcodes + i; 3814 if (0 == strcmp (name, opc->name)) 3815 { 3816 if (opc->parse_operands (opc)) 3817 return; 3818 continue; 3819 } 3820 } 3821 3822 as_bad (_("Invalid instruction: \"%s\""), str); 3823 as_bad (_("First invalid token: \"%s\""), fail_line_pointer); 3824 while (*input_line_pointer++) 3825 ; 3826 } 3827 3828 3829 3830 3831 3832 /* Relocation, relaxation and frag conversions. */ 3833 3834 /* PC-relative offsets are relative to the start of the 3835 next instruction. That is, the address of the offset, plus its 3836 size, since the offset is always the last part of the insn. */ 3837 long 3838 md_pcrel_from (fixS *fixP) 3839 { 3840 long ret = fixP->fx_size + fixP->fx_frag->fr_address; 3841 if (fixP->fx_addsy && S_IS_DEFINED (fixP->fx_addsy)) 3842 ret += fixP->fx_where; 3843 3844 return ret; 3845 } 3846 3847 3848 /* We need a port-specific relaxation function to cope with sym2 - sym1 3849 relative expressions with both symbols in the same segment (but not 3850 necessarily in the same frag as this insn), for example: 3851 ldab sym2-(sym1-2),pc 3852 sym1: 3853 The offset can be 5, 9 or 16 bits long. */ 3854 3855 long 3856 s12z_relax_frag (segT seg ATTRIBUTE_UNUSED, fragS *fragP ATTRIBUTE_UNUSED, 3857 long stretch ATTRIBUTE_UNUSED) 3858 { 3859 return 0; 3860 } 3861 3862 void 3863 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, asection *sec ATTRIBUTE_UNUSED, 3864 fragS *fragP ATTRIBUTE_UNUSED) 3865 { 3866 } 3867 3868 /* On an ELF system, we can't relax a weak symbol. The weak symbol 3869 can be overridden at final link time by a non weak symbol. We can 3870 relax externally visible symbol because there is no shared library 3871 and such symbol can't be overridden (unless they are weak). */ 3872 3873 /* Force truly undefined symbols to their maximum size, and generally set up 3874 the frag list to be relaxed. */ 3875 int 3876 md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED, asection *segment ATTRIBUTE_UNUSED) 3877 { 3878 return 0; 3879 } 3880 3881 3882 /* If while processing a fixup, a reloc really needs to be created 3883 then it is done here. */ 3884 arelent * 3885 tc_gen_reloc (asection *section, fixS *fixp) 3886 { 3887 arelent *reloc = XNEW (arelent); 3888 reloc->sym_ptr_ptr = XNEW (asymbol *); 3889 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 3890 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; 3891 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); 3892 if (reloc->howto == (reloc_howto_type *) NULL) 3893 { 3894 as_bad_where (fixp->fx_file, fixp->fx_line, 3895 _("Relocation %d is not supported by object file format."), 3896 (int) fixp->fx_r_type); 3897 return NULL; 3898 } 3899 3900 if (0 == (section->flags & SEC_CODE)) 3901 reloc->addend = fixp->fx_offset; 3902 else 3903 reloc->addend = fixp->fx_addnumber; 3904 3905 return reloc; 3906 } 3907 3908 /* See whether we need to force a relocation into the output file. */ 3909 int 3910 tc_s12z_force_relocation (fixS *fixP) 3911 { 3912 return generic_force_reloc (fixP); 3913 } 3914 3915 /* Here we decide which fixups can be adjusted to make them relative 3916 to the beginning of the section instead of the symbol. Basically 3917 we need to make sure that the linker relaxation is done 3918 correctly, so in some cases we force the original symbol to be 3919 used. */ 3920 bool 3921 tc_s12z_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED) 3922 { 3923 return true; 3924 } 3925 3926 void 3927 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) 3928 { 3929 long value = *valP; 3930 3931 if (fixP->fx_addsy == (symbolS *) NULL) 3932 fixP->fx_done = 1; 3933 3934 /* We don't actually support subtracting a symbol. */ 3935 if (fixP->fx_subsy != (symbolS *) NULL) 3936 as_bad_subtract (fixP); 3937 3938 /* 3939 Patch the instruction with the resolved operand. Elf relocation 3940 info will also be generated to take care of linker/loader fixups. 3941 */ 3942 char *where = fixP->fx_frag->fr_literal + fixP->fx_where; 3943 3944 switch (fixP->fx_r_type) 3945 { 3946 case BFD_RELOC_8: 3947 ((bfd_byte *) where)[0] = (bfd_byte) value; 3948 break; 3949 case BFD_RELOC_16: 3950 bfd_putb16 ((bfd_vma) value, (unsigned char *) where); 3951 break; 3952 case BFD_RELOC_24: 3953 bfd_putb24 ((bfd_vma) value, (unsigned char *) where); 3954 break; 3955 case BFD_RELOC_S12Z_OPR: 3956 { 3957 switch (fixP->fx_size) 3958 { 3959 case 3: 3960 bfd_putb24 ((bfd_vma) value, (unsigned char *) where); 3961 break; 3962 case 2: 3963 bfd_putb16 ((bfd_vma) value, (unsigned char *) where); 3964 break; 3965 default: 3966 abort (); 3967 } 3968 } 3969 break; 3970 case BFD_RELOC_32: 3971 bfd_putb32 ((bfd_vma) value, (unsigned char *) where); 3972 break; 3973 case BFD_RELOC_16_PCREL: 3974 if (value < -0x4000 || value > 0x3FFF) 3975 as_bad_where (fixP->fx_file, fixP->fx_line, 3976 _("Value out of 16-bit range.")); 3977 3978 bfd_putb16 ((bfd_vma) value | 0x8000, (unsigned char *) where); 3979 break; 3980 3981 default: 3982 as_fatal (_("Line %d: unknown relocation type: 0x%x."), 3983 fixP->fx_line, fixP->fx_r_type); 3984 } 3985 } 3986 3987 /* Set the ELF specific flags. */ 3988 void 3989 s12z_elf_final_processing (void) 3990 { 3991 } 3992