]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/coff-z8k.c
[PATCH] fix windmc typedef bug
[thirdparty/binutils-gdb.git] / bfd / coff-z8k.c
CommitLineData
252b5132 1/* BFD back-end for Zilog Z800n COFF binaries.
b3adc24a 2 Copyright (C) 1992-2020 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 =
b34976b6
AM
34HOWTO (R_IMM32, 0, 2, 32, FALSE, 0,
35 complain_overflow_bitfield, 0, "r_imm32", TRUE, 0xffffffff,
36 0xffffffff, FALSE);
252b5132
RH
37
38static reloc_howto_type r_imm4l =
b34976b6
AM
39HOWTO (R_IMM4L, 0, 0, 4, FALSE, 0,
40 complain_overflow_bitfield, 0, "r_imm4l", TRUE, 0xf, 0xf, FALSE);
252b5132
RH
41
42static reloc_howto_type r_da =
b34976b6
AM
43HOWTO (R_IMM16, 0, 1, 16, FALSE, 0,
44 complain_overflow_bitfield, 0, "r_da", TRUE, 0x0000ffff, 0x0000ffff,
45 FALSE);
252b5132
RH
46
47static reloc_howto_type r_imm8 =
b34976b6
AM
48HOWTO (R_IMM8, 0, 0, 8, FALSE, 0,
49 complain_overflow_bitfield, 0, "r_imm8", TRUE, 0x000000ff, 0x000000ff,
50 FALSE);
252b5132 51
6840198f 52static reloc_howto_type r_rel16 =
b34976b6
AM
53HOWTO (R_REL16, 0, 1, 16, FALSE, 0,
54 complain_overflow_bitfield, 0, "r_rel16", TRUE, 0x0000ffff, 0x0000ffff,
55 TRUE);
6840198f 56
252b5132 57static reloc_howto_type r_jr =
c0524131
NC
58HOWTO (R_JR, 1, 0, 8, TRUE, 0, complain_overflow_signed, 0,
59 "r_jr", TRUE, 0xff, 0xff, TRUE);
252b5132 60
6840198f 61static reloc_howto_type r_disp7 =
b34976b6 62HOWTO (R_DISP7, 0, 0, 7, TRUE, 0, complain_overflow_bitfield, 0,
c0524131 63 "r_disp7", TRUE, 0x7f, 0x7f, TRUE);
6840198f
NC
64
65static reloc_howto_type r_callr =
c0524131 66HOWTO (R_CALLR, 1, 1, 12, TRUE, 0, complain_overflow_signed, 0,
b34976b6 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
180 if (reloc->r_symndx > 0)
879db8be 181 relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
252b5132 182 else
879db8be 183 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
252b5132 184
252b5132
RH
185 relent->addend = reloc->r_offset;
186 relent->address -= section->vma;
187}
188
189static void
552585ed 190extra_case (bfd *in_abfd,
07d6d2b8
AM
191 struct bfd_link_info *link_info,
192 struct bfd_link_order *link_order,
193 arelent *reloc,
194 bfd_byte *data,
195 unsigned int *src_ptr,
196 unsigned int *dst_ptr)
252b5132 197{
879db8be 198 asection * input_section = link_order->u.indirect.section;
252b5132
RH
199
200 switch (reloc->howto->type)
201 {
202 case R_IMM8:
203 bfd_put_8 (in_abfd,
204 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
205 data + *dst_ptr);
206 (*dst_ptr) += 1;
207 (*src_ptr) += 1;
208 break;
209
210 case R_IMM32:
3c25c5f6
NC
211 /* If no flags are set, assume immediate value. */
212 if (! (*reloc->sym_ptr_ptr)->section->flags)
213 {
214 bfd_put_32 (in_abfd,
215 bfd_coff_reloc16_get_value (reloc, link_info,
216 input_section),
217 data + *dst_ptr);
218 }
219 else
220 {
221 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
222 input_section);
5c4491d3 223 /* Addresses are 23 bit, and the layout of those in a 32-bit
3c25c5f6
NC
224 value is as follows:
225 1AAAAAAA xxxxxxxx AAAAAAAA AAAAAAAA
226 (A - address bits, x - ignore). */
227 dst = (dst & 0xffff) | ((dst & 0xff0000) << 8) | 0x80000000;
228 bfd_put_32 (in_abfd, dst, data + *dst_ptr);
229 }
252b5132
RH
230 (*dst_ptr) += 4;
231 (*src_ptr) += 4;
232 break;
233
234 case R_IMM4L:
235 bfd_put_8 (in_abfd,
cbfe05c4 236 ((bfd_get_8 (in_abfd, data + *dst_ptr) & 0xf0)
252b5132
RH
237 | (0x0f
238 & bfd_coff_reloc16_get_value (reloc, link_info,
239 input_section))),
240 data + *dst_ptr);
241 (*dst_ptr) += 1;
242 (*src_ptr) += 1;
243 break;
244
245 case R_IMM16:
246 bfd_put_16 (in_abfd,
247 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
248 data + *dst_ptr);
249 (*dst_ptr) += 2;
250 (*src_ptr) += 2;
251 break;
252
253 case R_JR:
254 {
255 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
256 input_section);
44da2da1
AM
257 bfd_vma dot = (*dst_ptr
258 + input_section->output_offset
252b5132 259 + input_section->output_section->vma);
879db8be 260 int gap = dst - dot - 1; /* -1, since we're in the odd byte of the
07d6d2b8 261 word and the pc's been incremented. */
252b5132
RH
262
263 if (gap & 1)
264 abort ();
265 gap /= 2;
2ac27cd3 266 if (gap > 127 || gap < -128)
1a72702b
AM
267 (*link_info->callbacks->reloc_overflow)
268 (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
269 reloc->howto->name, reloc->addend, input_section->owner,
270 input_section, reloc->address);
271
252b5132
RH
272 bfd_put_8 (in_abfd, gap, data + *dst_ptr);
273 (*dst_ptr)++;
274 (*src_ptr)++;
275 break;
276 }
6840198f
NC
277
278 case R_DISP7:
279 {
280 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
281 input_section);
44da2da1
AM
282 bfd_vma dot = (*dst_ptr
283 + input_section->output_offset
6840198f 284 + input_section->output_section->vma);
879db8be 285 int gap = dst - dot - 1; /* -1, since we're in the odd byte of the
07d6d2b8 286 word and the pc's been incremented. */
6840198f
NC
287
288 if (gap & 1)
289 abort ();
290 gap /= 2;
291
8b7cf393 292 if (gap > 0 || gap < -127)
1a72702b
AM
293 (*link_info->callbacks->reloc_overflow)
294 (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
295 reloc->howto->name, reloc->addend, input_section->owner,
296 input_section, reloc->address);
297
6840198f 298 bfd_put_8 (in_abfd,
07d6d2b8
AM
299 (bfd_get_8 ( in_abfd, data + *dst_ptr) & 0x80) + (-gap & 0x7f),
300 data + *dst_ptr);
6840198f
NC
301 (*dst_ptr)++;
302 (*src_ptr)++;
303 break;
304 }
305
306 case R_CALLR:
307 {
308 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
309 input_section);
44da2da1
AM
310 bfd_vma dot = (*dst_ptr
311 + input_section->output_offset
6840198f
NC
312 + input_section->output_section->vma);
313 int gap = dst - dot - 2;
314
315 if (gap & 1)
316 abort ();
8b7cf393 317 if (gap > 4096 || gap < -4095)
1a72702b
AM
318 (*link_info->callbacks->reloc_overflow)
319 (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
320 reloc->howto->name, reloc->addend, input_section->owner,
321 input_section, reloc->address);
322
8b7cf393 323 gap /= 2;
6840198f 324 bfd_put_16 (in_abfd,
07d6d2b8
AM
325 (bfd_get_16 ( in_abfd, data + *dst_ptr) & 0xf000) | (-gap & 0x0fff),
326 data + *dst_ptr);
6840198f
NC
327 (*dst_ptr) += 2;
328 (*src_ptr) += 2;
329 break;
330 }
331
332 case R_REL16:
333 {
334 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
335 input_section);
44da2da1
AM
336 bfd_vma dot = (*dst_ptr
337 + input_section->output_offset
6840198f
NC
338 + input_section->output_section->vma);
339 int gap = dst - dot - 2;
340
341 if (gap > 32767 || gap < -32768)
1a72702b
AM
342 (*link_info->callbacks->reloc_overflow)
343 (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
344 reloc->howto->name, reloc->addend, input_section->owner,
345 input_section, reloc->address);
346
dc810e39 347 bfd_put_16 (in_abfd, (bfd_vma) gap, data + *dst_ptr);
6840198f
NC
348 (*dst_ptr) += 2;
349 (*src_ptr) += 2;
350 break;
351 }
879db8be 352
252b5132
RH
353 default:
354 abort ();
355 }
356}
357
c0524131
NC
358#define coff_reloc16_extra_cases extra_case
359#define coff_bfd_reloc_type_lookup coff_z8k_reloc_type_lookup
157090f7 360#define coff_bfd_reloc_name_lookup coff_z8k_reloc_name_lookup
252b5132 361
2b5c217d
NC
362#ifndef bfd_pe_print_pdata
363#define bfd_pe_print_pdata NULL
364#endif
365
252b5132
RH
366#include "coffcode.h"
367
252b5132 368#undef coff_bfd_get_relocated_section_contents
252b5132
RH
369#define coff_bfd_get_relocated_section_contents \
370 bfd_coff_reloc16_get_relocated_section_contents
c0524131
NC
371
372#undef coff_bfd_relax_section
252b5132
RH
373#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
374
6d00b590 375CREATE_BIG_COFF_TARGET_VEC (z8k_coff_vec, "coff-z8k", 0, 0, '_', NULL, COFF_SWAP_TABLE)