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. */
27 /* careful, this file includes data *declarations* */
28 #include "opcode/sparc.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
);
120 #else /* not __STDC__ */
122 static void print_insn();
124 static int getExpression();
125 #endif /* not __STDC__ */
127 static char *expr_end
;
128 static int special_case
;
131 * Instructions that require wierd handling because they're longer than
134 #define SPECIAL_CASE_SET 1
135 #define SPECIAL_CASE_FDIV 2
138 * sort of like s_lcomm
141 static int max_alignment
= 15;
143 static void s_reserve() {
152 name
= input_line_pointer
;
153 c
= get_symbol_end();
154 p
= input_line_pointer
;
158 if (*input_line_pointer
!= ',') {
159 as_bad("Expected comma after name");
160 ignore_rest_of_line();
164 ++input_line_pointer
;
166 if ((size
= get_absolute_expression()) < 0) {
167 as_bad("BSS length (%d.) <0! Ignored.", size
);
168 ignore_rest_of_line();
173 symbolP
= symbol_find_or_make(name
);
176 if (strncmp(input_line_pointer
, ",\"bss\"", 6) != 0) {
177 as_bad("bad .reserve segment: `%s'", input_line_pointer
);
181 input_line_pointer
+= 6;
184 if (*input_line_pointer
== ',') {
185 ++input_line_pointer
;
188 if (*input_line_pointer
== '\n') {
189 as_bad("Missing alignment");
193 align
= get_absolute_expression();
194 if (align
> max_alignment
){
195 align
= max_alignment
;
196 as_warn("Alignment too large: %d. assumed.", align
);
197 } else if (align
< 0) {
199 as_warn("Alignment negative. 0 assumed.");
202 #define SEG_BSS SEG_E2
203 record_alignment(SEG_E2
, align
);
205 record_alignment(SEG_BSS
, align
);
208 /* convert to a power of 2 alignment */
209 for (temp
= 0; (align
& 1) == 0; align
>>= 1, ++temp
) ;;
212 as_bad("Alignment not a power of 2");
213 ignore_rest_of_line();
215 } /* not a power of two */
220 align
= ~((~0) << align
); /* Convert to a mask */
221 local_bss_counter
= (local_bss_counter
+ align
) & (~align
);
222 } /* if has optional alignment */
224 if (S_GET_OTHER(symbolP
) == 0
225 && S_GET_DESC(symbolP
) == 0
226 && ((S_GET_SEGMENT(symbolP
) == SEG_BSS
227 && S_GET_VALUE(symbolP
) == local_bss_counter
)
228 || !S_IS_DEFINED(symbolP
))) {
229 S_SET_VALUE(symbolP
, local_bss_counter
);
230 S_SET_SEGMENT(symbolP
, SEG_BSS
);
231 symbolP
->sy_frag
= &bss_address_frag
;
232 local_bss_counter
+= size
;
234 as_warn("Ignoring attempt to re-define symbol from %d. to %d.",
235 S_GET_VALUE(symbolP
), local_bss_counter
);
236 } /* if not redefining */
238 demand_empty_rest_of_line();
242 static void s_common() {
247 register symbolS
* symbolP
;
249 name
= input_line_pointer
;
250 c
= get_symbol_end();
251 /* just after name is now '\0' */
252 p
= input_line_pointer
;
255 if (* input_line_pointer
!= ',') {
256 as_bad("Expected comma after symbol-name");
257 ignore_rest_of_line();
260 input_line_pointer
++; /* skip ',' */
261 if ((temp
= get_absolute_expression ()) < 0) {
262 as_bad(".COMMon length (%d.) <0! Ignored.", temp
);
263 ignore_rest_of_line();
267 symbolP
= symbol_find_or_make(name
);
269 if (S_IS_DEFINED(symbolP
)) {
270 as_bad("Ignoring attempt to re-define symbol");
271 ignore_rest_of_line();
274 if (S_GET_VALUE(symbolP
) != 0) {
275 if (S_GET_VALUE(symbolP
) != temp
) {
276 as_warn("Length of .comm \"%s\" is already %d. Not changed to %d.",
277 S_GET_NAME(symbolP
), S_GET_VALUE(symbolP
), temp
);
280 S_SET_VALUE(symbolP
, temp
);
281 S_SET_EXTERNAL(symbolP
);
283 know(symbolP
->sy_frag
== &zero_address_frag
);
284 if (strncmp(input_line_pointer
, ",\"bss\"", 6) != 0
285 && strncmp(input_line_pointer
, ",\"data\"", 7) != 0) {
286 p
=input_line_pointer
;
287 while(*p
&& *p
!='\n')
291 as_bad("bad .common segment: `%s'", input_line_pointer
);
295 input_line_pointer
+= 6 + (input_line_pointer
[2] == 'd'); /* Skip either */
296 demand_empty_rest_of_line();
300 static void s_seg() {
302 if (strncmp(input_line_pointer
, "\"text\"", 6) == 0) {
303 input_line_pointer
+= 6;
307 if (strncmp(input_line_pointer
, "\"data\"", 6) == 0) {
308 input_line_pointer
+= 6;
312 if (strncmp(input_line_pointer
, "\"data1\"", 7) == 0) {
313 input_line_pointer
+= 7;
317 if (strncmp(input_line_pointer
, "\"bss\"", 5) == 0) {
318 input_line_pointer
+= 5;
319 /* We only support 2 segments -- text and data -- for now, so
320 things in the "bss segment" will have to go into data for now.
321 You can still allocate SEG_BSS stuff with .lcomm or .reserve. */
322 subseg_new(SEG_DATA
, 255); /* FIXME-SOMEDAY */
325 as_bad("Unknown segment type");
326 demand_empty_rest_of_line();
330 static void s_data1() {
331 subseg_new(SEG_DATA
, 1);
332 demand_empty_rest_of_line();
336 static void s_proc() {
337 extern char is_end_of_line
[];
339 while (!is_end_of_line
[*input_line_pointer
]) {
340 ++input_line_pointer
;
342 ++input_line_pointer
;
346 /* This function is called once, at assembler startup time. It should
347 set up all the tables, etc. that the MD part of the assembler will need. */
349 register char *retval
= NULL
;
351 register unsigned int i
= 0;
353 op_hash
= hash_new();
355 as_fatal("Virtual memory exhausted");
357 while (i
< NUMOPCODES
) {
358 const char *name
= sparc_opcodes
[i
].name
;
359 retval
= hash_insert(op_hash
, name
, &sparc_opcodes
[i
]);
360 if(retval
!= NULL
&& *retval
!= '\0') {
361 fprintf (stderr
, "internal error: can't hash `%s': %s\n",
362 sparc_opcodes
[i
].name
, retval
);
367 if (sparc_opcodes
[i
].match
& sparc_opcodes
[i
].lose
) {
368 fprintf (stderr
, "internal error: losing opcode: `%s' \"%s\"\n",
369 sparc_opcodes
[i
].name
, sparc_opcodes
[i
].args
);
373 } while (i
< NUMOPCODES
374 && !strcmp(sparc_opcodes
[i
].name
, name
));
378 as_fatal("Broken assembler. No assembly attempted.");
380 for (i
= '0'; i
< '8'; ++i
)
382 for (i
= '0'; i
<= '9'; ++i
)
384 for (i
= 'a'; i
<= 'f'; ++i
)
385 toHex
[i
] = i
+ 10 - 'a';
386 for (i
= 'A'; i
<= 'F'; ++i
)
387 toHex
[i
] = i
+ 10 - 'A';
394 void md_assemble(str
)
403 /* See if "set" operand is absolute and small; skip sethi if so. */
404 if (special_case
== SPECIAL_CASE_SET
&& the_insn
.exp
.X_seg
== SEG_ABSOLUTE
) {
405 if (the_insn
.exp
.X_add_number
>= -(1<<12)
406 && the_insn
.exp
.X_add_number
< (1<<12)) {
407 the_insn
.opcode
= 0x80102000 /* or %g0,imm,... */
408 | (the_insn
.opcode
& 0x3E000000) /* dest reg */
409 | (the_insn
.exp
.X_add_number
& 0x1FFF); /* imm */
410 special_case
= 0; /* No longer special */
411 the_insn
.reloc
= NO_RELOC
; /* No longer relocated */
416 /* put out the opcode */
417 md_number_to_chars(toP
, the_insn
.opcode
, 4);
419 /* put out the symbol-dependent stuff */
420 if (the_insn
.reloc
!= NO_RELOC
) {
421 fix_new(frag_now
, /* which frag */
422 (toP
- frag_now
->fr_literal
), /* where */
424 the_insn
.exp
.X_add_symbol
,
425 the_insn
.exp
.X_subtract_symbol
,
426 the_insn
.exp
.X_add_number
,
430 switch (special_case
) {
432 case SPECIAL_CASE_SET
:
434 assert(the_insn
.reloc
== RELOC_HI22
);
435 /* See if "set" operand has no low-order bits; skip OR if so. */
436 if (the_insn
.exp
.X_seg
== SEG_ABSOLUTE
437 && ((the_insn
.exp
.X_add_number
& 0x3FF) == 0))
440 rsd
= (the_insn
.opcode
>> 25) & 0x1f;
441 the_insn
.opcode
= 0x80102000 | (rsd
<< 25) | (rsd
<< 14);
442 md_number_to_chars(toP
, the_insn
.opcode
, 4);
443 fix_new(frag_now
, /* which frag */
444 (toP
- frag_now
->fr_literal
), /* where */
446 the_insn
.exp
.X_add_symbol
,
447 the_insn
.exp
.X_subtract_symbol
,
448 the_insn
.exp
.X_add_number
,
453 case SPECIAL_CASE_FDIV
:
454 /* According to information leaked from Sun, the "fdiv" instructions
455 on early SPARC machines would produce incorrect results sometimes.
456 The workaround is to add an fmovs of the destination register to
457 itself just after the instruction. This was true on machines
458 with Weitek 1165 float chips, such as the Sun-4/260 and /280. */
460 assert(the_insn
.reloc
== NO_RELOC
);
462 rsd
= (the_insn
.opcode
>> 25) & 0x1f;
463 the_insn
.opcode
= 0x81A00020 | (rsd
<< 25) | rsd
; /* fmovs dest,dest */
464 md_number_to_chars(toP
, the_insn
.opcode
, 4);
471 as_fatal("failed sanity check.");
473 } /* md_assemble() */
475 static void sparc_ip(str
)
478 char *error_message
= "";
482 struct sparc_opcode
*insn
;
484 unsigned long opcode
;
485 unsigned int mask
= 0;
489 for (s
= str
; islower(*s
) || (*s
>= '0' && *s
<= '3'); ++s
)
506 as_bad("Unknown opcode: `%s'", str
);
509 if ((insn
= (struct sparc_opcode
*) hash_find(op_hash
, str
)) == NULL
) {
510 as_bad("Unknown opcode: `%s'", str
);
518 opcode
= insn
->match
;
519 memset(&the_insn
, '\0', sizeof(the_insn
));
520 the_insn
.reloc
= NO_RELOC
;
523 * Build the opcode, checking as we go to make
524 * sure that the operands match
526 for (args
= insn
->args
; ; ++args
) {
531 if (strncmp(s
, "%asr", 4) == 0) {
537 while (isdigit(*s
)) {
538 num
= num
*10 + *s
-'0';
542 if (num
< 16 || 31 < num
) {
543 error_message
= ": asr number must be between 15 and 31";
547 opcode
|= (*args
== 'M' ? RS1(num
) : RD(num
));
550 error_message
= ": expecting %asrN";
552 } /* if %asr followed by a number. */
557 /* start-sanitize-v9 */
560 the_insn
.reloc
= RELOC_11
;
564 the_insn
.reloc
= RELOC_WDISP2_14
;
569 the_insn
.reloc
= RELOC_WDISP19
;
574 if (*s
== 'p' && s
[1] == 'n') {
581 if (*s
== 'p' && s
[1] == 't') {
588 if (strncmp(s
, "%amr", 4) == 0) {
598 if (strncmp(s
, "icc", 3) == 0) {
608 if (strncmp(s
, "xcc", 3) == 0) {
618 if (strncmp(s
, "fcc0", 4) == 0) {
628 if (strncmp(s
, "fcc1", 4) == 0) {
638 if (strncmp(s
, "fcc2", 4) == 0) {
648 if (strncmp(s
, "fcc3", 4) == 0) {
655 if (strncmp(s
, "%pc", 3) == 0) {
662 if (strncmp(s
, "%modes", 6) == 0) {
669 if (strncmp(s
, "%tick", 5) == 0) {
675 /* end-sanitize-v9 */
677 case '\0': /* end of args */
693 case '[': /* these must match exactly */
701 case '#': /* must be at least one digit */
703 while (isdigit(*s
)) {
710 case 'C': /* coprocessor state register */
711 if (strncmp(s
, "%csr", 4) == 0) {
717 case 'b': /* next operand is a coprocessor register */
720 if (*s
++ == '%' && *s
++ == 'c' && isdigit(*s
)) {
723 mask
= 10 * (mask
- '0') + (*s
++ - '0');
733 opcode
|= mask
<< 14;
741 opcode
|= mask
<< 25;
747 case 'r': /* next operand must be a register */
754 case 'f': /* frame pointer */
761 case 'g': /* global register */
762 if (isoctal(c
= *s
++)) {
768 case 'i': /* in register */
769 if (isoctal(c
= *s
++)) {
775 case 'l': /* local register */
776 if (isoctal(c
= *s
++)) {
777 mask
= (c
- '0' + 16) ;
782 case 'o': /* out register */
783 if (isoctal(c
= *s
++)) {
784 mask
= (c
- '0' + 8) ;
789 case 's': /* stack pointer */
796 case 'r': /* any register */
797 if (!isdigit(c
= *s
++)) {
801 case '0': case '1': case '2': case '3': case '4':
802 case '5': case '6': case '7': case '8': case '9':
804 if ((c
= 10 * (c
- '0') + (*s
++ - '0')) >= 32) {
817 * Got the register, now figure out where
818 * it goes in the opcode.
823 opcode
|= mask
<< 14;
831 opcode
|= mask
<< 25;
835 opcode
|= (mask
<< 25) | (mask
<< 14);
841 /* start-sanitize-v9 */
847 /* end-sanitize-v9 */
848 case 'e': /* next operand is a floating point register */
863 /* start-sanitize-v9 */
865 && ((format
= *s
) == 'f'
869 /* end-sanitize-v9 */
870 && ((format
= *s
) == 'f')
872 /* start-sanitize-v9 */
874 /* end-sanitize-v9 */
879 for (mask
= 0; isdigit(*s
); ++s
) {
880 mask
= 10 * mask
+ (*s
- '0');
881 } /* read the number */
889 } /* register must be even numbered */
897 } /* register must be multiple of 4 */
901 error_message
= ": There are only 32 f registers; [0-31]";
904 /* start-sanitize-v9 */
909 error_message
= ": There are only 32 d registers [0, 2, ... 62].";
911 } else if (mask
& 1) {
912 error_message
= ": Only even numbered d registers exist.";
916 } else if (format
== 'q') {
919 ": There are only 16 q registers [0, 4, ... 60].";
921 } else if (mask
& 3) {
923 ": Only q registers evenly divisible by four exist.";
928 } /* depending on format */
932 } /* wrap high bit */
934 /* end-sanitize-v9 */
935 } /* if not an 'f' register. */
939 /* start-sanitize-v9 */
944 opcode
|= (mask
& 0x1f) << 9;
947 /* end-sanitize-v9 */
974 if (strncmp(s
, "%fsr", 4) == 0) {
980 case 'h': /* high 22 bits */
981 the_insn
.reloc
= RELOC_HI22
;
984 case 'l': /* 22 bit PC relative immediate */
985 the_insn
.reloc
= RELOC_WDISP22
;
989 case 'L': /* 30 bit immediate */
990 the_insn
.reloc
= RELOC_WDISP30
;
994 case 'n': /* 22 bit immediate */
995 the_insn
.reloc
= RELOC_22
;
998 case 'i': /* 13 bit immediate */
999 the_insn
.reloc
= RELOC_BASE13
;
1007 if ((c
= s
[1]) == 'h' && s
[2] == 'i') {
1008 the_insn
.reloc
= RELOC_HI22
;
1010 } else if (c
== 'l' && s
[2] == 'o') {
1011 the_insn
.reloc
= RELOC_LO10
;
1013 /* start-sanitize-v9 */
1018 the_insn
.reloc
= RELOC_HHI22
;
1024 the_insn
.reloc
= RELOC_HLO10
;
1027 /* end-sanitize-v9 */
1031 /* Note that if the getExpression() fails, we
1032 will still have created U entries in the
1033 symbol table for the 'symbols' in the input
1034 string. Try not to create U symbols for
1037 /* This stuff checks to see if the
1038 expression ends in +%reg If it does,
1039 it removes the register from the
1040 expression, and re-sets 's' to point
1041 to the right place */
1045 for (s1
= s
; *s1
&& *s1
!= ',' && *s1
!= ']'; s1
++) ;;
1047 if (s1
!= s
&& isdigit(s1
[-1])) {
1048 if(s1
[-2] == '%' && s1
[-3] == '+') {
1051 (void) getExpression(s
);
1055 } else if (strchr("goli0123456789", s1
[-2]) && s1
[-3] == '%' && s1
[-4] == '+') {
1058 (void) getExpression(s
);
1065 (void)getExpression(s
);
1077 char *push
= input_line_pointer
;
1080 input_line_pointer
= s
;
1082 if (expression(&e
) == SEG_ABSOLUTE
) {
1083 opcode
|= e
.X_add_number
<< 5;
1084 s
= input_line_pointer
;
1085 input_line_pointer
= push
;
1090 } /* alternate space */
1093 if (strncmp(s
, "%psr", 4) == 0) {
1099 case 'q': /* floating point queue */
1100 if (strncmp(s
, "%fq", 3) == 0) {
1106 case 'Q': /* coprocessor queue */
1107 if (strncmp(s
, "%cq", 3) == 0) {
1114 if (strcmp(str
, "set") == 0) {
1115 special_case
= SPECIAL_CASE_SET
;
1117 } else if (strncmp(str
, "fdiv", 4) == 0) {
1118 special_case
= SPECIAL_CASE_FDIV
;
1124 if (strncmp(s
, "%tbr", 4) != 0)
1130 if (strncmp(s
, "%wim", 4) != 0)
1136 if (strncmp(s
, "%y", 2) != 0)
1142 as_fatal("failed sanity check.");
1143 } /* switch on arg code */
1145 } /* for each arg that we expect */
1148 /* Args don't match. */
1149 if (((unsigned) (&insn
[1] - sparc_opcodes
)) < NUMOPCODES
1150 && !strcmp(insn
->name
, insn
[1].name
)) {
1155 as_bad("Illegal operands%s", error_message
);
1159 if (insn
->architecture
> current_architecture
) {
1160 if (!architecture_requested
|| warn_on_bump
) {
1163 as_warn("architecture bumped from \"%s\" to \"%s\" on \"%s\"",
1164 architecture_pname
[current_architecture
],
1165 architecture_pname
[insn
->architecture
],
1169 current_architecture
= insn
->architecture
;
1171 as_bad("architecture mismatch on \"%s\" (\"%s\"). current architecture is \"%s\"",
1173 architecture_pname
[insn
->architecture
],
1174 architecture_pname
[current_architecture
]);
1176 } /* if bump ok else error */
1177 } /* if architecture higher */
1181 } /* forever looking for a match */
1183 the_insn
.opcode
= opcode
;
1187 static int getExpression(str
)
1193 save_in
= input_line_pointer
;
1194 input_line_pointer
= str
;
1195 switch (seg
= expression(&the_insn
.exp
)) {
1202 case SEG_DIFFERENCE
:
1208 the_insn
.error
= "bad segment";
1209 expr_end
= input_line_pointer
;
1210 input_line_pointer
=save_in
;
1213 expr_end
= input_line_pointer
;
1214 input_line_pointer
= save_in
;
1216 } /* getExpression() */
1220 This is identical to the md_atof in m68k.c. I think this is right,
1223 Turn a string in input_line_pointer into a floating point constant of type
1224 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1225 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
1228 /* Equal to MAX_PRECISION in atof-ieee.c */
1229 #define MAX_LITTLENUMS 6
1231 char *md_atof(type
,litP
,sizeP
)
1237 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
1238 LITTLENUM_TYPE
*wordP
;
1270 return "Bad call to MD_ATOF()";
1272 t
=atof_ieee(input_line_pointer
,type
,words
);
1274 input_line_pointer
=t
;
1275 *sizeP
=prec
* sizeof(LITTLENUM_TYPE
);
1276 for(wordP
=words
;prec
--;) {
1277 md_number_to_chars(litP
,(long)(*wordP
++),sizeof(LITTLENUM_TYPE
));
1278 litP
+=sizeof(LITTLENUM_TYPE
);
1280 return ""; /* Someone should teach Dean about null pointers */
1284 * Write out big-endian.
1286 void md_number_to_chars(buf
,val
,n
)
1304 as_fatal("failed sanity check.");
1307 } /* md_number_to_chars() */
1309 /* Apply a fixS to the frags, now that we know the value it ought to
1312 void md_apply_fix(fixP
, val
)
1316 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
1318 assert(fixP
->fx_size
== 4);
1319 assert(fixP
->fx_r_type
< NO_RELOC
);
1321 fixP
->fx_addnumber
= val
; /* Remember value for emit_reloc */
1324 * This is a hack. There should be a better way to
1327 if (fixP
->fx_r_type
== RELOC_WDISP30
&& fixP
->fx_addsy
) {
1328 val
+= fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
1331 switch (fixP
->fx_r_type
) {
1334 buf
[0] = 0; /* val >> 24; */
1335 buf
[1] = 0; /* val >> 16; */
1336 buf
[2] = 0; /* val >> 8; */
1337 buf
[3] = 0; /* val; */
1341 case RELOC_8
: /* These don't seem to ever be needed. */
1348 val
= (val
>>= 2) + 1;
1349 buf
[0] |= (val
>> 24) & 0x3f;
1350 buf
[1]= (val
>> 16);
1355 /* start-sanitize-v9 */
1358 if (((val
> 0) && (val
& ~0x7ff))
1359 || ((val
< 0) && (~(val
- 1) & ~0x7ff))) {
1360 as_bad("relocation overflow.");
1363 buf
[2] = (val
>> 8) & 0x7;
1364 buf
[3] = val
& 0xff;
1367 case RELOC_WDISP2_14
:
1368 if (((val
> 0) && (val
& ~0x3fffc))
1369 || ((val
< 0) && (~(val
- 1) & ~0x3fffc))) {
1370 as_bad("relocation overflow.");
1373 val
= (val
>>= 2) + 1;
1374 buf
[1] |= ((val
>> 14) & 0x3) << 3;
1375 buf
[2] |= (val
>> 8) & 0x3f ;
1376 buf
[3] = val
& 0xff;
1380 if (((val
> 0) && (val
& ~0x1ffffc))
1381 || ((val
< 0) && (~(val
- 1) & ~0x1ffffc))) {
1382 as_bad("relocation overflow.");
1385 val
= (val
>>= 2) + 1;
1386 buf
[1] |= (val
>> 16) & 0x7;
1387 buf
[2] = (val
>> 8) & 0xff;
1388 buf
[3] = val
& 0xff;
1393 /* intentional fallthrough */
1395 /* end-sanitize-v9 */
1398 if(!fixP
->fx_addsy
) {
1399 buf
[1] |= (val
>> 26) & 0x3f;
1409 if (val
& ~0x003fffff) {
1410 as_bad("relocation overflow");
1412 buf
[1] |= (val
>> 16) & 0x3f;
1414 buf
[3] = val
& 0xff;
1418 if (val
& ~0x00001fff) {
1419 as_bad("relocation overflow");
1421 buf
[2] = (val
>> 8) & 0x1f;
1422 buf
[3] = val
& 0xff;
1425 /* start-sanitize-v9 */
1429 /* intentional fallthrough */
1431 /* end-sanitize-v9 */
1434 if(!fixP
->fx_addsy
) {
1435 buf
[2] |= (val
>> 8) & 0x03;
1441 case RELOC_SFA_BASE
:
1442 case RELOC_SFA_OFF13
:
1446 buf
[2] |= (val
>> 8) & 0x1f;
1451 val
= (val
>>= 2) + 1;
1454 buf
[1] |= (val
>> 16) & 0x3f;
1463 case RELOC_SEGOFF16
:
1464 case RELOC_GLOB_DAT
:
1465 case RELOC_JMP_SLOT
:
1466 case RELOC_RELATIVE
:
1471 as_bad("bad relocation type: 0x%02x", fixP
->fx_r_type
);
1474 } /* md_apply_fix() */
1476 /* should never be called for sparc */
1477 void md_create_short_jump(ptr
, from_addr
, to_addr
, frag
, to_symbol
)
1484 as_fatal("sparc_create_short_jmp\n");
1485 } /* md_create_short_jump() */
1487 /* Translate internal representation of relocation info to target format.
1489 On sparc: first 4 bytes are normal unsigned long address, next three
1490 bytes are index, most sig. byte first. Byte 7 is broken up with
1491 bit 7 as external, bits 6 & 5 unused, and the lower
1492 five bits as relocation type. Next 4 bytes are long addend. */
1493 /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
1494 void tc_aout_fix_to_chars(where
, fixP
, segment_address_in_file
)
1497 relax_addressT segment_address_in_file
;
1504 know(fixP
->fx_addsy
);
1506 if ((S_GET_TYPE(fixP
->fx_addsy
)) == N_UNDF
) {
1508 r_index
= fixP
->fx_addsy
->sy_number
;
1511 r_index
= S_GET_TYPE(fixP
->fx_addsy
);
1515 md_number_to_chars(where
,
1516 r_address
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
- segment_address_in_file
,
1519 /* now the fun stuff */
1520 where
[4] = (r_index
>> 16) & 0x0ff;
1521 where
[5] = (r_index
>> 8) & 0x0ff;
1522 where
[6] = r_index
& 0x0ff;
1523 where
[7] = ((r_extern
<< 7) & 0x80) | (0 & 0x60) | (fixP
->fx_r_type
& 0x1F);
1526 if (fixP
->fx_addsy
->sy_frag
) {
1527 r_addend
= fixP
->fx_addsy
->sy_frag
->fr_address
;
1530 if (fixP
->fx_pcrel
) {
1531 r_addend
-= r_address
;
1533 r_addend
= fixP
->fx_addnumber
;
1536 md_number_to_chars(&where
[8], r_addend
, 4);
1539 } /* tc_aout_fix_to_chars() */
1541 /* should never be called for sparc */
1542 void md_convert_frag(headers
, fragP
)
1543 object_headers
*headers
;
1544 register fragS
*fragP
;
1546 as_fatal("sparc_convert_frag\n");
1547 } /* md_convert_frag() */
1549 /* should never be called for sparc */
1550 void md_create_long_jump(ptr
, from_addr
, to_addr
, frag
, to_symbol
)
1552 long from_addr
, to_addr
;
1556 as_fatal("sparc_create_long_jump\n");
1557 } /* md_create_long_jump() */
1559 /* should never be called for sparc */
1560 int md_estimate_size_before_relax(fragP
, segtype
)
1564 as_fatal("sparc_estimate_size_before_relax\n");
1566 } /* md_estimate_size_before_relax() */
1569 /* for debugging only */
1570 static void print_insn(insn
)
1571 struct sparc_it
*insn
;
1602 fprintf(stderr
, "ERROR: %s\n");
1604 fprintf(stderr
, "opcode=0x%08x\n", insn
->opcode
);
1605 fprintf(stderr
, "reloc = %s\n", Reloc
[insn
->reloc
]);
1606 fprintf(stderr
, "exp = {
1608 fprintf(stderr
, "\t\tX_add_symbol = %s\n",
1609 ((insn
->exp
.X_add_symbol
!= NULL
)
1610 ? ((S_GET_NAME(insn
->exp
.X_add_symbol
) != NULL
)
1611 ? S_GET_NAME(insn
->exp
.X_add_symbol
)
1614 fprintf(stderr
, "\t\tX_sub_symbol = %s\n",
1615 ((insn
->exp
.X_subtract_symbol
!= NULL
)
1616 ? (S_GET_NAME(insn
->exp
.X_subtract_symbol
)
1617 ? S_GET_NAME(insn
->exp
.X_subtract_symbol
)
1620 fprintf(stderr
, "\t\tX_add_number = %d\n",
1621 insn
->exp
.X_add_number
);
1622 fprintf(stderr
, "}\n");
1624 } /* print_insn() */
1627 /* Set the hook... */
1629 /* void emit_sparc_reloc();
1630 void (*md_emit_relocations)() = emit_sparc_reloc; */
1635 * Sparc/AM29K relocations are completely different, so it needs
1636 * this machine dependent routine to emit them.
1638 #if defined(OBJ_AOUT) || defined(OBJ_BOUT)
1639 void emit_sparc_reloc(fixP
, segment_address_in_file
)
1640 register fixS
*fixP
;
1641 relax_addressT segment_address_in_file
;
1643 struct reloc_info_generic ri
;
1644 register symbolS
*symbolP
;
1645 extern char *next_object_file_charP
;
1646 /* long add_number; */
1648 memset((char *) &ri
, '\0', sizeof(ri
));
1649 for (; fixP
; fixP
= fixP
->fx_next
) {
1651 if (fixP
->fx_r_type
>= NO_RELOC
) {
1652 as_fatal("fixP->fx_r_type = %d\n", fixP
->fx_r_type
);
1655 if ((symbolP
= fixP
->fx_addsy
) != NULL
) {
1656 ri
.r_address
= fixP
->fx_frag
->fr_address
+
1657 fixP
->fx_where
- segment_address_in_file
;
1658 if ((S_GET_TYPE(symbolP
)) == N_UNDF
) {
1660 ri
.r_index
= symbolP
->sy_number
;
1663 ri
.r_index
= S_GET_TYPE(symbolP
);
1665 if (symbolP
&& symbolP
->sy_frag
) {
1666 ri
.r_addend
= symbolP
->sy_frag
->fr_address
;
1668 ri
.r_type
= fixP
->fx_r_type
;
1669 if (fixP
->fx_pcrel
) {
1670 /* ri.r_addend -= fixP->fx_where; */
1671 ri
.r_addend
-= ri
.r_address
;
1673 ri
.r_addend
= fixP
->fx_addnumber
;
1676 md_ri_to_chars(next_object_file_charP
, &ri
);
1677 next_object_file_charP
+= md_reloc_size
;
1681 } /* emit_sparc_reloc() */
1682 #endif /* aout or bout */
1683 #endif /* comment */
1687 * Invocation line includes a switch not recognized by the base assembler.
1688 * See if it's a processor-specific option. These are:
1691 * Warn on architecture bumps. See also -A.
1694 * Select the architecture. Instructions or features not
1695 * supported by the selected architecture cause fatal errors.
1697 * The default is to start at v6, and bump the architecture up
1698 * whenever an instruction is seen at a higher level.
1700 * If -bump is specified, a warning is printing when bumping to
1703 * If an architecture is specified, all instructions must match
1704 * that architecture. Any higher level instructions are flagged
1707 * if both an architecture and -bump are specified, the
1708 * architecture starts at the specified level, but bumps are
1712 /* start-sanitize-v9 */
1713 /* There is also a -Av9 architecture option. xoxorich. */
1714 /* end-sanitize-v9 */
1715 int md_parse_option(argP
, cntP
, vecP
)
1723 if (!strcmp(*argP
,"bump")){
1726 } else if (**argP
== 'A'){
1729 for (arch
= architecture_pname
; *arch
!= NULL
; ++arch
){
1730 if (strcmp(p
, *arch
) == 0){
1732 } /* found a match */
1733 } /* walk the pname table */
1736 as_bad("unknown architecture: %s", p
);
1738 current_architecture
= (enum sparc_architecture
) (arch
- architecture_pname
);
1739 architecture_requested
= 1;
1742 /* Unknown option */
1746 **argP
= '\0'; /* Done parsing this switch */
1748 } /* md_parse_option() */
1750 /* We have no need to default values of symbols. */
1753 symbolS
*md_undefined_symbol(name
)
1757 } /* md_undefined_symbol() */
1759 /* Parse an operand that is machine-specific.
1760 We just return without modifying the expression if we have nothing
1764 void md_operand(expressionP
)
1765 expressionS
*expressionP
;
1767 } /* md_operand() */
1769 /* Round up a section size to the appropriate boundary. */
1770 long md_section_align (segment
, size
)
1774 return (size
+ 7) & ~7; /* Round all sects to multiple of 8 */
1775 } /* md_section_align() */
1777 /* Exactly what point is a PC-relative offset relative TO?
1778 On the sparc, they're relative to the address of the offset, plus
1779 its size. This gets us to the following instruction.
1780 (??? Is this right? FIXME-SOON) */
1781 long md_pcrel_from(fixP
)
1784 return fixP
->fx_size
+ fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
1785 } /* md_pcrel_from() */
1787 void tc_aout_pre_write_hook(headers
)
1788 object_headers
*headers
;
1790 H_SET_VERSION(headers
, 1);
1792 } /* tc_aout_pre_write_hook() */
1801 /* end of tc-sparc.c */