daily update
[deliverable/binutils-gdb.git] / bfd / coff-z8k.c
CommitLineData
252b5132 1/* BFD back-end for Zilog Z800n COFF binaries.
4b95cf5c 2 Copyright (C) 1992-2014 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:
88 abort ();
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,
121 bfd_reloc_code_real_type code)
122{
123 switch (code)
124 {
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;
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
CG
171reloc_processing (arelent *relent,
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
CG
190extra_case (bfd *in_abfd,
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
NC
260 int gap = dst - dot - 1; /* -1, since we're in the odd byte of the
261 word and the pc's been incremented. */
252b5132
RH
262
263 if (gap & 1)
264 abort ();
265 gap /= 2;
266 if (gap > 128 || gap < -128)
267 {
268 if (! ((*link_info->callbacks->reloc_overflow)
dfeffb9f
L
269 (link_info, NULL,
270 bfd_asymbol_name (*reloc->sym_ptr_ptr),
252b5132
RH
271 reloc->howto->name, reloc->addend, input_section->owner,
272 input_section, reloc->address)))
273 abort ();
274 }
275 bfd_put_8 (in_abfd, gap, data + *dst_ptr);
276 (*dst_ptr)++;
277 (*src_ptr)++;
278 break;
279 }
6840198f
NC
280
281 case R_DISP7:
282 {
283 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
284 input_section);
44da2da1
AM
285 bfd_vma dot = (*dst_ptr
286 + input_section->output_offset
6840198f 287 + input_section->output_section->vma);
879db8be
NC
288 int gap = dst - dot - 1; /* -1, since we're in the odd byte of the
289 word and the pc's been incremented. */
6840198f
NC
290
291 if (gap & 1)
292 abort ();
293 gap /= 2;
294
8b7cf393 295 if (gap > 0 || gap < -127)
6840198f
NC
296 {
297 if (! ((*link_info->callbacks->reloc_overflow)
dfeffb9f
L
298 (link_info, NULL,
299 bfd_asymbol_name (*reloc->sym_ptr_ptr),
6840198f
NC
300 reloc->howto->name, reloc->addend, input_section->owner,
301 input_section, reloc->address)))
302 abort ();
303 }
304 bfd_put_8 (in_abfd,
305 (bfd_get_8 ( in_abfd, data + *dst_ptr) & 0x80) + (-gap & 0x7f),
306 data + *dst_ptr);
307 (*dst_ptr)++;
308 (*src_ptr)++;
309 break;
310 }
311
312 case R_CALLR:
313 {
314 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
315 input_section);
44da2da1
AM
316 bfd_vma dot = (*dst_ptr
317 + input_section->output_offset
6840198f
NC
318 + input_section->output_section->vma);
319 int gap = dst - dot - 2;
320
321 if (gap & 1)
322 abort ();
8b7cf393 323 if (gap > 4096 || gap < -4095)
6840198f
NC
324 {
325 if (! ((*link_info->callbacks->reloc_overflow)
dfeffb9f
L
326 (link_info, NULL,
327 bfd_asymbol_name (*reloc->sym_ptr_ptr),
6840198f
NC
328 reloc->howto->name, reloc->addend, input_section->owner,
329 input_section, reloc->address)))
330 abort ();
331 }
8b7cf393 332 gap /= 2;
6840198f
NC
333 bfd_put_16 (in_abfd,
334 (bfd_get_16 ( in_abfd, data + *dst_ptr) & 0xf000) | (-gap & 0x0fff),
335 data + *dst_ptr);
336 (*dst_ptr) += 2;
337 (*src_ptr) += 2;
338 break;
339 }
340
341 case R_REL16:
342 {
343 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
344 input_section);
44da2da1
AM
345 bfd_vma dot = (*dst_ptr
346 + input_section->output_offset
6840198f
NC
347 + input_section->output_section->vma);
348 int gap = dst - dot - 2;
349
350 if (gap > 32767 || gap < -32768)
351 {
352 if (! ((*link_info->callbacks->reloc_overflow)
dfeffb9f
L
353 (link_info, NULL,
354 bfd_asymbol_name (*reloc->sym_ptr_ptr),
6840198f
NC
355 reloc->howto->name, reloc->addend, input_section->owner,
356 input_section, reloc->address)))
357 abort ();
358 }
dc810e39 359 bfd_put_16 (in_abfd, (bfd_vma) gap, data + *dst_ptr);
6840198f
NC
360 (*dst_ptr) += 2;
361 (*src_ptr) += 2;
362 break;
363 }
879db8be 364
252b5132
RH
365 default:
366 abort ();
367 }
368}
369
c0524131
NC
370#define coff_reloc16_extra_cases extra_case
371#define coff_bfd_reloc_type_lookup coff_z8k_reloc_type_lookup
157090f7 372#define coff_bfd_reloc_name_lookup coff_z8k_reloc_name_lookup
252b5132 373
2b5c217d
NC
374#ifndef bfd_pe_print_pdata
375#define bfd_pe_print_pdata NULL
376#endif
377
252b5132
RH
378#include "coffcode.h"
379
252b5132 380#undef coff_bfd_get_relocated_section_contents
252b5132
RH
381#define coff_bfd_get_relocated_section_contents \
382 bfd_coff_reloc16_get_relocated_section_contents
c0524131
NC
383
384#undef coff_bfd_relax_section
252b5132
RH
385#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
386
6d00b590 387CREATE_BIG_COFF_TARGET_VEC (z8k_coff_vec, "coff-z8k", 0, 0, '_', NULL, COFF_SWAP_TABLE)
This page took 0.636572 seconds and 4 git commands to generate.