]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/coff-z8k.c
* Makefile.am (Makefile): Remove dependency.
[thirdparty/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,
c0524131 3 2004, 2005 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
11 the Free Software Foundation; either version 2 of the License, or
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
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
252b5132
RH
22
23#include "bfd.h"
24#include "sysdep.h"
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
f4ffd778 138/* Perform any necessary magic to the addend in a reloc entry. */
252b5132 139
252b5132
RH
140#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
141 cache_ptr->addend = ext_reloc.r_offset;
142
252b5132
RH
143#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
144 reloc_processing(relent, reloc, symbols, abfd, section)
145
cbfe05c4 146static void
552585ed
CG
147reloc_processing (arelent *relent,
148 struct internal_reloc *reloc,
149 asymbol **symbols,
150 bfd *abfd,
151 asection *section)
252b5132
RH
152{
153 relent->address = reloc->r_vaddr;
154 rtype2howto (relent, reloc);
155
156 if (reloc->r_symndx > 0)
879db8be 157 relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
252b5132 158 else
879db8be 159 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
252b5132 160
252b5132
RH
161 relent->addend = reloc->r_offset;
162 relent->address -= section->vma;
163}
164
165static void
552585ed
CG
166extra_case (bfd *in_abfd,
167 struct bfd_link_info *link_info,
168 struct bfd_link_order *link_order,
169 arelent *reloc,
170 bfd_byte *data,
171 unsigned int *src_ptr,
172 unsigned int *dst_ptr)
252b5132 173{
879db8be 174 asection * input_section = link_order->u.indirect.section;
252b5132
RH
175
176 switch (reloc->howto->type)
177 {
178 case R_IMM8:
179 bfd_put_8 (in_abfd,
180 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
181 data + *dst_ptr);
182 (*dst_ptr) += 1;
183 (*src_ptr) += 1;
184 break;
185
186 case R_IMM32:
3c25c5f6
NC
187 /* If no flags are set, assume immediate value. */
188 if (! (*reloc->sym_ptr_ptr)->section->flags)
189 {
190 bfd_put_32 (in_abfd,
191 bfd_coff_reloc16_get_value (reloc, link_info,
192 input_section),
193 data + *dst_ptr);
194 }
195 else
196 {
197 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
198 input_section);
5c4491d3 199 /* Addresses are 23 bit, and the layout of those in a 32-bit
3c25c5f6
NC
200 value is as follows:
201 1AAAAAAA xxxxxxxx AAAAAAAA AAAAAAAA
202 (A - address bits, x - ignore). */
203 dst = (dst & 0xffff) | ((dst & 0xff0000) << 8) | 0x80000000;
204 bfd_put_32 (in_abfd, dst, data + *dst_ptr);
205 }
252b5132
RH
206 (*dst_ptr) += 4;
207 (*src_ptr) += 4;
208 break;
209
210 case R_IMM4L:
211 bfd_put_8 (in_abfd,
cbfe05c4 212 ((bfd_get_8 (in_abfd, data + *dst_ptr) & 0xf0)
252b5132
RH
213 | (0x0f
214 & bfd_coff_reloc16_get_value (reloc, link_info,
215 input_section))),
216 data + *dst_ptr);
217 (*dst_ptr) += 1;
218 (*src_ptr) += 1;
219 break;
220
221 case R_IMM16:
222 bfd_put_16 (in_abfd,
223 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
224 data + *dst_ptr);
225 (*dst_ptr) += 2;
226 (*src_ptr) += 2;
227 break;
228
229 case R_JR:
230 {
231 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
232 input_section);
233 bfd_vma dot = (link_order->offset
234 + *dst_ptr
235 + input_section->output_section->vma);
879db8be
NC
236 int gap = dst - dot - 1; /* -1, since we're in the odd byte of the
237 word and the pc's been incremented. */
252b5132
RH
238
239 if (gap & 1)
240 abort ();
241 gap /= 2;
242 if (gap > 128 || gap < -128)
243 {
244 if (! ((*link_info->callbacks->reloc_overflow)
dfeffb9f
L
245 (link_info, NULL,
246 bfd_asymbol_name (*reloc->sym_ptr_ptr),
252b5132
RH
247 reloc->howto->name, reloc->addend, input_section->owner,
248 input_section, reloc->address)))
249 abort ();
250 }
251 bfd_put_8 (in_abfd, gap, data + *dst_ptr);
252 (*dst_ptr)++;
253 (*src_ptr)++;
254 break;
255 }
6840198f
NC
256
257 case R_DISP7:
258 {
259 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
260 input_section);
261 bfd_vma dot = (link_order->offset
262 + *dst_ptr
263 + input_section->output_section->vma);
879db8be
NC
264 int gap = dst - dot - 1; /* -1, since we're in the odd byte of the
265 word and the pc's been incremented. */
6840198f
NC
266
267 if (gap & 1)
268 abort ();
269 gap /= 2;
270
8b7cf393 271 if (gap > 0 || gap < -127)
6840198f
NC
272 {
273 if (! ((*link_info->callbacks->reloc_overflow)
dfeffb9f
L
274 (link_info, NULL,
275 bfd_asymbol_name (*reloc->sym_ptr_ptr),
6840198f
NC
276 reloc->howto->name, reloc->addend, input_section->owner,
277 input_section, reloc->address)))
278 abort ();
279 }
280 bfd_put_8 (in_abfd,
281 (bfd_get_8 ( in_abfd, data + *dst_ptr) & 0x80) + (-gap & 0x7f),
282 data + *dst_ptr);
283 (*dst_ptr)++;
284 (*src_ptr)++;
285 break;
286 }
287
288 case R_CALLR:
289 {
290 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
291 input_section);
292 bfd_vma dot = (link_order->offset
293 + *dst_ptr
294 + input_section->output_section->vma);
295 int gap = dst - dot - 2;
296
297 if (gap & 1)
298 abort ();
8b7cf393 299 if (gap > 4096 || gap < -4095)
6840198f
NC
300 {
301 if (! ((*link_info->callbacks->reloc_overflow)
dfeffb9f
L
302 (link_info, NULL,
303 bfd_asymbol_name (*reloc->sym_ptr_ptr),
6840198f
NC
304 reloc->howto->name, reloc->addend, input_section->owner,
305 input_section, reloc->address)))
306 abort ();
307 }
8b7cf393 308 gap /= 2;
6840198f
NC
309 bfd_put_16 (in_abfd,
310 (bfd_get_16 ( in_abfd, data + *dst_ptr) & 0xf000) | (-gap & 0x0fff),
311 data + *dst_ptr);
312 (*dst_ptr) += 2;
313 (*src_ptr) += 2;
314 break;
315 }
316
317 case R_REL16:
318 {
319 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
320 input_section);
321 bfd_vma dot = (link_order->offset
322 + *dst_ptr
323 + input_section->output_section->vma);
324 int gap = dst - dot - 2;
325
326 if (gap > 32767 || gap < -32768)
327 {
328 if (! ((*link_info->callbacks->reloc_overflow)
dfeffb9f
L
329 (link_info, NULL,
330 bfd_asymbol_name (*reloc->sym_ptr_ptr),
6840198f
NC
331 reloc->howto->name, reloc->addend, input_section->owner,
332 input_section, reloc->address)))
333 abort ();
334 }
dc810e39 335 bfd_put_16 (in_abfd, (bfd_vma) gap, data + *dst_ptr);
6840198f
NC
336 (*dst_ptr) += 2;
337 (*src_ptr) += 2;
338 break;
339 }
879db8be 340
252b5132
RH
341 default:
342 abort ();
343 }
344}
345
c0524131
NC
346#define coff_reloc16_extra_cases extra_case
347#define coff_bfd_reloc_type_lookup coff_z8k_reloc_type_lookup
252b5132
RH
348
349#include "coffcode.h"
350
252b5132 351#undef coff_bfd_get_relocated_section_contents
252b5132
RH
352#define coff_bfd_get_relocated_section_contents \
353 bfd_coff_reloc16_get_relocated_section_contents
c0524131
NC
354
355#undef coff_bfd_relax_section
252b5132
RH
356#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
357
3fa78519 358CREATE_BIG_COFF_TARGET_VEC (z8kcoff_vec, "coff-z8k", 0, 0, '_', NULL, COFF_SWAP_TABLE)