]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/coff-w65.c
This commit was manufactured by cvs2svn to create branch 'gdb_7_2-branch'.
[thirdparty/binutils-gdb.git] / bfd / coff-w65.c
CommitLineData
252b5132 1/* BFD back-end for WDC 65816 COFF binaries.
f592407e 2 Copyright 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2b5c217d 3 2006, 2007, 2008 Free Software Foundation, Inc.
252b5132
RH
4 Written by Steve Chamberlain, <sac@cygnus.com>.
5
cd123cb7 6 This file is part of BFD, the Binary File Descriptor library.
252b5132 7
cd123cb7
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
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
252b5132 12
cd123cb7
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
cd123cb7
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
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/w65.h"
28#include "coff/internal.h"
29#include "libcoff.h"
30
f4ffd778
NC
31static int 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 int w65_reloc16_estimate PARAMS ((bfd *, asection *, arelent *, unsigned int, struct bfd_link_info *));
35static void w65_reloc16_extra_cases PARAMS ((bfd *,struct bfd_link_info *, struct bfd_link_order *, arelent *, bfd_byte *, unsigned int *, unsigned int *));
36
252b5132
RH
37#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
38static reloc_howto_type howto_table[] =
f4ffd778 39 {
b34976b6
AM
40 HOWTO (R_W65_ABS8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, "abs8", TRUE, 0x000000ff, 0x000000ff, FALSE),
41 HOWTO (R_W65_ABS16, 1, 0, 16, FALSE, 0, complain_overflow_bitfield, 0, "abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
42 HOWTO (R_W65_ABS24, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 0, "abs24", TRUE, 0x00ffffff, 0x00ffffff, FALSE),
43 HOWTO (R_W65_ABS8S8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, ">abs8", TRUE, 0x000000ff, 0x000000ff, FALSE),
44 HOWTO (R_W65_ABS8S16, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, "^abs8", TRUE, 0x000000ff, 0x000000ff, FALSE),
45 HOWTO (R_W65_ABS16S8, 1, 0, 16, FALSE, 0, complain_overflow_bitfield, 0, ">abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
46 HOWTO (R_W65_ABS16S16,1, 0, 16, FALSE, 0, complain_overflow_bitfield, 0, "^abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
47 HOWTO (R_W65_PCR8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, "pcrel8", TRUE, 0x000000ff, 0x000000ff, TRUE),
48 HOWTO (R_W65_PCR16, 1, 0, 16, FALSE, 0, complain_overflow_bitfield, 0, "pcrel16", TRUE, 0x0000ffff, 0x0000ffff, TRUE),
49 HOWTO (R_W65_DP, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, "dp", TRUE, 0x000000ff, 0x000000ff, FALSE),
f4ffd778
NC
50 };
51
52/* Turn a howto into a reloc number. */
252b5132
RH
53
54#define SELECT_RELOC(x,howto) \
55 { x.r_type = select_reloc(howto); }
56
57#define BADMAG(x) (W65BADMAG(x))
58#define W65 1 /* Customize coffcode.h */
59#define __A_MAGIC_SET__
60
252b5132 61/* Code to swap in the reloc */
dc810e39
AM
62#define SWAP_IN_RELOC_OFFSET H_GET_32
63#define SWAP_OUT_RELOC_OFFSET H_PUT_32
252b5132
RH
64#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
65 dst->r_stuff[0] = 'S'; \
66 dst->r_stuff[1] = 'C';
67
252b5132
RH
68static int
69select_reloc (howto)
70 reloc_howto_type *howto;
71{
72 return howto->type ;
73}
74
f4ffd778 75/* Code to turn a r_type into a howto ptr, uses the above howto table. */
252b5132
RH
76
77static void
78rtype2howto (internal, dst)
79 arelent *internal;
80 struct internal_reloc *dst;
81{
f4ffd778 82 internal->howto = howto_table + dst->r_type - 1;
252b5132
RH
83}
84
85#define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
86
f4ffd778 87/* Perform any necessary magic to the addend in a reloc entry. */
252b5132 88
252b5132
RH
89#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
90 cache_ptr->addend = ext_reloc.r_offset;
91
252b5132
RH
92#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
93 reloc_processing(relent, reloc, symbols, abfd, section)
94
95static void
96reloc_processing (relent, reloc, symbols, abfd, section)
97 arelent * relent;
98 struct internal_reloc *reloc;
99 asymbol ** symbols;
100 bfd * abfd;
101 asection * section;
102{
103 relent->address = reloc->r_vaddr;
104 rtype2howto (relent, reloc);
105
106 if (((int) reloc->r_symndx) > 0)
f4ffd778 107 relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
252b5132 108 else
f592407e 109 relent->sym_ptr_ptr = (asymbol **) bfd_abs_section_ptr->symbol_ptr_ptr;
252b5132 110
252b5132
RH
111 relent->addend = reloc->r_offset;
112
113 relent->address -= section->vma;
114 /* relent->section = 0;*/
115}
116
252b5132 117static int
f4ffd778 118w65_reloc16_estimate (abfd, input_section, reloc, shrink, link_info)
252b5132
RH
119 bfd *abfd;
120 asection *input_section;
121 arelent *reloc;
122 unsigned int shrink;
123 struct bfd_link_info *link_info;
124{
cbfe05c4 125 bfd_vma value;
252b5132
RH
126 bfd_vma dot;
127 bfd_vma gap;
128
cbfe05c4 129 /* The address of the thing to be relocated will have moved back by
252b5132
RH
130 the size of the shrink - but we don't change reloc->address here,
131 since we need it to know where the relocation lives in the source
f4ffd778 132 uncooked section. */
252b5132
RH
133
134 /* reloc->address -= shrink; conceptual */
135
136 bfd_vma address = reloc->address - shrink;
252b5132
RH
137
138 switch (reloc->howto->type)
cbfe05c4 139 {
252b5132
RH
140 case R_MOV16B2:
141 case R_JMP2:
142 shrink+=2;
143 break;
144
f4ffd778 145 /* Thing is a move one byte. */
252b5132 146 case R_MOV16B1:
f4ffd778 147 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
252b5132
RH
148
149 if (value >= 0xff00)
cbfe05c4 150 {
252b5132 151 /* Change the reloc type from 16bit, possible 8 to 8bit
f4ffd778 152 possible 16. */
cbfe05c4 153 reloc->howto = reloc->howto + 1;
f4ffd778
NC
154 /* The place to relc moves back by one. */
155 /* This will be two bytes smaller in the long run. */
156 shrink += 2;
157 bfd_perform_slip (abfd, 2, input_section, address);
cbfe05c4 158 }
252b5132
RH
159
160 break;
cbfe05c4 161 /* This is the 24 bit branch which could become an 8 bitter,
f4ffd778
NC
162 the relocation points to the first byte of the insn, not the
163 actual data. */
252b5132
RH
164
165 case R_JMPL1:
f4ffd778 166 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
cbfe05c4 167
252b5132
RH
168 dot = input_section->output_section->vma +
169 input_section->output_offset + address;
cbfe05c4 170
252b5132
RH
171 /* See if the address we're looking at within 127 bytes of where
172 we are, if so then we can use a small branch rather than the
f4ffd778
NC
173 jump we were going to. */
174 gap = value - dot;
cbfe05c4 175
f4ffd778 176 if (-120 < (long) gap && (long) gap < 120)
cbfe05c4 177 {
252b5132 178 /* Change the reloc type from 24bit, possible 8 to 8bit
f4ffd778 179 possible 32. */
cbfe05c4 180 reloc->howto = reloc->howto + 1;
f4ffd778
NC
181 /* This will be two bytes smaller in the long run. */
182 shrink += 2;
183 bfd_perform_slip (abfd, 2, input_section, address);
252b5132
RH
184 }
185 break;
186
187 case R_JMP1:
f4ffd778 188 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
cbfe05c4 189
252b5132
RH
190 dot = input_section->output_section->vma +
191 input_section->output_offset + address;
cbfe05c4 192
252b5132
RH
193 /* See if the address we're looking at within 127 bytes of where
194 we are, if so then we can use a small branch rather than the
f4ffd778 195 jump we were going to. */
252b5132 196 gap = value - (dot - shrink);
252b5132 197
f4ffd778 198 if (-120 < (long) gap && (long) gap < 120)
cbfe05c4 199 {
252b5132 200 /* Change the reloc type from 16bit, possible 8 to 8bit
f4ffd778 201 possible 16. */
cbfe05c4 202 reloc->howto = reloc->howto + 1;
f4ffd778 203 /* The place to relc moves back by one. */
252b5132 204
f4ffd778
NC
205 /* This will be two bytes smaller in the long run. */
206 shrink += 2;
207 bfd_perform_slip (abfd, 2, input_section, address);
252b5132
RH
208 }
209 break;
210 }
211
252b5132
RH
212 return shrink;
213}
214
f4ffd778 215/* First phase of a relaxing link. */
252b5132
RH
216
217/* Reloc types
218 large small
219 R_MOV16B1 R_MOV16B2 mov.b with 16bit or 8 bit address
220 R_JMP1 R_JMP2 jmp or pcrel branch
221 R_JMPL1 R_JMPL_B8 24jmp or pcrel branch
f4ffd778 222 R_MOV24B1 R_MOV24B2 24 or 8 bit reloc for mov.b */
252b5132
RH
223
224static void
f4ffd778 225w65_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
252b5132
RH
226 dst_ptr)
227 bfd *abfd;
228 struct bfd_link_info *link_info;
229 struct bfd_link_order *link_order;
230 arelent *reloc;
231 bfd_byte *data;
232 unsigned int *src_ptr;
233 unsigned int *dst_ptr;
234{
235 unsigned int src_address = *src_ptr;
236 unsigned int dst_address = *dst_ptr;
237 asection *input_section = link_order->u.indirect.section;
238
239 switch (reloc->howto->type)
240 {
241 case R_W65_ABS8:
242 case R_W65_DP:
243 {
244 unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
245 input_section);
246 bfd_put_8 (abfd, gap, data + dst_address);
247 dst_address += 1;
248 src_address += 1;
249 }
250 break;
251
252 case R_W65_ABS8S8:
253 {
254 unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
255 input_section);
256 gap >>= 8;
257 bfd_put_8 (abfd, gap, data + dst_address);
258 dst_address += 1;
259 src_address += 1;
260 }
261 break;
262
263 case R_W65_ABS8S16:
264 {
265 unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
266 input_section);
f4ffd778 267 gap >>= 16;
252b5132
RH
268 bfd_put_8 (abfd, gap, data + dst_address);
269 dst_address += 1;
270 src_address += 1;
271 }
272 break;
273
274 case R_W65_ABS16:
275 {
276 unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
277 input_section);
278
dc810e39 279 bfd_put_16 (abfd, (bfd_vma) gap, data + dst_address);
252b5132
RH
280 dst_address += 2;
281 src_address += 2;
282 }
283 break;
284 case R_W65_ABS16S8:
285 {
286 unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
287 input_section);
288 gap >>= 8;
dc810e39 289 bfd_put_16 (abfd, (bfd_vma) gap, data + dst_address);
252b5132
RH
290 dst_address += 2;
291 src_address += 2;
292 }
293 break;
294 case R_W65_ABS16S16:
295 {
296 unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
297 input_section);
298 gap >>= 16;
dc810e39 299 bfd_put_16 (abfd, (bfd_vma) gap, data + dst_address);
252b5132
RH
300 dst_address += 2;
301 src_address += 2;
302 }
303 break;
304
305 case R_W65_ABS24:
306 {
307 unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
308 input_section);
dc810e39 309 bfd_put_16 (abfd, (bfd_vma) gap, data + dst_address);
f4ffd778 310 bfd_put_8 (abfd, gap >> 16, data+dst_address + 2);
252b5132
RH
311 dst_address += 3;
312 src_address += 3;
313 }
314 break;
315
316 case R_W65_PCR8:
317 {
318 int gap = bfd_coff_reloc16_get_value (reloc, link_info,
319 input_section);
44da2da1
AM
320 bfd_vma dot = (dst_address
321 + input_section->output_offset
322 + input_section->output_section->vma);
252b5132
RH
323
324 gap -= dot + 1;
f4ffd778
NC
325 if (gap < -128 || gap > 127)
326 {
327 if (! ((*link_info->callbacks->reloc_overflow)
dfeffb9f
L
328 (link_info, NULL,
329 bfd_asymbol_name (*reloc->sym_ptr_ptr),
f4ffd778
NC
330 reloc->howto->name, reloc->addend, input_section->owner,
331 input_section, reloc->address)))
332 abort ();
333 }
252b5132
RH
334 bfd_put_8 (abfd, gap, data + dst_address);
335 dst_address += 1;
336 src_address += 1;
337 }
338 break;
339
340 case R_W65_PCR16:
341 {
342 bfd_vma gap = bfd_coff_reloc16_get_value (reloc, link_info,
343 input_section);
44da2da1
AM
344 bfd_vma dot = (dst_address
345 + input_section->output_offset
346 + input_section->output_section->vma);
252b5132 347
252b5132 348 /* This wraps within the page, so ignore the relativeness, look at the
f4ffd778
NC
349 high part. */
350 if ((gap & 0xf0000) != (dot & 0xf0000))
351 {
352 if (! ((*link_info->callbacks->reloc_overflow)
dfeffb9f
L
353 (link_info, NULL,
354 bfd_asymbol_name (*reloc->sym_ptr_ptr),
f4ffd778
NC
355 reloc->howto->name, reloc->addend, input_section->owner,
356 input_section, reloc->address)))
357 abort ();
358 }
252b5132
RH
359
360 gap -= dot + 2;
361 bfd_put_16 (abfd, gap, data + dst_address);
362 dst_address += 2;
363 src_address += 2;
364 }
365 break;
366 default:
6e301b2b 367 printf (_("ignoring reloc %s\n"), reloc->howto->name);
252b5132
RH
368 break;
369
370 }
371 *src_ptr = src_address;
372 *dst_ptr = dst_address;
252b5132
RH
373}
374
f4ffd778
NC
375#define coff_reloc16_extra_cases w65_reloc16_extra_cases
376#define coff_reloc16_estimate w65_reloc16_estimate
252b5132 377
2b5c217d
NC
378#ifndef bfd_pe_print_pdata
379#define bfd_pe_print_pdata NULL
380#endif
381
252b5132
RH
382#include "coffcode.h"
383
252b5132
RH
384#undef coff_bfd_get_relocated_section_contents
385#undef coff_bfd_relax_section
386#define coff_bfd_get_relocated_section_contents \
387 bfd_coff_reloc16_get_relocated_section_contents
388#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
389
3fa78519 390CREATE_LITTLE_COFF_TARGET_VEC (w65_vec, "coff-w65", BFD_IS_RELAXABLE, 0, '_', NULL, COFF_SWAP_TABLE)