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