1 /* tc-sparc.c -- Assemble for the SPARC
2 Copyright (C) 1989, 1990, 1991 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. */
25 /* careful, this file includes data *declarations* */
26 #include "opcode/sparc.h"
30 void md_number_to_chars();
33 void md_convert_frag();
34 void md_create_short_jump();
35 void md_create_long_jump();
36 int md_estimate_size_before_relax();
37 void md_ri_to_chars();
38 symbolS
*md_undefined_symbol();
39 static void sparc_ip();
41 static enum sparc_architecture current_architecture
= v6
;
42 static int architecture_requested
= 0;
43 static int warn_on_bump
= 0;
45 const relax_typeS md_relax_table
[] = {
48 /* handle of the OPCODE hash table */
49 static struct hash_control
*op_hash
= NULL
;
51 static void s_seg(), s_proc(), s_data1(), s_reserve(), s_common();
52 extern void s_globl(), s_long(), s_short(), s_space(), cons();
53 extern void s_align_bytes(), s_ignore();
55 const pseudo_typeS md_pseudo_table
[] = {
56 { "align", s_align_bytes
, 0 }, /* Defaulting is invalid (0) */
57 { "common", s_common
, 0 },
58 { "global", s_globl
, 0 },
60 { "optim", s_ignore
, 0 },
61 { "proc", s_proc
, 0 },
62 { "reserve", s_reserve
, 0 },
64 { "skip", s_space
, 0 },
69 const int md_short_jump_size
= 4;
70 const int md_long_jump_size
= 4;
71 const int md_reloc_size
= 12; /* Size of relocation record */
73 /* This array holds the chars that always start a comment. If the
74 pre-processor is disabled, these aren't very useful */
75 const char comment_chars
[] = "!"; /* JF removed '|' from comment_chars */
77 /* This array holds the chars that only start a comment at the beginning of
78 a line. If the line seems to have the form '# 123 filename'
79 .line and .file directives will appear in the pre-processed output */
80 /* Note that input_file.c hand checks for '#' at the beginning of the
81 first line of the input file. This is because the compiler outputs
82 #NO_APP at the beginning of its output. */
83 /* Also note that comments started like this one will always
84 work if '/' isn't otherwise defined. */
85 const char line_comment_chars
[] = "#";
87 /* Chars that can be used to separate mant from exp in floating point nums */
88 const char EXP_CHARS
[] = "eE";
90 /* Chars that mean this number is a floating point constant */
93 const char FLT_CHARS
[] = "rRsSfFdDxXpP";
95 /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
96 changed in read.c . Ideally it shouldn't have to know about it at all,
97 but nothing is ideal around here.
100 static unsigned char octal
[256];
101 #define isoctal(c) octal[c]
102 static unsigned char toHex
[256];
106 unsigned long opcode
;
107 struct nlist
*nlistp
;
110 enum reloc_type reloc
;
111 } the_insn
, set_insn
;
115 static void print_insn(struct sparc_it
*insn
);
117 static int getExpression(char *str
);
120 static void print_insn();
122 static int getExpression();
124 static char *expr_end
;
125 static int special_case
;
128 * Instructions that require wierd handling because they're longer than
131 #define SPECIAL_CASE_SET 1
132 #define SPECIAL_CASE_FDIV 2
135 * sort of like s_lcomm
138 static int max_alignment
= 15;
140 static void s_reserve() {
149 name
= input_line_pointer
;
150 c
= get_symbol_end();
151 p
= input_line_pointer
;
155 if (*input_line_pointer
!= ',') {
156 as_bad("Expected comma after name");
157 ignore_rest_of_line();
161 ++input_line_pointer
;
163 if ((size
= get_absolute_expression()) < 0) {
164 as_bad("BSS length (%d.) <0! Ignored.", size
);
165 ignore_rest_of_line();
170 symbolP
= symbol_find_or_make(name
);
173 if (strncmp(input_line_pointer
, ",\"bss\"", 6) != 0) {
174 as_bad("bad .reserve segment: `%s'", input_line_pointer
);
178 input_line_pointer
+= 6;
181 if (*input_line_pointer
== ',') {
182 ++input_line_pointer
;
185 if (*input_line_pointer
== '\n') {
186 as_bad("Missing alignment");
190 align
= get_absolute_expression();
191 if (align
> max_alignment
){
192 align
= max_alignment
;
193 as_warn("Alignment too large: %d. assumed.", align
);
194 } else if (align
< 0) {
196 as_warn("Alignment negative. 0 assumed.");
199 #define SEG_BSS SEG_E2
200 record_alignment(SEG_E2
, align
);
202 record_alignment(SEG_BSS
, align
);
205 /* convert to a power of 2 alignment */
206 for (temp
= 0; (align
& 1) == 0; align
>>= 1, ++temp
) ;;
209 as_bad("Alignment not a power of 2");
210 ignore_rest_of_line();
212 } /* not a power of two */
217 align
= ~((~0) << align
); /* Convert to a mask */
218 local_bss_counter
= (local_bss_counter
+ align
) & (~align
);
219 } /* if has optional alignment */
221 if (S_GET_OTHER(symbolP
) == 0
222 && S_GET_DESC(symbolP
) == 0
223 && ((S_GET_SEGMENT(symbolP
) == SEG_BSS
224 && S_GET_VALUE(symbolP
) == local_bss_counter
)
225 || !S_IS_DEFINED(symbolP
))) {
226 S_SET_VALUE(symbolP
, local_bss_counter
);
227 S_SET_SEGMENT(symbolP
, SEG_BSS
);
228 symbolP
->sy_frag
= &bss_address_frag
;
229 local_bss_counter
+= size
;
231 as_warn("Ignoring attempt to re-define symbol from %d. to %d.",
232 S_GET_VALUE(symbolP
), local_bss_counter
);
233 } /* if not redefining */
235 demand_empty_rest_of_line();
239 static void s_common() {
244 register symbolS
* symbolP
;
246 name
= input_line_pointer
;
247 c
= get_symbol_end();
248 /* just after name is now '\0' */
249 p
= input_line_pointer
;
252 if (* input_line_pointer
!= ',') {
253 as_bad("Expected comma after symbol-name");
254 ignore_rest_of_line();
257 input_line_pointer
++; /* skip ',' */
258 if ((temp
= get_absolute_expression ()) < 0) {
259 as_bad(".COMMon length (%d.) <0! Ignored.", temp
);
260 ignore_rest_of_line();
264 symbolP
= symbol_find_or_make(name
);
266 if (S_IS_DEFINED(symbolP
)) {
267 as_bad("Ignoring attempt to re-define symbol");
268 ignore_rest_of_line();
271 if (S_GET_VALUE(symbolP
) != 0) {
272 if (S_GET_VALUE(symbolP
) != temp
) {
273 as_warn("Length of .comm \"%s\" is already %d. Not changed to %d.",
274 S_GET_NAME(symbolP
), S_GET_VALUE(symbolP
), temp
);
277 S_SET_VALUE(symbolP
, temp
);
278 S_SET_EXTERNAL(symbolP
);
280 know(symbolP
->sy_frag
== &zero_address_frag
);
281 if (strncmp(input_line_pointer
, ",\"bss\"", 6) != 0
282 && strncmp(input_line_pointer
, ",\"data\"", 7) != 0) {
283 p
=input_line_pointer
;
284 while(*p
&& *p
!='\n')
288 as_bad("bad .common segment: `%s'", input_line_pointer
);
292 input_line_pointer
+= 6 + (input_line_pointer
[2] == 'd'); /* Skip either */
293 demand_empty_rest_of_line();
297 static void s_seg() {
299 if (strncmp(input_line_pointer
, "\"text\"", 6) == 0) {
300 input_line_pointer
+= 6;
304 if (strncmp(input_line_pointer
, "\"data\"", 6) == 0) {
305 input_line_pointer
+= 6;
309 if (strncmp(input_line_pointer
, "\"data1\"", 7) == 0) {
310 input_line_pointer
+= 7;
314 if (strncmp(input_line_pointer
, "\"bss\"", 5) == 0) {
315 input_line_pointer
+= 5;
316 /* We only support 2 segments -- text and data -- for now, so
317 things in the "bss segment" will have to go into data for now.
318 You can still allocate SEG_BSS stuff with .lcomm or .reserve. */
319 subseg_new(SEG_DATA
, 255); /* FIXME-SOMEDAY */
322 as_bad("Unknown segment type");
323 demand_empty_rest_of_line();
327 static void s_data1() {
328 subseg_new(SEG_DATA
, 1);
329 demand_empty_rest_of_line();
333 static void s_proc() {
334 extern char is_end_of_line
[];
336 while (!is_end_of_line
[*input_line_pointer
]) {
337 ++input_line_pointer
;
339 ++input_line_pointer
;
343 /* This function is called once, at assembler startup time. It should
344 set up all the tables, etc. that the MD part of the assembler will need. */
346 register char *retval
= NULL
;
348 register unsigned int i
= 0;
350 op_hash
= hash_new();
352 as_fatal("Virtual memory exhausted");
354 while (i
< NUMOPCODES
) {
355 const char *name
= sparc_opcodes
[i
].name
;
356 retval
= hash_insert(op_hash
, name
, &sparc_opcodes
[i
]);
357 if(retval
!= NULL
&& *retval
!= '\0') {
358 fprintf (stderr
, "internal error: can't hash `%s': %s\n",
359 sparc_opcodes
[i
].name
, retval
);
364 if (sparc_opcodes
[i
].match
& sparc_opcodes
[i
].lose
) {
365 fprintf (stderr
, "internal error: losing opcode: `%s' \"%s\"\n",
366 sparc_opcodes
[i
].name
, sparc_opcodes
[i
].args
);
370 } while (i
< NUMOPCODES
371 && !strcmp(sparc_opcodes
[i
].name
, name
));
375 as_fatal("Broken assembler. No assembly attempted.");
377 for (i
= '0'; i
< '8'; ++i
)
379 for (i
= '0'; i
<= '9'; ++i
)
381 for (i
= 'a'; i
<= 'f'; ++i
)
382 toHex
[i
] = i
+ 10 - 'a';
383 for (i
= 'A'; i
<= 'F'; ++i
)
384 toHex
[i
] = i
+ 10 - 'A';
391 void md_assemble(str
)
400 /* See if "set" operand is absolute and small; skip sethi if so. */
401 if (special_case
== SPECIAL_CASE_SET
&& the_insn
.exp
.X_seg
== SEG_ABSOLUTE
) {
402 if (the_insn
.exp
.X_add_number
>= -(1<<12)
403 && the_insn
.exp
.X_add_number
< (1<<12)) {
404 the_insn
.opcode
= 0x80102000 /* or %g0,imm,... */
405 | (the_insn
.opcode
& 0x3E000000) /* dest reg */
406 | (the_insn
.exp
.X_add_number
& 0x1FFF); /* imm */
407 special_case
= 0; /* No longer special */
408 the_insn
.reloc
= NO_RELOC
; /* No longer relocated */
413 /* put out the opcode */
414 md_number_to_chars(toP
, the_insn
.opcode
, 4);
416 /* put out the symbol-dependent stuff */
417 if (the_insn
.reloc
!= NO_RELOC
) {
418 fix_new(frag_now
, /* which frag */
419 (toP
- frag_now
->fr_literal
), /* where */
421 the_insn
.exp
.X_add_symbol
,
422 the_insn
.exp
.X_subtract_symbol
,
423 the_insn
.exp
.X_add_number
,
427 switch (special_case
) {
429 case SPECIAL_CASE_SET
:
431 assert(the_insn
.reloc
== RELOC_HI22
);
432 /* See if "set" operand has no low-order bits; skip OR if so. */
433 if (the_insn
.exp
.X_seg
== SEG_ABSOLUTE
434 && ((the_insn
.exp
.X_add_number
& 0x3FF) == 0))
437 rsd
= (the_insn
.opcode
>> 25) & 0x1f;
438 the_insn
.opcode
= 0x80102000 | (rsd
<< 25) | (rsd
<< 14);
439 md_number_to_chars(toP
, the_insn
.opcode
, 4);
440 fix_new(frag_now
, /* which frag */
441 (toP
- frag_now
->fr_literal
), /* where */
443 the_insn
.exp
.X_add_symbol
,
444 the_insn
.exp
.X_subtract_symbol
,
445 the_insn
.exp
.X_add_number
,
450 case SPECIAL_CASE_FDIV
:
451 /* According to information leaked from Sun, the "fdiv" instructions
452 on early SPARC machines would produce incorrect results sometimes.
453 The workaround is to add an fmovs of the destination register to
454 itself just after the instruction. This was true on machines
455 with Weitek 1165 float chips, such as the Sun-4/260 and /280. */
457 assert(the_insn
.reloc
== NO_RELOC
);
459 rsd
= (the_insn
.opcode
>> 25) & 0x1f;
460 the_insn
.opcode
= 0x81A00020 | (rsd
<< 25) | rsd
; /* fmovs dest,dest */
461 md_number_to_chars(toP
, the_insn
.opcode
, 4);
468 as_fatal("failed sanity check.");
470 } /* md_assemble() */
472 static void sparc_ip(str
)
475 char *error_message
= "";
479 struct sparc_opcode
*insn
;
481 unsigned long opcode
;
482 unsigned int mask
= 0;
486 for (s
= str
; islower(*s
) || (*s
>= '0' && *s
<= '3'); ++s
)
503 as_bad("Unknown opcode: `%s'", str
);
506 if ((insn
= (struct sparc_opcode
*) hash_find(op_hash
, str
)) == NULL
) {
507 as_bad("Unknown opcode: `%s'", str
);
515 opcode
= insn
->match
;
516 bzero(&the_insn
, sizeof(the_insn
));
517 the_insn
.reloc
= NO_RELOC
;
520 * Build the opcode, checking as we go to make
521 * sure that the operands match
523 for (args
= insn
->args
; ; ++args
) {
528 if (strncmp(s
, "%asr", 4) == 0) {
534 while (isdigit(*s
)) {
535 num
= num
*10 + *s
-'0';
539 if (num
< 16 || 31 < num
) {
540 error_message
= ": asr number must be between 15 and 31";
544 opcode
|= (*args
== 'M' ? RS1(num
) : RD(num
));
547 error_message
= ": expecting %asrN";
549 } /* if %asr followed by a number. */
554 /* start-sanitize-v9 */
557 the_insn
.reloc
= RELOC_11
;
561 the_insn
.reloc
= RELOC_WDISP2_14
;
566 the_insn
.reloc
= RELOC_WDISP19
;
571 if (*s
== 'p' && s
[1] == 'n') {
578 if (*s
== 'p' && s
[1] == 't') {
585 if (strncmp(s
, "%amr", 4) == 0) {
595 if (strncmp(s
, "icc", 3) == 0) {
605 if (strncmp(s
, "xcc", 3) == 0) {
615 if (strncmp(s
, "fcc0", 4) == 0) {
625 if (strncmp(s
, "fcc1", 4) == 0) {
635 if (strncmp(s
, "fcc2", 4) == 0) {
645 if (strncmp(s
, "fcc3", 4) == 0) {
652 if (strncmp(s
, "%pc", 3) == 0) {
659 if (strncmp(s
, "%modes", 6) == 0) {
666 if (strncmp(s
, "%tick", 5) == 0) {
672 /* end-sanitize-v9 */
674 case '\0': /* end of args */
690 case '[': /* these must match exactly */
698 case '#': /* must be at least one digit */
700 while (isdigit(*s
)) {
707 case 'C': /* coprocessor state register */
708 if (strncmp(s
, "%csr", 4) == 0) {
714 case 'b': /* next operand is a coprocessor register */
717 if (*s
++ == '%' && *s
++ == 'c' && isdigit(*s
)) {
720 mask
= 10 * (mask
- '0') + (*s
++ - '0');
730 opcode
|= mask
<< 14;
738 opcode
|= mask
<< 25;
744 case 'r': /* next operand must be a register */
751 case 'f': /* frame pointer */
758 case 'g': /* global register */
759 if (isoctal(c
= *s
++)) {
765 case 'i': /* in register */
766 if (isoctal(c
= *s
++)) {
772 case 'l': /* local register */
773 if (isoctal(c
= *s
++)) {
774 mask
= (c
- '0' + 16) ;
779 case 'o': /* out register */
780 if (isoctal(c
= *s
++)) {
781 mask
= (c
- '0' + 8) ;
786 case 's': /* stack pointer */
793 case 'r': /* any register */
794 if (!isdigit(c
= *s
++)) {
798 case '0': case '1': case '2': case '3': case '4':
799 case '5': case '6': case '7': case '8': case '9':
801 if ((c
= 10 * (c
- '0') + (*s
++ - '0')) >= 32) {
814 * Got the register, now figure out where
815 * it goes in the opcode.
820 opcode
|= mask
<< 14;
828 opcode
|= mask
<< 25;
832 opcode
|= (mask
<< 25) | (mask
<< 14);
838 /* start-sanitize-v9 */
844 /* end-sanitize-v9 */
845 case 'e': /* next operand is a floating point register */
860 /* start-sanitize-v9 */
862 && ((format
= *s
) == 'f'
866 /* end-sanitize-v9 */
867 && ((format
= *s
) == 'f')
869 /* start-sanitize-v9 */
871 /* end-sanitize-v9 */
876 for (mask
= 0; isdigit(*s
); ++s
) {
877 mask
= 10 * mask
+ (*s
- '0');
878 } /* read the number */
886 } /* register must be even numbered */
894 } /* register must be multiple of 4 */
898 error_message
= ": There are only 32 f registers; [0-31]";
901 /* start-sanitize-v9 */
906 error_message
= ": There are only 32 d registers [0, 2, ... 62].";
908 } else if (mask
& 1) {
909 error_message
= ": Only even numbered d registers exist.";
913 } else if (format
== 'q') {
916 ": There are only 16 q registers [0, 4, ... 60].";
918 } else if (mask
& 3) {
920 ": Only q registers evenly divisible by four exist.";
925 } /* depending on format */
929 } /* wrap high bit */
931 /* end-sanitize-v9 */
932 } /* if not an 'f' register. */
936 /* start-sanitize-v9 */
941 opcode
|= (mask
& 0x1f) << 9;
944 /* end-sanitize-v9 */
971 if (strncmp(s
, "%fsr", 4) == 0) {
977 case 'h': /* high 22 bits */
978 the_insn
.reloc
= RELOC_HI22
;
981 case 'l': /* 22 bit PC relative immediate */
982 the_insn
.reloc
= RELOC_WDISP22
;
986 case 'L': /* 30 bit immediate */
987 the_insn
.reloc
= RELOC_WDISP30
;
991 case 'n': /* 22 bit immediate */
992 the_insn
.reloc
= RELOC_22
;
995 case 'i': /* 13 bit immediate */
996 the_insn
.reloc
= RELOC_BASE13
;
1004 if ((c
= s
[1]) == 'h' && s
[2] == 'i') {
1005 the_insn
.reloc
= RELOC_HI22
;
1007 } else if (c
== 'l' && s
[2] == 'o') {
1008 the_insn
.reloc
= RELOC_LO10
;
1010 /* start-sanitize-v9 */
1015 the_insn
.reloc
= RELOC_HHI22
;
1021 the_insn
.reloc
= RELOC_HLO10
;
1024 /* end-sanitize-v9 */
1028 /* Note that if the getExpression() fails, we
1029 will still have created U entries in the
1030 symbol table for the 'symbols' in the input
1031 string. Try not to create U symbols for
1034 /* This stuff checks to see if the
1035 expression ends in +%reg If it does,
1036 it removes the register from the
1037 expression, and re-sets 's' to point
1038 to the right place */
1042 for (s1
= s
; *s1
&& *s1
!= ',' && *s1
!= ']'; s1
++) ;;
1044 if (s1
!= s
&& isdigit(s1
[-1])) {
1045 if(s1
[-2] == '%' && s1
[-3] == '+') {
1048 (void) getExpression(s
);
1052 } else if (strchr("goli0123456789", s1
[-2]) && s1
[-3] == '%' && s1
[-4] == '+') {
1055 (void) getExpression(s
);
1062 (void)getExpression(s
);
1074 char *push
= input_line_pointer
;
1077 input_line_pointer
= s
;
1079 if (expression(&e
) == SEG_ABSOLUTE
) {
1080 opcode
|= e
.X_add_number
<< 5;
1081 s
= input_line_pointer
;
1082 input_line_pointer
= push
;
1087 } /* alternate space */
1090 if (strncmp(s
, "%psr", 4) == 0) {
1096 case 'q': /* floating point queue */
1097 if (strncmp(s
, "%fq", 3) == 0) {
1103 case 'Q': /* coprocessor queue */
1104 if (strncmp(s
, "%cq", 3) == 0) {
1111 if (strcmp(str
, "set") == 0) {
1112 special_case
= SPECIAL_CASE_SET
;
1114 } else if (strncmp(str
, "fdiv", 4) == 0) {
1115 special_case
= SPECIAL_CASE_FDIV
;
1121 if (strncmp(s
, "%tbr", 4) != 0)
1127 if (strncmp(s
, "%wim", 4) != 0)
1133 if (strncmp(s
, "%y", 2) != 0)
1139 as_fatal("failed sanity check.");
1140 } /* switch on arg code */
1142 } /* for each arg that we expect */
1145 /* Args don't match. */
1146 if (((unsigned) (&insn
[1] - sparc_opcodes
)) < NUMOPCODES
1147 && !strcmp(insn
->name
, insn
[1].name
)) {
1152 as_bad("Illegal operands%s", error_message
);
1156 if (insn
->architecture
> current_architecture
) {
1157 if (current_architecture
!= cypress
1158 && (!architecture_requested
|| warn_on_bump
)) {
1161 as_warn("architecture bumped from \"%s\" to \"%s\" on \"%s\"",
1162 architecture_pname
[current_architecture
],
1163 architecture_pname
[insn
->architecture
],
1167 current_architecture
= insn
->architecture
;
1169 as_bad("architecture mismatch on \"%s\" (\"%s\"). current architecture is \"%s\"",
1171 architecture_pname
[insn
->architecture
],
1172 architecture_pname
[current_architecture
]);
1174 } /* if bump ok else error */
1175 } /* if architecture higher */
1179 } /* forever looking for a match */
1181 the_insn
.opcode
= opcode
;
1185 static int getExpression(str
)
1191 save_in
= input_line_pointer
;
1192 input_line_pointer
= str
;
1193 switch (seg
= expression(&the_insn
.exp
)) {
1200 case SEG_DIFFERENCE
:
1206 the_insn
.error
= "bad segment";
1207 expr_end
= input_line_pointer
;
1208 input_line_pointer
=save_in
;
1211 expr_end
= input_line_pointer
;
1212 input_line_pointer
= save_in
;
1214 } /* getExpression() */
1218 This is identical to the md_atof in m68k.c. I think this is right,
1221 Turn a string in input_line_pointer into a floating point constant of type
1222 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1223 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
1226 /* Equal to MAX_PRECISION in atof-ieee.c */
1227 #define MAX_LITTLENUMS 6
1229 char *md_atof(type
,litP
,sizeP
)
1235 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
1236 LITTLENUM_TYPE
*wordP
;
1268 return "Bad call to MD_ATOF()";
1270 t
=atof_ieee(input_line_pointer
,type
,words
);
1272 input_line_pointer
=t
;
1273 *sizeP
=prec
* sizeof(LITTLENUM_TYPE
);
1274 for(wordP
=words
;prec
--;) {
1275 md_number_to_chars(litP
,(long)(*wordP
++),sizeof(LITTLENUM_TYPE
));
1276 litP
+=sizeof(LITTLENUM_TYPE
);
1278 return ""; /* Someone should teach Dean about null pointers */
1282 * Write out big-endian.
1284 void md_number_to_chars(buf
,val
,n
)
1302 as_fatal("failed sanity check.");
1305 } /* md_number_to_chars() */
1307 /* Apply a fixS to the frags, now that we know the value it ought to
1310 void md_apply_fix(fixP
, val
)
1314 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
1316 assert(fixP
->fx_size
== 4);
1317 assert(fixP
->fx_r_type
< NO_RELOC
);
1319 fixP
->fx_addnumber
= val
; /* Remember value for emit_reloc */
1322 * This is a hack. There should be a better way to
1325 if (fixP
->fx_r_type
== RELOC_WDISP30
&& fixP
->fx_addsy
) {
1326 val
+= fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
1329 switch (fixP
->fx_r_type
) {
1332 buf
[0] = 0; /* val >> 24; */
1333 buf
[1] = 0; /* val >> 16; */
1334 buf
[2] = 0; /* val >> 8; */
1335 buf
[3] = 0; /* val; */
1339 case RELOC_8
: /* These don't seem to ever be needed. */
1346 val
= (val
>>= 2) + 1;
1347 buf
[0] |= (val
>> 24) & 0x3f;
1348 buf
[1]= (val
>> 16);
1353 /* start-sanitize-v9 */
1356 if (((val
> 0) && (val
& ~0x7ff))
1357 || ((val
< 0) && (~(val
- 1) & ~0x7ff))) {
1358 as_bad("relocation overflow.");
1361 buf
[2] = (val
>> 8) & 0x7;
1362 buf
[3] = val
& 0xff;
1365 case RELOC_WDISP2_14
:
1366 if (((val
> 0) && (val
& ~0x3fffc))
1367 || ((val
< 0) && (~(val
- 1) & ~0x3fffc))) {
1368 as_bad("relocation overflow.");
1371 val
= (val
>>= 2) + 1;
1372 buf
[1] |= ((val
>> 14) & 0x3) << 3;
1373 buf
[2] |= (val
>> 8) & 0x3f ;
1374 buf
[3] = val
& 0xff;
1378 if (((val
> 0) && (val
& ~0x1ffffc))
1379 || ((val
< 0) && (~(val
- 1) & ~0x1ffffc))) {
1380 as_bad("relocation overflow.");
1383 val
= (val
>>= 2) + 1;
1384 buf
[1] |= (val
>> 16) & 0x7;
1385 buf
[2] = (val
>> 8) & 0xff;
1386 buf
[3] = val
& 0xff;
1391 /* intentional fallthrough */
1393 /* end-sanitize-v9 */
1396 if(!fixP
->fx_addsy
) {
1397 buf
[1] |= (val
>> 26) & 0x3f;
1407 if (val
& ~0x003fffff) {
1408 as_bad("relocation overflow");
1410 buf
[1] |= (val
>> 16) & 0x3f;
1412 buf
[3] = val
& 0xff;
1416 if (val
& ~0x00001fff) {
1417 as_bad("relocation overflow");
1419 buf
[2] = (val
>> 8) & 0x1f;
1420 buf
[3] = val
& 0xff;
1423 /* start-sanitize-v9 */
1427 /* intentional fallthrough */
1429 /* end-sanitize-v9 */
1432 if(!fixP
->fx_addsy
) {
1433 buf
[2] |= (val
>> 8) & 0x03;
1439 case RELOC_SFA_BASE
:
1440 case RELOC_SFA_OFF13
:
1444 buf
[2] |= (val
>> 8) & 0x1f;
1449 val
= (val
>>= 2) + 1;
1452 buf
[1] |= (val
>> 16) & 0x3f;
1461 case RELOC_SEGOFF16
:
1462 case RELOC_GLOB_DAT
:
1463 case RELOC_JMP_SLOT
:
1464 case RELOC_RELATIVE
:
1469 as_bad("bad relocation type: 0x%02x", fixP
->fx_r_type
);
1472 } /* md_apply_fix() */
1474 /* should never be called for sparc */
1475 void md_create_short_jump(ptr
, from_addr
, to_addr
, frag
, to_symbol
)
1482 as_fatal("sparc_create_short_jmp\n");
1483 } /* md_create_short_jump() */
1485 /* Translate internal representation of relocation info to target format.
1487 On sparc: first 4 bytes are normal unsigned long address, next three
1488 bytes are index, most sig. byte first. Byte 7 is broken up with
1489 bit 7 as external, bits 6 & 5 unused, and the lower
1490 five bits as relocation type. Next 4 bytes are long addend. */
1491 /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
1492 void tc_aout_fix_to_chars(where
, fixP
, segment_address_in_file
)
1495 relax_addressT segment_address_in_file
;
1502 know(fixP
->fx_addsy
);
1504 if ((S_GET_TYPE(fixP
->fx_addsy
)) == N_UNDF
) {
1506 r_index
= fixP
->fx_addsy
->sy_number
;
1509 r_index
= S_GET_TYPE(fixP
->fx_addsy
);
1513 md_number_to_chars(where
,
1514 r_address
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
- segment_address_in_file
,
1517 /* now the fun stuff */
1518 where
[4] = (r_index
>> 16) & 0x0ff;
1519 where
[5] = (r_index
>> 8) & 0x0ff;
1520 where
[6] = r_index
& 0x0ff;
1521 where
[7] = ((r_extern
<< 7) & 0x80) | (0 & 0x60) | (fixP
->fx_r_type
& 0x1F);
1524 if (fixP
->fx_addsy
->sy_frag
) {
1525 r_addend
= fixP
->fx_addsy
->sy_frag
->fr_address
;
1528 if (fixP
->fx_pcrel
) {
1529 r_addend
-= r_address
;
1531 r_addend
= fixP
->fx_addnumber
;
1534 md_number_to_chars(&where
[8], r_addend
, 4);
1537 } /* tc_aout_fix_to_chars() */
1539 /* should never be called for sparc */
1540 void md_convert_frag(headers
, fragP
)
1541 object_headers
*headers
;
1542 register fragS
*fragP
;
1544 as_fatal("sparc_convert_frag\n");
1545 } /* md_convert_frag() */
1547 /* should never be called for sparc */
1548 void md_create_long_jump(ptr
, from_addr
, to_addr
, frag
, to_symbol
)
1550 long from_addr
, to_addr
;
1554 as_fatal("sparc_create_long_jump\n");
1555 } /* md_create_long_jump() */
1557 /* should never be called for sparc */
1558 int md_estimate_size_before_relax(fragP
, segtype
)
1562 as_fatal("sparc_estimate_size_before_relax\n");
1564 } /* md_estimate_size_before_relax() */
1567 /* for debugging only */
1568 static void print_insn(insn
)
1569 struct sparc_it
*insn
;
1600 fprintf(stderr
, "ERROR: %s\n");
1602 fprintf(stderr
, "opcode=0x%08x\n", insn
->opcode
);
1603 fprintf(stderr
, "reloc = %s\n", Reloc
[insn
->reloc
]);
1604 fprintf(stderr
, "exp = {
1606 fprintf(stderr
, "\t\tX_add_symbol = %s\n",
1607 ((insn
->exp
.X_add_symbol
!= NULL
)
1608 ? ((S_GET_NAME(insn
->exp
.X_add_symbol
) != NULL
)
1609 ? S_GET_NAME(insn
->exp
.X_add_symbol
)
1612 fprintf(stderr
, "\t\tX_sub_symbol = %s\n",
1613 ((insn
->exp
.X_subtract_symbol
!= NULL
)
1614 ? (S_GET_NAME(insn
->exp
.X_subtract_symbol
)
1615 ? S_GET_NAME(insn
->exp
.X_subtract_symbol
)
1618 fprintf(stderr
, "\t\tX_add_number = %d\n",
1619 insn
->exp
.X_add_number
);
1620 fprintf(stderr
, "}\n");
1622 } /* print_insn() */
1625 /* Set the hook... */
1627 /* void emit_sparc_reloc();
1628 void (*md_emit_relocations)() = emit_sparc_reloc; */
1633 * Sparc/AM29K relocations are completely different, so it needs
1634 * this machine dependent routine to emit them.
1636 #if defined(OBJ_AOUT) || defined(OBJ_BOUT)
1637 void emit_sparc_reloc(fixP
, segment_address_in_file
)
1638 register fixS
*fixP
;
1639 relax_addressT segment_address_in_file
;
1641 struct reloc_info_generic ri
;
1642 register symbolS
*symbolP
;
1643 extern char *next_object_file_charP
;
1644 /* long add_number; */
1646 bzero((char *) &ri
, sizeof(ri
));
1647 for (; fixP
; fixP
= fixP
->fx_next
) {
1649 if (fixP
->fx_r_type
>= NO_RELOC
) {
1650 as_fatal("fixP->fx_r_type = %d\n", fixP
->fx_r_type
);
1653 if ((symbolP
= fixP
->fx_addsy
) != NULL
) {
1654 ri
.r_address
= fixP
->fx_frag
->fr_address
+
1655 fixP
->fx_where
- segment_address_in_file
;
1656 if ((S_GET_TYPE(symbolP
)) == N_UNDF
) {
1658 ri
.r_index
= symbolP
->sy_number
;
1661 ri
.r_index
= S_GET_TYPE(symbolP
);
1663 if (symbolP
&& symbolP
->sy_frag
) {
1664 ri
.r_addend
= symbolP
->sy_frag
->fr_address
;
1666 ri
.r_type
= fixP
->fx_r_type
;
1667 if (fixP
->fx_pcrel
) {
1668 /* ri.r_addend -= fixP->fx_where; */
1669 ri
.r_addend
-= ri
.r_address
;
1671 ri
.r_addend
= fixP
->fx_addnumber
;
1674 md_ri_to_chars(next_object_file_charP
, &ri
);
1675 next_object_file_charP
+= md_reloc_size
;
1679 } /* emit_sparc_reloc() */
1680 #endif /* aout or bout */
1681 #endif /* comment */
1685 * Invocation line includes a switch not recognized by the base assembler.
1686 * See if it's a processor-specific option. These are:
1689 * Warn on architecture bumps. See also -A.
1691 * -Av6, -Av7, -Acypress, -Av8
1692 * Select the architecture. Instructions or features not
1693 * supported by the selected architecture cause fatal errors.
1695 * The default is to start at v6, and bump the architecture up
1696 * whenever an instruction is seen at a higher level.
1698 * If -bump is specified, a warning is printing when bumping to
1701 * If an architecture is specified, all instructions must match
1702 * that architecture. Any higher level instructions are flagged
1705 * if both an architecture and -bump are specified, the
1706 * architecture starts at the specified level, but bumps are
1709 * Note that where cypress specific instructions conflict with
1710 * other instructions, the other instruction is assumed. Nothing
1711 * is upward compatible with cypress. Thus, to get the cypress
1712 * instruction set you MUST -Acypress.
1715 /* start-sanitize-v9 */
1716 /* There is also a -Av9 architecture option. xoxorich. */
1717 /* end-sanitize-v9 */
1718 int md_parse_option(argP
, cntP
, vecP
)
1726 if (!strcmp(*argP
,"bump")){
1729 } else if (**argP
== 'A'){
1732 for (arch
= architecture_pname
; *arch
!= NULL
; ++arch
){
1733 if (strcmp(p
, *arch
) == 0){
1735 } /* found a match */
1736 } /* walk the pname table */
1739 as_bad("unknown architecture: %s", p
);
1741 current_architecture
= (enum sparc_architecture
) (arch
- architecture_pname
);
1742 architecture_requested
= 1;
1745 /* Unknown option */
1749 **argP
= '\0'; /* Done parsing this switch */
1751 } /* md_parse_option() */
1753 /* We have no need to default values of symbols. */
1756 symbolS
*md_undefined_symbol(name
)
1760 } /* md_undefined_symbol() */
1762 /* Parse an operand that is machine-specific.
1763 We just return without modifying the expression if we have nothing
1767 void md_operand(expressionP
)
1768 expressionS
*expressionP
;
1770 } /* md_operand() */
1772 /* Round up a section size to the appropriate boundary. */
1773 long md_section_align (segment
, size
)
1777 return (size
+ 7) & ~7; /* Round all sects to multiple of 8 */
1778 } /* md_section_align() */
1780 /* Exactly what point is a PC-relative offset relative TO?
1781 On the sparc, they're relative to the address of the offset, plus
1782 its size. This gets us to the following instruction.
1783 (??? Is this right? FIXME-SOON) */
1784 long md_pcrel_from(fixP
)
1787 return fixP
->fx_size
+ fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
1788 } /* md_pcrel_from() */
1790 void tc_aout_pre_write_hook(headers
)
1791 object_headers
*headers
;
1793 H_SET_VERSION(headers
, 1);
1795 } /* tc_aout_pre_write_hook() */
1804 /* end of tp-sparc.c */