1 /* Assembly backend for the OpenRISC 1000. 2 Copyright (C) 2002 Free Software Foundation, Inc. 3 Contributed by Damjan Lampret <lampret@opencores.org>. 4 Modified bu Johan Rydberg, <johan.rydberg@netinsight.se>. 5 Based upon a29k port. 6 7 This file is part of GAS, the GNU Assembler. 8 9 GAS is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2, or (at your option) 12 any later version. 13 14 GAS is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with GAS; see the file COPYING. If not, write to 21 the Free Software Foundation, 59 Temple Place - Suite 330, 22 Boston, MA 02111-1307, USA. */ 23 24 /* tc-a29k.c used as a template. */ 25 26 #include "safe-ctype.h" 27 #include "as.h" 28 #include "opcode/or32.h" 29 30 #ifdef BFD_ASSEMBLER 31 #include "elf/or32.h" 32 #endif 33 34 #define DEBUG 0 35 36 #ifndef REGISTER_PREFIX 37 #define REGISTER_PREFIX '%' 38 #endif 39 40 /* Make it easier to clone this machine desc into another one. */ 41 #define machine_opcode or32_opcode 42 #define machine_opcodes or32_opcodes 43 #define machine_ip or32_ip 44 #define machine_it or32_it 45 46 /* Handle of the OPCODE hash table. */ 47 static struct hash_control *op_hash = NULL; 48 49 struct machine_it 50 { 51 char * error; 52 unsigned long opcode; 53 struct nlist * nlistp; 54 expressionS exp; 55 int pcrel; 56 int reloc_offset; /* Offset of reloc within insn. */ 57 int reloc; 58 } 59 the_insn; 60 61 static void machine_ip PARAMS ((char *)); 62 63 const pseudo_typeS md_pseudo_table[] = 64 { 65 {"align", s_align_bytes, 4 }, 66 {"space", s_space, 0 }, 67 {"cputype", s_ignore, 0 }, 68 {"reg", s_lsym, 0 }, /* Register equate, same as equ. */ 69 {"sect", s_ignore, 0 }, /* Creation of coff sections. */ 70 {"proc", s_ignore, 0 }, /* Start of a function. */ 71 {"endproc", s_ignore, 0 }, /* Function end. */ 72 {"word", cons, 4 }, 73 {NULL, 0, 0 }, 74 }; 75 76 int md_short_jump_size = 4; 77 int md_long_jump_size = 4; 78 79 #if defined(BFD_HEADERS) 80 #ifdef RELSZ 81 const int md_reloc_size = RELSZ; /* Coff headers. */ 82 #else 83 const int md_reloc_size = 12; /* Something else headers. */ 84 #endif 85 #else 86 const int md_reloc_size = 12; /* Not bfdized. */ 87 #endif 88 89 /* This array holds the chars that always start a comment. 90 If the pre-processor is disabled, these aren't very useful. */ 91 const char comment_chars[] = "#"; 92 93 /* This array holds the chars that only start a comment at the beginning of 94 a line. If the line seems to have the form '# 123 filename' 95 .line and .file directives will appear in the pre-processed output. */ 96 /* Note that input_file.c hand checks for '#' at the beginning of the 97 first line of the input file. This is because the compiler outputs 98 #NO_APP at the beginning of its output. */ 99 /* Also note that comments like this one will always work. */ 100 const char line_comment_chars[] = "#"; 101 102 /* We needed an unused char for line separation to work around the 103 lack of macros, using sed and such. */ 104 const char line_separator_chars[] = ";"; 105 106 /* Chars that can be used to separate mant from exp in floating point nums. */ 107 const char EXP_CHARS[] = "eE"; 108 109 /* Chars that mean this number is a floating point constant. 110 As in 0f12.456 111 or 0d1.2345e12. */ 112 const char FLT_CHARS[] = "rRsSfFdDxXpP"; 113 114 /* "l.jalr r9" precalculated opcode. */ 115 static unsigned long jalr_r9_opcode; 116 117 118 static int check_invalid_opcode PARAMS ((unsigned long)); 119 static void encode PARAMS ((const struct machine_opcode *, unsigned long *, signed long, char)); 120 static char *parse_operand PARAMS ((char *, expressionS *, int)); 121 122 /* Set bits in machine opcode according to insn->encoding 123 description and passed operand. */ 124 125 static void 126 encode (insn, opcode, param_val, param_ch) 127 const struct machine_opcode *insn; 128 unsigned long *opcode; 129 signed long param_val; 130 char param_ch; 131 { 132 int opc_pos = 0; 133 int param_pos = 0; 134 char *enc; 135 136 #if DEBUG 137 printf (" encode: opcode=%.8lx param_val=%.8lx abs=%.8lx param_ch=%c\n", 138 *opcode, param_val, abs (param_val), param_ch); 139 #endif 140 for (enc = insn->encoding; *enc != '\0'; enc++) 141 if (*enc == param_ch) 142 { 143 if (enc - 2 >= insn->encoding && (*(enc - 2) == '0') && (*(enc - 1) == 'x')) 144 continue; 145 else 146 param_pos ++; 147 } 148 149 opc_pos = 32; 150 151 for (enc = insn->encoding; *enc != '\0';) 152 { 153 if ((*enc == '0') && (*(enc + 1) == 'x')) 154 { 155 int tmp = strtol (enc, NULL, 16); 156 157 opc_pos -= 4; 158 *opcode |= tmp << opc_pos; 159 enc += 3; 160 } 161 else if ((*enc == '0') || (*enc == '-')) 162 { 163 opc_pos--; 164 enc++; 165 } 166 else if (*enc == '1') 167 { 168 opc_pos--; 169 *opcode |= 1 << opc_pos; 170 enc++; 171 } 172 else if (*enc == param_ch) 173 { 174 opc_pos--; 175 param_pos--; 176 *opcode |= ((param_val >> param_pos) & 0x1) << opc_pos; 177 enc++; 178 } 179 else if (ISALPHA (*enc)) 180 { 181 opc_pos--; 182 enc++; 183 } 184 else 185 enc++; 186 } 187 188 #if DEBUG 189 printf (" opcode=%.8lx\n", *opcode); 190 #endif 191 } 192 193 /* This function is called once, at assembler startup time. It should 194 set up all the tables, etc., that the MD part of the assembler will 195 need. */ 196 197 void 198 md_begin () 199 { 200 const char *retval = NULL; 201 int lose = 0; 202 int skipnext = 0; 203 unsigned int i; 204 205 /* Hash up all the opcodes for fast use later. */ 206 op_hash = hash_new (); 207 208 for (i = 0; i < or32_num_opcodes; i++) 209 { 210 const char *name = machine_opcodes[i].name; 211 212 if (skipnext) 213 { 214 skipnext = 0; 215 continue; 216 } 217 218 retval = hash_insert (op_hash, name, (PTR) &machine_opcodes[i]); 219 if (retval != NULL) 220 { 221 fprintf (stderr, "internal error: can't hash `%s': %s\n", 222 machine_opcodes[i].name, retval); 223 lose = 1; 224 } 225 } 226 227 if (lose) 228 as_fatal (_("Broken assembler. No assembly attempted.")); 229 230 encode (&machine_opcodes[insn_index ("l.jalr")], &jalr_r9_opcode, 9, 'B'); 231 } 232 233 /* Returns non zero if instruction is to be used. */ 234 235 static int 236 check_invalid_opcode (opcode) 237 unsigned long opcode; 238 { 239 return opcode == jalr_r9_opcode; 240 } 241 242 /* Assemble a single instruction. Its label has already been handled 243 by the generic front end. We just parse opcode and operands, and 244 produce the bytes of data and relocation. */ 245 246 void 247 md_assemble (str) 248 char *str; 249 { 250 char *toP; 251 252 #if DEBUG 253 printf ("NEW INSTRUCTION\n"); 254 #endif 255 256 know (str); 257 machine_ip (str); 258 toP = frag_more (4); 259 260 /* Put out the opcode. */ 261 md_number_to_chars (toP, the_insn.opcode, 4); 262 263 /* Put out the symbol-dependent stuff. */ 264 #ifdef BFD_ASSEMBLER 265 if (the_insn.reloc != BFD_RELOC_NONE) 266 #else 267 if (the_insn.reloc != NO_RELOC) 268 #endif 269 { 270 fix_new_exp (frag_now, 271 (toP - frag_now->fr_literal + the_insn.reloc_offset), 272 4, /* size */ 273 &the_insn.exp, 274 the_insn.pcrel, 275 the_insn.reloc); 276 } 277 } 278 279 /* This is true of the we have issued a "lo(" or "hi"(. */ 280 static int waiting_for_shift = 0; 281 282 static int mask_or_shift = 0; 283 284 #ifdef BFD_ASSEMBLER 285 static char * 286 parse_operand (s, operandp, opt) 287 char *s; 288 expressionS *operandp; 289 int opt; 290 { 291 char *save = input_line_pointer; 292 char *new; 293 294 #if DEBUG 295 printf (" PROCESS NEW OPERAND(%s) == %c (%d)\n", s, opt ? opt : '!', opt); 296 #endif 297 298 input_line_pointer = s; 299 300 if (strncasecmp (s, "HI(", 3) == 0) 301 { 302 waiting_for_shift = 1; 303 mask_or_shift = BFD_RELOC_HI16; 304 305 input_line_pointer += 3; 306 } 307 else if (strncasecmp (s, "LO(", 3) == 0) 308 { 309 mask_or_shift = BFD_RELOC_LO16; 310 311 input_line_pointer += 3; 312 } 313 else 314 mask_or_shift = 0; 315 316 if ((*s == '(') && (*(s+1) == 'r')) 317 s++; 318 319 if ((*s == 'r') && ISDIGIT (*(s + 1))) 320 { 321 operandp->X_add_number = strtol (s + 1, NULL, 10); 322 operandp->X_op = O_register; 323 for (; (*s != ',') && (*s != '\0');) 324 s++; 325 input_line_pointer = save; 326 return s; 327 } 328 329 expression (operandp); 330 331 if (operandp->X_op == O_absent) 332 { 333 if (! opt) 334 as_bad (_("missing operand")); 335 else 336 { 337 operandp->X_add_number = 0; 338 operandp->X_op = O_constant; 339 } 340 } 341 342 new = input_line_pointer; 343 input_line_pointer = save; 344 345 #if DEBUG 346 printf (" %s=parse_operand(%s): operandp->X_op = %u\n", new, s, operandp->X_op); 347 #endif 348 349 return new; 350 } 351 #else 352 353 static char * 354 parse_operand (s, operandp, opt) 355 char *s; 356 expressionS *operandp; 357 int opt; 358 { 359 char *save = input_line_pointer; 360 char *new; 361 362 #if DEBUG 363 printf (" PROCESS NEW OPERAND(%s) == %c (%d)\n", s, opt ? opt : '!', opt); 364 #endif 365 366 input_line_pointer = s; 367 368 if (strncasecmp (s, "HI(", 3) == 0) 369 { 370 waiting_for_shift = 1; 371 mask_or_shift = RELOC_CONSTH; 372 373 input_line_pointer += 3; 374 } 375 else if (strncasecmp (s, "LO(", 3) == 0) 376 { 377 mask_or_shift = RELOC_CONST; 378 379 input_line_pointer += 3; 380 } 381 else 382 mask_or_shift = 0; 383 384 385 expression (operandp); 386 387 if (operandp->X_op == O_absent) 388 { 389 if (! opt) 390 as_bad (_("missing operand")); 391 else 392 { 393 operandp->X_add_number = 0; 394 operandp->X_op = O_constant; 395 } 396 } 397 398 new = input_line_pointer; 399 input_line_pointer = save; 400 401 if ((operandp->X_op == O_symbol) && (*s != '_')) 402 { 403 #if DEBUG 404 printf ("symbol: '%s'\n", save); 405 #endif 406 407 for (save = s; s < new; s++) 408 if ((*s == REGISTER_PREFIX) && (*(s + 1) == 'r')) /* Register prefix. */ 409 s++; 410 411 if ((*s == 'r') && ISDIGIT (*(s + 1))) 412 { 413 operandp->X_add_number = strtol (s + 1, NULL, 10); 414 operandp->X_op = O_register; 415 } 416 s = save; 417 } 418 419 #if DEBUG 420 printf (" %s=parse_operand(%s): operandp->X_op = %u\n", new, s, operandp->X_op); 421 #endif 422 423 return new; 424 } 425 #endif 426 427 /* Instruction parsing. Takes a string containing the opcode. 428 Operands are at input_line_pointer. Output is in the_insn. 429 Warnings or errors are generated. */ 430 431 #ifdef BFD_ASSEMBLER 432 static void 433 machine_ip (str) 434 char *str; 435 { 436 char *s; 437 const char *args; 438 const struct machine_opcode *insn; 439 char *argsStart; 440 unsigned long opcode; 441 expressionS the_operand; 442 expressionS *operand = &the_operand; 443 unsigned int regno; 444 int reloc = BFD_RELOC_NONE; 445 446 #if DEBUG 447 printf ("machine_ip(%s)\n", str); 448 #endif 449 450 s = str; 451 for (; ISALNUM (*s) || *s == '.'; ++s) 452 if (ISUPPER (*s)) 453 *s = TOLOWER (*s); 454 455 switch (*s) 456 { 457 case '\0': 458 break; 459 460 case ' ': /* FIXME-SOMEDAY more whitespace. */ 461 *s++ = '\0'; 462 break; 463 464 default: 465 as_bad (_("unknown opcode1: `%s'"), str); 466 return; 467 } 468 469 if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL) 470 { 471 as_bad (_("unknown opcode2 `%s'."), str); 472 return; 473 } 474 475 argsStart = s; 476 opcode = 0; 477 memset (&the_insn, '\0', sizeof (the_insn)); 478 the_insn.reloc = BFD_RELOC_NONE; 479 480 reloc = BFD_RELOC_NONE; 481 482 /* Build the opcode, checking as we go to make sure that the 483 operands match. 484 485 If an operand matches, we modify the_insn or opcode appropriately, 486 and do a "continue". If an operand fails to match, we "break". */ 487 if (insn->args[0] != '\0') 488 { 489 /* Prime the pump. */ 490 s = parse_operand (s, operand, insn->args[0] == 'I'); 491 } 492 493 for (args = insn->args;; ++args) 494 { 495 #if DEBUG 496 printf (" args = %s\n", args); 497 #endif 498 switch (*args) 499 { 500 case '\0': /* End of args. */ 501 /* We have have 0 args, do the bazoooka! */ 502 if (args == insn->args) 503 encode (insn, &opcode, 0, 0); 504 505 if (*s == '\0') 506 { 507 /* We are truly done. */ 508 the_insn.opcode = opcode; 509 if (check_invalid_opcode (opcode)) 510 as_bad (_("instruction not allowed: %s"), str); 511 return; 512 } 513 as_bad (_("too many operands: %s"), s); 514 break; 515 516 case ',': /* Must match a comma. */ 517 if (*s++ == ',') 518 { 519 reloc = BFD_RELOC_NONE; 520 521 /* Parse next operand. */ 522 s = parse_operand (s, operand, args[1] == 'I'); 523 #if DEBUG 524 printf (" ',' case: operand->X_add_number = %d, *args = %s, *s = %s\n", 525 operand->X_add_number, args, s); 526 #endif 527 continue; 528 } 529 break; 530 531 case '(': /* Must match a (. */ 532 s = parse_operand (s, operand, args[1] == 'I'); 533 continue; 534 535 case ')': /* Must match a ). */ 536 continue; 537 538 case 'r': /* A general register. */ 539 args++; 540 541 if (operand->X_op != O_register) 542 break; /* Only registers. */ 543 544 know (operand->X_add_symbol == 0); 545 know (operand->X_op_symbol == 0); 546 regno = operand->X_add_number; 547 encode (insn, &opcode, regno, *args); 548 #if DEBUG 549 printf (" r: operand->X_op = %d\n", operand->X_op); 550 #endif 551 continue; 552 553 default: 554 /* if (! ISALPHA (*args)) 555 break; */ /* Only immediate values. */ 556 557 if (mask_or_shift) 558 { 559 #if DEBUG 560 printf ("mask_or_shift = %d\n", mask_or_shift); 561 #endif 562 reloc = mask_or_shift; 563 } 564 mask_or_shift = 0; 565 566 if (strncasecmp (args, "LO(", 3) == 0) 567 { 568 #if DEBUG 569 printf ("reloc_const\n"); 570 #endif 571 reloc = BFD_RELOC_LO16; 572 } 573 else if (strncasecmp (args, "HI(", 3) == 0) 574 { 575 #if DEBUG 576 printf ("reloc_consth\n"); 577 #endif 578 reloc = BFD_RELOC_HI16; 579 } 580 581 if (*s == '(') 582 { 583 operand->X_op = O_constant; 584 #if 0 585 operand->X_add_number = 0; /* ??? if enabled load/store offsets 586 are zero. */ 587 #endif 588 } 589 else if (*s == ')') 590 s += 1; 591 #if DEBUG 592 printf (" default case: operand->X_add_number = %d, *args = %s, *s = %s\n", operand->X_add_number, args, s); 593 #endif 594 if (operand->X_op == O_constant) 595 { 596 if (reloc == BFD_RELOC_NONE) 597 { 598 bfd_vma v, mask; 599 600 mask = 0x3ffffff; 601 v = abs (operand->X_add_number) & ~ mask; 602 if (v) 603 as_bad (_("call/jmp target out of range (1)")); 604 } 605 606 if (reloc == BFD_RELOC_HI16) 607 operand->X_add_number = ((operand->X_add_number >> 16) & 0xffff); 608 609 the_insn.pcrel = 0; 610 encode (insn, &opcode, operand->X_add_number, *args); 611 /* the_insn.reloc = BFD_RELOC_NONE; */ 612 continue; 613 } 614 615 if (reloc == BFD_RELOC_NONE) 616 the_insn.reloc = BFD_RELOC_32_GOT_PCREL; 617 else 618 the_insn.reloc = reloc; 619 620 /* the_insn.reloc = insn->reloc; */ 621 #if DEBUG 622 printf (" reloc sym=%d\n", the_insn.reloc); 623 printf (" BFD_RELOC_NONE=%d\n", BFD_RELOC_NONE); 624 #endif 625 the_insn.exp = *operand; 626 627 /* the_insn.reloc_offset = 1; */ 628 the_insn.pcrel = 1; /* Assume PC-relative jump. */ 629 630 /* FIXME-SOON, Do we figure out whether abs later, after 631 know sym val? */ 632 if (reloc == BFD_RELOC_LO16 || reloc == BFD_RELOC_HI16) 633 the_insn.pcrel = 0; 634 635 encode (insn, &opcode, operand->X_add_number, *args); 636 continue; 637 } 638 639 /* Types or values of args don't match. */ 640 as_bad (_("invalid operands")); 641 return; 642 } 643 } 644 645 #else 646 647 static void 648 machine_ip (str) 649 char *str; 650 { 651 char *s; 652 const char *args; 653 const struct machine_opcode *insn; 654 char *argsStart; 655 unsigned long opcode; 656 expressionS the_operand; 657 expressionS *operand = &the_operand; 658 unsigned int regno; 659 int reloc = NO_RELOC; 660 661 #if DEBUG 662 printf ("machine_ip(%s)\n", str); 663 #endif 664 665 s = str; 666 for (; ISALNUM (*s) || *s == '.'; ++s) 667 if (ISUPPER (*s)) 668 *s = TOLOWER (*s); 669 670 switch (*s) 671 { 672 case '\0': 673 break; 674 675 case ' ': /* FIXME-SOMEDAY more whitespace. */ 676 *s++ = '\0'; 677 break; 678 679 default: 680 as_bad (_("unknown opcode1: `%s'"), str); 681 return; 682 } 683 684 if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL) 685 { 686 as_bad (_("unknown opcode2 `%s'."), str); 687 return; 688 } 689 690 argsStart = s; 691 opcode = 0; 692 memset (&the_insn, '\0', sizeof (the_insn)); 693 the_insn.reloc = NO_RELOC; 694 695 reloc = NO_RELOC; 696 697 /* Build the opcode, checking as we go to make sure that the 698 operands match. 699 700 If an operand matches, we modify the_insn or opcode appropriately, 701 and do a "continue". If an operand fails to match, we "break". */ 702 if (insn->args[0] != '\0') 703 /* Prime the pump. */ 704 s = parse_operand (s, operand, 705 insn->args[0] == 'I' 706 || strcmp (insn->name, "l.nop") == 0); 707 708 for (args = insn->args;; ++args) 709 { 710 #if DEBUG 711 printf (" args = %s\n", args); 712 #endif 713 switch (*args) 714 { 715 case '\0': /* End of args. */ 716 /* We have have 0 args, do the bazoooka! */ 717 if (args == insn->args) 718 encode (insn, &opcode, 0, 0); 719 720 if (*s == '\0') 721 { 722 /* We are truly done. */ 723 the_insn.opcode = opcode; 724 if (check_invalid_opcode (opcode)) 725 as_bad (_("instruction not allowed: %s"), str); 726 return; 727 } 728 as_bad (_("too many operands: %s"), s); 729 break; 730 731 case ',': /* Must match a comma. */ 732 if (*s++ == ',') 733 { 734 reloc = NO_RELOC; 735 736 /* Parse next operand. */ 737 s = parse_operand (s, operand, args[1] == 'I'); 738 #if DEBUG 739 printf (" ',' case: operand->X_add_number = %d, *args = %s, *s = %s\n", 740 operand->X_add_number, args, s); 741 #endif 742 continue; 743 } 744 break; 745 746 case '(': /* Must match a (. */ 747 s = parse_operand (s, operand, args[1] == 'I'); 748 continue; 749 750 case ')': /* Must match a ). */ 751 continue; 752 753 case 'r': /* A general register. */ 754 args++; 755 756 if (operand->X_op != O_register) 757 break; /* Only registers. */ 758 759 know (operand->X_add_symbol == 0); 760 know (operand->X_op_symbol == 0); 761 regno = operand->X_add_number; 762 encode (insn, &opcode, regno, *args); 763 #if DEBUG 764 printf (" r: operand->X_op = %d\n", operand->X_op); 765 #endif 766 continue; 767 768 default: 769 /* if (! ISALPHA (*args)) 770 break; */ /* Only immediate values. */ 771 772 if (mask_or_shift) 773 { 774 #if DEBUG 775 printf ("mask_or_shift = %d\n", mask_or_shift); 776 #endif 777 reloc = mask_or_shift; 778 } 779 mask_or_shift = 0; 780 781 if (strncasecmp (args, "LO(", 3) == 0) 782 { 783 #if DEBUG 784 printf ("reloc_const\n"); 785 #endif 786 reloc = RELOC_CONST; 787 } 788 else if (strncasecmp (args, "HI(", 3) == 0) 789 { 790 #if DEBUG 791 printf ("reloc_consth\n"); 792 #endif 793 reloc = RELOC_CONSTH; 794 } 795 796 if (*s == '(') 797 { 798 operand->X_op = O_constant; 799 #if 0 800 operand->X_add_number = 0; /* ??? if enabled load/store offsets 801 are zero. */ 802 #endif 803 } 804 else if (*s == ')') 805 s += 1; 806 #if DEBUG 807 printf (" default case: operand->X_add_number = %d, *args = %s, *s = %s\n", 808 operand->X_add_number, args, s); 809 #endif 810 if (operand->X_op == O_constant) 811 { 812 if (reloc == NO_RELOC) 813 { 814 unsigned long v, mask; 815 816 mask = 0x3ffffff; 817 v = abs (operand->X_add_number) & ~ mask; 818 if (v) 819 as_bad (_("call/jmp target out of range (1)")); 820 } 821 822 if (reloc == RELOC_CONSTH) 823 operand->X_add_number = ((operand->X_add_number>>16) & 0xffff); 824 825 the_insn.pcrel = 0; 826 encode (insn, &opcode, operand->X_add_number, *args); 827 /* the_insn.reloc = NO_RELOC; */ 828 continue; 829 } 830 831 if (reloc == NO_RELOC) 832 the_insn.reloc = RELOC_JUMPTARG; 833 else 834 the_insn.reloc = reloc; 835 #if DEBUG 836 printf (" reloc sym=%d\n", the_insn.reloc); 837 printf (" NO_RELOC=%d\n", NO_RELOC); 838 #endif 839 the_insn.exp = *operand; 840 841 /* the_insn.reloc_offset = 1; */ 842 the_insn.pcrel = 1; /* Assume PC-relative jump. */ 843 844 /* FIXME-SOON, Do we figure out whether abs later, after 845 know sym val? */ 846 if (reloc == RELOC_CONST || reloc == RELOC_CONSTH) 847 the_insn.pcrel = 0; 848 849 encode (insn, &opcode, operand->X_add_number, *args); 850 continue; 851 } 852 853 /* Types or values of args don't match. */ 854 as_bad (_("invalid operands")); 855 return; 856 } 857 } 858 #endif 859 860 /* This is identical to the md_atof in m68k.c. I think this is right, 861 but I'm not sure. 862 863 Turn a string in input_line_pointer into a floating point constant 864 of type type, and store the appropriate bytes in *litP. The number 865 of LITTLENUMS emitted is stored in *sizeP . An error message is 866 returned, or NULL on OK. */ 867 868 /* Equal to MAX_PRECISION in atof-ieee.c. */ 869 #define MAX_LITTLENUMS 6 870 871 char * 872 md_atof (type, litP, sizeP) 873 char type; 874 char * litP; 875 int * sizeP; 876 { 877 int prec; 878 LITTLENUM_TYPE words[MAX_LITTLENUMS]; 879 LITTLENUM_TYPE *wordP; 880 char *t; 881 882 switch (type) 883 { 884 case 'f': 885 case 'F': 886 case 's': 887 case 'S': 888 prec = 2; 889 break; 890 891 case 'd': 892 case 'D': 893 case 'r': 894 case 'R': 895 prec = 4; 896 break; 897 898 case 'x': 899 case 'X': 900 prec = 6; 901 break; 902 903 case 'p': 904 case 'P': 905 prec = 6; 906 break; 907 908 default: 909 *sizeP = 0; 910 return _("Bad call to MD_ATOF()"); 911 } 912 913 t = atof_ieee (input_line_pointer, type, words); 914 if (t) 915 input_line_pointer = t; 916 917 *sizeP = prec * sizeof (LITTLENUM_TYPE); 918 919 for (wordP = words; prec--;) 920 { 921 md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE)); 922 litP += sizeof (LITTLENUM_TYPE); 923 } 924 925 return NULL; 926 } 927 928 /* Write out big-endian. */ 929 930 void 931 md_number_to_chars (buf, val, n) 932 char *buf; 933 valueT val; 934 int n; 935 { 936 number_to_chars_bigendian (buf, val, n); 937 } 938 939 #ifdef BFD_ASSEMBLER 940 void 941 md_apply_fix3 (fixP, val, seg) 942 fixS * fixP; 943 valueT * val; 944 segT seg ATTRIBUTE_UNUSED; 945 { 946 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; 947 long t_val; 948 949 t_val = (long) *val; 950 951 #if DEBUG 952 printf ("md_apply_fix val:%x\n", t_val); 953 #endif 954 955 fixP->fx_addnumber = t_val; /* Remember value for emit_reloc. */ 956 957 know (fixP->fx_size == 4); 958 know (fixP->fx_r_type < BFD_RELOC_NONE); 959 960 switch (fixP->fx_r_type) 961 { 962 case BFD_RELOC_32: /* XXXXXXXX pattern in a word. */ 963 #if DEBUG 964 printf ("reloc_const: val=%x\n", t_val); 965 #endif 966 buf[0] = t_val >> 24; 967 buf[1] = t_val >> 16; 968 buf[2] = t_val >> 8; 969 buf[3] = t_val; 970 break; 971 972 case BFD_RELOC_16: /* XXXX0000 pattern in a word. */ 973 #if DEBUG 974 printf ("reloc_const: val=%x\n", t_val); 975 #endif 976 buf[0] = t_val >> 8; 977 buf[1] = t_val; 978 break; 979 980 case BFD_RELOC_8: /* XX000000 pattern in a word. */ 981 #if DEBUG 982 printf ("reloc_const: val=%x\n", t_val); 983 #endif 984 buf[0] = t_val; 985 break; 986 987 case BFD_RELOC_LO16: /* 0000XXXX pattern in a word. */ 988 #if DEBUG 989 printf ("reloc_const: val=%x\n", t_val); 990 #endif 991 buf[2] = t_val >> 8; /* Holds bits 0000XXXX. */ 992 buf[3] = t_val; 993 break; 994 995 case BFD_RELOC_HI16: /* 0000XXXX pattern in a word. */ 996 #if DEBUG 997 printf ("reloc_consth: val=%x\n", t_val); 998 #endif 999 buf[2] = t_val >> 24; /* Holds bits XXXX0000. */ 1000 buf[3] = t_val >> 16; 1001 break; 1002 1003 case BFD_RELOC_32_GOT_PCREL: /* 0000XXXX pattern in a word. */ 1004 if (!fixP->fx_done) 1005 { 1006 /* The linker tries to support both AMD and old GNU style 1007 R_IREL relocs. That means that if the addend is exactly 1008 the negative of the address within the section, the 1009 linker will not handle it correctly. */ 1010 #if 0 1011 if (fixP->fx_pcrel 1012 && t_val != 0 1013 && t_val == - (fixP->fx_frag->fr_address + fixP->fx_where)) 1014 as_bad_where 1015 (fixP->fx_file, fixP->fx_line, 1016 _("the linker will not handle this relocation correctly (1)")); 1017 #endif 1018 } 1019 else if (fixP->fx_pcrel) 1020 { 1021 long v = t_val >> 28; 1022 1023 if (v != 0 && v != -1) 1024 as_bad_where (fixP->fx_file, fixP->fx_line, 1025 _("call/jmp target out of range (2)")); 1026 } 1027 else 1028 /* This case was supposed to be handled in machine_ip. */ 1029 abort (); 1030 1031 buf[0] |= (t_val >> 26) & 0x03; /* Holds bits 0FFFFFFC of address. */ 1032 buf[1] = t_val >> 18; 1033 buf[2] = t_val >> 10; 1034 buf[3] = t_val >> 2; 1035 break; 1036 1037 case BFD_RELOC_VTABLE_INHERIT: 1038 case BFD_RELOC_VTABLE_ENTRY: 1039 fixP->fx_done = 0; 1040 break; 1041 1042 case BFD_RELOC_NONE: 1043 default: 1044 as_bad (_("bad relocation type: 0x%02x"), fixP->fx_r_type); 1045 break; 1046 } 1047 1048 if (fixP->fx_addsy == (symbolS *) NULL) 1049 fixP->fx_done = 1; 1050 } 1051 #else 1052 void 1053 md_apply_fix3 (fixP, valP, seg) 1054 fixS *fixP; 1055 valueT *valP; 1056 segT seg ATTRIBUTE_UNUSED; 1057 { 1058 long val = *valP; 1059 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; 1060 1061 #if DEBUG 1062 printf ("md_apply_fix val:%x\n", val); 1063 #endif 1064 1065 fixP->fx_addnumber = val; /* Remember value for emit_reloc. */ 1066 1067 know (fixP->fx_size == 4); 1068 know (fixP->fx_r_type < NO_RELOC); 1069 1070 /* This is a hack. There should be a better way to handle this. */ 1071 if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy) 1072 val += fixP->fx_where + fixP->fx_frag->fr_address; 1073 1074 switch (fixP->fx_r_type) 1075 { 1076 case RELOC_32: 1077 buf[0] = val >> 24; 1078 buf[1] = val >> 16; 1079 buf[2] = val >> 8; 1080 buf[3] = val; 1081 break; 1082 1083 case RELOC_8: 1084 buf[0] = val; 1085 break; 1086 1087 case RELOC_WDISP30: 1088 val = (val >> 2) + 1; 1089 buf[0] |= (val >> 24) & 0x3f; 1090 buf[1] = (val >> 16); 1091 buf[2] = val >> 8; 1092 buf[3] = val; 1093 break; 1094 1095 case RELOC_HI22: 1096 buf[1] |= (val >> 26) & 0x3f; 1097 buf[2] = val >> 18; 1098 buf[3] = val >> 10; 1099 break; 1100 1101 case RELOC_LO10: 1102 buf[2] |= (val >> 8) & 0x03; 1103 buf[3] = val; 1104 break; 1105 1106 case RELOC_BASE13: 1107 buf[2] |= (val >> 8) & 0x1f; 1108 buf[3] = val; 1109 break; 1110 1111 case RELOC_WDISP22: 1112 val = (val >> 2) + 1; 1113 /* FALLTHROUGH */ 1114 case RELOC_BASE22: 1115 buf[1] |= (val >> 16) & 0x3f; 1116 buf[2] = val >> 8; 1117 buf[3] = val; 1118 break; 1119 1120 case RELOC_JUMPTARG: /* 0000XXXX pattern in a word. */ 1121 if (!fixP->fx_done) 1122 { 1123 /* The linker tries to support both AMD and old GNU style 1124 R_IREL relocs. That means that if the addend is exactly 1125 the negative of the address within the section, the 1126 linker will not handle it correctly. */ 1127 #if 0 1128 if (fixP->fx_pcrel 1129 && val != 0 1130 && val == - (fixP->fx_frag->fr_address + fixP->fx_where)) 1131 as_bad_where 1132 (fixP->fx_file, fixP->fx_line, 1133 _("the linker will not handle this relocation correctly (1)")); 1134 #endif 1135 } 1136 else if (fixP->fx_pcrel) 1137 { 1138 long v = val >> 28; 1139 #if 1 1140 if (v != 0 && v != -1) 1141 as_bad_where (fixP->fx_file, fixP->fx_line, 1142 _("call/jmp target out of range (2)")); 1143 #endif 1144 } 1145 else 1146 /* This case was supposed to be handled in machine_ip. */ 1147 abort (); 1148 1149 buf[0] |= (val >> 26) & 0x03; /* Holds bits 0FFFFFFC of address. */ 1150 buf[1] = val >> 18; 1151 buf[2] = val >> 10; 1152 buf[3] = val >> 2; 1153 break; 1154 1155 case RELOC_CONST: /* 0000XXXX pattern in a word. */ 1156 #if DEBUG 1157 printf ("reloc_const: val=%x\n", val); 1158 #endif 1159 buf[2] = val >> 8; /* Holds bits 0000XXXX. */ 1160 buf[3] = val; 1161 break; 1162 1163 case RELOC_CONSTH: /* 0000XXXX pattern in a word. */ 1164 #if DEBUG 1165 printf ("reloc_consth: val=%x\n", val); 1166 #endif 1167 buf[2] = val >> 24; /* Holds bits XXXX0000. */ 1168 buf[3] = val >> 16; 1169 break; 1170 1171 case BFD_RELOC_VTABLE_INHERIT: 1172 case BFD_RELOC_VTABLE_ENTRY: 1173 fixP->fx_done = 0; 1174 break; 1175 1176 case NO_RELOC: 1177 default: 1178 as_bad (_("bad relocation type: 0x%02x"), fixP->fx_r_type); 1179 break; 1180 } 1181 1182 if (fixP->fx_addsy == (symbolS *) NULL) 1183 fixP->fx_done = 1; 1184 } 1185 #endif 1186 1187 #ifdef OBJ_COFF 1188 short 1189 tc_coff_fix2rtype (fixP) 1190 fixS *fixP; 1191 { 1192 #if DEBUG 1193 printf ("tc_coff_fix2rtype\n"); 1194 #endif 1195 1196 switch (fixP->fx_r_type) 1197 { 1198 case RELOC_32: 1199 return (R_WORD); 1200 case RELOC_8: 1201 return (R_BYTE); 1202 case RELOC_CONST: 1203 return (R_ILOHALF); 1204 case RELOC_CONSTH: 1205 return (R_IHIHALF); 1206 case RELOC_JUMPTARG: 1207 return (R_IREL); 1208 default: 1209 printf ("need %d\n", fixP->fx_r_type); 1210 abort (); 1211 } 1212 1213 return 0; 1214 } 1215 1216 #endif /* OBJ_COFF */ 1217 1218 /* Should never be called for or32. */ 1219 1220 void 1221 md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) 1222 char * ptr ATTRIBUTE_UNUSED; 1223 addressT from_addr ATTRIBUTE_UNUSED; 1224 addressT to_addr ATTRIBUTE_UNUSED; 1225 fragS * frag ATTRIBUTE_UNUSED; 1226 symbolS * to_symbol ATTRIBUTE_UNUSED; 1227 { 1228 as_fatal ("or32_create_short_jmp\n"); 1229 } 1230 1231 /* Should never be called for or32. */ 1232 1233 #ifndef BFD_ASSEMBLER 1234 void 1235 md_convert_frag (headers, seg, fragP) 1236 object_headers * headers ATTRIBUTE_UNUSED; 1237 segT seg ATTRIBUTE_UNUSED; 1238 register fragS * fragP ATTRIBUTE_UNUSED; 1239 { 1240 as_fatal ("or32_convert_frag\n"); 1241 } 1242 1243 #else 1244 void 1245 md_convert_frag (headers, seg, fragP) 1246 bfd * headers ATTRIBUTE_UNUSED; 1247 segT seg ATTRIBUTE_UNUSED; 1248 fragS * fragP ATTRIBUTE_UNUSED; 1249 { 1250 as_fatal ("or32_convert_frag\n"); 1251 } 1252 #endif 1253 1254 /* Should never be called for or32. */ 1255 1256 void 1257 md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) 1258 char * ptr ATTRIBUTE_UNUSED; 1259 addressT from_addr ATTRIBUTE_UNUSED; 1260 addressT to_addr ATTRIBUTE_UNUSED; 1261 fragS * frag ATTRIBUTE_UNUSED; 1262 symbolS * to_symbol ATTRIBUTE_UNUSED; 1263 { 1264 as_fatal ("or32_create_long_jump\n"); 1265 } 1266 1267 /* Should never be called for or32. */ 1268 1269 int 1270 md_estimate_size_before_relax (fragP, segtype) 1271 fragS * fragP ATTRIBUTE_UNUSED; 1272 segT segtype ATTRIBUTE_UNUSED; 1273 { 1274 as_fatal ("or32_estimate_size_before_relax\n"); 1275 return 0; 1276 } 1277 1278 /* Translate internal representation of relocation info to target format. 1279 1280 On sparc/29k: first 4 bytes are normal unsigned long address, next three 1281 bytes are index, most sig. byte first. Byte 7 is broken up with 1282 bit 7 as external, bits 6 & 5 unused, and the lower 1283 five bits as relocation type. Next 4 bytes are long addend. */ 1284 /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com. */ 1285 1286 #ifdef OBJ_AOUT 1287 void 1288 tc_aout_fix_to_chars (where, fixP, segment_address_in_file) 1289 char *where; 1290 fixS *fixP; 1291 relax_addressT segment_address_in_file; 1292 { 1293 long r_symbolnum; 1294 1295 #if DEBUG 1296 printf ("tc_aout_fix_to_chars\n"); 1297 #endif 1298 1299 know (fixP->fx_r_type < BFD_RELOC_NONE); 1300 know (fixP->fx_addsy != NULL); 1301 1302 md_number_to_chars 1303 (where, 1304 fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file, 1305 4); 1306 1307 r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy) 1308 ? S_GET_TYPE (fixP->fx_addsy) 1309 : fixP->fx_addsy->sy_number); 1310 1311 where[4] = (r_symbolnum >> 16) & 0x0ff; 1312 where[5] = (r_symbolnum >> 8) & 0x0ff; 1313 where[6] = r_symbolnum & 0x0ff; 1314 where[7] = (((!S_IS_DEFINED (fixP->fx_addsy)) << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F); 1315 1316 /* Also easy. */ 1317 md_number_to_chars (&where[8], fixP->fx_addnumber, 4); 1318 } 1319 1320 #endif /* OBJ_AOUT */ 1321 1322 const char *md_shortopts = ""; 1323 1324 struct option md_longopts[] = 1325 { 1326 { NULL, no_argument, NULL, 0 } 1327 }; 1328 size_t md_longopts_size = sizeof (md_longopts); 1329 1330 int 1331 md_parse_option (c, arg) 1332 int c ATTRIBUTE_UNUSED; 1333 char * arg ATTRIBUTE_UNUSED; 1334 { 1335 return 0; 1336 } 1337 1338 void 1339 md_show_usage (stream) 1340 FILE * stream ATTRIBUTE_UNUSED; 1341 { 1342 } 1343 1344 /* This is called when a line is unrecognized. This is used to handle 1345 definitions of or32 style local labels. */ 1346 1347 int 1348 or32_unrecognized_line (c) 1349 int c; 1350 { 1351 int lab; 1352 char *s; 1353 1354 if (c != '$' 1355 || ! ISDIGIT ((unsigned char) input_line_pointer[0])) 1356 return 0; 1357 1358 s = input_line_pointer; 1359 1360 lab = 0; 1361 while (ISDIGIT ((unsigned char) *s)) 1362 { 1363 lab = lab * 10 + *s - '0'; 1364 ++s; 1365 } 1366 1367 if (*s != ':') 1368 /* Not a label definition. */ 1369 return 0; 1370 1371 if (dollar_label_defined (lab)) 1372 { 1373 as_bad (_("label \"$%d\" redefined"), lab); 1374 return 0; 1375 } 1376 1377 define_dollar_label (lab); 1378 colon (dollar_label_name (lab, 0)); 1379 input_line_pointer = s + 1; 1380 1381 return 1; 1382 } 1383 1384 #ifndef BFD_ASSEMBLER 1385 /* Record a fixup for a cons expression. */ 1386 /* 1387 void 1388 or32_cons_fix_new (frag, where, nbytes, exp) 1389 fragS *frag; 1390 int where; 1391 int nbytes; 1392 expressionS *exp; 1393 { 1394 fix_new_exp (frag, where, nbytes, exp, 0, 1395 nbytes == 5 ? RELOC_32 1396 : nbytes == 2 ? RELOC_16 1397 : RELOC_8); 1398 } 1399 void 1400 tc_aout_pre_write_hook () 1401 { 1402 #if DEBUG 1403 printf ("In tc_aout_pre_write_hook()\n"); 1404 #endif 1405 } 1406 */ 1407 #endif 1408 1409 /* Default the values of symbols known that should be "predefined". We 1410 don't bother to predefine them unless you actually use one, since there 1411 are a lot of them. */ 1412 1413 symbolS * 1414 md_undefined_symbol (name) 1415 char *name ATTRIBUTE_UNUSED; 1416 { 1417 #ifndef BFD_ASSEMBLER 1418 long regnum; 1419 char testbuf[5 + /*SLOP*/ 5]; 1420 1421 #if DEBUG 1422 printf ("md_undefined_symbol(%s)\n", name); 1423 #endif 1424 1425 /* Register name. */ 1426 if (name[0] == 'r' || name[0] == 'R' || name[0] == 'a' || name[0] == 'b') 1427 { 1428 /* Parse the number, make sure it has no extra zeroes or 1429 trailing chars. */ 1430 regnum = atol (& name[1]); 1431 1432 if (regnum > 31) 1433 as_fatal (_("register out of range")); 1434 1435 sprintf (testbuf, "%ld", regnum); 1436 1437 if (strcmp (testbuf, &name[1]) != 0) 1438 return NULL; /* gr007 or lr7foo or whatever. */ 1439 1440 /* We have a wiener! Define and return a new symbol for it. */ 1441 return (symbol_new (name, SEG_REGISTER, (valueT) regnum, 1442 &zero_address_frag)); 1443 } 1444 #endif 1445 return NULL; 1446 } 1447 1448 /* Parse an operand that is machine-specific. */ 1449 1450 void 1451 md_operand (expressionP) 1452 expressionS *expressionP; 1453 { 1454 #if DEBUG 1455 printf (" md_operand(input_line_pointer = %s)\n", input_line_pointer); 1456 #endif 1457 1458 if (input_line_pointer[0] == REGISTER_PREFIX && input_line_pointer[1] == 'r') 1459 { 1460 /* We have a numeric register expression. No biggy. */ 1461 input_line_pointer += 2; /* Skip %r */ 1462 (void) expression (expressionP); 1463 1464 if (expressionP->X_op != O_constant 1465 || expressionP->X_add_number > 255) 1466 as_bad (_("Invalid expression after %%%%\n")); 1467 expressionP->X_op = O_register; 1468 } 1469 else if (input_line_pointer[0] == '&') 1470 { 1471 /* We are taking the 'address' of a register...this one is not 1472 in the manual, but it *is* in traps/fpsymbol.h! What they 1473 seem to want is the register number, as an absolute number. */ 1474 input_line_pointer++; /* Skip & */ 1475 (void) expression (expressionP); 1476 1477 if (expressionP->X_op != O_register) 1478 as_bad (_("invalid register in & expression")); 1479 else 1480 expressionP->X_op = O_constant; 1481 } 1482 else if (input_line_pointer[0] == '$' 1483 && ISDIGIT ((unsigned char) input_line_pointer[1])) 1484 { 1485 long lab; 1486 char *name; 1487 symbolS *sym; 1488 1489 /* This is a local label. */ 1490 ++input_line_pointer; 1491 lab = (long) get_absolute_expression (); 1492 1493 if (dollar_label_defined (lab)) 1494 { 1495 name = dollar_label_name (lab, 0); 1496 sym = symbol_find (name); 1497 } 1498 else 1499 { 1500 name = dollar_label_name (lab, 1); 1501 sym = symbol_find_or_make (name); 1502 } 1503 1504 expressionP->X_op = O_symbol; 1505 expressionP->X_add_symbol = sym; 1506 expressionP->X_add_number = 0; 1507 } 1508 else if (input_line_pointer[0] == '$') 1509 { 1510 char *s; 1511 char type; 1512 int fieldnum, fieldlimit; 1513 LITTLENUM_TYPE floatbuf[8]; 1514 1515 /* $float(), $doubleN(), or $extendN() convert floating values 1516 to integers. */ 1517 s = input_line_pointer; 1518 1519 ++s; 1520 1521 fieldnum = 0; 1522 if (strncmp (s, "double", sizeof "double" - 1) == 0) 1523 { 1524 s += sizeof "double" - 1; 1525 type = 'd'; 1526 fieldlimit = 2; 1527 } 1528 else if (strncmp (s, "float", sizeof "float" - 1) == 0) 1529 { 1530 s += sizeof "float" - 1; 1531 type = 'f'; 1532 fieldlimit = 1; 1533 } 1534 else if (strncmp (s, "extend", sizeof "extend" - 1) == 0) 1535 { 1536 s += sizeof "extend" - 1; 1537 type = 'x'; 1538 fieldlimit = 4; 1539 } 1540 else 1541 return; 1542 1543 if (ISDIGIT (*s)) 1544 { 1545 fieldnum = *s - '0'; 1546 ++s; 1547 } 1548 if (fieldnum >= fieldlimit) 1549 return; 1550 1551 SKIP_WHITESPACE (); 1552 if (*s != '(') 1553 return; 1554 ++s; 1555 SKIP_WHITESPACE (); 1556 1557 s = atof_ieee (s, type, floatbuf); 1558 if (s == NULL) 1559 return; 1560 s = s; 1561 1562 SKIP_WHITESPACE (); 1563 if (*s != ')') 1564 return; 1565 ++s; 1566 SKIP_WHITESPACE (); 1567 1568 input_line_pointer = s; 1569 expressionP->X_op = O_constant; 1570 expressionP->X_unsigned = 1; 1571 expressionP->X_add_number = ((floatbuf[fieldnum * 2] 1572 << LITTLENUM_NUMBER_OF_BITS) 1573 + floatbuf[fieldnum * 2 + 1]); 1574 } 1575 } 1576 1577 /* Round up a section size to the appropriate boundary. */ 1578 1579 valueT 1580 md_section_align (segment, size) 1581 segT segment ATTRIBUTE_UNUSED; 1582 valueT size ATTRIBUTE_UNUSED; 1583 { 1584 return size; /* Byte alignment is fine. */ 1585 } 1586 1587 /* Exactly what point is a PC-relative offset relative TO? 1588 On the 29000, they're relative to the address of the instruction, 1589 which we have set up as the address of the fixup too. */ 1590 1591 long 1592 md_pcrel_from (fixP) 1593 fixS *fixP; 1594 { 1595 return fixP->fx_where + fixP->fx_frag->fr_address; 1596 } 1597 1598 /* Generate a reloc for a fixup. */ 1599 1600 #ifdef BFD_ASSEMBLER 1601 arelent * 1602 tc_gen_reloc (seg, fixp) 1603 asection *seg ATTRIBUTE_UNUSED; 1604 fixS *fixp; 1605 { 1606 arelent *reloc; 1607 1608 reloc = (arelent *) xmalloc (sizeof (arelent)); 1609 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); 1610 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 1611 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; 1612 /* reloc->address = fixp->fx_frag->fr_address + fixp->fx_where + fixp->fx_addnumber;*/ 1613 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); 1614 1615 if (reloc->howto == (reloc_howto_type *) NULL) 1616 { 1617 as_bad_where (fixp->fx_file, fixp->fx_line, 1618 _("reloc %d not supported by object file format"), 1619 (int) fixp->fx_r_type); 1620 return NULL; 1621 } 1622 1623 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) 1624 reloc->address = fixp->fx_offset; 1625 1626 reloc->addend = fixp->fx_addnumber; 1627 return reloc; 1628 } 1629 #endif 1630 1631