* configure: Ignore new autoconf configure options.
[binutils-gdb.git] / bfd / coff-h8300.c
1 /* BFD back-end for Hitachi H8/300 COFF binaries.
2 Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3 Written by Steve Chamberlain, <sac@cygnus.com>.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
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 2 of the License, or
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "obstack.h"
24 #include "libbfd.h"
25 #include "bfdlink.h"
26 #include "coff/h8300.h"
27 #include "coff/internal.h"
28 #include "libcoff.h"
29
30 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
31
32
33 /* special handling for H8/300 relocs.
34 We only come here for pcrel stuff and return normally if not an -r link.
35 When doing -r, we can't do any arithmetic for the pcrel stuff, because
36 the code in reloc.c assumes that we can manipulate the targets of
37 the pcrel branches. This isn't so, since the H8/300 can do relaxing,
38 which means that the gap after the instruction may not be enough to
39 contain the offset required for the branch, so we have to use the only
40 the addend until the final link */
41
42 static bfd_reloc_status_type
43 special (abfd, reloc_entry, symbol, data, input_section, output_bfd,
44 error_message)
45 bfd *abfd;
46 arelent *reloc_entry;
47 asymbol *symbol;
48 PTR data;
49 asection *input_section;
50 bfd *output_bfd;
51 char **error_message;
52 {
53 if (output_bfd == (bfd *) NULL)
54 return bfd_reloc_continue;
55
56 return bfd_reloc_ok;
57 }
58
59 static reloc_howto_type howto_table[] =
60 {
61 HOWTO (R_RELBYTE, 0, 0, 8, false, 0, complain_overflow_bitfield, special, "8", false, 0x000000ff, 0x000000ff, false),
62 HOWTO (R_RELWORD, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "16", false, 0x0000ffff, 0x0000ffff, false),
63 HOWTO (R_RELLONG, 0, 2, 32, false, 0, complain_overflow_bitfield, special, "32", false, 0xffffffff, 0xffffffff, false),
64 HOWTO (R_PCRBYTE, 0, 0, 8, true, 0, complain_overflow_signed, special, "DISP8", false, 0x000000ff, 0x000000ff, true),
65 HOWTO (R_PCRWORD, 0, 1, 16, true, 0, complain_overflow_signed, special, "DISP16", false, 0x0000ffff, 0x0000ffff, true),
66 HOWTO (R_PCRLONG, 0, 2, 32, true, 0, complain_overflow_signed, special, "DISP32", false, 0xffffffff, 0xffffffff, true),
67 HOWTO (R_MOVB1, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "16/8", false, 0x0000ffff, 0x0000ffff, false),
68 HOWTO (R_MOVB2, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "8/16", false, 0x0000ffff, 0x0000ffff, false),
69 HOWTO (R_JMP1, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "16/pcrel", false, 0x0000ffff, 0x0000ffff, false),
70 HOWTO (R_JMP2, 0, 0, 8, false, 0, complain_overflow_bitfield, special, "pcrecl/16", false, 0x000000ff, 0x000000ff, false),
71
72
73 HOWTO (R_JMPL1, 0, 2, 32, false, 0, complain_overflow_bitfield, special, "24/pcrell", false, 0x00ffffff, 0x00ffffff, false),
74 HOWTO (R_JMPL_B8, 0, 0, 8, false, 0, complain_overflow_bitfield, special, "pc8/24", false, 0x000000ff, 0x000000ff, false),
75
76 HOWTO (R_MOVLB1, 0, 1, 16, false, 0, complain_overflow_bitfield,special, "24/8", false, 0x0000ffff, 0x0000ffff, false),
77 HOWTO (R_MOVLB2, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "8/24", false, 0x0000ffff, 0x0000ffff, false),
78
79 };
80
81
82 /* Turn a howto into a reloc number */
83
84 #define SELECT_RELOC(x,howto) \
85 { x.r_type = select_reloc(howto); }
86
87 #define BADMAG(x) (H8300BADMAG(x)&& H8300HBADMAG(x))
88 #define H8300 1 /* Customize coffcode.h */
89 #define __A_MAGIC_SET__
90
91
92
93 /* Code to swap in the reloc */
94 #define SWAP_IN_RELOC_OFFSET bfd_h_get_32
95 #define SWAP_OUT_RELOC_OFFSET bfd_h_put_32
96 #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
97 dst->r_stuff[0] = 'S'; \
98 dst->r_stuff[1] = 'C';
99
100
101 static int
102 select_reloc (howto)
103 reloc_howto_type *howto;
104 {
105 return howto->type;
106 }
107
108 /* Code to turn a r_type into a howto ptr, uses the above howto table
109 */
110
111 static void
112 rtype2howto (internal, dst)
113 arelent *internal;
114 struct internal_reloc *dst;
115 {
116 switch (dst->r_type)
117 {
118 case R_RELBYTE:
119 internal->howto = howto_table + 0;
120 break;
121 case R_RELWORD:
122 internal->howto = howto_table + 1;
123 break;
124 case R_RELLONG:
125 internal->howto = howto_table + 2;
126 break;
127 case R_PCRBYTE:
128 internal->howto = howto_table + 3;
129 break;
130 case R_PCRWORD:
131 internal->howto = howto_table + 4;
132 break;
133 case R_PCRLONG:
134 internal->howto = howto_table + 5;
135 break;
136 case R_MOVB1:
137 internal->howto = howto_table + 6;
138 break;
139 case R_MOVB2:
140 internal->howto = howto_table + 7;
141 break;
142 case R_JMP1:
143 internal->howto = howto_table + 8;
144 break;
145 case R_JMP2:
146 internal->howto = howto_table + 9;
147 break;
148 case R_JMPL1:
149 internal->howto = howto_table + 10;
150 break;
151 case R_JMPL_B8:
152 internal->howto = howto_table + 11;
153 break;
154 case R_MOVLB1:
155 internal->howto = howto_table + 12;
156 break;
157 case R_MOVLB2:
158 internal->howto = howto_table + 13;
159 break;
160 default:
161 fprintf (stderr, "Bad reloc\n");
162 break;
163 }
164 }
165
166 #define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
167
168
169 /* Perform any necessaru magic to the addend in a reloc entry */
170
171
172 #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
173 cache_ptr->addend = ext_reloc.r_offset;
174
175
176 #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
177 reloc_processing(relent, reloc, symbols, abfd, section)
178
179 static void
180 reloc_processing (relent, reloc, symbols, abfd, section)
181 arelent * relent;
182 struct internal_reloc *reloc;
183 asymbol ** symbols;
184 bfd * abfd;
185 asection * section;
186 {
187 relent->address = reloc->r_vaddr;
188 rtype2howto (relent, reloc);
189
190 if (((int) reloc->r_symndx) > 0)
191 {
192 relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
193 }
194 else
195 {
196 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
197 }
198
199
200
201 relent->addend = reloc->r_offset;
202
203 relent->address -= section->vma;
204 /* relent->section = 0;*/
205 }
206
207
208 static int
209 h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info)
210 bfd *abfd;
211 asection *input_section;
212 arelent *reloc;
213 unsigned int shrink;
214 struct bfd_link_info *link_info;
215 {
216 bfd_vma value;
217 bfd_vma dot;
218 bfd_vma gap;
219
220 /* The address of the thing to be relocated will have moved back by
221 the size of the shrink - but we don't change reloc->address here,
222 since we need it to know where the relocation lives in the source
223 uncooked section */
224
225 /* reloc->address -= shrink; conceptual */
226
227 bfd_vma address = reloc->address - shrink;
228
229
230 switch (reloc->howto->type)
231 {
232 case R_MOVB2:
233 case R_JMP2:
234 shrink+=2;
235 break;
236
237 /* Thing is a move one byte */
238 case R_MOVB1:
239 value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
240
241 if (value >= 0xff00)
242 {
243
244 /* Change the reloc type from 16bit, possible 8 to 8bit
245 possible 16 */
246 reloc->howto = reloc->howto + 1;
247 /* The place to relc moves back by one */
248 /* This will be two bytes smaller in the long run */
249 shrink +=2 ;
250 bfd_perform_slip(abfd, 2, input_section, address);
251 }
252
253 break;
254 /* This is the 24 bit branch which could become an 8 bitter,
255 the relocation points to the first byte of the insn, not the
256 actual data */
257
258 case R_JMPL1:
259 value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
260
261 dot = input_section->output_section->vma +
262 input_section->output_offset + address;
263
264 /* See if the address we're looking at within 127 bytes of where
265 we are, if so then we can use a small branch rather than the
266 jump we were going to */
267
268 gap = value - dot ;
269
270 if (-120 < (long)gap && (long)gap < 120 )
271 {
272
273 /* Change the reloc type from 24bit, possible 8 to 8bit
274 possible 32 */
275 reloc->howto = reloc->howto + 1;
276 /* This will be two bytes smaller in the long run */
277 shrink +=2 ;
278 bfd_perform_slip(abfd, 2, input_section, address);
279 }
280 break;
281
282 case R_JMP1:
283
284 value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
285
286 dot = input_section->output_section->vma +
287 input_section->output_offset + address;
288
289 /* See if the address we're looking at within 127 bytes of where
290 we are, if so then we can use a small branch rather than the
291 jump we were going to */
292
293 gap = value - (dot - shrink);
294
295
296 if (-120 < (long)gap && (long)gap < 120 )
297 {
298
299 /* Change the reloc type from 16bit, possible 8 to 8bit
300 possible 16 */
301 reloc->howto = reloc->howto + 1;
302 /* The place to relc moves back by one */
303
304 /* This will be two bytes smaller in the long run */
305 shrink +=2 ;
306 bfd_perform_slip(abfd, 2, input_section, address);
307 }
308 break;
309 }
310
311
312 return shrink;
313 }
314
315
316 /* First phase of a relaxing link */
317
318 /* Reloc types
319 large small
320 R_MOVB1 R_MOVB2 mov.b with 16bit or 8 bit address
321 R_JMP1 R_JMP2 jmp or pcrel branch
322 R_JMPL1 R_JMPL_B8 24jmp or pcrel branch
323 R_MOVLB1 R_MOVLB2 24 or 8 bit reloc for mov.b
324
325 */
326
327 static void
328 h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
329 dst_ptr)
330 bfd *abfd;
331 struct bfd_link_info *link_info;
332 struct bfd_link_order *link_order;
333 arelent *reloc;
334 bfd_byte *data;
335 unsigned int *src_ptr;
336 unsigned int *dst_ptr;
337 {
338 unsigned int src_address = *src_ptr;
339 unsigned int dst_address = *dst_ptr;
340 asection *input_section = link_order->u.indirect.section;
341
342 switch (reloc->howto->type)
343 {
344 /* A 24 bit branch which could be a 8 bit pcrel, really pointing to
345 the byte before the 24bit hole, so we can treat it as a 32bit pointer */
346 case R_PCRBYTE:
347 {
348 bfd_vma dot = link_order->offset
349 + dst_address
350 + link_order->u.indirect.section->output_section->vma;
351 int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
352 - dot);
353 if (gap > 127 || gap < -128)
354 {
355 if (! ((*link_info->callbacks->reloc_overflow)
356 (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
357 reloc->howto->name, reloc->addend, input_section->owner,
358 input_section, reloc->address)))
359 abort ();
360 }
361 gap &= ~1;
362 bfd_put_8 (abfd, gap, data + dst_address);
363 dst_address++;
364 src_address++;
365
366 break;
367 }
368 case R_PCRWORD:
369 {
370 bfd_vma dot = link_order->offset
371 + dst_address
372 + link_order->u.indirect.section->output_section->vma;
373 int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
374 - dot) - 1;
375 if (gap > 32767 || gap < -32768)
376 {
377 if (! ((*link_info->callbacks->reloc_overflow)
378 (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
379 reloc->howto->name, reloc->addend, input_section->owner,
380 input_section, reloc->address)))
381 abort ();
382 }
383
384 bfd_put_16 (abfd, gap, data + dst_address);
385 dst_address+=2;
386 src_address+=2;
387
388 break;
389 }
390
391 case R_RELBYTE:
392 {
393 unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
394 input_section);
395 if (gap < 0xff
396 || (gap >= 0x0000ff00
397 && gap <= 0x0000ffff)
398 || ( gap >= 0x00ffff00
399 && gap <= 0x00ffffff)
400 || ( gap >= 0xffffff00
401 && gap <= 0xffffffff))
402 {
403 bfd_put_8 (abfd, gap, data + dst_address);
404 dst_address += 1;
405 src_address += 1;
406 }
407 else
408 {
409 if (! ((*link_info->callbacks->reloc_overflow)
410 (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
411 reloc->howto->name, reloc->addend, input_section->owner,
412 input_section, reloc->address)))
413 abort ();
414 }
415 }
416 break;
417 case R_JMP1:
418 /* A relword which would have like to have been a pcrel */
419 case R_MOVB1:
420 /* A relword which would like to have been modified but
421 didn't make it */
422 case R_RELWORD:
423 bfd_put_16 (abfd,
424 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
425 data + dst_address);
426 dst_address += 2;
427 src_address += 2;
428 break;
429 case R_RELLONG:
430 bfd_put_32 (abfd,
431 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
432 data + dst_address);
433 dst_address += 4;
434 src_address += 4;
435 break;
436
437 case R_MOVB2:
438 /* Special relaxed type, there will be a gap between where we
439 get stuff from and where we put stuff to now
440
441 for a mov.b @aa:16 -> mov.b @aa:8
442 opcode 0x6a 0x0y offset
443 -> 0x2y off
444 */
445 if (data[dst_address - 1] != 0x6a)
446 abort ();
447 switch (data[src_address] & 0xf0)
448 {
449 case 0x00:
450 /* Src is memory */
451 data[dst_address - 1] = (data[src_address] & 0xf) | 0x20;
452 break;
453 case 0x80:
454 /* Src is reg */
455 data[dst_address - 1] = (data[src_address] & 0xf) | 0x30;
456 break;
457 default:
458 abort ();
459 }
460
461 /* the offset must fit ! after all, what was all the relaxing
462 about ? */
463
464 bfd_put_8 (abfd,
465 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
466 data + dst_address);
467
468 /* Note the magic - src goes up by two bytes, but dst by only
469 one */
470 dst_address += 1;
471 src_address += 3;
472
473 break;
474
475 case R_JMP2:
476
477 /* Speciial relaxed type */
478 {
479 bfd_vma dot = link_order->offset
480 + dst_address
481 + link_order->u.indirect.section->output_section->vma;
482
483 int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
484 - dot - 1);
485
486 if ((gap & ~0xff) != 0 && ((gap & 0xff00) != 0xff00))
487 abort ();
488
489 bfd_put_8 (abfd, gap, data + dst_address);
490
491 switch (data[dst_address - 1])
492 {
493 case 0x5e:
494 /* jsr -> bsr */
495 bfd_put_8 (abfd, 0x55, data + dst_address - 1);
496 break;
497 case 0x5a:
498 /* jmp ->bra */
499 bfd_put_8 (abfd, 0x40, data + dst_address - 1);
500 break;
501
502 default:
503 abort ();
504 }
505 dst_address++;
506 src_address += 3;
507
508 break;
509 }
510 break;
511
512 case R_JMPL_B8: /* 24 bit branch which is now 8 bits */
513
514 /* Speciial relaxed type */
515 {
516 bfd_vma dot = link_order->offset
517 + dst_address
518 + link_order->u.indirect.section->output_section->vma;
519
520 int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
521 - dot - 2);
522
523 if ((gap & ~0xff) != 0 && ((gap & 0xff00) != 0xff00))
524 abort ();
525
526 switch (data[src_address])
527 {
528 case 0x5e:
529 /* jsr -> bsr */
530 bfd_put_8 (abfd, 0x55, data + dst_address);
531 break;
532 case 0x5a:
533 /* jmp ->bra */
534 bfd_put_8 (abfd, 0x40, data + dst_address);
535 break;
536
537 default:
538 bfd_put_8 (abfd, 0xde, data + dst_address);
539 break;
540 }
541
542 bfd_put_8 (abfd, gap, data + dst_address + 1);
543 dst_address += 2;
544 src_address += 4;
545
546 break;
547 }
548
549 case R_JMPL1:
550 {
551 int v = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
552 int o = bfd_get_32 (abfd, data + src_address);
553 v = (v & 0x00ffffff) | (o & 0xff000000);
554 bfd_put_32 (abfd, v, data + dst_address);
555 dst_address += 4;
556 src_address += 4;
557 }
558
559 break;
560
561
562 /* A 24 bit mov which could be an 8 bit move, really pointing to
563 the byte before the 24bit hole, so we can treat it as a 32bit pointer */
564 case R_MOVLB1:
565 {
566 int v = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
567 int o = bfd_get_32 (abfd, data + dst_address);
568 v = (v & 0x00ffffff) | (o & 0xff000000);
569 bfd_put_32 (abfd, v, data + dst_address);
570 dst_address += 4;
571 src_address += 4;
572 }
573
574 break;
575 default:
576
577 abort ();
578 break;
579
580 }
581 *src_ptr = src_address;
582 *dst_ptr = dst_address;
583
584 }
585
586 #define coff_reloc16_extra_cases h8300_reloc16_extra_cases
587 #define coff_reloc16_estimate h8300_reloc16_estimate
588
589 #define COFF_LONG_FILENAMES
590 #include "coffcode.h"
591
592
593 #undef coff_bfd_get_relocated_section_contents
594 #undef coff_bfd_relax_section
595 #define coff_bfd_get_relocated_section_contents \
596 bfd_coff_reloc16_get_relocated_section_contents
597 #define coff_bfd_relax_section bfd_coff_reloc16_relax_section
598
599
600
601 const bfd_target h8300coff_vec =
602 {
603 "coff-h8300", /* name */
604 bfd_target_coff_flavour,
605 true, /* data byte order is big */
606 true, /* header byte order is big */
607
608 (HAS_RELOC | EXEC_P | /* object flags */
609 HAS_LINENO | HAS_DEBUG |
610 HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE ),
611 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
612 '_', /* leading char */
613 '/', /* ar_pad_char */
614 15, /* ar_max_namelen */
615 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
616 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
617 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
618 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
619 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
620 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
621
622 {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
623 bfd_generic_archive_p, _bfd_dummy_target},
624 {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
625 bfd_false},
626 {bfd_false, coff_write_object_contents, /* bfd_write_contents */
627 _bfd_write_archive_contents, bfd_false},
628
629 BFD_JUMP_TABLE_GENERIC (coff),
630 BFD_JUMP_TABLE_COPY (coff),
631 BFD_JUMP_TABLE_CORE (_bfd_nocore),
632 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
633 BFD_JUMP_TABLE_SYMBOLS (coff),
634 BFD_JUMP_TABLE_RELOCS (coff),
635 BFD_JUMP_TABLE_WRITE (coff),
636 BFD_JUMP_TABLE_LINK (coff),
637 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
638
639 COFF_SWAP_TABLE,
640 };