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 1, 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 const relax_typeS md_relax_table
[] = {
46 /* handle of the OPCODE hash table */
47 static struct hash_control
*op_hash
= NULL
;
49 static void s_seg(), s_proc(), s_data1(), s_reserve(), s_common();
50 extern void s_globl(), s_long(), s_short(), s_space(), cons();
51 extern void s_align_bytes(), s_ignore();
53 const pseudo_typeS md_pseudo_table
[] = {
54 { "align", s_align_bytes
, 0 }, /* Defaulting is invalid (0) */
55 { "common", s_common
, 0 },
56 { "global", s_globl
, 0 },
58 { "optim", s_ignore
, 0 },
59 { "proc", s_proc
, 0 },
60 { "reserve", s_reserve
, 0 },
62 { "skip", s_space
, 0 },
67 int md_short_jump_size
= 4;
68 int md_long_jump_size
= 4;
69 int md_reloc_size
= 12; /* Size of relocation record */
71 /* This array holds the chars that always start a comment. If the
72 pre-processor is disabled, these aren't very useful */
73 char comment_chars
[] = "!"; /* JF removed '|' from comment_chars */
75 /* This array holds the chars that only start a comment at the beginning of
76 a line. If the line seems to have the form '# 123 filename'
77 .line and .file directives will appear in the pre-processed output */
78 /* Note that input_file.c hand checks for '#' at the beginning of the
79 first line of the input file. This is because the compiler outputs
80 #NO_APP at the beginning of its output. */
81 /* Also note that comments started like this one will always work */
82 char line_comment_chars
[] = "#";
84 /* Chars that can be used to separate mant from exp in floating point nums */
85 char EXP_CHARS
[] = "eE";
87 /* Chars that mean this number is a floating point constant */
90 char FLT_CHARS
[] = "rRsSfFdDxXpP";
92 /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
93 changed in read.c . Ideally it shouldn't have to know about it at all,
94 but nothing is ideal around here.
97 static unsigned char octal
[256];
98 #define isoctal(c) octal[c]
99 static unsigned char toHex
[256];
102 * anull bit - causes the branch delay slot instructions to not be executed
104 #define ANNUL (1 << 29)
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
)
427 struct sparc_opcode
*insn
;
429 unsigned long opcode
;
434 for (s
= str
; islower(*s
) || (*s
>= '0' && *s
<= '3'); ++s
)
451 as_bad("Unknown opcode: `%s'", str
);
454 if ((insn
= (struct sparc_opcode
*) hash_find(op_hash
, str
)) == NULL
) {
455 as_bad("Unknown opcode: `%s'", str
);
463 opcode
= insn
->match
;
464 bzero(&the_insn
, sizeof(the_insn
));
465 the_insn
.reloc
= NO_RELOC
;
468 * Build the opcode, checking as we go to make
469 * sure that the operands match
471 for (args
= insn
->args
; ; ++args
) {
474 case '\0': /* end of args */
490 case '[': /* these must match exactly */
498 case '#': /* must be at least one digit */
500 while (isdigit(*s
)) {
507 case 'C': /* coprocessor state register */
508 if (strncmp(s
, "%csr", 4) == 0) {
514 case 'b': /* next operand is a coprocessor register */
517 if (*s
++ == '%' && *s
++ == 'c' && isdigit(*s
)) {
520 mask
= 10 * (mask
- '0') + (*s
++ - '0');
530 opcode
|= mask
<< 14;
538 opcode
|= mask
<< 25;
544 case 'r': /* next operand must be a register */
551 case 'f': /* frame pointer */
558 case 'g': /* global register */
559 if (isoctal(c
= *s
++)) {
565 case 'i': /* in register */
566 if (isoctal(c
= *s
++)) {
572 case 'l': /* local register */
573 if (isoctal(c
= *s
++)) {
574 mask
= (c
- '0' + 16) ;
579 case 'o': /* out register */
580 if (isoctal(c
= *s
++)) {
581 mask
= (c
- '0' + 8) ;
586 case 's': /* stack pointer */
593 case 'r': /* any register */
594 if (!isdigit(c
= *s
++)) {
598 case '0': case '1': case '2': case '3': case '4':
599 case '5': case '6': case '7': case '8': case '9':
601 if ((c
= 10 * (c
- '0') + (*s
++ - '0')) >= 32) {
614 * Got the register, now figure out where
615 * it goes in the opcode.
620 opcode
|= mask
<< 14;
628 opcode
|= mask
<< 25;
632 opcode
|= (mask
<< 25) | (mask
<< 14);
638 case 'e': /* next operand is a floating point register */
641 if (*s
++ == '%' && *s
++ == 'f' && isdigit(*s
)) {
644 mask
= 10 * (mask
- '0') + (*s
++ - '0');
654 opcode
|= mask
<< 14;
662 opcode
|= mask
<< 25;
669 if (strncmp(s
, "%fsr", 4) == 0) {
675 case 'h': /* high 22 bits */
676 the_insn
.reloc
= RELOC_HI22
;
679 case 'l': /* 22 bit PC relative immediate */
680 the_insn
.reloc
= RELOC_WDISP22
;
684 case 'L': /* 30 bit immediate */
685 the_insn
.reloc
= RELOC_WDISP30
;
689 case 'i': /* 13 bit immediate */
690 the_insn
.reloc
= RELOC_BASE13
;
698 if ((c
= s
[1]) == 'h' && s
[2] == 'i') {
699 the_insn
.reloc
= RELOC_HI22
;
701 } else if (c
== 'l' && s
[2] == 'o') {
702 the_insn
.reloc
= RELOC_LO10
;
707 /* Note that if the getExpression() fails, we will still have
708 created U entries in the symbol table for the 'symbols'
709 in the input string. Try not to create U symbols for
712 /* This stuff checks to see if the expression ends
713 in +%reg If it does, it removes the register from
714 the expression, and re-sets 's' to point to the
719 for(s1
=s
;*s1
&& *s1
!=','&& *s1
!=']';s1
++)
722 if(s1
!=s
&& isdigit(s1
[-1])) {
723 if(s1
[-2]=='%' && s1
[-3]=='+') {
726 (void)getExpression(s
);
730 } else if(strchr("goli0123456789",s1
[-2]) && s1
[-3]=='%' && s1
[-4]=='+') {
733 (void)getExpression(s
);
740 (void)getExpression(s
);
751 case 'A': /* alternate space */
756 while (isdigit(*s
)) {
757 num
= num
*10 + *s
-'0';
767 if (strncmp(s
, "%psr", 4) == 0) {
773 case 'q': /* floating point queue */
774 if (strncmp(s
, "%fq", 3) == 0) {
780 case 'Q': /* coprocessor queue */
781 if (strncmp(s
, "%cq", 3) == 0) {
788 if (strcmp(str
, "set") == 0) {
789 special_case
= SPECIAL_CASE_SET
;
791 } else if (strncmp(str
, "fdiv", 4) == 0) {
792 special_case
= SPECIAL_CASE_FDIV
;
798 if (strncmp(s
, "%tbr", 4) != 0)
804 if (strncmp(s
, "%wim", 4) != 0)
810 if (strncmp(s
, "%y", 2) != 0)
817 } /* switch on arg code */
819 } /* for each arg that we expect */
822 /* Args don't match. */
823 if (((unsigned) (&insn
[1] - sparc_opcodes
)) < NUMOPCODES
824 && !strcmp(insn
->name
, insn
[1].name
)) {
831 as_bad("Illegal operands");
838 the_insn
.opcode
= opcode
;
842 static int getExpression(str
)
848 save_in
= input_line_pointer
;
849 input_line_pointer
= str
;
850 switch (seg
= expression(&the_insn
.exp
)) {
863 the_insn
.error
= "bad segment";
864 expr_end
= input_line_pointer
;
865 input_line_pointer
=save_in
;
868 expr_end
= input_line_pointer
;
869 input_line_pointer
= save_in
;
871 } /* getExpression() */
875 This is identical to the md_atof in m68k.c. I think this is right,
878 Turn a string in input_line_pointer into a floating point constant of type
879 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
880 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
883 /* Equal to MAX_PRECISION in atof-ieee.c */
884 #define MAX_LITTLENUMS 6
886 char *md_atof(type
,litP
,sizeP
)
892 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
893 LITTLENUM_TYPE
*wordP
;
925 return "Bad call to MD_ATOF()";
927 t
=atof_ieee(input_line_pointer
,type
,words
);
929 input_line_pointer
=t
;
930 *sizeP
=prec
* sizeof(LITTLENUM_TYPE
);
931 for(wordP
=words
;prec
--;) {
932 md_number_to_chars(litP
,(long)(*wordP
++),sizeof(LITTLENUM_TYPE
));
933 litP
+=sizeof(LITTLENUM_TYPE
);
935 return ""; /* Someone should teach Dean about null pointers */
939 * Write out big-endian.
941 void md_number_to_chars(buf
,val
,n
)
962 } /* md_number_to_chars() */
964 /* Apply a fixS to the frags, now that we know the value it ought to
967 void md_apply_fix(fixP
, val
)
971 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
973 assert(fixP
->fx_size
== 4);
974 assert(fixP
->fx_r_type
< NO_RELOC
);
976 fixP
->fx_addnumber
= val
; /* Remember value for emit_reloc */
979 * This is a hack. There should be a better way to
982 if (fixP
->fx_r_type
== RELOC_WDISP30
&& fixP
->fx_addsy
) {
983 val
+= fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
986 switch (fixP
->fx_r_type
) {
989 buf
[0] = 0; /* val >> 24; */
990 buf
[1] = 0; /* val >> 16; */
991 buf
[2] = 0; /* val >> 8; */
992 buf
[3] = 0; /* val; */
996 case RELOC_8
: /* These don't seem to ever be needed. */
1003 val
= (val
>>= 2) + 1;
1004 buf
[0] |= (val
>> 24) & 0x3f;
1005 buf
[1]= (val
>> 16);
1011 if(!fixP
->fx_addsy
) {
1012 buf
[1] |= (val
>> 26) & 0x3f;
1025 if(!fixP
->fx_addsy
) {
1026 buf
[2] |= (val
>> 8) & 0x03;
1032 case RELOC_SFA_BASE
:
1033 case RELOC_SFA_OFF13
:
1037 buf
[2] |= (val
>> 8) & 0x1f;
1042 val
= (val
>>= 2) + 1;
1045 buf
[1] |= (val
>> 16) & 0x3f;
1054 case RELOC_SEGOFF16
:
1055 case RELOC_GLOB_DAT
:
1056 case RELOC_JMP_SLOT
:
1057 case RELOC_RELATIVE
:
1062 as_bad("bad relocation type: 0x%02x", fixP
->fx_r_type
);
1065 } /* md_apply_fix() */
1067 /* should never be called for sparc */
1068 void md_create_short_jump(ptr
, from_addr
, to_addr
, frag
, to_symbol
)
1075 fprintf(stderr
, "sparc_create_short_jmp\n");
1077 } /* md_create_short_jump() */
1079 /* Translate internal representation of relocation info to target format.
1081 On sparc: first 4 bytes are normal unsigned long address, next three
1082 bytes are index, most sig. byte first. Byte 7 is broken up with
1083 bit 7 as external, bits 6 & 5 unused, and the lower
1084 five bits as relocation type. Next 4 bytes are long addend. */
1085 /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
1086 void md_ri_to_chars(the_bytes
, ri
)
1088 struct reloc_info_generic
*ri
;
1091 md_number_to_chars(the_bytes
, ri
->r_address
, 4);
1092 /* now the fun stuff */
1093 the_bytes
[4] = (ri
->r_index
>> 16) & 0x0ff;
1094 the_bytes
[5] = (ri
->r_index
>> 8) & 0x0ff;
1095 the_bytes
[6] = ri
->r_index
& 0x0ff;
1096 the_bytes
[7] = ((ri
->r_extern
<< 7) & 0x80) | (0 & 0x60) | (ri
->r_type
& 0x1F);
1098 md_number_to_chars(&the_bytes
[8], ri
->r_addend
, 4);
1099 } /* md_ri_to_chars() */
1101 /* should never be called for sparc */
1102 void md_convert_frag(fragP
)
1103 register fragS
*fragP
;
1105 fprintf(stderr
, "sparc_convert_frag\n");
1107 } /* md_convert_frag() */
1109 /* should never be called for sparc */
1110 void md_create_long_jump(ptr
, from_addr
, to_addr
, frag
, to_symbol
)
1112 long from_addr
, to_addr
;
1116 fprintf(stderr
, "sparc_create_long_jump\n");
1118 } /* md_create_long_jump() */
1120 /* should never be called for sparc */
1121 int md_estimate_size_before_relax(fragP
, segtype
)
1125 fprintf(stderr
, "sparc_estimate_size_before_relax\n");
1128 } /* md_estimate_size_before_relax() */
1131 /* for debugging only */
1132 static void print_insn(insn
)
1133 struct sparc_it
*insn
;
1164 fprintf(stderr
, "ERROR: %s\n");
1166 fprintf(stderr
, "opcode=0x%08x\n", insn
->opcode
);
1167 fprintf(stderr
, "reloc = %s\n", Reloc
[insn
->reloc
]);
1168 fprintf(stderr
, "exp = {
1170 fprintf(stderr
, "\t\tX_add_symbol = %s\n",
1171 ((insn
->exp
.X_add_symbol
!= NULL
)
1172 ? ((S_GET_NAME(insn
->exp
.X_add_symbol
) != NULL
)
1173 ? S_GET_NAME(insn
->exp
.X_add_symbol
)
1176 fprintf(stderr
, "\t\tX_sub_symbol = %s\n",
1177 ((insn
->exp
.X_subtract_symbol
!= NULL
)
1178 ? (S_GET_NAME(insn
->exp
.X_subtract_symbol
)
1179 ? S_GET_NAME(insn
->exp
.X_subtract_symbol
)
1182 fprintf(stderr
, "\t\tX_add_number = %d\n",
1183 insn
->exp
.X_add_number
);
1184 fprintf(stderr
, "}\n");
1186 } /* print_insn() */
1189 /* Set the hook... */
1191 void emit_sparc_reloc();
1192 void (*md_emit_relocations
)() = emit_sparc_reloc
;
1195 * Sparc/AM29K relocations are completely different, so it needs
1196 * this machine dependent routine to emit them.
1198 #if defined(OBJ_AOUT) || defined(OBJ_BOUT)
1199 void emit_sparc_reloc(fixP
, segment_address_in_file
)
1200 register fixS
*fixP
;
1201 relax_addressT segment_address_in_file
;
1203 struct reloc_info_generic ri
;
1204 register symbolS
*symbolP
;
1205 extern char *next_object_file_charP
;
1206 /* long add_number; */
1208 bzero((char *) &ri
, sizeof(ri
));
1209 for (; fixP
; fixP
= fixP
->fx_next
) {
1211 if (fixP
->fx_r_type
>= NO_RELOC
) {
1212 fprintf(stderr
, "fixP->fx_r_type = %d\n", fixP
->fx_r_type
);
1216 if ((symbolP
= fixP
->fx_addsy
) != NULL
) {
1217 ri
.r_address
= fixP
->fx_frag
->fr_address
+
1218 fixP
->fx_where
- segment_address_in_file
;
1219 if ((S_GET_TYPE(symbolP
)) == N_UNDF
) {
1221 ri
.r_index
= symbolP
->sy_number
;
1224 ri
.r_index
= S_GET_TYPE(symbolP
);
1226 if (symbolP
&& symbolP
->sy_frag
) {
1227 ri
.r_addend
= symbolP
->sy_frag
->fr_address
;
1229 ri
.r_type
= fixP
->fx_r_type
;
1230 if (fixP
->fx_pcrel
) {
1231 /* ri.r_addend -= fixP->fx_where; */
1232 ri
.r_addend
-= ri
.r_address
;
1234 ri
.r_addend
= fixP
->fx_addnumber
;
1237 md_ri_to_chars(next_object_file_charP
, &ri
);
1238 next_object_file_charP
+= md_reloc_size
;
1242 } /* emit_sparc_reloc() */
1243 #endif /* aout or bout */
1245 int md_parse_option(argP
,cntP
,vecP
)
1251 } /* md_parse_option() */
1253 /* We have no need to default values of symbols. */
1256 symbolS
*md_undefined_symbol(name
)
1260 } /* md_undefined_symbol() */
1262 /* Parse an operand that is machine-specific.
1263 We just return without modifying the expression if we have nothing
1267 void md_operand(expressionP
)
1268 expressionS
*expressionP
;
1270 } /* md_operand() */
1272 /* Round up a section size to the appropriate boundary. */
1273 long md_section_align (segment
, size
)
1277 return (size
+ 7) & ~7; /* Round all sects to multiple of 8 */
1278 } /* md_section_align() */
1280 /* Exactly what point is a PC-relative offset relative TO?
1281 On the sparc, they're relative to the address of the offset, plus
1282 its size. This gets us to the following instruction.
1283 (??? Is this right? FIXME-SOON) */
1284 long md_pcrel_from(fixP
)
1287 return fixP
->fx_size
+ fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
1288 } /* md_pcrel_from() */
1297 /* end of tp-sparc.c */