1 /* Assembly backend for the OpenRISC 1000. 2 Copyright (C) 2002, 2003, 2005 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, 51 Franklin Street - Fifth Floor, 22 Boston, MA 02110-1301, 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 #include "elf/or32.h" 30 31 #define DEBUG 0 32 33 #ifndef REGISTER_PREFIX 34 #define REGISTER_PREFIX '%' 35 #endif 36 37 /* Make it easier to clone this machine desc into another one. */ 38 #define machine_opcode or32_opcode 39 #define machine_opcodes or32_opcodes 40 #define machine_ip or32_ip 41 #define machine_it or32_it 42 43 /* Handle of the OPCODE hash table. */ 44 static struct hash_control *op_hash = NULL; 45 46 struct machine_it 47 { 48 char * error; 49 unsigned long opcode; 50 struct nlist * nlistp; 51 expressionS exp; 52 int pcrel; 53 int reloc_offset; /* Offset of reloc within insn. */ 54 int reloc; 55 } 56 the_insn; 57 58 const pseudo_typeS md_pseudo_table[] = 59 { 60 {"align", s_align_bytes, 4 }, 61 {"space", s_space, 0 }, 62 {"cputype", s_ignore, 0 }, 63 {"reg", s_lsym, 0 }, /* Register equate, same as equ. */ 64 {"sect", s_ignore, 0 }, /* Creation of coff sections. */ 65 {"proc", s_ignore, 0 }, /* Start of a function. */ 66 {"endproc", s_ignore, 0 }, /* Function end. */ 67 {"word", cons, 4 }, 68 {NULL, 0, 0 }, 69 }; 70 71 int md_short_jump_size = 4; 72 int md_long_jump_size = 4; 73 74 /* This array holds the chars that always start a comment. 75 If the pre-processor is disabled, these aren't very useful. */ 76 const char comment_chars[] = "#"; 77 78 /* This array holds the chars that only start a comment at the beginning of 79 a line. If the line seems to have the form '# 123 filename' 80 .line and .file directives will appear in the pre-processed output. */ 81 /* Note that input_file.c hand checks for '#' at the beginning of the 82 first line of the input file. This is because the compiler outputs 83 #NO_APP at the beginning of its output. */ 84 /* Also note that comments like this one will always work. */ 85 const char line_comment_chars[] = "#"; 86 87 /* We needed an unused char for line separation to work around the 88 lack of macros, using sed and such. */ 89 const char line_separator_chars[] = ";"; 90 91 /* Chars that can be used to separate mant from exp in floating point nums. */ 92 const char EXP_CHARS[] = "eE"; 93 94 /* Chars that mean this number is a floating point constant. 95 As in 0f12.456 96 or 0d1.2345e12. */ 97 const char FLT_CHARS[] = "rRsSfFdDxXpP"; 98 99 /* "l.jalr r9" precalculated opcode. */ 100 static unsigned long jalr_r9_opcode; 101 102 static void machine_ip (char *); 103 104 105 /* Set bits in machine opcode according to insn->encoding 106 description and passed operand. */ 107 108 static void 109 encode (const struct machine_opcode *insn, 110 unsigned long *opcode, 111 signed long param_val, 112 char param_ch) 113 { 114 int opc_pos = 0; 115 int param_pos = 0; 116 char *enc; 117 118 #if DEBUG 119 printf (" encode: opcode=%.8lx param_val=%.8lx abs=%.8lx param_ch=%c\n", 120 *opcode, param_val, abs (param_val), param_ch); 121 #endif 122 for (enc = insn->encoding; *enc != '\0'; enc++) 123 if (*enc == param_ch) 124 { 125 if (enc - 2 >= insn->encoding && (*(enc - 2) == '0') && (*(enc - 1) == 'x')) 126 continue; 127 else 128 param_pos ++; 129 } 130 131 opc_pos = 32; 132 133 for (enc = insn->encoding; *enc != '\0';) 134 { 135 if ((*enc == '0') && (*(enc + 1) == 'x')) 136 { 137 int tmp = strtol (enc, NULL, 16); 138 139 opc_pos -= 4; 140 *opcode |= tmp << opc_pos; 141 enc += 3; 142 } 143 else if ((*enc == '0') || (*enc == '-')) 144 { 145 opc_pos--; 146 enc++; 147 } 148 else if (*enc == '1') 149 { 150 opc_pos--; 151 *opcode |= 1 << opc_pos; 152 enc++; 153 } 154 else if (*enc == param_ch) 155 { 156 opc_pos--; 157 param_pos--; 158 *opcode |= ((param_val >> param_pos) & 0x1) << opc_pos; 159 enc++; 160 } 161 else if (ISALPHA (*enc)) 162 { 163 opc_pos--; 164 enc++; 165 } 166 else 167 enc++; 168 } 169 170 #if DEBUG 171 printf (" opcode=%.8lx\n", *opcode); 172 #endif 173 } 174 175 /* This function is called once, at assembler startup time. It should 176 set up all the tables, etc., that the MD part of the assembler will 177 need. */ 178 179 void 180 md_begin (void) 181 { 182 const char *retval = NULL; 183 int lose = 0; 184 int skipnext = 0; 185 unsigned int i; 186 187 /* Hash up all the opcodes for fast use later. */ 188 op_hash = hash_new (); 189 190 for (i = 0; i < or32_num_opcodes; i++) 191 { 192 const char *name = machine_opcodes[i].name; 193 194 if (skipnext) 195 { 196 skipnext = 0; 197 continue; 198 } 199 200 retval = hash_insert (op_hash, name, (void *) &machine_opcodes[i]); 201 if (retval != NULL) 202 { 203 fprintf (stderr, "internal error: can't hash `%s': %s\n", 204 machine_opcodes[i].name, retval); 205 lose = 1; 206 } 207 } 208 209 if (lose) 210 as_fatal (_("Broken assembler. No assembly attempted.")); 211 212 encode (&machine_opcodes[insn_index ("l.jalr")], &jalr_r9_opcode, 9, 'B'); 213 } 214 215 /* Returns non zero if instruction is to be used. */ 216 217 static int 218 check_invalid_opcode (unsigned long opcode) 219 { 220 return opcode == jalr_r9_opcode; 221 } 222 223 /* Assemble a single instruction. Its label has already been handled 224 by the generic front end. We just parse opcode and operands, and 225 produce the bytes of data and relocation. */ 226 227 void 228 md_assemble (char *str) 229 { 230 char *toP; 231 232 #if DEBUG 233 printf ("NEW INSTRUCTION\n"); 234 #endif 235 236 know (str); 237 machine_ip (str); 238 toP = frag_more (4); 239 240 /* Put out the opcode. */ 241 md_number_to_chars (toP, the_insn.opcode, 4); 242 243 /* Put out the symbol-dependent stuff. */ 244 if (the_insn.reloc != BFD_RELOC_NONE) 245 { 246 fix_new_exp (frag_now, 247 (toP - frag_now->fr_literal + the_insn.reloc_offset), 248 4, /* size */ 249 &the_insn.exp, 250 the_insn.pcrel, 251 the_insn.reloc); 252 } 253 } 254 255 /* This is true of the we have issued a "lo(" or "hi"(. */ 256 static int waiting_for_shift = 0; 257 258 static int mask_or_shift = 0; 259 260 static char * 261 parse_operand (char *s, expressionS *operandp, int opt) 262 { 263 char *save = input_line_pointer; 264 char *new; 265 266 #if DEBUG 267 printf (" PROCESS NEW OPERAND(%s) == %c (%d)\n", s, opt ? opt : '!', opt); 268 #endif 269 270 input_line_pointer = s; 271 272 if (strncasecmp (s, "HI(", 3) == 0) 273 { 274 waiting_for_shift = 1; 275 mask_or_shift = BFD_RELOC_HI16; 276 277 input_line_pointer += 3; 278 } 279 else if (strncasecmp (s, "LO(", 3) == 0) 280 { 281 mask_or_shift = BFD_RELOC_LO16; 282 283 input_line_pointer += 3; 284 } 285 else 286 mask_or_shift = 0; 287 288 if ((*s == '(') && (*(s+1) == 'r')) 289 s++; 290 291 if ((*s == 'r') && ISDIGIT (*(s + 1))) 292 { 293 operandp->X_add_number = strtol (s + 1, NULL, 10); 294 operandp->X_op = O_register; 295 for (; (*s != ',') && (*s != '\0');) 296 s++; 297 input_line_pointer = save; 298 return s; 299 } 300 301 expression (operandp); 302 303 if (operandp->X_op == O_absent) 304 { 305 if (! opt) 306 as_bad (_("missing operand")); 307 else 308 { 309 operandp->X_add_number = 0; 310 operandp->X_op = O_constant; 311 } 312 } 313 314 new = input_line_pointer; 315 input_line_pointer = save; 316 317 #if DEBUG 318 printf (" %s=parse_operand(%s): operandp->X_op = %u\n", new, s, operandp->X_op); 319 #endif 320 321 return new; 322 } 323 324 /* Instruction parsing. Takes a string containing the opcode. 325 Operands are at input_line_pointer. Output is in the_insn. 326 Warnings or errors are generated. */ 327 328 static void 329 machine_ip (char *str) 330 { 331 char *s; 332 const char *args; 333 const struct machine_opcode *insn; 334 char *argsStart; 335 unsigned long opcode; 336 expressionS the_operand; 337 expressionS *operand = &the_operand; 338 unsigned int regno; 339 int reloc = BFD_RELOC_NONE; 340 341 #if DEBUG 342 printf ("machine_ip(%s)\n", str); 343 #endif 344 345 s = str; 346 for (; ISALNUM (*s) || *s == '.'; ++s) 347 if (ISUPPER (*s)) 348 *s = TOLOWER (*s); 349 350 switch (*s) 351 { 352 case '\0': 353 break; 354 355 case ' ': /* FIXME-SOMEDAY more whitespace. */ 356 *s++ = '\0'; 357 break; 358 359 default: 360 as_bad (_("unknown opcode1: `%s'"), str); 361 return; 362 } 363 364 if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL) 365 { 366 as_bad (_("unknown opcode2 `%s'."), str); 367 return; 368 } 369 370 argsStart = s; 371 opcode = 0; 372 memset (&the_insn, '\0', sizeof (the_insn)); 373 the_insn.reloc = BFD_RELOC_NONE; 374 375 reloc = BFD_RELOC_NONE; 376 377 /* Build the opcode, checking as we go to make sure that the 378 operands match. 379 380 If an operand matches, we modify the_insn or opcode appropriately, 381 and do a "continue". If an operand fails to match, we "break". */ 382 if (insn->args[0] != '\0') 383 /* Prime the pump. */ 384 s = parse_operand (s, operand, insn->args[0] == 'I'); 385 386 for (args = insn->args;; ++args) 387 { 388 #if DEBUG 389 printf (" args = %s\n", args); 390 #endif 391 switch (*args) 392 { 393 case '\0': /* End of args. */ 394 /* We have have 0 args, do the bazoooka! */ 395 if (args == insn->args) 396 encode (insn, &opcode, 0, 0); 397 398 if (*s == '\0') 399 { 400 /* We are truly done. */ 401 the_insn.opcode = opcode; 402 if (check_invalid_opcode (opcode)) 403 as_bad (_("instruction not allowed: %s"), str); 404 return; 405 } 406 as_bad (_("too many operands: %s"), s); 407 break; 408 409 case ',': /* Must match a comma. */ 410 if (*s++ == ',') 411 { 412 reloc = BFD_RELOC_NONE; 413 414 /* Parse next operand. */ 415 s = parse_operand (s, operand, args[1] == 'I'); 416 #if DEBUG 417 printf (" ',' case: operand->X_add_number = %d, *args = %s, *s = %s\n", 418 operand->X_add_number, args, s); 419 #endif 420 continue; 421 } 422 break; 423 424 case '(': /* Must match a (. */ 425 s = parse_operand (s, operand, args[1] == 'I'); 426 continue; 427 428 case ')': /* Must match a ). */ 429 continue; 430 431 case 'r': /* A general register. */ 432 args++; 433 434 if (operand->X_op != O_register) 435 break; /* Only registers. */ 436 437 know (operand->X_add_symbol == 0); 438 know (operand->X_op_symbol == 0); 439 regno = operand->X_add_number; 440 encode (insn, &opcode, regno, *args); 441 #if DEBUG 442 printf (" r: operand->X_op = %d\n", operand->X_op); 443 #endif 444 continue; 445 446 default: 447 /* if (! ISALPHA (*args)) 448 break; */ /* Only immediate values. */ 449 450 if (mask_or_shift) 451 { 452 #if DEBUG 453 printf ("mask_or_shift = %d\n", mask_or_shift); 454 #endif 455 reloc = mask_or_shift; 456 } 457 mask_or_shift = 0; 458 459 if (strncasecmp (args, "LO(", 3) == 0) 460 { 461 #if DEBUG 462 printf ("reloc_const\n"); 463 #endif 464 reloc = BFD_RELOC_LO16; 465 } 466 else if (strncasecmp (args, "HI(", 3) == 0) 467 { 468 #if DEBUG 469 printf ("reloc_consth\n"); 470 #endif 471 reloc = BFD_RELOC_HI16; 472 } 473 474 if (*s == '(') 475 operand->X_op = O_constant; 476 else if (*s == ')') 477 s += 1; 478 #if DEBUG 479 printf (" default case: operand->X_add_number = %d, *args = %s, *s = %s\n", operand->X_add_number, args, s); 480 #endif 481 if (operand->X_op == O_constant) 482 { 483 if (reloc == BFD_RELOC_NONE) 484 { 485 bfd_vma v, mask; 486 487 mask = 0x3ffffff; 488 v = abs (operand->X_add_number) & ~ mask; 489 if (v) 490 as_bad (_("call/jmp target out of range (1)")); 491 } 492 493 if (reloc == BFD_RELOC_HI16) 494 operand->X_add_number = ((operand->X_add_number >> 16) & 0xffff); 495 496 the_insn.pcrel = 0; 497 encode (insn, &opcode, operand->X_add_number, *args); 498 /* the_insn.reloc = BFD_RELOC_NONE; */ 499 continue; 500 } 501 502 if (reloc == BFD_RELOC_NONE) 503 the_insn.reloc = BFD_RELOC_32_GOT_PCREL; 504 else 505 the_insn.reloc = reloc; 506 507 /* the_insn.reloc = insn->reloc; */ 508 #if DEBUG 509 printf (" reloc sym=%d\n", the_insn.reloc); 510 printf (" BFD_RELOC_NONE=%d\n", BFD_RELOC_NONE); 511 #endif 512 the_insn.exp = *operand; 513 514 /* the_insn.reloc_offset = 1; */ 515 the_insn.pcrel = 1; /* Assume PC-relative jump. */ 516 517 /* FIXME-SOON, Do we figure out whether abs later, after 518 know sym val? */ 519 if (reloc == BFD_RELOC_LO16 || reloc == BFD_RELOC_HI16) 520 the_insn.pcrel = 0; 521 522 encode (insn, &opcode, operand->X_add_number, *args); 523 continue; 524 } 525 526 /* Types or values of args don't match. */ 527 as_bad (_("invalid operands")); 528 return; 529 } 530 } 531 532 /* This is identical to the md_atof in m68k.c. I think this is right, 533 but I'm not sure. 534 535 Turn a string in input_line_pointer into a floating point constant 536 of type type, and store the appropriate bytes in *litP. The number 537 of LITTLENUMS emitted is stored in *sizeP . An error message is 538 returned, or NULL on OK. */ 539 540 /* Equal to MAX_PRECISION in atof-ieee.c. */ 541 #define MAX_LITTLENUMS 6 542 543 char * 544 md_atof (int type, char * litP, int * sizeP) 545 { 546 int prec; 547 LITTLENUM_TYPE words[MAX_LITTLENUMS]; 548 LITTLENUM_TYPE *wordP; 549 char *t; 550 551 switch (type) 552 { 553 case 'f': 554 case 'F': 555 case 's': 556 case 'S': 557 prec = 2; 558 break; 559 560 case 'd': 561 case 'D': 562 case 'r': 563 case 'R': 564 prec = 4; 565 break; 566 567 case 'x': 568 case 'X': 569 prec = 6; 570 break; 571 572 case 'p': 573 case 'P': 574 prec = 6; 575 break; 576 577 default: 578 *sizeP = 0; 579 return _("Bad call to MD_ATOF()"); 580 } 581 582 t = atof_ieee (input_line_pointer, type, words); 583 if (t) 584 input_line_pointer = t; 585 586 *sizeP = prec * sizeof (LITTLENUM_TYPE); 587 588 for (wordP = words; prec--;) 589 { 590 md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE)); 591 litP += sizeof (LITTLENUM_TYPE); 592 } 593 594 return NULL; 595 } 596 597 /* Write out big-endian. */ 598 599 void 600 md_number_to_chars (char *buf, valueT val, int n) 601 { 602 number_to_chars_bigendian (buf, val, n); 603 } 604 605 void 606 md_apply_fix (fixS * fixP, valueT * val, segT seg ATTRIBUTE_UNUSED) 607 { 608 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; 609 long t_val; 610 611 t_val = (long) *val; 612 613 #if DEBUG 614 printf ("md_apply_fix val:%x\n", t_val); 615 #endif 616 617 fixP->fx_addnumber = t_val; /* Remember value for emit_reloc. */ 618 619 know (fixP->fx_size == 4); 620 know (fixP->fx_r_type < BFD_RELOC_NONE); 621 622 switch (fixP->fx_r_type) 623 { 624 case BFD_RELOC_32: /* XXXXXXXX pattern in a word. */ 625 #if DEBUG 626 printf ("reloc_const: val=%x\n", t_val); 627 #endif 628 buf[0] = t_val >> 24; 629 buf[1] = t_val >> 16; 630 buf[2] = t_val >> 8; 631 buf[3] = t_val; 632 break; 633 634 case BFD_RELOC_16: /* XXXX0000 pattern in a word. */ 635 #if DEBUG 636 printf ("reloc_const: val=%x\n", t_val); 637 #endif 638 buf[0] = t_val >> 8; 639 buf[1] = t_val; 640 break; 641 642 case BFD_RELOC_8: /* XX000000 pattern in a word. */ 643 #if DEBUG 644 printf ("reloc_const: val=%x\n", t_val); 645 #endif 646 buf[0] = t_val; 647 break; 648 649 case BFD_RELOC_LO16: /* 0000XXXX pattern in a word. */ 650 #if DEBUG 651 printf ("reloc_const: val=%x\n", t_val); 652 #endif 653 buf[2] = t_val >> 8; /* Holds bits 0000XXXX. */ 654 buf[3] = t_val; 655 break; 656 657 case BFD_RELOC_HI16: /* 0000XXXX pattern in a word. */ 658 #if DEBUG 659 printf ("reloc_consth: val=%x\n", t_val); 660 #endif 661 buf[2] = t_val >> 24; /* Holds bits XXXX0000. */ 662 buf[3] = t_val >> 16; 663 break; 664 665 case BFD_RELOC_32_GOT_PCREL: /* 0000XXXX pattern in a word. */ 666 if (!fixP->fx_done) 667 ; 668 else if (fixP->fx_pcrel) 669 { 670 long v = t_val >> 28; 671 672 if (v != 0 && v != -1) 673 as_bad_where (fixP->fx_file, fixP->fx_line, 674 _("call/jmp target out of range (2)")); 675 } 676 else 677 /* This case was supposed to be handled in machine_ip. */ 678 abort (); 679 680 buf[0] |= (t_val >> 26) & 0x03; /* Holds bits 0FFFFFFC of address. */ 681 buf[1] = t_val >> 18; 682 buf[2] = t_val >> 10; 683 buf[3] = t_val >> 2; 684 break; 685 686 case BFD_RELOC_VTABLE_INHERIT: 687 case BFD_RELOC_VTABLE_ENTRY: 688 fixP->fx_done = 0; 689 break; 690 691 case BFD_RELOC_NONE: 692 default: 693 as_bad (_("bad relocation type: 0x%02x"), fixP->fx_r_type); 694 break; 695 } 696 697 if (fixP->fx_addsy == (symbolS *) NULL) 698 fixP->fx_done = 1; 699 } 700 701 /* Should never be called for or32. */ 702 703 void 704 md_create_short_jump (char * ptr ATTRIBUTE_UNUSED, 705 addressT from_addr ATTRIBUTE_UNUSED, 706 addressT to_addr ATTRIBUTE_UNUSED, 707 fragS * frag ATTRIBUTE_UNUSED, 708 symbolS * to_symbol ATTRIBUTE_UNUSED) 709 { 710 as_fatal ("or32_create_short_jmp\n"); 711 } 712 713 /* Should never be called for or32. */ 714 715 void 716 md_convert_frag (bfd * headers ATTRIBUTE_UNUSED, 717 segT seg ATTRIBUTE_UNUSED, 718 fragS * fragP ATTRIBUTE_UNUSED) 719 { 720 as_fatal ("or32_convert_frag\n"); 721 } 722 723 /* Should never be called for or32. */ 724 725 void 726 md_create_long_jump (char * ptr ATTRIBUTE_UNUSED, 727 addressT from_addr ATTRIBUTE_UNUSED, 728 addressT to_addr ATTRIBUTE_UNUSED, 729 fragS * frag ATTRIBUTE_UNUSED, 730 symbolS * to_symbol ATTRIBUTE_UNUSED) 731 { 732 as_fatal ("or32_create_long_jump\n"); 733 } 734 735 /* Should never be called for or32. */ 736 737 int 738 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, 739 segT segtype ATTRIBUTE_UNUSED) 740 { 741 as_fatal ("or32_estimate_size_before_relax\n"); 742 return 0; 743 } 744 745 /* Translate internal representation of relocation info to target format. 746 747 On sparc/29k: first 4 bytes are normal unsigned long address, next three 748 bytes are index, most sig. byte first. Byte 7 is broken up with 749 bit 7 as external, bits 6 & 5 unused, and the lower 750 five bits as relocation type. Next 4 bytes are long addend. */ 751 /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com. */ 752 753 #ifdef OBJ_AOUT 754 void 755 tc_aout_fix_to_chars (char *where, 756 fixS *fixP, 757 relax_addressT segment_address_in_file) 758 { 759 long r_symbolnum; 760 761 #if DEBUG 762 printf ("tc_aout_fix_to_chars\n"); 763 #endif 764 765 know (fixP->fx_r_type < BFD_RELOC_NONE); 766 know (fixP->fx_addsy != NULL); 767 768 md_number_to_chars 769 (where, 770 fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file, 771 4); 772 773 r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy) 774 ? S_GET_TYPE (fixP->fx_addsy) 775 : fixP->fx_addsy->sy_number); 776 777 where[4] = (r_symbolnum >> 16) & 0x0ff; 778 where[5] = (r_symbolnum >> 8) & 0x0ff; 779 where[6] = r_symbolnum & 0x0ff; 780 where[7] = (((!S_IS_DEFINED (fixP->fx_addsy)) << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F); 781 782 /* Also easy. */ 783 md_number_to_chars (&where[8], fixP->fx_addnumber, 4); 784 } 785 786 #endif /* OBJ_AOUT */ 787 788 const char *md_shortopts = ""; 789 790 struct option md_longopts[] = 791 { 792 { NULL, no_argument, NULL, 0 } 793 }; 794 size_t md_longopts_size = sizeof (md_longopts); 795 796 int 797 md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED) 798 { 799 return 0; 800 } 801 802 void 803 md_show_usage (FILE * stream ATTRIBUTE_UNUSED) 804 { 805 } 806 807 /* This is called when a line is unrecognized. This is used to handle 808 definitions of or32 style local labels. */ 809 810 int 811 or32_unrecognized_line (int c) 812 { 813 int lab; 814 char *s; 815 816 if (c != '$' 817 || ! ISDIGIT ((unsigned char) input_line_pointer[0])) 818 return 0; 819 820 s = input_line_pointer; 821 822 lab = 0; 823 while (ISDIGIT ((unsigned char) *s)) 824 { 825 lab = lab * 10 + *s - '0'; 826 ++s; 827 } 828 829 if (*s != ':') 830 /* Not a label definition. */ 831 return 0; 832 833 if (dollar_label_defined (lab)) 834 { 835 as_bad (_("label \"$%d\" redefined"), lab); 836 return 0; 837 } 838 839 define_dollar_label (lab); 840 colon (dollar_label_name (lab, 0)); 841 input_line_pointer = s + 1; 842 843 return 1; 844 } 845 846 /* Default the values of symbols known that should be "predefined". We 847 don't bother to predefine them unless you actually use one, since there 848 are a lot of them. */ 849 850 symbolS * 851 md_undefined_symbol (char *name ATTRIBUTE_UNUSED) 852 { 853 return NULL; 854 } 855 856 /* Parse an operand that is machine-specific. */ 857 858 void 859 md_operand (expressionS *expressionP) 860 { 861 #if DEBUG 862 printf (" md_operand(input_line_pointer = %s)\n", input_line_pointer); 863 #endif 864 865 if (input_line_pointer[0] == REGISTER_PREFIX && input_line_pointer[1] == 'r') 866 { 867 /* We have a numeric register expression. No biggy. */ 868 input_line_pointer += 2; /* Skip %r */ 869 (void) expression (expressionP); 870 871 if (expressionP->X_op != O_constant 872 || expressionP->X_add_number > 255) 873 as_bad (_("Invalid expression after %%%%\n")); 874 expressionP->X_op = O_register; 875 } 876 else if (input_line_pointer[0] == '&') 877 { 878 /* We are taking the 'address' of a register...this one is not 879 in the manual, but it *is* in traps/fpsymbol.h! What they 880 seem to want is the register number, as an absolute number. */ 881 input_line_pointer++; /* Skip & */ 882 (void) expression (expressionP); 883 884 if (expressionP->X_op != O_register) 885 as_bad (_("invalid register in & expression")); 886 else 887 expressionP->X_op = O_constant; 888 } 889 else if (input_line_pointer[0] == '$' 890 && ISDIGIT ((unsigned char) input_line_pointer[1])) 891 { 892 long lab; 893 char *name; 894 symbolS *sym; 895 896 /* This is a local label. */ 897 ++input_line_pointer; 898 lab = (long) get_absolute_expression (); 899 900 if (dollar_label_defined (lab)) 901 { 902 name = dollar_label_name (lab, 0); 903 sym = symbol_find (name); 904 } 905 else 906 { 907 name = dollar_label_name (lab, 1); 908 sym = symbol_find_or_make (name); 909 } 910 911 expressionP->X_op = O_symbol; 912 expressionP->X_add_symbol = sym; 913 expressionP->X_add_number = 0; 914 } 915 else if (input_line_pointer[0] == '$') 916 { 917 char *s; 918 char type; 919 int fieldnum, fieldlimit; 920 LITTLENUM_TYPE floatbuf[8]; 921 922 /* $float(), $doubleN(), or $extendN() convert floating values 923 to integers. */ 924 s = input_line_pointer; 925 926 ++s; 927 928 fieldnum = 0; 929 if (strncmp (s, "double", sizeof "double" - 1) == 0) 930 { 931 s += sizeof "double" - 1; 932 type = 'd'; 933 fieldlimit = 2; 934 } 935 else if (strncmp (s, "float", sizeof "float" - 1) == 0) 936 { 937 s += sizeof "float" - 1; 938 type = 'f'; 939 fieldlimit = 1; 940 } 941 else if (strncmp (s, "extend", sizeof "extend" - 1) == 0) 942 { 943 s += sizeof "extend" - 1; 944 type = 'x'; 945 fieldlimit = 4; 946 } 947 else 948 return; 949 950 if (ISDIGIT (*s)) 951 { 952 fieldnum = *s - '0'; 953 ++s; 954 } 955 if (fieldnum >= fieldlimit) 956 return; 957 958 SKIP_WHITESPACE (); 959 if (*s != '(') 960 return; 961 ++s; 962 SKIP_WHITESPACE (); 963 964 s = atof_ieee (s, type, floatbuf); 965 if (s == NULL) 966 return; 967 s = s; 968 969 SKIP_WHITESPACE (); 970 if (*s != ')') 971 return; 972 ++s; 973 SKIP_WHITESPACE (); 974 975 input_line_pointer = s; 976 expressionP->X_op = O_constant; 977 expressionP->X_unsigned = 1; 978 expressionP->X_add_number = ((floatbuf[fieldnum * 2] 979 << LITTLENUM_NUMBER_OF_BITS) 980 + floatbuf[fieldnum * 2 + 1]); 981 } 982 } 983 984 /* Round up a section size to the appropriate boundary. */ 985 986 valueT 987 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size ATTRIBUTE_UNUSED) 988 { 989 return size; /* Byte alignment is fine. */ 990 } 991 992 /* Exactly what point is a PC-relative offset relative TO? 993 On the 29000, they're relative to the address of the instruction, 994 which we have set up as the address of the fixup too. */ 995 996 long 997 md_pcrel_from (fixS *fixP) 998 { 999 return fixP->fx_where + fixP->fx_frag->fr_address; 1000 } 1001 1002 /* Generate a reloc for a fixup. */ 1003 1004 arelent * 1005 tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) 1006 { 1007 arelent *reloc; 1008 1009 reloc = xmalloc (sizeof (arelent)); 1010 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); 1011 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 1012 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; 1013 /* reloc->address = fixp->fx_frag->fr_address + fixp->fx_where + fixp->fx_addnumber;*/ 1014 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); 1015 1016 if (reloc->howto == (reloc_howto_type *) NULL) 1017 { 1018 as_bad_where (fixp->fx_file, fixp->fx_line, 1019 _("reloc %d not supported by object file format"), 1020 (int) fixp->fx_r_type); 1021 return NULL; 1022 } 1023 1024 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) 1025 reloc->address = fixp->fx_offset; 1026 1027 reloc->addend = fixp->fx_addnumber; 1028 return reloc; 1029 } 1030