*** empty log message ***
[deliverable/binutils-gdb.git] / bfd / aout-ns32k.c
CommitLineData
252b5132 1/* BFD back-end for ns32k a.out-ish binaries.
1725a96e 2 Copyright 1990, 1991, 1992, 1994, 1995, 1996, 1998, 2000, 2001
7898deda 3 Free Software Foundation, Inc.
252b5132
RH
4 Contributed by Ian Dall (idall@eleceng.adelaide.edu.au).
5
6This file is part of BFD, the Binary File Descriptor library.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
20Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21
22#define BYTES_IN_WORD 4
23
24#include "bfd.h"
25#include "aout/aout64.h"
26#include "ns32k.h"
27
28#define MYNS(OP) CAT(ns32kaout_,OP)
29reloc_howto_type *
30MYNS(bfd_reloc_type_lookup)
31 PARAMS((bfd *abfd AND
32 bfd_reloc_code_real_type code));
33
34boolean
35MYNS(write_object_contents)
36 PARAMS((bfd *abfd));
37
1725a96e
NC
38/* Avoid multiple definitions from aoutx if supporting
39 standard a.out format(s) as well as this one. */
252b5132
RH
40#define NAME(x,y) CAT3(ns32kaout,_32_,y)
41
42void bfd_ns32k_arch PARAMS ((void));
43
44#include "libaout.h"
45
46#define MY(OP) MYNS(OP)
47
48#define MY_swap_std_reloc_in MY(swap_std_reloc_in)
49#define MY_swap_std_reloc_out MY(swap_std_reloc_out)
50
51static void
52MY_swap_std_reloc_in PARAMS ((bfd *abfd, struct reloc_std_external *bytes,
53 arelent *cache_ptr, asymbol **symbols,
54 bfd_size_type symcount));
252b5132
RH
55static void
56MY_swap_std_reloc_out PARAMS ((bfd *abfd, arelent *g,
57 struct reloc_std_external *natptr));
1725a96e
NC
58reloc_howto_type *
59MY(reloc_howto) PARAMS ((bfd *, struct reloc_std_external *,
60 int *, int *, int *));
61void
62MY(put_reloc) PARAMS ((bfd *, int, int, long, reloc_howto_type *,
63 struct reloc_std_external *));
252b5132
RH
64
65/* The ns32k series is ah, unusual, when it comes to relocation.
1725a96e
NC
66 There are three storage methods for relocateable objects. There
67 are displacements, immediate operands and ordinary twos complement
68 data. Of these, only the last fits into the standard relocation
69 scheme. Immediate operands are stored huffman encoded and
70 immediate operands are stored big endian (where as the natural byte
71 order is little endian for this achitecture).
72
73 Note that the ns32k displacement storage method is orthogonal to
74 whether the relocation is pc relative or not. The "displacement"
75 storage scheme is used for essentially all address constants. The
76 displacement can be relative to zero (absolute displacement),
77 relative to the pc (pc relative), the stack pointer, the frame
78 pointer, the static base register and general purpose register etc.
79
80 For example:
81
82 sym1: .long . # pc relative 2's complement
83 sym1: .long foo # 2's complement not pc relative
84
85 self: movd @self, r0 # pc relative displacement
86 movd foo, r0 # non pc relative displacement
87
88 self: movd self, r0 # pc relative immediate
89 movd foo, r0 # non pc relative immediate
90
91 In addition, for historical reasons the encoding of the relocation types
92 in the a.out format relocation entries is such that even the relocation
93 methods which are standard are not encoded the standard way. */
252b5132 94
c4dfa77f 95reloc_howto_type MY(howto_table)[] =
1725a96e
NC
96 {
97 /* ns32k immediate operands. */
98 HOWTO (BFD_RELOC_NS32K_IMM_8, 0, 0, 8, false, 0, true,
99 _bfd_ns32k_reloc_imm, "NS32K_IMM_8",
100 true, 0x000000ff,0x000000ff, false),
101 HOWTO (BFD_RELOC_NS32K_IMM_16, 0, 1, 16, false, 0, true,
102 _bfd_ns32k_reloc_imm, "NS32K_IMM_16",
103 true, 0x0000ffff,0x0000ffff, false),
104 HOWTO (BFD_RELOC_NS32K_IMM_32, 0, 2, 32, false, 0, true,
105 _bfd_ns32k_reloc_imm, "NS32K_IMM_32",
106 true, 0xffffffff,0xffffffff, false),
107 HOWTO (BFD_RELOC_NS32K_IMM_8_PCREL, 0, 0, 8, true, 0, false,
108 _bfd_ns32k_reloc_imm, "PCREL_NS32K_IMM_8",
109 true, 0x000000ff, 0x000000ff, false),
110 HOWTO (BFD_RELOC_NS32K_IMM_16_PCREL, 0, 1, 16, true, 0, false,
111 _bfd_ns32k_reloc_imm, "PCREL_NS32K_IMM_16",
112 true, 0x0000ffff,0x0000ffff, false),
113 HOWTO (BFD_RELOC_NS32K_IMM_32_PCREL, 0, 2, 32, true, 0, false,
114 _bfd_ns32k_reloc_imm, "PCREL_NS32K_IMM_32",
115 true, 0xffffffff,0xffffffff, false),
116
117 /* ns32k displacements. */
118 HOWTO (BFD_RELOC_NS32K_DISP_8, 0, 0, 8, false, 0, true,
119 _bfd_ns32k_reloc_disp, "NS32K_DISP_8",
120 true, 0x000000ff,0x000000ff, false),
121 HOWTO (BFD_RELOC_NS32K_DISP_16, 0, 1, 16, false, 0, true,
122 _bfd_ns32k_reloc_disp, "NS32K_DISP_16",
123 true, 0x0000ffff, 0x0000ffff, false),
124 HOWTO (BFD_RELOC_NS32K_DISP_32, 0, 2, 32, false, 0, true,
125 _bfd_ns32k_reloc_disp, "NS32K_DISP_32",
126 true, 0xffffffff, 0xffffffff, false),
127 HOWTO (BFD_RELOC_NS32K_DISP_8_PCREL, 0, 0, 8, true, 0, false,
128 _bfd_ns32k_reloc_disp, "PCREL_NS32K_DISP_8",
129 true, 0x000000ff,0x000000ff, false),
130 HOWTO (BFD_RELOC_NS32K_DISP_16_PCREL, 0, 1, 16, true, 0, false,
131 _bfd_ns32k_reloc_disp, "PCREL_NS32K_DISP_16",
132 true, 0x0000ffff,0x0000ffff, false),
133 HOWTO (BFD_RELOC_NS32K_DISP_32_PCREL, 0, 2, 32, true, 0, false,
134 _bfd_ns32k_reloc_disp, "PCREL_NS32K_DISP_32",
135 true, 0xffffffff,0xffffffff, false),
136
137 /* Normal 2's complement. */
138 HOWTO (BFD_RELOC_8, 0, 0, 8, false, 0, complain_overflow_bitfield,0,
139 "8", true, 0x000000ff,0x000000ff, false),
140 HOWTO (BFD_RELOC_16, 0, 1, 16, false, 0, complain_overflow_bitfield,0,
141 "16", true, 0x0000ffff,0x0000ffff, false),
142 HOWTO (BFD_RELOC_32, 0, 2, 32, false, 0, complain_overflow_bitfield,0,
143 "32", true, 0xffffffff,0xffffffff, false),
144 HOWTO (BFD_RELOC_8_PCREL, 0, 0, 8, true, 0, complain_overflow_signed, 0,
145 "PCREL_8", true, 0x000000ff,0x000000ff, false),
146 HOWTO (BFD_RELOC_16_PCREL, 0, 1, 16, true, 0, complain_overflow_signed, 0,
147 "PCREL_16", true, 0x0000ffff,0x0000ffff, false),
148 HOWTO (BFD_RELOC_32_PCREL, 0, 2, 32, true, 0, complain_overflow_signed, 0,
149 "PCREL_32", true, 0xffffffff,0xffffffff, false),
150 };
252b5132 151
252b5132
RH
152#define CTOR_TABLE_RELOC_HOWTO(BFD) (MY(howto_table) + 14)
153
154#define RELOC_STD_BITS_NS32K_TYPE_BIG 0x06
155#define RELOC_STD_BITS_NS32K_TYPE_LITTLE 0x60
156#define RELOC_STD_BITS_NS32K_TYPE_SH_BIG 1
157#define RELOC_STD_BITS_NS32K_TYPE_SH_LITTLE 5
158
159reloc_howto_type *
beb0d161 160MY(reloc_howto) (abfd, rel, r_index, r_extern, r_pcrel)
5f771d47 161 bfd *abfd ATTRIBUTE_UNUSED;
252b5132
RH
162 struct reloc_std_external *rel;
163 int *r_index;
164 int *r_extern;
165 int *r_pcrel;
166{
167 unsigned int r_length;
168 int r_ns32k_type;
1725a96e
NC
169
170 /* BFD_ASSERT(bfd_header_little_endian (abfd)); */
252b5132
RH
171 *r_index = ((rel->r_index[2] << 16)
172 | (rel->r_index[1] << 8)
173 | rel->r_index[0] );
174 *r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE));
175 *r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
176 r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE)
177 >> RELOC_STD_BITS_LENGTH_SH_LITTLE);
178 r_ns32k_type = ((rel->r_type[0] & RELOC_STD_BITS_NS32K_TYPE_LITTLE)
179 >> RELOC_STD_BITS_NS32K_TYPE_SH_LITTLE);
180 return (MY(howto_table) + r_length + 3 * (*r_pcrel) + 6 * r_ns32k_type);
181}
182
beb0d161 183#define MY_reloc_howto(BFD,REL,IN,EX,PC) MY(reloc_howto) (BFD, REL, &IN, &EX, &PC)
252b5132
RH
184
185void
beb0d161 186MY(put_reloc) (abfd, r_extern, r_index, value, howto, reloc)
252b5132
RH
187 bfd *abfd;
188 int r_extern;
189 int r_index;
190 long value;
191 reloc_howto_type *howto;
192 struct reloc_std_external *reloc;
193{
194 unsigned int r_length;
195 int r_pcrel;
196 int r_ns32k_type;
1725a96e 197
252b5132 198 PUT_WORD (abfd, value, reloc->r_address);
1725a96e
NC
199 r_length = howto->size ; /* Size as a power of two. */
200 r_pcrel = (int) howto->pc_relative; /* Relative to PC? */
252b5132 201 r_ns32k_type = (howto - MY(howto_table) )/6;
1725a96e
NC
202
203 /* BFD_ASSERT (bfd_header_little_endian (abfd)); */
252b5132
RH
204 reloc->r_index[2] = r_index >> 16;
205 reloc->r_index[1] = r_index >> 8;
206 reloc->r_index[0] = r_index;
207 reloc->r_type[0] =
208 (r_extern? RELOC_STD_BITS_EXTERN_LITTLE: 0)
209 | (r_pcrel? RELOC_STD_BITS_PCREL_LITTLE: 0)
210 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE)
211 | (r_ns32k_type << RELOC_STD_BITS_NS32K_TYPE_SH_LITTLE);
212}
213
214#define MY_put_reloc(BFD, EXT, IDX, VAL, HOWTO, RELOC) \
beb0d161 215 MY(put_reloc) (BFD, EXT, IDX, VAL, HOWTO, RELOC)
252b5132
RH
216
217#define STAT_FOR_EXEC
218
219#define MY_final_link_relocate _bfd_ns32k_final_link_relocate
220#define MY_relocate_contents _bfd_ns32k_relocate_contents
221
222#include <aoutx.h>
223
224reloc_howto_type *
beb0d161 225MY(bfd_reloc_type_lookup) (abfd,code)
252b5132
RH
226 bfd *abfd;
227 bfd_reloc_code_real_type code;
228{
229
230#define ENTRY(i,j) case i: return &MY(howto_table)[j]
231
232 int ext = obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE;
233
234 BFD_ASSERT(ext == 0);
235 if (code == BFD_RELOC_CTOR)
236 switch (bfd_get_arch_info (abfd)->bits_per_address)
237 {
238 case 32:
239 code = BFD_RELOC_32;
240 break;
1725a96e
NC
241 default:
242 break;
252b5132
RH
243 }
244 switch (code)
245 {
246 ENTRY(BFD_RELOC_NS32K_IMM_8, 0);
247 ENTRY(BFD_RELOC_NS32K_IMM_16, 1);
248 ENTRY(BFD_RELOC_NS32K_IMM_32, 2);
249 ENTRY(BFD_RELOC_NS32K_IMM_8_PCREL, 3);
250 ENTRY(BFD_RELOC_NS32K_IMM_16_PCREL, 4);
251 ENTRY(BFD_RELOC_NS32K_IMM_32_PCREL, 5);
252 ENTRY(BFD_RELOC_NS32K_DISP_8, 6);
253 ENTRY(BFD_RELOC_NS32K_DISP_16, 7);
254 ENTRY(BFD_RELOC_NS32K_DISP_32, 8);
255 ENTRY(BFD_RELOC_NS32K_DISP_8_PCREL, 9);
256 ENTRY(BFD_RELOC_NS32K_DISP_16_PCREL, 10);
257 ENTRY(BFD_RELOC_NS32K_DISP_32_PCREL, 11);
258 ENTRY(BFD_RELOC_8, 12);
259 ENTRY(BFD_RELOC_16, 13);
260 ENTRY(BFD_RELOC_32, 14);
261 ENTRY(BFD_RELOC_8_PCREL, 15);
262 ENTRY(BFD_RELOC_16_PCREL, 16);
263 ENTRY(BFD_RELOC_32_PCREL, 17);
1725a96e
NC
264 default:
265 return (reloc_howto_type *) NULL;
252b5132
RH
266 }
267#undef ENTRY
268}
269
252b5132
RH
270static void
271MY_swap_std_reloc_in (abfd, bytes, cache_ptr, symbols, symcount)
272 bfd *abfd;
273 struct reloc_std_external *bytes;
274 arelent *cache_ptr;
275 asymbol **symbols;
5f771d47 276 bfd_size_type symcount ATTRIBUTE_UNUSED;
252b5132
RH
277{
278 int r_index;
279 int r_extern;
280 int r_pcrel;
281 struct aoutdata *su = &(abfd->tdata.aout_data->a);
282
283 cache_ptr->address = bfd_h_get_32 (abfd, bytes->r_address);
284
1725a96e 285 /* Now the fun stuff. */
252b5132
RH
286 cache_ptr->howto = MY_reloc_howto(abfd, bytes, r_index, r_extern, r_pcrel);
287
1725a96e 288 MOVE_ADDRESS (0);
252b5132
RH
289}
290
291static void
292MY_swap_std_reloc_out (abfd, g, natptr)
293 bfd *abfd;
294 arelent *g;
295 struct reloc_std_external *natptr;
296{
297 int r_index;
298 asymbol *sym = *(g->sym_ptr_ptr);
299 int r_extern;
300 unsigned int r_addend;
301 asection *output_section = sym->section->output_section;
302
303 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
c4dfa77f 304
1725a96e 305 /* Name was clobbered by aout_write_syms to be symbol index. */
252b5132 306
c4dfa77f 307 /* If this relocation is relative to a symbol then set the
252b5132
RH
308 r_index to the symbols index, and the r_extern bit.
309
310 Absolute symbols can come in in two ways, either as an offset
311 from the abs section, or as a symbol which has an abs value.
312 Check for that here. */
252b5132
RH
313 if (bfd_is_com_section (output_section)
314 || output_section == &bfd_abs_section
c4dfa77f 315 || output_section == &bfd_und_section)
252b5132
RH
316 {
317 if (bfd_abs_section.symbol == sym)
318 {
319 /* Whoops, looked like an abs symbol, but is really an offset
1725a96e 320 from the abs section. */
252b5132
RH
321 r_index = 0;
322 r_extern = 0;
323 }
c4dfa77f 324 else
252b5132 325 {
1725a96e 326 /* Fill in symbol. */
252b5132
RH
327 r_extern = 1;
328#undef KEEPIT
329#define KEEPIT udata.i
330 r_index = (*(g->sym_ptr_ptr))->KEEPIT;
c4dfa77f 331#undef KEEPIT
252b5132
RH
332 }
333 }
c4dfa77f 334 else
252b5132 335 {
1725a96e 336 /* Just an ordinary section. */
252b5132 337 r_extern = 0;
c4dfa77f 338 r_index = output_section->target_index;
252b5132
RH
339 }
340
341 MY_put_reloc (abfd, r_extern, r_index, g->address, g->howto, natptr);
342}
343
344bfd_reloc_status_type
345_bfd_ns32k_relocate_contents (howto, input_bfd, relocation, location)
346 reloc_howto_type *howto;
347 bfd *input_bfd;
348 bfd_vma relocation;
349 bfd_byte *location;
350{
351 int r_ns32k_type = (howto - MY(howto_table)) / 6;
352 long (*get_data) PARAMS ((bfd_byte *, long, long));
353 int (*put_data) PARAMS ((long, bfd_byte *, long, long));
354
355 switch (r_ns32k_type)
356 {
357 case 0:
358 get_data = _bfd_ns32k_get_immediate;
359 put_data = _bfd_ns32k_put_immediate;
360 break;
361 case 1:
362 get_data = _bfd_ns32k_get_displacement;
363 put_data = _bfd_ns32k_put_displacement;
364 break;
365 case 2:
366 return _bfd_relocate_contents (howto, input_bfd, relocation,
367 location);
368 /* NOT REACHED */
369 break;
370 default:
371 return bfd_reloc_notsupported;
372 }
373 return _bfd_do_ns32k_reloc_contents (howto, input_bfd, relocation,
374 location, get_data, put_data);
375}
This page took 0.095384 seconds and 4 git commands to generate.