1 /* m88k.c -- Assembler for the Motorola 88000 2 Contributed by Devon Bowen of Buffalo University 3 and Torbjorn Granlund of the Swedish Institute of Computer Science. 4 Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 5 2000 6 Free Software Foundation, Inc. 7 8 This file is part of GAS, the GNU Assembler. 9 10 GAS is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; either version 2, or (at your option) 13 any later version. 14 15 GAS is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with GAS; see the file COPYING. If not, write to the Free 22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 23 02111-1307, USA. */ 24 25 #include <ctype.h> 26 #include "as.h" 27 #include "subsegs.h" 28 #include "m88k-opcode.h" 29 30 struct field_val_assoc 31 { 32 char *name; 33 unsigned val; 34 }; 35 36 struct field_val_assoc cr_regs[] = 37 { 38 {"PID", 0}, 39 {"PSR", 1}, 40 {"EPSR", 2}, 41 {"SSBR", 3}, 42 {"SXIP", 4}, 43 {"SNIP", 5}, 44 {"SFIP", 6}, 45 {"VBR", 7}, 46 {"DMT0", 8}, 47 {"DMD0", 9}, 48 {"DMA0", 10}, 49 {"DMT1", 11}, 50 {"DMD1", 12}, 51 {"DMA1", 13}, 52 {"DMT2", 14}, 53 {"DMD2", 15}, 54 {"DMA2", 16}, 55 {"SR0", 17}, 56 {"SR1", 18}, 57 {"SR2", 19}, 58 {"SR3", 20}, 59 60 {NULL, 0}, 61 }; 62 63 struct field_val_assoc fcr_regs[] = 64 { 65 {"FPECR", 0}, 66 {"FPHS1", 1}, 67 {"FPLS1", 2}, 68 {"FPHS2", 3}, 69 {"FPLS2", 4}, 70 {"FPPT", 5}, 71 {"FPRH", 6}, 72 {"FPRL", 7}, 73 {"FPIT", 8}, 74 75 {"FPSR", 62}, 76 {"FPCR", 63}, 77 78 {NULL, 0}, 79 }; 80 81 struct field_val_assoc cmpslot[] = 82 { 83 /* Integer Floating point */ 84 {"nc", 0}, 85 {"cp", 1}, 86 {"eq", 2}, 87 {"ne", 3}, 88 {"gt", 4}, 89 {"le", 5}, 90 {"lt", 6}, 91 {"ge", 7}, 92 {"hi", 8}, {"ou", 8}, 93 {"ls", 9}, {"ib", 9}, 94 {"lo", 10}, {"in", 10}, 95 {"hs", 11}, {"ob", 11}, 96 {"be", 12}, {"ue", 12}, 97 {"nb", 13}, {"lg", 13}, 98 {"he", 14}, {"ug", 14}, 99 {"nh", 15}, {"ule", 15}, 100 {"ul", 16}, 101 {"uge", 17}, 102 103 {NULL, 0}, 104 }; 105 106 struct field_val_assoc cndmsk[] = 107 { 108 {"gt0", 1}, 109 {"eq0", 2}, 110 {"ge0", 3}, 111 {"lt0", 12}, 112 {"ne0", 13}, 113 {"le0", 14}, 114 115 {NULL, 0}, 116 }; 117 118 struct m88k_insn 119 { 120 unsigned long opcode; 121 expressionS exp; 122 enum reloc_type reloc; 123 }; 124 125 static char *get_bf PARAMS ((char *param, unsigned *valp)); 126 static char *get_cmp PARAMS ((char *param, unsigned *valp)); 127 static char *get_cnd PARAMS ((char *param, unsigned *valp)); 128 static char *get_cr PARAMS ((char *param, unsigned *regnop)); 129 static char *get_fcr PARAMS ((char *param, unsigned *regnop)); 130 static char *get_imm16 PARAMS ((char *param, struct m88k_insn *insn)); 131 static char *get_o6 PARAMS ((char *param, unsigned *valp)); 132 static char *get_reg PARAMS ((char *param, unsigned *regnop, int reg_prefix)); 133 static char *get_vec9 PARAMS ((char *param, unsigned *valp)); 134 static char *getval PARAMS ((char *param, unsigned int *valp)); 135 136 static char *get_pcr PARAMS ((char *param, struct m88k_insn *insn, 137 enum reloc_type reloc)); 138 139 static int calcop PARAMS ((struct m88k_opcode *format, 140 char *param, struct m88k_insn *insn)); 141 142 extern char *myname; 143 static struct hash_control *op_hash = NULL; 144 145 /* These bits should be turned off in the first address of every segment */ 146 int md_seg_align = 7; 147 148 /* These chars start a comment anywhere in a source file (except inside 149 another comment */ 150 const char comment_chars[] = ";"; 151 152 /* These chars only start a comment at the beginning of a line. */ 153 const char line_comment_chars[] = "#"; 154 155 const char line_separator_chars[] = ""; 156 157 /* Chars that can be used to separate mant from exp in floating point nums */ 158 const char EXP_CHARS[] = "eE"; 159 160 /* Chars that mean this number is a floating point constant */ 161 /* as in 0f123.456 */ 162 /* or 0H1.234E-12 (see exp chars above) */ 163 const char FLT_CHARS[] = "dDfF"; 164 165 extern void float_cons (), cons (), s_globl (), s_space (), 166 s_set (), s_lcomm (); 167 168 const pseudo_typeS md_pseudo_table[] = 169 { 170 {"align", s_align_bytes, 4}, 171 {"def", s_set, 0}, 172 {"dfloat", float_cons, 'd'}, 173 {"ffloat", float_cons, 'f'}, 174 {"global", s_globl, 0}, 175 {"half", cons, 2}, 176 {"bss", s_lcomm, 1}, 177 {"string", stringer, 0}, 178 {"word", cons, 4}, 179 /* Force set to be treated as an instruction. */ 180 {"set", NULL, 0}, 181 {".set", s_set, 0}, 182 {0} 183 }; 184 185 void 186 md_begin () 187 { 188 const char *retval = NULL; 189 unsigned int i = 0; 190 191 /* initialize hash table */ 192 193 op_hash = hash_new (); 194 195 /* loop until you see the end of the list */ 196 197 while (*m88k_opcodes[i].name) 198 { 199 char *name = m88k_opcodes[i].name; 200 201 /* hash each mnemonic and record its position */ 202 203 retval = hash_insert (op_hash, name, &m88k_opcodes[i]); 204 205 if (retval != NULL) 206 as_fatal (_("Can't hash instruction '%s':%s"), 207 m88k_opcodes[i].name, retval); 208 209 /* skip to next unique mnemonic or end of list */ 210 211 for (i++; !strcmp (m88k_opcodes[i].name, name); i++) 212 ; 213 } 214 } 215 216 CONST char *md_shortopts = ""; 217 struct option md_longopts[] = { 218 {NULL, no_argument, NULL, 0} 219 }; 220 size_t md_longopts_size = sizeof (md_longopts); 221 222 int 223 md_parse_option (c, arg) 224 int c; 225 char *arg; 226 { 227 return 0; 228 } 229 230 void 231 md_show_usage (stream) 232 FILE *stream; 233 { 234 } 235 236 void 237 md_assemble (op) 238 char *op; 239 { 240 char *param, *thisfrag; 241 char c; 242 struct m88k_opcode *format; 243 struct m88k_insn insn; 244 245 assert (op); 246 247 /* skip over instruction to find parameters */ 248 249 for (param = op; *param != 0 && !isspace (*param); param++) 250 ; 251 c = *param; 252 *param++ = '\0'; 253 254 /* try to find the instruction in the hash table */ 255 256 if ((format = (struct m88k_opcode *) hash_find (op_hash, op)) == NULL) 257 { 258 as_bad (_("Invalid mnemonic '%s'"), op); 259 return; 260 } 261 262 /* try parsing this instruction into insn */ 263 264 insn.exp.X_add_symbol = 0; 265 insn.exp.X_op_symbol = 0; 266 insn.exp.X_add_number = 0; 267 insn.exp.X_op = O_illegal; 268 insn.reloc = NO_RELOC; 269 270 while (!calcop (format, param, &insn)) 271 { 272 /* if it doesn't parse try the next instruction */ 273 274 if (!strcmp (format[0].name, format[1].name)) 275 format++; 276 else 277 { 278 as_fatal (_("Parameter syntax error")); 279 return; 280 } 281 } 282 283 /* grow the current frag and plop in the opcode */ 284 285 thisfrag = frag_more (4); 286 md_number_to_chars (thisfrag, insn.opcode, 4); 287 288 /* if this instruction requires labels mark it for later */ 289 290 switch (insn.reloc) 291 { 292 case NO_RELOC: 293 break; 294 295 case RELOC_LO16: 296 case RELOC_HI16: 297 fix_new_exp (frag_now, 298 thisfrag - frag_now->fr_literal + 2, 299 2, 300 &insn.exp, 301 0, 302 insn.reloc); 303 break; 304 305 case RELOC_IW16: 306 fix_new_exp (frag_now, 307 thisfrag - frag_now->fr_literal, 308 4, 309 &insn.exp, 310 0, 311 insn.reloc); 312 break; 313 314 case RELOC_PC16: 315 fix_new_exp (frag_now, 316 thisfrag - frag_now->fr_literal + 2, 317 2, 318 &insn.exp, 319 1, 320 insn.reloc); 321 break; 322 323 case RELOC_PC26: 324 fix_new_exp (frag_now, 325 thisfrag - frag_now->fr_literal, 326 4, 327 &insn.exp, 328 1, 329 insn.reloc); 330 break; 331 332 default: 333 as_fatal (_("Unknown relocation type")); 334 break; 335 } 336 } 337 338 static int 339 calcop (format, param, insn) 340 struct m88k_opcode *format; 341 char *param; 342 struct m88k_insn *insn; 343 { 344 char *fmt = format->op_spec; 345 int f; 346 unsigned val; 347 unsigned opcode; 348 int reg_prefix = 'r'; 349 350 insn->opcode = format->opcode; 351 opcode = 0; 352 353 for (;;) 354 { 355 if (param == 0) 356 return 0; 357 f = *fmt++; 358 switch (f) 359 { 360 case 0: 361 insn->opcode |= opcode; 362 return (*param == 0 || *param == '\n'); 363 364 default: 365 if (f != *param++) 366 return 0; 367 break; 368 369 case 'd': 370 param = get_reg (param, &val, reg_prefix); 371 reg_prefix = 'r'; 372 opcode |= val << 21; 373 break; 374 375 case 'o': 376 param = get_o6 (param, &val); 377 opcode |= ((val >> 2) << 7); 378 break; 379 380 case 'x': 381 reg_prefix = 'x'; 382 break; 383 384 case '1': 385 param = get_reg (param, &val, reg_prefix); 386 reg_prefix = 'r'; 387 opcode |= val << 16; 388 break; 389 390 case '2': 391 param = get_reg (param, &val, reg_prefix); 392 reg_prefix = 'r'; 393 opcode |= val; 394 break; 395 396 case '3': 397 param = get_reg (param, &val, 'r'); 398 opcode |= (val << 16) | val; 399 break; 400 401 case 'I': 402 param = get_imm16 (param, insn); 403 break; 404 405 case 'b': 406 param = get_bf (param, &val); 407 opcode |= val; 408 break; 409 410 case 'p': 411 param = get_pcr (param, insn, RELOC_PC16); 412 break; 413 414 case 'P': 415 param = get_pcr (param, insn, RELOC_PC26); 416 break; 417 418 case 'B': 419 param = get_cmp (param, &val); 420 opcode |= val; 421 break; 422 423 case 'M': 424 param = get_cnd (param, &val); 425 opcode |= val; 426 break; 427 428 case 'c': 429 param = get_cr (param, &val); 430 opcode |= val << 5; 431 break; 432 433 case 'f': 434 param = get_fcr (param, &val); 435 opcode |= val << 5; 436 break; 437 438 case 'V': 439 param = get_vec9 (param, &val); 440 opcode |= val; 441 break; 442 443 case '?': 444 /* Having this here repeats the warning somtimes. 445 But can't we stand that? */ 446 as_warn (_("Use of obsolete instruction")); 447 break; 448 } 449 } 450 } 451 452 static char * 453 match_name (param, assoc_tab, valp) 454 char *param; 455 struct field_val_assoc *assoc_tab; 456 unsigned *valp; 457 { 458 int i; 459 char *name; 460 int name_len; 461 462 for (i = 0;; i++) 463 { 464 name = assoc_tab[i].name; 465 if (name == NULL) 466 return NULL; 467 name_len = strlen (name); 468 if (!strncmp (param, name, name_len)) 469 { 470 *valp = assoc_tab[i].val; 471 return param + name_len; 472 } 473 } 474 } 475 476 static char * 477 get_reg (param, regnop, reg_prefix) 478 char *param; 479 unsigned *regnop; 480 int reg_prefix; 481 { 482 unsigned c; 483 unsigned regno; 484 485 c = *param++; 486 if (c == reg_prefix) 487 { 488 regno = *param++ - '0'; 489 if (regno < 10) 490 { 491 if (regno == 0) 492 { 493 *regnop = 0; 494 return param; 495 } 496 c = *param - '0'; 497 if (c < 10) 498 { 499 regno = regno * 10 + c; 500 if (c < 32) 501 { 502 *regnop = regno; 503 return param + 1; 504 } 505 } 506 else 507 { 508 *regnop = regno; 509 return param; 510 } 511 } 512 return NULL; 513 } 514 else if (c == 's' && param[0] == 'p') 515 { 516 *regnop = 31; 517 return param + 1; 518 } 519 520 return 0; 521 } 522 523 static char * 524 get_imm16 (param, insn) 525 char *param; 526 struct m88k_insn *insn; 527 { 528 enum reloc_type reloc = NO_RELOC; 529 unsigned int val; 530 char *save_ptr; 531 532 if (!strncmp (param, "hi16", 4) && !isalnum (param[4])) 533 { 534 reloc = RELOC_HI16; 535 param += 4; 536 } 537 else if (!strncmp (param, "lo16", 4) && !isalnum (param[4])) 538 { 539 reloc = RELOC_LO16; 540 param += 4; 541 } 542 else if (!strncmp (param, "iw16", 4) && !isalnum (param[4])) 543 { 544 reloc = RELOC_IW16; 545 param += 4; 546 } 547 548 save_ptr = input_line_pointer; 549 input_line_pointer = param; 550 expression (&insn->exp); 551 param = input_line_pointer; 552 input_line_pointer = save_ptr; 553 554 val = insn->exp.X_add_number; 555 556 if (insn->exp.X_op == O_constant) 557 { 558 /* Insert the value now, and reset reloc to NO_RELOC. */ 559 if (reloc == NO_RELOC) 560 { 561 /* Warn about too big expressions if not surrounded by xx16. */ 562 if (val > 0xffff) 563 as_warn (_("Expression truncated to 16 bits")); 564 } 565 566 if (reloc == RELOC_HI16) 567 val >>= 16; 568 569 insn->opcode |= val & 0xffff; 570 reloc = NO_RELOC; 571 } 572 else if (reloc == NO_RELOC) 573 /* We accept a symbol even without lo16, hi16, etc, and assume 574 lo16 was intended. */ 575 reloc = RELOC_LO16; 576 577 insn->reloc = reloc; 578 579 return param; 580 } 581 582 static char * 583 get_pcr (param, insn, reloc) 584 char *param; 585 struct m88k_insn *insn; 586 enum reloc_type reloc; 587 { 588 char *saveptr, *saveparam; 589 590 saveptr = input_line_pointer; 591 input_line_pointer = param; 592 593 expression (&insn->exp); 594 595 saveparam = input_line_pointer; 596 input_line_pointer = saveptr; 597 598 /* Botch: We should relocate now if O_constant. */ 599 insn->reloc = reloc; 600 601 return saveparam; 602 } 603 604 static char * 605 get_cmp (param, valp) 606 char *param; 607 unsigned *valp; 608 { 609 unsigned int val; 610 char *save_ptr; 611 612 save_ptr = param; 613 614 param = match_name (param, cmpslot, valp); 615 val = *valp; 616 617 if (param == NULL) 618 { 619 param = save_ptr; 620 621 save_ptr = input_line_pointer; 622 input_line_pointer = param; 623 val = get_absolute_expression (); 624 param = input_line_pointer; 625 input_line_pointer = save_ptr; 626 627 if (val >= 32) 628 { 629 as_warn (_("Expression truncated to 5 bits")); 630 val %= 32; 631 } 632 } 633 634 *valp = val << 21; 635 return param; 636 } 637 638 static char * 639 get_cnd (param, valp) 640 char *param; 641 unsigned *valp; 642 { 643 unsigned int val; 644 645 if (isdigit (*param)) 646 { 647 param = getval (param, &val); 648 649 if (val >= 32) 650 { 651 as_warn (_("Expression truncated to 5 bits")); 652 val %= 32; 653 } 654 } 655 else 656 { 657 if (isupper (*param)) 658 *param = tolower (*param); 659 660 if (isupper (param[1])) 661 param[1] = tolower (param[1]); 662 663 param = match_name (param, cndmsk, valp); 664 665 if (param == NULL) 666 return NULL; 667 668 val = *valp; 669 } 670 671 *valp = val << 21; 672 return param; 673 } 674 675 static char * 676 get_bf2 (param, bc) 677 char *param; 678 int bc; 679 { 680 int depth = 0; 681 int c; 682 683 for (;;) 684 { 685 c = *param; 686 if (c == 0) 687 return param; 688 else if (c == '(') 689 depth++; 690 else if (c == ')') 691 depth--; 692 else if (c == bc && depth <= 0) 693 return param; 694 param++; 695 } 696 } 697 698 static char * 699 get_bf_offset_expression (param, offsetp) 700 char *param; 701 unsigned *offsetp; 702 { 703 unsigned offset; 704 705 if (isalpha (param[0])) 706 { 707 if (isupper (param[0])) 708 param[0] = tolower (param[0]); 709 if (isupper (param[1])) 710 param[1] = tolower (param[1]); 711 712 param = match_name (param, cmpslot, offsetp); 713 714 return param; 715 } 716 else 717 { 718 input_line_pointer = param; 719 offset = get_absolute_expression (); 720 param = input_line_pointer; 721 } 722 723 *offsetp = offset; 724 return param; 725 } 726 727 static char * 728 get_bf (param, valp) 729 char *param; 730 unsigned *valp; 731 { 732 unsigned offset = 0; 733 unsigned width = 0; 734 char *xp; 735 char *save_ptr; 736 737 xp = get_bf2 (param, '<'); 738 739 save_ptr = input_line_pointer; 740 input_line_pointer = param; 741 if (*xp == 0) 742 { 743 /* We did not find '<'. We have an offset (width implicitly 32). */ 744 param = get_bf_offset_expression (param, &offset); 745 input_line_pointer = save_ptr; 746 if (param == NULL) 747 return NULL; 748 } 749 else 750 { 751 *xp++ = 0; /* Overwrite the '<' */ 752 param = get_bf2 (xp, '>'); 753 if (*param == 0) 754 return NULL; 755 *param++ = 0; /* Overwrite the '>' */ 756 757 width = get_absolute_expression (); 758 xp = get_bf_offset_expression (xp, &offset); 759 input_line_pointer = save_ptr; 760 761 if (xp + 1 != param) 762 return NULL; 763 } 764 765 *valp = ((width % 32) << 5) | (offset % 32); 766 767 return param; 768 } 769 770 static char * 771 get_cr (param, regnop) 772 char *param; 773 unsigned *regnop; 774 { 775 unsigned regno; 776 unsigned c; 777 778 if (!strncmp (param, "cr", 2)) 779 { 780 param += 2; 781 782 regno = *param++ - '0'; 783 if (regno < 10) 784 { 785 if (regno == 0) 786 { 787 *regnop = 0; 788 return param; 789 } 790 c = *param - '0'; 791 if (c < 10) 792 { 793 regno = regno * 10 + c; 794 if (c < 64) 795 { 796 *regnop = regno; 797 return param + 1; 798 } 799 } 800 else 801 { 802 *regnop = regno; 803 return param; 804 } 805 } 806 return NULL; 807 } 808 809 param = match_name (param, cr_regs, regnop); 810 811 return param; 812 } 813 814 static char * 815 get_fcr (param, regnop) 816 char *param; 817 unsigned *regnop; 818 { 819 unsigned regno; 820 unsigned c; 821 822 if (!strncmp (param, "fcr", 3)) 823 { 824 param += 3; 825 826 regno = *param++ - '0'; 827 if (regno < 10) 828 { 829 if (regno == 0) 830 { 831 *regnop = 0; 832 return param; 833 } 834 c = *param - '0'; 835 if (c < 10) 836 { 837 regno = regno * 10 + c; 838 if (c < 64) 839 { 840 *regnop = regno; 841 return param + 1; 842 } 843 } 844 else 845 { 846 *regnop = regno; 847 return param; 848 } 849 } 850 return NULL; 851 } 852 853 param = match_name (param, fcr_regs, regnop); 854 855 return param; 856 } 857 858 static char * 859 get_vec9 (param, valp) 860 char *param; 861 unsigned *valp; 862 { 863 unsigned val; 864 char *save_ptr; 865 866 save_ptr = input_line_pointer; 867 input_line_pointer = param; 868 val = get_absolute_expression (); 869 param = input_line_pointer; 870 input_line_pointer = save_ptr; 871 872 if (val >= 1 << 9) 873 as_warn (_("Expression truncated to 9 bits")); 874 875 *valp = val % (1 << 9); 876 877 return param; 878 } 879 880 static char * 881 get_o6 (param, valp) 882 char *param; 883 unsigned *valp; 884 { 885 unsigned val; 886 char *save_ptr; 887 888 save_ptr = input_line_pointer; 889 input_line_pointer = param; 890 val = get_absolute_expression (); 891 param = input_line_pointer; 892 input_line_pointer = save_ptr; 893 894 if (val & 0x3) 895 as_warn (_("Removed lower 2 bits of expression")); 896 897 *valp = val; 898 899 return(param); 900 } 901 902 #define hexval(z) \ 903 (isdigit (z) ? (z) - '0' : \ 904 islower (z) ? (z) - 'a' + 10 : \ 905 isupper (z) ? (z) - 'A' + 10 : -1) 906 907 static char * 908 getval (param, valp) 909 char *param; 910 unsigned int *valp; 911 { 912 unsigned int val = 0; 913 unsigned int c; 914 915 c = *param++; 916 if (c == '0') 917 { 918 c = *param++; 919 if (c == 'x' || c == 'X') 920 { 921 c = *param++; 922 c = hexval (c); 923 while (c < 16) 924 { 925 val = val * 16 + c; 926 c = *param++; 927 c = hexval (c); 928 } 929 } 930 else 931 { 932 c -= '0'; 933 while (c < 8) 934 { 935 val = val * 8 + c; 936 c = *param++ - '0'; 937 } 938 } 939 } 940 else 941 { 942 c -= '0'; 943 while (c < 10) 944 { 945 val = val * 10 + c; 946 c = *param++ - '0'; 947 } 948 } 949 950 *valp = val; 951 return param - 1; 952 } 953 954 void 955 md_number_to_chars (buf, val, nbytes) 956 char *buf; 957 valueT val; 958 int nbytes; 959 { 960 number_to_chars_bigendian (buf, val, nbytes); 961 } 962 963 #if 0 964 965 /* This routine is never called. What is it for? 966 Ian Taylor, Cygnus Support 13 Jul 1993 */ 967 968 void 969 md_number_to_imm (buf, val, nbytes, fixP, seg_type) 970 unsigned char *buf; 971 unsigned int val; 972 int nbytes; 973 fixS *fixP; 974 int seg_type; 975 { 976 if (seg_type != N_TEXT || fixP->fx_r_type == NO_RELOC) 977 { 978 switch (nbytes) 979 { 980 case 4: 981 *buf++ = val >> 24; 982 *buf++ = val >> 16; 983 case 2: 984 *buf++ = val >> 8; 985 case 1: 986 *buf = val; 987 break; 988 989 default: 990 abort (); 991 } 992 return; 993 } 994 995 switch (fixP->fx_r_type) 996 { 997 case RELOC_IW16: 998 buf[2] = val >> 8; 999 buf[3] = val; 1000 break; 1001 1002 case RELOC_LO16: 1003 buf[0] = val >> 8; 1004 buf[1] = val; 1005 break; 1006 1007 case RELOC_HI16: 1008 buf[0] = val >> 24; 1009 buf[1] = val >> 16; 1010 break; 1011 1012 case RELOC_PC16: 1013 val += 4; 1014 buf[0] = val >> 10; 1015 buf[1] = val >> 2; 1016 break; 1017 1018 case RELOC_PC26: 1019 val += 4; 1020 buf[0] |= (val >> 26) & 0x03; 1021 buf[1] = val >> 18; 1022 buf[2] = val >> 10; 1023 buf[3] = val >> 2; 1024 break; 1025 1026 case RELOC_32: 1027 buf[0] = val >> 24; 1028 buf[1] = val >> 16; 1029 buf[2] = val >> 8; 1030 buf[3] = val; 1031 break; 1032 1033 default: 1034 as_fatal (_("Bad relocation type")); 1035 break; 1036 } 1037 } 1038 1039 #endif /* 0 */ 1040 1041 void 1042 md_number_to_disp (buf, val, nbytes) 1043 char *buf; 1044 int val; 1045 int nbytes; 1046 { 1047 as_fatal (_("md_number_to_disp not defined")); 1048 md_number_to_chars (buf, val, nbytes); 1049 } 1050 1051 void 1052 md_number_to_field (buf, val, nbytes) 1053 char *buf; 1054 int val; 1055 int nbytes; 1056 { 1057 as_fatal (_("md_number_to_field not defined")); 1058 md_number_to_chars (buf, val, nbytes); 1059 } 1060 1061 #define MAX_LITTLENUMS 6 1062 1063 /* Turn a string in input_line_pointer into a floating point constant of type 1064 type, and store the appropriate bytes in *litP. The number of LITTLENUMS 1065 emitted is stored in *sizeP . An error message is returned, or NULL on OK. 1066 */ 1067 char * 1068 md_atof (type, litP, sizeP) 1069 char type; 1070 char *litP; 1071 int *sizeP; 1072 { 1073 int prec; 1074 LITTLENUM_TYPE words[MAX_LITTLENUMS]; 1075 LITTLENUM_TYPE *wordP; 1076 char *t; 1077 1078 switch (type) 1079 { 1080 case 'f': 1081 case 'F': 1082 case 's': 1083 case 'S': 1084 prec = 2; 1085 break; 1086 1087 case 'd': 1088 case 'D': 1089 case 'r': 1090 case 'R': 1091 prec = 4; 1092 break; 1093 1094 case 'x': 1095 case 'X': 1096 prec = 6; 1097 break; 1098 1099 case 'p': 1100 case 'P': 1101 prec = 6; 1102 break; 1103 1104 default: 1105 *sizeP = 0; 1106 return _("Bad call to MD_ATOF()"); 1107 } 1108 t = atof_ieee (input_line_pointer, type, words); 1109 if (t) 1110 input_line_pointer = t; 1111 1112 *sizeP = prec * sizeof (LITTLENUM_TYPE); 1113 for (wordP = words; prec--;) 1114 { 1115 md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE)); 1116 litP += sizeof (LITTLENUM_TYPE); 1117 } 1118 return 0; 1119 } 1120 1121 int md_short_jump_size = 4; 1122 1123 void 1124 md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) 1125 char *ptr; 1126 addressT from_addr, to_addr; 1127 fragS *frag; 1128 symbolS *to_symbol; 1129 { 1130 ptr[0] = (char) 0xc0; 1131 ptr[1] = 0x00; 1132 ptr[2] = 0x00; 1133 ptr[3] = 0x00; 1134 fix_new (frag, 1135 ptr - frag->fr_literal, 1136 4, 1137 to_symbol, 1138 (offsetT) 0, 1139 0, 1140 RELOC_PC26); /* Botch: Shouldn't this be RELOC_PC16? */ 1141 } 1142 1143 int md_long_jump_size = 4; 1144 1145 void 1146 md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) 1147 char *ptr; 1148 addressT from_addr, to_addr; 1149 fragS *frag; 1150 symbolS *to_symbol; 1151 { 1152 ptr[0] = (char) 0xc0; 1153 ptr[1] = 0x00; 1154 ptr[2] = 0x00; 1155 ptr[3] = 0x00; 1156 fix_new (frag, 1157 ptr - frag->fr_literal, 1158 4, 1159 to_symbol, 1160 (offsetT) 0, 1161 0, 1162 RELOC_PC26); 1163 } 1164 1165 int 1166 md_estimate_size_before_relax (fragP, segment_type) 1167 fragS *fragP; 1168 segT segment_type; 1169 { 1170 as_fatal (_("Relaxation should never occur")); 1171 return (-1); 1172 } 1173 1174 #if 0 1175 1176 /* As far as I can tell, this routine is never called. What is it 1177 doing here? 1178 Ian Taylor, Cygnus Support 13 Jul 1993 */ 1179 1180 /* 1181 * Risc relocations are completely different, so it needs 1182 * this machine dependent routine to emit them. 1183 */ 1184 void 1185 emit_relocations (fixP, segment_address_in_file) 1186 fixS *fixP; 1187 relax_addressT segment_address_in_file; 1188 { 1189 struct reloc_info_m88k ri; 1190 symbolS *symbolP; 1191 extern char *next_object_file_charP; 1192 1193 bzero ((char *) &ri, sizeof (ri)); 1194 for (; fixP; fixP = fixP->fx_next) 1195 { 1196 if (fixP->fx_r_type >= NO_RELOC) 1197 { 1198 fprintf (stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type); 1199 abort (); 1200 } 1201 1202 if ((symbolP = fixP->fx_addsy) != NULL) 1203 { 1204 ri.r_address = fixP->fx_frag->fr_address + 1205 fixP->fx_where - segment_address_in_file; 1206 if ((symbolP->sy_type & N_TYPE) == N_UNDF) 1207 { 1208 ri.r_extern = 1; 1209 ri.r_symbolnum = symbolP->sy_number; 1210 } 1211 else 1212 { 1213 ri.r_extern = 0; 1214 ri.r_symbolnum = symbolP->sy_type & N_TYPE; 1215 } 1216 if (symbolP && symbol_get_frag (symbolP)) 1217 { 1218 ri.r_addend = symbol_get_frag (symbolP)->fr_address; 1219 } 1220 ri.r_type = fixP->fx_r_type; 1221 if (fixP->fx_pcrel) 1222 { 1223 ri.r_addend -= ri.r_address; 1224 } 1225 else 1226 { 1227 ri.r_addend = fixP->fx_addnumber; 1228 } 1229 1230 append (&next_object_file_charP, (char *) &ri, sizeof (ri)); 1231 } 1232 } 1233 } 1234 1235 #endif /* 0 */ 1236 1237 #if 0 1238 1239 /* This routine can be subsumed by s_lcomm in read.c. 1240 Ian Taylor, Cygnus Support 13 Jul 1993 */ 1241 1242 static void 1243 s_bss () 1244 { 1245 char *name; 1246 char c; 1247 char *p; 1248 int temp, bss_align; 1249 symbolS *symbolP; 1250 1251 name = input_line_pointer; 1252 c = get_symbol_end (); 1253 p = input_line_pointer; 1254 *p = c; 1255 SKIP_WHITESPACE (); 1256 if (*input_line_pointer != ',') 1257 { 1258 as_warn (_("Expected comma after name")); 1259 ignore_rest_of_line (); 1260 return; 1261 } 1262 input_line_pointer++; 1263 if ((temp = get_absolute_expression ()) < 0) 1264 { 1265 as_warn (_("BSS length (%d.) <0! Ignored."), temp); 1266 ignore_rest_of_line (); 1267 return; 1268 } 1269 *p = 0; 1270 symbolP = symbol_find_or_make (name); 1271 *p = c; 1272 if (*input_line_pointer == ',') 1273 { 1274 input_line_pointer++; 1275 bss_align = get_absolute_expression (); 1276 } 1277 else 1278 bss_align = 0; 1279 1280 if (!S_IS_DEFINED(symbolP) 1281 || S_GET_SEGMENT(symbolP) == SEG_BSS) 1282 { 1283 if (! need_pass_2) 1284 { 1285 char *p; 1286 segT current_seg = now_seg; 1287 subsegT current_subseg = now_subseg; 1288 1289 subseg_set (SEG_BSS, 1); /* switch to bss */ 1290 1291 if (bss_align) 1292 frag_align (bss_align, 0, 0); 1293 1294 /* detach from old frag */ 1295 if (symbolP->sy_type == N_BSS && symbol_get_frag (symbolP) != NULL) 1296 symbol_get_frag (symbolP)->fr_symbol = NULL; 1297 1298 symbol_set_frag (symbolP, frag_now); 1299 p = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP, 1300 (offsetT) temp, (char *)0); 1301 *p = 0; 1302 S_SET_SEGMENT (symbolP, SEG_BSS); 1303 1304 subseg_set (current_seg, current_subseg); 1305 } 1306 } 1307 else 1308 { 1309 as_warn (_("Ignoring attempt to re-define symbol %s."), name); 1310 } 1311 1312 while (!is_end_of_line[(unsigned char) *input_line_pointer]) 1313 { 1314 input_line_pointer++; 1315 } 1316 } 1317 1318 #endif /* 0 */ 1319 1320 #ifdef M88KCOFF 1321 1322 /* These functions are needed if we are linking with obj-coffbfd.c. 1323 That file may be replaced by a more BFD oriented version at some 1324 point. If that happens, these functions should be rexamined. 1325 1326 Ian Lance Taylor, Cygnus Support, 13 July 1993. */ 1327 1328 /* Given a fixS structure (created by a call to fix_new, above), 1329 return the BFD relocation type to use for it. */ 1330 1331 short 1332 tc_coff_fix2rtype (fixp) 1333 fixS *fixp; 1334 { 1335 switch (fixp->fx_r_type) 1336 { 1337 case RELOC_LO16: 1338 return R_LVRT16; 1339 case RELOC_HI16: 1340 return R_HVRT16; 1341 case RELOC_PC16: 1342 return R_PCR16L; 1343 case RELOC_PC26: 1344 return R_PCR26L; 1345 case RELOC_32: 1346 return R_VRT32; 1347 case RELOC_IW16: 1348 return R_VRT16; 1349 default: 1350 abort (); 1351 } 1352 } 1353 1354 /* Apply a fixS to the object file. Since COFF does not use addends 1355 in relocs, the addend is actually stored directly in the object 1356 file itself. */ 1357 1358 void 1359 md_apply_fix (fixp, val) 1360 fixS *fixp; 1361 long val; 1362 { 1363 char *buf; 1364 1365 buf = fixp->fx_frag->fr_literal + fixp->fx_where; 1366 fixp->fx_offset = 0; 1367 1368 switch (fixp->fx_r_type) 1369 { 1370 case RELOC_IW16: 1371 fixp->fx_offset = val >> 16; 1372 buf[2] = val >> 8; 1373 buf[3] = val; 1374 break; 1375 1376 case RELOC_LO16: 1377 fixp->fx_offset = val >> 16; 1378 buf[0] = val >> 8; 1379 buf[1] = val; 1380 break; 1381 1382 case RELOC_HI16: 1383 fixp->fx_offset = val >> 16; 1384 buf[0] = val >> 8; 1385 buf[1] = val; 1386 break; 1387 1388 case RELOC_PC16: 1389 buf[0] = val >> 10; 1390 buf[1] = val >> 2; 1391 break; 1392 1393 case RELOC_PC26: 1394 buf[0] |= (val >> 26) & 0x03; 1395 buf[1] = val >> 18; 1396 buf[2] = val >> 10; 1397 buf[3] = val >> 2; 1398 break; 1399 1400 case RELOC_32: 1401 buf[0] = val >> 24; 1402 buf[1] = val >> 16; 1403 buf[2] = val >> 8; 1404 buf[3] = val; 1405 break; 1406 1407 default: 1408 abort (); 1409 } 1410 } 1411 1412 /* Where a PC relative offset is calculated from. On the m88k they 1413 are calculated from just after the instruction. */ 1414 1415 long 1416 md_pcrel_from (fixp) 1417 fixS *fixp; 1418 { 1419 switch (fixp->fx_r_type) 1420 { 1421 case RELOC_PC16: 1422 return fixp->fx_frag->fr_address + fixp->fx_where - 2; 1423 case RELOC_PC26: 1424 return fixp->fx_frag->fr_address + fixp->fx_where; 1425 default: 1426 abort (); 1427 } 1428 /*NOTREACHED*/ 1429 } 1430 1431 /* Fill in rs_align_code fragments. */ 1432 1433 void 1434 m88k_handle_align (fragp) 1435 fragS *fragp; 1436 { 1437 static const unsigned char nop_pattern[] = { 0xf4, 0x00, 0x58, 0x00 }; 1438 1439 int bytes; 1440 char *p; 1441 1442 if (fragp->fr_type != rs_align_code) 1443 return; 1444 1445 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; 1446 p = fragp->fr_literal + fragp->fr_fix; 1447 1448 if (bytes & 3) 1449 { 1450 int fix = bytes & 3; 1451 memset (p, 0, fix); 1452 p += fix; 1453 bytes -= fix; 1454 fragp->fr_fix += fix; 1455 } 1456 1457 memcpy (p, nop_pattern, 4); 1458 fragp->fr_var = 4; 1459 } 1460 1461 #endif /* M88KCOFF */ 1462