bfd/
[deliverable/binutils-gdb.git] / bfd / coff-h8500.c
CommitLineData
c2dcd04e 1/* BFD back-end for Renesas H8/500 COFF binaries.
3db64b00
AM
2 Copyright 1993, 1994, 1995, 1997, 1999, 2000, 2001, 2002, 2003, 2004,
3 2005, 2007 Free Software Foundation, Inc.
252b5132
RH
4 Contributed by Cygnus Support.
5 Written by Steve Chamberlain, <sac@cygnus.com>.
6
c2dcd04e 7 This file is part of BFD, the Binary File Descriptor library.
252b5132 8
c2dcd04e
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
c2dcd04e
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
c2dcd04e
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
3e110533 21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 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/h8500.h"
28#include "coff/internal.h"
29#include "libcoff.h"
30
f4ffd778
NC
31static int coff_h8500_select_reloc PARAMS ((reloc_howto_type *));
32static void rtype2howto PARAMS ((arelent *, struct internal_reloc *));
33static void reloc_processing PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection *));
34static void extra_case PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *, arelent *, bfd_byte *, unsigned int *, unsigned int *));
35
252b5132
RH
36#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
37
38static reloc_howto_type r_imm8 =
b34976b6
AM
39HOWTO (R_H8500_IMM8, 0, 1, 8, FALSE, 0,
40 complain_overflow_bitfield, 0, "r_imm8", TRUE, 0x000000ff, 0x000000ff, FALSE);
252b5132
RH
41
42static reloc_howto_type r_imm16 =
b34976b6
AM
43HOWTO (R_H8500_IMM16, 0, 1, 16, FALSE, 0,
44 complain_overflow_bitfield, 0, "r_imm16", TRUE, 0x0000ffff, 0x0000ffff, FALSE);
252b5132
RH
45
46static reloc_howto_type r_imm24 =
b34976b6
AM
47HOWTO (R_H8500_IMM24, 0, 1, 24, FALSE, 0,
48 complain_overflow_bitfield, 0, "r_imm24", TRUE, 0x00ffffff, 0x00ffffff, FALSE);
252b5132
RH
49
50static reloc_howto_type r_imm32 =
b34976b6
AM
51HOWTO (R_H8500_IMM32, 0, 1, 32, FALSE, 0,
52 complain_overflow_bitfield, 0, "r_imm32", TRUE, 0xffffffff, 0xffffffff, FALSE);
252b5132 53
252b5132 54static reloc_howto_type r_high8 =
b34976b6
AM
55HOWTO (R_H8500_HIGH8, 0, 1, 8, FALSE, 0,
56 complain_overflow_dont, 0, "r_high8", TRUE, 0x000000ff, 0x000000ff, FALSE);
252b5132
RH
57
58static reloc_howto_type r_low16 =
b34976b6
AM
59HOWTO (R_H8500_LOW16, 0, 1, 16, FALSE, 0,
60 complain_overflow_dont, 0, "r_low16", TRUE, 0x0000ffff, 0x0000ffff, FALSE);
252b5132
RH
61
62static reloc_howto_type r_pcrel8 =
b34976b6 63HOWTO (R_H8500_PCREL8, 0, 1, 8, TRUE, 0, complain_overflow_signed, 0, "r_pcrel8", TRUE, 0, 0, TRUE);
252b5132 64
252b5132 65static reloc_howto_type r_pcrel16 =
b34976b6 66HOWTO (R_H8500_PCREL16, 0, 1, 16, TRUE, 0, complain_overflow_signed, 0, "r_pcrel16", TRUE, 0, 0, TRUE);
252b5132
RH
67
68static reloc_howto_type r_high16 =
b34976b6
AM
69HOWTO (R_H8500_HIGH16, 0, 1, 8, FALSE, 0,
70 complain_overflow_dont, 0, "r_high16", TRUE, 0x000ffff, 0x0000ffff, FALSE);
f4ffd778
NC
71\f
72/* Turn a howto into a reloc number. */
252b5132 73
5fcfd273 74static int
252b5132
RH
75coff_h8500_select_reloc (howto)
76 reloc_howto_type *howto;
77{
78 return howto->type;
79}
80
81#define SELECT_RELOC(x,howto) x.r_type = coff_h8500_select_reloc(howto)
82
252b5132
RH
83#define BADMAG(x) H8500BADMAG(x)
84#define H8500 1 /* Customize coffcode.h */
85
86#define __A_MAGIC_SET__
87
f4ffd778 88/* Code to swap in the reloc. */
dc810e39
AM
89#define SWAP_IN_RELOC_OFFSET H_GET_32
90#define SWAP_OUT_RELOC_OFFSET H_PUT_32
252b5132
RH
91#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
92 dst->r_stuff[0] = 'S'; \
93 dst->r_stuff[1] = 'C';
94
f4ffd778 95/* Code to turn a r_type into a howto ptr, uses the above howto table. */
252b5132
RH
96
97static void
f4ffd778 98rtype2howto (internal, dst)
252b5132
RH
99 arelent * internal;
100 struct internal_reloc *dst;
101{
102 switch (dst->r_type)
103 {
104 default:
105 abort ();
106 break;
107 case R_H8500_IMM8:
108 internal->howto = &r_imm8;
109 break;
110 case R_H8500_IMM16:
111 internal->howto = &r_imm16;
112 break;
113 case R_H8500_IMM24:
114 internal->howto = &r_imm24;
115 break;
116 case R_H8500_IMM32:
117 internal->howto = &r_imm32;
118 break;
119 case R_H8500_PCREL8:
120 internal->howto = &r_pcrel8;
121 break;
122 case R_H8500_PCREL16:
123 internal->howto = &r_pcrel16;
124 break;
125 case R_H8500_HIGH8:
126 internal->howto = &r_high8;
127 break;
128 case R_H8500_HIGH16:
129 internal->howto = &r_high16;
130 break;
131 case R_H8500_LOW16:
132 internal->howto = &r_low16;
133 break;
134 }
135}
136
137#define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
138
f4ffd778 139/* Perform any necessary magic to the addend in a reloc entry. */
252b5132 140
252b5132
RH
141#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
142 cache_ptr->addend = ext_reloc.r_offset;
143
252b5132
RH
144#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
145 reloc_processing(relent, reloc, symbols, abfd, section)
146
147static void reloc_processing (relent, reloc, symbols, abfd, section)
148 arelent * relent;
149 struct internal_reloc *reloc;
150 asymbol ** symbols;
151 bfd * abfd;
152 asection * section;
153{
154 relent->address = reloc->r_vaddr;
155 rtype2howto (relent, reloc);
156
157 if (reloc->r_symndx > 0)
f4ffd778 158 relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
252b5132 159 else
f4ffd778 160 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
252b5132 161
252b5132
RH
162 relent->addend = reloc->r_offset;
163 relent->address -= section->vma;
164}
165
166static void
167extra_case (in_abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)
168 bfd *in_abfd;
169 struct bfd_link_info *link_info;
170 struct bfd_link_order *link_order;
171 arelent *reloc;
172 bfd_byte *data;
173 unsigned int *src_ptr;
174 unsigned int *dst_ptr;
175{
176 bfd_byte *d = data+*dst_ptr;
177 asection *input_section = link_order->u.indirect.section;
f4ffd778 178
252b5132
RH
179 switch (reloc->howto->type)
180 {
181 case R_H8500_IMM8:
182 bfd_put_8 (in_abfd,
183 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
184 d);
185 (*dst_ptr) += 1;
186 (*src_ptr) += 1;
187 break;
188
189 case R_H8500_HIGH8:
190 bfd_put_8 (in_abfd,
191 (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
192 >> 16),
f4ffd778 193 d);
252b5132
RH
194 (*dst_ptr) += 1;
195 (*src_ptr) += 1;
196 break;
197
198 case R_H8500_IMM16:
199 bfd_put_16 (in_abfd,
200 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
f4ffd778 201 d);
252b5132
RH
202 (*dst_ptr) += 2;
203 (*src_ptr) += 2;
204 break;
205
206 case R_H8500_LOW16:
207 bfd_put_16 (in_abfd,
208 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
209 d);
210
211 (*dst_ptr) += 2;
212 (*src_ptr) += 2;
213 break;
5fcfd273 214
252b5132
RH
215 case R_H8500_HIGH16:
216 bfd_put_16 (in_abfd,
217 (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
f4ffd778 218 >> 16),
252b5132
RH
219 d);
220
221 (*dst_ptr) += 2;
222 (*src_ptr) += 2;
223 break;
224
225 case R_H8500_IMM24:
226 {
f4ffd778 227 int v = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
6e301b2b 228 int o = bfd_get_32 (in_abfd, data+ *dst_ptr -1);
252b5132 229 v = (v & 0x00ffffff) | (o & 0xff00000);
dc810e39 230 bfd_put_32 (in_abfd, (bfd_vma) v, data + *dst_ptr -1);
f4ffd778
NC
231 (*dst_ptr) += 3;
232 (*src_ptr) += 3;;
252b5132
RH
233 }
234 break;
235 case R_H8500_IMM32:
236 {
f4ffd778 237 int v = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
dc810e39 238 bfd_put_32 (in_abfd, (bfd_vma) v, data + *dst_ptr);
f4ffd778
NC
239 (*dst_ptr) += 4;
240 (*src_ptr) += 4;;
252b5132
RH
241 }
242 break;
243
252b5132
RH
244 case R_H8500_PCREL8:
245 {
246 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
247 input_section);
44da2da1
AM
248 bfd_vma dot = (*dst_ptr
249 + input_section->output_offset
250 + input_section->output_section->vma);
252b5132 251 int gap = dst - dot - 1; /* -1 since were in the odd byte of the
f4ffd778 252 word and the pc's been incremented. */
252b5132
RH
253
254 if (gap > 128 || gap < -128)
255 {
256 if (! ((*link_info->callbacks->reloc_overflow)
dfeffb9f
L
257 (link_info, NULL,
258 bfd_asymbol_name (*reloc->sym_ptr_ptr),
252b5132
RH
259 reloc->howto->name, reloc->addend, input_section->owner,
260 input_section, reloc->address)))
261 abort ();
262 }
263 bfd_put_8 (in_abfd, gap, data + *dst_ptr);
264 (*dst_ptr)++;
265 (*src_ptr)++;
266 break;
267 }
268 case R_H8500_PCREL16:
269 {
270 bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
271 input_section);
44da2da1
AM
272 bfd_vma dot = (*dst_ptr
273 + input_section->output_offset
274 + input_section->output_section->vma);
252b5132 275 int gap = dst - dot - 1; /* -1 since were in the odd byte of the
f4ffd778 276 word and the pc's been incremented. */
252b5132
RH
277
278 if (gap > 32767 || gap < -32768)
279 {
280 if (! ((*link_info->callbacks->reloc_overflow)
dfeffb9f
L
281 (link_info, NULL,
282 bfd_asymbol_name (*reloc->sym_ptr_ptr),
252b5132
RH
283 reloc->howto->name, reloc->addend, input_section->owner,
284 input_section, reloc->address)))
285 abort ();
286 }
dc810e39 287 bfd_put_16 (in_abfd, (bfd_vma) gap, data + *dst_ptr);
f4ffd778
NC
288 (*dst_ptr) += 2;
289 (*src_ptr) += 2;
252b5132
RH
290 break;
291 }
292
293 default:
294 abort ();
295 }
296}
297
298#define coff_reloc16_extra_cases extra_case
299
300#include "coffcode.h"
301
252b5132
RH
302#undef coff_bfd_get_relocated_section_contents
303#undef coff_bfd_relax_section
304#define coff_bfd_get_relocated_section_contents \
305 bfd_coff_reloc16_get_relocated_section_contents
306#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
307
3fa78519 308CREATE_BIG_COFF_TARGET_VEC (h8500coff_vec, "coff-h8500", 0, 0, '_', NULL, COFF_SWAP_TABLE)
This page took 0.517694 seconds and 4 git commands to generate.