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