1 /*- 2 * This code is derived from software copyrighted by the Free Software 3 * Foundation. 4 * 5 * Modified 1993 by Chris Torek at Lawrence Berkeley Laboratory. 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)sparc.c 5.2 (Berkeley) 04/12/93"; 10 #endif /* not lint */ 11 12 /* sparc.c -- Assemble for the SPARC 13 Copyright (C) 1989 Free Software Foundation, Inc. 14 15 This file is part of GAS, the GNU Assembler. 16 17 GAS is free software; you can redistribute it and/or modify 18 it under the terms of the GNU General Public License as published by 19 the Free Software Foundation; either version 1, or (at your option) 20 any later version. 21 22 GAS is distributed in the hope that it will be useful, 23 but WITHOUT ANY WARRANTY; without even the implied warranty of 24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 GNU General Public License for more details. 26 27 You should have received a copy of the GNU General Public License 28 along with GAS; see the file COPYING. If not, write to 29 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 30 31 32 #include <stdio.h> 33 #include <ctype.h> 34 35 #include "sparc-opcode.h" 36 #include "as.h" 37 #include "frags.h" 38 #include "struc-symbol.h" 39 #include "flonum.h" 40 #include "expr.h" 41 #include "hash.h" 42 #include "md.h" 43 #include "sparc.h" 44 #include "write.h" 45 #include "read.h" 46 #include "symbols.h" 47 48 void md_begin(); 49 void md_end(); 50 void md_number_to_chars(); 51 void md_assemble(); 52 char *md_atof(); 53 void md_convert_frag(); 54 void md_create_short_jump(); 55 void md_create_long_jump(); 56 int md_estimate_size_before_relax(); 57 void md_number_to_imm(); 58 void md_number_to_disp(); 59 void md_number_to_field(); 60 void md_ri_to_chars(); 61 void emit_relocations(); 62 static void sparc_ip(); 63 64 const relax_typeS md_relax_table[] = { 0 }; 65 66 /* handle of the OPCODE hash table */ 67 static struct hash_control *op_hash = NULL; 68 69 static void s_seg(), s_proc(), s_data1(), s_reserve(), s_common(); 70 extern void s_globl(), s_long(), s_short(), s_space(), cons(); 71 72 const pseudo_typeS 73 md_pseudo_table[] = { 74 { "common", s_common, 0 }, 75 { "global", s_globl, 0 }, 76 { "half", cons, 2 }, 77 { "proc", s_proc, 0 }, 78 { "reserve", s_reserve, 0 }, 79 { "seg", s_seg, 0 }, 80 { "skip", s_space, 0 }, 81 { "word", cons, 4 }, 82 { NULL, 0, 0 }, 83 }; 84 85 int md_short_jump_size = 4; 86 int md_long_jump_size = 4; 87 int omagic = (0x103 << 16) | OMAGIC; /* Magic number for header */ 88 89 /* This array holds the chars that always start a comment. If the 90 pre-processor is disabled, these aren't very useful */ 91 char comment_chars[] = "!"; /* JF removed '|' from 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 '/*' will always start a comment */ 100 char line_comment_chars[] = "#"; 101 102 /* Chars that can be used to separate mant from exp in floating point nums */ 103 char EXP_CHARS[] = "eE"; 104 105 /* Chars that mean this number is a floating point constant */ 106 /* As in 0f12.456 */ 107 /* or 0d1.2345e12 */ 108 char FLT_CHARS[] = "rRsSfFdDxXpP"; 109 110 /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be 111 changed in read.c . Ideally it shouldn't have to know about it at all, 112 but nothing is ideal around here. 113 */ 114 int size_reloc_info = sizeof(struct reloc_info_sparc); 115 116 static unsigned char octal[256]; 117 #define isoctal(c) octal[c] 118 static unsigned char toHex[256]; 119 120 /* 121 * anull bit - causes the branch delay slot instructions to not be executed 122 */ 123 #define ANNUL (1 << 29) 124 125 struct sparc_it { 126 char *error; 127 unsigned long opcode; 128 struct nlist *nlistp; 129 expressionS exp; 130 int pcrel; 131 enum reloc_type reloc; 132 } the_insn, set_insn; 133 134 #ifdef __STDC__ 135 static void print_insn(struct sparc_it *insn); 136 static int getExpression(char *str); 137 #else 138 static void print_insn(); 139 static int getExpression(); 140 #endif 141 static char *expr_end; 142 static int special_case; 143 144 #define SPECIAL_CASE_SET 1 145 146 /* 147 * sort of like s_lcomm 148 * 149 */ 150 static void 151 s_reserve() 152 { 153 char *name; 154 char c; 155 char *p; 156 int temp; 157 symbolS *symbolP; 158 159 name = input_line_pointer; 160 c = get_symbol_end(); 161 p = input_line_pointer; 162 *p = c; 163 SKIP_WHITESPACE(); 164 if ( * input_line_pointer != ',' ) { 165 as_warn("Expected comma after name"); 166 ignore_rest_of_line(); 167 return; 168 } 169 input_line_pointer ++; 170 if ((temp = get_absolute_expression()) < 0) { 171 as_warn("BSS length (%d.) <0! Ignored.", temp); 172 ignore_rest_of_line(); 173 return; 174 } 175 *p = 0; 176 symbolP = symbol_find_or_make(name); 177 *p = c; 178 if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0) { 179 as_warn("bad .reserve segment: `%s'", input_line_pointer); 180 return; 181 } 182 input_line_pointer += 6; 183 if (symbolP->sy_other == 0 184 && symbolP->sy_desc == 0 185 && ((symbolP->sy_type == N_BSS 186 && symbolP->sy_value == local_bss_counter) 187 || ((symbolP->sy_type & N_TYPE) == N_UNDF 188 && symbolP->sy_value == 0))) { 189 symbolP->sy_value = local_bss_counter; 190 symbolP->sy_type = N_BSS; 191 symbolP->sy_frag = & bss_address_frag; 192 local_bss_counter += temp; 193 } else { 194 as_warn( "Ignoring attempt to re-define symbol from %d. to %d.", 195 symbolP->sy_value, local_bss_counter ); 196 } 197 demand_empty_rest_of_line(); 198 return; 199 } 200 201 static void 202 s_common() 203 { 204 register char *name; 205 register char c; 206 register char *p; 207 register int temp; 208 register symbolS * symbolP; 209 210 name = input_line_pointer; 211 c = get_symbol_end(); 212 /* just after name is now '\0' */ 213 p = input_line_pointer; 214 *p = c; 215 SKIP_WHITESPACE(); 216 if ( * input_line_pointer != ',' ) { 217 as_warn("Expected comma after symbol-name"); 218 ignore_rest_of_line(); 219 return; 220 } 221 input_line_pointer ++; /* skip ',' */ 222 if ( (temp = get_absolute_expression ()) < 0 ) { 223 as_warn(".COMMon length (%d.) <0! Ignored.", temp); 224 ignore_rest_of_line(); 225 return; 226 } 227 *p = 0; 228 symbolP = symbol_find_or_make (name); 229 *p = c; 230 if ( (symbolP->sy_type & N_TYPE) != N_UNDF || 231 symbolP->sy_other != 0 || symbolP->sy_desc != 0) { 232 as_warn( "Ignoring attempt to re-define symbol"); 233 ignore_rest_of_line(); 234 return; 235 } 236 if (symbolP->sy_value) { 237 if (symbolP->sy_value != temp) { 238 as_warn( "Length of .comm \"%s\" is already %d. Not changed to %d.", 239 symbolP->sy_name, symbolP->sy_value, temp); 240 } 241 } else { 242 symbolP->sy_value = temp; 243 symbolP->sy_type |= N_EXT; 244 } 245 know(symbolP->sy_frag == &zero_address_frag); 246 if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0) { 247 p=input_line_pointer; 248 while(*p && *p!='\n') 249 p++; 250 c= *p; 251 *p='\0'; 252 as_warn("bad .common segment: `%s'", input_line_pointer); 253 *p=c; 254 return; 255 } 256 input_line_pointer += 6; 257 demand_empty_rest_of_line(); 258 return; 259 } 260 261 static void 262 s_seg() 263 { 264 265 if (strncmp(input_line_pointer, "\"text\"", 6) == 0) { 266 input_line_pointer += 6; 267 s_text(); 268 return; 269 } 270 if (strncmp(input_line_pointer, "\"data\"", 6) == 0) { 271 input_line_pointer += 6; 272 s_data(); 273 return; 274 } 275 if (strncmp(input_line_pointer, "\"data1\"", 7) == 0) { 276 input_line_pointer += 7; 277 s_data1(); 278 return; 279 } 280 as_warn("Unknown segment type"); 281 demand_empty_rest_of_line(); 282 return; 283 } 284 285 static void 286 s_data1() 287 { 288 subseg_new(SEG_DATA, 1); 289 demand_empty_rest_of_line(); 290 return; 291 } 292 293 static void 294 s_proc() 295 { 296 extern char is_end_of_line[]; 297 298 while (!is_end_of_line[*input_line_pointer]) { 299 ++input_line_pointer; 300 } 301 ++input_line_pointer; 302 return; 303 } 304 305 /* This function is called once, at assembler startup time. It should 306 set up all the tables, etc. that the MD part of the assembler will need. */ 307 void 308 md_begin() 309 { 310 register char *retval = NULL; 311 int lose = 0; 312 register unsigned int i = 0; 313 314 op_hash = hash_new(); 315 if (op_hash == NULL) 316 as_fatal("Virtual memory exhausted"); 317 318 while (i < NUMOPCODES) 319 { 320 const char *name = sparc_opcodes[i].name; 321 retval = hash_insert(op_hash, name, &sparc_opcodes[i]); 322 if(retval != NULL && *retval != '\0') 323 { 324 fprintf (stderr, "internal error: can't hash `%s': %s\n", 325 sparc_opcodes[i].name, retval); 326 lose = 1; 327 } 328 do 329 { 330 if (sparc_opcodes[i].match & sparc_opcodes[i].lose) 331 { 332 fprintf (stderr, "internal error: losing opcode: `%s' \"%s\"\n", 333 sparc_opcodes[i].name, sparc_opcodes[i].args); 334 lose = 1; 335 } 336 ++i; 337 } while (i < NUMOPCODES 338 && !strcmp(sparc_opcodes[i].name, name)); 339 } 340 341 if (lose) 342 as_fatal ("Broken assembler. No assembly attempted."); 343 344 for (i = '0'; i < '8'; ++i) 345 octal[i] = 1; 346 for (i = '0'; i <= '9'; ++i) 347 toHex[i] = i - '0'; 348 for (i = 'a'; i <= 'f'; ++i) 349 toHex[i] = i + 10 - 'a'; 350 for (i = 'A'; i <= 'F'; ++i) 351 toHex[i] = i + 10 - 'A'; 352 } 353 354 void 355 md_end() 356 { 357 return; 358 } 359 360 void 361 md_assemble(str) 362 char *str; 363 { 364 char *toP; 365 int rsd; 366 367 assert(str); 368 sparc_ip(str); 369 toP = frag_more(4); 370 /* put out the opcode */ 371 md_number_to_chars(toP, the_insn.opcode, 4); 372 373 /* put out the symbol-dependent stuff */ 374 if (the_insn.reloc != NO_RELOC) { 375 fix_new( 376 frag_now, /* which frag */ 377 (toP - frag_now->fr_literal), /* where */ 378 4, /* size */ 379 the_insn.exp.X_add_symbol, 380 the_insn.exp.X_subtract_symbol, 381 the_insn.exp.X_add_number, 382 the_insn.pcrel, 383 the_insn.reloc 384 ); 385 } 386 switch (special_case) { 387 388 case SPECIAL_CASE_SET: 389 special_case = 0; 390 assert(the_insn.reloc == RELOC_HI22); 391 if (the_insn.exp.X_seg == SEG_ABSOLUTE && 392 the_insn.exp.X_add_symbol == 0 && 393 the_insn.exp.X_subtract_symbol == 0 && 394 (the_insn.exp.X_add_number & 0x3ff) == 0) 395 return; 396 toP = frag_more(4); 397 rsd = (the_insn.opcode >> 25) & 0x1f; 398 the_insn.opcode = 0x80102000 | (rsd << 25) | (rsd << 14); 399 md_number_to_chars(toP, the_insn.opcode, 4); 400 fix_new( 401 frag_now, /* which frag */ 402 (toP - frag_now->fr_literal), /* where */ 403 4, /* size */ 404 the_insn.exp.X_add_symbol, 405 the_insn.exp.X_subtract_symbol, 406 the_insn.exp.X_add_number, 407 the_insn.pcrel, 408 RELOC_LO10 409 ); 410 return; 411 412 case 0: 413 return; 414 415 default: 416 abort(); 417 } 418 } 419 420 static void 421 sparc_ip(str) 422 char *str; 423 { 424 char *s; 425 const char *args; 426 char c; 427 unsigned long i; 428 struct sparc_opcode *insn; 429 char *argsStart; 430 unsigned long opcode; 431 unsigned int mask; 432 int match = FALSE; 433 int comma = 0; 434 435 for (s = str; islower(*s) || (*s >= '0' && *s <= '3'); ++s) 436 ; 437 switch (*s) { 438 439 case '\0': 440 break; 441 442 case ',': 443 comma = 1; 444 445 /*FALLTHROUGH*/ 446 447 case ' ': 448 *s++ = '\0'; 449 break; 450 451 default: 452 as_warn("Unknown opcode: `%s'", str); 453 exit(1); 454 } 455 if ((insn = (struct sparc_opcode *) hash_find(op_hash, str)) == NULL) { 456 as_warn("Unknown opcode: `%s'", str); 457 return; 458 } 459 if (comma) { 460 *--s = ','; 461 } 462 argsStart = s; 463 for (;;) { 464 opcode = insn->match; 465 bzero(&the_insn, sizeof(the_insn)); 466 the_insn.reloc = NO_RELOC; 467 468 /* 469 * Build the opcode, checking as we go to make 470 * sure that the operands match 471 */ 472 for (args = insn->args; ; ++args) { 473 switch (*args) { 474 475 case '\0': /* end of args */ 476 if (*s == '\0') { 477 match = TRUE; 478 } 479 break; 480 481 case '+': 482 if (*s == '+') { 483 ++s; 484 continue; 485 } 486 if (*s == '-') { 487 continue; 488 } 489 break; 490 491 case '[': /* these must match exactly */ 492 case ']': 493 case ',': 494 case ' ': 495 if (*s++ == *args) 496 continue; 497 break; 498 499 case '#': /* must be at least one digit */ 500 if (isdigit(*s++)) { 501 while (isdigit(*s)) { 502 ++s; 503 } 504 continue; 505 } 506 break; 507 508 case 'C': /* coprocessor state register */ 509 if (strncmp(s, "%csr", 4) == 0) { 510 s += 4; 511 continue; 512 } 513 break; 514 515 case 'b': /* next operand is a coprocessor register */ 516 case 'c': 517 case 'D': 518 if (*s++ == '%' && *s++ == 'c' && isdigit(*s)) { 519 mask = *s++; 520 if (isdigit(*s)) { 521 mask = 10 * (mask - '0') + (*s++ - '0'); 522 if (mask >= 32) { 523 break; 524 } 525 } else { 526 mask -= '0'; 527 } 528 switch (*args) { 529 530 case 'b': 531 opcode |= mask << 14; 532 continue; 533 534 case 'c': 535 opcode |= mask; 536 continue; 537 538 case 'D': 539 opcode |= mask << 25; 540 continue; 541 } 542 } 543 break; 544 545 case 'r': /* next operand must be a register */ 546 case 'R': 547 case '1': 548 case '2': 549 case 'd': 550 if (*s++ == '%') { 551 switch (c = *s++) { 552 553 case 'f': /* frame pointer */ 554 if (*s++ == 'p') { 555 mask = 0x1e; 556 break; 557 } 558 goto error; 559 560 case 'g': /* global register */ 561 if (isoctal(c = *s++)) { 562 mask = c - '0'; 563 break; 564 } 565 goto error; 566 567 case 'i': /* in register */ 568 if (isoctal(c = *s++)) { 569 mask = c - '0' + 24; 570 break; 571 } 572 goto error; 573 574 case 'l': /* local register */ 575 if (isoctal(c = *s++)) { 576 mask= (c - '0' + 16) ; 577 break; 578 } 579 goto error; 580 581 case 'o': /* out register */ 582 if (isoctal(c = *s++)) { 583 mask= (c - '0' + 8) ; 584 break; 585 } 586 goto error; 587 588 case 's': /* stack pointer */ 589 if (*s++ == 'p') { 590 mask= 0xe; 591 break; 592 } 593 goto error; 594 595 case 'r': /* any register */ 596 if (!isdigit(c = *s++)) { 597 goto error; 598 } 599 /* FALLTHROUGH */ 600 case '0': case '1': case '2': case '3': case '4': 601 case '5': case '6': case '7': case '8': case '9': 602 if (isdigit(*s)) { 603 if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) { 604 goto error; 605 } 606 } else { 607 c -= '0'; 608 } 609 mask= c; 610 break; 611 612 default: 613 goto error; 614 } 615 /* 616 * Got the register, now figure out where 617 * it goes in the opcode. 618 */ 619 switch (*args) { 620 621 case '1': 622 opcode |= mask << 14; 623 continue; 624 625 case '2': 626 opcode |= mask; 627 continue; 628 629 case 'd': 630 opcode |= mask << 25; 631 continue; 632 633 case 'r': 634 opcode |= (mask << 25) | (mask << 14); 635 continue; 636 637 case 'R': 638 opcode |= (mask << 25) | mask; 639 continue; 640 } 641 } 642 break; 643 644 case 'e': /* next operand is a floating point register */ 645 case 'f': 646 case 'g': 647 if (*s++ == '%' && *s++ == 'f' && isdigit(*s)) { 648 mask = *s++; 649 if (isdigit(*s)) { 650 mask = 10 * (mask - '0') + (*s++ - '0'); 651 if (mask >= 32) { 652 break; 653 } 654 } else { 655 mask -= '0'; 656 } 657 switch (*args) { 658 659 case 'e': 660 opcode |= mask << 14; 661 continue; 662 663 case 'f': 664 opcode |= mask; 665 continue; 666 667 case 'g': 668 opcode |= mask << 25; 669 continue; 670 } 671 } 672 break; 673 674 case 'F': 675 if (strncmp(s, "%fsr", 4) == 0) { 676 s += 4; 677 continue; 678 } 679 break; 680 681 case 'h': /* high 22 bits */ 682 the_insn.reloc = RELOC_HI22; 683 goto immediate; 684 685 case 'l': /* 22 bit PC relative immediate */ 686 the_insn.reloc = RELOC_WDISP22; 687 the_insn.pcrel = 1; 688 goto immediate; 689 690 case 'L': /* 30 bit immediate */ 691 the_insn.reloc = RELOC_WDISP30; 692 the_insn.pcrel = 1; 693 goto immediate; 694 695 case 'i': /* 13 bit immediate */ 696 the_insn.reloc = RELOC_BASE13; 697 698 /*FALLTHROUGH*/ 699 700 immediate: 701 if(*s==' ') 702 s++; 703 if (*s == '%') { 704 if ((c = s[1]) == 'h' && s[2] == 'i') { 705 the_insn.reloc = RELOC_HI22; 706 s+=3; 707 } else if (c == 'l' && s[2] == 'o') { 708 the_insn.reloc = RELOC_LO10; 709 s+=3; 710 } else 711 break; 712 } 713 /* Note that if the getExpression() fails, we will still have 714 created U entries in the symbol table for the 'symbols' 715 in the input string. Try not to create U symbols for 716 registers, etc. */ 717 { 718 /* This stuff checks to see if the expression ends 719 in +%reg If it does, it removes the register from 720 the expression, and re-sets 's' to point to the 721 right place */ 722 723 char *s1; 724 725 for(s1=s;*s1 && *s1!=','&& *s1!=']';s1++) 726 ; 727 728 if(s1!=s && isdigit(s1[-1])) { 729 if(s1[-2]=='%' && s1[-3]=='+') { 730 s1-=3; 731 *s1='\0'; 732 (void)getExpression(s); 733 *s1='+'; 734 s=s1; 735 continue; 736 } else if(index("goli0123456789",s1[-2]) && s1[-3]=='%' && s1[-4]=='+') { 737 s1-=4; 738 *s1='\0'; 739 (void)getExpression(s); 740 *s1='+'; 741 s=s1; 742 continue; 743 } 744 } 745 } 746 (void)getExpression(s); 747 s = expr_end; 748 continue; 749 750 case 'a': 751 if (*s++ == 'a') { 752 opcode |= ANNUL; 753 continue; 754 } 755 break; 756 757 case 'A': /* alternate space */ 758 if (isdigit(*s)) { 759 long num; 760 761 num=0; 762 while (isdigit(*s)) { 763 num= num*10 + *s-'0'; 764 ++s; 765 } 766 opcode |= num<<5; 767 continue; 768 } 769 break; 770 /* abort(); */ 771 772 case 'p': 773 if (strncmp(s, "%psr", 4) == 0) { 774 s += 4; 775 continue; 776 } 777 break; 778 779 case 'q': /* floating point queue */ 780 if (strncmp(s, "%fq", 3) == 0) { 781 s += 3; 782 continue; 783 } 784 break; 785 786 case 'Q': /* coprocessor queue */ 787 if (strncmp(s, "%cq", 3) == 0) { 788 s += 3; 789 continue; 790 } 791 break; 792 793 case 'S': 794 if (strcmp(str, "set") == 0) { 795 special_case = SPECIAL_CASE_SET; 796 continue; 797 } 798 break; 799 800 case 't': 801 if (strncmp(s, "%tbr", 4) != 0) 802 break; 803 s += 4; 804 continue; 805 806 case 'w': 807 if (strncmp(s, "%wim", 4) != 0) 808 break; 809 s += 4; 810 continue; 811 812 case 'y': 813 if (strncmp(s, "%y", 2) != 0) 814 break; 815 s += 2; 816 continue; 817 818 default: 819 abort(); 820 } 821 break; 822 } 823 error: 824 if (match == FALSE) 825 { 826 /* Args don't match. */ 827 if (&insn[1] - sparc_opcodes < NUMOPCODES 828 && !strcmp(insn->name, insn[1].name)) 829 { 830 ++insn; 831 s = argsStart; 832 continue; 833 } 834 else 835 { 836 as_warn("Illegal operands"); 837 return; 838 } 839 } 840 break; 841 } 842 843 the_insn.opcode = opcode; 844 return; 845 } 846 847 static int 848 getExpression(str) 849 char *str; 850 { 851 char *save_in; 852 segT seg; 853 854 save_in = input_line_pointer; 855 input_line_pointer = str; 856 switch (seg = expression(&the_insn.exp)) { 857 858 case SEG_ABSOLUTE: 859 case SEG_TEXT: 860 case SEG_DATA: 861 case SEG_BSS: 862 case SEG_UNKNOWN: 863 case SEG_DIFFERENCE: 864 case SEG_BIG: 865 case SEG_NONE: 866 break; 867 868 default: 869 the_insn.error = "bad segment"; 870 expr_end = input_line_pointer; 871 input_line_pointer=save_in; 872 return 1; 873 } 874 expr_end = input_line_pointer; 875 input_line_pointer = save_in; 876 return 0; 877 } 878 879 880 /* 881 This is identical to the md_atof in m68k.c. I think this is right, 882 but I'm not sure. 883 884 Turn a string in input_line_pointer into a floating point constant of type 885 type, and store the appropriate bytes in *litP. The number of LITTLENUMS 886 emitted is stored in *sizeP . An error message is returned, or NULL on OK. 887 */ 888 889 /* Equal to MAX_PRECISION in atof-ieee.c */ 890 #define MAX_LITTLENUMS 6 891 892 char * 893 md_atof(type,litP,sizeP) 894 char type; 895 char *litP; 896 int *sizeP; 897 { 898 int prec; 899 LITTLENUM_TYPE words[MAX_LITTLENUMS]; 900 LITTLENUM_TYPE *wordP; 901 char *t; 902 char *atof_ieee(); 903 904 switch(type) { 905 906 case 'f': 907 case 'F': 908 case 's': 909 case 'S': 910 prec = 2; 911 break; 912 913 case 'd': 914 case 'D': 915 case 'r': 916 case 'R': 917 prec = 4; 918 break; 919 920 case 'x': 921 case 'X': 922 prec = 6; 923 break; 924 925 case 'p': 926 case 'P': 927 prec = 6; 928 break; 929 930 default: 931 *sizeP=0; 932 return "Bad call to MD_ATOF()"; 933 } 934 t=atof_ieee(input_line_pointer,type,words); 935 if(t) 936 input_line_pointer=t; 937 *sizeP=prec * sizeof(LITTLENUM_TYPE); 938 for(wordP=words;prec--;) { 939 md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE)); 940 litP+=sizeof(LITTLENUM_TYPE); 941 } 942 return ""; /* Someone should teach Dean about null pointers */ 943 } 944 945 /* 946 * Write out big-endian. 947 */ 948 void 949 md_number_to_chars(buf,val,n) 950 char *buf; 951 long val; 952 int n; 953 { 954 955 switch(n) { 956 957 case 4: 958 *buf++ = val >> 24; 959 *buf++ = val >> 16; 960 case 2: 961 *buf++ = val >> 8; 962 case 1: 963 *buf = val; 964 break; 965 966 default: 967 abort(); 968 } 969 return; 970 } 971 972 void 973 md_number_to_imm(buf,val,n, fixP, seg_type) 974 char *buf; 975 long val; 976 int n; 977 fixS *fixP; 978 int seg_type; 979 { 980 if (seg_type != N_TEXT || fixP->fx_r_type == NO_RELOC) { 981 switch (n) { 982 case 1: 983 *buf = val; 984 break; 985 case 2: 986 *buf++ = (val>>8); 987 *buf = val; 988 break; 989 case 4: 990 *buf++ = (val>>24); 991 *buf++ = (val>>16); 992 *buf++ = (val>>8); 993 *buf = val; 994 break; 995 default: 996 abort(); 997 } 998 return; 999 } 1000 1001 assert(n == 4); 1002 assert(fixP->fx_r_type < NO_RELOC); 1003 1004 /* 1005 * This is a hack. There should be a better way to 1006 * handle this. 1007 */ 1008 if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy) { 1009 val += fixP->fx_where + fixP->fx_frag->fr_address; 1010 } 1011 1012 switch (fixP->fx_r_type) { 1013 1014 case RELOC_32: 1015 buf[0] = val >> 24; 1016 buf[1] = val >> 16; 1017 buf[2] = val >> 8; 1018 buf[3] = val; 1019 break; 1020 1021 #if 0 1022 case RELOC_8: /* These don't seem to ever be needed. */ 1023 case RELOC_16: 1024 case RELOC_DISP8: 1025 case RELOC_DISP16: 1026 case RELOC_DISP32: 1027 #endif 1028 case RELOC_WDISP30: 1029 val = (val >>= 2) + 1; 1030 buf[0] |= (val >> 24) & 0x3f; 1031 buf[1]= (val >> 16); 1032 buf[2] = val >> 8; 1033 buf[3] = val; 1034 break; 1035 1036 case RELOC_HI22: 1037 if(!fixP->fx_addsy) { 1038 buf[1] |= (val >> 26) & 0x3f; 1039 buf[2] = val >> 18; 1040 buf[3] = val >> 10; 1041 } else { 1042 buf[2]=0; 1043 buf[3]=0; 1044 } 1045 break; 1046 #if 0 1047 case RELOC_22: 1048 case RELOC_13: 1049 #endif 1050 case RELOC_LO10: 1051 if(!fixP->fx_addsy) { 1052 buf[2] |= (val >> 8) & 0x03; 1053 buf[3] = val; 1054 } else 1055 buf[3]=0; 1056 break; 1057 #if 0 1058 case RELOC_SFA_BASE: 1059 case RELOC_SFA_OFF13: 1060 case RELOC_BASE10: 1061 #endif 1062 case RELOC_BASE13: 1063 buf[2] |= (val >> 8) & 0x1f; 1064 buf[3] = val; 1065 break; 1066 1067 case RELOC_WDISP22: 1068 val = (val >>= 2) + 1; 1069 /* FALLTHROUGH */ 1070 case RELOC_BASE22: 1071 buf[1] |= (val >> 16) & 0x3f; 1072 buf[2] = val >> 8; 1073 buf[3] = val; 1074 break; 1075 1076 #if 0 1077 case RELOC_PC10: 1078 case RELOC_PC22: 1079 case RELOC_JMP_TBL: 1080 case RELOC_SEGOFF16: 1081 case RELOC_GLOB_DAT: 1082 case RELOC_JMP_SLOT: 1083 case RELOC_RELATIVE: 1084 #endif 1085 1086 case NO_RELOC: 1087 default: 1088 as_warn("bad relocation type: 0x%02x", fixP->fx_r_type); 1089 break; 1090 } 1091 return; 1092 } 1093 1094 /* should never be called for sparc */ 1095 void 1096 md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol) 1097 char *ptr; 1098 long from_addr, to_addr; 1099 { 1100 fprintf(stderr, "sparc_create_short_jmp\n"); 1101 abort(); 1102 } 1103 1104 /* should never be called for sparc */ 1105 void 1106 md_number_to_disp(buf,val,n) 1107 char *buf; 1108 long val; 1109 { 1110 fprintf(stderr, "md_number_to_disp\n"); 1111 abort(); 1112 } 1113 1114 /* should never be called for sparc */ 1115 void 1116 md_number_to_field(buf,val,fix) 1117 char *buf; 1118 long val; 1119 void *fix; 1120 { 1121 fprintf(stderr, "sparc_number_to_field\n"); 1122 abort(); 1123 } 1124 1125 /* the bit-field entries in the relocation_info struct plays hell 1126 with the byte-order problems of cross-assembly. So as a hack, 1127 I added this mach. dependent ri twiddler. Ugly, but it gets 1128 you there. -KWK */ 1129 /* on sparc: first 4 bytes are normal unsigned long address, next three 1130 bytes are index, most sig. byte first. Byte 7 is broken up with 1131 bit 7 as external, bits 6 & 5 unused, and the lower 1132 five bits as relocation type. Next 4 bytes are long int addend. */ 1133 /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */ 1134 void 1135 md_ri_to_chars(ri_p, ri) 1136 struct reloc_info_sparc *ri_p, ri; 1137 { 1138 unsigned char the_bytes[sizeof(*ri_p)]; 1139 1140 /* this is easy */ 1141 md_number_to_chars(the_bytes, ri.r_address, sizeof(ri.r_address)); 1142 /* now the fun stuff */ 1143 the_bytes[4] = (ri.r_index >> 16) & 0x0ff; 1144 the_bytes[5] = (ri.r_index >> 8) & 0x0ff; 1145 the_bytes[6] = ri.r_index & 0x0ff; 1146 the_bytes[7] = ((ri.r_extern << 7) & 0x80) | (0 & 0x60) | (ri.r_type & 0x1F); 1147 /* Also easy */ 1148 md_number_to_chars(&the_bytes[8], ri.r_addend, sizeof(ri.r_addend)); 1149 /* now put it back where you found it, Junior... */ 1150 bcopy (the_bytes, (char *)ri_p, sizeof(*ri_p)); 1151 } 1152 1153 /* should never be called for sparc */ 1154 void 1155 md_convert_frag(fragP) 1156 register fragS *fragP; 1157 { 1158 fprintf(stderr, "sparc_convert_frag\n"); 1159 abort(); 1160 } 1161 1162 /* should never be called for sparc */ 1163 void 1164 md_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol) 1165 char *ptr; 1166 long from_addr, 1167 to_addr; 1168 fragS *frag; 1169 symbolS *to_symbol; 1170 { 1171 fprintf(stderr, "sparc_create_long_jump\n"); 1172 abort(); 1173 } 1174 1175 /* should never be called for sparc */ 1176 int 1177 md_estimate_size_before_relax(fragP, segtype) 1178 register fragS *fragP; 1179 { 1180 fprintf(stderr, "sparc_estimate_size_before_relax\n"); 1181 abort(); 1182 return 0; 1183 } 1184 1185 #if 0 1186 /* for debugging only */ 1187 static void 1188 print_insn(insn) 1189 struct sparc_it *insn; 1190 { 1191 char *Reloc[] = { 1192 "RELOC_8", 1193 "RELOC_16", 1194 "RELOC_32", 1195 "RELOC_DISP8", 1196 "RELOC_DISP16", 1197 "RELOC_DISP32", 1198 "RELOC_WDISP30", 1199 "RELOC_WDISP22", 1200 "RELOC_HI22", 1201 "RELOC_22", 1202 "RELOC_13", 1203 "RELOC_LO10", 1204 "RELOC_SFA_BASE", 1205 "RELOC_SFA_OFF13", 1206 "RELOC_BASE10", 1207 "RELOC_BASE13", 1208 "RELOC_BASE22", 1209 "RELOC_PC10", 1210 "RELOC_PC22", 1211 "RELOC_JMP_TBL", 1212 "RELOC_SEGOFF16", 1213 "RELOC_GLOB_DAT", 1214 "RELOC_JMP_SLOT", 1215 "RELOC_RELATIVE", 1216 "NO_RELOC" 1217 }; 1218 1219 if (insn->error) { 1220 fprintf(stderr, "ERROR: %s\n"); 1221 } 1222 fprintf(stderr, "opcode=0x%08x\n", insn->opcode); 1223 fprintf(stderr, "reloc = %s\n", Reloc[insn->reloc]); 1224 fprintf(stderr, "exp = {\n"); 1225 fprintf(stderr, "\t\tX_add_symbol = %s\n", 1226 insn->exp.X_add_symbol ? 1227 (insn->exp.X_add_symbol->sy_name ? 1228 insn->exp.X_add_symbol->sy_name : "???") : "0"); 1229 fprintf(stderr, "\t\tX_sub_symbol = %s\n", 1230 insn->exp.X_subtract_symbol ? 1231 (insn->exp.X_subtract_symbol->sy_name ? 1232 insn->exp.X_subtract_symbol->sy_name : "???") : "0"); 1233 fprintf(stderr, "\t\tX_add_number = %d\n", 1234 insn->exp.X_add_number); 1235 fprintf(stderr, "}\n"); 1236 return; 1237 } 1238 #endif 1239 1240 /* 1241 * Sparc relocations are completely different, so it needs 1242 * this machine dependent routine to emit them. 1243 */ 1244 void 1245 emit_relocations(fixP, segment_address_in_file) 1246 register fixS *fixP; 1247 relax_addressT segment_address_in_file; 1248 { 1249 struct reloc_info_sparc ri; 1250 register symbolS *symbolP; 1251 extern char *next_object_file_charP; 1252 long add_number; 1253 1254 bzero((char *) &ri, sizeof(ri)); 1255 for (; fixP; fixP = fixP->fx_next) { 1256 1257 if (fixP->fx_r_type >= NO_RELOC) { 1258 fprintf(stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type); 1259 abort(); 1260 } 1261 1262 if ((symbolP = fixP->fx_addsy) != NULL) { 1263 ri.r_address = fixP->fx_frag->fr_address + 1264 fixP->fx_where - segment_address_in_file; 1265 if ((symbolP->sy_type & N_TYPE) == N_UNDF) { 1266 ri.r_extern = 1; 1267 ri.r_index = symbolP->sy_number; 1268 } else { 1269 ri.r_extern = 0; 1270 ri.r_index = symbolP->sy_type & N_TYPE; 1271 } 1272 if (symbolP && symbolP->sy_frag) { 1273 ri.r_addend = symbolP->sy_frag->fr_address; 1274 } 1275 ri.r_type = fixP->fx_r_type; 1276 if (fixP->fx_pcrel) { 1277 /* ri.r_addend -= fixP->fx_where; */ 1278 ri.r_addend -= ri.r_address; 1279 } else { 1280 ri.r_addend = fixP->fx_addnumber; 1281 } 1282 1283 /* md_ri_to_chars((char *) &ri, ri); */ 1284 append(&next_object_file_charP, (char *)& ri, sizeof(ri)); 1285 } 1286 } 1287 return; 1288 } 1289 1290 int 1291 md_parse_option(argP,cntP,vecP) 1292 char **argP; 1293 int *cntP; 1294 char ***vecP; 1295 { 1296 return 1; 1297 } 1298 1299