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. */
20 /* static const char rcsid[] = "$Id$"; */
27 /* careful, this file includes data *declarations* */
28 #include "sparc-opcode.h"
32 void md_number_to_chars();
35 void md_convert_frag();
36 void md_create_short_jump();
37 void md_create_long_jump();
38 int md_estimate_size_before_relax();
39 void md_ri_to_chars();
40 symbolS
*md_undefined_symbol();
41 static void sparc_ip();
43 static enum sparc_architecture current_architecture
= v6
;
44 static int architecture_requested
= 0;
45 static int warn_on_bump
= 0;
47 const relax_typeS md_relax_table
[] = {
50 /* handle of the OPCODE hash table */
51 static struct hash_control
*op_hash
= NULL
;
53 static void s_seg(), s_proc(), s_data1(), s_reserve(), s_common();
54 extern void s_globl(), s_long(), s_short(), s_space(), cons();
55 extern void s_align_bytes(), s_ignore();
57 const pseudo_typeS md_pseudo_table
[] = {
58 { "align", s_align_bytes
, 0 }, /* Defaulting is invalid (0) */
59 { "common", s_common
, 0 },
60 { "global", s_globl
, 0 },
62 { "optim", s_ignore
, 0 },
63 { "proc", s_proc
, 0 },
64 { "reserve", s_reserve
, 0 },
66 { "skip", s_space
, 0 },
71 const int md_short_jump_size
= 4;
72 const int md_long_jump_size
= 4;
73 const int md_reloc_size
= 12; /* Size of relocation record */
75 /* This array holds the chars that always start a comment. If the
76 pre-processor is disabled, these aren't very useful */
77 const char comment_chars
[] = "!"; /* JF removed '|' from comment_chars */
79 /* This array holds the chars that only start a comment at the beginning of
80 a line. If the line seems to have the form '# 123 filename'
81 .line and .file directives will appear in the pre-processed output */
82 /* Note that input_file.c hand checks for '#' at the beginning of the
83 first line of the input file. This is because the compiler outputs
84 #NO_APP at the beginning of its output. */
85 /* Also note that comments started like this one will always
86 work if '/' isn't otherwise defined. */
87 const char line_comment_chars
[] = "#";
89 /* Chars that can be used to separate mant from exp in floating point nums */
90 const char EXP_CHARS
[] = "eE";
92 /* Chars that mean this number is a floating point constant */
95 const char FLT_CHARS
[] = "rRsSfFdDxXpP";
97 /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
98 changed in read.c . Ideally it shouldn't have to know about it at all,
99 but nothing is ideal around here.
102 static unsigned char octal
[256];
103 #define isoctal(c) octal[c]
104 static unsigned char toHex
[256];
108 unsigned long opcode
;
109 struct nlist
*nlistp
;
112 enum reloc_type reloc
;
113 } the_insn
, set_insn
;
117 static void print_insn(struct sparc_it
*insn
);
119 static int getExpression(char *str
);
122 static void print_insn();
124 static int getExpression();
126 static char *expr_end
;
127 static int special_case
;
130 * Instructions that require wierd handling because they're longer than
133 #define SPECIAL_CASE_SET 1
134 #define SPECIAL_CASE_FDIV 2
137 * sort of like s_lcomm
140 static void s_reserve() {
147 name
= input_line_pointer
;
148 c
= get_symbol_end();
149 p
= input_line_pointer
;
152 if (* input_line_pointer
!= ',') {
153 as_bad("Expected comma after name");
154 ignore_rest_of_line();
157 input_line_pointer
++;
158 if ((temp
= get_absolute_expression()) < 0) {
159 as_bad("BSS length (%d.) <0! Ignored.", temp
);
160 ignore_rest_of_line();
164 symbolP
= symbol_find_or_make(name
);
166 if (strncmp(input_line_pointer
, ",\"bss\"", 6) != 0) {
167 as_bad("bad .reserve segment: `%s'", input_line_pointer
);
170 input_line_pointer
+= 6;
171 if (S_GET_OTHER(symbolP
) == 0
172 && S_GET_DESC(symbolP
) == 0
173 && ((S_GET_TYPE(symbolP
) == N_BSS
174 && S_GET_VALUE(symbolP
) == local_bss_counter
)
175 || !S_IS_DEFINED(symbolP
))) {
176 S_SET_VALUE(symbolP
, local_bss_counter
);
177 S_SET_SEGMENT(symbolP
, SEG_BSS
);
178 symbolP
->sy_frag
= & bss_address_frag
;
179 local_bss_counter
+= temp
;
181 as_warn("Ignoring attempt to re-define symbol from %d. to %d.",
182 S_GET_VALUE(symbolP
), local_bss_counter
);
184 demand_empty_rest_of_line();
188 static void s_common() {
193 register symbolS
* symbolP
;
195 name
= input_line_pointer
;
196 c
= get_symbol_end();
197 /* just after name is now '\0' */
198 p
= input_line_pointer
;
201 if (* input_line_pointer
!= ',') {
202 as_bad("Expected comma after symbol-name");
203 ignore_rest_of_line();
206 input_line_pointer
++; /* skip ',' */
207 if ((temp
= get_absolute_expression ()) < 0) {
208 as_bad(".COMMon length (%d.) <0! Ignored.", temp
);
209 ignore_rest_of_line();
213 symbolP
= symbol_find_or_make(name
);
215 if (S_IS_DEFINED(symbolP
)) {
216 as_bad("Ignoring attempt to re-define symbol");
217 ignore_rest_of_line();
220 if (S_GET_VALUE(symbolP
) != 0) {
221 if (S_GET_VALUE(symbolP
) != temp
) {
222 as_warn("Length of .comm \"%s\" is already %d. Not changed to %d.",
223 S_GET_NAME(symbolP
), S_GET_VALUE(symbolP
), temp
);
226 S_SET_VALUE(symbolP
, temp
);
227 S_SET_EXTERNAL(symbolP
);
229 know(symbolP
->sy_frag
== &zero_address_frag
);
230 if (strncmp(input_line_pointer
, ",\"bss\"", 6) != 0
231 && strncmp(input_line_pointer
, ",\"data\"", 7) != 0) {
232 p
=input_line_pointer
;
233 while(*p
&& *p
!='\n')
237 as_bad("bad .common segment: `%s'", input_line_pointer
);
241 input_line_pointer
+= 6 + (input_line_pointer
[2] == 'd'); /* Skip either */
242 demand_empty_rest_of_line();
246 static void s_seg() {
248 if (strncmp(input_line_pointer
, "\"text\"", 6) == 0) {
249 input_line_pointer
+= 6;
253 if (strncmp(input_line_pointer
, "\"data\"", 6) == 0) {
254 input_line_pointer
+= 6;
258 if (strncmp(input_line_pointer
, "\"data1\"", 7) == 0) {
259 input_line_pointer
+= 7;
263 if (strncmp(input_line_pointer
, "\"bss\"", 5) == 0) {
264 input_line_pointer
+= 5;
265 /* We only support 2 segments -- text and data -- for now, so
266 things in the "bss segment" will have to go into data for now.
267 You can still allocate SEG_BSS stuff with .lcomm or .reserve. */
268 subseg_new(SEG_DATA
, 255); /* FIXME-SOMEDAY */
271 as_bad("Unknown segment type");
272 demand_empty_rest_of_line();
276 static void s_data1() {
277 subseg_new(SEG_DATA
, 1);
278 demand_empty_rest_of_line();
282 static void s_proc() {
283 extern char is_end_of_line
[];
285 while (!is_end_of_line
[*input_line_pointer
]) {
286 ++input_line_pointer
;
288 ++input_line_pointer
;
292 /* This function is called once, at assembler startup time. It should
293 set up all the tables, etc. that the MD part of the assembler will need. */
295 register char *retval
= NULL
;
297 register unsigned int i
= 0;
299 op_hash
= hash_new();
301 as_fatal("Virtual memory exhausted");
303 while (i
< NUMOPCODES
) {
304 const char *name
= sparc_opcodes
[i
].name
;
305 retval
= hash_insert(op_hash
, name
, &sparc_opcodes
[i
]);
306 if(retval
!= NULL
&& *retval
!= '\0') {
307 fprintf (stderr
, "internal error: can't hash `%s': %s\n",
308 sparc_opcodes
[i
].name
, retval
);
313 if (sparc_opcodes
[i
].match
& sparc_opcodes
[i
].lose
) {
314 fprintf (stderr
, "internal error: losing opcode: `%s' \"%s\"\n",
315 sparc_opcodes
[i
].name
, sparc_opcodes
[i
].args
);
319 } while (i
< NUMOPCODES
320 && !strcmp(sparc_opcodes
[i
].name
, name
));
324 as_fatal("Broken assembler. No assembly attempted.");
326 for (i
= '0'; i
< '8'; ++i
)
328 for (i
= '0'; i
<= '9'; ++i
)
330 for (i
= 'a'; i
<= 'f'; ++i
)
331 toHex
[i
] = i
+ 10 - 'a';
332 for (i
= 'A'; i
<= 'F'; ++i
)
333 toHex
[i
] = i
+ 10 - 'A';
340 void md_assemble(str
)
349 /* See if "set" operand is absolute and small; skip sethi if so. */
350 if (special_case
== SPECIAL_CASE_SET
&& the_insn
.exp
.X_seg
== SEG_ABSOLUTE
) {
351 if (the_insn
.exp
.X_add_number
>= -(1<<12)
352 && the_insn
.exp
.X_add_number
< (1<<12)) {
353 the_insn
.opcode
= 0x80102000 /* or %g0,imm,... */
354 | (the_insn
.opcode
& 0x3E000000) /* dest reg */
355 | (the_insn
.exp
.X_add_number
& 0x1FFF); /* imm */
356 special_case
= 0; /* No longer special */
357 the_insn
.reloc
= NO_RELOC
; /* No longer relocated */
362 /* put out the opcode */
363 md_number_to_chars(toP
, the_insn
.opcode
, 4);
365 /* put out the symbol-dependent stuff */
366 if (the_insn
.reloc
!= NO_RELOC
) {
367 fix_new(frag_now
, /* which frag */
368 (toP
- frag_now
->fr_literal
), /* where */
370 the_insn
.exp
.X_add_symbol
,
371 the_insn
.exp
.X_subtract_symbol
,
372 the_insn
.exp
.X_add_number
,
376 switch (special_case
) {
378 case SPECIAL_CASE_SET
:
380 assert(the_insn
.reloc
== RELOC_HI22
);
381 /* See if "set" operand has no low-order bits; skip OR if so. */
382 if (the_insn
.exp
.X_seg
== SEG_ABSOLUTE
383 && ((the_insn
.exp
.X_add_number
& 0x3FF) == 0))
386 rsd
= (the_insn
.opcode
>> 25) & 0x1f;
387 the_insn
.opcode
= 0x80102000 | (rsd
<< 25) | (rsd
<< 14);
388 md_number_to_chars(toP
, the_insn
.opcode
, 4);
389 fix_new(frag_now
, /* which frag */
390 (toP
- frag_now
->fr_literal
), /* where */
392 the_insn
.exp
.X_add_symbol
,
393 the_insn
.exp
.X_subtract_symbol
,
394 the_insn
.exp
.X_add_number
,
399 case SPECIAL_CASE_FDIV
:
400 /* According to information leaked from Sun, the "fdiv" instructions
401 on early SPARC machines would produce incorrect results sometimes.
402 The workaround is to add an fmovs of the destination register to
403 itself just after the instruction. This was true on machines
404 with Weitek 1165 float chips, such as the Sun-4/260 and /280. */
406 assert(the_insn
.reloc
== NO_RELOC
);
408 rsd
= (the_insn
.opcode
>> 25) & 0x1f;
409 the_insn
.opcode
= 0x81A00020 | (rsd
<< 25) | rsd
; /* fmovs dest,dest */
410 md_number_to_chars(toP
, the_insn
.opcode
, 4);
419 } /* md_assemble() */
421 static void sparc_ip(str
)
424 char *error_message
= "";
428 struct sparc_opcode
*insn
;
430 unsigned long opcode
;
431 unsigned int mask
= 0;
435 for (s
= str
; islower(*s
) || (*s
>= '0' && *s
<= '3'); ++s
)
452 as_bad("Unknown opcode: `%s'", str
);
455 if ((insn
= (struct sparc_opcode
*) hash_find(op_hash
, str
)) == NULL
) {
456 as_bad("Unknown opcode: `%s'", str
);
464 opcode
= insn
->match
;
465 bzero(&the_insn
, sizeof(the_insn
));
466 the_insn
.reloc
= NO_RELOC
;
469 * Build the opcode, checking as we go to make
470 * sure that the operands match
472 for (args
= insn
->args
; ; ++args
) {
477 if (strncmp(s
, "%asr", 4) == 0) {
483 while (isdigit(*s
)) {
484 num
= num
*10 + *s
-'0';
488 if (num
< 16 || 31 < num
) {
489 error_message
= ": asr number must be between 15 and 31";
493 opcode
|= (*args
== 'M' ? RS1(num
) : RD(num
));
496 error_message
= ": expecting %asrN";
498 } /* if %asr followed by a number. */
503 /* start-sanitize-v9 */
506 the_insn
.reloc
= RELOC_11
;
510 the_insn
.reloc
= RELOC_WDISP2_14
;
515 the_insn
.reloc
= RELOC_WDISP19
;
520 if (*s
== 'p' && s
[1] == 'n') {
527 if (*s
== 'p' && s
[1] == 't') {
534 if (strncmp(s
, "%amr", 4) == 0) {
544 if (strncmp(s
, "icc", 3) == 0) {
554 if (strncmp(s
, "xcc", 3) == 0) {
564 if (strncmp(s
, "fcc0", 4) == 0) {
574 if (strncmp(s
, "fcc1", 4) == 0) {
584 if (strncmp(s
, "fcc2", 4) == 0) {
594 if (strncmp(s
, "fcc3", 4) == 0) {
601 if (strncmp(s
, "%pc", 3) == 0) {
608 if (strncmp(s
, "%modes", 6) == 0) {
615 if (strncmp(s
, "%tick", 5) == 0) {
621 /* end-sanitize-v9 */
623 case '\0': /* end of args */
639 case '[': /* these must match exactly */
647 case '#': /* must be at least one digit */
649 while (isdigit(*s
)) {
656 case 'C': /* coprocessor state register */
657 if (strncmp(s
, "%csr", 4) == 0) {
663 case 'b': /* next operand is a coprocessor register */
666 if (*s
++ == '%' && *s
++ == 'c' && isdigit(*s
)) {
669 mask
= 10 * (mask
- '0') + (*s
++ - '0');
679 opcode
|= mask
<< 14;
687 opcode
|= mask
<< 25;
693 case 'r': /* next operand must be a register */
700 case 'f': /* frame pointer */
707 case 'g': /* global register */
708 if (isoctal(c
= *s
++)) {
714 case 'i': /* in register */
715 if (isoctal(c
= *s
++)) {
721 case 'l': /* local register */
722 if (isoctal(c
= *s
++)) {
723 mask
= (c
- '0' + 16) ;
728 case 'o': /* out register */
729 if (isoctal(c
= *s
++)) {
730 mask
= (c
- '0' + 8) ;
735 case 's': /* stack pointer */
742 case 'r': /* any register */
743 if (!isdigit(c
= *s
++)) {
747 case '0': case '1': case '2': case '3': case '4':
748 case '5': case '6': case '7': case '8': case '9':
750 if ((c
= 10 * (c
- '0') + (*s
++ - '0')) >= 32) {
763 * Got the register, now figure out where
764 * it goes in the opcode.
769 opcode
|= mask
<< 14;
777 opcode
|= mask
<< 25;
781 opcode
|= (mask
<< 25) | (mask
<< 14);
787 /* start-sanitize-v9 */
793 /* end-sanitize-v9 */
794 case 'e': /* next operand is a floating point register */
809 /* start-sanitize-v9 */
811 && ((format
= *s
) == 'f'
815 /* end-sanitize-v9 */
816 && ((format
= *s
) == 'f')
818 /* start-sanitize-v9 */
820 /* end-sanitize-v9 */
825 for (mask
= 0; isdigit(*s
); ++s
) {
826 mask
= 10 * mask
+ (*s
- '0');
827 } /* read the number */
835 } /* register must be even numbered */
843 } /* register must be multiple of 4 */
847 error_message
= ": There are only 32 f registers; [0-31]";
850 /* start-sanitize-v9 */
855 error_message
= ": There are only 32 d registers [0, 2, ... 62].";
857 } else if (mask
& 1) {
858 error_message
= ": Only even numbered d registers exist.";
862 } else if (format
== 'q') {
865 ": There are only 16 q registers [0, 4, ... 60].";
867 } else if (mask
& 3) {
869 ": Only q registers evenly divisible by four exist.";
874 } /* depending on format */
878 } /* wrap high bit */
879 } /* if not an 'f' register. */
881 /* end-sanitize-v9 */
885 /* start-sanitize-v9 */
890 opcode
|= (mask
& 0x1f) << 9;
893 /* end-sanitize-v9 */
920 if (strncmp(s
, "%fsr", 4) == 0) {
926 case 'h': /* high 22 bits */
927 the_insn
.reloc
= RELOC_HI22
;
930 case 'l': /* 22 bit PC relative immediate */
931 the_insn
.reloc
= RELOC_WDISP22
;
935 case 'L': /* 30 bit immediate */
936 the_insn
.reloc
= RELOC_WDISP30
;
940 case 'i': /* 13 bit immediate */
941 the_insn
.reloc
= RELOC_BASE13
;
949 if ((c
= s
[1]) == 'h' && s
[2] == 'i') {
950 the_insn
.reloc
= RELOC_HI22
;
952 } else if (c
== 'l' && s
[2] == 'o') {
953 the_insn
.reloc
= RELOC_LO10
;
955 /* start-sanitize-v9 */
960 the_insn
.reloc
= RELOC_HHI22
;
966 the_insn
.reloc
= RELOC_HLO10
;
969 /* end-sanitize-v9 */
973 /* Note that if the getExpression() fails, we
974 will still have created U entries in the
975 symbol table for the 'symbols' in the input
976 string. Try not to create U symbols for
979 /* This stuff checks to see if the
980 expression ends in +%reg If it does,
981 it removes the register from the
982 expression, and re-sets 's' to point
983 to the right place */
987 for(s1
=s
;*s1
&& *s1
!=','&& *s1
!=']';s1
++)
990 if(s1
!=s
&& isdigit(s1
[-1])) {
991 if(s1
[-2]=='%' && s1
[-3]=='+') {
994 (void)getExpression(s
);
998 } else if(strchr("goli0123456789",s1
[-2]) && s1
[-3]=='%' && s1
[-4]=='+') {
1001 (void)getExpression(s
);
1008 (void)getExpression(s
);
1019 case 'A': /* alternate space */
1024 while (isdigit(*s
)) {
1025 num
= num
*10 + *s
-'0';
1035 if (strncmp(s
, "%psr", 4) == 0) {
1041 case 'q': /* floating point queue */
1042 if (strncmp(s
, "%fq", 3) == 0) {
1048 case 'Q': /* coprocessor queue */
1049 if (strncmp(s
, "%cq", 3) == 0) {
1056 if (strcmp(str
, "set") == 0) {
1057 special_case
= SPECIAL_CASE_SET
;
1059 } else if (strncmp(str
, "fdiv", 4) == 0) {
1060 special_case
= SPECIAL_CASE_FDIV
;
1066 if (strncmp(s
, "%tbr", 4) != 0)
1072 if (strncmp(s
, "%wim", 4) != 0)
1078 if (strncmp(s
, "%y", 2) != 0)
1085 } /* switch on arg code */
1087 } /* for each arg that we expect */
1090 /* Args don't match. */
1091 if (((unsigned) (&insn
[1] - sparc_opcodes
)) < NUMOPCODES
1092 && !strcmp(insn
->name
, insn
[1].name
)) {
1097 as_bad("Illegal operands%s", error_message
);
1101 if (insn
->architecture
> current_architecture
) {
1102 if (current_architecture
!= cypress
1103 && (!architecture_requested
|| warn_on_bump
)) {
1106 as_warn("architecture bumped from \"%s\" to \"%s\" on \"%s\"",
1107 architecture_pname
[current_architecture
],
1108 architecture_pname
[insn
->architecture
],
1112 current_architecture
= insn
->architecture
;
1114 as_bad("architecture mismatch on \"%s\" (\"%s\"). current architecture is \"%s\"",
1116 architecture_pname
[insn
->architecture
],
1117 architecture_pname
[current_architecture
]);
1119 } /* if bump ok else error */
1120 } /* if architecture higher */
1124 } /* forever looking for a match */
1126 the_insn
.opcode
= opcode
;
1130 static int getExpression(str
)
1136 save_in
= input_line_pointer
;
1137 input_line_pointer
= str
;
1138 switch (seg
= expression(&the_insn
.exp
)) {
1145 case SEG_DIFFERENCE
:
1151 the_insn
.error
= "bad segment";
1152 expr_end
= input_line_pointer
;
1153 input_line_pointer
=save_in
;
1156 expr_end
= input_line_pointer
;
1157 input_line_pointer
= save_in
;
1159 } /* getExpression() */
1163 This is identical to the md_atof in m68k.c. I think this is right,
1166 Turn a string in input_line_pointer into a floating point constant of type
1167 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1168 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
1171 /* Equal to MAX_PRECISION in atof-ieee.c */
1172 #define MAX_LITTLENUMS 6
1174 char *md_atof(type
,litP
,sizeP
)
1180 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
1181 LITTLENUM_TYPE
*wordP
;
1213 return "Bad call to MD_ATOF()";
1215 t
=atof_ieee(input_line_pointer
,type
,words
);
1217 input_line_pointer
=t
;
1218 *sizeP
=prec
* sizeof(LITTLENUM_TYPE
);
1219 for(wordP
=words
;prec
--;) {
1220 md_number_to_chars(litP
,(long)(*wordP
++),sizeof(LITTLENUM_TYPE
));
1221 litP
+=sizeof(LITTLENUM_TYPE
);
1223 return ""; /* Someone should teach Dean about null pointers */
1227 * Write out big-endian.
1229 void md_number_to_chars(buf
,val
,n
)
1250 } /* md_number_to_chars() */
1252 /* Apply a fixS to the frags, now that we know the value it ought to
1255 void md_apply_fix(fixP
, val
)
1259 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
1261 assert(fixP
->fx_size
== 4);
1262 assert(fixP
->fx_r_type
< NO_RELOC
);
1264 fixP
->fx_addnumber
= val
; /* Remember value for emit_reloc */
1267 * This is a hack. There should be a better way to
1270 if (fixP
->fx_r_type
== RELOC_WDISP30
&& fixP
->fx_addsy
) {
1271 val
+= fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
1274 switch (fixP
->fx_r_type
) {
1277 buf
[0] = 0; /* val >> 24; */
1278 buf
[1] = 0; /* val >> 16; */
1279 buf
[2] = 0; /* val >> 8; */
1280 buf
[3] = 0; /* val; */
1284 case RELOC_8
: /* These don't seem to ever be needed. */
1291 val
= (val
>>= 2) + 1;
1292 buf
[0] |= (val
>> 24) & 0x3f;
1293 buf
[1]= (val
>> 16);
1298 /* start-sanitize-v9 */
1301 if (((val
> 0) && (val
& ~0x7ff))
1302 || ((val
< 0) && (~val
& ~0x7ff))) {
1303 as_bad("relocation overflow.");
1306 buf
[2] = (val
>> 8) & 0x7;
1307 buf
[3] = val
& 0xff;
1310 case RELOC_WDISP2_14
:
1311 if (((val
> 0) && (val
& ~0x3fffc))
1312 || ((val
< 0) && (~val
& ~0x3fffc))) {
1313 as_bad("relocation overflow.");
1316 val
= (val
>>= 2) + 1;
1317 buf
[1] |= ((val
>> 14) & 0x3) << 3;
1318 buf
[2] |= (val
>> 8) & 0x3f ;
1319 buf
[3] = val
& 0xff;
1323 if (((val
> 0) && (val
& ~0x1ffffc))
1324 || ((val
< 0) && (~val
& ~0x1ffffc))) {
1325 as_bad("relocation overflow.");
1328 val
= (val
>>= 2) + 1;
1329 buf
[1] |= (val
>> 16) & 0x7;
1330 buf
[2] = (val
>> 8) & 0xff;
1331 buf
[3] = val
& 0xff;
1336 /* intentional fallthrough */
1338 /* end-sanitize-v9 */
1341 if(!fixP
->fx_addsy
) {
1342 buf
[1] |= (val
>> 26) & 0x3f;
1355 /* start-sanitize-v9 */
1359 /* intentional fallthrough */
1361 /* end-sanitize-v9 */
1364 if(!fixP
->fx_addsy
) {
1365 buf
[2] |= (val
>> 8) & 0x03;
1371 case RELOC_SFA_BASE
:
1372 case RELOC_SFA_OFF13
:
1376 buf
[2] |= (val
>> 8) & 0x1f;
1381 val
= (val
>>= 2) + 1;
1384 buf
[1] |= (val
>> 16) & 0x3f;
1393 case RELOC_SEGOFF16
:
1394 case RELOC_GLOB_DAT
:
1395 case RELOC_JMP_SLOT
:
1396 case RELOC_RELATIVE
:
1401 as_bad("bad relocation type: 0x%02x", fixP
->fx_r_type
);
1404 } /* md_apply_fix() */
1406 /* should never be called for sparc */
1407 void md_create_short_jump(ptr
, from_addr
, to_addr
, frag
, to_symbol
)
1414 fprintf(stderr
, "sparc_create_short_jmp\n");
1416 } /* md_create_short_jump() */
1418 /* Translate internal representation of relocation info to target format.
1420 On sparc: first 4 bytes are normal unsigned long address, next three
1421 bytes are index, most sig. byte first. Byte 7 is broken up with
1422 bit 7 as external, bits 6 & 5 unused, and the lower
1423 five bits as relocation type. Next 4 bytes are long addend. */
1424 /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
1425 void tc_aout_fix_to_chars(where
, fixP
, segment_address_in_file
)
1428 relax_addressT segment_address_in_file
;
1435 know(fixP
->fx_addsy
);
1437 if ((S_GET_TYPE(fixP
->fx_addsy
)) == N_UNDF
) {
1439 r_index
= fixP
->fx_addsy
->sy_number
;
1442 r_index
= S_GET_TYPE(fixP
->fx_addsy
);
1446 md_number_to_chars(where
,
1447 r_address
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
- segment_address_in_file
,
1450 /* now the fun stuff */
1451 where
[4] = (r_index
>> 16) & 0x0ff;
1452 where
[5] = (r_index
>> 8) & 0x0ff;
1453 where
[6] = r_index
& 0x0ff;
1454 where
[7] = ((r_extern
<< 7) & 0x80) | (0 & 0x60) | (fixP
->fx_r_type
& 0x1F);
1457 if (fixP
->fx_addsy
->sy_frag
) {
1458 r_addend
= fixP
->fx_addsy
->sy_frag
->fr_address
;
1461 if (fixP
->fx_pcrel
) {
1462 r_addend
-= r_address
;
1464 r_addend
= fixP
->fx_addnumber
;
1467 md_number_to_chars(&where
[8], r_addend
, 4);
1470 } /* tc_aout_fix_to_chars() */
1472 /* should never be called for sparc */
1473 void md_convert_frag(headers
, fragP
)
1474 object_headers
*headers
;
1475 register fragS
*fragP
;
1477 fprintf(stderr
, "sparc_convert_frag\n");
1479 } /* md_convert_frag() */
1481 /* should never be called for sparc */
1482 void md_create_long_jump(ptr
, from_addr
, to_addr
, frag
, to_symbol
)
1484 long from_addr
, to_addr
;
1488 fprintf(stderr
, "sparc_create_long_jump\n");
1490 } /* md_create_long_jump() */
1492 /* should never be called for sparc */
1493 int md_estimate_size_before_relax(fragP
, segtype
)
1497 fprintf(stderr
, "sparc_estimate_size_before_relax\n");
1500 } /* md_estimate_size_before_relax() */
1503 /* for debugging only */
1504 static void print_insn(insn
)
1505 struct sparc_it
*insn
;
1536 fprintf(stderr
, "ERROR: %s\n");
1538 fprintf(stderr
, "opcode=0x%08x\n", insn
->opcode
);
1539 fprintf(stderr
, "reloc = %s\n", Reloc
[insn
->reloc
]);
1540 fprintf(stderr
, "exp = {
1542 fprintf(stderr
, "\t\tX_add_symbol = %s\n",
1543 ((insn
->exp
.X_add_symbol
!= NULL
)
1544 ? ((S_GET_NAME(insn
->exp
.X_add_symbol
) != NULL
)
1545 ? S_GET_NAME(insn
->exp
.X_add_symbol
)
1548 fprintf(stderr
, "\t\tX_sub_symbol = %s\n",
1549 ((insn
->exp
.X_subtract_symbol
!= NULL
)
1550 ? (S_GET_NAME(insn
->exp
.X_subtract_symbol
)
1551 ? S_GET_NAME(insn
->exp
.X_subtract_symbol
)
1554 fprintf(stderr
, "\t\tX_add_number = %d\n",
1555 insn
->exp
.X_add_number
);
1556 fprintf(stderr
, "}\n");
1558 } /* print_insn() */
1561 /* Set the hook... */
1563 /* void emit_sparc_reloc();
1564 void (*md_emit_relocations)() = emit_sparc_reloc; */
1569 * Sparc/AM29K relocations are completely different, so it needs
1570 * this machine dependent routine to emit them.
1572 #if defined(OBJ_AOUT) || defined(OBJ_BOUT)
1573 void emit_sparc_reloc(fixP
, segment_address_in_file
)
1574 register fixS
*fixP
;
1575 relax_addressT segment_address_in_file
;
1577 struct reloc_info_generic ri
;
1578 register symbolS
*symbolP
;
1579 extern char *next_object_file_charP
;
1580 /* long add_number; */
1582 bzero((char *) &ri
, sizeof(ri
));
1583 for (; fixP
; fixP
= fixP
->fx_next
) {
1585 if (fixP
->fx_r_type
>= NO_RELOC
) {
1586 fprintf(stderr
, "fixP->fx_r_type = %d\n", fixP
->fx_r_type
);
1590 if ((symbolP
= fixP
->fx_addsy
) != NULL
) {
1591 ri
.r_address
= fixP
->fx_frag
->fr_address
+
1592 fixP
->fx_where
- segment_address_in_file
;
1593 if ((S_GET_TYPE(symbolP
)) == N_UNDF
) {
1595 ri
.r_index
= symbolP
->sy_number
;
1598 ri
.r_index
= S_GET_TYPE(symbolP
);
1600 if (symbolP
&& symbolP
->sy_frag
) {
1601 ri
.r_addend
= symbolP
->sy_frag
->fr_address
;
1603 ri
.r_type
= fixP
->fx_r_type
;
1604 if (fixP
->fx_pcrel
) {
1605 /* ri.r_addend -= fixP->fx_where; */
1606 ri
.r_addend
-= ri
.r_address
;
1608 ri
.r_addend
= fixP
->fx_addnumber
;
1611 md_ri_to_chars(next_object_file_charP
, &ri
);
1612 next_object_file_charP
+= md_reloc_size
;
1616 } /* emit_sparc_reloc() */
1617 #endif /* aout or bout */
1618 #endif /* comment */
1622 * Invocation line includes a switch not recognized by the base assembler.
1623 * See if it's a processor-specific option. These are:
1626 * Warn on architecture bumps. See also -A.
1628 * -Av6, -Av7, -Acypress, -Av8
1629 * Select the architecture. Instructions or features not
1630 * supported by the selected architecture cause fatal errors.
1632 * The default is to start at v6, and bump the architecture up
1633 * whenever an instruction is seen at a higher level.
1635 * If -bump is specified, a warning is printing when bumping to
1638 * If an architecture is specified, all instructions must match
1639 * that architecture. Any higher level instructions are flagged
1642 * if both an architecture and -bump are specified, the
1643 * architecture starts at the specified level, but bumps are
1646 * Note that where cypress specific instructions conflict with
1647 * other instructions, the other instruction is assumed. Nothing
1648 * is upward compatible with cypress. Thus, to get the cypress
1649 * instruction set you MUST -Acypress.
1652 /* start-sanitize-v9 */
1653 /* There is also a -Av9 architecture option. xoxorich. */
1654 /* end-sanitize-v9 */
1655 int md_parse_option(argP
, cntP
, vecP
)
1663 if (!strcmp(*argP
,"bump")){
1666 } else if (**argP
== 'A'){
1669 for (arch
= architecture_pname
; *arch
!= NULL
; ++arch
){
1670 if (strcmp(p
, *arch
) == 0){
1672 } /* found a match */
1673 } /* walk the pname table */
1676 as_bad("unknown architecture: %s", p
);
1678 current_architecture
= (enum sparc_architecture
) (arch
- architecture_pname
);
1679 architecture_requested
= 1;
1682 /* Unknown option */
1686 **argP
= '\0'; /* Done parsing this switch */
1688 } /* md_parse_option() */
1690 /* We have no need to default values of symbols. */
1693 symbolS
*md_undefined_symbol(name
)
1697 } /* md_undefined_symbol() */
1699 /* Parse an operand that is machine-specific.
1700 We just return without modifying the expression if we have nothing
1704 void md_operand(expressionP
)
1705 expressionS
*expressionP
;
1707 } /* md_operand() */
1709 /* Round up a section size to the appropriate boundary. */
1710 long md_section_align (segment
, size
)
1714 return (size
+ 7) & ~7; /* Round all sects to multiple of 8 */
1715 } /* md_section_align() */
1717 /* Exactly what point is a PC-relative offset relative TO?
1718 On the sparc, they're relative to the address of the offset, plus
1719 its size. This gets us to the following instruction.
1720 (??? Is this right? FIXME-SOON) */
1721 long md_pcrel_from(fixP
)
1724 return fixP
->fx_size
+ fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
1725 } /* md_pcrel_from() */
1734 /* end of tp-sparc.c */