]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/coff-z8k.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / bfd / coff-z8k.c
CommitLineData
252b5132 1/* BFD back-end for Zilog Z800n COFF binaries.
d87bef3a 2 Copyright (C) 1992-2023 Free Software Foundation, Inc.
252b5132
RH
3 Contributed by Cygnus Support.
4 Written by Steve Chamberlain, <sac@cygnus.com>.
5
c0524131 6 This file is part of BFD, the Binary File Descriptor library.
252b5132 7
c0524131
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
cd123cb7 10 the Free Software Foundation; either version 3 of the License, or
c0524131 11 (at your option) any later version.
252b5132 12
c0524131
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
c0524131
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
cd123cb7
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
252b5132 22
252b5132 23#include "sysdep.h"
3db64b00 24#include "bfd.h"
252b5132
RH
25#include "libbfd.h"
26#include "bfdlink.h"
27#include "coff/z8k.h"
28#include "coff/internal.h"
29#include "libcoff.h"
30
31#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
32
33static reloc_howto_type r_imm32 =
c94cb026 34HOWTO (R_IMM32, 0, 4, 32, false, 0,
0a1b45a2
AM
35 complain_overflow_bitfield, 0, "r_imm32", true, 0xffffffff,
36 0xffffffff, false);
252b5132
RH
37
38static reloc_howto_type r_imm4l =
c94cb026 39HOWTO (R_IMM4L, 0, 1, 4, false, 0,
0a1b45a2 40 complain_overflow_bitfield, 0, "r_imm4l", true, 0xf, 0xf, false);
252b5132
RH
41
42static reloc_howto_type r_da =
c94cb026 43HOWTO (R_IMM16, 0, 2, 16, false, 0,
0a1b45a2
AM
44 complain_overflow_bitfield, 0, "r_da", true, 0x0000ffff, 0x0000ffff,
45 false);
252b5132
RH
46
47static reloc_howto_type r_imm8 =
c94cb026 48HOWTO (R_IMM8, 0, 1, 8, false, 0,
0a1b45a2
AM
49 complain_overflow_bitfield, 0, "r_imm8", true, 0x000000ff, 0x000000ff,
50 false);
252b5132 51
6840198f 52static reloc_howto_type r_rel16 =
c94cb026 53HOWTO (R_REL16, 0, 2, 16, false, 0,
0a1b45a2
AM
54 complain_overflow_bitfield, 0, "r_rel16", true, 0x0000ffff, 0x0000ffff,
55 true);
6840198f 56
252b5132 57static reloc_howto_type r_jr =
c94cb026 58HOWTO (R_JR, 1, 1, 8, true, 0, complain_overflow_signed, 0,
0a1b45a2 59 "r_jr", true, 0xff, 0xff, true);
252b5132 60
6840198f 61static reloc_howto_type r_disp7 =
c94cb026 62HOWTO (R_DISP7, 0, 1, 7, true, 0, complain_overflow_bitfield, 0,
0a1b45a2 63 "r_disp7", true, 0x7f, 0x7f, true);
6840198f
NC
64
65static reloc_howto_type r_callr =
c94cb026 66HOWTO (R_CALLR, 1, 2, 12, true, 0, complain_overflow_signed, 0,
0a1b45a2 67 "r_callr", true, 0xfff, 0xfff, true);
6840198f 68
252b5132 69#define BADMAG(x) Z8KBADMAG(x)
c0524131 70#define Z8K 1 /* Customize coffcode.h. */
252b5132
RH
71#define __A_MAGIC_SET__
72
f4ffd778 73/* Code to swap in the reloc. */
dc810e39
AM
74#define SWAP_IN_RELOC_OFFSET H_GET_32
75#define SWAP_OUT_RELOC_OFFSET H_PUT_32
252b5132
RH
76#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
77 dst->r_stuff[0] = 'S'; \
78 dst->r_stuff[1] = 'C';
79
f4ffd778 80/* Code to turn a r_type into a howto ptr, uses the above howto table. */
252b5132
RH
81
82static void
552585ed 83rtype2howto (arelent *internal, struct internal_reloc *dst)
252b5132
RH
84{
85 switch (dst->r_type)
86 {
87 default:
a1165289 88 internal->howto = NULL;
252b5132
RH
89 break;
90 case R_IMM8:
91 internal->howto = &r_imm8;
92 break;
93 case R_IMM16:
94 internal->howto = &r_da;
95 break;
96 case R_JR:
97 internal->howto = &r_jr;
98 break;
6840198f
NC
99 case R_DISP7:
100 internal->howto = &r_disp7;
101 break;
102 case R_CALLR:
103 internal->howto = &r_callr;
104 break;
105 case R_REL16:
106 internal->howto = &r_rel16;
107 break;
252b5132
RH
108 case R_IMM32:
109 internal->howto = &r_imm32;
110 break;
111 case R_IMM4L:
112 internal->howto = &r_imm4l;
113 break;
114 }
115}
116
f4ffd778 117#define RTYPE2HOWTO(internal, relocentry) rtype2howto (internal, relocentry)
252b5132 118
c0524131
NC
119static reloc_howto_type *
120coff_z8k_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
07d6d2b8 121 bfd_reloc_code_real_type code)
c0524131
NC
122{
123 switch (code)
124 {
07d6d2b8
AM
125 case BFD_RELOC_8: return & r_imm8;
126 case BFD_RELOC_16: return & r_da;
127 case BFD_RELOC_32: return & r_imm32;
128 case BFD_RELOC_8_PCREL: return & r_jr;
129 case BFD_RELOC_16_PCREL: return & r_rel16;
130 case BFD_RELOC_Z8K_DISP7: return & r_disp7;
131 case BFD_RELOC_Z8K_CALLR: return & r_callr;
132 case BFD_RELOC_Z8K_IMM4L: return & r_imm4l;
c0524131
NC
133 default: BFD_FAIL ();
134 return 0;
135 }
136}
137
157090f7
AM
138static reloc_howto_type *
139coff_z8k_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
140 const char *r_name)
141{
142 if (strcasecmp (r_imm8.name, r_name) == 0)
143 return &r_imm8;
144 if (strcasecmp (r_da.name, r_name) == 0)
145 return &r_da;
146 if (strcasecmp (r_imm32.name, r_name) == 0)
147 return &r_imm32;
148 if (strcasecmp (r_jr.name, r_name) == 0)
149 return &r_jr;
150 if (strcasecmp (r_rel16.name, r_name) == 0)
151 return &r_rel16;
152 if (strcasecmp (r_disp7.name, r_name) == 0)
153 return &r_disp7;
154 if (strcasecmp (r_callr.name, r_name) == 0)
155 return &r_callr;
156 if (strcasecmp (r_imm4l.name, r_name) == 0)
157 return &r_imm4l;
158
159 return NULL;
160}
161
f4ffd778 162/* Perform any necessary magic to the addend in a reloc entry. */
252b5132 163
252b5132
RH
164#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
165 cache_ptr->addend = ext_reloc.r_offset;
166
252b5132
RH
167#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
168 reloc_processing(relent, reloc, symbols, abfd, section)
169
cbfe05c4 170static void
552585ed 171reloc_processing (arelent *relent,
07d6d2b8
AM
172 struct internal_reloc *reloc,
173 asymbol **symbols,
174 bfd *abfd,
175 asection *section)
252b5132
RH
176{
177 relent->address = reloc->r_vaddr;
178 rtype2howto (relent, reloc);
179
e6b6fad2 180 if (reloc->r_symndx == -1 || symbols == NULL)
e039f7ed
AM
181 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
182 else if (reloc->r_symndx >= 0 && reloc->r_symndx < obj_conv_table_size (abfd))
879db8be 183 relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
252b5132 184 else
e039f7ed
AM
185 {
186 _bfd_error_handler
187 /* xgettext:c-format */
188 (_("%pB: warning: illegal symbol index %ld in relocs"),
189 abfd, reloc->r_symndx);
190 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
191 }
252b5132
RH
192 relent->addend = reloc->r_offset;
193 relent->address -= section->vma;
194}
195
196static void
552585ed 197extra_case (bfd *in_abfd,
07d6d2b8
AM
198 struct bfd_link_info *link_info,
199 struct bfd_link_order *link_order,
200 arelent *reloc,
201 bfd_byte *data,
202 unsigned int *src_ptr,
203 unsigned int *dst_ptr)
252b5132 204{
879db8be 205 asection * input_section = link_order->u.indirect.section;
252b5132
RH
206
207 switch (reloc->howto->type)
208 {
209 case R_IMM8:
210 bfd_put_8 (in_abfd,
211 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
212 data + *dst_ptr);
213 (*dst_ptr) += 1;
214 (*src_ptr) += 1;
215 break;
216
217 case R_IMM32:
3c25c5f6
NC
218 /* If no flags are set, assume immediate value. */
219 if (! (*reloc->sym_ptr_ptr)->section->flags)
220 {
221 bfd_put_32 (in_abfd,
222 bfd_coff_reloc16_get_value (reloc, link_info,
223 input_section),
224 data + *dst_ptr);
225 }
226 else
227 {
228 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
229 input_section);
5c4491d3 230 /* Addresses are 23 bit, and the layout of those in a 32-bit
3c25c5f6
NC
231 value is as follows:
232 1AAAAAAA xxxxxxxx AAAAAAAA AAAAAAAA
233 (A - address bits, x - ignore). */
234 dst = (dst & 0xffff) | ((dst & 0xff0000) << 8) | 0x80000000;
235 bfd_put_32 (in_abfd, dst, data + *dst_ptr);
236 }
252b5132
RH
237 (*dst_ptr) += 4;
238 (*src_ptr) += 4;
239 break;
240
241 case R_IMM4L:
242 bfd_put_8 (in_abfd,
cbfe05c4 243 ((bfd_get_8 (in_abfd, data + *dst_ptr) & 0xf0)
252b5132
RH
244 | (0x0f
245 & bfd_coff_reloc16_get_value (reloc, link_info,
246 input_section))),
247 data + *dst_ptr);
248 (*dst_ptr) += 1;
249 (*src_ptr) += 1;
250 break;
251
252 case R_IMM16:
253 bfd_put_16 (in_abfd,
254 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
255 data + *dst_ptr);
256 (*dst_ptr) += 2;
257 (*src_ptr) += 2;
258 break;
259
260 case R_JR:
261 {
262 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
263 input_section);
44da2da1
AM
264 bfd_vma dot = (*dst_ptr
265 + input_section->output_offset
252b5132 266 + input_section->output_section->vma);
879db8be 267 int gap = dst - dot - 1; /* -1, since we're in the odd byte of the
07d6d2b8 268 word and the pc's been incremented. */
252b5132
RH
269
270 if (gap & 1)
271 abort ();
272 gap /= 2;
2ac27cd3 273 if (gap > 127 || gap < -128)
1a72702b
AM
274 (*link_info->callbacks->reloc_overflow)
275 (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
276 reloc->howto->name, reloc->addend, input_section->owner,
277 input_section, reloc->address);
278
252b5132
RH
279 bfd_put_8 (in_abfd, gap, data + *dst_ptr);
280 (*dst_ptr)++;
281 (*src_ptr)++;
282 break;
283 }
6840198f
NC
284
285 case R_DISP7:
286 {
287 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
288 input_section);
44da2da1
AM
289 bfd_vma dot = (*dst_ptr
290 + input_section->output_offset
6840198f 291 + input_section->output_section->vma);
879db8be 292 int gap = dst - dot - 1; /* -1, since we're in the odd byte of the
07d6d2b8 293 word and the pc's been incremented. */
6840198f
NC
294
295 if (gap & 1)
296 abort ();
297 gap /= 2;
298
8b7cf393 299 if (gap > 0 || gap < -127)
1a72702b
AM
300 (*link_info->callbacks->reloc_overflow)
301 (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
302 reloc->howto->name, reloc->addend, input_section->owner,
303 input_section, reloc->address);
304
6840198f 305 bfd_put_8 (in_abfd,
07d6d2b8
AM
306 (bfd_get_8 ( in_abfd, data + *dst_ptr) & 0x80) + (-gap & 0x7f),
307 data + *dst_ptr);
6840198f
NC
308 (*dst_ptr)++;
309 (*src_ptr)++;
310 break;
311 }
312
313 case R_CALLR:
314 {
315 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
316 input_section);
44da2da1
AM
317 bfd_vma dot = (*dst_ptr
318 + input_section->output_offset
6840198f
NC
319 + input_section->output_section->vma);
320 int gap = dst - dot - 2;
321
322 if (gap & 1)
323 abort ();
8b7cf393 324 if (gap > 4096 || gap < -4095)
1a72702b
AM
325 (*link_info->callbacks->reloc_overflow)
326 (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
327 reloc->howto->name, reloc->addend, input_section->owner,
328 input_section, reloc->address);
329
8b7cf393 330 gap /= 2;
6840198f 331 bfd_put_16 (in_abfd,
07d6d2b8
AM
332 (bfd_get_16 ( in_abfd, data + *dst_ptr) & 0xf000) | (-gap & 0x0fff),
333 data + *dst_ptr);
6840198f
NC
334 (*dst_ptr) += 2;
335 (*src_ptr) += 2;
336 break;
337 }
338
339 case R_REL16:
340 {
341 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
342 input_section);
44da2da1
AM
343 bfd_vma dot = (*dst_ptr
344 + input_section->output_offset
6840198f
NC
345 + input_section->output_section->vma);
346 int gap = dst - dot - 2;
347
348 if (gap > 32767 || gap < -32768)
1a72702b
AM
349 (*link_info->callbacks->reloc_overflow)
350 (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
351 reloc->howto->name, reloc->addend, input_section->owner,
352 input_section, reloc->address);
353
dc810e39 354 bfd_put_16 (in_abfd, (bfd_vma) gap, data + *dst_ptr);
6840198f
NC
355 (*dst_ptr) += 2;
356 (*src_ptr) += 2;
357 break;
358 }
879db8be 359
252b5132
RH
360 default:
361 abort ();
362 }
363}
364
c0524131
NC
365#define coff_reloc16_extra_cases extra_case
366#define coff_bfd_reloc_type_lookup coff_z8k_reloc_type_lookup
157090f7 367#define coff_bfd_reloc_name_lookup coff_z8k_reloc_name_lookup
252b5132 368
2b5c217d
NC
369#ifndef bfd_pe_print_pdata
370#define bfd_pe_print_pdata NULL
371#endif
372
252b5132
RH
373#include "coffcode.h"
374
252b5132 375#undef coff_bfd_get_relocated_section_contents
252b5132
RH
376#define coff_bfd_get_relocated_section_contents \
377 bfd_coff_reloc16_get_relocated_section_contents
c0524131
NC
378
379#undef coff_bfd_relax_section
252b5132
RH
380#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
381
6d00b590 382CREATE_BIG_COFF_TARGET_VEC (z8k_coff_vec, "coff-z8k", 0, 0, '_', NULL, COFF_SWAP_TABLE)