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