1 /* tc-sparc.c -- Assemble for the SPARC
2 Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 * $FreeBSD: src/gnu/usr.bin/as/config/tc-sparc.c,v 1.8 1999/08/27 23:34:30 peter Exp $
22 * $DragonFly: src/gnu/usr.bin/as/config/Attic/tc-sparc.c,v 1.2 2003/06/17 04:25:44 dillon Exp $
31 /* careful, this file includes data *declarations* */
32 #include "opcode/sparc.h"
37 void md_number_to_chars();
40 void md_convert_frag();
41 void md_create_short_jump();
42 void md_create_long_jump();
43 int md_estimate_size_before_relax();
44 void md_ri_to_chars();
45 symbolS *md_undefined_symbol();
46 static void sparc_ip();
48 static enum sparc_architecture current_architecture = v6;
49 static int architecture_requested = 0;
50 static int warn_on_bump = 0;
52 const relax_typeS md_relax_table[] = {
55 /* handle of the OPCODE hash table */
56 static struct hash_control *op_hash = NULL;
58 static void s_seg(), s_proc(), s_data1(), s_reserve(), s_common(), s_empty();
59 extern void s_globl(), s_long(), s_short(), s_space(), cons();
60 extern void s_align_bytes(), s_ignore();
62 const pseudo_typeS md_pseudo_table[] = {
63 { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0) */
64 { "empty", s_empty, 0 },
65 { "common", s_common, 0 },
66 { "global", s_globl, 0 },
68 { "optim", s_ignore, 0 },
69 { "proc", s_proc, 0 },
70 { "reserve", s_reserve, 0 },
72 { "skip", s_space, 0 },
77 const int md_short_jump_size = 4;
78 const int md_long_jump_size = 4;
79 const int md_reloc_size = 12; /* Size of relocation record */
81 /* This array holds the chars that always start a comment. If the
82 pre-processor is disabled, these aren't very useful */
83 const char comment_chars[] = "!"; /* JF removed '|' from comment_chars */
85 /* This array holds the chars that only start a comment at the beginning of
86 a line. If the line seems to have the form '# 123 filename'
87 .line and .file directives will appear in the pre-processed output */
88 /* Note that input_file.c hand checks for '#' at the beginning of the
89 first line of the input file. This is because the compiler outputs
90 #NO_APP at the beginning of its output. */
91 /* Also note that comments started like this one will always
92 work if '/' isn't otherwise defined. */
93 const char line_comment_chars[] = "#";
95 /* Chars that can be used to separate mant from exp in floating point nums */
96 const char EXP_CHARS[] = "eE";
98 /* Chars that mean this number is a floating point constant */
101 const char FLT_CHARS[] = "rRsSfFdDxXpP";
103 /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
104 changed in read.c. Ideally it shouldn't have to know about it at all,
105 but nothing is ideal around here.
108 static unsigned char octal[256];
109 #define isoctal(c) octal[c]
110 static unsigned char toHex[256];
114 unsigned long opcode;
115 struct nlist *nlistp;
118 enum reloc_type reloc;
119 } the_insn, set_insn;
123 static void print_insn(struct sparc_it *insn);
125 static int getExpression(char *str);
126 #else /* not __STDC__ */
128 static void print_insn();
130 static int getExpression();
131 #endif /* not __STDC__ */
133 static char *Reloc[] = {
161 static char *expr_end;
162 static int special_case;
165 * Instructions that require wierd handling because they're longer than
168 #define SPECIAL_CASE_SET 1
169 #define SPECIAL_CASE_FDIV 2
172 * sort of like s_lcomm
175 static int max_alignment = 15;
177 static void s_reserve() {
186 name = input_line_pointer;
187 c = get_symbol_end();
188 p = input_line_pointer;
192 if (*input_line_pointer != ',') {
193 as_bad("Expected comma after name");
194 ignore_rest_of_line();
198 ++input_line_pointer;
200 if ((size = get_absolute_expression()) < 0) {
201 as_bad("BSS length (%d.) <0! Ignored.", size);
202 ignore_rest_of_line();
207 symbolP = symbol_find_or_make(name);
210 if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0) {
211 as_bad("bad .reserve segment: `%s'", input_line_pointer);
215 input_line_pointer += 6;
218 if (*input_line_pointer == ',') {
219 ++input_line_pointer;
222 if (*input_line_pointer == '\n') {
223 as_bad("Missing alignment");
227 align = get_absolute_expression();
228 if (align > max_alignment){
229 align = max_alignment;
230 as_warn("Alignment too large: %d. assumed.", align);
231 } else if (align < 0) {
233 as_warn("Alignment negative. 0 assumed.");
236 #define SEG_BSS SEG_E2
237 record_alignment(SEG_E2, align);
239 record_alignment(SEG_BSS, align);
242 /* convert to a power of 2 alignment */
243 for (temp = 0; (align & 1) == 0; align >>= 1, ++temp) ;;
246 as_bad("Alignment not a power of 2");
247 ignore_rest_of_line();
249 } /* not a power of two */
254 align = ~((~0) << align); /* Convert to a mask */
255 local_bss_counter = (local_bss_counter + align) & (~align);
256 } /* if has optional alignment */
258 if (S_GET_OTHER(symbolP) == 0
259 && S_GET_DESC(symbolP) == 0
260 && ((S_GET_SEGMENT(symbolP) == SEG_BSS
261 && S_GET_VALUE(symbolP) == local_bss_counter)
262 || !S_IS_DEFINED(symbolP))) {
263 S_SET_VALUE(symbolP, local_bss_counter);
264 S_SET_SEGMENT(symbolP, SEG_BSS);
265 symbolP->sy_frag = &bss_address_frag;
266 local_bss_counter += size;
268 as_warn("Ignoring attempt to re-define symbol from %d. to %d.",
269 S_GET_VALUE(symbolP), local_bss_counter);
270 } /* if not redefining */
272 demand_empty_rest_of_line();
276 static void s_common() {
281 register symbolS * symbolP;
283 name = input_line_pointer;
284 c = get_symbol_end();
285 /* just after name is now '\0' */
286 p = input_line_pointer;
289 if (* input_line_pointer != ',') {
290 as_bad("Expected comma after symbol-name");
291 ignore_rest_of_line();
294 input_line_pointer ++; /* skip ',' */
295 if ((temp = get_absolute_expression ()) < 0) {
296 as_bad(".COMMon length (%d.) <0! Ignored.", temp);
297 ignore_rest_of_line();
301 symbolP = symbol_find_or_make(name);
303 if (S_IS_DEFINED(symbolP)) {
304 as_bad("Ignoring attempt to re-define symbol");
305 ignore_rest_of_line();
308 if (S_GET_VALUE(symbolP) != 0) {
309 if (S_GET_VALUE(symbolP) != temp) {
310 as_warn("Length of .comm \"%s\" is already %d. Not changed to %d.",
311 S_GET_NAME(symbolP), S_GET_VALUE(symbolP), temp);
314 S_SET_VALUE(symbolP, temp);
315 S_SET_EXTERNAL(symbolP);
317 know(symbolP->sy_frag == &zero_address_frag);
318 if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0
319 && strncmp(input_line_pointer, ",\"data\"", 7) != 0) {
320 p=input_line_pointer;
321 while (*p && *p != '\n')
325 as_bad("bad .common segment: `%s'", input_line_pointer);
329 input_line_pointer += 6 + (input_line_pointer[2] == 'd'); /* Skip either */
330 demand_empty_rest_of_line();
334 static void s_seg() {
336 if (strncmp(input_line_pointer, "\"text\"", 6) == 0) {
337 input_line_pointer += 6;
341 if (strncmp(input_line_pointer, "\"data\"", 6) == 0) {
342 input_line_pointer += 6;
346 if (strncmp(input_line_pointer, "\"data1\"", 7) == 0) {
347 input_line_pointer += 7;
351 if (strncmp(input_line_pointer, "\"bss\"", 5) == 0) {
352 input_line_pointer += 5;
353 /* We only support 2 segments -- text and data -- for now, so
354 things in the "bss segment" will have to go into data for now.
355 You can still allocate SEG_BSS stuff with .lcomm or .reserve. */
356 subseg_new(SEG_DATA, 255); /* FIXME-SOMEDAY */
359 as_bad("Unknown segment type");
360 demand_empty_rest_of_line();
364 static void s_data1() {
365 subseg_new(SEG_DATA, 1);
366 demand_empty_rest_of_line();
370 static void s_proc() {
371 extern char is_end_of_line[];
373 while (!is_end_of_line[*input_line_pointer]) {
374 ++input_line_pointer;
376 ++input_line_pointer;
381 * GI: This is needed for compatability with Sun's assembler - which
382 * otherwise generates a warning when certain "suspect" instructions
383 * appear in the delay slot of a branch. And more seriously without
384 * this directive in certain cases Sun's assembler will rearrange
385 * code thinking it knows how to alter things when it doesn't.
390 demand_empty_rest_of_line();
394 /* This function is called once, at assembler startup time. It should
395 set up all the tables, etc. that the MD part of the assembler will need. */
397 register char *retval = NULL;
399 register unsigned int i = 0;
401 op_hash = hash_new();
403 as_fatal("Virtual memory exhausted");
405 while (i < NUMOPCODES) {
406 const char *name = sparc_opcodes[i].name;
407 retval = hash_insert(op_hash, name, &sparc_opcodes[i]);
408 if (retval != NULL && *retval != '\0') {
409 fprintf (stderr, "internal error: can't hash `%s': %s\n",
410 sparc_opcodes[i].name, retval);
415 if (sparc_opcodes[i].match & sparc_opcodes[i].lose) {
416 fprintf (stderr, "internal error: losing opcode: `%s' \"%s\"\n",
417 sparc_opcodes[i].name, sparc_opcodes[i].args);
421 } while (i < NUMOPCODES
422 && !strcmp(sparc_opcodes[i].name, name));
426 as_fatal("Broken assembler. No assembly attempted.");
428 for (i = '0'; i < '8'; ++i)
430 for (i = '0'; i <= '9'; ++i)
432 for (i = 'a'; i <= 'f'; ++i)
433 toHex[i] = i + 10 - 'a';
434 for (i = 'A'; i <= 'F'; ++i)
435 toHex[i] = i + 10 - 'A';
439 GOT_symbol = symbol_find_or_make("__GLOBAL_OFFSET_TABLE_");
447 void md_assemble(str)
456 /* See if "set" operand is absolute and small; skip sethi if so. */
457 if (special_case == SPECIAL_CASE_SET && the_insn.exp.X_seg == SEG_ABSOLUTE) {
458 if (the_insn.exp.X_add_number >= -(1<<12)
459 && the_insn.exp.X_add_number < (1<<12)) {
460 the_insn.opcode = 0x80102000 /* or %g0,imm,... */
461 | (the_insn.opcode & 0x3E000000) /* dest reg */
462 | (the_insn.exp.X_add_number & 0x1FFF); /* imm */
463 special_case = 0; /* No longer special */
464 the_insn.reloc = NO_RELOC; /* No longer relocated */
469 /* put out the opcode */
470 md_number_to_chars(toP, the_insn.opcode, 4);
472 /* put out the symbol-dependent stuff */
473 if (the_insn.reloc != NO_RELOC) {
474 fix_new(frag_now, /* which frag */
475 (toP - frag_now->fr_literal), /* where */
477 the_insn.exp.X_add_symbol,
478 the_insn.exp.X_subtract_symbol,
479 the_insn.exp.X_add_number,
482 the_insn.exp.X_got_symbol);
484 switch (special_case) {
486 case SPECIAL_CASE_SET:
488 know(the_insn.reloc == RELOC_HI22 ||
489 the_insn.reloc == RELOC_BASE22);
490 /* See if "set" operand has no low-order bits; skip OR if so. */
491 if (the_insn.exp.X_seg == SEG_ABSOLUTE
492 && ((the_insn.exp.X_add_number & 0x3FF) == 0))
495 rsd = (the_insn.opcode >> 25) & 0x1f;
496 the_insn.opcode = 0x80102000 | (rsd << 25) | (rsd << 14);
497 md_number_to_chars(toP, the_insn.opcode, 4);
498 fix_new(frag_now, /* which frag */
499 (toP - frag_now->fr_literal), /* where */
501 the_insn.exp.X_add_symbol,
502 the_insn.exp.X_subtract_symbol,
503 the_insn.exp.X_add_number,
505 the_insn.reloc==RELOC_BASE22?RELOC_BASE10:RELOC_LO10,
506 the_insn.exp.X_got_symbol);
509 case SPECIAL_CASE_FDIV:
510 /* According to information leaked from Sun, the "fdiv" instructions
511 on early SPARC machines would produce incorrect results sometimes.
512 The workaround is to add an fmovs of the destination register to
513 itself just after the instruction. This was true on machines
514 with Weitek 1165 float chips, such as the Sun-4/260 and /280. */
516 assert(the_insn.reloc == NO_RELOC);
518 rsd = (the_insn.opcode >> 25) & 0x1f;
519 the_insn.opcode = 0x81A00020 | (rsd << 25) | rsd; /* fmovs dest,dest */
520 md_number_to_chars(toP, the_insn.opcode, 4);
527 as_fatal("md_assemble: failed sanity check.");
529 } /* md_assemble() */
531 static void sparc_ip(str)
534 char *error_message = "";
538 struct sparc_opcode *insn;
540 unsigned long opcode;
541 unsigned int mask = 0;
545 for (s = str; islower(*s) || (*s >= '0' && *s <= '3'); ++s)
562 as_bad("Unknown opcode: `%s'", str);
565 if ((insn = (struct sparc_opcode *) hash_find(op_hash, str)) == NULL) {
566 as_bad("Unknown opcode: `%s'", str);
574 opcode = insn->match;
575 memset(&the_insn, '\0', sizeof(the_insn));
576 the_insn.reloc = NO_RELOC;
579 * Build the opcode, checking as we go to make
580 * sure that the operands match
582 for (args = insn->args; ; ++args) {
587 if (strncmp(s, "%asr", 4) == 0) {
593 while (isdigit(*s)) {
594 num = num*10 + *s-'0';
598 if (num < 16 || 31 < num) {
599 error_message = ": asr number must be between 15 and 31";
603 opcode |= (*args == 'M' ? RS1(num) : RD(num));
606 error_message = ": expecting %asrN";
608 } /* if %asr followed by a number. */
614 case '\0': /* end of args */
630 case '[': /* these must match exactly */
638 case '#': /* must be at least one digit */
640 while (isdigit(*s)) {
647 case 'C': /* coprocessor state register */
648 if (strncmp(s, "%csr", 4) == 0) {
654 case 'b': /* next operand is a coprocessor register */
657 if (*s++ == '%' && *s++ == 'c' && isdigit(*s)) {
660 mask = 10 * (mask - '0') + (*s++ - '0');
670 opcode |= mask << 14;
678 opcode |= mask << 25;
684 case 'r': /* next operand must be a register */
693 case 'f': /* frame pointer */
700 case 'g': /* global register */
701 if (isoctal(c = *s++)) {
707 case 'i': /* in register */
708 if (isoctal(c = *s++)) {
714 case 'l': /* local register */
715 if (isoctal(c = *s++)) {
716 mask= (c - '0' + 16) ;
721 case 'o': /* out register */
722 if (isoctal(c = *s++)) {
723 mask= (c - '0' + 8) ;
728 case 's': /* stack pointer */
735 case 'r': /* any register */
736 if (!isdigit(c = *s++)) {
740 case '0': case '1': case '2': case '3': case '4':
741 case '5': case '6': case '7': case '8': case '9':
743 if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) {
753 opcode |= (mask << 25) | mask;
760 * Got the register, now figure out where
761 * it goes in the opcode.
766 opcode |= mask << 14;
774 opcode |= mask << 25;
778 opcode |= (mask << 25) | (mask << 14);
781 opcode |= (mask << 25) | mask;
787 case 'e': /* next operand is a floating point register */
802 && ((format = *s) == 'f')
808 for (mask = 0; isdigit(*s); ++s) {
809 mask = 10 * mask + (*s - '0');
810 } /* read the number */
818 } /* register must be even numbered */
826 } /* register must be multiple of 4 */
830 error_message = ": There are only 32 f registers; [0-31]";
833 } /* if not an 'f' register. */
863 if (strncmp(s, "%fsr", 4) == 0) {
869 case 'h': /* high 22 bits */
871 * In the case of a `set' pseudo instruction
872 * we have an implied `%hi' operator.
874 if (special_case == SPECIAL_CASE_SET)
875 the_insn.reloc = RELOC_HI22;
877 the_insn.reloc = RELOC_22;
880 case 'l': /* 22 bit PC relative immediate */
881 the_insn.reloc = RELOC_WDISP22;
885 case 'L': /* 30 bit immediate */
888 picmode?RELOC_JMP_TBL:
894 case 'n': /* 22 bit immediate */
895 the_insn.reloc = RELOC_22;
898 case 'i': /* 13 bit immediate */
899 the_insn.reloc = RELOC_13;
907 if ((c = s[1]) == 'h' && s[2] == 'i') {
908 if (the_insn.reloc != RELOC_22)
910 "`%hi' in improper context");
911 the_insn.reloc = RELOC_HI22;
913 } else if (c == 'l' && s[2] == 'o') {
914 the_insn.reloc = RELOC_LO10;
919 /* Note that if the getExpression() fails, we
920 will still have created U entries in the
921 symbol table for the 'symbols' in the input
922 string. Try not to create U symbols for
925 /* This stuff checks to see if the
926 expression ends in +%reg If it does,
927 it removes the register from the
928 expression, and re-sets 's' to point
929 to the right place */
933 for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++) ;;
935 if (s1 != s && isdigit(s1[-1])) {
936 if (s1[-2] == '%' && s1[-3] == '+') {
939 (void) getExpression(s);
943 } else if (strchr("goli0123456789", s1[-2]) && s1[-3] == '%' && s1[-4] == '+') {
946 (void) getExpression(s);
953 (void)getExpression(s);
956 * Handle refs to __GLOBAL_OFFSET_TABLE_
958 if (the_insn.exp.X_got_symbol) {
959 switch(the_insn.reloc) {
962 the_insn.reloc = RELOC_PC22;
966 the_insn.reloc = RELOC_PC10;
974 if (picmode && the_insn.exp.X_add_symbol) {
975 switch (the_insn.reloc) {
977 the_insn.reloc = RELOC_BASE10;
978 the_insn.exp.X_add_symbol->sy_forceout = 1;
981 the_insn.reloc = RELOC_BASE22;
982 the_insn.exp.X_add_symbol->sy_forceout = 1;
985 the_insn.reloc = RELOC_BASE13;
986 the_insn.exp.X_add_symbol->sy_forceout = 1;
1002 char *push = input_line_pointer;
1005 input_line_pointer = s;
1007 if (expression(&e) == SEG_ABSOLUTE) {
1008 opcode |= e.X_add_number << 5;
1009 s = input_line_pointer;
1010 input_line_pointer = push;
1015 } /* alternate space */
1018 if (strncmp(s, "%psr", 4) == 0) {
1024 case 'q': /* floating point queue */
1025 if (strncmp(s, "%fq", 3) == 0) {
1031 case 'Q': /* coprocessor queue */
1032 if (strncmp(s, "%cq", 3) == 0) {
1039 if (strcmp(str, "set") == 0) {
1040 special_case = SPECIAL_CASE_SET;
1042 } else if (strncmp(str, "fdiv", 4) == 0) {
1043 special_case = SPECIAL_CASE_FDIV;
1049 if (strncmp(s, "%tbr", 4) != 0)
1055 if (strncmp(s, "%wim", 4) != 0)
1061 if (strncmp(s, "%y", 2) != 0)
1067 as_fatal("sparc_ip: failed sanity check.");
1068 } /* switch on arg code */
1070 } /* for each arg that we expect */
1073 /* Args don't match. */
1074 if (((unsigned) (&insn[1] - sparc_opcodes)) < NUMOPCODES
1075 && !strcmp(insn->name, insn[1].name)) {
1080 as_bad("Illegal operands%s", error_message);
1084 if (insn->architecture > current_architecture) {
1085 if (!architecture_requested || warn_on_bump) {
1088 as_warn("architecture bumped from \"%s\" to \"%s\" on \"%s\"",
1089 architecture_pname[current_architecture],
1090 architecture_pname[insn->architecture],
1094 current_architecture = insn->architecture;
1096 as_bad("architecture mismatch on \"%s\" (\"%s\"). current architecture is \"%s\"",
1098 architecture_pname[insn->architecture],
1099 architecture_pname[current_architecture]);
1101 } /* if bump ok else error */
1102 } /* if architecture higher */
1106 } /* forever looking for a match */
1108 the_insn.opcode = opcode;
1111 print_insn(&the_insn);
1116 static int getExpression(str)
1122 save_in = input_line_pointer;
1123 input_line_pointer = str;
1124 switch (seg = expression(&the_insn.exp)) {
1131 case SEG_DIFFERENCE:
1137 the_insn.error = "bad segment";
1138 expr_end = input_line_pointer;
1139 input_line_pointer=save_in;
1143 expr_end = input_line_pointer;
1144 input_line_pointer = save_in;
1146 } /* getExpression() */
1150 This is identical to the md_atof in m68k.c. I think this is right,
1153 Turn a string in input_line_pointer into a floating point constant of type
1154 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1155 emitted is stored in *sizeP. An error message is returned, or NULL on OK.
1158 /* Equal to MAX_PRECISION in atof-ieee.c */
1159 #define MAX_LITTLENUMS 6
1161 char *md_atof(type,litP,sizeP)
1167 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1168 LITTLENUM_TYPE *wordP;
1200 return "Bad call to MD_ATOF()";
1202 t=atof_ieee(input_line_pointer,type,words);
1204 input_line_pointer=t;
1205 *sizeP=prec * sizeof(LITTLENUM_TYPE);
1206 for (wordP=words;prec--;) {
1207 md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
1208 litP+=sizeof(LITTLENUM_TYPE);
1210 return ""; /* Someone should teach Dean about null pointers */
1214 * Write out big-endian.
1216 void md_number_to_chars(buf,val,n)
1234 as_fatal("md_number_to_chars: failed sanity check.");
1237 } /* md_number_to_chars() */
1239 static int reloc_check(val, bits, fixP)
1242 fixS *fixP /* For reporting errors */;
1244 if (((val & (-1 << bits)) != 0)
1245 && ((val & (-1 << bits)) != (-1 << (bits - 0)))) {
1247 long addr = fixP->fx_where + fixP->fx_frag->fr_address;
1251 if (fixP->fx_frag->line) {
1252 fname = fixP->fx_frag->line->file->filename;
1253 ln = fixP->fx_frag->line->line;
1259 as_warn_where(fname, ln,
1260 "Relocation (%s) overflow at %#x, value truncated.",
1261 Reloc[fixP->fx_r_type], addr);
1264 } /* reloc_check() */
1267 /* Apply a fixS to the frags, now that we know the value it ought to
1270 void md_apply_fix(fixP, val)
1274 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
1275 long addr = fixP->fx_where + fixP->fx_frag->fr_address;
1279 fprintf(stderr, "md_apply_fix: \"%s\" \"%s\", val %d -- %s\n",
1280 ((fixP->fx_addsy != NULL)
1281 ? ((S_GET_NAME(fixP->fx_addsy) != NULL)
1282 ? S_GET_NAME(fixP->fx_addsy)
1285 ((fixP->fx_subsy != NULL)
1286 ? ((S_GET_NAME(fixP->fx_subsy) != NULL)
1287 ? S_GET_NAME(fixP->fx_subsy)
1290 val, Reloc[fixP->fx_r_type]);
1293 assert(fixP->fx_size == 4);
1294 assert(fixP->fx_r_type < NO_RELOC);
1296 fixP->fx_addnumber = val; /* Remember value for emit_reloc */
1299 * This is a hack. There should be a better way to
1302 if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy) {
1303 val += fixP->fx_where + fixP->fx_frag->fr_address;
1306 switch (fixP->fx_r_type) {
1308 /* Michael Bloom <mb@ttidca.tti.com> says... [This] change was
1309 made to match the behavior of Sun's assembler. Some broken
1310 loaders depend on that. At least one such loader actually
1311 adds the section data to what it finds in the addend. (It
1312 should only be using the addend like Sun's loader seems to).
1313 This caused incorrect relocation: (addend + adjustment)
1314 became ( ( 2 * addend ) + adjustment ). [and there should
1315 be no cases that reach here anyway. */
1317 if (fixP->fx_addsy == NULL) {
1319 * Ok, the remarks above do not hold if the
1320 * expression has been reduced to a number.
1335 if (!fixP->fx_addsy) {
1336 val = (val >>= 2) + 1;
1337 reloc_check(val, 30, fixP);
1339 buf[0] |= (val >> 24) & 0x3f;
1340 buf[1]= (val >> 16);
1347 val = (val >>= 2) + 1;
1348 reloc_check(val, 30, fixP);
1350 buf[0] |= (val >> 24) & 0x3f;
1351 buf[1]= (val >> 16);
1357 val = (val >>= 2) + 1;
1358 reloc_check(val, 22, fixP);
1360 buf[1] |= (val >> 16) & 0x3f;
1366 * We should only use the RELOC_HI22 type as a result of the %hi
1367 * operator (which is implicit in the case of the `set' pseudo op),
1368 * This is NOT the same as using the `sethi' instruction, which merely
1369 * puts the 22 bit operand into the high 22 bits of the destination
1373 if (!fixP->fx_addsy) {
1374 reloc_check(val, 22, fixP);
1376 buf[1] |= (val >> 16) & 0x3f;
1384 if (!fixP->fx_addsy) {
1385 buf[1] |= (val >> 26) & 0x3f;
1389 if (picmode && fixP->fx_r_type == RELOC_HI22)
1390 as_warn("non-PIC access to %s",
1391 S_GET_NAME(fixP->fx_addsy));
1399 if (!fixP->fx_addsy) {
1400 reloc_check(val, 13, fixP);
1401 buf[2] |= (val >> 8) & 0x1f;
1410 if (!fixP->fx_addsy) {
1411 buf[2] |= (val >> 8) & 0x03;
1412 buf[3] = val & 0xff;
1414 if (picmode && fixP->fx_r_type == RELOC_LO10)
1415 as_warn("non-PIC access to %s",
1416 S_GET_NAME(fixP->fx_addsy));
1423 if (fixP->fx_addsy != GOT_symbol) {
1429 case RELOC_8: /* These don't seem to ever be needed. */
1434 case RELOC_SEGOFF16:
1435 case RELOC_SFA_BASE:
1436 case RELOC_SFA_OFF13:
1438 case RELOC_GLOB_DAT: /* These are output by linker only */
1439 case RELOC_JMP_SLOT:
1440 case RELOC_RELATIVE:
1445 as_bad("bad relocation type: 0x%02x", fixP->fx_r_type);
1448 } /* md_apply_fix() */
1450 /* should never be called for sparc */
1451 void md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)
1458 as_fatal("sparc_create_short_jmp\n");
1459 } /* md_create_short_jump() */
1461 /* Translate internal representation of relocation info to target format.
1463 On sparc: first 4 bytes are normal unsigned long address, next three
1464 bytes are index, most sig. byte first. Byte 7 is broken up with
1465 bit 7 as external, bits 6 & 5 unused, and the lower
1466 five bits as relocation type. Next 4 bytes are long addend. */
1467 /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
1468 void tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
1471 relax_addressT segment_address_in_file;
1481 know(fixP->fx_addsy);
1483 if (!S_IS_DEFINED(fixP->fx_addsy)) {
1485 r_index = fixP->fx_addsy->sy_number;
1488 r_index = S_GET_TYPE(fixP->fx_addsy);
1491 switch (fixP->fx_r_type) {
1495 r_index = fixP->fx_addsy->sy_number;
1496 if (S_IS_EXTERNAL(fixP->fx_addsy))
1502 if (!S_IS_EXTERNAL(fixP->fx_addsy))
1505 r_index = fixP->fx_addsy->sy_number;
1516 md_number_to_chars(where,
1517 r_address = fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
1520 /* now the fun stuff */
1521 where[4] = (r_index >> 16) & 0x0ff;
1522 where[5] = (r_index >> 8) & 0x0ff;
1523 where[6] = r_index & 0x0ff;
1524 where[7] = ((r_extern << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F);
1527 if (fixP->fx_addsy->sy_frag) {
1528 r_addend = fixP->fx_addsy->sy_frag->fr_address;
1531 if (fixP->fx_pcrel) {
1533 if (fixP->fx_gotsy) {
1534 r_addend = r_address;
1535 r_addend += fixP->fx_addnumber;
1538 r_addend -= r_address;
1545 r_addend = fixP->fx_addnumber;
1548 md_number_to_chars(&where[8], r_addend, 4);
1551 } /* tc_aout_fix_to_chars() */
1553 /* should never be called for sparc */
1554 void md_convert_frag(headers, fragP)
1555 object_headers *headers;
1556 register fragS *fragP;
1558 as_fatal("sparc_convert_frag\n");
1559 } /* md_convert_frag() */
1561 /* should never be called for sparc */
1562 void md_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol)
1564 long from_addr, to_addr;
1568 as_fatal("sparc_create_long_jump\n");
1569 } /* md_create_long_jump() */
1571 /* should never be called for sparc */
1572 int md_estimate_size_before_relax(fragP, segtype)
1576 as_fatal("sparc_estimate_size_before_relax\n");
1578 } /* md_estimate_size_before_relax() */
1581 /* for debugging only */
1582 static void print_insn(insn)
1583 struct sparc_it *insn;
1587 fprintf(stderr, "ERROR: %s\n", insn->error);
1589 fprintf(stderr, "opcode=0x%08x\n", insn->opcode);
1590 fprintf(stderr, "reloc = %s\n", Reloc[insn->reloc]);
1591 fprintf(stderr, "exp = {\n");
1592 fprintf(stderr, "\t\tX_add_symbol = %s\n",
1593 ((insn->exp.X_add_symbol != NULL)
1594 ? ((S_GET_NAME(insn->exp.X_add_symbol) != NULL)
1595 ? S_GET_NAME(insn->exp.X_add_symbol)
1598 fprintf(stderr, "\t\tX_sub_symbol = %s\n",
1599 ((insn->exp.X_subtract_symbol != NULL)
1600 ? (S_GET_NAME(insn->exp.X_subtract_symbol)
1601 ? S_GET_NAME(insn->exp.X_subtract_symbol)
1604 fprintf(stderr, "\t\tX_got_symbol = %s\n",
1605 ((insn->exp.X_got_symbol != NULL)
1606 ? (S_GET_NAME(insn->exp.X_got_symbol)
1607 ? S_GET_NAME(insn->exp.X_got_symbol)
1610 fprintf(stderr, "\t\tX_add_number = %d\n",
1611 insn->exp.X_add_number);
1612 fprintf(stderr, "}\n");
1614 } /* print_insn() */
1617 /* Set the hook... */
1619 /* void emit_sparc_reloc();
1620 void (*md_emit_relocations)() = emit_sparc_reloc; */
1625 * Sparc/AM29K relocations are completely different, so it needs
1626 * this machine dependent routine to emit them.
1628 #if defined(OBJ_AOUT) || defined(OBJ_BOUT)
1629 void emit_sparc_reloc(fixP, segment_address_in_file)
1630 register fixS *fixP;
1631 relax_addressT segment_address_in_file;
1633 struct reloc_info_generic ri;
1634 register symbolS *symbolP;
1635 extern char *next_object_file_charP;
1636 /* long add_number; */
1638 memset((char *) &ri, '\0', sizeof(ri));
1639 for (; fixP; fixP = fixP->fx_next) {
1641 if (fixP->fx_r_type >= NO_RELOC) {
1642 as_fatal("fixP->fx_r_type = %d\n", fixP->fx_r_type);
1645 if ((symbolP = fixP->fx_addsy) != NULL) {
1646 ri.r_address = fixP->fx_frag->fr_address +
1647 fixP->fx_where - segment_address_in_file;
1648 if ((S_GET_TYPE(symbolP)) == N_UNDF) {
1650 ri.r_index = symbolP->sy_number;
1653 ri.r_index = S_GET_TYPE(symbolP);
1655 if (symbolP && symbolP->sy_frag) {
1656 ri.r_addend = symbolP->sy_frag->fr_address;
1658 ri.r_type = fixP->fx_r_type;
1659 if (fixP->fx_pcrel) {
1660 /* ri.r_addend -= fixP->fx_where; */
1661 ri.r_addend -= ri.r_address;
1663 ri.r_addend = fixP->fx_addnumber;
1666 md_ri_to_chars(next_object_file_charP, &ri);
1667 next_object_file_charP += md_reloc_size;
1671 } /* emit_sparc_reloc() */
1672 #endif /* aout or bout */
1673 #endif /* comment */
1677 * Invocation line includes a switch not recognized by the base assembler.
1678 * See if it's a processor-specific option. These are:
1681 * Warn on architecture bumps. See also -A.
1684 * Select the architecture. Instructions or features not
1685 * supported by the selected architecture cause fatal errors.
1687 * The default is to start at v6, and bump the architecture up
1688 * whenever an instruction is seen at a higher level.
1690 * If -bump is specified, a warning is printing when bumping to
1693 * If an architecture is specified, all instructions must match
1694 * that architecture. Any higher level instructions are flagged
1697 * if both an architecture and -bump are specified, the
1698 * architecture starts at the specified level, but bumps are
1702 int md_parse_option(argP, cntP, vecP)
1710 if (!strcmp(*argP,"bump")){
1713 } else if (**argP == 'A'){
1716 for (arch = architecture_pname; *arch != NULL; ++arch){
1717 if (strcmp(p, *arch) == 0){
1719 } /* found a match */
1720 } /* walk the pname table */
1723 as_bad("unknown architecture: %s", p);
1725 current_architecture = (enum sparc_architecture) (arch - architecture_pname);
1726 architecture_requested = 1;
1729 } else if (**argP == 'k' || **argP == 'K') {
1730 /* Predefine GOT symbol */
1731 GOT_symbol = symbol_find_or_make("__GLOBAL_OFFSET_TABLE_");
1734 /* Unknown option */
1738 **argP = '\0'; /* Done parsing this switch */
1740 } /* md_parse_option() */
1742 /* We have no need to default values of symbols. */
1745 symbolS *md_undefined_symbol(name)
1749 } /* md_undefined_symbol() */
1751 /* Parse an operand that is machine-specific.
1752 We just return without modifying the expression if we have nothing
1756 void md_operand(expressionP)
1757 expressionS *expressionP;
1759 } /* md_operand() */
1761 /* Round up a section size to the appropriate boundary. */
1762 long md_section_align(segment, size)
1766 return((size + 7) & ~7); /* Round all sects to multiple of 8 */
1767 } /* md_section_align() */
1769 /* Exactly what point is a PC-relative offset relative TO?
1770 On the sparc, they're relative to the address of the offset, plus
1771 its size. This gets us to the following instruction.
1772 (??? Is this right? FIXME-SOON) */
1773 long md_pcrel_from(fixP)
1778 * _GLOBAL_OFFSET_TABLE_ refs are relative to the offset of the
1779 * current instruction. We omit fx_size from the computation (which
1780 * is always 4 anyway).
1783 return fixP->fx_where + fixP->fx_frag->fr_address;
1786 return(fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address);
1787 } /* md_pcrel_from() */
1789 void tc_aout_pre_write_hook(headers)
1790 object_headers *headers;
1792 H_SET_VERSION(headers, 1);
1794 } /* tc_aout_pre_write_hook() */
1803 /* end of tc-sparc.c */