ld64 with ppc
[darwin-xtools.git] / cctools / as / fixes.c
blob32a685b06f40099d2fa3930ee7651b28b05b244d
1 /* fixes.h (was taken from write.c in the original GAS)
2 Copyright (C) 1986,1987 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)
9 any later version.
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 /* FROM line 25 */
21 #include "as.h"
23 #include "sections.h"
24 #include "obstack.h"
25 #include "frags.h"
26 #include "fixes.h"
27 #include "symbols.h"
28 #include "input-scrub.h"
29 #include <mach-o/x86_64/reloc.h>
32 static fixS *
33 fix_new_internal (fragS *frag, /* Which frag? */
34 int where, /* where in that frag? */
35 int size, /* 1, 2 or 4 bytes */
36 symbolS *add_symbol, /* X_add_symbol */
37 symbolS *sub_symbol, /* X_subtract_symbol */
38 signed_target_addr_t offset, /* X_add_number */
39 int pcrel, /* TRUE if PC-relative relocation */
40 int pcrel_reloc, /* TRUE if must have relocation entry */
41 int r_type) /* relocation type */
43 struct fix *fixP;
45 fixP = (struct fix *)obstack_alloc(&notes, sizeof(struct fix));
47 fixP->fx_frag = frag;
48 fixP->fx_where = where;
49 fixP->fx_size = size;
50 fixP->fx_addsy = add_symbol;
51 fixP->fx_subsy = sub_symbol;
52 fixP->fx_offset = offset;
53 fixP->fx_pcrel = pcrel;
54 fixP->fx_pcrel_reloc = pcrel_reloc;
55 fixP->fx_r_type = r_type;
56 fixP->fx_sectdiff_divide_by_two = 0;
57 #if defined(I386) && defined(ARCH64)
58 if(fixP->fx_r_type == X86_64_RELOC_SIGNED){
59 switch(offset){
60 case -1:
61 fixP->fx_r_type = X86_64_RELOC_SIGNED_1;
62 break;
63 case -2:
64 fixP->fx_r_type = X86_64_RELOC_SIGNED_2;
65 break;
66 case -4:
67 fixP->fx_r_type = X86_64_RELOC_SIGNED_4;
68 break;
69 default:
70 break;
73 if(fixP->fx_r_type == X86_64_RELOC_GOT ||
74 fixP->fx_r_type == X86_64_RELOC_GOT_LOAD){
76 * GOT and GOT_LOAD relocs are always PC-relative and
77 * should not be converted to non-PC-relative addressing
78 * later.
80 fixP->fx_pcrel = TRUE;
81 fixP->fx_pcrel_reloc = TRUE;
83 /* We don't need this for non-local symbols, but it doesn't hurt. */
84 fixP->fx_localsy = symbol_new("L0\002", N_SECT, frchain_now->frch_nsect,
85 0, where, frag);
86 symbol_assign_index(fixP->fx_localsy);
87 #endif
88 as_file_and_line (&fixP->file, &fixP->line);
90 fixP->fx_next = frchain_now->frch_fix_root;
91 frchain_now->frch_fix_root = fixP;
93 return fixP;
96 #include "expr.h" /* HACK */
98 * fix_new() creates a fixS in obstack 'notes'.
100 fixS *
101 fix_new(
102 fragS *frag, /* which frag? */
103 int where, /* where in that frag? */
104 int size, /* 1, 2 or 4 bytes */
105 symbolS *add_symbol, /* X_add_symbol */
106 symbolS *sub_symbol, /* X_subtract_symbol */
107 signed_target_addr_t
108 offset, /* X_add_number */
109 int pcrel, /* TRUE if PC-relative relocation */
110 int pcrel_reloc, /* TRUE if must have relocation entry */
111 int r_type) /* relocation type */
113 return fix_new_internal (frag, where, size, add_symbol,
114 sub_symbol, offset, pcrel, pcrel_reloc, r_type);
117 /* FROM write.c line 291 */
118 typedef int RELOC_ENUM;
119 #define X_op X_seg
120 #define X_op_symbol X_add_symbol
121 /* Create a fixup for an expression. Currently we only support fixups
122 for difference expressions. That is itself more than most object
123 file formats support anyhow. */
125 fixS *
126 fix_new_exp (fragS *frag, /* Which frag? */
127 int where, /* Where in that frag? */
128 int size, /* 1, 2, or 4 usually. */
129 expressionS *exp, /* Expression. */
130 int pcrel, /* TRUE if PC-relative relocation. */
131 int pcrel_reloc, /* TRUE if must have relocation entry */
132 RELOC_ENUM r_type /* Relocation type. */)
134 symbolS *add = NULL;
135 symbolS *sub = NULL;
136 offsetT off = 0;
138 switch (exp->X_op)
140 #ifdef NOTYET
141 case O_absent:
142 break;
144 case O_register:
145 as_bad (_("register value used as expression"));
146 break;
148 case O_add:
149 /* This comes up when _GLOBAL_OFFSET_TABLE_+(.-L0) is read, if
150 the difference expression cannot immediately be reduced. */
152 symbolS *stmp = make_expr_symbol (exp);
154 exp->X_op = O_symbol;
155 exp->X_op_symbol = 0;
156 exp->X_add_symbol = stmp;
157 exp->X_add_number = 0;
159 return fix_new_exp (frag, where, size, exp, pcrel, r_type);
162 case O_symbol_rva:
163 add = exp->X_add_symbol;
164 off = exp->X_add_number;
166 #if defined(BFD_ASSEMBLER)
167 r_type = BFD_RELOC_RVA;
168 #else
169 #if defined(TC_RVA_RELOC)
170 r_type = TC_RVA_RELOC;
171 #else
172 as_fatal (_("rva not supported"));
173 #endif
174 #endif
175 break;
177 case O_uminus:
178 sub = exp->X_add_symbol;
179 off = exp->X_add_number;
180 break;
182 case O_subtract:
183 sub = exp->X_op_symbol;
184 /* Fall through. */
185 #endif
186 case O_symbol:
187 add = exp->X_add_symbol;
188 /* Fall through. */
189 case O_constant:
190 off = exp->X_add_number;
191 break;
193 default:
194 add = make_expr_symbol (exp);
195 break;
198 return fix_new_internal (frag, where, size, add, sub, off, pcrel, pcrel_reloc, r_type);