1 /* tc-mn10200.c -- Assembler code for the Matsushita 10200 2 Copyright (C) 1996-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 "opcode/mn10200.h" 25 26 /* Structure to hold information about predefined registers. */ 27 struct reg_name 28 { 29 const char *name; 30 int value; 31 }; 32 33 /* Generic assembler global variables which must be defined by all 34 targets. */ 35 36 /* Characters which always start a comment. */ 37 const char comment_chars[] = "#"; 38 39 /* Characters which start a comment at the beginning of a line. */ 40 const char line_comment_chars[] = ";#"; 41 42 /* Characters which may be used to separate multiple commands on a 43 single line. */ 44 const char line_separator_chars[] = ";"; 45 46 /* Characters which are used to indicate an exponent in a floating 47 point number. */ 48 const char EXP_CHARS[] = "eE"; 49 50 /* Characters which mean that a number is a floating point constant, 51 as in 0d1.0. */ 52 const char FLT_CHARS[] = "dD"; 53 54 const relax_typeS md_relax_table[] = 55 { 56 /* bCC relaxing */ 57 {0x81, -0x7e, 2, 1}, 58 {0x8004, -0x7ffb, 5, 2}, 59 {0x800006, -0x7ffff9, 7, 0}, 60 /* bCCx relaxing */ 61 {0x81, -0x7e, 3, 4}, 62 {0x8004, -0x7ffb, 6, 5}, 63 {0x800006, -0x7ffff9, 8, 0}, 64 /* jsr relaxing */ 65 {0x8004, -0x7ffb, 3, 7}, 66 {0x800006, -0x7ffff9, 5, 0}, 67 /* jmp relaxing */ 68 {0x81, -0x7e, 2, 9}, 69 {0x8004, -0x7ffb, 3, 10}, 70 {0x800006, -0x7ffff9, 5, 0}, 71 72 }; 73 74 75 /* Fixups. */ 76 #define MAX_INSN_FIXUPS 5 77 78 struct mn10200_fixup 79 { 80 expressionS exp; 81 int opindex; 82 bfd_reloc_code_real_type reloc; 83 }; 84 85 struct mn10200_fixup fixups[MAX_INSN_FIXUPS]; 86 static int fc; 87 88 const char *md_shortopts = ""; 89 90 struct option md_longopts[] = 91 { 92 {NULL, no_argument, NULL, 0} 93 }; 94 95 size_t md_longopts_size = sizeof (md_longopts); 96 97 /* The target specific pseudo-ops which we support. */ 98 const pseudo_typeS md_pseudo_table[] = 99 { 100 { NULL, NULL, 0 } 101 }; 102 103 /* Opcode hash table. */ 104 static htab_t mn10200_hash; 105 106 /* This table is sorted. Suitable for searching by a binary search. */ 107 static const struct reg_name data_registers[] = 108 { 109 { "d0", 0 }, 110 { "d1", 1 }, 111 { "d2", 2 }, 112 { "d3", 3 }, 113 }; 114 #define DATA_REG_NAME_CNT \ 115 (sizeof (data_registers) / sizeof (struct reg_name)) 116 117 static const struct reg_name address_registers[] = 118 { 119 { "a0", 0 }, 120 { "a1", 1 }, 121 { "a2", 2 }, 122 { "a3", 3 }, 123 }; 124 #define ADDRESS_REG_NAME_CNT \ 125 (sizeof (address_registers) / sizeof (struct reg_name)) 126 127 static const struct reg_name other_registers[] = 128 { 129 { "mdr", 0 }, 130 { "psw", 0 }, 131 }; 132 #define OTHER_REG_NAME_CNT \ 133 (sizeof (other_registers) / sizeof (struct reg_name)) 134 135 /* reg_name_search does a binary search of the given register table 136 to see if "name" is a valid register name. Returns the register 137 number from the array on success, or -1 on failure. */ 138 139 static int 140 reg_name_search (const struct reg_name *regs, 141 int regcount, 142 const char *name) 143 { 144 int middle, low, high; 145 int cmp; 146 147 low = 0; 148 high = regcount - 1; 149 150 do 151 { 152 middle = (low + high) / 2; 153 cmp = strcasecmp (name, regs[middle].name); 154 if (cmp < 0) 155 high = middle - 1; 156 else if (cmp > 0) 157 low = middle + 1; 158 else 159 return regs[middle].value; 160 } 161 while (low <= high); 162 return -1; 163 } 164 165 /* Summary of register_name(). 166 167 in: Input_line_pointer points to 1st char of operand. 168 169 out: An expressionS. 170 The operand may have been a register: in this case, X_op == O_register, 171 X_add_number is set to the register number, and truth is returned. 172 Input_line_pointer->(next non-blank) char after operand, or is in 173 its original state. */ 174 175 static bool 176 data_register_name (expressionS *expressionP) 177 { 178 int reg_number; 179 char *name; 180 char *start; 181 char c; 182 183 /* Find the spelling of the operand. */ 184 start = input_line_pointer; 185 c = get_symbol_name (&name); 186 reg_number = reg_name_search (data_registers, DATA_REG_NAME_CNT, name); 187 188 /* Put back the delimiting char. */ 189 (void) restore_line_pointer (c); 190 191 /* Look to see if it's in the register table. */ 192 if (reg_number >= 0) 193 { 194 expressionP->X_op = O_register; 195 expressionP->X_add_number = reg_number; 196 197 /* Make the rest nice. */ 198 expressionP->X_add_symbol = NULL; 199 expressionP->X_op_symbol = NULL; 200 201 return true; 202 } 203 204 /* Reset the line as if we had not done anything. */ 205 input_line_pointer = start; 206 return false; 207 } 208 209 /* Summary of register_name(). 210 211 in: Input_line_pointer points to 1st char of operand. 212 213 out: An expressionS. 214 The operand may have been a register: in this case, X_op == O_register, 215 X_add_number is set to the register number, and truth is returned. 216 Input_line_pointer->(next non-blank) char after operand, or is in 217 its original state. */ 218 219 static bool 220 address_register_name (expressionS *expressionP) 221 { 222 int reg_number; 223 char *name; 224 char *start; 225 char c; 226 227 /* Find the spelling of the operand. */ 228 start = input_line_pointer; 229 c = get_symbol_name (&name); 230 reg_number = reg_name_search (address_registers, ADDRESS_REG_NAME_CNT, name); 231 232 /* Put back the delimiting char. */ 233 (void) restore_line_pointer (c); 234 235 /* Look to see if it's in the register table. */ 236 if (reg_number >= 0) 237 { 238 expressionP->X_op = O_register; 239 expressionP->X_add_number = reg_number; 240 241 /* Make the rest nice. */ 242 expressionP->X_add_symbol = NULL; 243 expressionP->X_op_symbol = NULL; 244 245 return true; 246 } 247 248 /* Reset the line as if we had not done anything. */ 249 input_line_pointer = start; 250 return false; 251 } 252 253 /* Summary of register_name(). 254 255 in: Input_line_pointer points to 1st char of operand. 256 257 out: An expressionS. 258 The operand may have been a register: in this case, X_op == O_register, 259 X_add_number is set to the register number, and truth is returned. 260 Input_line_pointer->(next non-blank) char after operand, or is in 261 its original state. */ 262 263 static bool 264 other_register_name (expressionS *expressionP) 265 { 266 int reg_number; 267 char *name; 268 char *start; 269 char c; 270 271 /* Find the spelling of the operand. */ 272 start = input_line_pointer; 273 c = get_symbol_name (&name); 274 reg_number = reg_name_search (other_registers, OTHER_REG_NAME_CNT, name); 275 276 /* Put back the delimiting char. */ 277 (void) restore_line_pointer (c); 278 279 /* Look to see if it's in the register table. */ 280 if (reg_number >= 0) 281 { 282 expressionP->X_op = O_register; 283 expressionP->X_add_number = reg_number; 284 285 /* Make the rest nice. */ 286 expressionP->X_add_symbol = NULL; 287 expressionP->X_op_symbol = NULL; 288 289 return true; 290 } 291 292 /* Reset the line as if we had not done anything. */ 293 input_line_pointer = start; 294 return false; 295 } 296 297 void 298 md_show_usage (FILE *stream) 299 { 300 fprintf (stream, _("MN10200 options:\n\ 301 none yet\n")); 302 } 303 304 int 305 md_parse_option (int c ATTRIBUTE_UNUSED, 306 const char *arg ATTRIBUTE_UNUSED) 307 { 308 return 0; 309 } 310 311 symbolS * 312 md_undefined_symbol (char *name ATTRIBUTE_UNUSED) 313 { 314 return 0; 315 } 316 317 const char * 318 md_atof (int type, char *litp, int *sizep) 319 { 320 return ieee_md_atof (type, litp, sizep, false); 321 } 322 323 void 324 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, 325 asection *sec, 326 fragS *fragP) 327 { 328 static unsigned long label_count = 0; 329 char buf[40]; 330 331 subseg_change (sec, 0); 332 if (fragP->fr_subtype == 0) 333 { 334 fix_new (fragP, fragP->fr_fix + 1, 1, fragP->fr_symbol, 335 fragP->fr_offset, 1, BFD_RELOC_8_PCREL); 336 fragP->fr_var = 0; 337 fragP->fr_fix += 2; 338 } 339 else if (fragP->fr_subtype == 1) 340 { 341 /* Reverse the condition of the first branch. */ 342 int offset = fragP->fr_fix; 343 int opcode = fragP->fr_literal[offset] & 0xff; 344 345 switch (opcode) 346 { 347 case 0xe8: 348 opcode = 0xe9; 349 break; 350 case 0xe9: 351 opcode = 0xe8; 352 break; 353 case 0xe0: 354 opcode = 0xe2; 355 break; 356 case 0xe2: 357 opcode = 0xe0; 358 break; 359 case 0xe3: 360 opcode = 0xe1; 361 break; 362 case 0xe1: 363 opcode = 0xe3; 364 break; 365 case 0xe4: 366 opcode = 0xe6; 367 break; 368 case 0xe6: 369 opcode = 0xe4; 370 break; 371 case 0xe7: 372 opcode = 0xe5; 373 break; 374 case 0xe5: 375 opcode = 0xe7; 376 break; 377 default: 378 abort (); 379 } 380 fragP->fr_literal[offset] = opcode; 381 382 /* Create a fixup for the reversed conditional branch. */ 383 sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++); 384 fix_new (fragP, fragP->fr_fix + 1, 1, 385 symbol_new (buf, sec, fragP->fr_next, 0), 386 fragP->fr_offset, 1, BFD_RELOC_8_PCREL); 387 388 /* Now create the unconditional branch + fixup to the 389 final target. */ 390 fragP->fr_literal[offset + 2] = 0xfc; 391 fix_new (fragP, fragP->fr_fix + 3, 2, fragP->fr_symbol, 392 fragP->fr_offset, 1, BFD_RELOC_16_PCREL); 393 fragP->fr_var = 0; 394 fragP->fr_fix += 5; 395 } 396 else if (fragP->fr_subtype == 2) 397 { 398 /* Reverse the condition of the first branch. */ 399 int offset = fragP->fr_fix; 400 int opcode = fragP->fr_literal[offset] & 0xff; 401 402 switch (opcode) 403 { 404 case 0xe8: 405 opcode = 0xe9; 406 break; 407 case 0xe9: 408 opcode = 0xe8; 409 break; 410 case 0xe0: 411 opcode = 0xe2; 412 break; 413 case 0xe2: 414 opcode = 0xe0; 415 break; 416 case 0xe3: 417 opcode = 0xe1; 418 break; 419 case 0xe1: 420 opcode = 0xe3; 421 break; 422 case 0xe4: 423 opcode = 0xe6; 424 break; 425 case 0xe6: 426 opcode = 0xe4; 427 break; 428 case 0xe7: 429 opcode = 0xe5; 430 break; 431 case 0xe5: 432 opcode = 0xe7; 433 break; 434 default: 435 abort (); 436 } 437 fragP->fr_literal[offset] = opcode; 438 439 /* Create a fixup for the reversed conditional branch. */ 440 sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++); 441 fix_new (fragP, fragP->fr_fix + 1, 1, 442 symbol_new (buf, sec, fragP->fr_next, 0), 443 fragP->fr_offset, 1, BFD_RELOC_8_PCREL); 444 445 /* Now create the unconditional branch + fixup to the 446 final target. */ 447 fragP->fr_literal[offset + 2] = 0xf4; 448 fragP->fr_literal[offset + 3] = 0xe0; 449 fix_new (fragP, fragP->fr_fix + 4, 4, fragP->fr_symbol, 450 fragP->fr_offset, 1, BFD_RELOC_24_PCREL); 451 fragP->fr_var = 0; 452 fragP->fr_fix += 7; 453 } 454 else if (fragP->fr_subtype == 3) 455 { 456 fix_new (fragP, fragP->fr_fix + 2, 1, fragP->fr_symbol, 457 fragP->fr_offset, 1, BFD_RELOC_8_PCREL); 458 fragP->fr_var = 0; 459 fragP->fr_fix += 3; 460 } 461 else if (fragP->fr_subtype == 4) 462 { 463 /* Reverse the condition of the first branch. */ 464 int offset = fragP->fr_fix; 465 int opcode = fragP->fr_literal[offset + 1] & 0xff; 466 467 switch (opcode) 468 { 469 case 0xfc: 470 opcode = 0xfd; 471 break; 472 case 0xfd: 473 opcode = 0xfc; 474 break; 475 case 0xfe: 476 opcode = 0xff; 477 break; 478 case 0xff: 479 opcode = 0xfe; 480 break; 481 case 0xe8: 482 opcode = 0xe9; 483 break; 484 case 0xe9: 485 opcode = 0xe8; 486 break; 487 case 0xe0: 488 opcode = 0xe2; 489 break; 490 case 0xe2: 491 opcode = 0xe0; 492 break; 493 case 0xe3: 494 opcode = 0xe1; 495 break; 496 case 0xe1: 497 opcode = 0xe3; 498 break; 499 case 0xe4: 500 opcode = 0xe6; 501 break; 502 case 0xe6: 503 opcode = 0xe4; 504 break; 505 case 0xe7: 506 opcode = 0xe5; 507 break; 508 case 0xe5: 509 opcode = 0xe7; 510 break; 511 case 0xec: 512 opcode = 0xed; 513 break; 514 case 0xed: 515 opcode = 0xec; 516 break; 517 case 0xee: 518 opcode = 0xef; 519 break; 520 case 0xef: 521 opcode = 0xee; 522 break; 523 default: 524 abort (); 525 } 526 fragP->fr_literal[offset + 1] = opcode; 527 528 /* Create a fixup for the reversed conditional branch. */ 529 sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++); 530 fix_new (fragP, fragP->fr_fix + 2, 1, 531 symbol_new (buf, sec, fragP->fr_next, 0), 532 fragP->fr_offset, 1, BFD_RELOC_8_PCREL); 533 534 /* Now create the unconditional branch + fixup to the 535 final target. */ 536 fragP->fr_literal[offset + 3] = 0xfc; 537 fix_new (fragP, fragP->fr_fix + 4, 2, fragP->fr_symbol, 538 fragP->fr_offset, 1, BFD_RELOC_16_PCREL); 539 fragP->fr_var = 0; 540 fragP->fr_fix += 6; 541 } 542 else if (fragP->fr_subtype == 5) 543 { 544 /* Reverse the condition of the first branch. */ 545 int offset = fragP->fr_fix; 546 int opcode = fragP->fr_literal[offset + 1] & 0xff; 547 548 switch (opcode) 549 { 550 case 0xfc: 551 opcode = 0xfd; 552 break; 553 case 0xfd: 554 opcode = 0xfc; 555 break; 556 case 0xfe: 557 opcode = 0xff; 558 break; 559 case 0xff: 560 opcode = 0xfe; 561 break; 562 case 0xe8: 563 opcode = 0xe9; 564 break; 565 case 0xe9: 566 opcode = 0xe8; 567 break; 568 case 0xe0: 569 opcode = 0xe2; 570 break; 571 case 0xe2: 572 opcode = 0xe0; 573 break; 574 case 0xe3: 575 opcode = 0xe1; 576 break; 577 case 0xe1: 578 opcode = 0xe3; 579 break; 580 case 0xe4: 581 opcode = 0xe6; 582 break; 583 case 0xe6: 584 opcode = 0xe4; 585 break; 586 case 0xe7: 587 opcode = 0xe5; 588 break; 589 case 0xe5: 590 opcode = 0xe7; 591 break; 592 case 0xec: 593 opcode = 0xed; 594 break; 595 case 0xed: 596 opcode = 0xec; 597 break; 598 case 0xee: 599 opcode = 0xef; 600 break; 601 case 0xef: 602 opcode = 0xee; 603 break; 604 default: 605 abort (); 606 } 607 fragP->fr_literal[offset + 1] = opcode; 608 609 /* Create a fixup for the reversed conditional branch. */ 610 sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++); 611 fix_new (fragP, fragP->fr_fix + 2, 1, 612 symbol_new (buf, sec, fragP->fr_next, 0), 613 fragP->fr_offset, 1, BFD_RELOC_8_PCREL); 614 615 /* Now create the unconditional branch + fixup to the 616 final target. */ 617 fragP->fr_literal[offset + 3] = 0xf4; 618 fragP->fr_literal[offset + 4] = 0xe0; 619 fix_new (fragP, fragP->fr_fix + 5, 4, fragP->fr_symbol, 620 fragP->fr_offset, 1, BFD_RELOC_24_PCREL); 621 fragP->fr_var = 0; 622 fragP->fr_fix += 8; 623 } 624 else if (fragP->fr_subtype == 6) 625 { 626 fix_new (fragP, fragP->fr_fix + 1, 2, fragP->fr_symbol, 627 fragP->fr_offset, 1, BFD_RELOC_16_PCREL); 628 fragP->fr_var = 0; 629 fragP->fr_fix += 3; 630 } 631 else if (fragP->fr_subtype == 7) 632 { 633 int offset = fragP->fr_fix; 634 fragP->fr_literal[offset] = 0xf4; 635 fragP->fr_literal[offset + 1] = 0xe1; 636 637 fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol, 638 fragP->fr_offset, 1, BFD_RELOC_24_PCREL); 639 fragP->fr_var = 0; 640 fragP->fr_fix += 5; 641 } 642 else if (fragP->fr_subtype == 8) 643 { 644 fragP->fr_literal[fragP->fr_fix] = 0xea; 645 fix_new (fragP, fragP->fr_fix + 1, 1, fragP->fr_symbol, 646 fragP->fr_offset, 1, BFD_RELOC_8_PCREL); 647 fragP->fr_var = 0; 648 fragP->fr_fix += 2; 649 } 650 else if (fragP->fr_subtype == 9) 651 { 652 int offset = fragP->fr_fix; 653 fragP->fr_literal[offset] = 0xfc; 654 655 fix_new (fragP, fragP->fr_fix + 1, 4, fragP->fr_symbol, 656 fragP->fr_offset, 1, BFD_RELOC_16_PCREL); 657 fragP->fr_var = 0; 658 fragP->fr_fix += 3; 659 } 660 else if (fragP->fr_subtype == 10) 661 { 662 int offset = fragP->fr_fix; 663 fragP->fr_literal[offset] = 0xf4; 664 fragP->fr_literal[offset + 1] = 0xe0; 665 666 fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol, 667 fragP->fr_offset, 1, BFD_RELOC_24_PCREL); 668 fragP->fr_var = 0; 669 fragP->fr_fix += 5; 670 } 671 else 672 abort (); 673 } 674 675 valueT 676 md_section_align (asection *seg, valueT addr) 677 { 678 int align = bfd_section_alignment (seg); 679 return ((addr + (1 << align) - 1) & -(1 << align)); 680 } 681 682 void 683 md_begin (void) 684 { 685 const char *prev_name = ""; 686 const struct mn10200_opcode *op; 687 688 mn10200_hash = str_htab_create (); 689 690 /* Insert unique names into hash table. The MN10200 instruction set 691 has many identical opcode names that have different opcodes based 692 on the operands. This hash table then provides a quick index to 693 the first opcode with a particular name in the opcode table. */ 694 695 op = mn10200_opcodes; 696 while (op->name) 697 { 698 if (strcmp (prev_name, op->name)) 699 { 700 prev_name = (char *) op->name; 701 str_hash_insert (mn10200_hash, op->name, op, 0); 702 } 703 op++; 704 } 705 706 /* This is both a simplification (we don't have to write md_apply_fix) 707 and support for future optimizations (branch shortening and similar 708 stuff in the linker. */ 709 linkrelax = 1; 710 } 711 712 static unsigned long 713 check_operand (unsigned long insn ATTRIBUTE_UNUSED, 714 const struct mn10200_operand *operand, 715 offsetT val) 716 { 717 /* No need to check 24bit or 32bit operands for a bit. */ 718 if (operand->bits < 24 719 && (operand->flags & MN10200_OPERAND_NOCHECK) == 0) 720 { 721 long min, max; 722 offsetT test; 723 724 if ((operand->flags & MN10200_OPERAND_SIGNED) != 0) 725 { 726 max = (1 << (operand->bits - 1)) - 1; 727 min = - (1 << (operand->bits - 1)); 728 } 729 else 730 { 731 max = (1 << operand->bits) - 1; 732 min = 0; 733 } 734 735 test = val; 736 737 if (test < (offsetT) min || test > (offsetT) max) 738 return 0; 739 else 740 return 1; 741 } 742 return 1; 743 } 744 /* If while processing a fixup, a reloc really needs to be created 745 Then it is done here. */ 746 747 arelent * 748 tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) 749 { 750 arelent *reloc; 751 reloc = XNEW (arelent); 752 753 if (fixp->fx_subsy != NULL) 754 { 755 if (S_GET_SEGMENT (fixp->fx_addsy) == S_GET_SEGMENT (fixp->fx_subsy) 756 && S_IS_DEFINED (fixp->fx_subsy)) 757 { 758 fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy); 759 fixp->fx_subsy = NULL; 760 } 761 else 762 /* FIXME: We should try more ways to resolve difference expressions 763 here. At least this is better than silently ignoring the 764 subtrahend. */ 765 as_bad_subtract (fixp); 766 } 767 768 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); 769 if (reloc->howto == NULL) 770 { 771 as_bad_where (fixp->fx_file, fixp->fx_line, 772 _("reloc %d not supported by object file format"), 773 (int) fixp->fx_r_type); 774 return NULL; 775 } 776 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; 777 reloc->sym_ptr_ptr = XNEW (asymbol *); 778 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 779 reloc->addend = fixp->fx_offset; 780 return reloc; 781 } 782 783 int 784 md_estimate_size_before_relax (fragS *fragp, asection *seg) 785 { 786 if (fragp->fr_subtype == 6 787 && (!S_IS_DEFINED (fragp->fr_symbol) 788 || seg != S_GET_SEGMENT (fragp->fr_symbol))) 789 fragp->fr_subtype = 7; 790 else if (fragp->fr_subtype == 8 791 && (!S_IS_DEFINED (fragp->fr_symbol) 792 || seg != S_GET_SEGMENT (fragp->fr_symbol))) 793 fragp->fr_subtype = 10; 794 795 if (fragp->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0])) 796 abort (); 797 798 return md_relax_table[fragp->fr_subtype].rlx_length; 799 } 800 801 long 802 md_pcrel_from (fixS *fixp) 803 { 804 return fixp->fx_frag->fr_address; 805 } 806 807 void 808 md_apply_fix (fixS * fixP, valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED) 809 { 810 /* We shouldn't ever get here because linkrelax is nonzero. */ 811 abort (); 812 fixP->fx_done = 1; 813 } 814 815 /* Insert an operand value into an instruction. */ 816 817 static void 818 mn10200_insert_operand (unsigned long *insnp, 819 unsigned long *extensionp, 820 const struct mn10200_operand *operand, 821 offsetT val, 822 char *file, 823 unsigned int line, 824 unsigned int shift) 825 { 826 /* No need to check 24 or 32bit operands for a bit. */ 827 if (operand->bits < 24 828 && (operand->flags & MN10200_OPERAND_NOCHECK) == 0) 829 { 830 long min, max; 831 offsetT test; 832 833 if ((operand->flags & MN10200_OPERAND_SIGNED) != 0) 834 { 835 max = (1 << (operand->bits - 1)) - 1; 836 min = - (1 << (operand->bits - 1)); 837 } 838 else 839 { 840 max = (1 << operand->bits) - 1; 841 min = 0; 842 } 843 844 test = val; 845 846 if (test < (offsetT) min || test > (offsetT) max) 847 as_warn_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line); 848 } 849 850 if ((operand->flags & MN10200_OPERAND_EXTENDED) == 0) 851 { 852 *insnp |= (((long) val & ((1 << operand->bits) - 1)) 853 << (operand->shift + shift)); 854 855 if ((operand->flags & MN10200_OPERAND_REPEATED) != 0) 856 *insnp |= (((long) val & ((1 << operand->bits) - 1)) 857 << (operand->shift + shift + 2)); 858 } 859 else 860 { 861 *extensionp |= (val >> 16) & 0xff; 862 *insnp |= val & 0xffff; 863 } 864 } 865 866 void 867 md_assemble (char *str) 868 { 869 char *s; 870 struct mn10200_opcode *opcode; 871 struct mn10200_opcode *next_opcode; 872 const unsigned char *opindex_ptr; 873 int next_opindex, relaxable; 874 unsigned long insn, extension, size = 0; 875 char *f; 876 int i; 877 int match; 878 879 /* Get the opcode. */ 880 for (s = str; *s != '\0' && !ISSPACE (*s); s++) 881 ; 882 if (*s != '\0') 883 *s++ = '\0'; 884 885 /* Find the first opcode with the proper name. */ 886 opcode = (struct mn10200_opcode *) str_hash_find (mn10200_hash, str); 887 if (opcode == NULL) 888 { 889 as_bad (_("Unrecognized opcode: `%s'"), str); 890 return; 891 } 892 893 str = s; 894 while (ISSPACE (*str)) 895 ++str; 896 897 input_line_pointer = str; 898 899 for (;;) 900 { 901 const char *errmsg = NULL; 902 int op_idx; 903 char *hold; 904 int extra_shift = 0; 905 906 relaxable = 0; 907 fc = 0; 908 match = 0; 909 next_opindex = 0; 910 insn = opcode->opcode; 911 extension = 0; 912 for (op_idx = 1, opindex_ptr = opcode->operands; 913 *opindex_ptr != 0; 914 opindex_ptr++, op_idx++) 915 { 916 const struct mn10200_operand *operand; 917 expressionS ex; 918 919 if (next_opindex == 0) 920 { 921 operand = &mn10200_operands[*opindex_ptr]; 922 } 923 else 924 { 925 operand = &mn10200_operands[next_opindex]; 926 next_opindex = 0; 927 } 928 929 errmsg = NULL; 930 931 while (*str == ' ' || *str == ',') 932 ++str; 933 934 if (operand->flags & MN10200_OPERAND_RELAX) 935 relaxable = 1; 936 937 /* Gather the operand. */ 938 hold = input_line_pointer; 939 input_line_pointer = str; 940 941 if (operand->flags & MN10200_OPERAND_PAREN) 942 { 943 if (*input_line_pointer != ')' && *input_line_pointer != '(') 944 { 945 input_line_pointer = hold; 946 str = hold; 947 goto error; 948 } 949 input_line_pointer++; 950 goto keep_going; 951 } 952 /* See if we can match the operands. */ 953 else if (operand->flags & MN10200_OPERAND_DREG) 954 { 955 if (!data_register_name (&ex)) 956 { 957 input_line_pointer = hold; 958 str = hold; 959 goto error; 960 } 961 } 962 else if (operand->flags & MN10200_OPERAND_AREG) 963 { 964 if (!address_register_name (&ex)) 965 { 966 input_line_pointer = hold; 967 str = hold; 968 goto error; 969 } 970 } 971 else if (operand->flags & MN10200_OPERAND_PSW) 972 { 973 char *start; 974 char c = get_symbol_name (&start); 975 976 if (strcmp (start, "psw") != 0) 977 { 978 (void) restore_line_pointer (c); 979 input_line_pointer = hold; 980 str = hold; 981 goto error; 982 } 983 (void) restore_line_pointer (c); 984 goto keep_going; 985 } 986 else if (operand->flags & MN10200_OPERAND_MDR) 987 { 988 char *start; 989 char c = get_symbol_name (&start); 990 991 if (strcmp (start, "mdr") != 0) 992 { 993 (void) restore_line_pointer (c); 994 input_line_pointer = hold; 995 str = hold; 996 goto error; 997 } 998 (void) restore_line_pointer (c); 999 goto keep_going; 1000 } 1001 else if (data_register_name (&ex)) 1002 { 1003 input_line_pointer = hold; 1004 str = hold; 1005 goto error; 1006 } 1007 else if (address_register_name (&ex)) 1008 { 1009 input_line_pointer = hold; 1010 str = hold; 1011 goto error; 1012 } 1013 else if (other_register_name (&ex)) 1014 { 1015 input_line_pointer = hold; 1016 str = hold; 1017 goto error; 1018 } 1019 else if (*str == ')' || *str == '(') 1020 { 1021 input_line_pointer = hold; 1022 str = hold; 1023 goto error; 1024 } 1025 else 1026 { 1027 expression (&ex); 1028 resolve_register (&ex); 1029 } 1030 1031 switch (ex.X_op) 1032 { 1033 case O_illegal: 1034 errmsg = _("illegal operand"); 1035 goto error; 1036 case O_absent: 1037 errmsg = _("missing operand"); 1038 goto error; 1039 case O_register: 1040 if ((operand->flags 1041 & (MN10200_OPERAND_DREG | MN10200_OPERAND_AREG)) == 0) 1042 { 1043 input_line_pointer = hold; 1044 str = hold; 1045 goto error; 1046 } 1047 1048 if (opcode->format == FMT_2 || opcode->format == FMT_5) 1049 extra_shift = 8; 1050 else if (opcode->format == FMT_3 || opcode->format == FMT_6 1051 || opcode->format == FMT_7) 1052 extra_shift = 16; 1053 else 1054 extra_shift = 0; 1055 1056 mn10200_insert_operand (&insn, &extension, operand, 1057 ex.X_add_number, NULL, 1058 0, extra_shift); 1059 1060 break; 1061 1062 case O_constant: 1063 /* If this operand can be promoted, and it doesn't 1064 fit into the allocated bitfield for this insn, 1065 then promote it (ie this opcode does not match). */ 1066 if (operand->flags 1067 & (MN10200_OPERAND_PROMOTE | MN10200_OPERAND_RELAX) 1068 && !check_operand (insn, operand, ex.X_add_number)) 1069 { 1070 input_line_pointer = hold; 1071 str = hold; 1072 goto error; 1073 } 1074 1075 mn10200_insert_operand (&insn, &extension, operand, 1076 ex.X_add_number, NULL, 1077 0, 0); 1078 break; 1079 1080 default: 1081 /* If this operand can be promoted, then this opcode didn't 1082 match since we can't know if it needed promotion! */ 1083 if (operand->flags & MN10200_OPERAND_PROMOTE) 1084 { 1085 input_line_pointer = hold; 1086 str = hold; 1087 goto error; 1088 } 1089 1090 /* We need to generate a fixup for this expression. */ 1091 if (fc >= MAX_INSN_FIXUPS) 1092 as_fatal (_("too many fixups")); 1093 fixups[fc].exp = ex; 1094 fixups[fc].opindex = *opindex_ptr; 1095 fixups[fc].reloc = BFD_RELOC_UNUSED; 1096 ++fc; 1097 break; 1098 } 1099 1100 keep_going: 1101 str = input_line_pointer; 1102 input_line_pointer = hold; 1103 1104 while (*str == ' ' || *str == ',') 1105 ++str; 1106 1107 } 1108 1109 /* Make sure we used all the operands! */ 1110 if (*str != ',') 1111 match = 1; 1112 1113 error: 1114 if (match == 0) 1115 { 1116 next_opcode = opcode + 1; 1117 if (!strcmp (next_opcode->name, opcode->name)) 1118 { 1119 opcode = next_opcode; 1120 continue; 1121 } 1122 1123 as_bad ("%s", errmsg); 1124 return; 1125 } 1126 break; 1127 } 1128 1129 while (ISSPACE (*str)) 1130 ++str; 1131 1132 if (*str != '\0') 1133 as_bad (_("junk at end of line: `%s'"), str); 1134 1135 input_line_pointer = str; 1136 1137 if (opcode->format == FMT_1) 1138 size = 1; 1139 else if (opcode->format == FMT_2 || opcode->format == FMT_4) 1140 size = 2; 1141 else if (opcode->format == FMT_3 || opcode->format == FMT_5) 1142 size = 3; 1143 else if (opcode->format == FMT_6) 1144 size = 4; 1145 else if (opcode->format == FMT_7) 1146 size = 5; 1147 else 1148 abort (); 1149 1150 /* Write out the instruction. */ 1151 dwarf2_emit_insn (size); 1152 if (relaxable && fc > 0) 1153 { 1154 /* On a 64-bit host the size of an 'int' is not the same 1155 as the size of a pointer, so we need a union to convert 1156 the opindex field of the fr_cgen structure into a char * 1157 so that it can be stored in the frag. We do not have 1158 to worry about losing accuracy as we are not going to 1159 be even close to the 32bit limit of the int. */ 1160 union 1161 { 1162 int opindex; 1163 char * ptr; 1164 } 1165 opindex_converter; 1166 int type; 1167 1168 /* bCC */ 1169 if (size == 2 && opcode->opcode != 0xfc0000) 1170 { 1171 /* Handle bra specially. Basically treat it like jmp so 1172 that we automatically handle 8, 16 and 32 bit offsets 1173 correctly as well as jumps to an undefined address. 1174 1175 It is also important to not treat it like other bCC 1176 instructions since the long forms of bra is different 1177 from other bCC instructions. */ 1178 if (opcode->opcode == 0xea00) 1179 type = 8; 1180 else 1181 type = 0; 1182 } 1183 /* jsr */ 1184 else if (size == 3 && opcode->opcode == 0xfd0000) 1185 type = 6; 1186 /* jmp */ 1187 else if (size == 3 && opcode->opcode == 0xfc0000) 1188 type = 8; 1189 /* bCCx */ 1190 else 1191 type = 3; 1192 1193 opindex_converter.opindex = fixups[0].opindex; 1194 f = frag_var (rs_machine_dependent, 8, 8 - size, type, 1195 fixups[0].exp.X_add_symbol, 1196 fixups[0].exp.X_add_number, 1197 opindex_converter.ptr); 1198 number_to_chars_bigendian (f, insn, size); 1199 if (8 - size > 4) 1200 { 1201 number_to_chars_bigendian (f + size, 0, 4); 1202 number_to_chars_bigendian (f + size + 4, 0, 8 - size - 4); 1203 } 1204 else 1205 number_to_chars_bigendian (f + size, 0, 8 - size); 1206 } 1207 else 1208 { 1209 f = frag_more (size); 1210 1211 /* Oh, what a mess. The instruction is in big endian format, but 1212 16 and 24bit immediates are little endian! */ 1213 if (opcode->format == FMT_3) 1214 { 1215 number_to_chars_bigendian (f, (insn >> 16) & 0xff, 1); 1216 number_to_chars_littleendian (f + 1, insn & 0xffff, 2); 1217 } 1218 else if (opcode->format == FMT_6) 1219 { 1220 number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2); 1221 number_to_chars_littleendian (f + 2, insn & 0xffff, 2); 1222 } 1223 else if (opcode->format == FMT_7) 1224 { 1225 number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2); 1226 number_to_chars_littleendian (f + 2, insn & 0xffff, 2); 1227 number_to_chars_littleendian (f + 4, extension & 0xff, 1); 1228 } 1229 else 1230 number_to_chars_bigendian (f, insn, size > 4 ? 4 : size); 1231 1232 /* Create any fixups. */ 1233 for (i = 0; i < fc; i++) 1234 { 1235 const struct mn10200_operand *operand; 1236 int reloc_size; 1237 1238 operand = &mn10200_operands[fixups[i].opindex]; 1239 if (fixups[i].reloc != BFD_RELOC_UNUSED) 1240 { 1241 reloc_howto_type *reloc_howto; 1242 int offset; 1243 fixS *fixP; 1244 1245 reloc_howto = bfd_reloc_type_lookup (stdoutput, 1246 fixups[i].reloc); 1247 1248 if (!reloc_howto) 1249 abort (); 1250 1251 reloc_size = bfd_get_reloc_size (reloc_howto); 1252 1253 if (reloc_size < 1 || reloc_size > 4) 1254 abort (); 1255 1256 offset = 4 - reloc_size; 1257 fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, 1258 reloc_size, 1259 &fixups[i].exp, 1260 reloc_howto->pc_relative, 1261 fixups[i].reloc); 1262 1263 /* PC-relative offsets are from the first byte of the 1264 next instruction, not from the start of the current 1265 instruction. */ 1266 if (reloc_howto->pc_relative) 1267 fixP->fx_offset += reloc_size; 1268 } 1269 else 1270 { 1271 int reloc, pcrel, offset; 1272 fixS *fixP; 1273 1274 reloc = BFD_RELOC_NONE; 1275 /* How big is the reloc? Remember SPLIT relocs are 1276 implicitly 32bits. */ 1277 reloc_size = operand->bits; 1278 1279 offset = size - reloc_size / 8; 1280 1281 /* Is the reloc pc-relative? */ 1282 pcrel = (operand->flags & MN10200_OPERAND_PCREL) != 0; 1283 1284 /* Choose a proper BFD relocation type. */ 1285 if (pcrel) 1286 { 1287 if (reloc_size == 8) 1288 reloc = BFD_RELOC_8_PCREL; 1289 else if (reloc_size == 24) 1290 reloc = BFD_RELOC_24_PCREL; 1291 else 1292 abort (); 1293 } 1294 else 1295 { 1296 if (reloc_size == 32) 1297 reloc = BFD_RELOC_32; 1298 else if (reloc_size == 16) 1299 reloc = BFD_RELOC_16; 1300 else if (reloc_size == 8) 1301 reloc = BFD_RELOC_8; 1302 else if (reloc_size == 24) 1303 reloc = BFD_RELOC_24; 1304 else 1305 abort (); 1306 } 1307 1308 /* Convert the size of the reloc into what fix_new_exp 1309 wants. */ 1310 reloc_size = reloc_size / 8; 1311 if (reloc_size == 8) 1312 reloc_size = 0; 1313 else if (reloc_size == 16) 1314 reloc_size = 1; 1315 else if (reloc_size == 32 || reloc_size == 24) 1316 reloc_size = 2; 1317 1318 fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, 1319 reloc_size, &fixups[i].exp, pcrel, 1320 ((bfd_reloc_code_real_type) reloc)); 1321 1322 /* PC-relative offsets are from the first byte of the 1323 next instruction, not from the start of the current 1324 instruction. */ 1325 if (pcrel) 1326 fixP->fx_offset += size; 1327 } 1328 } 1329 } 1330 } 1331