1 | /* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000)
|
---|
2 | Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
|
---|
3 | Free Software Foundation, Inc.
|
---|
4 | Written by Ian Lance Taylor, Cygnus Support.
|
---|
5 |
|
---|
6 | This file is part of GAS, the GNU Assembler.
|
---|
7 |
|
---|
8 | GAS is free software; you can redistribute it and/or modify
|
---|
9 | it under the terms of the GNU General Public License as published by
|
---|
10 | the Free Software Foundation; either version 2, or (at your option)
|
---|
11 | any later version.
|
---|
12 |
|
---|
13 | GAS is distributed in the hope that it will be useful,
|
---|
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
16 | GNU General Public License for more details.
|
---|
17 |
|
---|
18 | You should have received a copy of the GNU General Public License
|
---|
19 | along with GAS; see the file COPYING. If not, write to the Free
|
---|
20 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
---|
21 | 02111-1307, USA. */
|
---|
22 |
|
---|
23 | #include <stdio.h>
|
---|
24 | #include "as.h"
|
---|
25 | #include "safe-ctype.h"
|
---|
26 | #include "subsegs.h"
|
---|
27 |
|
---|
28 | #include "opcode/ppc.h"
|
---|
29 |
|
---|
30 | #ifdef OBJ_ELF
|
---|
31 | #include "elf/ppc.h"
|
---|
32 | #include "dwarf2dbg.h"
|
---|
33 | #endif
|
---|
34 |
|
---|
35 | #ifdef TE_PE
|
---|
36 | #include "coff/pe.h"
|
---|
37 | #endif
|
---|
38 |
|
---|
39 | /* This is the assembler for the PowerPC or POWER (RS/6000) chips. */
|
---|
40 |
|
---|
41 | /* Tell the main code what the endianness is. */
|
---|
42 | extern int target_big_endian;
|
---|
43 |
|
---|
44 | /* Whether or not, we've set target_big_endian. */
|
---|
45 | static int set_target_endian = 0;
|
---|
46 |
|
---|
47 | /* Whether to use user friendly register names. */
|
---|
48 | #ifndef TARGET_REG_NAMES_P
|
---|
49 | #ifdef TE_PE
|
---|
50 | #define TARGET_REG_NAMES_P TRUE
|
---|
51 | #else
|
---|
52 | #define TARGET_REG_NAMES_P FALSE
|
---|
53 | #endif
|
---|
54 | #endif
|
---|
55 |
|
---|
56 | /* Macros for calculating LO, HI, HA, HIGHER, HIGHERA, HIGHEST,
|
---|
57 | HIGHESTA. */
|
---|
58 |
|
---|
59 | /* #lo(value) denotes the least significant 16 bits of the indicated. */
|
---|
60 | #define PPC_LO(v) ((v) & 0xffff)
|
---|
61 |
|
---|
62 | /* #hi(value) denotes bits 16 through 31 of the indicated value. */
|
---|
63 | #define PPC_HI(v) (((v) >> 16) & 0xffff)
|
---|
64 |
|
---|
65 | /* #ha(value) denotes the high adjusted value: bits 16 through 31 of
|
---|
66 | the indicated value, compensating for #lo() being treated as a
|
---|
67 | signed number. */
|
---|
68 | #define PPC_HA(v) PPC_HI ((v) + 0x8000)
|
---|
69 |
|
---|
70 | /* #higher(value) denotes bits 32 through 47 of the indicated value. */
|
---|
71 | #define PPC_HIGHER(v) (((v) >> 16 >> 16) & 0xffff)
|
---|
72 |
|
---|
73 | /* #highera(value) denotes bits 32 through 47 of the indicated value,
|
---|
74 | compensating for #lo() being treated as a signed number. */
|
---|
75 | #define PPC_HIGHERA(v) PPC_HIGHER ((v) + 0x8000)
|
---|
76 |
|
---|
77 | /* #highest(value) denotes bits 48 through 63 of the indicated value. */
|
---|
78 | #define PPC_HIGHEST(v) (((v) >> 24 >> 24) & 0xffff)
|
---|
79 |
|
---|
80 | /* #highesta(value) denotes bits 48 through 63 of the indicated value,
|
---|
81 | compensating for #lo being treated as a signed number. */
|
---|
82 | #define PPC_HIGHESTA(v) PPC_HIGHEST ((v) + 0x8000)
|
---|
83 |
|
---|
84 | #define SEX16(val) ((((val) & 0xffff) ^ 0x8000) - 0x8000)
|
---|
85 |
|
---|
86 | static bfd_boolean reg_names_p = TARGET_REG_NAMES_P;
|
---|
87 |
|
---|
88 | static bfd_boolean register_name PARAMS ((expressionS *));
|
---|
89 | static void ppc_set_cpu PARAMS ((void));
|
---|
90 | static unsigned long ppc_insert_operand
|
---|
91 | PARAMS ((unsigned long insn, const struct powerpc_operand *operand,
|
---|
92 | offsetT val, char *file, unsigned int line));
|
---|
93 | static void ppc_macro PARAMS ((char *str, const struct powerpc_macro *macro));
|
---|
94 | static void ppc_byte PARAMS ((int));
|
---|
95 |
|
---|
96 | #if defined (OBJ_XCOFF) || defined (OBJ_ELF)
|
---|
97 | static int ppc_is_toc_sym PARAMS ((symbolS *sym));
|
---|
98 | static void ppc_tc PARAMS ((int));
|
---|
99 | static void ppc_machine PARAMS ((int));
|
---|
100 | #endif
|
---|
101 |
|
---|
102 | #ifdef OBJ_XCOFF
|
---|
103 | static void ppc_comm PARAMS ((int));
|
---|
104 | static void ppc_bb PARAMS ((int));
|
---|
105 | static void ppc_bc PARAMS ((int));
|
---|
106 | static void ppc_bf PARAMS ((int));
|
---|
107 | static void ppc_biei PARAMS ((int));
|
---|
108 | static void ppc_bs PARAMS ((int));
|
---|
109 | static void ppc_eb PARAMS ((int));
|
---|
110 | static void ppc_ec PARAMS ((int));
|
---|
111 | static void ppc_ef PARAMS ((int));
|
---|
112 | static void ppc_es PARAMS ((int));
|
---|
113 | static void ppc_csect PARAMS ((int));
|
---|
114 | static void ppc_change_csect PARAMS ((symbolS *));
|
---|
115 | static void ppc_function PARAMS ((int));
|
---|
116 | static void ppc_extern PARAMS ((int));
|
---|
117 | static void ppc_lglobl PARAMS ((int));
|
---|
118 | static void ppc_section PARAMS ((int));
|
---|
119 | static void ppc_named_section PARAMS ((int));
|
---|
120 | static void ppc_stabx PARAMS ((int));
|
---|
121 | static void ppc_rename PARAMS ((int));
|
---|
122 | static void ppc_toc PARAMS ((int));
|
---|
123 | static void ppc_xcoff_cons PARAMS ((int));
|
---|
124 | static void ppc_vbyte PARAMS ((int));
|
---|
125 | #endif
|
---|
126 |
|
---|
127 | #ifdef OBJ_ELF
|
---|
128 | static bfd_reloc_code_real_type ppc_elf_suffix PARAMS ((char **, expressionS *));
|
---|
129 | static void ppc_elf_cons PARAMS ((int));
|
---|
130 | static void ppc_elf_rdata PARAMS ((int));
|
---|
131 | static void ppc_elf_lcomm PARAMS ((int));
|
---|
132 | static void ppc_elf_validate_fix PARAMS ((fixS *, segT));
|
---|
133 | static void ppc_apuinfo_section_add PARAMS ((unsigned int apu, unsigned int version));
|
---|
134 | #endif
|
---|
135 |
|
---|
136 | #ifdef TE_PE
|
---|
137 | static void ppc_set_current_section PARAMS ((segT));
|
---|
138 | static void ppc_previous PARAMS ((int));
|
---|
139 | static void ppc_pdata PARAMS ((int));
|
---|
140 | static void ppc_ydata PARAMS ((int));
|
---|
141 | static void ppc_reldata PARAMS ((int));
|
---|
142 | static void ppc_rdata PARAMS ((int));
|
---|
143 | static void ppc_ualong PARAMS ((int));
|
---|
144 | static void ppc_znop PARAMS ((int));
|
---|
145 | static void ppc_pe_comm PARAMS ((int));
|
---|
146 | static void ppc_pe_section PARAMS ((int));
|
---|
147 | static void ppc_pe_function PARAMS ((int));
|
---|
148 | static void ppc_pe_tocd PARAMS ((int));
|
---|
149 | #endif
|
---|
150 | |
---|
151 |
|
---|
152 | /* Generic assembler global variables which must be defined by all
|
---|
153 | targets. */
|
---|
154 |
|
---|
155 | #ifdef OBJ_ELF
|
---|
156 | /* This string holds the chars that always start a comment. If the
|
---|
157 | pre-processor is disabled, these aren't very useful. The macro
|
---|
158 | tc_comment_chars points to this. We use this, rather than the
|
---|
159 | usual comment_chars, so that we can switch for Solaris conventions. */
|
---|
160 | static const char ppc_solaris_comment_chars[] = "#!";
|
---|
161 | static const char ppc_eabi_comment_chars[] = "#";
|
---|
162 |
|
---|
163 | #ifdef TARGET_SOLARIS_COMMENT
|
---|
164 | const char *ppc_comment_chars = ppc_solaris_comment_chars;
|
---|
165 | #else
|
---|
166 | const char *ppc_comment_chars = ppc_eabi_comment_chars;
|
---|
167 | #endif
|
---|
168 | #else
|
---|
169 | const char comment_chars[] = "#";
|
---|
170 | #endif
|
---|
171 |
|
---|
172 | /* Characters which start a comment at the beginning of a line. */
|
---|
173 | const char line_comment_chars[] = "#";
|
---|
174 |
|
---|
175 | /* Characters which may be used to separate multiple commands on a
|
---|
176 | single line. */
|
---|
177 | const char line_separator_chars[] = ";";
|
---|
178 |
|
---|
179 | /* Characters which are used to indicate an exponent in a floating
|
---|
180 | point number. */
|
---|
181 | const char EXP_CHARS[] = "eE";
|
---|
182 |
|
---|
183 | /* Characters which mean that a number is a floating point constant,
|
---|
184 | as in 0d1.0. */
|
---|
185 | const char FLT_CHARS[] = "dD";
|
---|
186 | |
---|
187 |
|
---|
188 | /* The target specific pseudo-ops which we support. */
|
---|
189 |
|
---|
190 | const pseudo_typeS md_pseudo_table[] =
|
---|
191 | {
|
---|
192 | /* Pseudo-ops which must be overridden. */
|
---|
193 | { "byte", ppc_byte, 0 },
|
---|
194 |
|
---|
195 | #ifdef OBJ_XCOFF
|
---|
196 | /* Pseudo-ops specific to the RS/6000 XCOFF format. Some of these
|
---|
197 | legitimately belong in the obj-*.c file. However, XCOFF is based
|
---|
198 | on COFF, and is only implemented for the RS/6000. We just use
|
---|
199 | obj-coff.c, and add what we need here. */
|
---|
200 | { "comm", ppc_comm, 0 },
|
---|
201 | { "lcomm", ppc_comm, 1 },
|
---|
202 | { "bb", ppc_bb, 0 },
|
---|
203 | { "bc", ppc_bc, 0 },
|
---|
204 | { "bf", ppc_bf, 0 },
|
---|
205 | { "bi", ppc_biei, 0 },
|
---|
206 | { "bs", ppc_bs, 0 },
|
---|
207 | { "csect", ppc_csect, 0 },
|
---|
208 | { "data", ppc_section, 'd' },
|
---|
209 | { "eb", ppc_eb, 0 },
|
---|
210 | { "ec", ppc_ec, 0 },
|
---|
211 | { "ef", ppc_ef, 0 },
|
---|
212 | { "ei", ppc_biei, 1 },
|
---|
213 | { "es", ppc_es, 0 },
|
---|
214 | { "extern", ppc_extern, 0 },
|
---|
215 | { "function", ppc_function, 0 },
|
---|
216 | { "lglobl", ppc_lglobl, 0 },
|
---|
217 | { "rename", ppc_rename, 0 },
|
---|
218 | { "section", ppc_named_section, 0 },
|
---|
219 | { "stabx", ppc_stabx, 0 },
|
---|
220 | { "text", ppc_section, 't' },
|
---|
221 | { "toc", ppc_toc, 0 },
|
---|
222 | { "long", ppc_xcoff_cons, 2 },
|
---|
223 | { "llong", ppc_xcoff_cons, 3 },
|
---|
224 | { "word", ppc_xcoff_cons, 1 },
|
---|
225 | { "short", ppc_xcoff_cons, 1 },
|
---|
226 | { "vbyte", ppc_vbyte, 0 },
|
---|
227 | #endif
|
---|
228 |
|
---|
229 | #ifdef OBJ_ELF
|
---|
230 | { "llong", ppc_elf_cons, 8 },
|
---|
231 | { "quad", ppc_elf_cons, 8 },
|
---|
232 | { "long", ppc_elf_cons, 4 },
|
---|
233 | { "word", ppc_elf_cons, 2 },
|
---|
234 | { "short", ppc_elf_cons, 2 },
|
---|
235 | { "rdata", ppc_elf_rdata, 0 },
|
---|
236 | { "rodata", ppc_elf_rdata, 0 },
|
---|
237 | { "lcomm", ppc_elf_lcomm, 0 },
|
---|
238 | { "file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0 },
|
---|
239 | { "loc", dwarf2_directive_loc, 0 },
|
---|
240 | #endif
|
---|
241 |
|
---|
242 | #ifdef TE_PE
|
---|
243 | /* Pseudo-ops specific to the Windows NT PowerPC PE (coff) format. */
|
---|
244 | { "previous", ppc_previous, 0 },
|
---|
245 | { "pdata", ppc_pdata, 0 },
|
---|
246 | { "ydata", ppc_ydata, 0 },
|
---|
247 | { "reldata", ppc_reldata, 0 },
|
---|
248 | { "rdata", ppc_rdata, 0 },
|
---|
249 | { "ualong", ppc_ualong, 0 },
|
---|
250 | { "znop", ppc_znop, 0 },
|
---|
251 | { "comm", ppc_pe_comm, 0 },
|
---|
252 | { "lcomm", ppc_pe_comm, 1 },
|
---|
253 | { "section", ppc_pe_section, 0 },
|
---|
254 | { "function", ppc_pe_function,0 },
|
---|
255 | { "tocd", ppc_pe_tocd, 0 },
|
---|
256 | #endif
|
---|
257 |
|
---|
258 | #if defined (OBJ_XCOFF) || defined (OBJ_ELF)
|
---|
259 | { "tc", ppc_tc, 0 },
|
---|
260 | { "machine", ppc_machine, 0 },
|
---|
261 | #endif
|
---|
262 |
|
---|
263 | { NULL, NULL, 0 }
|
---|
264 | };
|
---|
265 |
|
---|
266 | |
---|
267 |
|
---|
268 | /* Predefined register names if -mregnames (or default for Windows NT).
|
---|
269 | In general, there are lots of them, in an attempt to be compatible
|
---|
270 | with a number of other Windows NT assemblers. */
|
---|
271 |
|
---|
272 | /* Structure to hold information about predefined registers. */
|
---|
273 | struct pd_reg
|
---|
274 | {
|
---|
275 | char *name;
|
---|
276 | int value;
|
---|
277 | };
|
---|
278 |
|
---|
279 | /* List of registers that are pre-defined:
|
---|
280 |
|
---|
281 | Each general register has predefined names of the form:
|
---|
282 | 1. r<reg_num> which has the value <reg_num>.
|
---|
283 | 2. r.<reg_num> which has the value <reg_num>.
|
---|
284 |
|
---|
285 | Each floating point register has predefined names of the form:
|
---|
286 | 1. f<reg_num> which has the value <reg_num>.
|
---|
287 | 2. f.<reg_num> which has the value <reg_num>.
|
---|
288 |
|
---|
289 | Each vector unit register has predefined names of the form:
|
---|
290 | 1. v<reg_num> which has the value <reg_num>.
|
---|
291 | 2. v.<reg_num> which has the value <reg_num>.
|
---|
292 |
|
---|
293 | Each condition register has predefined names of the form:
|
---|
294 | 1. cr<reg_num> which has the value <reg_num>.
|
---|
295 | 2. cr.<reg_num> which has the value <reg_num>.
|
---|
296 |
|
---|
297 | There are individual registers as well:
|
---|
298 | sp or r.sp has the value 1
|
---|
299 | rtoc or r.toc has the value 2
|
---|
300 | fpscr has the value 0
|
---|
301 | xer has the value 1
|
---|
302 | lr has the value 8
|
---|
303 | ctr has the value 9
|
---|
304 | pmr has the value 0
|
---|
305 | dar has the value 19
|
---|
306 | dsisr has the value 18
|
---|
307 | dec has the value 22
|
---|
308 | sdr1 has the value 25
|
---|
309 | srr0 has the value 26
|
---|
310 | srr1 has the value 27
|
---|
311 |
|
---|
312 | The table is sorted. Suitable for searching by a binary search. */
|
---|
313 |
|
---|
314 | static const struct pd_reg pre_defined_registers[] =
|
---|
315 | {
|
---|
316 | { "cr.0", 0 }, /* Condition Registers */
|
---|
317 | { "cr.1", 1 },
|
---|
318 | { "cr.2", 2 },
|
---|
319 | { "cr.3", 3 },
|
---|
320 | { "cr.4", 4 },
|
---|
321 | { "cr.5", 5 },
|
---|
322 | { "cr.6", 6 },
|
---|
323 | { "cr.7", 7 },
|
---|
324 |
|
---|
325 | { "cr0", 0 },
|
---|
326 | { "cr1", 1 },
|
---|
327 | { "cr2", 2 },
|
---|
328 | { "cr3", 3 },
|
---|
329 | { "cr4", 4 },
|
---|
330 | { "cr5", 5 },
|
---|
331 | { "cr6", 6 },
|
---|
332 | { "cr7", 7 },
|
---|
333 |
|
---|
334 | { "ctr", 9 },
|
---|
335 |
|
---|
336 | { "dar", 19 }, /* Data Access Register */
|
---|
337 | { "dec", 22 }, /* Decrementer */
|
---|
338 | { "dsisr", 18 }, /* Data Storage Interrupt Status Register */
|
---|
339 |
|
---|
340 | { "f.0", 0 }, /* Floating point registers */
|
---|
341 | { "f.1", 1 },
|
---|
342 | { "f.10", 10 },
|
---|
343 | { "f.11", 11 },
|
---|
344 | { "f.12", 12 },
|
---|
345 | { "f.13", 13 },
|
---|
346 | { "f.14", 14 },
|
---|
347 | { "f.15", 15 },
|
---|
348 | { "f.16", 16 },
|
---|
349 | { "f.17", 17 },
|
---|
350 | { "f.18", 18 },
|
---|
351 | { "f.19", 19 },
|
---|
352 | { "f.2", 2 },
|
---|
353 | { "f.20", 20 },
|
---|
354 | { "f.21", 21 },
|
---|
355 | { "f.22", 22 },
|
---|
356 | { "f.23", 23 },
|
---|
357 | { "f.24", 24 },
|
---|
358 | { "f.25", 25 },
|
---|
359 | { "f.26", 26 },
|
---|
360 | { "f.27", 27 },
|
---|
361 | { "f.28", 28 },
|
---|
362 | { "f.29", 29 },
|
---|
363 | { "f.3", 3 },
|
---|
364 | { "f.30", 30 },
|
---|
365 | { "f.31", 31 },
|
---|
366 | { "f.4", 4 },
|
---|
367 | { "f.5", 5 },
|
---|
368 | { "f.6", 6 },
|
---|
369 | { "f.7", 7 },
|
---|
370 | { "f.8", 8 },
|
---|
371 | { "f.9", 9 },
|
---|
372 |
|
---|
373 | { "f0", 0 },
|
---|
374 | { "f1", 1 },
|
---|
375 | { "f10", 10 },
|
---|
376 | { "f11", 11 },
|
---|
377 | { "f12", 12 },
|
---|
378 | { "f13", 13 },
|
---|
379 | { "f14", 14 },
|
---|
380 | { "f15", 15 },
|
---|
381 | { "f16", 16 },
|
---|
382 | { "f17", 17 },
|
---|
383 | { "f18", 18 },
|
---|
384 | { "f19", 19 },
|
---|
385 | { "f2", 2 },
|
---|
386 | { "f20", 20 },
|
---|
387 | { "f21", 21 },
|
---|
388 | { "f22", 22 },
|
---|
389 | { "f23", 23 },
|
---|
390 | { "f24", 24 },
|
---|
391 | { "f25", 25 },
|
---|
392 | { "f26", 26 },
|
---|
393 | { "f27", 27 },
|
---|
394 | { "f28", 28 },
|
---|
395 | { "f29", 29 },
|
---|
396 | { "f3", 3 },
|
---|
397 | { "f30", 30 },
|
---|
398 | { "f31", 31 },
|
---|
399 | { "f4", 4 },
|
---|
400 | { "f5", 5 },
|
---|
401 | { "f6", 6 },
|
---|
402 | { "f7", 7 },
|
---|
403 | { "f8", 8 },
|
---|
404 | { "f9", 9 },
|
---|
405 |
|
---|
406 | { "fpscr", 0 },
|
---|
407 |
|
---|
408 | { "lr", 8 }, /* Link Register */
|
---|
409 |
|
---|
410 | { "pmr", 0 },
|
---|
411 |
|
---|
412 | { "r.0", 0 }, /* General Purpose Registers */
|
---|
413 | { "r.1", 1 },
|
---|
414 | { "r.10", 10 },
|
---|
415 | { "r.11", 11 },
|
---|
416 | { "r.12", 12 },
|
---|
417 | { "r.13", 13 },
|
---|
418 | { "r.14", 14 },
|
---|
419 | { "r.15", 15 },
|
---|
420 | { "r.16", 16 },
|
---|
421 | { "r.17", 17 },
|
---|
422 | { "r.18", 18 },
|
---|
423 | { "r.19", 19 },
|
---|
424 | { "r.2", 2 },
|
---|
425 | { "r.20", 20 },
|
---|
426 | { "r.21", 21 },
|
---|
427 | { "r.22", 22 },
|
---|
428 | { "r.23", 23 },
|
---|
429 | { "r.24", 24 },
|
---|
430 | { "r.25", 25 },
|
---|
431 | { "r.26", 26 },
|
---|
432 | { "r.27", 27 },
|
---|
433 | { "r.28", 28 },
|
---|
434 | { "r.29", 29 },
|
---|
435 | { "r.3", 3 },
|
---|
436 | { "r.30", 30 },
|
---|
437 | { "r.31", 31 },
|
---|
438 | { "r.4", 4 },
|
---|
439 | { "r.5", 5 },
|
---|
440 | { "r.6", 6 },
|
---|
441 | { "r.7", 7 },
|
---|
442 | { "r.8", 8 },
|
---|
443 | { "r.9", 9 },
|
---|
444 |
|
---|
445 | { "r.sp", 1 }, /* Stack Pointer */
|
---|
446 |
|
---|
447 | { "r.toc", 2 }, /* Pointer to the table of contents */
|
---|
448 |
|
---|
449 | { "r0", 0 }, /* More general purpose registers */
|
---|
450 | { "r1", 1 },
|
---|
451 | { "r10", 10 },
|
---|
452 | { "r11", 11 },
|
---|
453 | { "r12", 12 },
|
---|
454 | { "r13", 13 },
|
---|
455 | { "r14", 14 },
|
---|
456 | { "r15", 15 },
|
---|
457 | { "r16", 16 },
|
---|
458 | { "r17", 17 },
|
---|
459 | { "r18", 18 },
|
---|
460 | { "r19", 19 },
|
---|
461 | { "r2", 2 },
|
---|
462 | { "r20", 20 },
|
---|
463 | { "r21", 21 },
|
---|
464 | { "r22", 22 },
|
---|
465 | { "r23", 23 },
|
---|
466 | { "r24", 24 },
|
---|
467 | { "r25", 25 },
|
---|
468 | { "r26", 26 },
|
---|
469 | { "r27", 27 },
|
---|
470 | { "r28", 28 },
|
---|
471 | { "r29", 29 },
|
---|
472 | { "r3", 3 },
|
---|
473 | { "r30", 30 },
|
---|
474 | { "r31", 31 },
|
---|
475 | { "r4", 4 },
|
---|
476 | { "r5", 5 },
|
---|
477 | { "r6", 6 },
|
---|
478 | { "r7", 7 },
|
---|
479 | { "r8", 8 },
|
---|
480 | { "r9", 9 },
|
---|
481 |
|
---|
482 | { "rtoc", 2 }, /* Table of contents */
|
---|
483 |
|
---|
484 | { "sdr1", 25 }, /* Storage Description Register 1 */
|
---|
485 |
|
---|
486 | { "sp", 1 },
|
---|
487 |
|
---|
488 | { "srr0", 26 }, /* Machine Status Save/Restore Register 0 */
|
---|
489 | { "srr1", 27 }, /* Machine Status Save/Restore Register 1 */
|
---|
490 |
|
---|
491 | { "v.0", 0 }, /* Vector registers */
|
---|
492 | { "v.1", 1 },
|
---|
493 | { "v.10", 10 },
|
---|
494 | { "v.11", 11 },
|
---|
495 | { "v.12", 12 },
|
---|
496 | { "v.13", 13 },
|
---|
497 | { "v.14", 14 },
|
---|
498 | { "v.15", 15 },
|
---|
499 | { "v.16", 16 },
|
---|
500 | { "v.17", 17 },
|
---|
501 | { "v.18", 18 },
|
---|
502 | { "v.19", 19 },
|
---|
503 | { "v.2", 2 },
|
---|
504 | { "v.20", 20 },
|
---|
505 | { "v.21", 21 },
|
---|
506 | { "v.22", 22 },
|
---|
507 | { "v.23", 23 },
|
---|
508 | { "v.24", 24 },
|
---|
509 | { "v.25", 25 },
|
---|
510 | { "v.26", 26 },
|
---|
511 | { "v.27", 27 },
|
---|
512 | { "v.28", 28 },
|
---|
513 | { "v.29", 29 },
|
---|
514 | { "v.3", 3 },
|
---|
515 | { "v.30", 30 },
|
---|
516 | { "v.31", 31 },
|
---|
517 | { "v.4", 4 },
|
---|
518 | { "v.5", 5 },
|
---|
519 | { "v.6", 6 },
|
---|
520 | { "v.7", 7 },
|
---|
521 | { "v.8", 8 },
|
---|
522 | { "v.9", 9 },
|
---|
523 |
|
---|
524 | { "v0", 0 },
|
---|
525 | { "v1", 1 },
|
---|
526 | { "v10", 10 },
|
---|
527 | { "v11", 11 },
|
---|
528 | { "v12", 12 },
|
---|
529 | { "v13", 13 },
|
---|
530 | { "v14", 14 },
|
---|
531 | { "v15", 15 },
|
---|
532 | { "v16", 16 },
|
---|
533 | { "v17", 17 },
|
---|
534 | { "v18", 18 },
|
---|
535 | { "v19", 19 },
|
---|
536 | { "v2", 2 },
|
---|
537 | { "v20", 20 },
|
---|
538 | { "v21", 21 },
|
---|
539 | { "v22", 22 },
|
---|
540 | { "v23", 23 },
|
---|
541 | { "v24", 24 },
|
---|
542 | { "v25", 25 },
|
---|
543 | { "v26", 26 },
|
---|
544 | { "v27", 27 },
|
---|
545 | { "v28", 28 },
|
---|
546 | { "v29", 29 },
|
---|
547 | { "v3", 3 },
|
---|
548 | { "v30", 30 },
|
---|
549 | { "v31", 31 },
|
---|
550 | { "v4", 4 },
|
---|
551 | { "v5", 5 },
|
---|
552 | { "v6", 6 },
|
---|
553 | { "v7", 7 },
|
---|
554 | { "v8", 8 },
|
---|
555 | { "v9", 9 },
|
---|
556 |
|
---|
557 | { "xer", 1 },
|
---|
558 |
|
---|
559 | };
|
---|
560 |
|
---|
561 | #define REG_NAME_CNT (sizeof (pre_defined_registers) / sizeof (struct pd_reg))
|
---|
562 |
|
---|
563 | /* Given NAME, find the register number associated with that name, return
|
---|
564 | the integer value associated with the given name or -1 on failure. */
|
---|
565 |
|
---|
566 | static int reg_name_search
|
---|
567 | PARAMS ((const struct pd_reg *, int, const char * name));
|
---|
568 |
|
---|
569 | static int
|
---|
570 | reg_name_search (regs, regcount, name)
|
---|
571 | const struct pd_reg *regs;
|
---|
572 | int regcount;
|
---|
573 | const char *name;
|
---|
574 | {
|
---|
575 | int middle, low, high;
|
---|
576 | int cmp;
|
---|
577 |
|
---|
578 | low = 0;
|
---|
579 | high = regcount - 1;
|
---|
580 |
|
---|
581 | do
|
---|
582 | {
|
---|
583 | middle = (low + high) / 2;
|
---|
584 | cmp = strcasecmp (name, regs[middle].name);
|
---|
585 | if (cmp < 0)
|
---|
586 | high = middle - 1;
|
---|
587 | else if (cmp > 0)
|
---|
588 | low = middle + 1;
|
---|
589 | else
|
---|
590 | return regs[middle].value;
|
---|
591 | }
|
---|
592 | while (low <= high);
|
---|
593 |
|
---|
594 | return -1;
|
---|
595 | }
|
---|
596 |
|
---|
597 | /*
|
---|
598 | * Summary of register_name.
|
---|
599 | *
|
---|
600 | * in: Input_line_pointer points to 1st char of operand.
|
---|
601 | *
|
---|
602 | * out: A expressionS.
|
---|
603 | * The operand may have been a register: in this case, X_op == O_register,
|
---|
604 | * X_add_number is set to the register number, and truth is returned.
|
---|
605 | * Input_line_pointer->(next non-blank) char after operand, or is in its
|
---|
606 | * original state.
|
---|
607 | */
|
---|
608 |
|
---|
609 | static bfd_boolean
|
---|
610 | register_name (expressionP)
|
---|
611 | expressionS *expressionP;
|
---|
612 | {
|
---|
613 | int reg_number;
|
---|
614 | char *name;
|
---|
615 | char *start;
|
---|
616 | char c;
|
---|
617 |
|
---|
618 | /* Find the spelling of the operand. */
|
---|
619 | start = name = input_line_pointer;
|
---|
620 | if (name[0] == '%' && ISALPHA (name[1]))
|
---|
621 | name = ++input_line_pointer;
|
---|
622 |
|
---|
623 | else if (!reg_names_p || !ISALPHA (name[0]))
|
---|
624 | return FALSE;
|
---|
625 |
|
---|
626 | c = get_symbol_end ();
|
---|
627 | reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
|
---|
628 |
|
---|
629 | /* Put back the delimiting char. */
|
---|
630 | *input_line_pointer = c;
|
---|
631 |
|
---|
632 | /* Look to see if it's in the register table. */
|
---|
633 | if (reg_number >= 0)
|
---|
634 | {
|
---|
635 | expressionP->X_op = O_register;
|
---|
636 | expressionP->X_add_number = reg_number;
|
---|
637 |
|
---|
638 | /* Make the rest nice. */
|
---|
639 | expressionP->X_add_symbol = NULL;
|
---|
640 | expressionP->X_op_symbol = NULL;
|
---|
641 | return TRUE;
|
---|
642 | }
|
---|
643 |
|
---|
644 | /* Reset the line as if we had not done anything. */
|
---|
645 | input_line_pointer = start;
|
---|
646 | return FALSE;
|
---|
647 | }
|
---|
648 | |
---|
649 |
|
---|
650 | /* This function is called for each symbol seen in an expression. It
|
---|
651 | handles the special parsing which PowerPC assemblers are supposed
|
---|
652 | to use for condition codes. */
|
---|
653 |
|
---|
654 | /* Whether to do the special parsing. */
|
---|
655 | static bfd_boolean cr_operand;
|
---|
656 |
|
---|
657 | /* Names to recognize in a condition code. This table is sorted. */
|
---|
658 | static const struct pd_reg cr_names[] =
|
---|
659 | {
|
---|
660 | { "cr0", 0 },
|
---|
661 | { "cr1", 1 },
|
---|
662 | { "cr2", 2 },
|
---|
663 | { "cr3", 3 },
|
---|
664 | { "cr4", 4 },
|
---|
665 | { "cr5", 5 },
|
---|
666 | { "cr6", 6 },
|
---|
667 | { "cr7", 7 },
|
---|
668 | { "eq", 2 },
|
---|
669 | { "gt", 1 },
|
---|
670 | { "lt", 0 },
|
---|
671 | { "so", 3 },
|
---|
672 | { "un", 3 }
|
---|
673 | };
|
---|
674 |
|
---|
675 | /* Parsing function. This returns non-zero if it recognized an
|
---|
676 | expression. */
|
---|
677 |
|
---|
678 | int
|
---|
679 | ppc_parse_name (name, expr)
|
---|
680 | const char *name;
|
---|
681 | expressionS *expr;
|
---|
682 | {
|
---|
683 | int val;
|
---|
684 |
|
---|
685 | if (! cr_operand)
|
---|
686 | return 0;
|
---|
687 |
|
---|
688 | val = reg_name_search (cr_names, sizeof cr_names / sizeof cr_names[0],
|
---|
689 | name);
|
---|
690 | if (val < 0)
|
---|
691 | return 0;
|
---|
692 |
|
---|
693 | expr->X_op = O_constant;
|
---|
694 | expr->X_add_number = val;
|
---|
695 |
|
---|
696 | return 1;
|
---|
697 | }
|
---|
698 | |
---|
699 |
|
---|
700 | /* Local variables. */
|
---|
701 |
|
---|
702 | /* The type of processor we are assembling for. This is one or more
|
---|
703 | of the PPC_OPCODE flags defined in opcode/ppc.h. */
|
---|
704 | static unsigned long ppc_cpu = 0;
|
---|
705 |
|
---|
706 | /* Whether to target xcoff64/elf64. */
|
---|
707 | static unsigned int ppc_obj64 = BFD_DEFAULT_TARGET_SIZE == 64;
|
---|
708 |
|
---|
709 | /* Opcode hash table. */
|
---|
710 | static struct hash_control *ppc_hash;
|
---|
711 |
|
---|
712 | /* Macro hash table. */
|
---|
713 | static struct hash_control *ppc_macro_hash;
|
---|
714 |
|
---|
715 | #ifdef OBJ_ELF
|
---|
716 | /* What type of shared library support to use. */
|
---|
717 | static enum { SHLIB_NONE, SHLIB_PIC, SHLIB_MRELOCATABLE } shlib = SHLIB_NONE;
|
---|
718 |
|
---|
719 | /* Flags to set in the elf header. */
|
---|
720 | static flagword ppc_flags = 0;
|
---|
721 |
|
---|
722 | /* Whether this is Solaris or not. */
|
---|
723 | #ifdef TARGET_SOLARIS_COMMENT
|
---|
724 | #define SOLARIS_P TRUE
|
---|
725 | #else
|
---|
726 | #define SOLARIS_P FALSE
|
---|
727 | #endif
|
---|
728 |
|
---|
729 | static bfd_boolean msolaris = SOLARIS_P;
|
---|
730 | #endif
|
---|
731 |
|
---|
732 | #ifdef OBJ_XCOFF
|
---|
733 |
|
---|
734 | /* The RS/6000 assembler uses the .csect pseudo-op to generate code
|
---|
735 | using a bunch of different sections. These assembler sections,
|
---|
736 | however, are all encompassed within the .text or .data sections of
|
---|
737 | the final output file. We handle this by using different
|
---|
738 | subsegments within these main segments. */
|
---|
739 |
|
---|
740 | /* Next subsegment to allocate within the .text segment. */
|
---|
741 | static subsegT ppc_text_subsegment = 2;
|
---|
742 |
|
---|
743 | /* Linked list of csects in the text section. */
|
---|
744 | static symbolS *ppc_text_csects;
|
---|
745 |
|
---|
746 | /* Next subsegment to allocate within the .data segment. */
|
---|
747 | static subsegT ppc_data_subsegment = 2;
|
---|
748 |
|
---|
749 | /* Linked list of csects in the data section. */
|
---|
750 | static symbolS *ppc_data_csects;
|
---|
751 |
|
---|
752 | /* The current csect. */
|
---|
753 | static symbolS *ppc_current_csect;
|
---|
754 |
|
---|
755 | /* The RS/6000 assembler uses a TOC which holds addresses of functions
|
---|
756 | and variables. Symbols are put in the TOC with the .tc pseudo-op.
|
---|
757 | A special relocation is used when accessing TOC entries. We handle
|
---|
758 | the TOC as a subsegment within the .data segment. We set it up if
|
---|
759 | we see a .toc pseudo-op, and save the csect symbol here. */
|
---|
760 | static symbolS *ppc_toc_csect;
|
---|
761 |
|
---|
762 | /* The first frag in the TOC subsegment. */
|
---|
763 | static fragS *ppc_toc_frag;
|
---|
764 |
|
---|
765 | /* The first frag in the first subsegment after the TOC in the .data
|
---|
766 | segment. NULL if there are no subsegments after the TOC. */
|
---|
767 | static fragS *ppc_after_toc_frag;
|
---|
768 |
|
---|
769 | /* The current static block. */
|
---|
770 | static symbolS *ppc_current_block;
|
---|
771 |
|
---|
772 | /* The COFF debugging section; set by md_begin. This is not the
|
---|
773 | .debug section, but is instead the secret BFD section which will
|
---|
774 | cause BFD to set the section number of a symbol to N_DEBUG. */
|
---|
775 | static asection *ppc_coff_debug_section;
|
---|
776 |
|
---|
777 | #endif /* OBJ_XCOFF */
|
---|
778 |
|
---|
779 | #ifdef TE_PE
|
---|
780 |
|
---|
781 | /* Various sections that we need for PE coff support. */
|
---|
782 | static segT ydata_section;
|
---|
783 | static segT pdata_section;
|
---|
784 | static segT reldata_section;
|
---|
785 | static segT rdata_section;
|
---|
786 | static segT tocdata_section;
|
---|
787 |
|
---|
788 | /* The current section and the previous section. See ppc_previous. */
|
---|
789 | static segT ppc_previous_section;
|
---|
790 | static segT ppc_current_section;
|
---|
791 |
|
---|
792 | #endif /* TE_PE */
|
---|
793 |
|
---|
794 | #ifdef OBJ_ELF
|
---|
795 | symbolS *GOT_symbol; /* Pre-defined "_GLOBAL_OFFSET_TABLE" */
|
---|
796 | #define PPC_APUINFO_ISEL 0x40
|
---|
797 | #define PPC_APUINFO_PMR 0x41
|
---|
798 | #define PPC_APUINFO_RFMCI 0x42
|
---|
799 | #define PPC_APUINFO_CACHELCK 0x43
|
---|
800 | #define PPC_APUINFO_SPE 0x100
|
---|
801 | #define PPC_APUINFO_EFS 0x101
|
---|
802 | #define PPC_APUINFO_BRLOCK 0x102
|
---|
803 |
|
---|
804 | /*
|
---|
805 | * We keep a list of APUinfo
|
---|
806 | */
|
---|
807 | unsigned long *ppc_apuinfo_list;
|
---|
808 | unsigned int ppc_apuinfo_num;
|
---|
809 | unsigned int ppc_apuinfo_num_alloc;
|
---|
810 | #endif /* OBJ_ELF */
|
---|
811 | |
---|
812 |
|
---|
813 | #ifdef OBJ_ELF
|
---|
814 | const char *const md_shortopts = "b:l:usm:K:VQ:";
|
---|
815 | #else
|
---|
816 | const char *const md_shortopts = "um:";
|
---|
817 | #endif
|
---|
818 | const struct option md_longopts[] = {
|
---|
819 | {NULL, no_argument, NULL, 0}
|
---|
820 | };
|
---|
821 | const size_t md_longopts_size = sizeof (md_longopts);
|
---|
822 |
|
---|
823 | int
|
---|
824 | md_parse_option (c, arg)
|
---|
825 | int c;
|
---|
826 | char *arg;
|
---|
827 | {
|
---|
828 | switch (c)
|
---|
829 | {
|
---|
830 | case 'u':
|
---|
831 | /* -u means that any undefined symbols should be treated as
|
---|
832 | external, which is the default for gas anyhow. */
|
---|
833 | break;
|
---|
834 |
|
---|
835 | #ifdef OBJ_ELF
|
---|
836 | case 'l':
|
---|
837 | /* Solaris as takes -le (presumably for little endian). For completeness
|
---|
838 | sake, recognize -be also. */
|
---|
839 | if (strcmp (arg, "e") == 0)
|
---|
840 | {
|
---|
841 | target_big_endian = 0;
|
---|
842 | set_target_endian = 1;
|
---|
843 | }
|
---|
844 | else
|
---|
845 | return 0;
|
---|
846 |
|
---|
847 | break;
|
---|
848 |
|
---|
849 | case 'b':
|
---|
850 | if (strcmp (arg, "e") == 0)
|
---|
851 | {
|
---|
852 | target_big_endian = 1;
|
---|
853 | set_target_endian = 1;
|
---|
854 | }
|
---|
855 | else
|
---|
856 | return 0;
|
---|
857 |
|
---|
858 | break;
|
---|
859 |
|
---|
860 | case 'K':
|
---|
861 | /* Recognize -K PIC. */
|
---|
862 | if (strcmp (arg, "PIC") == 0 || strcmp (arg, "pic") == 0)
|
---|
863 | {
|
---|
864 | shlib = SHLIB_PIC;
|
---|
865 | ppc_flags |= EF_PPC_RELOCATABLE_LIB;
|
---|
866 | }
|
---|
867 | else
|
---|
868 | return 0;
|
---|
869 |
|
---|
870 | break;
|
---|
871 | #endif
|
---|
872 |
|
---|
873 | /* a64 and a32 determine whether to use XCOFF64 or XCOFF32. */
|
---|
874 | case 'a':
|
---|
875 | if (strcmp (arg, "64") == 0)
|
---|
876 | {
|
---|
877 | #ifdef BFD64
|
---|
878 | ppc_obj64 = 1;
|
---|
879 | #else
|
---|
880 | as_fatal (_("%s unsupported"), "-a64");
|
---|
881 | #endif
|
---|
882 | }
|
---|
883 | else if (strcmp (arg, "32") == 0)
|
---|
884 | ppc_obj64 = 0;
|
---|
885 | else
|
---|
886 | return 0;
|
---|
887 | break;
|
---|
888 |
|
---|
889 | case 'm':
|
---|
890 | /* -mpwrx and -mpwr2 mean to assemble for the IBM POWER/2
|
---|
891 | (RIOS2). */
|
---|
892 | if (strcmp (arg, "pwrx") == 0 || strcmp (arg, "pwr2") == 0)
|
---|
893 | ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | PPC_OPCODE_32;
|
---|
894 | /* -mpwr means to assemble for the IBM POWER (RIOS1). */
|
---|
895 | else if (strcmp (arg, "pwr") == 0)
|
---|
896 | ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32;
|
---|
897 | /* -m601 means to assemble for the PowerPC 601, which includes
|
---|
898 | instructions that are holdovers from the Power. */
|
---|
899 | else if (strcmp (arg, "601") == 0)
|
---|
900 | ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
|
---|
901 | | PPC_OPCODE_601 | PPC_OPCODE_32);
|
---|
902 | /* -mppc, -mppc32, -m603, and -m604 mean to assemble for the
|
---|
903 | PowerPC 603/604. */
|
---|
904 | else if (strcmp (arg, "ppc") == 0
|
---|
905 | || strcmp (arg, "ppc32") == 0
|
---|
906 | || strcmp (arg, "603") == 0
|
---|
907 | || strcmp (arg, "604") == 0)
|
---|
908 | ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
|
---|
909 | /* -m403 and -m405 mean to assemble for the PowerPC 403/405. */
|
---|
910 | else if (strcmp (arg, "403") == 0
|
---|
911 | || strcmp (arg, "405") == 0)
|
---|
912 | ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
|
---|
913 | | PPC_OPCODE_403 | PPC_OPCODE_32);
|
---|
914 | else if (strcmp (arg, "7400") == 0
|
---|
915 | || strcmp (arg, "7410") == 0
|
---|
916 | || strcmp (arg, "7450") == 0
|
---|
917 | || strcmp (arg, "7455") == 0)
|
---|
918 | ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
|
---|
919 | | PPC_OPCODE_ALTIVEC | PPC_OPCODE_32);
|
---|
920 | else if (strcmp (arg, "altivec") == 0)
|
---|
921 | {
|
---|
922 | if (ppc_cpu == 0)
|
---|
923 | ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ALTIVEC;
|
---|
924 | else
|
---|
925 | ppc_cpu |= PPC_OPCODE_ALTIVEC;
|
---|
926 | }
|
---|
927 | else if (strcmp (arg, "e500") == 0 || strcmp (arg, "e500x2") == 0)
|
---|
928 | {
|
---|
929 | ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
|
---|
930 | | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
|
---|
931 | | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
|
---|
932 | | PPC_OPCODE_RFMCI);
|
---|
933 | }
|
---|
934 | else if (strcmp (arg, "spe") == 0)
|
---|
935 | {
|
---|
936 | if (ppc_cpu == 0)
|
---|
937 | ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_SPE | PPC_OPCODE_EFS;
|
---|
938 | else
|
---|
939 | ppc_cpu |= PPC_OPCODE_SPE;
|
---|
940 | }
|
---|
941 | /* -mppc64 and -m620 mean to assemble for the 64-bit PowerPC
|
---|
942 | 620. */
|
---|
943 | else if (strcmp (arg, "ppc64") == 0 || strcmp (arg, "620") == 0)
|
---|
944 | {
|
---|
945 | ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
|
---|
946 | }
|
---|
947 | else if (strcmp (arg, "ppc64bridge") == 0)
|
---|
948 | {
|
---|
949 | ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
|
---|
950 | | PPC_OPCODE_64_BRIDGE | PPC_OPCODE_64);
|
---|
951 | }
|
---|
952 | /* -mbooke/-mbooke32 mean enable 32-bit BookE support. */
|
---|
953 | else if (strcmp (arg, "booke") == 0 || strcmp (arg, "booke32") == 0)
|
---|
954 | {
|
---|
955 | ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32;
|
---|
956 | }
|
---|
957 | /* -mbooke64 means enable 64-bit BookE support. */
|
---|
958 | else if (strcmp (arg, "booke64") == 0)
|
---|
959 | {
|
---|
960 | ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE
|
---|
961 | | PPC_OPCODE_BOOKE64 | PPC_OPCODE_64);
|
---|
962 | }
|
---|
963 | else if (strcmp (arg, "power4") == 0)
|
---|
964 | {
|
---|
965 | ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
|
---|
966 | | PPC_OPCODE_64 | PPC_OPCODE_POWER4);
|
---|
967 | }
|
---|
968 | /* -mcom means assemble for the common intersection between Power
|
---|
969 | and PowerPC. At present, we just allow the union, rather
|
---|
970 | than the intersection. */
|
---|
971 | else if (strcmp (arg, "com") == 0)
|
---|
972 | ppc_cpu = PPC_OPCODE_COMMON | PPC_OPCODE_32;
|
---|
973 | /* -many means to assemble for any architecture (PWR/PWRX/PPC). */
|
---|
974 | else if (strcmp (arg, "any") == 0)
|
---|
975 | ppc_cpu = PPC_OPCODE_ANY | PPC_OPCODE_32;
|
---|
976 |
|
---|
977 | else if (strcmp (arg, "regnames") == 0)
|
---|
978 | reg_names_p = TRUE;
|
---|
979 |
|
---|
980 | else if (strcmp (arg, "no-regnames") == 0)
|
---|
981 | reg_names_p = FALSE;
|
---|
982 |
|
---|
983 | #ifdef OBJ_ELF
|
---|
984 | /* -mrelocatable/-mrelocatable-lib -- warn about initializations
|
---|
985 | that require relocation. */
|
---|
986 | else if (strcmp (arg, "relocatable") == 0)
|
---|
987 | {
|
---|
988 | shlib = SHLIB_MRELOCATABLE;
|
---|
989 | ppc_flags |= EF_PPC_RELOCATABLE;
|
---|
990 | }
|
---|
991 |
|
---|
992 | else if (strcmp (arg, "relocatable-lib") == 0)
|
---|
993 | {
|
---|
994 | shlib = SHLIB_MRELOCATABLE;
|
---|
995 | ppc_flags |= EF_PPC_RELOCATABLE_LIB;
|
---|
996 | }
|
---|
997 |
|
---|
998 | /* -memb, set embedded bit. */
|
---|
999 | else if (strcmp (arg, "emb") == 0)
|
---|
1000 | ppc_flags |= EF_PPC_EMB;
|
---|
1001 |
|
---|
1002 | /* -mlittle/-mbig set the endianess. */
|
---|
1003 | else if (strcmp (arg, "little") == 0
|
---|
1004 | || strcmp (arg, "little-endian") == 0)
|
---|
1005 | {
|
---|
1006 | target_big_endian = 0;
|
---|
1007 | set_target_endian = 1;
|
---|
1008 | }
|
---|
1009 |
|
---|
1010 | else if (strcmp (arg, "big") == 0 || strcmp (arg, "big-endian") == 0)
|
---|
1011 | {
|
---|
1012 | target_big_endian = 1;
|
---|
1013 | set_target_endian = 1;
|
---|
1014 | }
|
---|
1015 |
|
---|
1016 | else if (strcmp (arg, "solaris") == 0)
|
---|
1017 | {
|
---|
1018 | msolaris = TRUE;
|
---|
1019 | ppc_comment_chars = ppc_solaris_comment_chars;
|
---|
1020 | }
|
---|
1021 |
|
---|
1022 | else if (strcmp (arg, "no-solaris") == 0)
|
---|
1023 | {
|
---|
1024 | msolaris = FALSE;
|
---|
1025 | ppc_comment_chars = ppc_eabi_comment_chars;
|
---|
1026 | }
|
---|
1027 | #endif
|
---|
1028 | else
|
---|
1029 | {
|
---|
1030 | as_bad (_("invalid switch -m%s"), arg);
|
---|
1031 | return 0;
|
---|
1032 | }
|
---|
1033 | break;
|
---|
1034 |
|
---|
1035 | #ifdef OBJ_ELF
|
---|
1036 | /* -V: SVR4 argument to print version ID. */
|
---|
1037 | case 'V':
|
---|
1038 | print_version_id ();
|
---|
1039 | break;
|
---|
1040 |
|
---|
1041 | /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
|
---|
1042 | should be emitted or not. FIXME: Not implemented. */
|
---|
1043 | case 'Q':
|
---|
1044 | break;
|
---|
1045 |
|
---|
1046 | /* Solaris takes -s to specify that .stabs go in a .stabs section,
|
---|
1047 | rather than .stabs.excl, which is ignored by the linker.
|
---|
1048 | FIXME: Not implemented. */
|
---|
1049 | case 's':
|
---|
1050 | if (arg)
|
---|
1051 | return 0;
|
---|
1052 |
|
---|
1053 | break;
|
---|
1054 | #endif
|
---|
1055 |
|
---|
1056 | default:
|
---|
1057 | return 0;
|
---|
1058 | }
|
---|
1059 |
|
---|
1060 | return 1;
|
---|
1061 | }
|
---|
1062 |
|
---|
1063 | void
|
---|
1064 | md_show_usage (stream)
|
---|
1065 | FILE *stream;
|
---|
1066 | {
|
---|
1067 | fprintf (stream, _("\
|
---|
1068 | PowerPC options:\n\
|
---|
1069 | -u ignored\n\
|
---|
1070 | -mpwrx, -mpwr2 generate code for POWER/2 (RIOS2)\n\
|
---|
1071 | -mpwr generate code for POWER (RIOS1)\n\
|
---|
1072 | -m601 generate code for PowerPC 601\n\
|
---|
1073 | -mppc, -mppc32, -m603, -m604\n\
|
---|
1074 | generate code for PowerPC 603/604\n\
|
---|
1075 | -m403, -m405 generate code for PowerPC 403/405\n\
|
---|
1076 | -m7400, -m7410, -m7450, -m7455\n\
|
---|
1077 | generate code For PowerPC 7400/7410/7450/7455\n\
|
---|
1078 | -mppc64, -m620 generate code for PowerPC 620/625/630\n\
|
---|
1079 | -mppc64bridge generate code for PowerPC 64, including bridge insns\n\
|
---|
1080 | -mbooke64 generate code for 64-bit PowerPC BookE\n\
|
---|
1081 | -mbooke, mbooke32 generate code for 32-bit PowerPC BookE\n\
|
---|
1082 | -mpower4 generate code for Power4 architecture\n\
|
---|
1083 | -maltivec generate code for AltiVec\n\
|
---|
1084 | -mcom generate code Power/PowerPC common instructions\n\
|
---|
1085 | -many generate code for any architecture (PWR/PWRX/PPC)\n\
|
---|
1086 | -mregnames Allow symbolic names for registers\n\
|
---|
1087 | -mno-regnames Do not allow symbolic names for registers\n"));
|
---|
1088 | fprintf (stream, _("\
|
---|
1089 | -me500, -me500x2 generate code for Motorola e500 core complex\n\
|
---|
1090 | -mspe generate code for Motorola SPE instructions\n"));
|
---|
1091 | #ifdef OBJ_ELF
|
---|
1092 | fprintf (stream, _("\
|
---|
1093 | -mrelocatable support for GCC's -mrelocatble option\n\
|
---|
1094 | -mrelocatable-lib support for GCC's -mrelocatble-lib option\n\
|
---|
1095 | -memb set PPC_EMB bit in ELF flags\n\
|
---|
1096 | -mlittle, -mlittle-endian\n\
|
---|
1097 | generate code for a little endian machine\n\
|
---|
1098 | -mbig, -mbig-endian generate code for a big endian machine\n\
|
---|
1099 | -msolaris generate code for Solaris\n\
|
---|
1100 | -mno-solaris do not generate code for Solaris\n\
|
---|
1101 | -V print assembler version number\n\
|
---|
1102 | -Qy, -Qn ignored\n"));
|
---|
1103 | #endif
|
---|
1104 | }
|
---|
1105 | |
---|
1106 |
|
---|
1107 | /* Set ppc_cpu if it is not already set. */
|
---|
1108 |
|
---|
1109 | static void
|
---|
1110 | ppc_set_cpu ()
|
---|
1111 | {
|
---|
1112 | const char *default_os = TARGET_OS;
|
---|
1113 | const char *default_cpu = TARGET_CPU;
|
---|
1114 |
|
---|
1115 | if (ppc_cpu == 0)
|
---|
1116 | {
|
---|
1117 | if (ppc_obj64)
|
---|
1118 | ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
|
---|
1119 | else if (strncmp (default_os, "aix", 3) == 0
|
---|
1120 | && default_os[3] >= '4' && default_os[3] <= '9')
|
---|
1121 | ppc_cpu = PPC_OPCODE_COMMON | PPC_OPCODE_32;
|
---|
1122 | else if (strncmp (default_os, "aix3", 4) == 0)
|
---|
1123 | ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32;
|
---|
1124 | else if (strcmp (default_cpu, "rs6000") == 0)
|
---|
1125 | ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32;
|
---|
1126 | else if (strncmp (default_cpu, "powerpc", 7) == 0)
|
---|
1127 | {
|
---|
1128 | if (default_cpu[7] == '6' && default_cpu[8] == '4')
|
---|
1129 | ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
|
---|
1130 | else
|
---|
1131 | ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
|
---|
1132 | }
|
---|
1133 | else
|
---|
1134 | as_fatal (_("Unknown default cpu = %s, os = %s"),
|
---|
1135 | default_cpu, default_os);
|
---|
1136 | }
|
---|
1137 | }
|
---|
1138 |
|
---|
1139 | /* Figure out the BFD architecture to use. */
|
---|
1140 |
|
---|
1141 | enum bfd_architecture
|
---|
1142 | ppc_arch ()
|
---|
1143 | {
|
---|
1144 | const char *default_cpu = TARGET_CPU;
|
---|
1145 | ppc_set_cpu ();
|
---|
1146 |
|
---|
1147 | if ((ppc_cpu & PPC_OPCODE_PPC) != 0)
|
---|
1148 | return bfd_arch_powerpc;
|
---|
1149 | else if ((ppc_cpu & PPC_OPCODE_POWER) != 0)
|
---|
1150 | return bfd_arch_rs6000;
|
---|
1151 | else if ((ppc_cpu & (PPC_OPCODE_COMMON | PPC_OPCODE_ANY)) != 0)
|
---|
1152 | {
|
---|
1153 | if (strcmp (default_cpu, "rs6000") == 0)
|
---|
1154 | return bfd_arch_rs6000;
|
---|
1155 | else if (strncmp (default_cpu, "powerpc", 7) == 0)
|
---|
1156 | return bfd_arch_powerpc;
|
---|
1157 | }
|
---|
1158 |
|
---|
1159 | as_fatal (_("Neither Power nor PowerPC opcodes were selected."));
|
---|
1160 | return bfd_arch_unknown;
|
---|
1161 | }
|
---|
1162 |
|
---|
1163 | unsigned long
|
---|
1164 | ppc_mach ()
|
---|
1165 | {
|
---|
1166 | if (ppc_obj64)
|
---|
1167 | return bfd_mach_ppc64;
|
---|
1168 | else if (ppc_arch () == bfd_arch_rs6000)
|
---|
1169 | return bfd_mach_rs6k;
|
---|
1170 | else
|
---|
1171 | return bfd_mach_ppc;
|
---|
1172 | }
|
---|
1173 |
|
---|
1174 | extern char*
|
---|
1175 | ppc_target_format ()
|
---|
1176 | {
|
---|
1177 | #ifdef OBJ_COFF
|
---|
1178 | #ifdef TE_PE
|
---|
1179 | return target_big_endian ? "pe-powerpc" : "pe-powerpcle";
|
---|
1180 | #elif TE_POWERMAC
|
---|
1181 | return "xcoff-powermac";
|
---|
1182 | #else
|
---|
1183 | # ifdef TE_AIX5
|
---|
1184 | return (ppc_obj64 ? "aix5coff64-rs6000" : "aixcoff-rs6000");
|
---|
1185 | # else
|
---|
1186 | return (ppc_obj64 ? "aixcoff64-rs6000" : "aixcoff-rs6000");
|
---|
1187 | # endif
|
---|
1188 | #endif
|
---|
1189 | #endif
|
---|
1190 | #ifdef OBJ_ELF
|
---|
1191 | return (target_big_endian
|
---|
1192 | ? (ppc_obj64 ? "elf64-powerpc" : "elf32-powerpc")
|
---|
1193 | : (ppc_obj64 ? "elf64-powerpcle" : "elf32-powerpcle"));
|
---|
1194 | #endif
|
---|
1195 | }
|
---|
1196 |
|
---|
1197 | /* This function is called when the assembler starts up. It is called
|
---|
1198 | after the options have been parsed and the output file has been
|
---|
1199 | opened. */
|
---|
1200 |
|
---|
1201 | void
|
---|
1202 | md_begin ()
|
---|
1203 | {
|
---|
1204 | register const struct powerpc_opcode *op;
|
---|
1205 | const struct powerpc_opcode *op_end;
|
---|
1206 | const struct powerpc_macro *macro;
|
---|
1207 | const struct powerpc_macro *macro_end;
|
---|
1208 | bfd_boolean dup_insn = FALSE;
|
---|
1209 |
|
---|
1210 | ppc_set_cpu ();
|
---|
1211 |
|
---|
1212 | #ifdef OBJ_ELF
|
---|
1213 | /* Set the ELF flags if desired. */
|
---|
1214 | if (ppc_flags && !msolaris)
|
---|
1215 | bfd_set_private_flags (stdoutput, ppc_flags);
|
---|
1216 | #endif
|
---|
1217 |
|
---|
1218 | /* Insert the opcodes into a hash table. */
|
---|
1219 | ppc_hash = hash_new ();
|
---|
1220 |
|
---|
1221 | op_end = powerpc_opcodes + powerpc_num_opcodes;
|
---|
1222 | for (op = powerpc_opcodes; op < op_end; op++)
|
---|
1223 | {
|
---|
1224 | know ((op->opcode & op->mask) == op->opcode);
|
---|
1225 |
|
---|
1226 | if ((op->flags & ppc_cpu & ~(PPC_OPCODE_32 | PPC_OPCODE_64)) != 0
|
---|
1227 | && ((op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64)) == 0
|
---|
1228 | || ((op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64))
|
---|
1229 | == (ppc_cpu & (PPC_OPCODE_32 | PPC_OPCODE_64)))
|
---|
1230 | || (ppc_cpu & PPC_OPCODE_64_BRIDGE) != 0)
|
---|
1231 | /* Certain instructions (eg: extsw) do not exist in the
|
---|
1232 | 32-bit BookE instruction set, but they do exist in the
|
---|
1233 | 64-bit BookE instruction set, and other PPC instruction
|
---|
1234 | sets. Check to see if the opcode has the BOOKE64 flag set.
|
---|
1235 | If it does make sure that the target CPU is not the BookE32. */
|
---|
1236 | && ((op->flags & PPC_OPCODE_BOOKE64) == 0
|
---|
1237 | || (ppc_cpu & PPC_OPCODE_BOOKE64) == PPC_OPCODE_BOOKE64
|
---|
1238 | || (ppc_cpu & PPC_OPCODE_BOOKE) == 0)
|
---|
1239 | && ((op->flags & (PPC_OPCODE_POWER4 | PPC_OPCODE_NOPOWER4)) == 0
|
---|
1240 | || ((op->flags & PPC_OPCODE_POWER4)
|
---|
1241 | == (ppc_cpu & PPC_OPCODE_POWER4))))
|
---|
1242 | {
|
---|
1243 | const char *retval;
|
---|
1244 |
|
---|
1245 | retval = hash_insert (ppc_hash, op->name, (PTR) op);
|
---|
1246 | if (retval != (const char *) NULL)
|
---|
1247 | {
|
---|
1248 | /* Ignore Power duplicates for -m601. */
|
---|
1249 | if ((ppc_cpu & PPC_OPCODE_601) != 0
|
---|
1250 | && (op->flags & PPC_OPCODE_POWER) != 0)
|
---|
1251 | continue;
|
---|
1252 |
|
---|
1253 | as_bad (_("Internal assembler error for instruction %s"),
|
---|
1254 | op->name);
|
---|
1255 | dup_insn = TRUE;
|
---|
1256 | }
|
---|
1257 | }
|
---|
1258 | }
|
---|
1259 |
|
---|
1260 | /* Insert the macros into a hash table. */
|
---|
1261 | ppc_macro_hash = hash_new ();
|
---|
1262 |
|
---|
1263 | macro_end = powerpc_macros + powerpc_num_macros;
|
---|
1264 | for (macro = powerpc_macros; macro < macro_end; macro++)
|
---|
1265 | {
|
---|
1266 | if ((macro->flags & ppc_cpu) != 0)
|
---|
1267 | {
|
---|
1268 | const char *retval;
|
---|
1269 |
|
---|
1270 | retval = hash_insert (ppc_macro_hash, macro->name, (PTR) macro);
|
---|
1271 | if (retval != (const char *) NULL)
|
---|
1272 | {
|
---|
1273 | as_bad (_("Internal assembler error for macro %s"), macro->name);
|
---|
1274 | dup_insn = TRUE;
|
---|
1275 | }
|
---|
1276 | }
|
---|
1277 | }
|
---|
1278 |
|
---|
1279 | if (dup_insn)
|
---|
1280 | abort ();
|
---|
1281 |
|
---|
1282 | /* Tell the main code what the endianness is if it is not overidden
|
---|
1283 | by the user. */
|
---|
1284 | if (!set_target_endian)
|
---|
1285 | {
|
---|
1286 | set_target_endian = 1;
|
---|
1287 | target_big_endian = PPC_BIG_ENDIAN;
|
---|
1288 | }
|
---|
1289 |
|
---|
1290 | #ifdef OBJ_XCOFF
|
---|
1291 | ppc_coff_debug_section = coff_section_from_bfd_index (stdoutput, N_DEBUG);
|
---|
1292 |
|
---|
1293 | /* Create dummy symbols to serve as initial csects. This forces the
|
---|
1294 | text csects to precede the data csects. These symbols will not
|
---|
1295 | be output. */
|
---|
1296 | ppc_text_csects = symbol_make ("dummy\001");
|
---|
1297 | symbol_get_tc (ppc_text_csects)->within = ppc_text_csects;
|
---|
1298 | ppc_data_csects = symbol_make ("dummy\001");
|
---|
1299 | symbol_get_tc (ppc_data_csects)->within = ppc_data_csects;
|
---|
1300 | #endif
|
---|
1301 |
|
---|
1302 | #ifdef TE_PE
|
---|
1303 |
|
---|
1304 | ppc_current_section = text_section;
|
---|
1305 | ppc_previous_section = 0;
|
---|
1306 |
|
---|
1307 | #endif
|
---|
1308 | }
|
---|
1309 |
|
---|
1310 | void
|
---|
1311 | ppc_cleanup ()
|
---|
1312 | {
|
---|
1313 | #ifdef OBJ_ELF
|
---|
1314 | if (ppc_apuinfo_list == NULL)
|
---|
1315 | return;
|
---|
1316 |
|
---|
1317 | /* Ok, so write the section info out. We have this layout:
|
---|
1318 |
|
---|
1319 | byte data what
|
---|
1320 | ---- ---- ----
|
---|
1321 | 0 8 length of "APUinfo\0"
|
---|
1322 | 4 (n*4) number of APU's (4 bytes each)
|
---|
1323 | 8 2 note type 2
|
---|
1324 | 12 "APUinfo\0" name
|
---|
1325 | 20 APU#1 first APU's info
|
---|
1326 | 24 APU#2 second APU's info
|
---|
1327 | ... ...
|
---|
1328 | */
|
---|
1329 | {
|
---|
1330 | char *p;
|
---|
1331 | asection *seg = now_seg;
|
---|
1332 | subsegT subseg = now_subseg;
|
---|
1333 | asection *apuinfo_secp = (asection *) NULL;
|
---|
1334 | unsigned int i;
|
---|
1335 |
|
---|
1336 | /* Create the .PPC.EMB.apuinfo section. */
|
---|
1337 | apuinfo_secp = subseg_new (".PPC.EMB.apuinfo", 0);
|
---|
1338 | bfd_set_section_flags (stdoutput,
|
---|
1339 | apuinfo_secp,
|
---|
1340 | SEC_HAS_CONTENTS | SEC_READONLY);
|
---|
1341 |
|
---|
1342 | p = frag_more (4);
|
---|
1343 | md_number_to_chars (p, (valueT) 8, 4);
|
---|
1344 |
|
---|
1345 | p = frag_more (4);
|
---|
1346 | md_number_to_chars (p, (valueT) ppc_apuinfo_num, 4);
|
---|
1347 |
|
---|
1348 | p = frag_more (4);
|
---|
1349 | md_number_to_chars (p, (valueT) 2, 4);
|
---|
1350 |
|
---|
1351 | p = frag_more (8);
|
---|
1352 | strcpy (p, "APUinfo");
|
---|
1353 |
|
---|
1354 | for (i = 0; i < ppc_apuinfo_num; i++)
|
---|
1355 | {
|
---|
1356 | p = frag_more (4);
|
---|
1357 | md_number_to_chars (p, (valueT) ppc_apuinfo_list[i], 4);
|
---|
1358 | }
|
---|
1359 |
|
---|
1360 | frag_align (2, 0, 0);
|
---|
1361 |
|
---|
1362 | /* We probably can't restore the current segment, for there likely
|
---|
1363 | isn't one yet... */
|
---|
1364 | if (seg && subseg)
|
---|
1365 | subseg_set (seg, subseg);
|
---|
1366 | }
|
---|
1367 | #endif
|
---|
1368 | }
|
---|
1369 |
|
---|
1370 | /* Insert an operand value into an instruction. */
|
---|
1371 |
|
---|
1372 | static unsigned long
|
---|
1373 | ppc_insert_operand (insn, operand, val, file, line)
|
---|
1374 | unsigned long insn;
|
---|
1375 | const struct powerpc_operand *operand;
|
---|
1376 | offsetT val;
|
---|
1377 | char *file;
|
---|
1378 | unsigned int line;
|
---|
1379 | {
|
---|
1380 | if (operand->bits != 32)
|
---|
1381 | {
|
---|
1382 | long min, max;
|
---|
1383 | offsetT test;
|
---|
1384 |
|
---|
1385 | if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
|
---|
1386 | {
|
---|
1387 | if ((operand->flags & PPC_OPERAND_SIGNOPT) != 0)
|
---|
1388 | max = (1 << operand->bits) - 1;
|
---|
1389 | else
|
---|
1390 | max = (1 << (operand->bits - 1)) - 1;
|
---|
1391 | min = - (1 << (operand->bits - 1));
|
---|
1392 |
|
---|
1393 | if (!ppc_obj64)
|
---|
1394 | {
|
---|
1395 | /* Some people write 32 bit hex constants with the sign
|
---|
1396 | extension done by hand. This shouldn't really be
|
---|
1397 | valid, but, to permit this code to assemble on a 64
|
---|
1398 | bit host, we sign extend the 32 bit value. */
|
---|
1399 | if (val > 0
|
---|
1400 | && (val & (offsetT) 0x80000000) != 0
|
---|
1401 | && (val & (offsetT) 0xffffffff) == val)
|
---|
1402 | {
|
---|
1403 | val -= 0x80000000;
|
---|
1404 | val -= 0x80000000;
|
---|
1405 | }
|
---|
1406 | }
|
---|
1407 | }
|
---|
1408 | else
|
---|
1409 | {
|
---|
1410 | max = (1 << operand->bits) - 1;
|
---|
1411 | min = 0;
|
---|
1412 | }
|
---|
1413 |
|
---|
1414 | if ((operand->flags & PPC_OPERAND_NEGATIVE) != 0)
|
---|
1415 | test = - val;
|
---|
1416 | else
|
---|
1417 | test = val;
|
---|
1418 |
|
---|
1419 | if (test < (offsetT) min || test > (offsetT) max)
|
---|
1420 | {
|
---|
1421 | const char *err =
|
---|
1422 | _("operand out of range (%s not between %ld and %ld)");
|
---|
1423 | char buf[100];
|
---|
1424 |
|
---|
1425 | sprint_value (buf, test);
|
---|
1426 | as_bad_where (file, line, err, buf, min, max);
|
---|
1427 | }
|
---|
1428 | }
|
---|
1429 |
|
---|
1430 | if (operand->insert)
|
---|
1431 | {
|
---|
1432 | const char *errmsg;
|
---|
1433 |
|
---|
1434 | errmsg = NULL;
|
---|
1435 | insn = (*operand->insert) (insn, (long) val, ppc_cpu, &errmsg);
|
---|
1436 | if (errmsg != (const char *) NULL)
|
---|
1437 | as_bad_where (file, line, errmsg);
|
---|
1438 | }
|
---|
1439 | else
|
---|
1440 | insn |= (((long) val & ((1 << operand->bits) - 1))
|
---|
1441 | << operand->shift);
|
---|
1442 |
|
---|
1443 | return insn;
|
---|
1444 | }
|
---|
1445 |
|
---|
1446 | |
---|
1447 |
|
---|
1448 | #ifdef OBJ_ELF
|
---|
1449 | /* Parse @got, etc. and return the desired relocation. */
|
---|
1450 | static bfd_reloc_code_real_type
|
---|
1451 | ppc_elf_suffix (str_p, exp_p)
|
---|
1452 | char **str_p;
|
---|
1453 | expressionS *exp_p;
|
---|
1454 | {
|
---|
1455 | struct map_bfd {
|
---|
1456 | char *string;
|
---|
1457 | int length;
|
---|
1458 | int reloc;
|
---|
1459 | };
|
---|
1460 |
|
---|
1461 | char ident[20];
|
---|
1462 | char *str = *str_p;
|
---|
1463 | char *str2;
|
---|
1464 | int ch;
|
---|
1465 | int len;
|
---|
1466 | const struct map_bfd *ptr;
|
---|
1467 |
|
---|
1468 | #define MAP(str,reloc) { str, sizeof (str)-1, reloc }
|
---|
1469 |
|
---|
1470 | static const struct map_bfd mapping[] = {
|
---|
1471 | MAP ("l", (int) BFD_RELOC_LO16),
|
---|
1472 | MAP ("h", (int) BFD_RELOC_HI16),
|
---|
1473 | MAP ("ha", (int) BFD_RELOC_HI16_S),
|
---|
1474 | MAP ("brtaken", (int) BFD_RELOC_PPC_B16_BRTAKEN),
|
---|
1475 | MAP ("brntaken", (int) BFD_RELOC_PPC_B16_BRNTAKEN),
|
---|
1476 | MAP ("got", (int) BFD_RELOC_16_GOTOFF),
|
---|
1477 | MAP ("got@l", (int) BFD_RELOC_LO16_GOTOFF),
|
---|
1478 | MAP ("got@h", (int) BFD_RELOC_HI16_GOTOFF),
|
---|
1479 | MAP ("got@ha", (int) BFD_RELOC_HI16_S_GOTOFF),
|
---|
1480 | MAP ("fixup", (int) BFD_RELOC_CTOR),
|
---|
1481 | MAP ("plt", (int) BFD_RELOC_24_PLT_PCREL),
|
---|
1482 | MAP ("pltrel24", (int) BFD_RELOC_24_PLT_PCREL),
|
---|
1483 | MAP ("copy", (int) BFD_RELOC_PPC_COPY),
|
---|
1484 | MAP ("globdat", (int) BFD_RELOC_PPC_GLOB_DAT),
|
---|
1485 | MAP ("local24pc", (int) BFD_RELOC_PPC_LOCAL24PC),
|
---|
1486 | MAP ("local", (int) BFD_RELOC_PPC_LOCAL24PC),
|
---|
1487 | MAP ("pltrel", (int) BFD_RELOC_32_PLT_PCREL),
|
---|
1488 | MAP ("plt@l", (int) BFD_RELOC_LO16_PLTOFF),
|
---|
1489 | MAP ("plt@h", (int) BFD_RELOC_HI16_PLTOFF),
|
---|
1490 | MAP ("plt@ha", (int) BFD_RELOC_HI16_S_PLTOFF),
|
---|
1491 | MAP ("sdarel", (int) BFD_RELOC_GPREL16),
|
---|
1492 | MAP ("sectoff", (int) BFD_RELOC_16_BASEREL),
|
---|
1493 | MAP ("sectoff@l", (int) BFD_RELOC_LO16_BASEREL),
|
---|
1494 | MAP ("sectoff@h", (int) BFD_RELOC_HI16_BASEREL),
|
---|
1495 | MAP ("sectoff@ha", (int) BFD_RELOC_HI16_S_BASEREL),
|
---|
1496 | MAP ("naddr", (int) BFD_RELOC_PPC_EMB_NADDR32),
|
---|
1497 | MAP ("naddr16", (int) BFD_RELOC_PPC_EMB_NADDR16),
|
---|
1498 | MAP ("naddr@l", (int) BFD_RELOC_PPC_EMB_NADDR16_LO),
|
---|
1499 | MAP ("naddr@h", (int) BFD_RELOC_PPC_EMB_NADDR16_HI),
|
---|
1500 | MAP ("naddr@ha", (int) BFD_RELOC_PPC_EMB_NADDR16_HA),
|
---|
1501 | MAP ("sdai16", (int) BFD_RELOC_PPC_EMB_SDAI16),
|
---|
1502 | MAP ("sda2rel", (int) BFD_RELOC_PPC_EMB_SDA2REL),
|
---|
1503 | MAP ("sda2i16", (int) BFD_RELOC_PPC_EMB_SDA2I16),
|
---|
1504 | MAP ("sda21", (int) BFD_RELOC_PPC_EMB_SDA21),
|
---|
1505 | MAP ("mrkref", (int) BFD_RELOC_PPC_EMB_MRKREF),
|
---|
1506 | MAP ("relsect", (int) BFD_RELOC_PPC_EMB_RELSEC16),
|
---|
1507 | MAP ("relsect@l", (int) BFD_RELOC_PPC_EMB_RELST_LO),
|
---|
1508 | MAP ("relsect@h", (int) BFD_RELOC_PPC_EMB_RELST_HI),
|
---|
1509 | MAP ("relsect@ha", (int) BFD_RELOC_PPC_EMB_RELST_HA),
|
---|
1510 | MAP ("bitfld", (int) BFD_RELOC_PPC_EMB_BIT_FLD),
|
---|
1511 | MAP ("relsda", (int) BFD_RELOC_PPC_EMB_RELSDA),
|
---|
1512 | MAP ("xgot", (int) BFD_RELOC_PPC_TOC16),
|
---|
1513 | MAP ("tls", (int) BFD_RELOC_PPC_TLS),
|
---|
1514 | MAP ("dtpmod", (int) BFD_RELOC_PPC_DTPMOD),
|
---|
1515 | MAP ("dtprel", (int) BFD_RELOC_PPC_DTPREL),
|
---|
1516 | MAP ("dtprel@l", (int) BFD_RELOC_PPC_DTPREL16_LO),
|
---|
1517 | MAP ("dtprel@h", (int) BFD_RELOC_PPC_DTPREL16_HI),
|
---|
1518 | MAP ("dtprel@ha", (int) BFD_RELOC_PPC_DTPREL16_HA),
|
---|
1519 | MAP ("tprel", (int) BFD_RELOC_PPC_TPREL),
|
---|
1520 | MAP ("tprel@l", (int) BFD_RELOC_PPC_TPREL16_LO),
|
---|
1521 | MAP ("tprel@h", (int) BFD_RELOC_PPC_TPREL16_HI),
|
---|
1522 | MAP ("tprel@ha", (int) BFD_RELOC_PPC_TPREL16_HA),
|
---|
1523 | MAP ("got@tlsgd", (int) BFD_RELOC_PPC_GOT_TLSGD16),
|
---|
1524 | MAP ("got@tlsgd@l", (int) BFD_RELOC_PPC_GOT_TLSGD16_LO),
|
---|
1525 | MAP ("got@tlsgd@h", (int) BFD_RELOC_PPC_GOT_TLSGD16_HI),
|
---|
1526 | MAP ("got@tlsgd@ha", (int) BFD_RELOC_PPC_GOT_TLSGD16_HA),
|
---|
1527 | MAP ("got@tlsld", (int) BFD_RELOC_PPC_GOT_TLSLD16),
|
---|
1528 | MAP ("got@tlsld@l", (int) BFD_RELOC_PPC_GOT_TLSLD16_LO),
|
---|
1529 | MAP ("got@tlsld@h", (int) BFD_RELOC_PPC_GOT_TLSLD16_HI),
|
---|
1530 | MAP ("got@tlsld@ha", (int) BFD_RELOC_PPC_GOT_TLSLD16_HA),
|
---|
1531 | MAP ("got@dtprel", (int) BFD_RELOC_PPC_GOT_DTPREL16),
|
---|
1532 | MAP ("got@dtprel@l", (int) BFD_RELOC_PPC_GOT_DTPREL16_LO),
|
---|
1533 | MAP ("got@dtprel@h", (int) BFD_RELOC_PPC_GOT_DTPREL16_HI),
|
---|
1534 | MAP ("got@dtprel@ha", (int) BFD_RELOC_PPC_GOT_DTPREL16_HA),
|
---|
1535 | MAP ("got@tprel", (int) BFD_RELOC_PPC_GOT_TPREL16),
|
---|
1536 | MAP ("got@tprel@l", (int) BFD_RELOC_PPC_GOT_TPREL16_LO),
|
---|
1537 | MAP ("got@tprel@h", (int) BFD_RELOC_PPC_GOT_TPREL16_HI),
|
---|
1538 | MAP ("got@tprel@ha", (int) BFD_RELOC_PPC_GOT_TPREL16_HA),
|
---|
1539 | /* The following are only valid for ppc64. Negative values are
|
---|
1540 | used instead of a flag. */
|
---|
1541 | MAP ("higher", - (int) BFD_RELOC_PPC64_HIGHER),
|
---|
1542 | MAP ("highera", - (int) BFD_RELOC_PPC64_HIGHER_S),
|
---|
1543 | MAP ("highest", - (int) BFD_RELOC_PPC64_HIGHEST),
|
---|
1544 | MAP ("highesta", - (int) BFD_RELOC_PPC64_HIGHEST_S),
|
---|
1545 | MAP ("tocbase", - (int) BFD_RELOC_PPC64_TOC),
|
---|
1546 | MAP ("toc", - (int) BFD_RELOC_PPC_TOC16),
|
---|
1547 | MAP ("toc@l", - (int) BFD_RELOC_PPC64_TOC16_LO),
|
---|
1548 | MAP ("toc@h", - (int) BFD_RELOC_PPC64_TOC16_HI),
|
---|
1549 | MAP ("toc@ha", - (int) BFD_RELOC_PPC64_TOC16_HA),
|
---|
1550 | MAP ("dtprel@higher", - (int) BFD_RELOC_PPC64_DTPREL16_HIGHER),
|
---|
1551 | MAP ("dtprel@highera", - (int) BFD_RELOC_PPC64_DTPREL16_HIGHERA),
|
---|
1552 | MAP ("dtprel@highest", - (int) BFD_RELOC_PPC64_DTPREL16_HIGHEST),
|
---|
1553 | MAP ("dtprel@highesta", - (int) BFD_RELOC_PPC64_DTPREL16_HIGHESTA),
|
---|
1554 | MAP ("tprel@higher", - (int) BFD_RELOC_PPC64_TPREL16_HIGHER),
|
---|
1555 | MAP ("tprel@highera", - (int) BFD_RELOC_PPC64_TPREL16_HIGHERA),
|
---|
1556 | MAP ("tprel@highest", - (int) BFD_RELOC_PPC64_TPREL16_HIGHEST),
|
---|
1557 | MAP ("tprel@highesta", - (int) BFD_RELOC_PPC64_TPREL16_HIGHESTA),
|
---|
1558 | { (char *) 0, 0, (int) BFD_RELOC_UNUSED }
|
---|
1559 | };
|
---|
1560 |
|
---|
1561 | if (*str++ != '@')
|
---|
1562 | return BFD_RELOC_UNUSED;
|
---|
1563 |
|
---|
1564 | for (ch = *str, str2 = ident;
|
---|
1565 | (str2 < ident + sizeof (ident) - 1
|
---|
1566 | && (ISALNUM (ch) || ch == '@'));
|
---|
1567 | ch = *++str)
|
---|
1568 | {
|
---|
1569 | *str2++ = TOLOWER (ch);
|
---|
1570 | }
|
---|
1571 |
|
---|
1572 | *str2 = '\0';
|
---|
1573 | len = str2 - ident;
|
---|
1574 |
|
---|
1575 | ch = ident[0];
|
---|
1576 | for (ptr = &mapping[0]; ptr->length > 0; ptr++)
|
---|
1577 | if (ch == ptr->string[0]
|
---|
1578 | && len == ptr->length
|
---|
1579 | && memcmp (ident, ptr->string, ptr->length) == 0)
|
---|
1580 | {
|
---|
1581 | int reloc = ptr->reloc;
|
---|
1582 |
|
---|
1583 | if (reloc < 0)
|
---|
1584 | {
|
---|
1585 | if (!ppc_obj64)
|
---|
1586 | return BFD_RELOC_UNUSED;
|
---|
1587 | reloc = -reloc;
|
---|
1588 | }
|
---|
1589 |
|
---|
1590 | if (!ppc_obj64)
|
---|
1591 | if (exp_p->X_add_number != 0
|
---|
1592 | && (reloc == (int) BFD_RELOC_16_GOTOFF
|
---|
1593 | || reloc == (int) BFD_RELOC_LO16_GOTOFF
|
---|
1594 | || reloc == (int) BFD_RELOC_HI16_GOTOFF
|
---|
1595 | || reloc == (int) BFD_RELOC_HI16_S_GOTOFF))
|
---|
1596 | as_warn (_("identifier+constant@got means identifier@got+constant"));
|
---|
1597 |
|
---|
1598 | /* Now check for identifier@suffix+constant. */
|
---|
1599 | if (*str == '-' || *str == '+')
|
---|
1600 | {
|
---|
1601 | char *orig_line = input_line_pointer;
|
---|
1602 | expressionS new_exp;
|
---|
1603 |
|
---|
1604 | input_line_pointer = str;
|
---|
1605 | expression (&new_exp);
|
---|
1606 | if (new_exp.X_op == O_constant)
|
---|
1607 | {
|
---|
1608 | exp_p->X_add_number += new_exp.X_add_number;
|
---|
1609 | str = input_line_pointer;
|
---|
1610 | }
|
---|
1611 |
|
---|
1612 | if (&input_line_pointer != str_p)
|
---|
1613 | input_line_pointer = orig_line;
|
---|
1614 | }
|
---|
1615 | *str_p = str;
|
---|
1616 |
|
---|
1617 | if (reloc == (int) BFD_RELOC_PPC64_TOC
|
---|
1618 | && exp_p->X_op == O_symbol)
|
---|
1619 | {
|
---|
1620 | /* This reloc type ignores the symbol. Change the symbol
|
---|
1621 | so that the dummy .TOC. symbol can be omitted from the
|
---|
1622 | object file. */
|
---|
1623 | exp_p->X_add_symbol = &abs_symbol;
|
---|
1624 | }
|
---|
1625 |
|
---|
1626 | return (bfd_reloc_code_real_type) reloc;
|
---|
1627 | }
|
---|
1628 |
|
---|
1629 | return BFD_RELOC_UNUSED;
|
---|
1630 | }
|
---|
1631 |
|
---|
1632 | /* Like normal .long/.short/.word, except support @got, etc.
|
---|
1633 | Clobbers input_line_pointer, checks end-of-line. */
|
---|
1634 | static void
|
---|
1635 | ppc_elf_cons (nbytes)
|
---|
1636 | register int nbytes; /* 1=.byte, 2=.word, 4=.long, 8=.llong. */
|
---|
1637 | {
|
---|
1638 | expressionS exp;
|
---|
1639 | bfd_reloc_code_real_type reloc;
|
---|
1640 |
|
---|
1641 | if (is_it_end_of_statement ())
|
---|
1642 | {
|
---|
1643 | demand_empty_rest_of_line ();
|
---|
1644 | return;
|
---|
1645 | }
|
---|
1646 |
|
---|
1647 | do
|
---|
1648 | {
|
---|
1649 | expression (&exp);
|
---|
1650 | if (exp.X_op == O_symbol
|
---|
1651 | && *input_line_pointer == '@'
|
---|
1652 | && (reloc = ppc_elf_suffix (&input_line_pointer,
|
---|
1653 | &exp)) != BFD_RELOC_UNUSED)
|
---|
1654 | {
|
---|
1655 | reloc_howto_type *reloc_howto;
|
---|
1656 | int size;
|
---|
1657 |
|
---|
1658 | reloc_howto = bfd_reloc_type_lookup (stdoutput, reloc);
|
---|
1659 | size = bfd_get_reloc_size (reloc_howto);
|
---|
1660 |
|
---|
1661 | if (size > nbytes)
|
---|
1662 | {
|
---|
1663 | as_bad (_("%s relocations do not fit in %d bytes\n"),
|
---|
1664 | reloc_howto->name, nbytes);
|
---|
1665 | }
|
---|
1666 | else
|
---|
1667 | {
|
---|
1668 | char *p;
|
---|
1669 | int offset;
|
---|
1670 |
|
---|
1671 | p = frag_more (nbytes);
|
---|
1672 | offset = 0;
|
---|
1673 | if (target_big_endian)
|
---|
1674 | offset = nbytes - size;
|
---|
1675 | fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
|
---|
1676 | &exp, 0, reloc);
|
---|
1677 | }
|
---|
1678 | }
|
---|
1679 | else
|
---|
1680 | emit_expr (&exp, (unsigned int) nbytes);
|
---|
1681 | }
|
---|
1682 | while (*input_line_pointer++ == ',');
|
---|
1683 |
|
---|
1684 | /* Put terminator back into stream. */
|
---|
1685 | input_line_pointer--;
|
---|
1686 | demand_empty_rest_of_line ();
|
---|
1687 | }
|
---|
1688 |
|
---|
1689 | /* Solaris pseduo op to change to the .rodata section. */
|
---|
1690 | static void
|
---|
1691 | ppc_elf_rdata (xxx)
|
---|
1692 | int xxx;
|
---|
1693 | {
|
---|
1694 | char *save_line = input_line_pointer;
|
---|
1695 | static char section[] = ".rodata\n";
|
---|
1696 |
|
---|
1697 | /* Just pretend this is .section .rodata */
|
---|
1698 | input_line_pointer = section;
|
---|
1699 | obj_elf_section (xxx);
|
---|
1700 |
|
---|
1701 | input_line_pointer = save_line;
|
---|
1702 | }
|
---|
1703 |
|
---|
1704 | /* Pseudo op to make file scope bss items. */
|
---|
1705 | static void
|
---|
1706 | ppc_elf_lcomm (xxx)
|
---|
1707 | int xxx ATTRIBUTE_UNUSED;
|
---|
1708 | {
|
---|
1709 | register char *name;
|
---|
1710 | register char c;
|
---|
1711 | register char *p;
|
---|
1712 | offsetT size;
|
---|
1713 | register symbolS *symbolP;
|
---|
1714 | offsetT align;
|
---|
1715 | segT old_sec;
|
---|
1716 | int old_subsec;
|
---|
1717 | char *pfrag;
|
---|
1718 | int align2;
|
---|
1719 |
|
---|
1720 | name = input_line_pointer;
|
---|
1721 | c = get_symbol_end ();
|
---|
1722 |
|
---|
1723 | /* just after name is now '\0'. */
|
---|
1724 | p = input_line_pointer;
|
---|
1725 | *p = c;
|
---|
1726 | SKIP_WHITESPACE ();
|
---|
1727 | if (*input_line_pointer != ',')
|
---|
1728 | {
|
---|
1729 | as_bad (_("Expected comma after symbol-name: rest of line ignored."));
|
---|
1730 | ignore_rest_of_line ();
|
---|
1731 | return;
|
---|
1732 | }
|
---|
1733 |
|
---|
1734 | input_line_pointer++; /* skip ',' */
|
---|
1735 | if ((size = get_absolute_expression ()) < 0)
|
---|
1736 | {
|
---|
1737 | as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) size);
|
---|
1738 | ignore_rest_of_line ();
|
---|
1739 | return;
|
---|
1740 | }
|
---|
1741 |
|
---|
1742 | /* The third argument to .lcomm is the alignment. */
|
---|
1743 | if (*input_line_pointer != ',')
|
---|
1744 | align = 8;
|
---|
1745 | else
|
---|
1746 | {
|
---|
1747 | ++input_line_pointer;
|
---|
1748 | align = get_absolute_expression ();
|
---|
1749 | if (align <= 0)
|
---|
1750 | {
|
---|
1751 | as_warn (_("ignoring bad alignment"));
|
---|
1752 | align = 8;
|
---|
1753 | }
|
---|
1754 | }
|
---|
1755 |
|
---|
1756 | *p = 0;
|
---|
1757 | symbolP = symbol_find_or_make (name);
|
---|
1758 | *p = c;
|
---|
1759 |
|
---|
1760 | if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
|
---|
1761 | {
|
---|
1762 | as_bad (_("Ignoring attempt to re-define symbol `%s'."),
|
---|
1763 | S_GET_NAME (symbolP));
|
---|
1764 | ignore_rest_of_line ();
|
---|
1765 | return;
|
---|
1766 | }
|
---|
1767 |
|
---|
1768 | if (S_GET_VALUE (symbolP) && S_GET_VALUE (symbolP) != (valueT) size)
|
---|
1769 | {
|
---|
1770 | as_bad (_("Length of .lcomm \"%s\" is already %ld. Not changed to %ld."),
|
---|
1771 | S_GET_NAME (symbolP),
|
---|
1772 | (long) S_GET_VALUE (symbolP),
|
---|
1773 | (long) size);
|
---|
1774 |
|
---|
1775 | ignore_rest_of_line ();
|
---|
1776 | return;
|
---|
1777 | }
|
---|
1778 |
|
---|
1779 | /* Allocate_bss. */
|
---|
1780 | old_sec = now_seg;
|
---|
1781 | old_subsec = now_subseg;
|
---|
1782 | if (align)
|
---|
1783 | {
|
---|
1784 | /* Convert to a power of 2 alignment. */
|
---|
1785 | for (align2 = 0; (align & 1) == 0; align >>= 1, ++align2);
|
---|
1786 | if (align != 1)
|
---|
1787 | {
|
---|
1788 | as_bad (_("Common alignment not a power of 2"));
|
---|
1789 | ignore_rest_of_line ();
|
---|
1790 | return;
|
---|
1791 | }
|
---|
1792 | }
|
---|
1793 | else
|
---|
1794 | align2 = 0;
|
---|
1795 |
|
---|
1796 | record_alignment (bss_section, align2);
|
---|
1797 | subseg_set (bss_section, 0);
|
---|
1798 | if (align2)
|
---|
1799 | frag_align (align2, 0, 0);
|
---|
1800 | if (S_GET_SEGMENT (symbolP) == bss_section)
|
---|
1801 | symbol_get_frag (symbolP)->fr_symbol = 0;
|
---|
1802 | symbol_set_frag (symbolP, frag_now);
|
---|
1803 | pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size,
|
---|
1804 | (char *) 0);
|
---|
1805 | *pfrag = 0;
|
---|
1806 | S_SET_SIZE (symbolP, size);
|
---|
1807 | S_SET_SEGMENT (symbolP, bss_section);
|
---|
1808 | subseg_set (old_sec, old_subsec);
|
---|
1809 | demand_empty_rest_of_line ();
|
---|
1810 | }
|
---|
1811 |
|
---|
1812 | /* Validate any relocations emitted for -mrelocatable, possibly adding
|
---|
1813 | fixups for word relocations in writable segments, so we can adjust
|
---|
1814 | them at runtime. */
|
---|
1815 | static void
|
---|
1816 | ppc_elf_validate_fix (fixp, seg)
|
---|
1817 | fixS *fixp;
|
---|
1818 | segT seg;
|
---|
1819 | {
|
---|
1820 | if (fixp->fx_done || fixp->fx_pcrel)
|
---|
1821 | return;
|
---|
1822 |
|
---|
1823 | switch (shlib)
|
---|
1824 | {
|
---|
1825 | case SHLIB_NONE:
|
---|
1826 | case SHLIB_PIC:
|
---|
1827 | return;
|
---|
1828 |
|
---|
1829 | case SHLIB_MRELOCATABLE:
|
---|
1830 | if (fixp->fx_r_type <= BFD_RELOC_UNUSED
|
---|
1831 | && fixp->fx_r_type != BFD_RELOC_16_GOTOFF
|
---|
1832 | && fixp->fx_r_type != BFD_RELOC_HI16_GOTOFF
|
---|
1833 | && fixp->fx_r_type != BFD_RELOC_LO16_GOTOFF
|
---|
1834 | && fixp->fx_r_type != BFD_RELOC_HI16_S_GOTOFF
|
---|
1835 | && fixp->fx_r_type != BFD_RELOC_16_BASEREL
|
---|
1836 | && fixp->fx_r_type != BFD_RELOC_LO16_BASEREL
|
---|
1837 | && fixp->fx_r_type != BFD_RELOC_HI16_BASEREL
|
---|
1838 | && fixp->fx_r_type != BFD_RELOC_HI16_S_BASEREL
|
---|
1839 | && (seg->flags & SEC_LOAD) != 0
|
---|
1840 | && strcmp (segment_name (seg), ".got2") != 0
|
---|
1841 | && strcmp (segment_name (seg), ".dtors") != 0
|
---|
1842 | && strcmp (segment_name (seg), ".ctors") != 0
|
---|
1843 | && strcmp (segment_name (seg), ".fixup") != 0
|
---|
1844 | && strcmp (segment_name (seg), ".gcc_except_table") != 0
|
---|
1845 | && strcmp (segment_name (seg), ".eh_frame") != 0
|
---|
1846 | && strcmp (segment_name (seg), ".ex_shared") != 0)
|
---|
1847 | {
|
---|
1848 | if ((seg->flags & (SEC_READONLY | SEC_CODE)) != 0
|
---|
1849 | || fixp->fx_r_type != BFD_RELOC_CTOR)
|
---|
1850 | {
|
---|
1851 | as_bad_where (fixp->fx_file, fixp->fx_line,
|
---|
1852 | _("Relocation cannot be done when using -mrelocatable"));
|
---|
1853 | }
|
---|
1854 | }
|
---|
1855 | return;
|
---|
1856 | }
|
---|
1857 | }
|
---|
1858 |
|
---|
1859 | /* Prevent elf_frob_file_before_adjust removing a weak undefined
|
---|
1860 | function descriptor sym if the corresponding code sym is used. */
|
---|
1861 |
|
---|
1862 | void
|
---|
1863 | ppc_frob_file_before_adjust ()
|
---|
1864 | {
|
---|
1865 | symbolS *symp;
|
---|
1866 |
|
---|
1867 | if (!ppc_obj64)
|
---|
1868 | return;
|
---|
1869 |
|
---|
1870 | for (symp = symbol_rootP; symp; symp = symbol_next (symp))
|
---|
1871 | {
|
---|
1872 | const char *name;
|
---|
1873 | char *dotname;
|
---|
1874 | symbolS *dotsym;
|
---|
1875 | size_t len;
|
---|
1876 |
|
---|
1877 | name = S_GET_NAME (symp);
|
---|
1878 | if (name[0] == '.')
|
---|
1879 | continue;
|
---|
1880 |
|
---|
1881 | if (! S_IS_WEAK (symp)
|
---|
1882 | || S_IS_DEFINED (symp))
|
---|
1883 | continue;
|
---|
1884 |
|
---|
1885 | len = strlen (name) + 1;
|
---|
1886 | dotname = xmalloc (len + 1);
|
---|
1887 | dotname[0] = '.';
|
---|
1888 | memcpy (dotname + 1, name, len);
|
---|
1889 | dotsym = symbol_find (dotname);
|
---|
1890 | free (dotname);
|
---|
1891 | if (dotsym != NULL && (symbol_used_p (dotsym)
|
---|
1892 | || symbol_used_in_reloc_p (dotsym)))
|
---|
1893 | {
|
---|
1894 | symbol_mark_used (symp);
|
---|
1895 | }
|
---|
1896 | }
|
---|
1897 |
|
---|
1898 | /* Don't emit .TOC. symbol. */
|
---|
1899 | symp = symbol_find (".TOC.");
|
---|
1900 | if (symp != NULL)
|
---|
1901 | symbol_remove (symp, &symbol_rootP, &symbol_lastP);
|
---|
1902 | }
|
---|
1903 | #endif /* OBJ_ELF */
|
---|
1904 | |
---|
1905 |
|
---|
1906 | #ifdef TE_PE
|
---|
1907 |
|
---|
1908 | /*
|
---|
1909 | * Summary of parse_toc_entry.
|
---|
1910 | *
|
---|
1911 | * in: Input_line_pointer points to the '[' in one of:
|
---|
1912 | *
|
---|
1913 | * [toc] [tocv] [toc32] [toc64]
|
---|
1914 | *
|
---|
1915 | * Anything else is an error of one kind or another.
|
---|
1916 | *
|
---|
1917 | * out:
|
---|
1918 | * return value: success or failure
|
---|
1919 | * toc_kind: kind of toc reference
|
---|
1920 | * input_line_pointer:
|
---|
1921 | * success: first char after the ']'
|
---|
1922 | * failure: unchanged
|
---|
1923 | *
|
---|
1924 | * settings:
|
---|
1925 | *
|
---|
1926 | * [toc] - rv == success, toc_kind = default_toc
|
---|
1927 | * [tocv] - rv == success, toc_kind = data_in_toc
|
---|
1928 | * [toc32] - rv == success, toc_kind = must_be_32
|
---|
1929 | * [toc64] - rv == success, toc_kind = must_be_64
|
---|
1930 | *
|
---|
1931 | */
|
---|
1932 |
|
---|
1933 | enum toc_size_qualifier
|
---|
1934 | {
|
---|
1935 | default_toc, /* The toc cell constructed should be the system default size */
|
---|
1936 | data_in_toc, /* This is a direct reference to a toc cell */
|
---|
1937 | must_be_32, /* The toc cell constructed must be 32 bits wide */
|
---|
1938 | must_be_64 /* The toc cell constructed must be 64 bits wide */
|
---|
1939 | };
|
---|
1940 |
|
---|
1941 | static int
|
---|
1942 | parse_toc_entry (toc_kind)
|
---|
1943 | enum toc_size_qualifier *toc_kind;
|
---|
1944 | {
|
---|
1945 | char *start;
|
---|
1946 | char *toc_spec;
|
---|
1947 | char c;
|
---|
1948 | enum toc_size_qualifier t;
|
---|
1949 |
|
---|
1950 | /* Save the input_line_pointer. */
|
---|
1951 | start = input_line_pointer;
|
---|
1952 |
|
---|
1953 | /* Skip over the '[' , and whitespace. */
|
---|
1954 | ++input_line_pointer;
|
---|
1955 | SKIP_WHITESPACE ();
|
---|
1956 |
|
---|
1957 | /* Find the spelling of the operand. */
|
---|
1958 | toc_spec = input_line_pointer;
|
---|
1959 | c = get_symbol_end ();
|
---|
1960 |
|
---|
1961 | if (strcmp (toc_spec, "toc") == 0)
|
---|
1962 | {
|
---|
1963 | t = default_toc;
|
---|
1964 | }
|
---|
1965 | else if (strcmp (toc_spec, "tocv") == 0)
|
---|
1966 | {
|
---|
1967 | t = data_in_toc;
|
---|
1968 | }
|
---|
1969 | else if (strcmp (toc_spec, "toc32") == 0)
|
---|
1970 | {
|
---|
1971 | t = must_be_32;
|
---|
1972 | }
|
---|
1973 | else if (strcmp (toc_spec, "toc64") == 0)
|
---|
1974 | {
|
---|
1975 | t = must_be_64;
|
---|
1976 | }
|
---|
1977 | else
|
---|
1978 | {
|
---|
1979 | as_bad (_("syntax error: invalid toc specifier `%s'"), toc_spec);
|
---|
1980 | *input_line_pointer = c;
|
---|
1981 | input_line_pointer = start;
|
---|
1982 | return 0;
|
---|
1983 | }
|
---|
1984 |
|
---|
1985 | /* Now find the ']'. */
|
---|
1986 | *input_line_pointer = c;
|
---|
1987 |
|
---|
1988 | SKIP_WHITESPACE (); /* leading whitespace could be there. */
|
---|
1989 | c = *input_line_pointer++; /* input_line_pointer->past char in c. */
|
---|
1990 |
|
---|
1991 | if (c != ']')
|
---|
1992 | {
|
---|
1993 | as_bad (_("syntax error: expected `]', found `%c'"), c);
|
---|
1994 | input_line_pointer = start;
|
---|
1995 | return 0;
|
---|
1996 | }
|
---|
1997 |
|
---|
1998 | *toc_kind = t;
|
---|
1999 | return 1;
|
---|
2000 | }
|
---|
2001 | #endif
|
---|
2002 | |
---|
2003 |
|
---|
2004 |
|
---|
2005 | #ifdef OBJ_ELF
|
---|
2006 | #define APUID(a,v) ((((a) & 0xffff) << 16) | ((v) & 0xffff))
|
---|
2007 | static void
|
---|
2008 | ppc_apuinfo_section_add (apu, version)
|
---|
2009 | unsigned int apu, version;
|
---|
2010 | {
|
---|
2011 | unsigned int i;
|
---|
2012 |
|
---|
2013 | /* Check we don't already exist. */
|
---|
2014 | for (i = 0; i < ppc_apuinfo_num; i++)
|
---|
2015 | if (ppc_apuinfo_list[i] == APUID (apu, version))
|
---|
2016 | return;
|
---|
2017 |
|
---|
2018 | if (ppc_apuinfo_num == ppc_apuinfo_num_alloc)
|
---|
2019 | {
|
---|
2020 | if (ppc_apuinfo_num_alloc == 0)
|
---|
2021 | {
|
---|
2022 | ppc_apuinfo_num_alloc = 4;
|
---|
2023 | ppc_apuinfo_list = (unsigned long *)
|
---|
2024 | xmalloc (sizeof (unsigned long) * ppc_apuinfo_num_alloc);
|
---|
2025 | }
|
---|
2026 | else
|
---|
2027 | {
|
---|
2028 | ppc_apuinfo_num_alloc += 4;
|
---|
2029 | ppc_apuinfo_list = (unsigned long *) xrealloc (ppc_apuinfo_list,
|
---|
2030 | sizeof (unsigned long) * ppc_apuinfo_num_alloc);
|
---|
2031 | }
|
---|
2032 | }
|
---|
2033 | ppc_apuinfo_list[ppc_apuinfo_num++] = APUID (apu, version);
|
---|
2034 | }
|
---|
2035 | #undef APUID
|
---|
2036 | #endif
|
---|
2037 | |
---|
2038 |
|
---|
2039 |
|
---|
2040 | /* We need to keep a list of fixups. We can't simply generate them as
|
---|
2041 | we go, because that would require us to first create the frag, and
|
---|
2042 | that would screw up references to ``.''. */
|
---|
2043 |
|
---|
2044 | struct ppc_fixup
|
---|
2045 | {
|
---|
2046 | expressionS exp;
|
---|
2047 | int opindex;
|
---|
2048 | bfd_reloc_code_real_type reloc;
|
---|
2049 | };
|
---|
2050 |
|
---|
2051 | #define MAX_INSN_FIXUPS (5)
|
---|
2052 |
|
---|
2053 | /* This routine is called for each instruction to be assembled. */
|
---|
2054 |
|
---|
2055 | void
|
---|
2056 | md_assemble (str)
|
---|
2057 | char *str;
|
---|
2058 | {
|
---|
2059 | char *s;
|
---|
2060 | const struct powerpc_opcode *opcode;
|
---|
2061 | unsigned long insn;
|
---|
2062 | const unsigned char *opindex_ptr;
|
---|
2063 | int skip_optional;
|
---|
2064 | int need_paren;
|
---|
2065 | int next_opindex;
|
---|
2066 | struct ppc_fixup fixups[MAX_INSN_FIXUPS];
|
---|
2067 | int fc;
|
---|
2068 | char *f;
|
---|
2069 | int i;
|
---|
2070 | #ifdef OBJ_ELF
|
---|
2071 | bfd_reloc_code_real_type reloc;
|
---|
2072 | #endif
|
---|
2073 |
|
---|
2074 | /* Get the opcode. */
|
---|
2075 | for (s = str; *s != '\0' && ! ISSPACE (*s); s++)
|
---|
2076 | ;
|
---|
2077 | if (*s != '\0')
|
---|
2078 | *s++ = '\0';
|
---|
2079 |
|
---|
2080 | /* Look up the opcode in the hash table. */
|
---|
2081 | opcode = (const struct powerpc_opcode *) hash_find (ppc_hash, str);
|
---|
2082 | if (opcode == (const struct powerpc_opcode *) NULL)
|
---|
2083 | {
|
---|
2084 | const struct powerpc_macro *macro;
|
---|
2085 |
|
---|
2086 | macro = (const struct powerpc_macro *) hash_find (ppc_macro_hash, str);
|
---|
2087 | if (macro == (const struct powerpc_macro *) NULL)
|
---|
2088 | as_bad (_("Unrecognized opcode: `%s'"), str);
|
---|
2089 | else
|
---|
2090 | ppc_macro (s, macro);
|
---|
2091 |
|
---|
2092 | return;
|
---|
2093 | }
|
---|
2094 |
|
---|
2095 | insn = opcode->opcode;
|
---|
2096 |
|
---|
2097 | str = s;
|
---|
2098 | while (ISSPACE (*str))
|
---|
2099 | ++str;
|
---|
2100 |
|
---|
2101 | /* PowerPC operands are just expressions. The only real issue is
|
---|
2102 | that a few operand types are optional. All cases which might use
|
---|
2103 | an optional operand separate the operands only with commas (in
|
---|
2104 | some cases parentheses are used, as in ``lwz 1,0(1)'' but such
|
---|
2105 | cases never have optional operands). There is never more than
|
---|
2106 | one optional operand for an instruction. So, before we start
|
---|
2107 | seriously parsing the operands, we check to see if we have an
|
---|
2108 | optional operand, and, if we do, we count the number of commas to
|
---|
2109 | see whether the operand should be omitted. */
|
---|
2110 | skip_optional = 0;
|
---|
2111 | for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
|
---|
2112 | {
|
---|
2113 | const struct powerpc_operand *operand;
|
---|
2114 |
|
---|
2115 | operand = &powerpc_operands[*opindex_ptr];
|
---|
2116 | if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
|
---|
2117 | {
|
---|
2118 | unsigned int opcount;
|
---|
2119 | unsigned int num_operands_expected;
|
---|
2120 | unsigned int i;
|
---|
2121 |
|
---|
2122 | /* There is an optional operand. Count the number of
|
---|
2123 | commas in the input line. */
|
---|
2124 | if (*str == '\0')
|
---|
2125 | opcount = 0;
|
---|
2126 | else
|
---|
2127 | {
|
---|
2128 | opcount = 1;
|
---|
2129 | s = str;
|
---|
2130 | while ((s = strchr (s, ',')) != (char *) NULL)
|
---|
2131 | {
|
---|
2132 | ++opcount;
|
---|
2133 | ++s;
|
---|
2134 | }
|
---|
2135 | }
|
---|
2136 |
|
---|
2137 | /* Compute the number of expected operands.
|
---|
2138 | Do not count fake operands. */
|
---|
2139 | for (num_operands_expected = 0, i = 0; opcode->operands[i]; i ++)
|
---|
2140 | if ((powerpc_operands [opcode->operands[i]].flags & PPC_OPERAND_FAKE) == 0)
|
---|
2141 | ++ num_operands_expected;
|
---|
2142 |
|
---|
2143 | /* If there are fewer operands in the line then are called
|
---|
2144 | for by the instruction, we want to skip the optional
|
---|
2145 | operand. */
|
---|
2146 | if (opcount < num_operands_expected)
|
---|
2147 | skip_optional = 1;
|
---|
2148 |
|
---|
2149 | break;
|
---|
2150 | }
|
---|
2151 | }
|
---|
2152 |
|
---|
2153 | /* Gather the operands. */
|
---|
2154 | need_paren = 0;
|
---|
2155 | next_opindex = 0;
|
---|
2156 | fc = 0;
|
---|
2157 | for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
|
---|
2158 | {
|
---|
2159 | const struct powerpc_operand *operand;
|
---|
2160 | const char *errmsg;
|
---|
2161 | char *hold;
|
---|
2162 | expressionS ex;
|
---|
2163 | char endc;
|
---|
2164 |
|
---|
2165 | if (next_opindex == 0)
|
---|
2166 | operand = &powerpc_operands[*opindex_ptr];
|
---|
2167 | else
|
---|
2168 | {
|
---|
2169 | operand = &powerpc_operands[next_opindex];
|
---|
2170 | next_opindex = 0;
|
---|
2171 | }
|
---|
2172 | errmsg = NULL;
|
---|
2173 |
|
---|
2174 | /* If this is a fake operand, then we do not expect anything
|
---|
2175 | from the input. */
|
---|
2176 | if ((operand->flags & PPC_OPERAND_FAKE) != 0)
|
---|
2177 | {
|
---|
2178 | insn = (*operand->insert) (insn, 0L, ppc_cpu, &errmsg);
|
---|
2179 | if (errmsg != (const char *) NULL)
|
---|
2180 | as_bad (errmsg);
|
---|
2181 | continue;
|
---|
2182 | }
|
---|
2183 |
|
---|
2184 | /* If this is an optional operand, and we are skipping it, just
|
---|
2185 | insert a zero. */
|
---|
2186 | if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
|
---|
2187 | && skip_optional)
|
---|
2188 | {
|
---|
2189 | if (operand->insert)
|
---|
2190 | {
|
---|
2191 | insn = (*operand->insert) (insn, 0L, ppc_cpu, &errmsg);
|
---|
2192 | if (errmsg != (const char *) NULL)
|
---|
2193 | as_bad (errmsg);
|
---|
2194 | }
|
---|
2195 | if ((operand->flags & PPC_OPERAND_NEXT) != 0)
|
---|
2196 | next_opindex = *opindex_ptr + 1;
|
---|
2197 | continue;
|
---|
2198 | }
|
---|
2199 |
|
---|
2200 | /* Gather the operand. */
|
---|
2201 | hold = input_line_pointer;
|
---|
2202 | input_line_pointer = str;
|
---|
2203 |
|
---|
2204 | #ifdef TE_PE
|
---|
2205 | if (*input_line_pointer == '[')
|
---|
2206 | {
|
---|
2207 | /* We are expecting something like the second argument here:
|
---|
2208 | *
|
---|
2209 | * lwz r4,[toc].GS.0.static_int(rtoc)
|
---|
2210 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
---|
2211 | * The argument following the `]' must be a symbol name, and the
|
---|
2212 | * register must be the toc register: 'rtoc' or '2'
|
---|
2213 | *
|
---|
2214 | * The effect is to 0 as the displacement field
|
---|
2215 | * in the instruction, and issue an IMAGE_REL_PPC_TOCREL16 (or
|
---|
2216 | * the appropriate variation) reloc against it based on the symbol.
|
---|
2217 | * The linker will build the toc, and insert the resolved toc offset.
|
---|
2218 | *
|
---|
2219 | * Note:
|
---|
2220 | * o The size of the toc entry is currently assumed to be
|
---|
2221 | * 32 bits. This should not be assumed to be a hard coded
|
---|
2222 | * number.
|
---|
2223 | * o In an effort to cope with a change from 32 to 64 bits,
|
---|
2224 | * there are also toc entries that are specified to be
|
---|
2225 | * either 32 or 64 bits:
|
---|
2226 | * lwz r4,[toc32].GS.0.static_int(rtoc)
|
---|
2227 | * lwz r4,[toc64].GS.0.static_int(rtoc)
|
---|
2228 | * These demand toc entries of the specified size, and the
|
---|
2229 | * instruction probably requires it.
|
---|
2230 | */
|
---|
2231 |
|
---|
2232 | int valid_toc;
|
---|
2233 | enum toc_size_qualifier toc_kind;
|
---|
2234 | bfd_reloc_code_real_type toc_reloc;
|
---|
2235 |
|
---|
2236 | /* Go parse off the [tocXX] part. */
|
---|
2237 | valid_toc = parse_toc_entry (&toc_kind);
|
---|
2238 |
|
---|
2239 | if (!valid_toc)
|
---|
2240 | {
|
---|
2241 | /* Note: message has already been issued.
|
---|
2242 | FIXME: what sort of recovery should we do?
|
---|
2243 | demand_rest_of_line (); return; ? */
|
---|
2244 | }
|
---|
2245 |
|
---|
2246 | /* Now get the symbol following the ']'. */
|
---|
2247 | expression (&ex);
|
---|
2248 |
|
---|
2249 | switch (toc_kind)
|
---|
2250 | {
|
---|
2251 | case default_toc:
|
---|
2252 | /* In this case, we may not have seen the symbol yet,
|
---|
2253 | since it is allowed to appear on a .extern or .globl
|
---|
2254 | or just be a label in the .data section. */
|
---|
2255 | toc_reloc = BFD_RELOC_PPC_TOC16;
|
---|
2256 | break;
|
---|
2257 | case data_in_toc:
|
---|
2258 | /* 1. The symbol must be defined and either in the toc
|
---|
2259 | section, or a global.
|
---|
2260 | 2. The reloc generated must have the TOCDEFN flag set
|
---|
2261 | in upper bit mess of the reloc type.
|
---|
2262 | FIXME: It's a little confusing what the tocv
|
---|
2263 | qualifier can be used for. At the very least, I've
|
---|
2264 | seen three uses, only one of which I'm sure I can
|
---|
2265 | explain. */
|
---|
2266 | if (ex.X_op == O_symbol)
|
---|
2267 | {
|
---|
2268 | assert (ex.X_add_symbol != NULL);
|
---|
2269 | if (symbol_get_bfdsym (ex.X_add_symbol)->section
|
---|
2270 | != tocdata_section)
|
---|
2271 | {
|
---|
2272 | as_bad (_("[tocv] symbol is not a toc symbol"));
|
---|
2273 | }
|
---|
2274 | }
|
---|
2275 |
|
---|
2276 | toc_reloc = BFD_RELOC_PPC_TOC16;
|
---|
2277 | break;
|
---|
2278 | case must_be_32:
|
---|
2279 | /* FIXME: these next two specifically specify 32/64 bit
|
---|
2280 | toc entries. We don't support them today. Is this
|
---|
2281 | the right way to say that? */
|
---|
2282 | toc_reloc = BFD_RELOC_UNUSED;
|
---|
2283 | as_bad (_("Unimplemented toc32 expression modifier"));
|
---|
2284 | break;
|
---|
2285 | case must_be_64:
|
---|
2286 | /* FIXME: see above. */
|
---|
2287 | toc_reloc = BFD_RELOC_UNUSED;
|
---|
2288 | as_bad (_("Unimplemented toc64 expression modifier"));
|
---|
2289 | break;
|
---|
2290 | default:
|
---|
2291 | fprintf (stderr,
|
---|
2292 | _("Unexpected return value [%d] from parse_toc_entry!\n"),
|
---|
2293 | toc_kind);
|
---|
2294 | abort ();
|
---|
2295 | break;
|
---|
2296 | }
|
---|
2297 |
|
---|
2298 | /* We need to generate a fixup for this expression. */
|
---|
2299 | if (fc >= MAX_INSN_FIXUPS)
|
---|
2300 | as_fatal (_("too many fixups"));
|
---|
2301 |
|
---|
2302 | fixups[fc].reloc = toc_reloc;
|
---|
2303 | fixups[fc].exp = ex;
|
---|
2304 | fixups[fc].opindex = *opindex_ptr;
|
---|
2305 | ++fc;
|
---|
2306 |
|
---|
2307 | /* Ok. We've set up the fixup for the instruction. Now make it
|
---|
2308 | look like the constant 0 was found here. */
|
---|
2309 | ex.X_unsigned = 1;
|
---|
2310 | ex.X_op = O_constant;
|
---|
2311 | ex.X_add_number = 0;
|
---|
2312 | ex.X_add_symbol = NULL;
|
---|
2313 | ex.X_op_symbol = NULL;
|
---|
2314 | }
|
---|
2315 |
|
---|
2316 | else
|
---|
2317 | #endif /* TE_PE */
|
---|
2318 | {
|
---|
2319 | if (! register_name (&ex))
|
---|
2320 | {
|
---|
2321 | if ((operand->flags & PPC_OPERAND_CR) != 0)
|
---|
2322 | cr_operand = TRUE;
|
---|
2323 | expression (&ex);
|
---|
2324 | cr_operand = FALSE;
|
---|
2325 | }
|
---|
2326 | }
|
---|
2327 |
|
---|
2328 | str = input_line_pointer;
|
---|
2329 | input_line_pointer = hold;
|
---|
2330 |
|
---|
2331 | if (ex.X_op == O_illegal)
|
---|
2332 | as_bad (_("illegal operand"));
|
---|
2333 | else if (ex.X_op == O_absent)
|
---|
2334 | as_bad (_("missing operand"));
|
---|
2335 | else if (ex.X_op == O_register)
|
---|
2336 | {
|
---|
2337 | insn = ppc_insert_operand (insn, operand, ex.X_add_number,
|
---|
2338 | (char *) NULL, 0);
|
---|
2339 | }
|
---|
2340 | else if (ex.X_op == O_constant)
|
---|
2341 | {
|
---|
2342 | #ifdef OBJ_ELF
|
---|
2343 | /* Allow @HA, @L, @H on constants. */
|
---|
2344 | char *orig_str = str;
|
---|
2345 |
|
---|
2346 | if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
|
---|
2347 | switch (reloc)
|
---|
2348 | {
|
---|
2349 | default:
|
---|
2350 | str = orig_str;
|
---|
2351 | break;
|
---|
2352 |
|
---|
2353 | case BFD_RELOC_LO16:
|
---|
2354 | /* X_unsigned is the default, so if the user has done
|
---|
2355 | something which cleared it, we always produce a
|
---|
2356 | signed value. */
|
---|
2357 | if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
|
---|
2358 | ex.X_add_number &= 0xffff;
|
---|
2359 | else
|
---|
2360 | ex.X_add_number = SEX16 (ex.X_add_number);
|
---|
2361 | break;
|
---|
2362 |
|
---|
2363 | case BFD_RELOC_HI16:
|
---|
2364 | if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
|
---|
2365 | ex.X_add_number = PPC_HI (ex.X_add_number);
|
---|
2366 | else
|
---|
2367 | ex.X_add_number = SEX16 (PPC_HI (ex.X_add_number));
|
---|
2368 | break;
|
---|
2369 |
|
---|
2370 | case BFD_RELOC_HI16_S:
|
---|
2371 | if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
|
---|
2372 | ex.X_add_number = PPC_HA (ex.X_add_number);
|
---|
2373 | else
|
---|
2374 | ex.X_add_number = SEX16 (PPC_HA (ex.X_add_number));
|
---|
2375 | break;
|
---|
2376 |
|
---|
2377 | case BFD_RELOC_PPC64_HIGHER:
|
---|
2378 | if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
|
---|
2379 | ex.X_add_number = PPC_HIGHER (ex.X_add_number);
|
---|
2380 | else
|
---|
2381 | ex.X_add_number = SEX16 (PPC_HIGHER (ex.X_add_number));
|
---|
2382 | break;
|
---|
2383 |
|
---|
2384 | case BFD_RELOC_PPC64_HIGHER_S:
|
---|
2385 | if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
|
---|
2386 | ex.X_add_number = PPC_HIGHERA (ex.X_add_number);
|
---|
2387 | else
|
---|
2388 | ex.X_add_number = SEX16 (PPC_HIGHERA (ex.X_add_number));
|
---|
2389 | break;
|
---|
2390 |
|
---|
2391 | case BFD_RELOC_PPC64_HIGHEST:
|
---|
2392 | if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
|
---|
2393 | ex.X_add_number = PPC_HIGHEST (ex.X_add_number);
|
---|
2394 | else
|
---|
2395 | ex.X_add_number = SEX16 (PPC_HIGHEST (ex.X_add_number));
|
---|
2396 | break;
|
---|
2397 |
|
---|
2398 | case BFD_RELOC_PPC64_HIGHEST_S:
|
---|
2399 | if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
|
---|
2400 | ex.X_add_number = PPC_HIGHESTA (ex.X_add_number);
|
---|
2401 | else
|
---|
2402 | ex.X_add_number = SEX16 (PPC_HIGHESTA (ex.X_add_number));
|
---|
2403 | break;
|
---|
2404 | }
|
---|
2405 | #endif /* OBJ_ELF */
|
---|
2406 | insn = ppc_insert_operand (insn, operand, ex.X_add_number,
|
---|
2407 | (char *) NULL, 0);
|
---|
2408 | }
|
---|
2409 | #ifdef OBJ_ELF
|
---|
2410 | else if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
|
---|
2411 | {
|
---|
2412 | /* Some TLS tweaks. */
|
---|
2413 | switch (reloc)
|
---|
2414 | {
|
---|
2415 | default:
|
---|
2416 | break;
|
---|
2417 | case BFD_RELOC_PPC_TLS:
|
---|
2418 | insn = ppc_insert_operand (insn, operand, ppc_obj64 ? 13 : 2,
|
---|
2419 | (char *) NULL, 0);
|
---|
2420 | break;
|
---|
2421 | /* We'll only use the 32 (or 64) bit form of these relocations
|
---|
2422 | in constants. Instructions get the 16 bit form. */
|
---|
2423 | case BFD_RELOC_PPC_DTPREL:
|
---|
2424 | reloc = BFD_RELOC_PPC_DTPREL16;
|
---|
2425 | break;
|
---|
2426 | case BFD_RELOC_PPC_TPREL:
|
---|
2427 | reloc = BFD_RELOC_PPC_TPREL16;
|
---|
2428 | break;
|
---|
2429 | }
|
---|
2430 |
|
---|
2431 | /* For the absolute forms of branches, convert the PC
|
---|
2432 | relative form back into the absolute. */
|
---|
2433 | if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
|
---|
2434 | {
|
---|
2435 | switch (reloc)
|
---|
2436 | {
|
---|
2437 | case BFD_RELOC_PPC_B26:
|
---|
2438 | reloc = BFD_RELOC_PPC_BA26;
|
---|
2439 | break;
|
---|
2440 | case BFD_RELOC_PPC_B16:
|
---|
2441 | reloc = BFD_RELOC_PPC_BA16;
|
---|
2442 | break;
|
---|
2443 | case BFD_RELOC_PPC_B16_BRTAKEN:
|
---|
2444 | reloc = BFD_RELOC_PPC_BA16_BRTAKEN;
|
---|
2445 | break;
|
---|
2446 | case BFD_RELOC_PPC_B16_BRNTAKEN:
|
---|
2447 | reloc = BFD_RELOC_PPC_BA16_BRNTAKEN;
|
---|
2448 | break;
|
---|
2449 | default:
|
---|
2450 | break;
|
---|
2451 | }
|
---|
2452 | }
|
---|
2453 |
|
---|
2454 | if (ppc_obj64
|
---|
2455 | && (operand->flags & PPC_OPERAND_DS) != 0)
|
---|
2456 | {
|
---|
2457 | switch (reloc)
|
---|
2458 | {
|
---|
2459 | case BFD_RELOC_16:
|
---|
2460 | reloc = BFD_RELOC_PPC64_ADDR16_DS;
|
---|
2461 | break;
|
---|
2462 | case BFD_RELOC_LO16:
|
---|
2463 | reloc = BFD_RELOC_PPC64_ADDR16_LO_DS;
|
---|
2464 | break;
|
---|
2465 | case BFD_RELOC_16_GOTOFF:
|
---|
2466 | reloc = BFD_RELOC_PPC64_GOT16_DS;
|
---|
2467 | break;
|
---|
2468 | case BFD_RELOC_LO16_GOTOFF:
|
---|
2469 | reloc = BFD_RELOC_PPC64_GOT16_LO_DS;
|
---|
2470 | break;
|
---|
2471 | case BFD_RELOC_LO16_PLTOFF:
|
---|
2472 | reloc = BFD_RELOC_PPC64_PLT16_LO_DS;
|
---|
2473 | break;
|
---|
2474 | case BFD_RELOC_16_BASEREL:
|
---|
2475 | reloc = BFD_RELOC_PPC64_SECTOFF_DS;
|
---|
2476 | break;
|
---|
2477 | case BFD_RELOC_LO16_BASEREL:
|
---|
2478 | reloc = BFD_RELOC_PPC64_SECTOFF_LO_DS;
|
---|
2479 | break;
|
---|
2480 | case BFD_RELOC_PPC_TOC16:
|
---|
2481 | reloc = BFD_RELOC_PPC64_TOC16_DS;
|
---|
2482 | break;
|
---|
2483 | case BFD_RELOC_PPC64_TOC16_LO:
|
---|
2484 | reloc = BFD_RELOC_PPC64_TOC16_LO_DS;
|
---|
2485 | break;
|
---|
2486 | case BFD_RELOC_PPC64_PLTGOT16:
|
---|
2487 | reloc = BFD_RELOC_PPC64_PLTGOT16_DS;
|
---|
2488 | break;
|
---|
2489 | case BFD_RELOC_PPC64_PLTGOT16_LO:
|
---|
2490 | reloc = BFD_RELOC_PPC64_PLTGOT16_LO_DS;
|
---|
2491 | break;
|
---|
2492 | case BFD_RELOC_PPC_DTPREL16:
|
---|
2493 | reloc = BFD_RELOC_PPC64_DTPREL16_DS;
|
---|
2494 | break;
|
---|
2495 | case BFD_RELOC_PPC_DTPREL16_LO:
|
---|
2496 | reloc = BFD_RELOC_PPC64_DTPREL16_LO_DS;
|
---|
2497 | break;
|
---|
2498 | case BFD_RELOC_PPC_TPREL16:
|
---|
2499 | reloc = BFD_RELOC_PPC64_TPREL16_DS;
|
---|
2500 | break;
|
---|
2501 | case BFD_RELOC_PPC_TPREL16_LO:
|
---|
2502 | reloc = BFD_RELOC_PPC64_TPREL16_LO_DS;
|
---|
2503 | break;
|
---|
2504 | case BFD_RELOC_PPC_GOT_DTPREL16:
|
---|
2505 | case BFD_RELOC_PPC_GOT_DTPREL16_LO:
|
---|
2506 | case BFD_RELOC_PPC_GOT_TPREL16:
|
---|
2507 | case BFD_RELOC_PPC_GOT_TPREL16_LO:
|
---|
2508 | break;
|
---|
2509 | default:
|
---|
2510 | as_bad (_("unsupported relocation for DS offset field"));
|
---|
2511 | break;
|
---|
2512 | }
|
---|
2513 | }
|
---|
2514 |
|
---|
2515 | /* We need to generate a fixup for this expression. */
|
---|
2516 | if (fc >= MAX_INSN_FIXUPS)
|
---|
2517 | as_fatal (_("too many fixups"));
|
---|
2518 | fixups[fc].exp = ex;
|
---|
2519 | fixups[fc].opindex = 0;
|
---|
2520 | fixups[fc].reloc = reloc;
|
---|
2521 | ++fc;
|
---|
2522 | }
|
---|
2523 | #endif /* OBJ_ELF */
|
---|
2524 |
|
---|
2525 | else
|
---|
2526 | {
|
---|
2527 | /* We need to generate a fixup for this expression. */
|
---|
2528 | if (fc >= MAX_INSN_FIXUPS)
|
---|
2529 | as_fatal (_("too many fixups"));
|
---|
2530 | fixups[fc].exp = ex;
|
---|
2531 | fixups[fc].opindex = *opindex_ptr;
|
---|
2532 | fixups[fc].reloc = BFD_RELOC_UNUSED;
|
---|
2533 | ++fc;
|
---|
2534 | }
|
---|
2535 |
|
---|
2536 | if (need_paren)
|
---|
2537 | {
|
---|
2538 | endc = ')';
|
---|
2539 | need_paren = 0;
|
---|
2540 | }
|
---|
2541 | else if ((operand->flags & PPC_OPERAND_PARENS) != 0)
|
---|
2542 | {
|
---|
2543 | endc = '(';
|
---|
2544 | need_paren = 1;
|
---|
2545 | }
|
---|
2546 | else
|
---|
2547 | endc = ',';
|
---|
2548 |
|
---|
2549 | /* The call to expression should have advanced str past any
|
---|
2550 | whitespace. */
|
---|
2551 | if (*str != endc
|
---|
2552 | && (endc != ',' || *str != '\0'))
|
---|
2553 | {
|
---|
2554 | as_bad (_("syntax error; found `%c' but expected `%c'"), *str, endc);
|
---|
2555 | break;
|
---|
2556 | }
|
---|
2557 |
|
---|
2558 | if (*str != '\0')
|
---|
2559 | ++str;
|
---|
2560 | }
|
---|
2561 |
|
---|
2562 | while (ISSPACE (*str))
|
---|
2563 | ++str;
|
---|
2564 |
|
---|
2565 | if (*str != '\0')
|
---|
2566 | as_bad (_("junk at end of line: `%s'"), str);
|
---|
2567 |
|
---|
2568 | #ifdef OBJ_ELF
|
---|
2569 | /* Do we need/want a APUinfo section? */
|
---|
2570 | if (ppc_cpu & (PPC_OPCODE_SPE
|
---|
2571 | | PPC_OPCODE_ISEL | PPC_OPCODE_EFS
|
---|
2572 | | PPC_OPCODE_BRLOCK | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
|
---|
2573 | | PPC_OPCODE_RFMCI))
|
---|
2574 | {
|
---|
2575 | /* These are all version "1". */
|
---|
2576 | if (opcode->flags & PPC_OPCODE_SPE)
|
---|
2577 | ppc_apuinfo_section_add (PPC_APUINFO_SPE, 1);
|
---|
2578 | if (opcode->flags & PPC_OPCODE_ISEL)
|
---|
2579 | ppc_apuinfo_section_add (PPC_APUINFO_ISEL, 1);
|
---|
2580 | if (opcode->flags & PPC_OPCODE_EFS)
|
---|
2581 | ppc_apuinfo_section_add (PPC_APUINFO_EFS, 1);
|
---|
2582 | if (opcode->flags & PPC_OPCODE_BRLOCK)
|
---|
2583 | ppc_apuinfo_section_add (PPC_APUINFO_BRLOCK, 1);
|
---|
2584 | if (opcode->flags & PPC_OPCODE_PMR)
|
---|
2585 | ppc_apuinfo_section_add (PPC_APUINFO_PMR, 1);
|
---|
2586 | if (opcode->flags & PPC_OPCODE_CACHELCK)
|
---|
2587 | ppc_apuinfo_section_add (PPC_APUINFO_CACHELCK, 1);
|
---|
2588 | if (opcode->flags & PPC_OPCODE_RFMCI)
|
---|
2589 | ppc_apuinfo_section_add (PPC_APUINFO_RFMCI, 1);
|
---|
2590 | }
|
---|
2591 | #endif
|
---|
2592 |
|
---|
2593 | /* Write out the instruction. */
|
---|
2594 | f = frag_more (4);
|
---|
2595 | md_number_to_chars (f, insn, 4);
|
---|
2596 |
|
---|
2597 | #ifdef OBJ_ELF
|
---|
2598 | dwarf2_emit_insn (4);
|
---|
2599 | #endif
|
---|
2600 |
|
---|
2601 | /* Create any fixups. At this point we do not use a
|
---|
2602 | bfd_reloc_code_real_type, but instead just use the
|
---|
2603 | BFD_RELOC_UNUSED plus the operand index. This lets us easily
|
---|
2604 | handle fixups for any operand type, although that is admittedly
|
---|
2605 | not a very exciting feature. We pick a BFD reloc type in
|
---|
2606 | md_apply_fix3. */
|
---|
2607 | for (i = 0; i < fc; i++)
|
---|
2608 | {
|
---|
2609 | const struct powerpc_operand *operand;
|
---|
2610 |
|
---|
2611 | operand = &powerpc_operands[fixups[i].opindex];
|
---|
2612 | if (fixups[i].reloc != BFD_RELOC_UNUSED)
|
---|
2613 | {
|
---|
2614 | reloc_howto_type *reloc_howto;
|
---|
2615 | int size;
|
---|
2616 | int offset;
|
---|
2617 | fixS *fixP;
|
---|
2618 |
|
---|
2619 | reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
|
---|
2620 | if (!reloc_howto)
|
---|
2621 | abort ();
|
---|
2622 |
|
---|
2623 | size = bfd_get_reloc_size (reloc_howto);
|
---|
2624 | offset = target_big_endian ? (4 - size) : 0;
|
---|
2625 |
|
---|
2626 | if (size < 1 || size > 4)
|
---|
2627 | abort ();
|
---|
2628 |
|
---|
2629 | fixP = fix_new_exp (frag_now,
|
---|
2630 | f - frag_now->fr_literal + offset,
|
---|
2631 | size,
|
---|
2632 | &fixups[i].exp,
|
---|
2633 | reloc_howto->pc_relative,
|
---|
2634 | fixups[i].reloc);
|
---|
2635 |
|
---|
2636 | /* Turn off complaints that the addend is too large for things like
|
---|
2637 | foo+100000@ha. */
|
---|
2638 | switch (fixups[i].reloc)
|
---|
2639 | {
|
---|
2640 | case BFD_RELOC_16_GOTOFF:
|
---|
2641 | case BFD_RELOC_PPC_TOC16:
|
---|
2642 | case BFD_RELOC_LO16:
|
---|
2643 | case BFD_RELOC_HI16:
|
---|
2644 | case BFD_RELOC_HI16_S:
|
---|
2645 | #ifdef OBJ_ELF
|
---|
2646 | case BFD_RELOC_PPC64_HIGHER:
|
---|
2647 | case BFD_RELOC_PPC64_HIGHER_S:
|
---|
2648 | case BFD_RELOC_PPC64_HIGHEST:
|
---|
2649 | case BFD_RELOC_PPC64_HIGHEST_S:
|
---|
2650 | #endif
|
---|
2651 | fixP->fx_no_overflow = 1;
|
---|
2652 | break;
|
---|
2653 | default:
|
---|
2654 | break;
|
---|
2655 | }
|
---|
2656 | }
|
---|
2657 | else
|
---|
2658 | fix_new_exp (frag_now,
|
---|
2659 | f - frag_now->fr_literal,
|
---|
2660 | 4,
|
---|
2661 | &fixups[i].exp,
|
---|
2662 | (operand->flags & PPC_OPERAND_RELATIVE) != 0,
|
---|
2663 | ((bfd_reloc_code_real_type)
|
---|
2664 | (fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
|
---|
2665 | }
|
---|
2666 | }
|
---|
2667 |
|
---|
2668 | /* Handle a macro. Gather all the operands, transform them as
|
---|
2669 | described by the macro, and call md_assemble recursively. All the
|
---|
2670 | operands are separated by commas; we don't accept parentheses
|
---|
2671 | around operands here. */
|
---|
2672 |
|
---|
2673 | static void
|
---|
2674 | ppc_macro (str, macro)
|
---|
2675 | char *str;
|
---|
2676 | const struct powerpc_macro *macro;
|
---|
2677 | {
|
---|
2678 | char *operands[10];
|
---|
2679 | unsigned int count;
|
---|
2680 | char *s;
|
---|
2681 | unsigned int len;
|
---|
2682 | const char *format;
|
---|
2683 | int arg;
|
---|
2684 | char *send;
|
---|
2685 | char *complete;
|
---|
2686 |
|
---|
2687 | /* Gather the users operands into the operands array. */
|
---|
2688 | count = 0;
|
---|
2689 | s = str;
|
---|
2690 | while (1)
|
---|
2691 | {
|
---|
2692 | if (count >= sizeof operands / sizeof operands[0])
|
---|
2693 | break;
|
---|
2694 | operands[count++] = s;
|
---|
2695 | s = strchr (s, ',');
|
---|
2696 | if (s == (char *) NULL)
|
---|
2697 | break;
|
---|
2698 | *s++ = '\0';
|
---|
2699 | }
|
---|
2700 |
|
---|
2701 | if (count != macro->operands)
|
---|
2702 | {
|
---|
2703 | as_bad (_("wrong number of operands"));
|
---|
2704 | return;
|
---|
2705 | }
|
---|
2706 |
|
---|
2707 | /* Work out how large the string must be (the size is unbounded
|
---|
2708 | because it includes user input). */
|
---|
2709 | len = 0;
|
---|
2710 | format = macro->format;
|
---|
2711 | while (*format != '\0')
|
---|
2712 | {
|
---|
2713 | if (*format != '%')
|
---|
2714 | {
|
---|
2715 | ++len;
|
---|
2716 | ++format;
|
---|
2717 | }
|
---|
2718 | else
|
---|
2719 | {
|
---|
2720 | arg = strtol (format + 1, &send, 10);
|
---|
2721 | know (send != format && arg >= 0 && arg < count);
|
---|
2722 | len += strlen (operands[arg]);
|
---|
2723 | format = send;
|
---|
2724 | }
|
---|
2725 | }
|
---|
2726 |
|
---|
2727 | /* Put the string together. */
|
---|
2728 | complete = s = (char *) alloca (len + 1);
|
---|
2729 | format = macro->format;
|
---|
2730 | while (*format != '\0')
|
---|
2731 | {
|
---|
2732 | if (*format != '%')
|
---|
2733 | *s++ = *format++;
|
---|
2734 | else
|
---|
2735 | {
|
---|
2736 | arg = strtol (format + 1, &send, 10);
|
---|
2737 | strcpy (s, operands[arg]);
|
---|
2738 | s += strlen (s);
|
---|
2739 | format = send;
|
---|
2740 | }
|
---|
2741 | }
|
---|
2742 | *s = '\0';
|
---|
2743 |
|
---|
2744 | /* Assemble the constructed instruction. */
|
---|
2745 | md_assemble (complete);
|
---|
2746 | }
|
---|
2747 | |
---|
2748 |
|
---|
2749 | #ifdef OBJ_ELF
|
---|
2750 | /* For ELF, add support for SHF_EXCLUDE and SHT_ORDERED. */
|
---|
2751 |
|
---|
2752 | int
|
---|
2753 | ppc_section_letter (letter, ptr_msg)
|
---|
2754 | int letter;
|
---|
2755 | char **ptr_msg;
|
---|
2756 | {
|
---|
2757 | if (letter == 'e')
|
---|
2758 | return SHF_EXCLUDE;
|
---|
2759 |
|
---|
2760 | *ptr_msg = _("Bad .section directive: want a,e,w,x,M,S,G,T in string");
|
---|
2761 | return 0;
|
---|
2762 | }
|
---|
2763 |
|
---|
2764 | int
|
---|
2765 | ppc_section_word (str, len)
|
---|
2766 | char *str;
|
---|
2767 | size_t len;
|
---|
2768 | {
|
---|
2769 | if (len == 7 && strncmp (str, "exclude", 7) == 0)
|
---|
2770 | return SHF_EXCLUDE;
|
---|
2771 |
|
---|
2772 | return -1;
|
---|
2773 | }
|
---|
2774 |
|
---|
2775 | int
|
---|
2776 | ppc_section_type (str, len)
|
---|
2777 | char *str;
|
---|
2778 | size_t len;
|
---|
2779 | {
|
---|
2780 | if (len == 7 && strncmp (str, "ordered", 7) == 0)
|
---|
2781 | return SHT_ORDERED;
|
---|
2782 |
|
---|
2783 | return -1;
|
---|
2784 | }
|
---|
2785 |
|
---|
2786 | int
|
---|
2787 | ppc_section_flags (flags, attr, type)
|
---|
2788 | int flags;
|
---|
2789 | int attr;
|
---|
2790 | int type;
|
---|
2791 | {
|
---|
2792 | if (type == SHT_ORDERED)
|
---|
2793 | flags |= SEC_ALLOC | SEC_LOAD | SEC_SORT_ENTRIES;
|
---|
2794 |
|
---|
2795 | if (attr & SHF_EXCLUDE)
|
---|
2796 | flags |= SEC_EXCLUDE;
|
---|
2797 |
|
---|
2798 | return flags;
|
---|
2799 | }
|
---|
2800 | #endif /* OBJ_ELF */
|
---|
2801 |
|
---|
2802 | |
---|
2803 |
|
---|
2804 | /* Pseudo-op handling. */
|
---|
2805 |
|
---|
2806 | /* The .byte pseudo-op. This is similar to the normal .byte
|
---|
2807 | pseudo-op, but it can also take a single ASCII string. */
|
---|
2808 |
|
---|
2809 | static void
|
---|
2810 | ppc_byte (ignore)
|
---|
2811 | int ignore ATTRIBUTE_UNUSED;
|
---|
2812 | {
|
---|
2813 | if (*input_line_pointer != '\"')
|
---|
2814 | {
|
---|
2815 | cons (1);
|
---|
2816 | return;
|
---|
2817 | }
|
---|
2818 |
|
---|
2819 | /* Gather characters. A real double quote is doubled. Unusual
|
---|
2820 | characters are not permitted. */
|
---|
2821 | ++input_line_pointer;
|
---|
2822 | while (1)
|
---|
2823 | {
|
---|
2824 | char c;
|
---|
2825 |
|
---|
2826 | c = *input_line_pointer++;
|
---|
2827 |
|
---|
2828 | if (c == '\"')
|
---|
2829 | {
|
---|
2830 | if (*input_line_pointer != '\"')
|
---|
2831 | break;
|
---|
2832 | ++input_line_pointer;
|
---|
2833 | }
|
---|
2834 |
|
---|
2835 | FRAG_APPEND_1_CHAR (c);
|
---|
2836 | }
|
---|
2837 |
|
---|
2838 | demand_empty_rest_of_line ();
|
---|
2839 | }
|
---|
2840 | |
---|
2841 |
|
---|
2842 | #ifdef OBJ_XCOFF
|
---|
2843 |
|
---|
2844 | /* XCOFF specific pseudo-op handling. */
|
---|
2845 |
|
---|
2846 | /* This is set if we are creating a .stabx symbol, since we don't want
|
---|
2847 | to handle symbol suffixes for such symbols. */
|
---|
2848 | static bfd_boolean ppc_stab_symbol;
|
---|
2849 |
|
---|
2850 | /* The .comm and .lcomm pseudo-ops for XCOFF. XCOFF puts common
|
---|
2851 | symbols in the .bss segment as though they were local common
|
---|
2852 | symbols, and uses a different smclas. The native Aix 4.3.3 assember
|
---|
2853 | aligns .comm and .lcomm to 4 bytes. */
|
---|
2854 |
|
---|
2855 | static void
|
---|
2856 | ppc_comm (lcomm)
|
---|
2857 | int lcomm;
|
---|
2858 | {
|
---|
2859 | asection *current_seg = now_seg;
|
---|
2860 | subsegT current_subseg = now_subseg;
|
---|
2861 | char *name;
|
---|
2862 | char endc;
|
---|
2863 | char *end_name;
|
---|
2864 | offsetT size;
|
---|
2865 | offsetT align;
|
---|
2866 | symbolS *lcomm_sym = NULL;
|
---|
2867 | symbolS *sym;
|
---|
2868 | char *pfrag;
|
---|
2869 |
|
---|
2870 | name = input_line_pointer;
|
---|
2871 | endc = get_symbol_end ();
|
---|
2872 | end_name = input_line_pointer;
|
---|
2873 | *end_name = endc;
|
---|
2874 |
|
---|
2875 | if (*input_line_pointer != ',')
|
---|
2876 | {
|
---|
2877 | as_bad (_("missing size"));
|
---|
2878 | ignore_rest_of_line ();
|
---|
2879 | return;
|
---|
2880 | }
|
---|
2881 | ++input_line_pointer;
|
---|
2882 |
|
---|
2883 | size = get_absolute_expression ();
|
---|
2884 | if (size < 0)
|
---|
2885 | {
|
---|
2886 | as_bad (_("negative size"));
|
---|
2887 | ignore_rest_of_line ();
|
---|
2888 | return;
|
---|
2889 | }
|
---|
2890 |
|
---|
2891 | if (! lcomm)
|
---|
2892 | {
|
---|
2893 | /* The third argument to .comm is the alignment. */
|
---|
2894 | if (*input_line_pointer != ',')
|
---|
2895 | align = 2;
|
---|
2896 | else
|
---|
2897 | {
|
---|
2898 | ++input_line_pointer;
|
---|
2899 | align = get_absolute_expression ();
|
---|
2900 | if (align <= 0)
|
---|
2901 | {
|
---|
2902 | as_warn (_("ignoring bad alignment"));
|
---|
2903 | align = 2;
|
---|
2904 | }
|
---|
2905 | }
|
---|
2906 | }
|
---|
2907 | else
|
---|
2908 | {
|
---|
2909 | char *lcomm_name;
|
---|
2910 | char lcomm_endc;
|
---|
2911 |
|
---|
2912 | if (size <= 4)
|
---|
2913 | align = 2;
|
---|
2914 | else
|
---|
2915 | align = 3;
|
---|
2916 |
|
---|
2917 | /* The third argument to .lcomm appears to be the real local
|
---|
2918 | common symbol to create. References to the symbol named in
|
---|
2919 | the first argument are turned into references to the third
|
---|
2920 | argument. */
|
---|
2921 | if (*input_line_pointer != ',')
|
---|
2922 | {
|
---|
2923 | as_bad (_("missing real symbol name"));
|
---|
2924 | ignore_rest_of_line ();
|
---|
2925 | return;
|
---|
2926 | }
|
---|
2927 | ++input_line_pointer;
|
---|
2928 |
|
---|
2929 | lcomm_name = input_line_pointer;
|
---|
2930 | lcomm_endc = get_symbol_end ();
|
---|
2931 |
|
---|
2932 | lcomm_sym = symbol_find_or_make (lcomm_name);
|
---|
2933 |
|
---|
2934 | *input_line_pointer = lcomm_endc;
|
---|
2935 | }
|
---|
2936 |
|
---|
2937 | *end_name = '\0';
|
---|
2938 | sym = symbol_find_or_make (name);
|
---|
2939 | *end_name = endc;
|
---|
2940 |
|
---|
2941 | if (S_IS_DEFINED (sym)
|
---|
2942 | || S_GET_VALUE (sym) != 0)
|
---|
2943 | {
|
---|
2944 | as_bad (_("attempt to redefine symbol"));
|
---|
2945 | ignore_rest_of_line ();
|
---|
2946 | return;
|
---|
2947 | }
|
---|
2948 |
|
---|
2949 | record_alignment (bss_section, align);
|
---|
2950 |
|
---|
2951 | if (! lcomm
|
---|
2952 | || ! S_IS_DEFINED (lcomm_sym))
|
---|
2953 | {
|
---|
2954 | symbolS *def_sym;
|
---|
2955 | offsetT def_size;
|
---|
2956 |
|
---|
2957 | if (! lcomm)
|
---|
2958 | {
|
---|
2959 | def_sym = sym;
|
---|
2960 | def_size = size;
|
---|
2961 | S_SET_EXTERNAL (sym);
|
---|
2962 | }
|
---|
2963 | else
|
---|
2964 | {
|
---|
2965 | symbol_get_tc (lcomm_sym)->output = 1;
|
---|
2966 | def_sym = lcomm_sym;
|
---|
2967 | def_size = 0;
|
---|
2968 | }
|
---|
2969 |
|
---|
2970 | subseg_set (bss_section, 1);
|
---|
2971 | frag_align (align, 0, 0);
|
---|
2972 |
|
---|
2973 | symbol_set_frag (def_sym, frag_now);
|
---|
2974 | pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, def_sym,
|
---|
2975 | def_size, (char *) NULL);
|
---|
2976 | *pfrag = 0;
|
---|
2977 | S_SET_SEGMENT (def_sym, bss_section);
|
---|
2978 | symbol_get_tc (def_sym)->align = align;
|
---|
2979 | }
|
---|
2980 | else if (lcomm)
|
---|
2981 | {
|
---|
2982 | /* Align the size of lcomm_sym. */
|
---|
2983 | symbol_get_frag (lcomm_sym)->fr_offset =
|
---|
2984 | ((symbol_get_frag (lcomm_sym)->fr_offset + (1 << align) - 1)
|
---|
2985 | &~ ((1 << align) - 1));
|
---|
2986 | if (align > symbol_get_tc (lcomm_sym)->align)
|
---|
2987 | symbol_get_tc (lcomm_sym)->align = align;
|
---|
2988 | }
|
---|
2989 |
|
---|
2990 | if (lcomm)
|
---|
2991 | {
|
---|
2992 | /* Make sym an offset from lcomm_sym. */
|
---|
2993 | S_SET_SEGMENT (sym, bss_section);
|
---|
2994 | symbol_set_frag (sym, symbol_get_frag (lcomm_sym));
|
---|
2995 | S_SET_VALUE (sym, symbol_get_frag (lcomm_sym)->fr_offset);
|
---|
2996 | symbol_get_frag (lcomm_sym)->fr_offset += size;
|
---|
2997 | }
|
---|
2998 |
|
---|
2999 | subseg_set (current_seg, current_subseg);
|
---|
3000 |
|
---|
3001 | demand_empty_rest_of_line ();
|
---|
3002 | }
|
---|
3003 |
|
---|
3004 | /* The .csect pseudo-op. This switches us into a different
|
---|
3005 | subsegment. The first argument is a symbol whose value is the
|
---|
3006 | start of the .csect. In COFF, csect symbols get special aux
|
---|
3007 | entries defined by the x_csect field of union internal_auxent. The
|
---|
3008 | optional second argument is the alignment (the default is 2). */
|
---|
3009 |
|
---|
3010 | static void
|
---|
3011 | ppc_csect (ignore)
|
---|
3012 | int ignore ATTRIBUTE_UNUSED;
|
---|
3013 | {
|
---|
3014 | char *name;
|
---|
3015 | char endc;
|
---|
3016 | symbolS *sym;
|
---|
3017 |
|
---|
3018 | name = input_line_pointer;
|
---|
3019 | endc = get_symbol_end ();
|
---|
3020 |
|
---|
3021 | sym = symbol_find_or_make (name);
|
---|
3022 |
|
---|
3023 | *input_line_pointer = endc;
|
---|
3024 |
|
---|
3025 | if (S_GET_NAME (sym)[0] == '\0')
|
---|
3026 | {
|
---|
3027 | /* An unnamed csect is assumed to be [PR]. */
|
---|
3028 | symbol_get_tc (sym)->class = XMC_PR;
|
---|
3029 | }
|
---|
3030 |
|
---|
3031 | ppc_change_csect (sym);
|
---|
3032 |
|
---|
3033 | if (*input_line_pointer == ',')
|
---|
3034 | {
|
---|
3035 | ++input_line_pointer;
|
---|
3036 | symbol_get_tc (sym)->align = get_absolute_expression ();
|
---|
3037 | }
|
---|
3038 |
|
---|
3039 | demand_empty_rest_of_line ();
|
---|
3040 | }
|
---|
3041 |
|
---|
3042 | /* Change to a different csect. */
|
---|
3043 |
|
---|
3044 | static void
|
---|
3045 | ppc_change_csect (sym)
|
---|
3046 | symbolS *sym;
|
---|
3047 | {
|
---|
3048 | if (S_IS_DEFINED (sym))
|
---|
3049 | subseg_set (S_GET_SEGMENT (sym), symbol_get_tc (sym)->subseg);
|
---|
3050 | else
|
---|
3051 | {
|
---|
3052 | symbolS **list_ptr;
|
---|
3053 | int after_toc;
|
---|
3054 | int hold_chunksize;
|
---|
3055 | symbolS *list;
|
---|
3056 |
|
---|
3057 | /* This is a new csect. We need to look at the symbol class to
|
---|
3058 | figure out whether it should go in the text section or the
|
---|
3059 | data section. */
|
---|
3060 | after_toc = 0;
|
---|
3061 | switch (symbol_get_tc (sym)->class)
|
---|
3062 | {
|
---|
3063 | case XMC_PR:
|
---|
3064 | case XMC_RO:
|
---|
3065 | case XMC_DB:
|
---|
3066 | case XMC_GL:
|
---|
3067 | case XMC_XO:
|
---|
3068 | case XMC_SV:
|
---|
3069 | case XMC_TI:
|
---|
3070 | case XMC_TB:
|
---|
3071 | S_SET_SEGMENT (sym, text_section);
|
---|
3072 | symbol_get_tc (sym)->subseg = ppc_text_subsegment;
|
---|
3073 | ++ppc_text_subsegment;
|
---|
3074 | list_ptr = &ppc_text_csects;
|
---|
3075 | break;
|
---|
3076 | case XMC_RW:
|
---|
3077 | case XMC_TC0:
|
---|
3078 | case XMC_TC:
|
---|
3079 | case XMC_DS:
|
---|
3080 | case XMC_UA:
|
---|
3081 | case XMC_BS:
|
---|
3082 | case XMC_UC:
|
---|
3083 | if (ppc_toc_csect != NULL
|
---|
3084 | && (symbol_get_tc (ppc_toc_csect)->subseg + 1
|
---|
3085 | == ppc_data_subsegment))
|
---|
3086 | after_toc = 1;
|
---|
3087 | S_SET_SEGMENT (sym, data_section);
|
---|
3088 | symbol_get_tc (sym)->subseg = ppc_data_subsegment;
|
---|
3089 | ++ppc_data_subsegment;
|
---|
3090 | list_ptr = &ppc_data_csects;
|
---|
3091 | break;
|
---|
3092 | default:
|
---|
3093 | abort ();
|
---|
3094 | }
|
---|
3095 |
|
---|
3096 | /* We set the obstack chunk size to a small value before
|
---|
3097 | changing subsegments, so that we don't use a lot of memory
|
---|
3098 | space for what may be a small section. */
|
---|
3099 | hold_chunksize = chunksize;
|
---|
3100 | chunksize = 64;
|
---|
3101 |
|
---|
3102 | subseg_new (segment_name (S_GET_SEGMENT (sym)),
|
---|
3103 | symbol_get_tc (sym)->subseg);
|
---|
3104 |
|
---|
3105 | chunksize = hold_chunksize;
|
---|
3106 |
|
---|
3107 | if (after_toc)
|
---|
3108 | ppc_after_toc_frag = frag_now;
|
---|
3109 |
|
---|
3110 | symbol_set_frag (sym, frag_now);
|
---|
3111 | S_SET_VALUE (sym, (valueT) frag_now_fix ());
|
---|
3112 |
|
---|
3113 | symbol_get_tc (sym)->align = 2;
|
---|
3114 | symbol_get_tc (sym)->output = 1;
|
---|
3115 | symbol_get_tc (sym)->within = sym;
|
---|
3116 |
|
---|
3117 | for (list = *list_ptr;
|
---|
3118 | symbol_get_tc (list)->next != (symbolS *) NULL;
|
---|
3119 | list = symbol_get_tc (list)->next)
|
---|
3120 | ;
|
---|
3121 | symbol_get_tc (list)->next = sym;
|
---|
3122 |
|
---|
3123 | symbol_remove (sym, &symbol_rootP, &symbol_lastP);
|
---|
3124 | symbol_append (sym, symbol_get_tc (list)->within, &symbol_rootP,
|
---|
3125 | &symbol_lastP);
|
---|
3126 | }
|
---|
3127 |
|
---|
3128 | ppc_current_csect = sym;
|
---|
3129 | }
|
---|
3130 |
|
---|
3131 | /* This function handles the .text and .data pseudo-ops. These
|
---|
3132 | pseudo-ops aren't really used by XCOFF; we implement them for the
|
---|
3133 | convenience of people who aren't used to XCOFF. */
|
---|
3134 |
|
---|
3135 | static void
|
---|
3136 | ppc_section (type)
|
---|
3137 | int type;
|
---|
3138 | {
|
---|
3139 | const char *name;
|
---|
3140 | symbolS *sym;
|
---|
3141 |
|
---|
3142 | if (type == 't')
|
---|
3143 | name = ".text[PR]";
|
---|
3144 | else if (type == 'd')
|
---|
3145 | name = ".data[RW]";
|
---|
3146 | else
|
---|
3147 | abort ();
|
---|
3148 |
|
---|
3149 | sym = symbol_find_or_make (name);
|
---|
3150 |
|
---|
3151 | ppc_change_csect (sym);
|
---|
3152 |
|
---|
3153 | demand_empty_rest_of_line ();
|
---|
3154 | }
|
---|
3155 |
|
---|
3156 | /* This function handles the .section pseudo-op. This is mostly to
|
---|
3157 | give an error, since XCOFF only supports .text, .data and .bss, but
|
---|
3158 | we do permit the user to name the text or data section. */
|
---|
3159 |
|
---|
3160 | static void
|
---|
3161 | ppc_named_section (ignore)
|
---|
3162 | int ignore ATTRIBUTE_UNUSED;
|
---|
3163 | {
|
---|
3164 | char *user_name;
|
---|
3165 | const char *real_name;
|
---|
3166 | char c;
|
---|
3167 | symbolS *sym;
|
---|
3168 |
|
---|
3169 | user_name = input_line_pointer;
|
---|
3170 | c = get_symbol_end ();
|
---|
3171 |
|
---|
3172 | if (strcmp (user_name, ".text") == 0)
|
---|
3173 | real_name = ".text[PR]";
|
---|
3174 | else if (strcmp (user_name, ".data") == 0)
|
---|
3175 | real_name = ".data[RW]";
|
---|
3176 | else
|
---|
3177 | {
|
---|
3178 | as_bad (_("The XCOFF file format does not support arbitrary sections"));
|
---|
3179 | *input_line_pointer = c;
|
---|
3180 | ignore_rest_of_line ();
|
---|
3181 | return;
|
---|
3182 | }
|
---|
3183 |
|
---|
3184 | *input_line_pointer = c;
|
---|
3185 |
|
---|
3186 | sym = symbol_find_or_make (real_name);
|
---|
3187 |
|
---|
3188 | ppc_change_csect (sym);
|
---|
3189 |
|
---|
3190 | demand_empty_rest_of_line ();
|
---|
3191 | }
|
---|
3192 |
|
---|
3193 | /* The .extern pseudo-op. We create an undefined symbol. */
|
---|
3194 |
|
---|
3195 | static void
|
---|
3196 | ppc_extern (ignore)
|
---|
3197 | int ignore ATTRIBUTE_UNUSED;
|
---|
3198 | {
|
---|
3199 | char *name;
|
---|
3200 | char endc;
|
---|
3201 |
|
---|
3202 | name = input_line_pointer;
|
---|
3203 | endc = get_symbol_end ();
|
---|
3204 |
|
---|
3205 | (void) symbol_find_or_make (name);
|
---|
3206 |
|
---|
3207 | *input_line_pointer = endc;
|
---|
3208 |
|
---|
3209 | demand_empty_rest_of_line ();
|
---|
3210 | }
|
---|
3211 |
|
---|
3212 | /* The .lglobl pseudo-op. Keep the symbol in the symbol table. */
|
---|
3213 |
|
---|
3214 | static void
|
---|
3215 | ppc_lglobl (ignore)
|
---|
3216 | int ignore ATTRIBUTE_UNUSED;
|
---|
3217 | {
|
---|
3218 | char *name;
|
---|
3219 | char endc;
|
---|
3220 | symbolS *sym;
|
---|
3221 |
|
---|
3222 | name = input_line_pointer;
|
---|
3223 | endc = get_symbol_end ();
|
---|
3224 |
|
---|
3225 | sym = symbol_find_or_make (name);
|
---|
3226 |
|
---|
3227 | *input_line_pointer = endc;
|
---|
3228 |
|
---|
3229 | symbol_get_tc (sym)->output = 1;
|
---|
3230 |
|
---|
3231 | demand_empty_rest_of_line ();
|
---|
3232 | }
|
---|
3233 |
|
---|
3234 | /* The .rename pseudo-op. The RS/6000 assembler can rename symbols,
|
---|
3235 | although I don't know why it bothers. */
|
---|
3236 |
|
---|
3237 | static void
|
---|
3238 | ppc_rename (ignore)
|
---|
3239 | int ignore ATTRIBUTE_UNUSED;
|
---|
3240 | {
|
---|
3241 | char *name;
|
---|
3242 | char endc;
|
---|
3243 | symbolS *sym;
|
---|
3244 | int len;
|
---|
3245 |
|
---|
3246 | name = input_line_pointer;
|
---|
3247 | endc = get_symbol_end ();
|
---|
3248 |
|
---|
3249 | sym = symbol_find_or_make (name);
|
---|
3250 |
|
---|
3251 | *input_line_pointer = endc;
|
---|
3252 |
|
---|
3253 | if (*input_line_pointer != ',')
|
---|
3254 | {
|
---|
3255 | as_bad (_("missing rename string"));
|
---|
3256 | ignore_rest_of_line ();
|
---|
3257 | return;
|
---|
3258 | }
|
---|
3259 | ++input_line_pointer;
|
---|
3260 |
|
---|
3261 | symbol_get_tc (sym)->real_name = demand_copy_C_string (&len);
|
---|
3262 |
|
---|
3263 | demand_empty_rest_of_line ();
|
---|
3264 | }
|
---|
3265 |
|
---|
3266 | /* The .stabx pseudo-op. This is similar to a normal .stabs
|
---|
3267 | pseudo-op, but slightly different. A sample is
|
---|
3268 | .stabx "main:F-1",.main,142,0
|
---|
3269 | The first argument is the symbol name to create. The second is the
|
---|
3270 | value, and the third is the storage class. The fourth seems to be
|
---|
3271 | always zero, and I am assuming it is the type. */
|
---|
3272 |
|
---|
3273 | static void
|
---|
3274 | ppc_stabx (ignore)
|
---|
3275 | int ignore ATTRIBUTE_UNUSED;
|
---|
3276 | {
|
---|
3277 | char *name;
|
---|
3278 | int len;
|
---|
3279 | symbolS *sym;
|
---|
3280 | expressionS exp;
|
---|
3281 |
|
---|
3282 | name = demand_copy_C_string (&len);
|
---|
3283 |
|
---|
3284 | if (*input_line_pointer != ',')
|
---|
3285 | {
|
---|
3286 | as_bad (_("missing value"));
|
---|
3287 | return;
|
---|
3288 | }
|
---|
3289 | ++input_line_pointer;
|
---|
3290 |
|
---|
3291 | ppc_stab_symbol = TRUE;
|
---|
3292 | sym = symbol_make (name);
|
---|
3293 | ppc_stab_symbol = FALSE;
|
---|
3294 |
|
---|
3295 | symbol_get_tc (sym)->real_name = name;
|
---|
3296 |
|
---|
3297 | (void) expression (&exp);
|
---|
3298 |
|
---|
3299 | switch (exp.X_op)
|
---|
3300 | {
|
---|
3301 | case O_illegal:
|
---|
3302 | case O_absent:
|
---|
3303 | case O_big:
|
---|
3304 | as_bad (_("illegal .stabx expression; zero assumed"));
|
---|
3305 | exp.X_add_number = 0;
|
---|
3306 | /* Fall through. */
|
---|
3307 | case O_constant:
|
---|
3308 | S_SET_VALUE (sym, (valueT) exp.X_add_number);
|
---|
3309 | symbol_set_frag (sym, &zero_address_frag);
|
---|
3310 | break;
|
---|
3311 |
|
---|
3312 | case O_symbol:
|
---|
3313 | if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section)
|
---|
3314 | symbol_set_value_expression (sym, &exp);
|
---|
3315 | else
|
---|
3316 | {
|
---|
3317 | S_SET_VALUE (sym,
|
---|
3318 | exp.X_add_number + S_GET_VALUE (exp.X_add_symbol));
|
---|
3319 | symbol_set_frag (sym, symbol_get_frag (exp.X_add_symbol));
|
---|
3320 | }
|
---|
3321 | break;
|
---|
3322 |
|
---|
3323 | default:
|
---|
3324 | /* The value is some complex expression. This will probably
|
---|
3325 | fail at some later point, but this is probably the right
|
---|
3326 | thing to do here. */
|
---|
3327 | symbol_set_value_expression (sym, &exp);
|
---|
3328 | break;
|
---|
3329 | }
|
---|
3330 |
|
---|
3331 | S_SET_SEGMENT (sym, ppc_coff_debug_section);
|
---|
3332 | symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
|
---|
3333 |
|
---|
3334 | if (*input_line_pointer != ',')
|
---|
3335 | {
|
---|
3336 | as_bad (_("missing class"));
|
---|
3337 | return;
|
---|
3338 | }
|
---|
3339 | ++input_line_pointer;
|
---|
3340 |
|
---|
3341 | S_SET_STORAGE_CLASS (sym, get_absolute_expression ());
|
---|
3342 |
|
---|
3343 | if (*input_line_pointer != ',')
|
---|
3344 | {
|
---|
3345 | as_bad (_("missing type"));
|
---|
3346 | return;
|
---|
3347 | }
|
---|
3348 | ++input_line_pointer;
|
---|
3349 |
|
---|
3350 | S_SET_DATA_TYPE (sym, get_absolute_expression ());
|
---|
3351 |
|
---|
3352 | symbol_get_tc (sym)->output = 1;
|
---|
3353 |
|
---|
3354 | if (S_GET_STORAGE_CLASS (sym) == C_STSYM) {
|
---|
3355 |
|
---|
3356 | symbol_get_tc (sym)->within = ppc_current_block;
|
---|
3357 |
|
---|
3358 | /* In this case :
|
---|
3359 |
|
---|
3360 | .bs name
|
---|
3361 | .stabx "z",arrays_,133,0
|
---|
3362 | .es
|
---|
3363 |
|
---|
3364 | .comm arrays_,13768,3
|
---|
3365 |
|
---|
3366 | resolve_symbol_value will copy the exp's "within" into sym's when the
|
---|
3367 | offset is 0. Since this seems to be corner case problem,
|
---|
3368 | only do the correction for storage class C_STSYM. A better solution
|
---|
3369 | would be to have the tc field updated in ppc_symbol_new_hook. */
|
---|
3370 |
|
---|
3371 | if (exp.X_op == O_symbol)
|
---|
3372 | {
|
---|
3373 | symbol_get_tc (exp.X_add_symbol)->within = ppc_current_block;
|
---|
3374 | }
|
---|
3375 | }
|
---|
3376 |
|
---|
3377 | if (exp.X_op != O_symbol
|
---|
3378 | || ! S_IS_EXTERNAL (exp.X_add_symbol)
|
---|
3379 | || S_GET_SEGMENT (exp.X_add_symbol) != bss_section)
|
---|
3380 | ppc_frob_label (sym);
|
---|
3381 | else
|
---|
3382 | {
|
---|
3383 | symbol_remove (sym, &symbol_rootP, &symbol_lastP);
|
---|
3384 | symbol_append (sym, exp.X_add_symbol, &symbol_rootP, &symbol_lastP);
|
---|
3385 | if (symbol_get_tc (ppc_current_csect)->within == exp.X_add_symbol)
|
---|
3386 | symbol_get_tc (ppc_current_csect)->within = sym;
|
---|
3387 | }
|
---|
3388 |
|
---|
3389 | demand_empty_rest_of_line ();
|
---|
3390 | }
|
---|
3391 |
|
---|
3392 | /* The .function pseudo-op. This takes several arguments. The first
|
---|
3393 | argument seems to be the external name of the symbol. The second
|
---|
3394 | argment seems to be the label for the start of the function. gcc
|
---|
3395 | uses the same name for both. I have no idea what the third and
|
---|
3396 | fourth arguments are meant to be. The optional fifth argument is
|
---|
3397 | an expression for the size of the function. In COFF this symbol
|
---|
3398 | gets an aux entry like that used for a csect. */
|
---|
3399 |
|
---|
3400 | static void
|
---|
3401 | ppc_function (ignore)
|
---|
3402 | int ignore ATTRIBUTE_UNUSED;
|
---|
3403 | {
|
---|
3404 | char *name;
|
---|
3405 | char endc;
|
---|
3406 | char *s;
|
---|
3407 | symbolS *ext_sym;
|
---|
3408 | symbolS *lab_sym;
|
---|
3409 |
|
---|
3410 | name = input_line_pointer;
|
---|
3411 | endc = get_symbol_end ();
|
---|
3412 |
|
---|
3413 | /* Ignore any [PR] suffix. */
|
---|
3414 | name = ppc_canonicalize_symbol_name (name);
|
---|
3415 | s = strchr (name, '[');
|
---|
3416 | if (s != (char *) NULL
|
---|
3417 | && strcmp (s + 1, "PR]") == 0)
|
---|
3418 | *s = '\0';
|
---|
3419 |
|
---|
3420 | ext_sym = symbol_find_or_make (name);
|
---|
3421 |
|
---|
3422 | *input_line_pointer = endc;
|
---|
3423 |
|
---|
3424 | if (*input_line_pointer != ',')
|
---|
3425 | {
|
---|
3426 | as_bad (_("missing symbol name"));
|
---|
3427 | ignore_rest_of_line ();
|
---|
3428 | return;
|
---|
3429 | }
|
---|
3430 | ++input_line_pointer;
|
---|
3431 |
|
---|
3432 | name = input_line_pointer;
|
---|
3433 | endc = get_symbol_end ();
|
---|
3434 |
|
---|
3435 | lab_sym = symbol_find_or_make (name);
|
---|
3436 |
|
---|
3437 | *input_line_pointer = endc;
|
---|
3438 |
|
---|
3439 | if (ext_sym != lab_sym)
|
---|
3440 | {
|
---|
3441 | expressionS exp;
|
---|
3442 |
|
---|
3443 | exp.X_op = O_symbol;
|
---|
3444 | exp.X_add_symbol = lab_sym;
|
---|
3445 | exp.X_op_symbol = NULL;
|
---|
3446 | exp.X_add_number = 0;
|
---|
3447 | exp.X_unsigned = 0;
|
---|
3448 | symbol_set_value_expression (ext_sym, &exp);
|
---|
3449 | }
|
---|
3450 |
|
---|
3451 | if (symbol_get_tc (ext_sym)->class == -1)
|
---|
3452 | symbol_get_tc (ext_sym)->class = XMC_PR;
|
---|
3453 | symbol_get_tc (ext_sym)->output = 1;
|
---|
3454 |
|
---|
3455 | if (*input_line_pointer == ',')
|
---|
3456 | {
|
---|
3457 | expressionS ignore;
|
---|
3458 |
|
---|
3459 | /* Ignore the third argument. */
|
---|
3460 | ++input_line_pointer;
|
---|
3461 | expression (&ignore);
|
---|
3462 | if (*input_line_pointer == ',')
|
---|
3463 | {
|
---|
3464 | /* Ignore the fourth argument. */
|
---|
3465 | ++input_line_pointer;
|
---|
3466 | expression (&ignore);
|
---|
3467 | if (*input_line_pointer == ',')
|
---|
3468 | {
|
---|
3469 | /* The fifth argument is the function size. */
|
---|
3470 | ++input_line_pointer;
|
---|
3471 | symbol_get_tc (ext_sym)->size = symbol_new ("L0\001",
|
---|
3472 | absolute_section,
|
---|
3473 | (valueT) 0,
|
---|
3474 | &zero_address_frag);
|
---|
3475 | pseudo_set (symbol_get_tc (ext_sym)->size);
|
---|
3476 | }
|
---|
3477 | }
|
---|
3478 | }
|
---|
3479 |
|
---|
3480 | S_SET_DATA_TYPE (ext_sym, DT_FCN << N_BTSHFT);
|
---|
3481 | SF_SET_FUNCTION (ext_sym);
|
---|
3482 | SF_SET_PROCESS (ext_sym);
|
---|
3483 | coff_add_linesym (ext_sym);
|
---|
3484 |
|
---|
3485 | demand_empty_rest_of_line ();
|
---|
3486 | }
|
---|
3487 |
|
---|
3488 | /* The .bf pseudo-op. This is just like a COFF C_FCN symbol named
|
---|
3489 | ".bf". If the pseudo op .bi was seen before .bf, patch the .bi sym
|
---|
3490 | with the correct line number */
|
---|
3491 |
|
---|
3492 | static symbolS *saved_bi_sym = 0;
|
---|
3493 |
|
---|
3494 | static void
|
---|
3495 | ppc_bf (ignore)
|
---|
3496 | int ignore ATTRIBUTE_UNUSED;
|
---|
3497 | {
|
---|
3498 | symbolS *sym;
|
---|
3499 |
|
---|
3500 | sym = symbol_make (".bf");
|
---|
3501 | S_SET_SEGMENT (sym, text_section);
|
---|
3502 | symbol_set_frag (sym, frag_now);
|
---|
3503 | S_SET_VALUE (sym, frag_now_fix ());
|
---|
3504 | S_SET_STORAGE_CLASS (sym, C_FCN);
|
---|
3505 |
|
---|
3506 | coff_line_base = get_absolute_expression ();
|
---|
3507 |
|
---|
3508 | S_SET_NUMBER_AUXILIARY (sym, 1);
|
---|
3509 | SA_SET_SYM_LNNO (sym, coff_line_base);
|
---|
3510 |
|
---|
3511 | /* Line number for bi. */
|
---|
3512 | if (saved_bi_sym)
|
---|
3513 | {
|
---|
3514 | S_SET_VALUE (saved_bi_sym, coff_n_line_nos);
|
---|
3515 | saved_bi_sym = 0;
|
---|
3516 | }
|
---|
3517 |
|
---|
3518 |
|
---|
3519 | symbol_get_tc (sym)->output = 1;
|
---|
3520 |
|
---|
3521 | ppc_frob_label (sym);
|
---|
3522 |
|
---|
3523 | demand_empty_rest_of_line ();
|
---|
3524 | }
|
---|
3525 |
|
---|
3526 | /* The .ef pseudo-op. This is just like a COFF C_FCN symbol named
|
---|
3527 | ".ef", except that the line number is absolute, not relative to the
|
---|
3528 | most recent ".bf" symbol. */
|
---|
3529 |
|
---|
3530 | static void
|
---|
3531 | ppc_ef (ignore)
|
---|
3532 | int ignore ATTRIBUTE_UNUSED;
|
---|
3533 | {
|
---|
3534 | symbolS *sym;
|
---|
3535 |
|
---|
3536 | sym = symbol_make (".ef");
|
---|
3537 | S_SET_SEGMENT (sym, text_section);
|
---|
3538 | symbol_set_frag (sym, frag_now);
|
---|
3539 | S_SET_VALUE (sym, frag_now_fix ());
|
---|
3540 | S_SET_STORAGE_CLASS (sym, C_FCN);
|
---|
3541 | S_SET_NUMBER_AUXILIARY (sym, 1);
|
---|
3542 | SA_SET_SYM_LNNO (sym, get_absolute_expression ());
|
---|
3543 | symbol_get_tc (sym)->output = 1;
|
---|
3544 |
|
---|
3545 | ppc_frob_label (sym);
|
---|
3546 |
|
---|
3547 | demand_empty_rest_of_line ();
|
---|
3548 | }
|
---|
3549 |
|
---|
3550 | /* The .bi and .ei pseudo-ops. These take a string argument and
|
---|
3551 | generates a C_BINCL or C_EINCL symbol, which goes at the start of
|
---|
3552 | the symbol list. The value of .bi will be know when the next .bf
|
---|
3553 | is encountered. */
|
---|
3554 |
|
---|
3555 | static void
|
---|
3556 | ppc_biei (ei)
|
---|
3557 | int ei;
|
---|
3558 | {
|
---|
3559 | static symbolS *last_biei;
|
---|
3560 |
|
---|
3561 | char *name;
|
---|
3562 | int len;
|
---|
3563 | symbolS *sym;
|
---|
3564 | symbolS *look;
|
---|
3565 |
|
---|
3566 | name = demand_copy_C_string (&len);
|
---|
3567 |
|
---|
3568 | /* The value of these symbols is actually file offset. Here we set
|
---|
3569 | the value to the index into the line number entries. In
|
---|
3570 | ppc_frob_symbols we set the fix_line field, which will cause BFD
|
---|
3571 | to do the right thing. */
|
---|
3572 |
|
---|
3573 | sym = symbol_make (name);
|
---|
3574 | /* obj-coff.c currently only handles line numbers correctly in the
|
---|
3575 | .text section. */
|
---|
3576 | S_SET_SEGMENT (sym, text_section);
|
---|
3577 | S_SET_VALUE (sym, coff_n_line_nos);
|
---|
3578 | symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
|
---|
3579 |
|
---|
3580 | S_SET_STORAGE_CLASS (sym, ei ? C_EINCL : C_BINCL);
|
---|
3581 | symbol_get_tc (sym)->output = 1;
|
---|
3582 |
|
---|
3583 | /* Save bi. */
|
---|
3584 | if (ei)
|
---|
3585 | saved_bi_sym = 0;
|
---|
3586 | else
|
---|
3587 | saved_bi_sym = sym;
|
---|
3588 |
|
---|
3589 | for (look = last_biei ? last_biei : symbol_rootP;
|
---|
3590 | (look != (symbolS *) NULL
|
---|
3591 | && (S_GET_STORAGE_CLASS (look) == C_FILE
|
---|
3592 | || S_GET_STORAGE_CLASS (look) == C_BINCL
|
---|
3593 | || S_GET_STORAGE_CLASS (look) == C_EINCL));
|
---|
3594 | look = symbol_next (look))
|
---|
3595 | ;
|
---|
3596 | if (look != (symbolS *) NULL)
|
---|
3597 | {
|
---|
3598 | symbol_remove (sym, &symbol_rootP, &symbol_lastP);
|
---|
3599 | symbol_insert (sym, look, &symbol_rootP, &symbol_lastP);
|
---|
3600 | last_biei = sym;
|
---|
3601 | }
|
---|
3602 |
|
---|
3603 | demand_empty_rest_of_line ();
|
---|
3604 | }
|
---|
3605 |
|
---|
3606 | /* The .bs pseudo-op. This generates a C_BSTAT symbol named ".bs".
|
---|
3607 | There is one argument, which is a csect symbol. The value of the
|
---|
3608 | .bs symbol is the index of this csect symbol. */
|
---|
3609 |
|
---|
3610 | static void
|
---|
3611 | ppc_bs (ignore)
|
---|
3612 | int ignore ATTRIBUTE_UNUSED;
|
---|
3613 | {
|
---|
3614 | char *name;
|
---|
3615 | char endc;
|
---|
3616 | symbolS *csect;
|
---|
3617 | symbolS *sym;
|
---|
3618 |
|
---|
3619 | if (ppc_current_block != NULL)
|
---|
3620 | as_bad (_("nested .bs blocks"));
|
---|
3621 |
|
---|
3622 | name = input_line_pointer;
|
---|
3623 | endc = get_symbol_end ();
|
---|
3624 |
|
---|
3625 | csect = symbol_find_or_make (name);
|
---|
3626 |
|
---|
3627 | *input_line_pointer = endc;
|
---|
3628 |
|
---|
3629 | sym = symbol_make (".bs");
|
---|
3630 | S_SET_SEGMENT (sym, now_seg);
|
---|
3631 | S_SET_STORAGE_CLASS (sym, C_BSTAT);
|
---|
3632 | symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
|
---|
3633 | symbol_get_tc (sym)->output = 1;
|
---|
3634 |
|
---|
3635 | symbol_get_tc (sym)->within = csect;
|
---|
3636 |
|
---|
3637 | ppc_frob_label (sym);
|
---|
3638 |
|
---|
3639 | ppc_current_block = sym;
|
---|
3640 |
|
---|
3641 | demand_empty_rest_of_line ();
|
---|
3642 | }
|
---|
3643 |
|
---|
3644 | /* The .es pseudo-op. Generate a C_ESTART symbol named .es. */
|
---|
3645 |
|
---|
3646 | static void
|
---|
3647 | ppc_es (ignore)
|
---|
3648 | int ignore ATTRIBUTE_UNUSED;
|
---|
3649 | {
|
---|
3650 | symbolS *sym;
|
---|
3651 |
|
---|
3652 | if (ppc_current_block == NULL)
|
---|
3653 | as_bad (_(".es without preceding .bs"));
|
---|
3654 |
|
---|
3655 | sym = symbol_make (".es");
|
---|
3656 | S_SET_SEGMENT (sym, now_seg);
|
---|
3657 | S_SET_STORAGE_CLASS (sym, C_ESTAT);
|
---|
3658 | symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
|
---|
3659 | symbol_get_tc (sym)->output = 1;
|
---|
3660 |
|
---|
3661 | ppc_frob_label (sym);
|
---|
3662 |
|
---|
3663 | ppc_current_block = NULL;
|
---|
3664 |
|
---|
3665 | demand_empty_rest_of_line ();
|
---|
3666 | }
|
---|
3667 |
|
---|
3668 | /* The .bb pseudo-op. Generate a C_BLOCK symbol named .bb, with a
|
---|
3669 | line number. */
|
---|
3670 |
|
---|
3671 | static void
|
---|
3672 | ppc_bb (ignore)
|
---|
3673 | int ignore ATTRIBUTE_UNUSED;
|
---|
3674 | {
|
---|
3675 | symbolS *sym;
|
---|
3676 |
|
---|
3677 | sym = symbol_make (".bb");
|
---|
3678 | S_SET_SEGMENT (sym, text_section);
|
---|
3679 | symbol_set_frag (sym, frag_now);
|
---|
3680 | S_SET_VALUE (sym, frag_now_fix ());
|
---|
3681 | S_SET_STORAGE_CLASS (sym, C_BLOCK);
|
---|
3682 |
|
---|
3683 | S_SET_NUMBER_AUXILIARY (sym, 1);
|
---|
3684 | SA_SET_SYM_LNNO (sym, get_absolute_expression ());
|
---|
3685 |
|
---|
3686 | symbol_get_tc (sym)->output = 1;
|
---|
3687 |
|
---|
3688 | SF_SET_PROCESS (sym);
|
---|
3689 |
|
---|
3690 | ppc_frob_label (sym);
|
---|
3691 |
|
---|
3692 | demand_empty_rest_of_line ();
|
---|
3693 | }
|
---|
3694 |
|
---|
3695 | /* The .eb pseudo-op. Generate a C_BLOCK symbol named .eb, with a
|
---|
3696 | line number. */
|
---|
3697 |
|
---|
3698 | static void
|
---|
3699 | ppc_eb (ignore)
|
---|
3700 | int ignore ATTRIBUTE_UNUSED;
|
---|
3701 | {
|
---|
3702 | symbolS *sym;
|
---|
3703 |
|
---|
3704 | sym = symbol_make (".eb");
|
---|
3705 | S_SET_SEGMENT (sym, text_section);
|
---|
3706 | symbol_set_frag (sym, frag_now);
|
---|
3707 | S_SET_VALUE (sym, frag_now_fix ());
|
---|
3708 | S_SET_STORAGE_CLASS (sym, C_BLOCK);
|
---|
3709 | S_SET_NUMBER_AUXILIARY (sym, 1);
|
---|
3710 | SA_SET_SYM_LNNO (sym, get_absolute_expression ());
|
---|
3711 | symbol_get_tc (sym)->output = 1;
|
---|
3712 |
|
---|
3713 | SF_SET_PROCESS (sym);
|
---|
3714 |
|
---|
3715 | ppc_frob_label (sym);
|
---|
3716 |
|
---|
3717 | demand_empty_rest_of_line ();
|
---|
3718 | }
|
---|
3719 |
|
---|
3720 | /* The .bc pseudo-op. This just creates a C_BCOMM symbol with a
|
---|
3721 | specified name. */
|
---|
3722 |
|
---|
3723 | static void
|
---|
3724 | ppc_bc (ignore)
|
---|
3725 | int ignore ATTRIBUTE_UNUSED;
|
---|
3726 | {
|
---|
3727 | char *name;
|
---|
3728 | int len;
|
---|
3729 | symbolS *sym;
|
---|
3730 |
|
---|
3731 | name = demand_copy_C_string (&len);
|
---|
3732 | sym = symbol_make (name);
|
---|
3733 | S_SET_SEGMENT (sym, ppc_coff_debug_section);
|
---|
3734 | symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
|
---|
3735 | S_SET_STORAGE_CLASS (sym, C_BCOMM);
|
---|
3736 | S_SET_VALUE (sym, 0);
|
---|
3737 | symbol_get_tc (sym)->output = 1;
|
---|
3738 |
|
---|
3739 | ppc_frob_label (sym);
|
---|
3740 |
|
---|
3741 | demand_empty_rest_of_line ();
|
---|
3742 | }
|
---|
3743 |
|
---|
3744 | /* The .ec pseudo-op. This just creates a C_ECOMM symbol. */
|
---|
3745 |
|
---|
3746 | static void
|
---|
3747 | ppc_ec (ignore)
|
---|
3748 | int ignore ATTRIBUTE_UNUSED;
|
---|
3749 | {
|
---|
3750 | symbolS *sym;
|
---|
3751 |
|
---|
3752 | sym = symbol_make (".ec");
|
---|
3753 | S_SET_SEGMENT (sym, ppc_coff_debug_section);
|
---|
3754 | symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
|
---|
3755 | S_SET_STORAGE_CLASS (sym, C_ECOMM);
|
---|
3756 | S_SET_VALUE (sym, 0);
|
---|
3757 | symbol_get_tc (sym)->output = 1;
|
---|
3758 |
|
---|
3759 | ppc_frob_label (sym);
|
---|
3760 |
|
---|
3761 | demand_empty_rest_of_line ();
|
---|
3762 | }
|
---|
3763 |
|
---|
3764 | /* The .toc pseudo-op. Switch to the .toc subsegment. */
|
---|
3765 |
|
---|
3766 | static void
|
---|
3767 | ppc_toc (ignore)
|
---|
3768 | int ignore ATTRIBUTE_UNUSED;
|
---|
3769 | {
|
---|
3770 | if (ppc_toc_csect != (symbolS *) NULL)
|
---|
3771 | subseg_set (data_section, symbol_get_tc (ppc_toc_csect)->subseg);
|
---|
3772 | else
|
---|
3773 | {
|
---|
3774 | subsegT subseg;
|
---|
3775 | symbolS *sym;
|
---|
3776 | symbolS *list;
|
---|
3777 |
|
---|
3778 | subseg = ppc_data_subsegment;
|
---|
3779 | ++ppc_data_subsegment;
|
---|
3780 |
|
---|
3781 | subseg_new (segment_name (data_section), subseg);
|
---|
3782 | ppc_toc_frag = frag_now;
|
---|
3783 |
|
---|
3784 | sym = symbol_find_or_make ("TOC[TC0]");
|
---|
3785 | symbol_set_frag (sym, frag_now);
|
---|
3786 | S_SET_SEGMENT (sym, data_section);
|
---|
3787 | S_SET_VALUE (sym, (valueT) frag_now_fix ());
|
---|
3788 | symbol_get_tc (sym)->subseg = subseg;
|
---|
3789 | symbol_get_tc (sym)->output = 1;
|
---|
3790 | symbol_get_tc (sym)->within = sym;
|
---|
3791 |
|
---|
3792 | ppc_toc_csect = sym;
|
---|
3793 |
|
---|
3794 | for (list = ppc_data_csects;
|
---|
3795 | symbol_get_tc (list)->next != (symbolS *) NULL;
|
---|
3796 | list = symbol_get_tc (list)->next)
|
---|
3797 | ;
|
---|
3798 | symbol_get_tc (list)->next = sym;
|
---|
3799 |
|
---|
3800 | symbol_remove (sym, &symbol_rootP, &symbol_lastP);
|
---|
3801 | symbol_append (sym, symbol_get_tc (list)->within, &symbol_rootP,
|
---|
3802 | &symbol_lastP);
|
---|
3803 | }
|
---|
3804 |
|
---|
3805 | ppc_current_csect = ppc_toc_csect;
|
---|
3806 |
|
---|
3807 | demand_empty_rest_of_line ();
|
---|
3808 | }
|
---|
3809 |
|
---|
3810 | /* The AIX assembler automatically aligns the operands of a .long or
|
---|
3811 | .short pseudo-op, and we want to be compatible. */
|
---|
3812 |
|
---|
3813 | static void
|
---|
3814 | ppc_xcoff_cons (log_size)
|
---|
3815 | int log_size;
|
---|
3816 | {
|
---|
3817 | frag_align (log_size, 0, 0);
|
---|
3818 | record_alignment (now_seg, log_size);
|
---|
3819 | cons (1 << log_size);
|
---|
3820 | }
|
---|
3821 |
|
---|
3822 | static void
|
---|
3823 | ppc_vbyte (dummy)
|
---|
3824 | int dummy ATTRIBUTE_UNUSED;
|
---|
3825 | {
|
---|
3826 | expressionS exp;
|
---|
3827 | int byte_count;
|
---|
3828 |
|
---|
3829 | (void) expression (&exp);
|
---|
3830 |
|
---|
3831 | if (exp.X_op != O_constant)
|
---|
3832 | {
|
---|
3833 | as_bad (_("non-constant byte count"));
|
---|
3834 | return;
|
---|
3835 | }
|
---|
3836 |
|
---|
3837 | byte_count = exp.X_add_number;
|
---|
3838 |
|
---|
3839 | if (*input_line_pointer != ',')
|
---|
3840 | {
|
---|
3841 | as_bad (_("missing value"));
|
---|
3842 | return;
|
---|
3843 | }
|
---|
3844 |
|
---|
3845 | ++input_line_pointer;
|
---|
3846 | cons (byte_count);
|
---|
3847 | }
|
---|
3848 |
|
---|
3849 | #endif /* OBJ_XCOFF */
|
---|
3850 | #if defined (OBJ_XCOFF) || defined (OBJ_ELF)
|
---|
3851 | |
---|
3852 |
|
---|
3853 | /* The .tc pseudo-op. This is used when generating either XCOFF or
|
---|
3854 | ELF. This takes two or more arguments.
|
---|
3855 |
|
---|
3856 | When generating XCOFF output, the first argument is the name to
|
---|
3857 | give to this location in the toc; this will be a symbol with class
|
---|
3858 | TC. The rest of the arguments are N-byte values to actually put at
|
---|
3859 | this location in the TOC; often there is just one more argument, a
|
---|
3860 | relocateable symbol reference. The size of the value to store
|
---|
3861 | depends on target word size. A 32-bit target uses 4-byte values, a
|
---|
3862 | 64-bit target uses 8-byte values.
|
---|
3863 |
|
---|
3864 | When not generating XCOFF output, the arguments are the same, but
|
---|
3865 | the first argument is simply ignored. */
|
---|
3866 |
|
---|
3867 | static void
|
---|
3868 | ppc_tc (ignore)
|
---|
3869 | int ignore ATTRIBUTE_UNUSED;
|
---|
3870 | {
|
---|
3871 | #ifdef OBJ_XCOFF
|
---|
3872 |
|
---|
3873 | /* Define the TOC symbol name. */
|
---|
3874 | {
|
---|
3875 | char *name;
|
---|
3876 | char endc;
|
---|
3877 | symbolS *sym;
|
---|
3878 |
|
---|
3879 | if (ppc_toc_csect == (symbolS *) NULL
|
---|
3880 | || ppc_toc_csect != ppc_current_csect)
|
---|
3881 | {
|
---|
3882 | as_bad (_(".tc not in .toc section"));
|
---|
3883 | ignore_rest_of_line ();
|
---|
3884 | return;
|
---|
3885 | }
|
---|
3886 |
|
---|
3887 | name = input_line_pointer;
|
---|
3888 | endc = get_symbol_end ();
|
---|
3889 |
|
---|
3890 | sym = symbol_find_or_make (name);
|
---|
3891 |
|
---|
3892 | *input_line_pointer = endc;
|
---|
3893 |
|
---|
3894 | if (S_IS_DEFINED (sym))
|
---|
3895 | {
|
---|
3896 | symbolS *label;
|
---|
3897 |
|
---|
3898 | label = symbol_get_tc (ppc_current_csect)->within;
|
---|
3899 | if (symbol_get_tc (label)->class != XMC_TC0)
|
---|
3900 | {
|
---|
3901 | as_bad (_(".tc with no label"));
|
---|
3902 | ignore_rest_of_line ();
|
---|
3903 | return;
|
---|
3904 | }
|
---|
3905 |
|
---|
3906 | S_SET_SEGMENT (label, S_GET_SEGMENT (sym));
|
---|
3907 | symbol_set_frag (label, symbol_get_frag (sym));
|
---|
3908 | S_SET_VALUE (label, S_GET_VALUE (sym));
|
---|
3909 |
|
---|
3910 | while (! is_end_of_line[(unsigned char) *input_line_pointer])
|
---|
3911 | ++input_line_pointer;
|
---|
3912 |
|
---|
3913 | return;
|
---|
3914 | }
|
---|
3915 |
|
---|
3916 | S_SET_SEGMENT (sym, now_seg);
|
---|
3917 | symbol_set_frag (sym, frag_now);
|
---|
3918 | S_SET_VALUE (sym, (valueT) frag_now_fix ());
|
---|
3919 | symbol_get_tc (sym)->class = XMC_TC;
|
---|
3920 | symbol_get_tc (sym)->output = 1;
|
---|
3921 |
|
---|
3922 | ppc_frob_label (sym);
|
---|
3923 | }
|
---|
3924 |
|
---|
3925 | #endif /* OBJ_XCOFF */
|
---|
3926 | #ifdef OBJ_ELF
|
---|
3927 | int align;
|
---|
3928 |
|
---|
3929 | /* Skip the TOC symbol name. */
|
---|
3930 | while (is_part_of_name (*input_line_pointer)
|
---|
3931 | || *input_line_pointer == '['
|
---|
3932 | || *input_line_pointer == ']'
|
---|
3933 | || *input_line_pointer == '{'
|
---|
3934 | || *input_line_pointer == '}')
|
---|
3935 | ++input_line_pointer;
|
---|
3936 |
|
---|
3937 | /* Align to a four/eight byte boundary. */
|
---|
3938 | align = ppc_obj64 ? 3 : 2;
|
---|
3939 | frag_align (align, 0, 0);
|
---|
3940 | record_alignment (now_seg, align);
|
---|
3941 | #endif /* OBJ_ELF */
|
---|
3942 |
|
---|
3943 | if (*input_line_pointer != ',')
|
---|
3944 | demand_empty_rest_of_line ();
|
---|
3945 | else
|
---|
3946 | {
|
---|
3947 | ++input_line_pointer;
|
---|
3948 | cons (ppc_obj64 ? 8 : 4);
|
---|
3949 | }
|
---|
3950 | }
|
---|
3951 |
|
---|
3952 | /* Pseudo-op .machine. */
|
---|
3953 | /* FIXME: `.machine' is a nop for the moment. It would be nice to
|
---|
3954 | accept this directive on the first line of input and set ppc_obj64
|
---|
3955 | and the target format accordingly. Unfortunately, the target
|
---|
3956 | format is selected in output-file.c:output_file_create before we
|
---|
3957 | even get to md_begin, so it's not possible without changing
|
---|
3958 | as.c:main. */
|
---|
3959 |
|
---|
3960 | static void
|
---|
3961 | ppc_machine (ignore)
|
---|
3962 | int ignore ATTRIBUTE_UNUSED;
|
---|
3963 | {
|
---|
3964 | discard_rest_of_line ();
|
---|
3965 | }
|
---|
3966 |
|
---|
3967 | /* See whether a symbol is in the TOC section. */
|
---|
3968 |
|
---|
3969 | static int
|
---|
3970 | ppc_is_toc_sym (sym)
|
---|
3971 | symbolS *sym;
|
---|
3972 | {
|
---|
3973 | #ifdef OBJ_XCOFF
|
---|
3974 | return symbol_get_tc (sym)->class == XMC_TC;
|
---|
3975 | #endif
|
---|
3976 | #ifdef OBJ_ELF
|
---|
3977 | const char *sname = segment_name (S_GET_SEGMENT (sym));
|
---|
3978 | if (ppc_obj64)
|
---|
3979 | return strcmp (sname, ".toc") == 0;
|
---|
3980 | else
|
---|
3981 | return strcmp (sname, ".got") == 0;
|
---|
3982 | #endif
|
---|
3983 | }
|
---|
3984 | #endif /* defined (OBJ_XCOFF) || defined (OBJ_ELF) */
|
---|
3985 | |
---|
3986 |
|
---|
3987 | #ifdef TE_PE
|
---|
3988 |
|
---|
3989 | /* Pseudo-ops specific to the Windows NT PowerPC PE (coff) format. */
|
---|
3990 |
|
---|
3991 | /* Set the current section. */
|
---|
3992 | static void
|
---|
3993 | ppc_set_current_section (new)
|
---|
3994 | segT new;
|
---|
3995 | {
|
---|
3996 | ppc_previous_section = ppc_current_section;
|
---|
3997 | ppc_current_section = new;
|
---|
3998 | }
|
---|
3999 |
|
---|
4000 | /* pseudo-op: .previous
|
---|
4001 | behaviour: toggles the current section with the previous section.
|
---|
4002 | errors: None
|
---|
4003 | warnings: "No previous section" */
|
---|
4004 |
|
---|
4005 | static void
|
---|
4006 | ppc_previous (ignore)
|
---|
4007 | int ignore ATTRIBUTE_UNUSED;
|
---|
4008 | {
|
---|
4009 | symbolS *tmp;
|
---|
4010 |
|
---|
4011 | if (ppc_previous_section == NULL)
|
---|
4012 | {
|
---|
4013 | as_warn (_("No previous section to return to. Directive ignored."));
|
---|
4014 | return;
|
---|
4015 | }
|
---|
4016 |
|
---|
4017 | subseg_set (ppc_previous_section, 0);
|
---|
4018 |
|
---|
4019 | ppc_set_current_section (ppc_previous_section);
|
---|
4020 | }
|
---|
4021 |
|
---|
4022 | /* pseudo-op: .pdata
|
---|
4023 | behaviour: predefined read only data section
|
---|
4024 | double word aligned
|
---|
4025 | errors: None
|
---|
4026 | warnings: None
|
---|
4027 | initial: .section .pdata "adr3"
|
---|
4028 | a - don't know -- maybe a misprint
|
---|
4029 | d - initialized data
|
---|
4030 | r - readable
|
---|
4031 | 3 - double word aligned (that would be 4 byte boundary)
|
---|
4032 |
|
---|
4033 | commentary:
|
---|
4034 | Tag index tables (also known as the function table) for exception
|
---|
4035 | handling, debugging, etc. */
|
---|
4036 |
|
---|
4037 | static void
|
---|
4038 | ppc_pdata (ignore)
|
---|
4039 | int ignore ATTRIBUTE_UNUSED;
|
---|
4040 | {
|
---|
4041 | if (pdata_section == 0)
|
---|
4042 | {
|
---|
4043 | pdata_section = subseg_new (".pdata", 0);
|
---|
4044 |
|
---|
4045 | bfd_set_section_flags (stdoutput, pdata_section,
|
---|
4046 | (SEC_ALLOC | SEC_LOAD | SEC_RELOC
|
---|
4047 | | SEC_READONLY | SEC_DATA ));
|
---|
4048 |
|
---|
4049 | bfd_set_section_alignment (stdoutput, pdata_section, 2);
|
---|
4050 | }
|
---|
4051 | else
|
---|
4052 | {
|
---|
4053 | pdata_section = subseg_new (".pdata", 0);
|
---|
4054 | }
|
---|
4055 | ppc_set_current_section (pdata_section);
|
---|
4056 | }
|
---|
4057 |
|
---|
4058 | /* pseudo-op: .ydata
|
---|
4059 | behaviour: predefined read only data section
|
---|
4060 | double word aligned
|
---|
4061 | errors: None
|
---|
4062 | warnings: None
|
---|
4063 | initial: .section .ydata "drw3"
|
---|
4064 | a - don't know -- maybe a misprint
|
---|
4065 | d - initialized data
|
---|
4066 | r - readable
|
---|
4067 | 3 - double word aligned (that would be 4 byte boundary)
|
---|
4068 | commentary:
|
---|
4069 | Tag tables (also known as the scope table) for exception handling,
|
---|
4070 | debugging, etc. */
|
---|
4071 |
|
---|
4072 | static void
|
---|
4073 | ppc_ydata (ignore)
|
---|
4074 | int ignore ATTRIBUTE_UNUSED;
|
---|
4075 | {
|
---|
4076 | if (ydata_section == 0)
|
---|
4077 | {
|
---|
4078 | ydata_section = subseg_new (".ydata", 0);
|
---|
4079 | bfd_set_section_flags (stdoutput, ydata_section,
|
---|
4080 | (SEC_ALLOC | SEC_LOAD | SEC_RELOC
|
---|
4081 | | SEC_READONLY | SEC_DATA ));
|
---|
4082 |
|
---|
4083 | bfd_set_section_alignment (stdoutput, ydata_section, 3);
|
---|
4084 | }
|
---|
4085 | else
|
---|
4086 | {
|
---|
4087 | ydata_section = subseg_new (".ydata", 0);
|
---|
4088 | }
|
---|
4089 | ppc_set_current_section (ydata_section);
|
---|
4090 | }
|
---|
4091 |
|
---|
4092 | /* pseudo-op: .reldata
|
---|
4093 | behaviour: predefined read write data section
|
---|
4094 | double word aligned (4-byte)
|
---|
4095 | FIXME: relocation is applied to it
|
---|
4096 | FIXME: what's the difference between this and .data?
|
---|
4097 | errors: None
|
---|
4098 | warnings: None
|
---|
4099 | initial: .section .reldata "drw3"
|
---|
4100 | d - initialized data
|
---|
4101 | r - readable
|
---|
4102 | w - writeable
|
---|
4103 | 3 - double word aligned (that would be 8 byte boundary)
|
---|
4104 |
|
---|
4105 | commentary:
|
---|
4106 | Like .data, but intended to hold data subject to relocation, such as
|
---|
4107 | function descriptors, etc. */
|
---|
4108 |
|
---|
4109 | static void
|
---|
4110 | ppc_reldata (ignore)
|
---|
4111 | int ignore ATTRIBUTE_UNUSED;
|
---|
4112 | {
|
---|
4113 | if (reldata_section == 0)
|
---|
4114 | {
|
---|
4115 | reldata_section = subseg_new (".reldata", 0);
|
---|
4116 |
|
---|
4117 | bfd_set_section_flags (stdoutput, reldata_section,
|
---|
4118 | (SEC_ALLOC | SEC_LOAD | SEC_RELOC
|
---|
4119 | | SEC_DATA));
|
---|
4120 |
|
---|
4121 | bfd_set_section_alignment (stdoutput, reldata_section, 2);
|
---|
4122 | }
|
---|
4123 | else
|
---|
4124 | {
|
---|
4125 | reldata_section = subseg_new (".reldata", 0);
|
---|
4126 | }
|
---|
4127 | ppc_set_current_section (reldata_section);
|
---|
4128 | }
|
---|
4129 |
|
---|
4130 | /* pseudo-op: .rdata
|
---|
4131 | behaviour: predefined read only data section
|
---|
4132 | double word aligned
|
---|
4133 | errors: None
|
---|
4134 | warnings: None
|
---|
4135 | initial: .section .rdata "dr3"
|
---|
4136 | d - initialized data
|
---|
4137 | r - readable
|
---|
4138 | 3 - double word aligned (that would be 4 byte boundary) */
|
---|
4139 |
|
---|
4140 | static void
|
---|
4141 | ppc_rdata (ignore)
|
---|
4142 | int ignore ATTRIBUTE_UNUSED;
|
---|
4143 | {
|
---|
4144 | if (rdata_section == 0)
|
---|
4145 | {
|
---|
4146 | rdata_section = subseg_new (".rdata", 0);
|
---|
4147 | bfd_set_section_flags (stdoutput, rdata_section,
|
---|
4148 | (SEC_ALLOC | SEC_LOAD | SEC_RELOC
|
---|
4149 | | SEC_READONLY | SEC_DATA ));
|
---|
4150 |
|
---|
4151 | bfd_set_section_alignment (stdoutput, rdata_section, 2);
|
---|
4152 | }
|
---|
4153 | else
|
---|
4154 | {
|
---|
4155 | rdata_section = subseg_new (".rdata", 0);
|
---|
4156 | }
|
---|
4157 | ppc_set_current_section (rdata_section);
|
---|
4158 | }
|
---|
4159 |
|
---|
4160 | /* pseudo-op: .ualong
|
---|
4161 | behaviour: much like .int, with the exception that no alignment is
|
---|
4162 | performed.
|
---|
4163 | FIXME: test the alignment statement
|
---|
4164 | errors: None
|
---|
4165 | warnings: None */
|
---|
4166 |
|
---|
4167 | static void
|
---|
4168 | ppc_ualong (ignore)
|
---|
4169 | int ignore ATTRIBUTE_UNUSED;
|
---|
4170 | {
|
---|
4171 | /* Try for long. */
|
---|
4172 | cons (4);
|
---|
4173 | }
|
---|
4174 |
|
---|
4175 | /* pseudo-op: .znop <symbol name>
|
---|
4176 | behaviour: Issue a nop instruction
|
---|
4177 | Issue a IMAGE_REL_PPC_IFGLUE relocation against it, using
|
---|
4178 | the supplied symbol name.
|
---|
4179 | errors: None
|
---|
4180 | warnings: Missing symbol name */
|
---|
4181 |
|
---|
4182 | static void
|
---|
4183 | ppc_znop (ignore)
|
---|
4184 | int ignore ATTRIBUTE_UNUSED;
|
---|
4185 | {
|
---|
4186 | unsigned long insn;
|
---|
4187 | const struct powerpc_opcode *opcode;
|
---|
4188 | expressionS ex;
|
---|
4189 | char *f;
|
---|
4190 | symbolS *sym;
|
---|
4191 | char *symbol_name;
|
---|
4192 | char c;
|
---|
4193 | char *name;
|
---|
4194 | unsigned int exp;
|
---|
4195 | flagword flags;
|
---|
4196 | asection *sec;
|
---|
4197 |
|
---|
4198 | /* Strip out the symbol name. */
|
---|
4199 | symbol_name = input_line_pointer;
|
---|
4200 | c = get_symbol_end ();
|
---|
4201 |
|
---|
4202 | name = xmalloc (input_line_pointer - symbol_name + 1);
|
---|
4203 | strcpy (name, symbol_name);
|
---|
4204 |
|
---|
4205 | sym = symbol_find_or_make (name);
|
---|
4206 |
|
---|
4207 | *input_line_pointer = c;
|
---|
4208 |
|
---|
4209 | SKIP_WHITESPACE ();
|
---|
4210 |
|
---|
4211 | /* Look up the opcode in the hash table. */
|
---|
4212 | opcode = (const struct powerpc_opcode *) hash_find (ppc_hash, "nop");
|
---|
4213 |
|
---|
4214 | /* Stick in the nop. */
|
---|
4215 | insn = opcode->opcode;
|
---|
4216 |
|
---|
4217 | /* Write out the instruction. */
|
---|
4218 | f = frag_more (4);
|
---|
4219 | md_number_to_chars (f, insn, 4);
|
---|
4220 | fix_new (frag_now,
|
---|
4221 | f - frag_now->fr_literal,
|
---|
4222 | 4,
|
---|
4223 | sym,
|
---|
4224 | 0,
|
---|
4225 | 0,
|
---|
4226 | BFD_RELOC_16_GOT_PCREL);
|
---|
4227 |
|
---|
4228 | }
|
---|
4229 |
|
---|
4230 | /* pseudo-op:
|
---|
4231 | behaviour:
|
---|
4232 | errors:
|
---|
4233 | warnings: */
|
---|
4234 |
|
---|
4235 | static void
|
---|
4236 | ppc_pe_comm (lcomm)
|
---|
4237 | int lcomm;
|
---|
4238 | {
|
---|
4239 | register char *name;
|
---|
4240 | register char c;
|
---|
4241 | register char *p;
|
---|
4242 | offsetT temp;
|
---|
4243 | register symbolS *symbolP;
|
---|
4244 | offsetT align;
|
---|
4245 |
|
---|
4246 | name = input_line_pointer;
|
---|
4247 | c = get_symbol_end ();
|
---|
4248 |
|
---|
4249 | /* just after name is now '\0'. */
|
---|
4250 | p = input_line_pointer;
|
---|
4251 | *p = c;
|
---|
4252 | SKIP_WHITESPACE ();
|
---|
4253 | if (*input_line_pointer != ',')
|
---|
4254 | {
|
---|
4255 | as_bad (_("Expected comma after symbol-name: rest of line ignored."));
|
---|
4256 | ignore_rest_of_line ();
|
---|
4257 | return;
|
---|
4258 | }
|
---|
4259 |
|
---|
4260 | input_line_pointer++; /* skip ',' */
|
---|
4261 | if ((temp = get_absolute_expression ()) < 0)
|
---|
4262 | {
|
---|
4263 | as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) temp);
|
---|
4264 | ignore_rest_of_line ();
|
---|
4265 | return;
|
---|
4266 | }
|
---|
4267 |
|
---|
4268 | if (! lcomm)
|
---|
4269 | {
|
---|
4270 | /* The third argument to .comm is the alignment. */
|
---|
4271 | if (*input_line_pointer != ',')
|
---|
4272 | align = 3;
|
---|
4273 | else
|
---|
4274 | {
|
---|
4275 | ++input_line_pointer;
|
---|
4276 | align = get_absolute_expression ();
|
---|
4277 | if (align <= 0)
|
---|
4278 | {
|
---|
4279 | as_warn (_("ignoring bad alignment"));
|
---|
4280 | align = 3;
|
---|
4281 | }
|
---|
4282 | }
|
---|
4283 | }
|
---|
4284 |
|
---|
4285 | *p = 0;
|
---|
4286 | symbolP = symbol_find_or_make (name);
|
---|
4287 |
|
---|
4288 | *p = c;
|
---|
4289 | if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
|
---|
4290 | {
|
---|
4291 | as_bad (_("Ignoring attempt to re-define symbol `%s'."),
|
---|
4292 | S_GET_NAME (symbolP));
|
---|
4293 | ignore_rest_of_line ();
|
---|
4294 | return;
|
---|
4295 | }
|
---|
4296 |
|
---|
4297 | if (S_GET_VALUE (symbolP))
|
---|
4298 | {
|
---|
4299 | if (S_GET_VALUE (symbolP) != (valueT) temp)
|
---|
4300 | as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."),
|
---|
4301 | S_GET_NAME (symbolP),
|
---|
4302 | (long) S_GET_VALUE (symbolP),
|
---|
4303 | (long) temp);
|
---|
4304 | }
|
---|
4305 | else
|
---|
4306 | {
|
---|
4307 | S_SET_VALUE (symbolP, (valueT) temp);
|
---|
4308 | S_SET_EXTERNAL (symbolP);
|
---|
4309 | }
|
---|
4310 |
|
---|
4311 | demand_empty_rest_of_line ();
|
---|
4312 | }
|
---|
4313 |
|
---|
4314 | /*
|
---|
4315 | * implement the .section pseudo op:
|
---|
4316 | * .section name {, "flags"}
|
---|
4317 | * ^ ^
|
---|
4318 | * | +--- optional flags: 'b' for bss
|
---|
4319 | * | 'i' for info
|
---|
4320 | * +-- section name 'l' for lib
|
---|
4321 | * 'n' for noload
|
---|
4322 | * 'o' for over
|
---|
4323 | * 'w' for data
|
---|
4324 | * 'd' (apparently m88k for data)
|
---|
4325 | * 'x' for text
|
---|
4326 | * But if the argument is not a quoted string, treat it as a
|
---|
4327 | * subsegment number.
|
---|
4328 | *
|
---|
4329 | * FIXME: this is a copy of the section processing from obj-coff.c, with
|
---|
4330 | * additions/changes for the moto-pas assembler support. There are three
|
---|
4331 | * categories:
|
---|
4332 | *
|
---|
4333 | * FIXME: I just noticed this. This doesn't work at all really. It it
|
---|
4334 | * setting bits that bfd probably neither understands or uses. The
|
---|
4335 | * correct approach (?) will have to incorporate extra fields attached
|
---|
4336 | * to the section to hold the system specific stuff. (krk)
|
---|
4337 | *
|
---|
4338 | * Section Contents:
|
---|
4339 | * 'a' - unknown - referred to in documentation, but no definition supplied
|
---|
4340 | * 'c' - section has code
|
---|
4341 | * 'd' - section has initialized data
|
---|
4342 | * 'u' - section has uninitialized data
|
---|
4343 | * 'i' - section contains directives (info)
|
---|
4344 | * 'n' - section can be discarded
|
---|
4345 | * 'R' - remove section at link time
|
---|
4346 | *
|
---|
4347 | * Section Protection:
|
---|
4348 | * 'r' - section is readable
|
---|
4349 | * 'w' - section is writeable
|
---|
4350 | * 'x' - section is executable
|
---|
4351 | * 's' - section is sharable
|
---|
4352 | *
|
---|
4353 | * Section Alignment:
|
---|
4354 | * '0' - align to byte boundary
|
---|
4355 | * '1' - align to halfword undary
|
---|
4356 | * '2' - align to word boundary
|
---|
4357 | * '3' - align to doubleword boundary
|
---|
4358 | * '4' - align to quadword boundary
|
---|
4359 | * '5' - align to 32 byte boundary
|
---|
4360 | * '6' - align to 64 byte boundary
|
---|
4361 | *
|
---|
4362 | */
|
---|
4363 |
|
---|
4364 | void
|
---|
4365 | ppc_pe_section (ignore)
|
---|
4366 | int ignore ATTRIBUTE_UNUSED;
|
---|
4367 | {
|
---|
4368 | /* Strip out the section name. */
|
---|
4369 | char *section_name;
|
---|
4370 | char c;
|
---|
4371 | char *name;
|
---|
4372 | unsigned int exp;
|
---|
4373 | flagword flags;
|
---|
4374 | segT sec;
|
---|
4375 | int align;
|
---|
4376 |
|
---|
4377 | section_name = input_line_pointer;
|
---|
4378 | c = get_symbol_end ();
|
---|
4379 |
|
---|
4380 | name = xmalloc (input_line_pointer - section_name + 1);
|
---|
4381 | strcpy (name, section_name);
|
---|
4382 |
|
---|
4383 | *input_line_pointer = c;
|
---|
4384 |
|
---|
4385 | SKIP_WHITESPACE ();
|
---|
4386 |
|
---|
4387 | exp = 0;
|
---|
4388 | flags = SEC_NO_FLAGS;
|
---|
4389 |
|
---|
4390 | if (strcmp (name, ".idata$2") == 0)
|
---|
4391 | {
|
---|
4392 | align = 0;
|
---|
4393 | }
|
---|
4394 | else if (strcmp (name, ".idata$3") == 0)
|
---|
4395 | {
|
---|
4396 | align = 0;
|
---|
4397 | }
|
---|
4398 | else if (strcmp (name, ".idata$4") == 0)
|
---|
4399 | {
|
---|
4400 | align = 2;
|
---|
4401 | }
|
---|
4402 | else if (strcmp (name, ".idata$5") == 0)
|
---|
4403 | {
|
---|
4404 | align = 2;
|
---|
4405 | }
|
---|
4406 | else if (strcmp (name, ".idata$6") == 0)
|
---|
4407 | {
|
---|
4408 | align = 1;
|
---|
4409 | }
|
---|
4410 | else
|
---|
4411 | /* Default alignment to 16 byte boundary. */
|
---|
4412 | align = 4;
|
---|
4413 |
|
---|
4414 | if (*input_line_pointer == ',')
|
---|
4415 | {
|
---|
4416 | ++input_line_pointer;
|
---|
4417 | SKIP_WHITESPACE ();
|
---|
4418 | if (*input_line_pointer != '"')
|
---|
4419 | exp = get_absolute_expression ();
|
---|
4420 | else
|
---|
4421 | {
|
---|
4422 | ++input_line_pointer;
|
---|
4423 | while (*input_line_pointer != '"'
|
---|
4424 | && ! is_end_of_line[(unsigned char) *input_line_pointer])
|
---|
4425 | {
|
---|
4426 | switch (*input_line_pointer)
|
---|
4427 | {
|
---|
4428 | /* Section Contents */
|
---|
4429 | case 'a': /* unknown */
|
---|
4430 | as_bad (_("Unsupported section attribute -- 'a'"));
|
---|
4431 | break;
|
---|
4432 | case 'c': /* code section */
|
---|
4433 | flags |= SEC_CODE;
|
---|
4434 | break;
|
---|
4435 | case 'd': /* section has initialized data */
|
---|
4436 | flags |= SEC_DATA;
|
---|
4437 | break;
|
---|
4438 | case 'u': /* section has uninitialized data */
|
---|
4439 | /* FIXME: This is IMAGE_SCN_CNT_UNINITIALIZED_DATA
|
---|
4440 | in winnt.h */
|
---|
4441 | flags |= SEC_ROM;
|
---|
4442 | break;
|
---|
4443 | case 'i': /* section contains directives (info) */
|
---|
4444 | /* FIXME: This is IMAGE_SCN_LNK_INFO
|
---|
4445 | in winnt.h */
|
---|
4446 | flags |= SEC_HAS_CONTENTS;
|
---|
4447 | break;
|
---|
4448 | case 'n': /* section can be discarded */
|
---|
4449 | flags &=~ SEC_LOAD;
|
---|
4450 | break;
|
---|
4451 | case 'R': /* Remove section at link time */
|
---|
4452 | flags |= SEC_NEVER_LOAD;
|
---|
4453 | break;
|
---|
4454 |
|
---|
4455 | /* Section Protection */
|
---|
4456 | case 'r': /* section is readable */
|
---|
4457 | flags |= IMAGE_SCN_MEM_READ;
|
---|
4458 | break;
|
---|
4459 | case 'w': /* section is writeable */
|
---|
4460 | flags |= IMAGE_SCN_MEM_WRITE;
|
---|
4461 | break;
|
---|
4462 | case 'x': /* section is executable */
|
---|
4463 | flags |= IMAGE_SCN_MEM_EXECUTE;
|
---|
4464 | break;
|
---|
4465 | case 's': /* section is sharable */
|
---|
4466 | flags |= IMAGE_SCN_MEM_SHARED;
|
---|
4467 | break;
|
---|
4468 |
|
---|
4469 | /* Section Alignment */
|
---|
4470 | case '0': /* align to byte boundary */
|
---|
4471 | flags |= IMAGE_SCN_ALIGN_1BYTES;
|
---|
4472 | align = 0;
|
---|
4473 | break;
|
---|
4474 | case '1': /* align to halfword boundary */
|
---|
4475 | flags |= IMAGE_SCN_ALIGN_2BYTES;
|
---|
4476 | align = 1;
|
---|
4477 | break;
|
---|
4478 | case '2': /* align to word boundary */
|
---|
4479 | flags |= IMAGE_SCN_ALIGN_4BYTES;
|
---|
4480 | align = 2;
|
---|
4481 | break;
|
---|
4482 | case '3': /* align to doubleword boundary */
|
---|
4483 | flags |= IMAGE_SCN_ALIGN_8BYTES;
|
---|
4484 | align = 3;
|
---|
4485 | break;
|
---|
4486 | case '4': /* align to quadword boundary */
|
---|
4487 | flags |= IMAGE_SCN_ALIGN_16BYTES;
|
---|
4488 | align = 4;
|
---|
4489 | break;
|
---|
4490 | case '5': /* align to 32 byte boundary */
|
---|
4491 | flags |= IMAGE_SCN_ALIGN_32BYTES;
|
---|
4492 | align = 5;
|
---|
4493 | break;
|
---|
4494 | case '6': /* align to 64 byte boundary */
|
---|
4495 | flags |= IMAGE_SCN_ALIGN_64BYTES;
|
---|
4496 | align = 6;
|
---|
4497 | break;
|
---|
4498 |
|
---|
4499 | default:
|
---|
4500 | as_bad (_("unknown section attribute '%c'"),
|
---|
4501 | *input_line_pointer);
|
---|
4502 | break;
|
---|
4503 | }
|
---|
4504 | ++input_line_pointer;
|
---|
4505 | }
|
---|
4506 | if (*input_line_pointer == '"')
|
---|
4507 | ++input_line_pointer;
|
---|
4508 | }
|
---|
4509 | }
|
---|
4510 |
|
---|
4511 | sec = subseg_new (name, (subsegT) exp);
|
---|
4512 |
|
---|
4513 | ppc_set_current_section (sec);
|
---|
4514 |
|
---|
4515 | if (flags != SEC_NO_FLAGS)
|
---|
4516 | {
|
---|
4517 | if (! bfd_set_section_flags (stdoutput, sec, flags))
|
---|
4518 | as_bad (_("error setting flags for \"%s\": %s"),
|
---|
4519 | bfd_section_name (stdoutput, sec),
|
---|
4520 | bfd_errmsg (bfd_get_error ()));
|
---|
4521 | }
|
---|
4522 |
|
---|
4523 | bfd_set_section_alignment (stdoutput, sec, align);
|
---|
4524 |
|
---|
4525 | }
|
---|
4526 |
|
---|
4527 | static void
|
---|
4528 | ppc_pe_function (ignore)
|
---|
4529 | int ignore ATTRIBUTE_UNUSED;
|
---|
4530 | {
|
---|
4531 | char *name;
|
---|
4532 | char endc;
|
---|
4533 | symbolS *ext_sym;
|
---|
4534 |
|
---|
4535 | name = input_line_pointer;
|
---|
4536 | endc = get_symbol_end ();
|
---|
4537 |
|
---|
4538 | ext_sym = symbol_find_or_make (name);
|
---|
4539 |
|
---|
4540 | *input_line_pointer = endc;
|
---|
4541 |
|
---|
4542 | S_SET_DATA_TYPE (ext_sym, DT_FCN << N_BTSHFT);
|
---|
4543 | SF_SET_FUNCTION (ext_sym);
|
---|
4544 | SF_SET_PROCESS (ext_sym);
|
---|
4545 | coff_add_linesym (ext_sym);
|
---|
4546 |
|
---|
4547 | demand_empty_rest_of_line ();
|
---|
4548 | }
|
---|
4549 |
|
---|
4550 | static void
|
---|
4551 | ppc_pe_tocd (ignore)
|
---|
4552 | int ignore ATTRIBUTE_UNUSED;
|
---|
4553 | {
|
---|
4554 | if (tocdata_section == 0)
|
---|
4555 | {
|
---|
4556 | tocdata_section = subseg_new (".tocd", 0);
|
---|
4557 | /* FIXME: section flags won't work. */
|
---|
4558 | bfd_set_section_flags (stdoutput, tocdata_section,
|
---|
4559 | (SEC_ALLOC | SEC_LOAD | SEC_RELOC
|
---|
4560 | | SEC_READONLY | SEC_DATA));
|
---|
4561 |
|
---|
4562 | bfd_set_section_alignment (stdoutput, tocdata_section, 2);
|
---|
4563 | }
|
---|
4564 | else
|
---|
4565 | {
|
---|
4566 | rdata_section = subseg_new (".tocd", 0);
|
---|
4567 | }
|
---|
4568 |
|
---|
4569 | ppc_set_current_section (tocdata_section);
|
---|
4570 |
|
---|
4571 | demand_empty_rest_of_line ();
|
---|
4572 | }
|
---|
4573 |
|
---|
4574 | /* Don't adjust TOC relocs to use the section symbol. */
|
---|
4575 |
|
---|
4576 | int
|
---|
4577 | ppc_pe_fix_adjustable (fix)
|
---|
4578 | fixS *fix;
|
---|
4579 | {
|
---|
4580 | return fix->fx_r_type != BFD_RELOC_PPC_TOC16;
|
---|
4581 | }
|
---|
4582 |
|
---|
4583 | #endif
|
---|
4584 | |
---|
4585 |
|
---|
4586 | #ifdef OBJ_XCOFF
|
---|
4587 |
|
---|
4588 | /* XCOFF specific symbol and file handling. */
|
---|
4589 |
|
---|
4590 | /* Canonicalize the symbol name. We use the to force the suffix, if
|
---|
4591 | any, to use square brackets, and to be in upper case. */
|
---|
4592 |
|
---|
4593 | char *
|
---|
4594 | ppc_canonicalize_symbol_name (name)
|
---|
4595 | char *name;
|
---|
4596 | {
|
---|
4597 | char *s;
|
---|
4598 |
|
---|
4599 | if (ppc_stab_symbol)
|
---|
4600 | return name;
|
---|
4601 |
|
---|
4602 | for (s = name; *s != '\0' && *s != '{' && *s != '['; s++)
|
---|
4603 | ;
|
---|
4604 | if (*s != '\0')
|
---|
4605 | {
|
---|
4606 | char brac;
|
---|
4607 |
|
---|
4608 | if (*s == '[')
|
---|
4609 | brac = ']';
|
---|
4610 | else
|
---|
4611 | {
|
---|
4612 | *s = '[';
|
---|
4613 | brac = '}';
|
---|
4614 | }
|
---|
4615 |
|
---|
4616 | for (s++; *s != '\0' && *s != brac; s++)
|
---|
4617 | *s = TOUPPER (*s);
|
---|
4618 |
|
---|
4619 | if (*s == '\0' || s[1] != '\0')
|
---|
4620 | as_bad (_("bad symbol suffix"));
|
---|
4621 |
|
---|
4622 | *s = ']';
|
---|
4623 | }
|
---|
4624 |
|
---|
4625 | return name;
|
---|
4626 | }
|
---|
4627 |
|
---|
4628 | /* Set the class of a symbol based on the suffix, if any. This is
|
---|
4629 | called whenever a new symbol is created. */
|
---|
4630 |
|
---|
4631 | void
|
---|
4632 | ppc_symbol_new_hook (sym)
|
---|
4633 | symbolS *sym;
|
---|
4634 | {
|
---|
4635 | struct ppc_tc_sy *tc;
|
---|
4636 | const char *s;
|
---|
4637 |
|
---|
4638 | tc = symbol_get_tc (sym);
|
---|
4639 | tc->next = NULL;
|
---|
4640 | tc->output = 0;
|
---|
4641 | tc->class = -1;
|
---|
4642 | tc->real_name = NULL;
|
---|
4643 | tc->subseg = 0;
|
---|
4644 | tc->align = 0;
|
---|
4645 | tc->size = NULL;
|
---|
4646 | tc->within = NULL;
|
---|
4647 |
|
---|
4648 | if (ppc_stab_symbol)
|
---|
4649 | return;
|
---|
4650 |
|
---|
4651 | s = strchr (S_GET_NAME (sym), '[');
|
---|
4652 | if (s == (const char *) NULL)
|
---|
4653 | {
|
---|
4654 | /* There is no suffix. */
|
---|
4655 | return;
|
---|
4656 | }
|
---|
4657 |
|
---|
4658 | ++s;
|
---|
4659 |
|
---|
4660 | switch (s[0])
|
---|
4661 | {
|
---|
4662 | case 'B':
|
---|
4663 | if (strcmp (s, "BS]") == 0)
|
---|
4664 | tc->class = XMC_BS;
|
---|
4665 | break;
|
---|
4666 | case 'D':
|
---|
4667 | if (strcmp (s, "DB]") == 0)
|
---|
4668 | tc->class = XMC_DB;
|
---|
4669 | else if (strcmp (s, "DS]") == 0)
|
---|
4670 | tc->class = XMC_DS;
|
---|
4671 | break;
|
---|
4672 | case 'G':
|
---|
4673 | if (strcmp (s, "GL]") == 0)
|
---|
4674 | tc->class = XMC_GL;
|
---|
4675 | break;
|
---|
4676 | case 'P':
|
---|
4677 | if (strcmp (s, "PR]") == 0)
|
---|
4678 | tc->class = XMC_PR;
|
---|
4679 | break;
|
---|
4680 | case 'R':
|
---|
4681 | if (strcmp (s, "RO]") == 0)
|
---|
4682 | tc->class = XMC_RO;
|
---|
4683 | else if (strcmp (s, "RW]") == 0)
|
---|
4684 | tc->class = XMC_RW;
|
---|
4685 | break;
|
---|
4686 | case 'S':
|
---|
4687 | if (strcmp (s, "SV]") == 0)
|
---|
4688 | tc->class = XMC_SV;
|
---|
4689 | break;
|
---|
4690 | case 'T':
|
---|
4691 | if (strcmp (s, "TC]") == 0)
|
---|
4692 | tc->class = XMC_TC;
|
---|
4693 | else if (strcmp (s, "TI]") == 0)
|
---|
4694 | tc->class = XMC_TI;
|
---|
4695 | else if (strcmp (s, "TB]") == 0)
|
---|
4696 | tc->class = XMC_TB;
|
---|
4697 | else if (strcmp (s, "TC0]") == 0 || strcmp (s, "T0]") == 0)
|
---|
4698 | tc->class = XMC_TC0;
|
---|
4699 | break;
|
---|
4700 | case 'U':
|
---|
4701 | if (strcmp (s, "UA]") == 0)
|
---|
4702 | tc->class = XMC_UA;
|
---|
4703 | else if (strcmp (s, "UC]") == 0)
|
---|
4704 | tc->class = XMC_UC;
|
---|
4705 | break;
|
---|
4706 | case 'X':
|
---|
4707 | if (strcmp (s, "XO]") == 0)
|
---|
4708 | tc->class = XMC_XO;
|
---|
4709 | break;
|
---|
4710 | }
|
---|
4711 |
|
---|
4712 | if (tc->class == -1)
|
---|
4713 | as_bad (_("Unrecognized symbol suffix"));
|
---|
4714 | }
|
---|
4715 |
|
---|
4716 | /* Set the class of a label based on where it is defined. This
|
---|
4717 | handles symbols without suffixes. Also, move the symbol so that it
|
---|
4718 | follows the csect symbol. */
|
---|
4719 |
|
---|
4720 | void
|
---|
4721 | ppc_frob_label (sym)
|
---|
4722 | symbolS *sym;
|
---|
4723 | {
|
---|
4724 | if (ppc_current_csect != (symbolS *) NULL)
|
---|
4725 | {
|
---|
4726 | if (symbol_get_tc (sym)->class == -1)
|
---|
4727 | symbol_get_tc (sym)->class = symbol_get_tc (ppc_current_csect)->class;
|
---|
4728 |
|
---|
4729 | symbol_remove (sym, &symbol_rootP, &symbol_lastP);
|
---|
4730 | symbol_append (sym, symbol_get_tc (ppc_current_csect)->within,
|
---|
4731 | &symbol_rootP, &symbol_lastP);
|
---|
4732 | symbol_get_tc (ppc_current_csect)->within = sym;
|
---|
4733 | }
|
---|
4734 | }
|
---|
4735 |
|
---|
4736 | /* This variable is set by ppc_frob_symbol if any absolute symbols are
|
---|
4737 | seen. It tells ppc_adjust_symtab whether it needs to look through
|
---|
4738 | the symbols. */
|
---|
4739 |
|
---|
4740 | static bfd_boolean ppc_saw_abs;
|
---|
4741 |
|
---|
4742 | /* Change the name of a symbol just before writing it out. Set the
|
---|
4743 | real name if the .rename pseudo-op was used. Otherwise, remove any
|
---|
4744 | class suffix. Return 1 if the symbol should not be included in the
|
---|
4745 | symbol table. */
|
---|
4746 |
|
---|
4747 | int
|
---|
4748 | ppc_frob_symbol (sym)
|
---|
4749 | symbolS *sym;
|
---|
4750 | {
|
---|
4751 | static symbolS *ppc_last_function;
|
---|
4752 | static symbolS *set_end;
|
---|
4753 |
|
---|
4754 | /* Discard symbols that should not be included in the output symbol
|
---|
4755 | table. */
|
---|
4756 | if (! symbol_used_in_reloc_p (sym)
|
---|
4757 | && ((symbol_get_bfdsym (sym)->flags & BSF_SECTION_SYM) != 0
|
---|
4758 | || (! S_IS_EXTERNAL (sym)
|
---|
4759 | && ! symbol_get_tc (sym)->output
|
---|
4760 | && S_GET_STORAGE_CLASS (sym) != C_FILE)))
|
---|
4761 | return 1;
|
---|
4762 |
|
---|
4763 | /* This one will disappear anyway. Don't make a csect sym for it. */
|
---|
4764 | if (sym == abs_section_sym)
|
---|
4765 | return 1;
|
---|
4766 |
|
---|
4767 | if (symbol_get_tc (sym)->real_name != (char *) NULL)
|
---|
4768 | S_SET_NAME (sym, symbol_get_tc (sym)->real_name);
|
---|
4769 | else
|
---|
4770 | {
|
---|
4771 | const char *name;
|
---|
4772 | const char *s;
|
---|
4773 |
|
---|
4774 | name = S_GET_NAME (sym);
|
---|
4775 | s = strchr (name, '[');
|
---|
4776 | if (s != (char *) NULL)
|
---|
4777 | {
|
---|
4778 | unsigned int len;
|
---|
4779 | char *snew;
|
---|
4780 |
|
---|
4781 | len = s - name;
|
---|
4782 | snew = xmalloc (len + 1);
|
---|
4783 | memcpy (snew, name, len);
|
---|
4784 | snew[len] = '\0';
|
---|
4785 |
|
---|
4786 | S_SET_NAME (sym, snew);
|
---|
4787 | }
|
---|
4788 | }
|
---|
4789 |
|
---|
4790 | if (set_end != (symbolS *) NULL)
|
---|
4791 | {
|
---|
4792 | SA_SET_SYM_ENDNDX (set_end, sym);
|
---|
4793 | set_end = NULL;
|
---|
4794 | }
|
---|
4795 |
|
---|
4796 | if (SF_GET_FUNCTION (sym))
|
---|
4797 | {
|
---|
4798 | if (ppc_last_function != (symbolS *) NULL)
|
---|
4799 | as_bad (_("two .function pseudo-ops with no intervening .ef"));
|
---|
4800 | ppc_last_function = sym;
|
---|
4801 | if (symbol_get_tc (sym)->size != (symbolS *) NULL)
|
---|
4802 | {
|
---|
4803 | resolve_symbol_value (symbol_get_tc (sym)->size);
|
---|
4804 | SA_SET_SYM_FSIZE (sym,
|
---|
4805 | (long) S_GET_VALUE (symbol_get_tc (sym)->size));
|
---|
4806 | }
|
---|
4807 | }
|
---|
4808 | else if (S_GET_STORAGE_CLASS (sym) == C_FCN
|
---|
4809 | && strcmp (S_GET_NAME (sym), ".ef") == 0)
|
---|
4810 | {
|
---|
4811 | if (ppc_last_function == (symbolS *) NULL)
|
---|
4812 | as_bad (_(".ef with no preceding .function"));
|
---|
4813 | else
|
---|
4814 | {
|
---|
4815 | set_end = ppc_last_function;
|
---|
4816 | ppc_last_function = NULL;
|
---|
4817 |
|
---|
4818 | /* We don't have a C_EFCN symbol, but we need to force the
|
---|
4819 | COFF backend to believe that it has seen one. */
|
---|
4820 | coff_last_function = NULL;
|
---|
4821 | }
|
---|
4822 | }
|
---|
4823 |
|
---|
4824 | if (! S_IS_EXTERNAL (sym)
|
---|
4825 | && (symbol_get_bfdsym (sym)->flags & BSF_SECTION_SYM) == 0
|
---|
4826 | && S_GET_STORAGE_CLASS (sym) != C_FILE
|
---|
4827 | && S_GET_STORAGE_CLASS (sym) != C_FCN
|
---|
4828 | && S_GET_STORAGE_CLASS (sym) != C_BLOCK
|
---|
4829 | && S_GET_STORAGE_CLASS (sym) != C_BSTAT
|
---|
4830 | && S_GET_STORAGE_CLASS (sym) != C_ESTAT
|
---|
4831 | && S_GET_STORAGE_CLASS (sym) != C_BINCL
|
---|
4832 | && S_GET_STORAGE_CLASS (sym) != C_EINCL
|
---|
4833 | && S_GET_SEGMENT (sym) != ppc_coff_debug_section)
|
---|
4834 | S_SET_STORAGE_CLASS (sym, C_HIDEXT);
|
---|
4835 |
|
---|
4836 | if (S_GET_STORAGE_CLASS (sym) == C_EXT
|
---|
4837 | || S_GET_STORAGE_CLASS (sym) == C_HIDEXT)
|
---|
4838 | {
|
---|
4839 | int i;
|
---|
4840 | union internal_auxent *a;
|
---|
4841 |
|
---|
4842 | /* Create a csect aux. */
|
---|
4843 | i = S_GET_NUMBER_AUXILIARY (sym);
|
---|
4844 | S_SET_NUMBER_AUXILIARY (sym, i + 1);
|
---|
4845 | a = &coffsymbol (symbol_get_bfdsym (sym))->native[i + 1].u.auxent;
|
---|
4846 | if (symbol_get_tc (sym)->class == XMC_TC0)
|
---|
4847 | {
|
---|
4848 | /* This is the TOC table. */
|
---|
4849 | know (strcmp (S_GET_NAME (sym), "TOC") == 0);
|
---|
4850 | a->x_csect.x_scnlen.l = 0;
|
---|
4851 | a->x_csect.x_smtyp = (2 << 3) | XTY_SD;
|
---|
4852 | }
|
---|
4853 | else if (symbol_get_tc (sym)->subseg != 0)
|
---|
4854 | {
|
---|
4855 | /* This is a csect symbol. x_scnlen is the size of the
|
---|
4856 | csect. */
|
---|
4857 | if (symbol_get_tc (sym)->next == (symbolS *) NULL)
|
---|
4858 | a->x_csect.x_scnlen.l = (bfd_section_size (stdoutput,
|
---|
4859 | S_GET_SEGMENT (sym))
|
---|
4860 | - S_GET_VALUE (sym));
|
---|
4861 | else
|
---|
4862 | {
|
---|
4863 | resolve_symbol_value (symbol_get_tc (sym)->next);
|
---|
4864 | a->x_csect.x_scnlen.l = (S_GET_VALUE (symbol_get_tc (sym)->next)
|
---|
4865 | - S_GET_VALUE (sym));
|
---|
4866 | }
|
---|
4867 | a->x_csect.x_smtyp = (symbol_get_tc (sym)->align << 3) | XTY_SD;
|
---|
4868 | }
|
---|
4869 | else if (S_GET_SEGMENT (sym) == bss_section)
|
---|
4870 | {
|
---|
4871 | /* This is a common symbol. */
|
---|
4872 | a->x_csect.x_scnlen.l = symbol_get_frag (sym)->fr_offset;
|
---|
4873 | a->x_csect.x_smtyp = (symbol_get_tc (sym)->align << 3) | XTY_CM;
|
---|
4874 | if (S_IS_EXTERNAL (sym))
|
---|
4875 | symbol_get_tc (sym)->class = XMC_RW;
|
---|
4876 | else
|
---|
4877 | symbol_get_tc (sym)->class = XMC_BS;
|
---|
4878 | }
|
---|
4879 | else if (S_GET_SEGMENT (sym) == absolute_section)
|
---|
4880 | {
|
---|
4881 | /* This is an absolute symbol. The csect will be created by
|
---|
4882 | ppc_adjust_symtab. */
|
---|
4883 | ppc_saw_abs = TRUE;
|
---|
4884 | a->x_csect.x_smtyp = XTY_LD;
|
---|
4885 | if (symbol_get_tc (sym)->class == -1)
|
---|
4886 | symbol_get_tc (sym)->class = XMC_XO;
|
---|
4887 | }
|
---|
4888 | else if (! S_IS_DEFINED (sym))
|
---|
4889 | {
|
---|
4890 | /* This is an external symbol. */
|
---|
4891 | a->x_csect.x_scnlen.l = 0;
|
---|
4892 | a->x_csect.x_smtyp = XTY_ER;
|
---|
4893 | }
|
---|
4894 | else if (symbol_get_tc (sym)->class == XMC_TC)
|
---|
4895 | {
|
---|
4896 | symbolS *next;
|
---|
4897 |
|
---|
4898 | /* This is a TOC definition. x_scnlen is the size of the
|
---|
4899 | TOC entry. */
|
---|
4900 | next = symbol_next (sym);
|
---|
4901 | while (symbol_get_tc (next)->class == XMC_TC0)
|
---|
4902 | next = symbol_next (next);
|
---|
4903 | if (next == (symbolS *) NULL
|
---|
4904 | || symbol_get_tc (next)->class != XMC_TC)
|
---|
4905 | {
|
---|
4906 | if (ppc_after_toc_frag == (fragS *) NULL)
|
---|
4907 | a->x_csect.x_scnlen.l = (bfd_section_size (stdoutput,
|
---|
4908 | data_section)
|
---|
4909 | - S_GET_VALUE (sym));
|
---|
4910 | else
|
---|
4911 | a->x_csect.x_scnlen.l = (ppc_after_toc_frag->fr_address
|
---|
4912 | - S_GET_VALUE (sym));
|
---|
4913 | }
|
---|
4914 | else
|
---|
4915 | {
|
---|
4916 | resolve_symbol_value (next);
|
---|
4917 | a->x_csect.x_scnlen.l = (S_GET_VALUE (next)
|
---|
4918 | - S_GET_VALUE (sym));
|
---|
4919 | }
|
---|
4920 | a->x_csect.x_smtyp = (2 << 3) | XTY_SD;
|
---|
4921 | }
|
---|
4922 | else
|
---|
4923 | {
|
---|
4924 | symbolS *csect;
|
---|
4925 |
|
---|
4926 | /* This is a normal symbol definition. x_scnlen is the
|
---|
4927 | symbol index of the containing csect. */
|
---|
4928 | if (S_GET_SEGMENT (sym) == text_section)
|
---|
4929 | csect = ppc_text_csects;
|
---|
4930 | else if (S_GET_SEGMENT (sym) == data_section)
|
---|
4931 | csect = ppc_data_csects;
|
---|
4932 | else
|
---|
4933 | abort ();
|
---|
4934 |
|
---|
4935 | /* Skip the initial dummy symbol. */
|
---|
4936 | csect = symbol_get_tc (csect)->next;
|
---|
4937 |
|
---|
4938 | if (csect == (symbolS *) NULL)
|
---|
4939 | {
|
---|
4940 | as_warn (_("warning: symbol %s has no csect"), S_GET_NAME (sym));
|
---|
4941 | a->x_csect.x_scnlen.l = 0;
|
---|
4942 | }
|
---|
4943 | else
|
---|
4944 | {
|
---|
4945 | while (symbol_get_tc (csect)->next != (symbolS *) NULL)
|
---|
4946 | {
|
---|
4947 | resolve_symbol_value (symbol_get_tc (csect)->next);
|
---|
4948 | if (S_GET_VALUE (symbol_get_tc (csect)->next)
|
---|
4949 | > S_GET_VALUE (sym))
|
---|
4950 | break;
|
---|
4951 | csect = symbol_get_tc (csect)->next;
|
---|
4952 | }
|
---|
4953 |
|
---|
4954 | a->x_csect.x_scnlen.p =
|
---|
4955 | coffsymbol (symbol_get_bfdsym (csect))->native;
|
---|
4956 | coffsymbol (symbol_get_bfdsym (sym))->native[i + 1].fix_scnlen =
|
---|
4957 | 1;
|
---|
4958 | }
|
---|
4959 | a->x_csect.x_smtyp = XTY_LD;
|
---|
4960 | }
|
---|
4961 |
|
---|
4962 | a->x_csect.x_parmhash = 0;
|
---|
4963 | a->x_csect.x_snhash = 0;
|
---|
4964 | if (symbol_get_tc (sym)->class == -1)
|
---|
4965 | a->x_csect.x_smclas = XMC_PR;
|
---|
4966 | else
|
---|
4967 | a->x_csect.x_smclas = symbol_get_tc (sym)->class;
|
---|
4968 | a->x_csect.x_stab = 0;
|
---|
4969 | a->x_csect.x_snstab = 0;
|
---|
4970 |
|
---|
4971 | /* Don't let the COFF backend resort these symbols. */
|
---|
4972 | symbol_get_bfdsym (sym)->flags |= BSF_NOT_AT_END;
|
---|
4973 | }
|
---|
4974 | else if (S_GET_STORAGE_CLASS (sym) == C_BSTAT)
|
---|
4975 | {
|
---|
4976 | /* We want the value to be the symbol index of the referenced
|
---|
4977 | csect symbol. BFD will do that for us if we set the right
|
---|
4978 | flags. */
|
---|
4979 | asymbol *bsym = symbol_get_bfdsym (symbol_get_tc (sym)->within);
|
---|
4980 | combined_entry_type *c = coffsymbol (bsym)->native;
|
---|
4981 |
|
---|
4982 | S_SET_VALUE (sym, (valueT) (size_t) c);
|
---|
4983 | coffsymbol (symbol_get_bfdsym (sym))->native->fix_value = 1;
|
---|
4984 | }
|
---|
4985 | else if (S_GET_STORAGE_CLASS (sym) == C_STSYM)
|
---|
4986 | {
|
---|
4987 | symbolS *block;
|
---|
4988 | symbolS *csect;
|
---|
4989 |
|
---|
4990 | /* The value is the offset from the enclosing csect. */
|
---|
4991 | block = symbol_get_tc (sym)->within;
|
---|
4992 | csect = symbol_get_tc (block)->within;
|
---|
4993 | resolve_symbol_value (csect);
|
---|
4994 | S_SET_VALUE (sym, S_GET_VALUE (sym) - S_GET_VALUE (csect));
|
---|
4995 | }
|
---|
4996 | else if (S_GET_STORAGE_CLASS (sym) == C_BINCL
|
---|
4997 | || S_GET_STORAGE_CLASS (sym) == C_EINCL)
|
---|
4998 | {
|
---|
4999 | /* We want the value to be a file offset into the line numbers.
|
---|
5000 | BFD will do that for us if we set the right flags. We have
|
---|
5001 | already set the value correctly. */
|
---|
5002 | coffsymbol (symbol_get_bfdsym (sym))->native->fix_line = 1;
|
---|
5003 | }
|
---|
5004 |
|
---|
5005 | return 0;
|
---|
5006 | }
|
---|
5007 |
|
---|
5008 | /* Adjust the symbol table. This creates csect symbols for all
|
---|
5009 | absolute symbols. */
|
---|
5010 |
|
---|
5011 | void
|
---|
5012 | ppc_adjust_symtab ()
|
---|
5013 | {
|
---|
5014 | symbolS *sym;
|
---|
5015 |
|
---|
5016 | if (! ppc_saw_abs)
|
---|
5017 | return;
|
---|
5018 |
|
---|
5019 | for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
|
---|
5020 | {
|
---|
5021 | symbolS *csect;
|
---|
5022 | int i;
|
---|
5023 | union internal_auxent *a;
|
---|
5024 |
|
---|
5025 | if (S_GET_SEGMENT (sym) != absolute_section)
|
---|
5026 | continue;
|
---|
5027 |
|
---|
5028 | csect = symbol_create (".abs[XO]", absolute_section,
|
---|
5029 | S_GET_VALUE (sym), &zero_address_frag);
|
---|
5030 | symbol_get_bfdsym (csect)->value = S_GET_VALUE (sym);
|
---|
5031 | S_SET_STORAGE_CLASS (csect, C_HIDEXT);
|
---|
5032 | i = S_GET_NUMBER_AUXILIARY (csect);
|
---|
5033 | S_SET_NUMBER_AUXILIARY (csect, i + 1);
|
---|
5034 | a = &coffsymbol (symbol_get_bfdsym (csect))->native[i + 1].u.auxent;
|
---|
5035 | a->x_csect.x_scnlen.l = 0;
|
---|
5036 | a->x_csect.x_smtyp = XTY_SD;
|
---|
5037 | a->x_csect.x_parmhash = 0;
|
---|
5038 | a->x_csect.x_snhash = 0;
|
---|
5039 | a->x_csect.x_smclas = XMC_XO;
|
---|
5040 | a->x_csect.x_stab = 0;
|
---|
5041 | a->x_csect.x_snstab = 0;
|
---|
5042 |
|
---|
5043 | symbol_insert (csect, sym, &symbol_rootP, &symbol_lastP);
|
---|
5044 |
|
---|
5045 | i = S_GET_NUMBER_AUXILIARY (sym);
|
---|
5046 | a = &coffsymbol (symbol_get_bfdsym (sym))->native[i].u.auxent;
|
---|
5047 | a->x_csect.x_scnlen.p = coffsymbol (symbol_get_bfdsym (csect))->native;
|
---|
5048 | coffsymbol (symbol_get_bfdsym (sym))->native[i].fix_scnlen = 1;
|
---|
5049 | }
|
---|
5050 |
|
---|
5051 | ppc_saw_abs = FALSE;
|
---|
5052 | }
|
---|
5053 |
|
---|
5054 | /* Set the VMA for a section. This is called on all the sections in
|
---|
5055 | turn. */
|
---|
5056 |
|
---|
5057 | void
|
---|
5058 | ppc_frob_section (sec)
|
---|
5059 | asection *sec;
|
---|
5060 | {
|
---|
5061 | static bfd_size_type vma = 0;
|
---|
5062 |
|
---|
5063 | bfd_set_section_vma (stdoutput, sec, vma);
|
---|
5064 | vma += bfd_section_size (stdoutput, sec);
|
---|
5065 | }
|
---|
5066 |
|
---|
5067 | #endif /* OBJ_XCOFF */
|
---|
5068 | |
---|
5069 |
|
---|
5070 | /* Turn a string in input_line_pointer into a floating point constant
|
---|
5071 | of type TYPE, and store the appropriate bytes in *LITP. The number
|
---|
5072 | of LITTLENUMS emitted is stored in *SIZEP. An error message is
|
---|
5073 | returned, or NULL on OK. */
|
---|
5074 |
|
---|
5075 | char *
|
---|
5076 | md_atof (type, litp, sizep)
|
---|
5077 | int type;
|
---|
5078 | char *litp;
|
---|
5079 | int *sizep;
|
---|
5080 | {
|
---|
5081 | int prec;
|
---|
5082 | LITTLENUM_TYPE words[4];
|
---|
5083 | char *t;
|
---|
5084 | int i;
|
---|
5085 |
|
---|
5086 | switch (type)
|
---|
5087 | {
|
---|
5088 | case 'f':
|
---|
5089 | prec = 2;
|
---|
5090 | break;
|
---|
5091 |
|
---|
5092 | case 'd':
|
---|
5093 | prec = 4;
|
---|
5094 | break;
|
---|
5095 |
|
---|
5096 | default:
|
---|
5097 | *sizep = 0;
|
---|
5098 | return _("bad call to md_atof");
|
---|
5099 | }
|
---|
5100 |
|
---|
5101 | t = atof_ieee (input_line_pointer, type, words);
|
---|
5102 | if (t)
|
---|
5103 | input_line_pointer = t;
|
---|
5104 |
|
---|
5105 | *sizep = prec * 2;
|
---|
5106 |
|
---|
5107 | if (target_big_endian)
|
---|
5108 | {
|
---|
5109 | for (i = 0; i < prec; i++)
|
---|
5110 | {
|
---|
5111 | md_number_to_chars (litp, (valueT) words[i], 2);
|
---|
5112 | litp += 2;
|
---|
5113 | }
|
---|
5114 | }
|
---|
5115 | else
|
---|
5116 | {
|
---|
5117 | for (i = prec - 1; i >= 0; i--)
|
---|
5118 | {
|
---|
5119 | md_number_to_chars (litp, (valueT) words[i], 2);
|
---|
5120 | litp += 2;
|
---|
5121 | }
|
---|
5122 | }
|
---|
5123 |
|
---|
5124 | return NULL;
|
---|
5125 | }
|
---|
5126 |
|
---|
5127 | /* Write a value out to the object file, using the appropriate
|
---|
5128 | endianness. */
|
---|
5129 |
|
---|
5130 | void
|
---|
5131 | md_number_to_chars (buf, val, n)
|
---|
5132 | char *buf;
|
---|
5133 | valueT val;
|
---|
5134 | int n;
|
---|
5135 | {
|
---|
5136 | if (target_big_endian)
|
---|
5137 | number_to_chars_bigendian (buf, val, n);
|
---|
5138 | else
|
---|
5139 | number_to_chars_littleendian (buf, val, n);
|
---|
5140 | }
|
---|
5141 |
|
---|
5142 | /* Align a section (I don't know why this is machine dependent). */
|
---|
5143 |
|
---|
5144 | valueT
|
---|
5145 | md_section_align (seg, addr)
|
---|
5146 | asection *seg;
|
---|
5147 | valueT addr;
|
---|
5148 | {
|
---|
5149 | int align = bfd_get_section_alignment (stdoutput, seg);
|
---|
5150 |
|
---|
5151 | return ((addr + (1 << align) - 1) & (-1 << align));
|
---|
5152 | }
|
---|
5153 |
|
---|
5154 | /* We don't have any form of relaxing. */
|
---|
5155 |
|
---|
5156 | int
|
---|
5157 | md_estimate_size_before_relax (fragp, seg)
|
---|
5158 | fragS *fragp ATTRIBUTE_UNUSED;
|
---|
5159 | asection *seg ATTRIBUTE_UNUSED;
|
---|
5160 | {
|
---|
5161 | abort ();
|
---|
5162 | return 0;
|
---|
5163 | }
|
---|
5164 |
|
---|
5165 | /* Convert a machine dependent frag. We never generate these. */
|
---|
5166 |
|
---|
5167 | void
|
---|
5168 | md_convert_frag (abfd, sec, fragp)
|
---|
5169 | bfd *abfd ATTRIBUTE_UNUSED;
|
---|
5170 | asection *sec ATTRIBUTE_UNUSED;
|
---|
5171 | fragS *fragp ATTRIBUTE_UNUSED;
|
---|
5172 | {
|
---|
5173 | abort ();
|
---|
5174 | }
|
---|
5175 |
|
---|
5176 | /* We have no need to default values of symbols. */
|
---|
5177 |
|
---|
5178 | symbolS *
|
---|
5179 | md_undefined_symbol (name)
|
---|
5180 | char *name ATTRIBUTE_UNUSED;
|
---|
5181 | {
|
---|
5182 | return 0;
|
---|
5183 | }
|
---|
5184 | |
---|
5185 |
|
---|
5186 | /* Functions concerning relocs. */
|
---|
5187 |
|
---|
5188 | /* The location from which a PC relative jump should be calculated,
|
---|
5189 | given a PC relative reloc. */
|
---|
5190 |
|
---|
5191 | long
|
---|
5192 | md_pcrel_from_section (fixp, sec)
|
---|
5193 | fixS *fixp;
|
---|
5194 | segT sec ATTRIBUTE_UNUSED;
|
---|
5195 | {
|
---|
5196 | return fixp->fx_frag->fr_address + fixp->fx_where;
|
---|
5197 | }
|
---|
5198 |
|
---|
5199 | #ifdef OBJ_XCOFF
|
---|
5200 |
|
---|
5201 | /* This is called to see whether a fixup should be adjusted to use a
|
---|
5202 | section symbol. We take the opportunity to change a fixup against
|
---|
5203 | a symbol in the TOC subsegment into a reloc against the
|
---|
5204 | corresponding .tc symbol. */
|
---|
5205 |
|
---|
5206 | int
|
---|
5207 | ppc_fix_adjustable (fix)
|
---|
5208 | fixS *fix;
|
---|
5209 | {
|
---|
5210 | valueT val = resolve_symbol_value (fix->fx_addsy);
|
---|
5211 | segT symseg = S_GET_SEGMENT (fix->fx_addsy);
|
---|
5212 | TC_SYMFIELD_TYPE *tc;
|
---|
5213 |
|
---|
5214 | if (symseg == absolute_section)
|
---|
5215 | return 0;
|
---|
5216 |
|
---|
5217 | if (ppc_toc_csect != (symbolS *) NULL
|
---|
5218 | && fix->fx_addsy != ppc_toc_csect
|
---|
5219 | && symseg == data_section
|
---|
5220 | && val >= ppc_toc_frag->fr_address
|
---|
5221 | && (ppc_after_toc_frag == (fragS *) NULL
|
---|
5222 | || val < ppc_after_toc_frag->fr_address))
|
---|
5223 | {
|
---|
5224 | symbolS *sy;
|
---|
5225 |
|
---|
5226 | for (sy = symbol_next (ppc_toc_csect);
|
---|
5227 | sy != (symbolS *) NULL;
|
---|
5228 | sy = symbol_next (sy))
|
---|
5229 | {
|
---|
5230 | TC_SYMFIELD_TYPE *sy_tc = symbol_get_tc (sy);
|
---|
5231 |
|
---|
5232 | if (sy_tc->class == XMC_TC0)
|
---|
5233 | continue;
|
---|
5234 | if (sy_tc->class != XMC_TC)
|
---|
5235 | break;
|
---|
5236 | if (val == resolve_symbol_value (sy))
|
---|
5237 | {
|
---|
5238 | fix->fx_addsy = sy;
|
---|
5239 | fix->fx_addnumber = val - ppc_toc_frag->fr_address;
|
---|
5240 | return 0;
|
---|
5241 | }
|
---|
5242 | }
|
---|
5243 |
|
---|
5244 | as_bad_where (fix->fx_file, fix->fx_line,
|
---|
5245 | _("symbol in .toc does not match any .tc"));
|
---|
5246 | }
|
---|
5247 |
|
---|
5248 | /* Possibly adjust the reloc to be against the csect. */
|
---|
5249 | tc = symbol_get_tc (fix->fx_addsy);
|
---|
5250 | if (tc->subseg == 0
|
---|
5251 | && tc->class != XMC_TC0
|
---|
5252 | && tc->class != XMC_TC
|
---|
5253 | && symseg != bss_section
|
---|
5254 | /* Don't adjust if this is a reloc in the toc section. */
|
---|
5255 | && (symseg != data_section
|
---|
5256 | || ppc_toc_csect == NULL
|
---|
5257 | || val < ppc_toc_frag->fr_address
|
---|
5258 | || (ppc_after_toc_frag != NULL
|
---|
5259 | && val >= ppc_after_toc_frag->fr_address)))
|
---|
5260 | {
|
---|
5261 | symbolS *csect;
|
---|
5262 | symbolS *next_csect;
|
---|
5263 |
|
---|
5264 | if (symseg == text_section)
|
---|
5265 | csect = ppc_text_csects;
|
---|
5266 | else if (symseg == data_section)
|
---|
5267 | csect = ppc_data_csects;
|
---|
5268 | else
|
---|
5269 | abort ();
|
---|
5270 |
|
---|
5271 | /* Skip the initial dummy symbol. */
|
---|
5272 | csect = symbol_get_tc (csect)->next;
|
---|
5273 |
|
---|
5274 | if (csect != (symbolS *) NULL)
|
---|
5275 | {
|
---|
5276 | while ((next_csect = symbol_get_tc (csect)->next) != (symbolS *) NULL
|
---|
5277 | && (symbol_get_frag (next_csect)->fr_address <= val))
|
---|
5278 | {
|
---|
5279 | /* If the csect address equals the symbol value, then we
|
---|
5280 | have to look through the full symbol table to see
|
---|
5281 | whether this is the csect we want. Note that we will
|
---|
5282 | only get here if the csect has zero length. */
|
---|
5283 | if (symbol_get_frag (csect)->fr_address == val
|
---|
5284 | && S_GET_VALUE (csect) == val)
|
---|
5285 | {
|
---|
5286 | symbolS *scan;
|
---|
5287 |
|
---|
5288 | for (scan = symbol_next (csect);
|
---|
5289 | scan != NULL;
|
---|
5290 | scan = symbol_next (scan))
|
---|
5291 | {
|
---|
5292 | if (symbol_get_tc (scan)->subseg != 0)
|
---|
5293 | break;
|
---|
5294 | if (scan == fix->fx_addsy)
|
---|
5295 | break;
|
---|
5296 | }
|
---|
5297 |
|
---|
5298 | /* If we found the symbol before the next csect
|
---|
5299 | symbol, then this is the csect we want. */
|
---|
5300 | if (scan == fix->fx_addsy)
|
---|
5301 | break;
|
---|
5302 | }
|
---|
5303 |
|
---|
5304 | csect = next_csect;
|
---|
5305 | }
|
---|
5306 |
|
---|
5307 | fix->fx_offset += val - symbol_get_frag (csect)->fr_address;
|
---|
5308 | fix->fx_addsy = csect;
|
---|
5309 | }
|
---|
5310 | return 0;
|
---|
5311 | }
|
---|
5312 |
|
---|
5313 | /* Adjust a reloc against a .lcomm symbol to be against the base
|
---|
5314 | .lcomm. */
|
---|
5315 | if (symseg == bss_section
|
---|
5316 | && ! S_IS_EXTERNAL (fix->fx_addsy))
|
---|
5317 | {
|
---|
5318 | symbolS *sy = symbol_get_frag (fix->fx_addsy)->fr_symbol;
|
---|
5319 |
|
---|
5320 | fix->fx_offset += val - resolve_symbol_value (sy);
|
---|
5321 | fix->fx_addsy = sy;
|
---|
5322 | }
|
---|
5323 |
|
---|
5324 | return 0;
|
---|
5325 | }
|
---|
5326 |
|
---|
5327 | /* A reloc from one csect to another must be kept. The assembler
|
---|
5328 | will, of course, keep relocs between sections, and it will keep
|
---|
5329 | absolute relocs, but we need to force it to keep PC relative relocs
|
---|
5330 | between two csects in the same section. */
|
---|
5331 |
|
---|
5332 | int
|
---|
5333 | ppc_force_relocation (fix)
|
---|
5334 | fixS *fix;
|
---|
5335 | {
|
---|
5336 | /* At this point fix->fx_addsy should already have been converted to
|
---|
5337 | a csect symbol. If the csect does not include the fragment, then
|
---|
5338 | we need to force the relocation. */
|
---|
5339 | if (fix->fx_pcrel
|
---|
5340 | && fix->fx_addsy != NULL
|
---|
5341 | && symbol_get_tc (fix->fx_addsy)->subseg != 0
|
---|
5342 | && ((symbol_get_frag (fix->fx_addsy)->fr_address
|
---|
5343 | > fix->fx_frag->fr_address)
|
---|
5344 | || (symbol_get_tc (fix->fx_addsy)->next != NULL
|
---|
5345 | && (symbol_get_frag (symbol_get_tc (fix->fx_addsy)->next)->fr_address
|
---|
5346 | <= fix->fx_frag->fr_address))))
|
---|
5347 | return 1;
|
---|
5348 |
|
---|
5349 | return generic_force_reloc (fix);
|
---|
5350 | }
|
---|
5351 |
|
---|
5352 | #endif /* OBJ_XCOFF */
|
---|
5353 |
|
---|
5354 | #ifdef OBJ_ELF
|
---|
5355 | /* If this function returns non-zero, it guarantees that a relocation
|
---|
5356 | will be emitted for a fixup. */
|
---|
5357 |
|
---|
5358 | int
|
---|
5359 | ppc_force_relocation (fix)
|
---|
5360 | fixS *fix;
|
---|
5361 | {
|
---|
5362 | /* Branch prediction relocations must force a relocation, as must
|
---|
5363 | the vtable description relocs. */
|
---|
5364 | switch (fix->fx_r_type)
|
---|
5365 | {
|
---|
5366 | case BFD_RELOC_PPC_B16_BRTAKEN:
|
---|
5367 | case BFD_RELOC_PPC_B16_BRNTAKEN:
|
---|
5368 | case BFD_RELOC_PPC_BA16_BRTAKEN:
|
---|
5369 | case BFD_RELOC_PPC_BA16_BRNTAKEN:
|
---|
5370 | case BFD_RELOC_PPC64_TOC:
|
---|
5371 | return 1;
|
---|
5372 | default:
|
---|
5373 | break;
|
---|
5374 | }
|
---|
5375 |
|
---|
5376 | if (fix->fx_r_type >= BFD_RELOC_PPC_TLS
|
---|
5377 | && fix->fx_r_type <= BFD_RELOC_PPC64_DTPREL16_HIGHESTA)
|
---|
5378 | return 1;
|
---|
5379 |
|
---|
5380 | return generic_force_reloc (fix);
|
---|
5381 | }
|
---|
5382 |
|
---|
5383 | int
|
---|
5384 | ppc_fix_adjustable (fix)
|
---|
5385 | fixS *fix;
|
---|
5386 | {
|
---|
5387 | return (fix->fx_r_type != BFD_RELOC_16_GOTOFF
|
---|
5388 | && fix->fx_r_type != BFD_RELOC_LO16_GOTOFF
|
---|
5389 | && fix->fx_r_type != BFD_RELOC_HI16_GOTOFF
|
---|
5390 | && fix->fx_r_type != BFD_RELOC_HI16_S_GOTOFF
|
---|
5391 | && fix->fx_r_type != BFD_RELOC_GPREL16
|
---|
5392 | && fix->fx_r_type != BFD_RELOC_VTABLE_INHERIT
|
---|
5393 | && fix->fx_r_type != BFD_RELOC_VTABLE_ENTRY
|
---|
5394 | && !(fix->fx_r_type >= BFD_RELOC_PPC_TLS
|
---|
5395 | && fix->fx_r_type <= BFD_RELOC_PPC64_DTPREL16_HIGHESTA)
|
---|
5396 | && (fix->fx_pcrel
|
---|
5397 | || (fix->fx_subsy != NULL
|
---|
5398 | && (S_GET_SEGMENT (fix->fx_subsy)
|
---|
5399 | == S_GET_SEGMENT (fix->fx_addsy)))
|
---|
5400 | || S_IS_LOCAL (fix->fx_addsy)));
|
---|
5401 | }
|
---|
5402 | #endif
|
---|
5403 |
|
---|
5404 | /* Apply a fixup to the object code. This is called for all the
|
---|
5405 | fixups we generated by the call to fix_new_exp, above. In the call
|
---|
5406 | above we used a reloc code which was the largest legal reloc code
|
---|
5407 | plus the operand index. Here we undo that to recover the operand
|
---|
5408 | index. At this point all symbol values should be fully resolved,
|
---|
5409 | and we attempt to completely resolve the reloc. If we can not do
|
---|
5410 | that, we determine the correct reloc code and put it back in the
|
---|
5411 | fixup. */
|
---|
5412 |
|
---|
5413 | void
|
---|
5414 | md_apply_fix3 (fixP, valP, seg)
|
---|
5415 | fixS *fixP;
|
---|
5416 | valueT * valP;
|
---|
5417 | segT seg ATTRIBUTE_UNUSED;
|
---|
5418 | {
|
---|
5419 | valueT value = * valP;
|
---|
5420 |
|
---|
5421 | #ifdef OBJ_ELF
|
---|
5422 | if (fixP->fx_addsy != NULL)
|
---|
5423 | {
|
---|
5424 | /* Hack around bfd_install_relocation brain damage. */
|
---|
5425 | if (fixP->fx_pcrel)
|
---|
5426 | value += fixP->fx_frag->fr_address + fixP->fx_where;
|
---|
5427 | }
|
---|
5428 | else
|
---|
5429 | fixP->fx_done = 1;
|
---|
5430 | #else
|
---|
5431 | /* FIXME FIXME FIXME: The value we are passed in *valP includes
|
---|
5432 | the symbol values. Since we are using BFD_ASSEMBLER, if we are
|
---|
5433 | doing this relocation the code in write.c is going to call
|
---|
5434 | bfd_install_relocation, which is also going to use the symbol
|
---|
5435 | value. That means that if the reloc is fully resolved we want to
|
---|
5436 | use *valP since bfd_install_relocation is not being used.
|
---|
5437 | However, if the reloc is not fully resolved we do not want to use
|
---|
5438 | *valP, and must use fx_offset instead. However, if the reloc
|
---|
5439 | is PC relative, we do want to use *valP since it includes the
|
---|
5440 | result of md_pcrel_from. This is confusing. */
|
---|
5441 | if (fixP->fx_addsy == (symbolS *) NULL)
|
---|
5442 | fixP->fx_done = 1;
|
---|
5443 |
|
---|
5444 | else if (fixP->fx_pcrel)
|
---|
5445 | ;
|
---|
5446 |
|
---|
5447 | else
|
---|
5448 | value = fixP->fx_offset;
|
---|
5449 | #endif
|
---|
5450 |
|
---|
5451 | if (fixP->fx_subsy != (symbolS *) NULL)
|
---|
5452 | {
|
---|
5453 | /* We can't actually support subtracting a symbol. */
|
---|
5454 | as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
|
---|
5455 | }
|
---|
5456 |
|
---|
5457 | if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
|
---|
5458 | {
|
---|
5459 | int opindex;
|
---|
5460 | const struct powerpc_operand *operand;
|
---|
5461 | char *where;
|
---|
5462 | unsigned long insn;
|
---|
5463 |
|
---|
5464 | opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
|
---|
5465 |
|
---|
5466 | operand = &powerpc_operands[opindex];
|
---|
5467 |
|
---|
5468 | #ifdef OBJ_XCOFF
|
---|
5469 | /* An instruction like `lwz 9,sym(30)' when `sym' is not a TOC symbol
|
---|
5470 | does not generate a reloc. It uses the offset of `sym' within its
|
---|
5471 | csect. Other usages, such as `.long sym', generate relocs. This
|
---|
5472 | is the documented behaviour of non-TOC symbols. */
|
---|
5473 | if ((operand->flags & PPC_OPERAND_PARENS) != 0
|
---|
5474 | && operand->bits == 16
|
---|
5475 | && operand->shift == 0
|
---|
5476 | && (operand->insert == NULL || ppc_obj64)
|
---|
5477 | && fixP->fx_addsy != NULL
|
---|
5478 | && symbol_get_tc (fixP->fx_addsy)->subseg != 0
|
---|
5479 | && symbol_get_tc (fixP->fx_addsy)->class != XMC_TC
|
---|
5480 | && symbol_get_tc (fixP->fx_addsy)->class != XMC_TC0
|
---|
5481 | && S_GET_SEGMENT (fixP->fx_addsy) != bss_section)
|
---|
5482 | {
|
---|
5483 | value = fixP->fx_offset;
|
---|
5484 | fixP->fx_done = 1;
|
---|
5485 | }
|
---|
5486 | #endif
|
---|
5487 |
|
---|
5488 | /* Fetch the instruction, insert the fully resolved operand
|
---|
5489 | value, and stuff the instruction back again. */
|
---|
5490 | where = fixP->fx_frag->fr_literal + fixP->fx_where;
|
---|
5491 | if (target_big_endian)
|
---|
5492 | insn = bfd_getb32 ((unsigned char *) where);
|
---|
5493 | else
|
---|
5494 | insn = bfd_getl32 ((unsigned char *) where);
|
---|
5495 | insn = ppc_insert_operand (insn, operand, (offsetT) value,
|
---|
5496 | fixP->fx_file, fixP->fx_line);
|
---|
5497 | if (target_big_endian)
|
---|
5498 | bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
|
---|
5499 | else
|
---|
5500 | bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
|
---|
5501 |
|
---|
5502 | if (fixP->fx_done)
|
---|
5503 | /* Nothing else to do here. */
|
---|
5504 | return;
|
---|
5505 |
|
---|
5506 | assert (fixP->fx_addsy != NULL);
|
---|
5507 |
|
---|
5508 | /* Determine a BFD reloc value based on the operand information.
|
---|
5509 | We are only prepared to turn a few of the operands into
|
---|
5510 | relocs. */
|
---|
5511 | if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
|
---|
5512 | && operand->bits == 26
|
---|
5513 | && operand->shift == 0)
|
---|
5514 | fixP->fx_r_type = BFD_RELOC_PPC_B26;
|
---|
5515 | else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
|
---|
5516 | && operand->bits == 16
|
---|
5517 | && operand->shift == 0)
|
---|
5518 | {
|
---|
5519 | fixP->fx_r_type = BFD_RELOC_PPC_B16;
|
---|
5520 | #ifdef OBJ_XCOFF
|
---|
5521 | fixP->fx_size = 2;
|
---|
5522 | if (target_big_endian)
|
---|
5523 | fixP->fx_where += 2;
|
---|
5524 | #endif
|
---|
5525 | }
|
---|
5526 | else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
|
---|
5527 | && operand->bits == 26
|
---|
5528 | && operand->shift == 0)
|
---|
5529 | fixP->fx_r_type = BFD_RELOC_PPC_BA26;
|
---|
5530 | else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
|
---|
5531 | && operand->bits == 16
|
---|
5532 | && operand->shift == 0)
|
---|
5533 | {
|
---|
5534 | fixP->fx_r_type = BFD_RELOC_PPC_BA16;
|
---|
5535 | #ifdef OBJ_XCOFF
|
---|
5536 | fixP->fx_size = 2;
|
---|
5537 | if (target_big_endian)
|
---|
5538 | fixP->fx_where += 2;
|
---|
5539 | #endif
|
---|
5540 | }
|
---|
5541 | #if defined (OBJ_XCOFF) || defined (OBJ_ELF)
|
---|
5542 | else if ((operand->flags & PPC_OPERAND_PARENS) != 0
|
---|
5543 | && operand->bits == 16
|
---|
5544 | && operand->shift == 0)
|
---|
5545 | {
|
---|
5546 | if (ppc_is_toc_sym (fixP->fx_addsy))
|
---|
5547 | {
|
---|
5548 | fixP->fx_r_type = BFD_RELOC_PPC_TOC16;
|
---|
5549 | #ifdef OBJ_ELF
|
---|
5550 | if (ppc_obj64
|
---|
5551 | && (operand->flags & PPC_OPERAND_DS) != 0)
|
---|
5552 | fixP->fx_r_type = BFD_RELOC_PPC64_TOC16_DS;
|
---|
5553 | #endif
|
---|
5554 | }
|
---|
5555 | else
|
---|
5556 | {
|
---|
5557 | fixP->fx_r_type = BFD_RELOC_16;
|
---|
5558 | #ifdef OBJ_ELF
|
---|
5559 | if (ppc_obj64
|
---|
5560 | && (operand->flags & PPC_OPERAND_DS) != 0)
|
---|
5561 | fixP->fx_r_type = BFD_RELOC_PPC64_ADDR16_DS;
|
---|
5562 | #endif
|
---|
5563 | }
|
---|
5564 | fixP->fx_size = 2;
|
---|
5565 | if (target_big_endian)
|
---|
5566 | fixP->fx_where += 2;
|
---|
5567 | }
|
---|
5568 | #endif /* defined (OBJ_XCOFF) || defined (OBJ_ELF) */
|
---|
5569 | else
|
---|
5570 | {
|
---|
5571 | char *sfile;
|
---|
5572 | unsigned int sline;
|
---|
5573 |
|
---|
5574 | /* Use expr_symbol_where to see if this is an expression
|
---|
5575 | symbol. */
|
---|
5576 | if (expr_symbol_where (fixP->fx_addsy, &sfile, &sline))
|
---|
5577 | as_bad_where (fixP->fx_file, fixP->fx_line,
|
---|
5578 | _("unresolved expression that must be resolved"));
|
---|
5579 | else
|
---|
5580 | as_bad_where (fixP->fx_file, fixP->fx_line,
|
---|
5581 | _("unsupported relocation against %s"),
|
---|
5582 | S_GET_NAME (fixP->fx_addsy));
|
---|
5583 | fixP->fx_done = 1;
|
---|
5584 | return;
|
---|
5585 | }
|
---|
5586 | }
|
---|
5587 | else
|
---|
5588 | {
|
---|
5589 | #ifdef OBJ_ELF
|
---|
5590 | ppc_elf_validate_fix (fixP, seg);
|
---|
5591 | #endif
|
---|
5592 | switch (fixP->fx_r_type)
|
---|
5593 | {
|
---|
5594 | case BFD_RELOC_CTOR:
|
---|
5595 | if (ppc_obj64)
|
---|
5596 | goto ctor64;
|
---|
5597 | /* fall through */
|
---|
5598 |
|
---|
5599 | case BFD_RELOC_32:
|
---|
5600 | if (fixP->fx_pcrel)
|
---|
5601 | fixP->fx_r_type = BFD_RELOC_32_PCREL;
|
---|
5602 | /* fall through */
|
---|
5603 |
|
---|
5604 | case BFD_RELOC_RVA:
|
---|
5605 | case BFD_RELOC_32_PCREL:
|
---|
5606 | case BFD_RELOC_PPC_EMB_NADDR32:
|
---|
5607 | md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
|
---|
5608 | value, 4);
|
---|
5609 | break;
|
---|
5610 |
|
---|
5611 | case BFD_RELOC_64:
|
---|
5612 | ctor64:
|
---|
5613 | if (fixP->fx_pcrel)
|
---|
5614 | fixP->fx_r_type = BFD_RELOC_64_PCREL;
|
---|
5615 | /* fall through */
|
---|
5616 |
|
---|
5617 | case BFD_RELOC_64_PCREL:
|
---|
5618 | md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
|
---|
5619 | value, 8);
|
---|
5620 | break;
|
---|
5621 |
|
---|
5622 | case BFD_RELOC_LO16:
|
---|
5623 | case BFD_RELOC_16:
|
---|
5624 | case BFD_RELOC_GPREL16:
|
---|
5625 | case BFD_RELOC_16_GOT_PCREL:
|
---|
5626 | case BFD_RELOC_16_GOTOFF:
|
---|
5627 | case BFD_RELOC_LO16_GOTOFF:
|
---|
5628 | case BFD_RELOC_HI16_GOTOFF:
|
---|
5629 | case BFD_RELOC_HI16_S_GOTOFF:
|
---|
5630 | case BFD_RELOC_16_BASEREL:
|
---|
5631 | case BFD_RELOC_LO16_BASEREL:
|
---|
5632 | case BFD_RELOC_HI16_BASEREL:
|
---|
5633 | case BFD_RELOC_HI16_S_BASEREL:
|
---|
5634 | case BFD_RELOC_PPC_EMB_NADDR16:
|
---|
5635 | case BFD_RELOC_PPC_EMB_NADDR16_LO:
|
---|
5636 | case BFD_RELOC_PPC_EMB_NADDR16_HI:
|
---|
5637 | case BFD_RELOC_PPC_EMB_NADDR16_HA:
|
---|
5638 | case BFD_RELOC_PPC_EMB_SDAI16:
|
---|
5639 | case BFD_RELOC_PPC_EMB_SDA2REL:
|
---|
5640 | case BFD_RELOC_PPC_EMB_SDA2I16:
|
---|
5641 | case BFD_RELOC_PPC_EMB_RELSEC16:
|
---|
5642 | case BFD_RELOC_PPC_EMB_RELST_LO:
|
---|
5643 | case BFD_RELOC_PPC_EMB_RELST_HI:
|
---|
5644 | case BFD_RELOC_PPC_EMB_RELST_HA:
|
---|
5645 | case BFD_RELOC_PPC_EMB_RELSDA:
|
---|
5646 | case BFD_RELOC_PPC_TOC16:
|
---|
5647 | #ifdef OBJ_ELF
|
---|
5648 | case BFD_RELOC_PPC64_TOC16_LO:
|
---|
5649 | case BFD_RELOC_PPC64_TOC16_HI:
|
---|
5650 | case BFD_RELOC_PPC64_TOC16_HA:
|
---|
5651 | #endif
|
---|
5652 | if (fixP->fx_pcrel)
|
---|
5653 | {
|
---|
5654 | if (fixP->fx_addsy != NULL)
|
---|
5655 | as_bad_where (fixP->fx_file, fixP->fx_line,
|
---|
5656 | _("cannot emit PC relative %s relocation against %s"),
|
---|
5657 | bfd_get_reloc_code_name (fixP->fx_r_type),
|
---|
5658 | S_GET_NAME (fixP->fx_addsy));
|
---|
5659 | else
|
---|
5660 | as_bad_where (fixP->fx_file, fixP->fx_line,
|
---|
5661 | _("cannot emit PC relative %s relocation"),
|
---|
5662 | bfd_get_reloc_code_name (fixP->fx_r_type));
|
---|
5663 | }
|
---|
5664 |
|
---|
5665 | md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
|
---|
5666 | value, 2);
|
---|
5667 | break;
|
---|
5668 |
|
---|
5669 | /* This case happens when you write, for example,
|
---|
5670 | lis %r3,(L1-L2)@ha
|
---|
5671 | where L1 and L2 are defined later. */
|
---|
5672 | case BFD_RELOC_HI16:
|
---|
5673 | if (fixP->fx_pcrel)
|
---|
5674 | abort ();
|
---|
5675 | md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
|
---|
5676 | PPC_HI (value), 2);
|
---|
5677 | break;
|
---|
5678 |
|
---|
5679 | case BFD_RELOC_HI16_S:
|
---|
5680 | if (fixP->fx_pcrel)
|
---|
5681 | abort ();
|
---|
5682 | md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
|
---|
5683 | PPC_HA (value), 2);
|
---|
5684 | break;
|
---|
5685 |
|
---|
5686 | #ifdef OBJ_ELF
|
---|
5687 | case BFD_RELOC_PPC64_HIGHER:
|
---|
5688 | if (fixP->fx_pcrel)
|
---|
5689 | abort ();
|
---|
5690 | md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
|
---|
5691 | PPC_HIGHER (value), 2);
|
---|
5692 | break;
|
---|
5693 |
|
---|
5694 | case BFD_RELOC_PPC64_HIGHER_S:
|
---|
5695 | if (fixP->fx_pcrel)
|
---|
5696 | abort ();
|
---|
5697 | md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
|
---|
5698 | PPC_HIGHERA (value), 2);
|
---|
5699 | break;
|
---|
5700 |
|
---|
5701 | case BFD_RELOC_PPC64_HIGHEST:
|
---|
5702 | if (fixP->fx_pcrel)
|
---|
5703 | abort ();
|
---|
5704 | md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
|
---|
5705 | PPC_HIGHEST (value), 2);
|
---|
5706 | break;
|
---|
5707 |
|
---|
5708 | case BFD_RELOC_PPC64_HIGHEST_S:
|
---|
5709 | if (fixP->fx_pcrel)
|
---|
5710 | abort ();
|
---|
5711 | md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
|
---|
5712 | PPC_HIGHESTA (value), 2);
|
---|
5713 | break;
|
---|
5714 |
|
---|
5715 | case BFD_RELOC_PPC64_ADDR16_DS:
|
---|
5716 | case BFD_RELOC_PPC64_ADDR16_LO_DS:
|
---|
5717 | case BFD_RELOC_PPC64_GOT16_DS:
|
---|
5718 | case BFD_RELOC_PPC64_GOT16_LO_DS:
|
---|
5719 | case BFD_RELOC_PPC64_PLT16_LO_DS:
|
---|
5720 | case BFD_RELOC_PPC64_SECTOFF_DS:
|
---|
5721 | case BFD_RELOC_PPC64_SECTOFF_LO_DS:
|
---|
5722 | case BFD_RELOC_PPC64_TOC16_DS:
|
---|
5723 | case BFD_RELOC_PPC64_TOC16_LO_DS:
|
---|
5724 | case BFD_RELOC_PPC64_PLTGOT16_DS:
|
---|
5725 | case BFD_RELOC_PPC64_PLTGOT16_LO_DS:
|
---|
5726 | if (fixP->fx_pcrel)
|
---|
5727 | abort ();
|
---|
5728 | {
|
---|
5729 | unsigned char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
|
---|
5730 | unsigned long val;
|
---|
5731 |
|
---|
5732 | if (target_big_endian)
|
---|
5733 | val = bfd_getb16 (where);
|
---|
5734 | else
|
---|
5735 | val = bfd_getl16 (where);
|
---|
5736 | val |= (value & 0xfffc);
|
---|
5737 | if (target_big_endian)
|
---|
5738 | bfd_putb16 ((bfd_vma) val, where);
|
---|
5739 | else
|
---|
5740 | bfd_putl16 ((bfd_vma) val, where);
|
---|
5741 | }
|
---|
5742 | break;
|
---|
5743 |
|
---|
5744 | case BFD_RELOC_PPC_TLS:
|
---|
5745 | case BFD_RELOC_PPC_DTPMOD:
|
---|
5746 | case BFD_RELOC_PPC_TPREL16:
|
---|
5747 | case BFD_RELOC_PPC_TPREL16_LO:
|
---|
5748 | case BFD_RELOC_PPC_TPREL16_HI:
|
---|
5749 | case BFD_RELOC_PPC_TPREL16_HA:
|
---|
5750 | case BFD_RELOC_PPC_TPREL:
|
---|
5751 | case BFD_RELOC_PPC_DTPREL16:
|
---|
5752 | case BFD_RELOC_PPC_DTPREL16_LO:
|
---|
5753 | case BFD_RELOC_PPC_DTPREL16_HI:
|
---|
5754 | case BFD_RELOC_PPC_DTPREL16_HA:
|
---|
5755 | case BFD_RELOC_PPC_DTPREL:
|
---|
5756 | case BFD_RELOC_PPC_GOT_TLSGD16:
|
---|
5757 | case BFD_RELOC_PPC_GOT_TLSGD16_LO:
|
---|
5758 | case BFD_RELOC_PPC_GOT_TLSGD16_HI:
|
---|
5759 | case BFD_RELOC_PPC_GOT_TLSGD16_HA:
|
---|
5760 | case BFD_RELOC_PPC_GOT_TLSLD16:
|
---|
5761 | case BFD_RELOC_PPC_GOT_TLSLD16_LO:
|
---|
5762 | case BFD_RELOC_PPC_GOT_TLSLD16_HI:
|
---|
5763 | case BFD_RELOC_PPC_GOT_TLSLD16_HA:
|
---|
5764 | case BFD_RELOC_PPC_GOT_TPREL16:
|
---|
5765 | case BFD_RELOC_PPC_GOT_TPREL16_LO:
|
---|
5766 | case BFD_RELOC_PPC_GOT_TPREL16_HI:
|
---|
5767 | case BFD_RELOC_PPC_GOT_TPREL16_HA:
|
---|
5768 | case BFD_RELOC_PPC_GOT_DTPREL16:
|
---|
5769 | case BFD_RELOC_PPC_GOT_DTPREL16_LO:
|
---|
5770 | case BFD_RELOC_PPC_GOT_DTPREL16_HI:
|
---|
5771 | case BFD_RELOC_PPC_GOT_DTPREL16_HA:
|
---|
5772 | case BFD_RELOC_PPC64_TPREL16_DS:
|
---|
5773 | case BFD_RELOC_PPC64_TPREL16_LO_DS:
|
---|
5774 | case BFD_RELOC_PPC64_TPREL16_HIGHER:
|
---|
5775 | case BFD_RELOC_PPC64_TPREL16_HIGHERA:
|
---|
5776 | case BFD_RELOC_PPC64_TPREL16_HIGHEST:
|
---|
5777 | case BFD_RELOC_PPC64_TPREL16_HIGHESTA:
|
---|
5778 | case BFD_RELOC_PPC64_DTPREL16_DS:
|
---|
5779 | case BFD_RELOC_PPC64_DTPREL16_LO_DS:
|
---|
5780 | case BFD_RELOC_PPC64_DTPREL16_HIGHER:
|
---|
5781 | case BFD_RELOC_PPC64_DTPREL16_HIGHERA:
|
---|
5782 | case BFD_RELOC_PPC64_DTPREL16_HIGHEST:
|
---|
5783 | case BFD_RELOC_PPC64_DTPREL16_HIGHESTA:
|
---|
5784 | break;
|
---|
5785 | #endif
|
---|
5786 | /* Because SDA21 modifies the register field, the size is set to 4
|
---|
5787 | bytes, rather than 2, so offset it here appropriately. */
|
---|
5788 | case BFD_RELOC_PPC_EMB_SDA21:
|
---|
5789 | if (fixP->fx_pcrel)
|
---|
5790 | abort ();
|
---|
5791 |
|
---|
5792 | md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where
|
---|
5793 | + ((target_big_endian) ? 2 : 0),
|
---|
5794 | value, 2);
|
---|
5795 | break;
|
---|
5796 |
|
---|
5797 | case BFD_RELOC_8:
|
---|
5798 | if (fixP->fx_pcrel)
|
---|
5799 | abort ();
|
---|
5800 |
|
---|
5801 | md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
|
---|
5802 | value, 1);
|
---|
5803 | break;
|
---|
5804 |
|
---|
5805 | case BFD_RELOC_24_PLT_PCREL:
|
---|
5806 | case BFD_RELOC_PPC_LOCAL24PC:
|
---|
5807 | if (!fixP->fx_pcrel && !fixP->fx_done)
|
---|
5808 | abort ();
|
---|
5809 |
|
---|
5810 | if (fixP->fx_done)
|
---|
5811 | {
|
---|
5812 | char *where;
|
---|
5813 | unsigned long insn;
|
---|
5814 |
|
---|
5815 | /* Fetch the instruction, insert the fully resolved operand
|
---|
5816 | value, and stuff the instruction back again. */
|
---|
5817 | where = fixP->fx_frag->fr_literal + fixP->fx_where;
|
---|
5818 | if (target_big_endian)
|
---|
5819 | insn = bfd_getb32 ((unsigned char *) where);
|
---|
5820 | else
|
---|
5821 | insn = bfd_getl32 ((unsigned char *) where);
|
---|
5822 | if ((value & 3) != 0)
|
---|
5823 | as_bad_where (fixP->fx_file, fixP->fx_line,
|
---|
5824 | _("must branch to an address a multiple of 4"));
|
---|
5825 | if ((offsetT) value < -0x40000000
|
---|
5826 | || (offsetT) value >= 0x40000000)
|
---|
5827 | as_bad_where (fixP->fx_file, fixP->fx_line,
|
---|
5828 | _("@local or @plt branch destination is too far away, %ld bytes"),
|
---|
5829 | (long) value);
|
---|
5830 | insn = insn | (value & 0x03fffffc);
|
---|
5831 | if (target_big_endian)
|
---|
5832 | bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
|
---|
5833 | else
|
---|
5834 | bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
|
---|
5835 | }
|
---|
5836 | break;
|
---|
5837 |
|
---|
5838 | case BFD_RELOC_VTABLE_INHERIT:
|
---|
5839 | fixP->fx_done = 0;
|
---|
5840 | if (fixP->fx_addsy
|
---|
5841 | && !S_IS_DEFINED (fixP->fx_addsy)
|
---|
5842 | && !S_IS_WEAK (fixP->fx_addsy))
|
---|
5843 | S_SET_WEAK (fixP->fx_addsy);
|
---|
5844 | break;
|
---|
5845 |
|
---|
5846 | case BFD_RELOC_VTABLE_ENTRY:
|
---|
5847 | fixP->fx_done = 0;
|
---|
5848 | break;
|
---|
5849 |
|
---|
5850 | #ifdef OBJ_ELF
|
---|
5851 | /* Generated by reference to `sym@tocbase'. The sym is
|
---|
5852 | ignored by the linker. */
|
---|
5853 | case BFD_RELOC_PPC64_TOC:
|
---|
5854 | fixP->fx_done = 0;
|
---|
5855 | break;
|
---|
5856 | #endif
|
---|
5857 | default:
|
---|
5858 | fprintf (stderr,
|
---|
5859 | _("Gas failure, reloc value %d\n"), fixP->fx_r_type);
|
---|
5860 | fflush (stderr);
|
---|
5861 | abort ();
|
---|
5862 | }
|
---|
5863 | }
|
---|
5864 |
|
---|
5865 | #ifdef OBJ_ELF
|
---|
5866 | fixP->fx_addnumber = value;
|
---|
5867 | #else
|
---|
5868 | if (fixP->fx_r_type != BFD_RELOC_PPC_TOC16)
|
---|
5869 | fixP->fx_addnumber = 0;
|
---|
5870 | else
|
---|
5871 | {
|
---|
5872 | #ifdef TE_PE
|
---|
5873 | fixP->fx_addnumber = 0;
|
---|
5874 | #else
|
---|
5875 | /* We want to use the offset within the data segment of the
|
---|
5876 | symbol, not the actual VMA of the symbol. */
|
---|
5877 | fixP->fx_addnumber =
|
---|
5878 | - bfd_get_section_vma (stdoutput, S_GET_SEGMENT (fixP->fx_addsy));
|
---|
5879 | #endif
|
---|
5880 | }
|
---|
5881 | #endif
|
---|
5882 | }
|
---|
5883 |
|
---|
5884 | /* Generate a reloc for a fixup. */
|
---|
5885 |
|
---|
5886 | arelent *
|
---|
5887 | tc_gen_reloc (seg, fixp)
|
---|
5888 | asection *seg ATTRIBUTE_UNUSED;
|
---|
5889 | fixS *fixp;
|
---|
5890 | {
|
---|
5891 | arelent *reloc;
|
---|
5892 |
|
---|
5893 | reloc = (arelent *) xmalloc (sizeof (arelent));
|
---|
5894 |
|
---|
5895 | reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
|
---|
5896 | *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
|
---|
5897 | reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
|
---|
5898 | reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
|
---|
5899 | if (reloc->howto == (reloc_howto_type *) NULL)
|
---|
5900 | {
|
---|
5901 | as_bad_where (fixp->fx_file, fixp->fx_line,
|
---|
5902 | _("reloc %d not supported by object file format"),
|
---|
5903 | (int) fixp->fx_r_type);
|
---|
5904 | return NULL;
|
---|
5905 | }
|
---|
5906 | reloc->addend = fixp->fx_addnumber;
|
---|
5907 |
|
---|
5908 | return reloc;
|
---|
5909 | }
|
---|