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, 2001, 2002 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 "as.h" 26 #include "safe-ctype.h" 27 #include "subsegs.h" 28 #include "m88k-opcode.h" 29 30 #if defined (OBJ_ELF) 31 #include "elf/m88k.h" 32 #endif 33 34 #define RELOC_LO16 BFD_RELOC_LO16 35 #define RELOC_HI16 BFD_RELOC_HI16 36 #define RELOC_PC16 BFD_RELOC_18_PCREL_S2 37 #define RELOC_PC26 BFD_RELOC_28_PCREL_S2 38 #define RELOC_32 BFD_RELOC_32 39 #define NO_RELOC BFD_RELOC_NONE 40 41 struct field_val_assoc 42 { 43 char *name; 44 unsigned val; 45 }; 46 47 struct field_val_assoc m88100_cr_regs[] = 48 { 49 {"PID", 0}, 50 {"PSR", 1}, 51 {"EPSR", 2}, 52 {"SSBR", 3}, 53 {"SXIP", 4}, 54 {"SNIP", 5}, 55 {"SFIP", 6}, 56 {"VBR", 7}, 57 {"DMT0", 8}, 58 {"DMD0", 9}, 59 {"DMA0", 10}, 60 {"DMT1", 11}, 61 {"DMD1", 12}, 62 {"DMA1", 13}, 63 {"DMT2", 14}, 64 {"DMD2", 15}, 65 {"DMA2", 16}, 66 {"SR0", 17}, 67 {"SR1", 18}, 68 {"SR2", 19}, 69 {"SR3", 20}, 70 71 {NULL, 0}, 72 }; 73 74 struct field_val_assoc m88110_cr_regs[] = 75 { 76 {"PID", 0}, 77 {"PSR", 1}, 78 {"EPSR", 2}, 79 {"EXIP", 4}, 80 {"ENIP", 5}, 81 {"VBR", 7}, 82 {"SRX", 16}, 83 {"SR0", 17}, 84 {"SR1", 18}, 85 {"SR2", 19}, 86 {"SR3", 20}, 87 {"ICMD", 25}, 88 {"ICTL", 26}, 89 {"ISAR", 27}, 90 {"ISAP", 28}, 91 {"IUAP", 29}, 92 {"IIR", 30}, 93 {"IBP", 31}, 94 {"IPPU", 32}, 95 {"IPPL", 33}, 96 {"ISR", 34}, 97 {"ILAR", 35}, 98 {"IPAR", 36}, 99 {"DCMD", 40}, 100 {"DCTL", 41}, 101 {"DSAR", 42}, 102 {"DSAP", 43}, 103 {"DUAP", 44}, 104 {"DIR", 45}, 105 {"DBP", 46}, 106 {"DPPU", 47}, 107 {"DPPL", 48}, 108 {"DSR", 49}, 109 {"DLAR", 50}, 110 {"DPAR", 51}, 111 112 {NULL, 0}, 113 }; 114 115 struct field_val_assoc fcr_regs[] = 116 { 117 {"FPECR", 0}, 118 {"FPHS1", 1}, 119 {"FPLS1", 2}, 120 {"FPHS2", 3}, 121 {"FPLS2", 4}, 122 {"FPPT", 5}, 123 {"FPRH", 6}, 124 {"FPRL", 7}, 125 {"FPIT", 8}, 126 127 {"FPSR", 62}, 128 {"FPCR", 63}, 129 130 {NULL, 0}, 131 }; 132 133 struct field_val_assoc cmpslot[] = 134 { 135 /* Integer Floating point */ 136 {"nc", 0}, 137 {"cp", 1}, 138 {"eq", 2}, 139 {"ne", 3}, 140 {"gt", 4}, 141 {"le", 5}, 142 {"lt", 6}, 143 {"ge", 7}, 144 {"hi", 8}, {"ou", 8}, 145 {"ls", 9}, {"ib", 9}, 146 {"lo", 10}, {"in", 10}, 147 {"hs", 11}, {"ob", 11}, 148 {"be", 12}, {"ue", 12}, 149 {"nb", 13}, {"lg", 13}, 150 {"he", 14}, {"ug", 14}, 151 {"nh", 15}, {"ule", 15}, 152 {"ul", 16}, 153 {"uge", 17}, 154 155 {NULL, 0}, 156 }; 157 158 struct field_val_assoc cndmsk[] = 159 { 160 {"gt0", 1}, 161 {"eq0", 2}, 162 {"ge0", 3}, 163 {"lt0", 12}, 164 {"ne0", 13}, 165 {"le0", 14}, 166 167 {NULL, 0}, 168 }; 169 170 struct m88k_insn 171 { 172 unsigned long opcode; 173 expressionS exp; 174 enum m88k_reloc_type reloc; 175 }; 176 177 static char *get_bf (char *param, unsigned *valp); 178 static char *get_cmp (char *param, unsigned *valp); 179 static char *get_cnd (char *param, unsigned *valp); 180 static char *get_bf2 (char *param, int bc); 181 static char *get_bf_offset_expression (char *param, unsigned *offsetp); 182 static char *get_cr (char *param, unsigned *regnop); 183 static char *get_fcr (char *param, unsigned *regnop); 184 static char *get_imm16 (char *param, struct m88k_insn *insn); 185 static char *get_o6 (char *param, unsigned *valp); 186 static char *match_name (char *, struct field_val_assoc *, unsigned *); 187 static char *get_reg (char *param, unsigned *regnop, unsigned int reg_prefix); 188 static char *get_vec9 (char *param, unsigned *valp); 189 static char *getval (char *param, unsigned int *valp); 190 static char *get_pcr (char *param, struct m88k_insn *insn, 191 enum m88k_reloc_type reloc); 192 193 static int calcop (struct m88k_opcode *format, 194 char *param, struct m88k_insn *insn); 195 196 static void s_m88k_88110 (int); 197 198 static struct hash_control *op_hash = NULL; 199 200 /* Current cpu (either 88100 or 88110, or 0 if unspecified). Defaults to 201 zero, overriden with -m<cpu> options or assembler pseudo-ops. */ 202 static int current_cpu = 0; 203 204 /* These chars start a comment anywhere in a source file (except inside 205 another comment. */ 206 #if defined(OBJ_ELF) 207 const char comment_chars[] = "|"; 208 #elif defined(OBJ_AOUT) 209 const char comment_chars[] = "|#"; 210 #else 211 const char comment_chars[] = ";"; 212 #endif 213 214 /* These chars only start a comment at the beginning of a line. */ 215 #if defined(OBJ_AOUT) 216 const char line_comment_chars[] = ";"; 217 #else 218 const char line_comment_chars[] = "#"; 219 #endif 220 221 #if defined(OBJ_ELF) 222 const char line_separator_chars[] = ";"; 223 #else 224 const char line_separator_chars[] = ""; 225 #endif 226 227 /* Chars that can be used to separate mant from exp in floating point nums */ 228 const char EXP_CHARS[] = "eE"; 229 230 /* Chars that mean this number is a floating point constant */ 231 /* as in 0f123.456 */ 232 /* or 0H1.234E-12 (see exp chars above) */ 233 const char FLT_CHARS[] = "dDfF"; 234 235 const pseudo_typeS md_pseudo_table[] = 236 { 237 #ifndef OBJ_ELF 238 {"align", s_align_bytes, 4}, 239 #else 240 /* handled with s_align_ptwo in read.c potable[] */ 241 #endif 242 {"bss", s_lcomm, 1}, 243 {"def", s_set, 0}, 244 {"half", cons, 2}, 245 {"requires_88110", s_m88k_88110, 0}, 246 {"sbss", s_lcomm, 1}, 247 #if !defined(OBJ_ELF) || !defined(TE_OpenBSD) /* i.e. NO_PSEUDO_DOT == 1 */ 248 /* Force set to be treated as an instruction. */ 249 {"set", NULL, 0}, 250 {".set", s_set, 0}, 251 #endif 252 {"uahalf", cons, 2}, 253 {"uaword", cons, 4}, 254 {"word", cons, 4}, /* override potable[] which has word == short */ 255 {NULL, NULL, 0} 256 }; 257 258 static void 259 s_m88k_88110(int i ATTRIBUTE_UNUSED) 260 { 261 current_cpu = 88110; 262 } 263 264 void 265 md_begin (void) 266 { 267 const char *retval = NULL; 268 unsigned int i = 0; 269 270 /* Initialize hash table. */ 271 op_hash = hash_new (); 272 273 while (*m88k_opcodes[i].name) 274 { 275 char *name = m88k_opcodes[i].name; 276 277 /* Hash each mnemonic and record its position. */ 278 retval = hash_insert (op_hash, name, &m88k_opcodes[i]); 279 280 if (retval != NULL) 281 as_fatal (_("Can't hash instruction '%s':%s"), 282 m88k_opcodes[i].name, retval); 283 284 /* Skip to next unique mnemonic or end of list. */ 285 for (i++; !strcmp (m88k_opcodes[i].name, name); i++) 286 ; 287 } 288 289 #ifdef OBJ_ELF 290 record_alignment (text_section, 2); 291 record_alignment (data_section, 2); 292 record_alignment (bss_section, 2); 293 294 bfd_set_private_flags (stdoutput, 0); 295 #endif 296 } 297 298 const char *md_shortopts = "m:"; 299 struct option md_longopts[] = { 300 {NULL, no_argument, NULL, 0} 301 }; 302 size_t md_longopts_size = sizeof (md_longopts); 303 304 int 305 md_parse_option (int c, char *arg) 306 { 307 switch (c) 308 { 309 case 'm': 310 if (strcmp (arg, "88100") == 0) 311 current_cpu = 88100; 312 else if (strcmp (arg, "88110") == 0) 313 current_cpu = 88110; 314 else 315 as_bad (_("Option `%s' is not recognized."), arg); 316 break; 317 318 default: 319 return 0; 320 } 321 322 return 1; 323 } 324 325 void 326 md_show_usage (FILE *stream) 327 { 328 fputs (_("\ 329 M88k options:\n\ 330 -m88100 | -m88110 select processor type\n"), 331 stream); 332 } 333 334 #ifdef OBJ_ELF 335 enum m88k_pic_reloc_type { 336 pic_reloc_none, 337 pic_reloc_abdiff, 338 pic_reloc_gotrel, 339 pic_reloc_plt 340 }; 341 342 static bfd_reloc_code_real_type 343 m88k_get_reloc_code(struct m88k_insn *insn) 344 { 345 switch (insn->exp.X_md) 346 { 347 default: 348 case pic_reloc_none: 349 return insn->reloc; 350 351 case pic_reloc_abdiff: 352 if (insn->reloc == BFD_RELOC_LO16) 353 return BFD_RELOC_LO16_BASEREL; 354 if (insn->reloc == BFD_RELOC_HI16) 355 return BFD_RELOC_HI16_BASEREL; 356 break; 357 358 case pic_reloc_gotrel: 359 if (insn->reloc == BFD_RELOC_LO16) 360 return BFD_RELOC_LO16_GOTOFF; 361 if (insn->reloc == BFD_RELOC_HI16) 362 return BFD_RELOC_HI16_GOTOFF; 363 break; 364 365 case pic_reloc_plt: 366 if (insn->reloc == BFD_RELOC_32) 367 return BFD_RELOC_32_PLTOFF; 368 if (insn->reloc == BFD_RELOC_28_PCREL_S2) 369 return BFD_RELOC_32_PLT_PCREL; 370 break; 371 } 372 373 as_bad ("Can't process pic type %d relocation type %d", 374 insn->exp.X_md, insn->reloc); 375 376 return BFD_RELOC_NONE; 377 } 378 #else 379 #define m88k_get_reloc_code(insn) (insn).reloc 380 #endif 381 382 void 383 md_assemble (char *op) 384 { 385 char *param, *thisfrag; 386 char c; 387 struct m88k_opcode *format; 388 struct m88k_insn insn; 389 fixS *fixP; 390 391 assert (op); 392 393 /* Skip over instruction to find parameters. */ 394 for (param = op; *param != 0 && !ISSPACE (*param); param++) 395 ; 396 c = *param; 397 *param++ = '\0'; 398 399 /* Try to find the instruction in the hash table. */ 400 /* XXX will not match XRF flavours of 88100 instructions on 88110 */ 401 if ((format = (struct m88k_opcode *) hash_find (op_hash, op)) == NULL) 402 { 403 as_bad (_("Invalid mnemonic '%s'"), op); 404 return; 405 } 406 407 /* Try parsing this instruction into insn. */ 408 insn.exp.X_add_symbol = 0; 409 insn.exp.X_op_symbol = 0; 410 insn.exp.X_add_number = 0; 411 insn.exp.X_op = O_illegal; 412 insn.exp.X_md = pic_reloc_none; 413 insn.reloc = NO_RELOC; 414 415 while (!calcop (format, param, &insn)) 416 { 417 /* If it doesn't parse try the next instruction. */ 418 if (!strcmp (format[0].name, format[1].name)) 419 format++; 420 else 421 { 422 as_fatal (_("Parameter syntax error")); 423 return; 424 } 425 } 426 427 /* Grow the current frag and plop in the opcode. */ 428 thisfrag = frag_more (4); 429 md_number_to_chars (thisfrag, insn.opcode, 4); 430 431 /* If this instruction requires labels mark it for later. */ 432 switch (insn.reloc) 433 { 434 case NO_RELOC: 435 break; 436 437 case RELOC_LO16: 438 case RELOC_HI16: 439 fixP = fix_new_exp (frag_now, 440 thisfrag - frag_now->fr_literal + 2, 441 2, 442 &insn.exp, 443 0, 444 m88k_get_reloc_code(&insn)); 445 fixP->fx_no_overflow = 1; 446 break; 447 448 #ifdef M88KCOFF 449 case RELOC_IW16: 450 fix_new_exp (frag_now, 451 thisfrag - frag_now->fr_literal, 452 4, 453 &insn.exp, 454 0, 455 m88k_get_reloc_code(&insn)); 456 break; 457 #endif 458 459 case RELOC_PC16: 460 #ifdef OBJ_ELF 461 fix_new_exp (frag_now, 462 thisfrag - frag_now->fr_literal , 463 4, 464 &insn.exp, 465 1, 466 m88k_get_reloc_code(&insn)); 467 #else 468 fix_new_exp (frag_now, 469 thisfrag - frag_now->fr_literal + 2, 470 2, 471 &insn.exp, 472 1, 473 m88k_get_reloc_code(&insn)); 474 #endif 475 break; 476 477 case RELOC_PC26: 478 fix_new_exp (frag_now, 479 thisfrag - frag_now->fr_literal, 480 4, 481 &insn.exp, 482 1, 483 m88k_get_reloc_code(&insn)); 484 break; 485 486 case RELOC_32: 487 fix_new_exp (frag_now, 488 thisfrag - frag_now->fr_literal, 489 4, 490 &insn.exp, 491 0, 492 m88k_get_reloc_code(&insn)); 493 break; 494 495 default: 496 as_fatal (_("Unknown relocation type")); 497 break; 498 } 499 } 500 501 static int 502 calcop (struct m88k_opcode *format, char *param, struct m88k_insn *insn) 503 { 504 char *fmt = format->op_spec; 505 int f; 506 unsigned val; 507 unsigned opcode; 508 unsigned int reg_prefix = 'r'; 509 510 insn->opcode = format->opcode; 511 opcode = 0; 512 513 /* 514 * Instructions which have no arguments (such as rte) will get 515 * correctly reported only if param == "", although there could be 516 * whitespace following the instruction. 517 * Rather than eating whitespace here, let's assume everything is 518 * fine. If there were non-wanted arguments, they will be parsed as 519 * an incorrect opcode at the offending line, so that's not too bad. 520 * -- miod 521 */ 522 if (*fmt == '\0') 523 return 1; 524 525 for (;;) 526 { 527 if (param == NULL) 528 return 0; 529 530 f = *fmt++; 531 switch (f) 532 { 533 case 0: 534 insn->opcode |= opcode; 535 return (*param == 0 || *param == '\n'); 536 537 default: 538 if (f != *param++) 539 return 0; 540 break; 541 542 case 'd': 543 param = get_reg (param, &val, reg_prefix); 544 reg_prefix = 'r'; 545 opcode |= val << 21; 546 break; 547 548 case 'o': 549 param = get_o6 (param, &val); 550 opcode |= ((val >> 2) << 7); 551 break; 552 553 case 'x': 554 reg_prefix = 'x'; 555 break; 556 557 case '1': 558 param = get_reg (param, &val, reg_prefix); 559 reg_prefix = 'r'; 560 opcode |= val << 16; 561 break; 562 563 case '2': 564 param = get_reg (param, &val, reg_prefix); 565 reg_prefix = 'r'; 566 opcode |= val; 567 break; 568 569 case '3': 570 param = get_reg (param, &val, 'r'); 571 opcode |= (val << 16) | val; 572 break; 573 574 case 'I': 575 param = get_imm16 (param, insn); 576 break; 577 578 case 'b': 579 param = get_bf (param, &val); 580 opcode |= val; 581 break; 582 583 case 'p': 584 param = get_pcr (param, insn, RELOC_PC16); 585 break; 586 587 case 'P': 588 param = get_pcr (param, insn, RELOC_PC26); 589 break; 590 591 case 'B': 592 param = get_cmp (param, &val); 593 opcode |= val; 594 break; 595 596 case 'M': 597 param = get_cnd (param, &val); 598 opcode |= val; 599 break; 600 601 case 'c': 602 param = get_cr (param, &val); 603 opcode |= val << 5; 604 break; 605 606 case 'f': 607 param = get_fcr (param, &val); 608 opcode |= val << 5; 609 break; 610 611 case 'V': 612 param = get_vec9 (param, &val); 613 opcode |= val; 614 break; 615 616 case '?': 617 /* Having this here repeats the warning sometimes. 618 But can't we stand that? */ 619 as_warn (_("Use of obsolete instruction")); 620 break; 621 } 622 } 623 } 624 625 static char * 626 match_name (char *param, struct field_val_assoc *assoc_tab, unsigned *valp) 627 { 628 int i; 629 char *name; 630 int name_len; 631 632 for (i = 0;; i++) 633 { 634 name = assoc_tab[i].name; 635 if (name == NULL) 636 return NULL; 637 name_len = strlen (name); 638 if (!strncmp (param, name, name_len)) 639 { 640 *valp = assoc_tab[i].val; 641 return param + name_len; 642 } 643 } 644 } 645 646 static char * 647 get_reg (char *param, unsigned *regnop, unsigned int reg_prefix) 648 { 649 unsigned c; 650 unsigned regno; 651 652 #ifdef REGISTER_PREFIX 653 c = *param++; 654 if (c != REGISTER_PREFIX) 655 return NULL; 656 #endif 657 658 c = *param++; 659 if (c == reg_prefix) 660 { 661 regno = *param++ - '0'; 662 if (regno < 10) 663 { 664 if (regno == 0) 665 { 666 *regnop = 0; 667 return param; 668 } 669 c = *param - '0'; 670 if (c < 10) 671 { 672 regno = regno * 10 + c; 673 if (c < 32) 674 { 675 *regnop = regno; 676 return param + 1; 677 } 678 } 679 else 680 { 681 *regnop = regno; 682 return param; 683 } 684 } 685 return NULL; 686 } 687 else if (c == 's' && param[0] == 'p') 688 { 689 *regnop = 31; 690 return param + 1; 691 } 692 693 return NULL; 694 } 695 696 static char * 697 get_imm16 (char *param, struct m88k_insn *insn) 698 { 699 enum m88k_reloc_type reloc = NO_RELOC; 700 unsigned int val; 701 char *save_ptr; 702 #ifdef REGISTER_PREFIX 703 int found_prefix = 0; 704 #endif 705 706 #ifdef REGISTER_PREFIX 707 if (*param == REGISTER_PREFIX) 708 { 709 param++; 710 found_prefix = 1; 711 } 712 #endif 713 714 if (!strncmp (param, "hi16", 4) && !ISALNUM (param[4])) 715 { 716 reloc = RELOC_HI16; 717 param += 4; 718 } 719 else if (!strncmp (param, "lo16", 4) && !ISALNUM (param[4])) 720 { 721 reloc = RELOC_LO16; 722 param += 4; 723 } 724 #ifdef M88KCOFF 725 else if (!strncmp (param, "iw16", 4) && !ISALNUM (param[4])) 726 { 727 reloc = RELOC_IW16; 728 param += 4; 729 } 730 #endif 731 732 #ifdef REGISTER_PREFIX 733 if (found_prefix && reloc == NO_RELOC) 734 return NULL; 735 #endif 736 737 save_ptr = input_line_pointer; 738 input_line_pointer = param; 739 expression (&insn->exp); 740 param = input_line_pointer; 741 input_line_pointer = save_ptr; 742 743 val = insn->exp.X_add_number; 744 745 if (insn->exp.X_op == O_constant) 746 { 747 /* Insert the value now, and reset reloc to NO_RELOC. */ 748 if (reloc == NO_RELOC) 749 { 750 /* Warn about too big expressions if not surrounded by xx16. */ 751 if (val > 0xffff) 752 as_warn (_("Expression truncated to 16 bits")); 753 } 754 755 if (reloc == RELOC_HI16) 756 val >>= 16; 757 758 insn->opcode |= val & 0xffff; 759 reloc = NO_RELOC; 760 } 761 else if (reloc == NO_RELOC) 762 /* We accept a symbol even without lo16, hi16, etc, and assume 763 lo16 was intended. */ 764 reloc = RELOC_LO16; 765 766 insn->reloc = reloc; 767 768 return param; 769 } 770 771 static char * 772 get_pcr (char *param, struct m88k_insn *insn, enum m88k_reloc_type reloc) 773 { 774 char *saveptr, *saveparam; 775 776 saveptr = input_line_pointer; 777 input_line_pointer = param; 778 779 expression (&insn->exp); 780 781 saveparam = input_line_pointer; 782 input_line_pointer = saveptr; 783 784 /* Botch: We should relocate now if O_constant. */ 785 insn->reloc = reloc; 786 787 return saveparam; 788 } 789 790 static char * 791 get_cmp (char *param, unsigned *valp) 792 { 793 unsigned int val; 794 char *save_ptr; 795 796 save_ptr = param; 797 798 #ifdef REGISTER_PREFIX 799 /* SVR4 compiler prefixes condition codes with the register prefix */ 800 if (*param == REGISTER_PREFIX) 801 param++; 802 #endif 803 param = match_name (param, cmpslot, valp); 804 val = *valp; 805 806 if (param == NULL) 807 { 808 param = save_ptr; 809 810 save_ptr = input_line_pointer; 811 input_line_pointer = param; 812 val = get_absolute_expression (); 813 param = input_line_pointer; 814 input_line_pointer = save_ptr; 815 816 if (val >= 32) 817 { 818 as_warn (_("Expression truncated to 5 bits")); 819 val %= 32; 820 } 821 } 822 823 *valp = val << 21; 824 return param; 825 } 826 827 static char * 828 get_cnd (char *param, unsigned *valp) 829 { 830 unsigned int val; 831 832 if (ISDIGIT (*param)) 833 { 834 param = getval (param, &val); 835 836 if (val >= 32) 837 { 838 as_warn (_("Expression truncated to 5 bits")); 839 val %= 32; 840 } 841 } 842 else 843 { 844 #ifdef REGISTER_PREFIX 845 /* SVR4 compiler prefixes condition codes with the register prefix */ 846 if (*param == REGISTER_PREFIX) 847 param++; 848 #endif 849 850 param[0] = TOLOWER (param[0]); 851 param[1] = TOLOWER (param[1]); 852 853 param = match_name (param, cndmsk, valp); 854 855 if (param == NULL) 856 return NULL; 857 858 val = *valp; 859 } 860 861 *valp = val << 21; 862 return param; 863 } 864 865 static char * 866 get_bf2 (char *param, int bc) 867 { 868 int depth = 0; 869 int c; 870 871 for (;;) 872 { 873 c = *param; 874 if (c == 0) 875 return param; 876 else if (c == '(') 877 depth++; 878 else if (c == ')') 879 depth--; 880 else if (c == bc && depth <= 0) 881 return param; 882 param++; 883 } 884 } 885 886 static char * 887 get_bf_offset_expression (char *param, unsigned *offsetp) 888 { 889 unsigned offset; 890 891 #ifdef REGISTER_PREFIX 892 /* SVR4 compiler prefixes condition codes with the register prefix */ 893 if (*param == REGISTER_PREFIX && ISALPHA (param[1])) 894 param++; 895 #endif 896 897 if (ISALPHA (param[0])) 898 { 899 param[0] = TOLOWER (param[0]); 900 param[1] = TOLOWER (param[1]); 901 902 param = match_name (param, cmpslot, offsetp); 903 904 return param; 905 } 906 else 907 { 908 input_line_pointer = param; 909 offset = get_absolute_expression (); 910 param = input_line_pointer; 911 } 912 913 *offsetp = offset; 914 return param; 915 } 916 917 static char * 918 get_bf (char *param, unsigned *valp) 919 { 920 unsigned offset = 0; 921 unsigned width = 0; 922 char *xp; 923 char *save_ptr; 924 925 xp = get_bf2 (param, '<'); 926 927 save_ptr = input_line_pointer; 928 input_line_pointer = param; 929 if (*xp == 0) 930 { 931 /* We did not find '<'. We have an offset (width implicitly 32). */ 932 param = get_bf_offset_expression (param, &offset); 933 input_line_pointer = save_ptr; 934 if (param == NULL) 935 return NULL; 936 } 937 else 938 { 939 *xp++ = 0; /* Overwrite the '<' */ 940 param = get_bf2 (xp, '>'); 941 if (*param == 0) 942 return NULL; 943 *param++ = 0; /* Overwrite the '>' */ 944 945 width = get_absolute_expression (); 946 xp = get_bf_offset_expression (xp, &offset); 947 input_line_pointer = save_ptr; 948 949 if (xp + 1 != param) 950 return NULL; 951 } 952 953 *valp = ((width % 32) << 5) | (offset % 32); 954 955 return param; 956 } 957 958 static char * 959 get_cr (char *param, unsigned *regnop) 960 { 961 unsigned regno; 962 unsigned c; 963 964 #ifdef REGISTER_PREFIX 965 if (*param++ != REGISTER_PREFIX) 966 return NULL; 967 #endif 968 969 if (!strncmp (param, "cr", 2)) 970 { 971 param += 2; 972 973 regno = *param++ - '0'; 974 if (regno < 10) 975 { 976 if (regno == 0) 977 { 978 *regnop = 0; 979 return param; 980 } 981 c = *param - '0'; 982 if (c < 10) 983 { 984 regno = regno * 10 + c; 985 if (c < 64) 986 { 987 *regnop = regno; 988 return param + 1; 989 } 990 } 991 else 992 { 993 *regnop = regno; 994 return param; 995 } 996 } 997 return NULL; 998 } 999 1000 param = match_name (param, 1001 current_cpu == 88110 ? m88110_cr_regs : m88100_cr_regs, 1002 regnop); 1003 1004 return param; 1005 } 1006 1007 static char * 1008 get_fcr (char *param, unsigned *regnop) 1009 { 1010 unsigned regno; 1011 unsigned c; 1012 1013 #ifdef REGISTER_PREFIX 1014 if (*param++ != REGISTER_PREFIX) 1015 return NULL; 1016 #endif 1017 1018 if (!strncmp (param, "fcr", 3)) 1019 { 1020 param += 3; 1021 1022 regno = *param++ - '0'; 1023 if (regno < 10) 1024 { 1025 if (regno == 0) 1026 { 1027 *regnop = 0; 1028 return param; 1029 } 1030 c = *param - '0'; 1031 if (c < 10) 1032 { 1033 regno = regno * 10 + c; 1034 if (c < 64) 1035 { 1036 *regnop = regno; 1037 return param + 1; 1038 } 1039 } 1040 else 1041 { 1042 *regnop = regno; 1043 return param; 1044 } 1045 } 1046 return NULL; 1047 } 1048 1049 param = match_name (param, fcr_regs, regnop); 1050 1051 return param; 1052 } 1053 1054 static char * 1055 get_vec9 (char *param, unsigned *valp) 1056 { 1057 unsigned val; 1058 char *save_ptr; 1059 1060 save_ptr = input_line_pointer; 1061 input_line_pointer = param; 1062 val = get_absolute_expression (); 1063 param = input_line_pointer; 1064 input_line_pointer = save_ptr; 1065 1066 if (val >= 1 << 9) 1067 as_warn (_("Expression truncated to 9 bits")); 1068 1069 *valp = val % (1 << 9); 1070 1071 return param; 1072 } 1073 1074 static char * 1075 get_o6 (char *param, unsigned *valp) 1076 { 1077 unsigned val; 1078 char *save_ptr; 1079 1080 save_ptr = input_line_pointer; 1081 input_line_pointer = param; 1082 val = get_absolute_expression (); 1083 param = input_line_pointer; 1084 input_line_pointer = save_ptr; 1085 1086 if (val & 0x3) 1087 as_warn (_("Removed lower 2 bits of expression")); 1088 1089 *valp = val; 1090 1091 return (param); 1092 } 1093 1094 #define hexval(z) \ 1095 (ISDIGIT (z) ? (z) - '0' : \ 1096 ISLOWER (z) ? (z) - 'a' + 10 : \ 1097 ISUPPER (z) ? (z) - 'A' + 10 : (unsigned) -1) 1098 1099 static char * 1100 getval (char *param, unsigned int *valp) 1101 { 1102 unsigned int val = 0; 1103 unsigned int c; 1104 1105 c = *param++; 1106 if (c == '0') 1107 { 1108 c = *param++; 1109 if (c == 'x' || c == 'X') 1110 { 1111 c = *param++; 1112 c = hexval (c); 1113 while (c < 16) 1114 { 1115 val = val * 16 + c; 1116 c = *param++; 1117 c = hexval (c); 1118 } 1119 } 1120 else 1121 { 1122 c -= '0'; 1123 while (c < 8) 1124 { 1125 val = val * 8 + c; 1126 c = *param++ - '0'; 1127 } 1128 } 1129 } 1130 else 1131 { 1132 c -= '0'; 1133 while (c < 10) 1134 { 1135 val = val * 10 + c; 1136 c = *param++ - '0'; 1137 } 1138 } 1139 1140 *valp = val; 1141 return param - 1; 1142 } 1143 1144 void 1145 md_number_to_chars (char *buf, valueT val, int nbytes) 1146 { 1147 number_to_chars_bigendian (buf, val, nbytes); 1148 } 1149 1150 #define MAX_LITTLENUMS 6 1151 1152 /* Turn a string in input_line_pointer into a floating point constant of type 1153 type, and store the appropriate bytes in *litP. The number of LITTLENUMS 1154 emitted is stored in *sizeP . An error message is returned, or NULL on OK. 1155 */ 1156 char * 1157 md_atof (int type, char *litP, int *sizeP) 1158 { 1159 int prec; 1160 LITTLENUM_TYPE words[MAX_LITTLENUMS]; 1161 LITTLENUM_TYPE *wordP; 1162 char *t; 1163 1164 switch (type) 1165 { 1166 case 'f': 1167 case 'F': 1168 case 's': 1169 case 'S': 1170 prec = 2; 1171 break; 1172 1173 case 'd': 1174 case 'D': 1175 case 'r': 1176 case 'R': 1177 prec = 4; 1178 break; 1179 1180 case 'x': 1181 case 'X': 1182 prec = 6; 1183 break; 1184 1185 case 'p': 1186 case 'P': 1187 prec = 6; 1188 break; 1189 1190 default: 1191 *sizeP = 0; 1192 return _("Bad call to MD_ATOF()"); 1193 } 1194 t = atof_ieee (input_line_pointer, type, words); 1195 if (t) 1196 input_line_pointer = t; 1197 1198 *sizeP = prec * sizeof (LITTLENUM_TYPE); 1199 for (wordP = words; prec--;) 1200 { 1201 md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE)); 1202 litP += sizeof (LITTLENUM_TYPE); 1203 } 1204 return 0; 1205 } 1206 1207 int md_short_jump_size = 4; 1208 int md_long_jump_size = 4; 1209 1210 void 1211 md_create_short_jump (char *ptr, addressT from_addr ATTRIBUTE_UNUSED, 1212 addressT to_addr ATTRIBUTE_UNUSED, fragS *frag, symbolS *to_symbol) 1213 { 1214 /* Since all instructions have the same width, it does not make sense to 1215 try and abuse a conditional instruction to get a short displacement 1216 (such as bb1 0, %r0, address). */ 1217 md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol); 1218 } 1219 1220 void 1221 md_create_long_jump (char *ptr, addressT from_addr ATTRIBUTE_UNUSED, 1222 addressT to_addr ATTRIBUTE_UNUSED, fragS *frag, symbolS *to_symbol) 1223 { 1224 ptr[0] = (char) 0xc0; /* br to_addr */ 1225 ptr[1] = 0x00; 1226 ptr[2] = 0x00; 1227 ptr[3] = 0x00; 1228 fix_new (frag, 1229 ptr - frag->fr_literal, 1230 4, 1231 to_symbol, 1232 (offsetT) 0, 1233 0, 1234 RELOC_PC26); 1235 } 1236 1237 int 1238 md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED, 1239 segT segment_type ATTRIBUTE_UNUSED) 1240 { 1241 as_fatal (_("Relaxation should never occur")); 1242 return (-1); 1243 } 1244 1245 #ifdef M88KCOFF 1246 1247 /* These functions are needed if we are linking with obj-coffbfd.c. 1248 That file may be replaced by a more BFD oriented version at some 1249 point. If that happens, these functions should be reexamined. 1250 1251 Ian Lance Taylor, Cygnus Support, 13 July 1993. */ 1252 1253 /* Given a fixS structure (created by a call to fix_new, above), 1254 return the BFD relocation type to use for it. */ 1255 1256 short 1257 tc_coff_fix2rtype (fixS *fixp) 1258 { 1259 switch (fixp->fx_r_type) 1260 { 1261 case RELOC_LO16: 1262 return R_LVRT16; 1263 case RELOC_HI16: 1264 return R_HVRT16; 1265 case RELOC_PC16: 1266 return R_PCR16L; 1267 case RELOC_PC26: 1268 return R_PCR26L; 1269 case RELOC_32: 1270 return R_VRT32; 1271 case RELOC_IW16: 1272 return R_VRT16; 1273 default: 1274 abort (); 1275 } 1276 } 1277 1278 /* Apply a fixS to the object file. Since COFF does not use addends 1279 in relocs, the addend is actually stored directly in the object 1280 file itself. */ 1281 1282 void 1283 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) 1284 { 1285 long val = * (long *) valP; 1286 char *buf; 1287 1288 buf = fixP->fx_frag->fr_literal + fixP->fx_where; 1289 fixP->fx_addnumber = val; 1290 fixP->fx_offset = 0; 1291 1292 switch (fixP->fx_r_type) 1293 { 1294 case RELOC_IW16: 1295 fixP->fx_offset = val >> 16; 1296 buf[2] = val >> 8; 1297 buf[3] = val; 1298 break; 1299 1300 case RELOC_LO16: 1301 fixP->fx_offset = val >> 16; 1302 buf[0] = val >> 8; 1303 buf[1] = val; 1304 break; 1305 1306 case RELOC_HI16: 1307 buf[0] = val >> 24; 1308 buf[1] = val >> 16; 1309 break; 1310 1311 case RELOC_PC16: 1312 buf[0] = val >> 10; 1313 buf[1] = val >> 2; 1314 break; 1315 1316 case RELOC_PC26: 1317 buf[0] |= (val >> 26) & 0x03; 1318 buf[1] = val >> 18; 1319 buf[2] = val >> 10; 1320 buf[3] = val >> 2; 1321 break; 1322 1323 case RELOC_32: 1324 buf[0] = val >> 24; 1325 buf[1] = val >> 16; 1326 buf[2] = val >> 8; 1327 buf[3] = val; 1328 break; 1329 1330 default: 1331 abort (); 1332 } 1333 1334 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) 1335 fixP->fx_done = 1; 1336 } 1337 1338 #endif /* M88KCOFF */ 1339 1340 /* Fill in rs_align_code fragments. */ 1341 1342 void 1343 m88k_handle_align (fragS *fragp) 1344 { 1345 static const unsigned char nop_pattern[] = { 0xf4, 0x00, 0x58, 0x00 }; 1346 1347 int bytes; 1348 char *p; 1349 1350 if (fragp->fr_type != rs_align_code) 1351 return; 1352 1353 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; 1354 p = fragp->fr_literal + fragp->fr_fix; 1355 1356 if (bytes & 3) 1357 { 1358 int fix = bytes & 3; 1359 memset (p, 0, fix); 1360 p += fix; 1361 bytes -= fix; 1362 fragp->fr_fix += fix; 1363 } 1364 1365 memcpy (p, nop_pattern, 4); 1366 fragp->fr_var = 4; 1367 } 1368 1369 /* Where a PC relative offset is calculated from. On the m88k they 1370 are calculated from just after the instruction. */ 1371 1372 long 1373 md_pcrel_from (fixS *fixp) 1374 { 1375 switch (fixp->fx_r_type) 1376 { 1377 case RELOC_PC16: 1378 #ifdef OBJ_ELF 1379 /* FALLTHROUGH */ 1380 #else 1381 return fixp->fx_frag->fr_address + fixp->fx_where - 2; 1382 #endif 1383 case RELOC_PC26: 1384 #ifdef OBJ_ELF 1385 case BFD_RELOC_32_PLT_PCREL: 1386 #endif 1387 return fixp->fx_frag->fr_address + fixp->fx_where; 1388 default: 1389 abort (); 1390 } 1391 /*NOTREACHED*/ 1392 } 1393 1394 #ifdef OBJ_ELF 1395 1396 valueT 1397 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) 1398 { 1399 return size; 1400 } 1401 1402 /* Generate the BFD reloc to be stuck in the object file from the 1403 fixup used internally in the assembler. */ 1404 1405 arelent * 1406 tc_gen_reloc (asection *sec ATTRIBUTE_UNUSED, fixS *fixp) 1407 { 1408 arelent *reloc; 1409 bfd_reloc_code_real_type code; 1410 1411 reloc = (arelent *) xmalloc (sizeof (arelent)); 1412 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); 1413 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 1414 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; 1415 1416 /* Make sure none of our internal relocations make it this far. 1417 They'd better have been fully resolved by this point. */ 1418 assert ((int) fixp->fx_r_type > 0); 1419 1420 code = fixp->fx_r_type; 1421 reloc->howto = bfd_reloc_type_lookup (stdoutput, code); 1422 if (reloc->howto == NULL) 1423 { 1424 as_bad_where (fixp->fx_file, fixp->fx_line, 1425 _("cannot represent `%s' relocation in object file"), 1426 bfd_get_reloc_code_name (code)); 1427 return NULL; 1428 } 1429 1430 if (!fixp->fx_pcrel != !reloc->howto->pc_relative) 1431 { 1432 as_fatal (_("internal error? cannot generate `%s' relocation"), 1433 bfd_get_reloc_code_name (code)); 1434 } 1435 assert (!fixp->fx_pcrel == !reloc->howto->pc_relative); 1436 1437 reloc->addend = fixp->fx_offset; 1438 1439 return reloc; 1440 } 1441 1442 /* Apply a fixS to the object file. This is called for all the 1443 fixups we generated by the call to fix_new_exp, above. In the call 1444 above we used a reloc code which was the largest legal reloc code 1445 plus the operand index. Here we undo that to recover the operand 1446 index. At this point all symbol values should be fully resolved, 1447 and we attempt to completely resolve the reloc. If we can not do 1448 that, we determine the correct reloc code and put it back in the 1449 fixup. 1450 1451 This is the ELF version. 1452 */ 1453 1454 void 1455 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) 1456 { 1457 valueT val = * (valueT *) valP; 1458 char *buf; 1459 long insn; 1460 1461 buf = fixP->fx_frag->fr_literal + fixP->fx_where; 1462 1463 if (fixP->fx_subsy != NULL) 1464 as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex")); 1465 1466 if (fixP->fx_addsy) 1467 { 1468 #if 0 1469 /* can't empty 26-bit relocation values with memset() */ 1470 if (fixP->fx_r_type == BFD_RELOC_28_PCREL_S2) 1471 { 1472 insn = bfd_getb32 ((unsigned char *) buf); 1473 insn &= ~0x03ffffff; 1474 bfd_putb32(insn, buf); 1475 } 1476 else 1477 memset(buf, 0, fixP->fx_size); 1478 #endif 1479 1480 if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT 1481 && !S_IS_DEFINED (fixP->fx_addsy) 1482 && !S_IS_WEAK (fixP->fx_addsy)) 1483 S_SET_WEAK (fixP->fx_addsy); 1484 1485 return; 1486 } 1487 1488 switch (fixP->fx_r_type) 1489 { 1490 case BFD_RELOC_VTABLE_INHERIT: 1491 case BFD_RELOC_VTABLE_ENTRY: 1492 return; 1493 1494 case BFD_RELOC_HI16_BASEREL: 1495 case BFD_RELOC_LO16_BASEREL: 1496 case BFD_RELOC_HI16_GOTOFF: 1497 case BFD_RELOC_LO16_GOTOFF: 1498 case BFD_RELOC_32_PLTOFF: 1499 return; 1500 1501 case BFD_RELOC_LO16: 1502 case BFD_RELOC_HI16: 1503 if (fixP->fx_pcrel) 1504 abort (); 1505 buf[0] = val >> 8; 1506 buf[1] = val; 1507 break; 1508 1509 case BFD_RELOC_18_PCREL_S2: 1510 if ((val & 0x03) != 0) 1511 as_bad_where (fixP->fx_file, fixP->fx_line, 1512 "Branch to unaligned address (%lx)", (long)val); 1513 buf[2] = val >> 10; 1514 buf[3] = val >> 2; 1515 break; 1516 1517 case BFD_RELOC_32_PLT_PCREL: 1518 case BFD_RELOC_28_PCREL_S2: 1519 if ((val & 0x03) != 0) 1520 as_bad_where (fixP->fx_file, fixP->fx_line, 1521 "Branch to unaligned address (%lx)", (long)val); 1522 buf[0] |= (val >> 26) & 0x03; 1523 buf[1] = val >> 18; 1524 buf[2] = val >> 10; 1525 buf[3] = val >> 2; 1526 break; 1527 1528 case BFD_RELOC_32: 1529 insn = val; 1530 bfd_putb32(insn, buf); 1531 break; 1532 1533 default: 1534 abort (); 1535 } 1536 1537 if (/* fixP->fx_addsy == NULL && */ fixP->fx_pcrel == 0) 1538 fixP->fx_done = 1; 1539 } 1540 1541 /* Set the ELF specific flags. */ 1542 void 1543 m88k_elf_final_processing (void) 1544 { 1545 if (current_cpu == 88110) 1546 elf_elfheader (stdoutput)->e_flags |= EF_M88110; 1547 } 1548 1549 inline static char * 1550 m88k_end_of_name (char *suffix, const char *pattern, size_t patlen) 1551 { 1552 if (strncmp (suffix, pattern, patlen) == 0 1553 && ! is_part_of_name (suffix[patlen])) 1554 return suffix + patlen; 1555 1556 return NULL; 1557 } 1558 1559 int 1560 m88k_parse_name (const char *name, expressionS *expressionP, char *nextcharP) 1561 { 1562 char *next = input_line_pointer; 1563 char *next_end; 1564 enum m88k_pic_reloc_type reloc_type = pic_reloc_none; 1565 symbolS *symbolP; 1566 segT segment; 1567 1568 if (*nextcharP != '#') 1569 return 0; 1570 1571 if ((next_end = m88k_end_of_name (next + 1, "abdiff", 6)) != NULL) 1572 { 1573 reloc_type = pic_reloc_abdiff; 1574 } 1575 else if ((next_end = m88k_end_of_name (next + 1, "got_rel", 7)) != NULL) 1576 { 1577 reloc_type = pic_reloc_gotrel; 1578 } 1579 else if ((next_end = m88k_end_of_name (next + 1, "plt", 3)) != NULL) 1580 { 1581 reloc_type = pic_reloc_plt; 1582 } 1583 else 1584 return 0; 1585 1586 symbolP = symbol_find_or_make (name); 1587 segment = S_GET_SEGMENT (symbolP); 1588 if (segment == absolute_section) 1589 { 1590 expressionP->X_op = O_constant; 1591 expressionP->X_add_number = S_GET_VALUE (symbolP); 1592 } 1593 else if (segment == reg_section) 1594 { 1595 expressionP->X_op = O_register; 1596 expressionP->X_add_number = S_GET_VALUE (symbolP); 1597 } 1598 else 1599 { 1600 expressionP->X_op = O_symbol; 1601 expressionP->X_add_symbol = symbolP; 1602 expressionP->X_add_number = 0; 1603 } 1604 expressionP->X_md = reloc_type; 1605 1606 *input_line_pointer = *nextcharP; 1607 input_line_pointer = next_end; 1608 *nextcharP = *input_line_pointer; 1609 *input_line_pointer = '\0'; 1610 1611 return 1; 1612 } 1613 1614 int 1615 m88k_fix_adjustable (fixS *fix) 1616 { 1617 return (fix->fx_r_type != BFD_RELOC_LO16_GOTOFF 1618 && fix->fx_r_type != BFD_RELOC_HI16_GOTOFF 1619 && fix->fx_r_type != BFD_RELOC_VTABLE_INHERIT 1620 && fix->fx_r_type != BFD_RELOC_VTABLE_ENTRY 1621 && (fix->fx_pcrel 1622 || (fix->fx_subsy != NULL 1623 && (S_GET_SEGMENT (fix->fx_subsy) 1624 == S_GET_SEGMENT (fix->fx_addsy))) 1625 || S_IS_LOCAL (fix->fx_addsy))); 1626 } 1627 #endif /* OBJ_ELF */ 1628 1629 #ifdef OBJ_AOUT 1630 1631 /* Round up a section size to the appropriate boundary. */ 1632 valueT 1633 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) 1634 { 1635 /* For a.out, force the section size to be aligned. If we don't do 1636 this, BFD will align it for us, but it will not write out the 1637 final bytes of the section. This may be a bug in BFD, but it is 1638 easier to fix it here since that is how the other a.out targets 1639 work. */ 1640 int align; 1641 1642 align = bfd_get_section_alignment (stdoutput, segment); 1643 valueT mask = ((valueT) 1 << align) - 1; 1644 1645 return (size + mask) & ~mask; 1646 } 1647 1648 const int md_reloc_size = 12; /* sizeof(struct relocation_info); */ 1649 1650 void 1651 tc_aout_fix_to_chars (char *where, fixS *fixP, 1652 relax_addressT segment_address_in_file) 1653 { 1654 long r_symbolnum; 1655 long r_addend = 0; 1656 long r_address; 1657 1658 know (fixP->fx_addsy != NULL); 1659 1660 r_address = fixP->fx_frag->fr_address + fixP->fx_where 1661 - segment_address_in_file; 1662 md_number_to_chars (where, r_address, 4); 1663 1664 r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy) 1665 ? S_GET_TYPE (fixP->fx_addsy) 1666 : fixP->fx_addsy->sy_number); 1667 1668 where[4] = (r_symbolnum >> 16) & 0x0ff; 1669 where[5] = (r_symbolnum >> 8) & 0x0ff; 1670 where[6] = r_symbolnum & 0x0ff; 1671 where[7] = ((((!S_IS_DEFINED (fixP->fx_addsy)) << 7) & 0x80) | (0 & 0x70) | 1672 (fixP->fx_r_type & 0xf)); 1673 1674 if (fixP->fx_addsy->sy_frag) { 1675 r_addend = fixP->fx_addsy->sy_frag->fr_address; 1676 } 1677 1678 if (fixP->fx_pcrel) { 1679 r_addend -= r_address; 1680 } else { 1681 r_addend = fixP->fx_addnumber; 1682 } 1683 1684 md_number_to_chars(&where[8], r_addend, 4); 1685 } 1686 1687 void 1688 tc_headers_hook (object_headers *headers) 1689 { 1690 #if defined(TE_NetBSD) || defined(TE_OpenBSD) 1691 N_SET_INFO(headers->header, OMAGIC, M_88K_OPENBSD, 0); 1692 headers->header.a_info = htonl(headers->header.a_info); 1693 #endif 1694 } 1695 1696 #endif /* OBJ_AOUT */ 1697