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