bfd/ChangeLog:
[deliverable/binutils-gdb.git] / bfd / coff-z80.c
CommitLineData
3c9b82ba 1/* BFD back-end for Zilog Z80 COFF binaries.
aa820537 2 Copyright 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
3c9b82ba
NC
3 Contributed by Arnold Metselaar <arnold_m@operamail.com>
4
5 This file is part of BFD, the Binary File Descriptor library.
6
68ffbac6 7 This program is free software; you can redistribute it and/or modify
3c9b82ba 8 it under the terms of the GNU General Public License as published by
cd123cb7 9 the Free Software Foundation; either version 3 of the License, or
3c9b82ba
NC
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
21
3c9b82ba 22#include "sysdep.h"
3db64b00 23#include "bfd.h"
3c9b82ba
NC
24#include "libbfd.h"
25#include "bfdlink.h"
26#include "coff/z80.h"
27#include "coff/internal.h"
28#include "libcoff.h"
29
30#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 0
31
32static reloc_howto_type r_imm32 =
96d4e9de 33HOWTO (R_IMM32, 0, 2, 32, FALSE, 0,
3c9b82ba
NC
34 complain_overflow_dont, 0, "r_imm32", TRUE, 0xffffffff, 0xffffffff,
35 FALSE);
36
134dcee5
AM
37static reloc_howto_type r_imm24 =
38HOWTO (R_IMM24, 0, 1, 24, FALSE, 0,
39 complain_overflow_dont, 0, "r_imm24", TRUE, 0x00ffffff, 0x00ffffff,
40 FALSE);
41
3c9b82ba
NC
42static reloc_howto_type r_imm16 =
43HOWTO (R_IMM16, 0, 1, 16, FALSE, 0,
44 complain_overflow_dont, 0, "r_imm16", TRUE, 0x0000ffff, 0x0000ffff,
45 FALSE);
46
47static reloc_howto_type r_imm8 =
48HOWTO (R_IMM8, 0, 0, 8, FALSE, 0,
49 complain_overflow_bitfield, 0, "r_imm8", TRUE, 0x000000ff, 0x000000ff,
50 FALSE);
51
52static reloc_howto_type r_jr =
68ffbac6 53HOWTO (R_JR, 0, 0, 8, TRUE, 0,
3c9b82ba
NC
54 complain_overflow_signed, 0, "r_jr", FALSE, 0, 0xFF,
55 FALSE);
56
57static reloc_howto_type r_off8 =
68ffbac6 58HOWTO (R_OFF8, 0, 0, 8, FALSE, 0,
3c9b82ba
NC
59 complain_overflow_signed, 0,"r_off8", FALSE, 0, 0xff,
60 FALSE);
61
62
63#define BADMAG(x) Z80BADMAG(x)
64#define Z80 1 /* Customize coffcode.h. */
65#define __A_MAGIC_SET__
66
67/* Code to swap in the reloc. */
68
69#define SWAP_IN_RELOC_OFFSET H_GET_32
70#define SWAP_OUT_RELOC_OFFSET H_PUT_32
71
72#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
73 dst->r_stuff[0] = 'S'; \
74 dst->r_stuff[1] = 'C';
75
76/* Code to turn a r_type into a howto ptr, uses the above howto table. */
77
78static void
79rtype2howto (arelent *internal, struct internal_reloc *dst)
80{
81 switch (dst->r_type)
82 {
83 default:
84 abort ();
85 break;
86 case R_IMM8:
87 internal->howto = &r_imm8;
88 break;
89 case R_IMM16:
90 internal->howto = &r_imm16;
91 break;
134dcee5
AM
92 case R_IMM24:
93 internal->howto = &r_imm24;
94 break;
3c9b82ba
NC
95 case R_IMM32:
96 internal->howto = &r_imm32;
97 break;
98 case R_JR:
99 internal->howto = &r_jr;
100 break;
101 case R_OFF8:
102 internal->howto = &r_off8;
103 break;
104 }
105}
106
107#define RTYPE2HOWTO(internal, relocentry) rtype2howto (internal, relocentry)
108
109static reloc_howto_type *
110coff_z80_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
111 bfd_reloc_code_real_type code)
112{
113 switch (code)
114 {
115 case BFD_RELOC_8: return & r_imm8;
116 case BFD_RELOC_16: return & r_imm16;
134dcee5 117 case BFD_RELOC_24: return & r_imm24;
3c9b82ba
NC
118 case BFD_RELOC_32: return & r_imm32;
119 case BFD_RELOC_8_PCREL: return & r_jr;
120 case BFD_RELOC_Z80_DISP8: return & r_off8;
121 default: BFD_FAIL ();
122 return NULL;
123 }
124}
125
157090f7
AM
126static reloc_howto_type *
127coff_z80_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
128 const char *r_name)
129{
130 if (strcasecmp (r_imm8.name, r_name) == 0)
131 return &r_imm8;
132 if (strcasecmp (r_imm16.name, r_name) == 0)
133 return &r_imm16;
134 if (strcasecmp (r_imm24.name, r_name) == 0)
135 return &r_imm24;
136 if (strcasecmp (r_imm32.name, r_name) == 0)
137 return &r_imm32;
138 if (strcasecmp (r_jr.name, r_name) == 0)
139 return &r_jr;
140 if (strcasecmp (r_off8.name, r_name) == 0)
141 return &r_off8;
142
143 return NULL;
144}
145
3c9b82ba
NC
146/* Perform any necessary magic to the addend in a reloc entry. */
147
148#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
149 cache_ptr->addend = ext_reloc.r_offset;
150
151#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
152 reloc_processing(relent, reloc, symbols, abfd, section)
153
154static void
155reloc_processing (arelent *relent,
156 struct internal_reloc *reloc,
157 asymbol **symbols,
158 bfd *abfd,
159 asection *section)
160{
161 relent->address = reloc->r_vaddr;
162 rtype2howto (relent, reloc);
163
164 if (reloc->r_symndx > 0)
165 relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
166 else
167 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
168
169 relent->addend = reloc->r_offset;
170 relent->address -= section->vma;
171}
172
173static void
174extra_case (bfd *in_abfd,
175 struct bfd_link_info *link_info,
176 struct bfd_link_order *link_order,
177 arelent *reloc,
178 bfd_byte *data,
179 unsigned int *src_ptr,
180 unsigned int *dst_ptr)
181{
182 asection * input_section = link_order->u.indirect.section;
183 int val;
184
185 switch (reloc->howto->type)
186 {
187 case R_OFF8:
188 val = bfd_coff_reloc16_get_value (reloc, link_info,
189 input_section);
190 if (val>127 || val<-128) /* Test for overflow. */
191 {
192 if (! ((*link_info->callbacks->reloc_overflow)
193 (link_info, NULL,
194 bfd_asymbol_name (*reloc->sym_ptr_ptr),
195 reloc->howto->name, reloc->addend, input_section->owner,
196 input_section, reloc->address)))
197 abort ();
198 }
199 bfd_put_8 (in_abfd, val, data + *dst_ptr);
200 (*dst_ptr) += 1;
201 (*src_ptr) += 1;
202 break;
203
204 case R_IMM8:
134dcee5 205 val = bfd_get_8 ( in_abfd, data+*src_ptr)
3c9b82ba
NC
206 + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
207 bfd_put_8 (in_abfd, val, data + *dst_ptr);
208 (*dst_ptr) += 1;
209 (*src_ptr) += 1;
210 break;
211
212 case R_IMM16:
213 val = bfd_get_16 ( in_abfd, data+*src_ptr)
214 + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
215 bfd_put_16 (in_abfd, val, data + *dst_ptr);
216 (*dst_ptr) += 2;
217 (*src_ptr) += 2;
218 break;
219
134dcee5
AM
220 case R_IMM24:
221 val = bfd_get_16 ( in_abfd, data+*src_ptr)
222 + (bfd_get_8 ( in_abfd, data+*src_ptr+2) << 16)
223 + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
224 bfd_put_16 (in_abfd, val, data + *dst_ptr);
225 bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr+2);
226 (*dst_ptr) += 3;
227 (*src_ptr) += 3;
228 break;
229
3c9b82ba
NC
230 case R_IMM32:
231 val = bfd_get_32 ( in_abfd, data+*src_ptr)
232 + bfd_coff_reloc16_get_value (reloc, link_info, input_section);
233 bfd_put_32 (in_abfd, val, data + *dst_ptr);
234 (*dst_ptr) += 4;
235 (*src_ptr) += 4;
236 break;
237
238 case R_JR:
239 {
240 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
241 input_section);
44da2da1
AM
242 bfd_vma dot = (*dst_ptr
243 + input_section->output_offset
3c9b82ba
NC
244 + input_section->output_section->vma);
245 int gap = dst - dot - 1; /* -1, Since the offset is relative
246 to the value of PC after reading
247 the offset. */
248
249 if (gap >= 128 || gap < -128)
250 {
251 if (! ((*link_info->callbacks->reloc_overflow)
252 (link_info, NULL,
253 bfd_asymbol_name (*reloc->sym_ptr_ptr),
254 reloc->howto->name, reloc->addend, input_section->owner,
255 input_section, reloc->address)))
256 abort ();
257 }
258 bfd_put_8 (in_abfd, gap, data + *dst_ptr);
259 (*dst_ptr)++;
260 (*src_ptr)++;
261 break;
262 }
263
264 default:
265 abort ();
266 }
267}
268
269#define coff_reloc16_extra_cases extra_case
270#define coff_bfd_reloc_type_lookup coff_z80_reloc_type_lookup
157090f7 271#define coff_bfd_reloc_name_lookup coff_z80_reloc_name_lookup
3c9b82ba 272
2b5c217d
NC
273#ifndef bfd_pe_print_pdata
274#define bfd_pe_print_pdata NULL
275#endif
276
3c9b82ba
NC
277#include "coffcode.h"
278
279#undef coff_bfd_get_relocated_section_contents
280#define coff_bfd_get_relocated_section_contents \
281 bfd_coff_reloc16_get_relocated_section_contents
282
283#undef coff_bfd_relax_section
284#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
285
6c293e26 286CREATE_LITTLE_COFF_TARGET_VEC (z80coff_vec, "coff-z80", 0,
68ffbac6 287 SEC_CODE | SEC_DATA, '\0', NULL,
3c9b82ba
NC
288 COFF_SWAP_TABLE)
289
This page took 0.379309 seconds and 4 git commands to generate.