source: trunk/src/binutils/bfd/coff-w65.c@ 610

Last change on this file since 610 was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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