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>.
5 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
26 #include "coff/h8300.h"
27 #include "coff/internal.h"
30 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
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 */
42 static bfd_reloc_status_type
43 special (abfd, reloc_entry, symbol, data, input_section, output_bfd,
49 asection *input_section;
53 if (output_bfd == (bfd *) NULL)
54 return bfd_reloc_continue;
59 static reloc_howto_type howto_table[] =
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),
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),
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),
82 /* Turn a howto into a reloc number */
84 #define SELECT_RELOC(x,howto) \
85 { x.r_type = select_reloc(howto); }
87 #define BADMAG(x) (H8300BADMAG(x)&& H8300HBADMAG(x))
88 #define H8300 1 /* Customize coffcode.h */
89 #define __A_MAGIC_SET__
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';
103 reloc_howto_type *howto;
108 /* Code to turn a r_type into a howto ptr, uses the above howto table
112 rtype2howto (internal, dst)
114 struct internal_reloc *dst;
119 internal->howto = howto_table + 0;
122 internal->howto = howto_table + 1;
125 internal->howto = howto_table + 2;
128 internal->howto = howto_table + 3;
131 internal->howto = howto_table + 4;
134 internal->howto = howto_table + 5;
137 internal->howto = howto_table + 6;
140 internal->howto = howto_table + 7;
143 internal->howto = howto_table + 8;
146 internal->howto = howto_table + 9;
149 internal->howto = howto_table + 10;
152 internal->howto = howto_table + 11;
155 internal->howto = howto_table + 12;
158 internal->howto = howto_table + 13;
161 fprintf (stderr, "Bad reloc\n");
166 #define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
169 /* Perform any necessaru magic to the addend in a reloc entry */
172 #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
173 cache_ptr->addend = ext_reloc.r_offset;
176 #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
177 reloc_processing(relent, reloc, symbols, abfd, section)
180 reloc_processing (relent, reloc, symbols, abfd, section)
182 struct internal_reloc *reloc;
187 relent->address = reloc->r_vaddr;
188 rtype2howto (relent, reloc);
190 if (((int) reloc->r_symndx) > 0)
192 relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
196 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
201 relent->addend = reloc->r_offset;
203 relent->address -= section->vma;
204 /* relent->section = 0;*/
209 h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info)
211 asection *input_section;
214 struct bfd_link_info *link_info;
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
225 /* reloc->address -= shrink; conceptual */
227 bfd_vma address = reloc->address - shrink;
230 switch (reloc->howto->type)
237 /* Thing is a move one byte */
239 value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
244 /* Change the reloc type from 16bit, possible 8 to 8bit
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 */
250 bfd_perform_slip(abfd, 2, input_section, address);
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
259 value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
261 dot = input_section->output_section->vma +
262 input_section->output_offset + address;
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 */
270 if (-120 < (long)gap && (long)gap < 120 )
273 /* Change the reloc type from 24bit, possible 8 to 8bit
275 reloc->howto = reloc->howto + 1;
276 /* This will be two bytes smaller in the long run */
278 bfd_perform_slip(abfd, 2, input_section, address);
284 value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
286 dot = input_section->output_section->vma +
287 input_section->output_offset + address;
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 */
293 gap = value - (dot - shrink);
296 if (-120 < (long)gap && (long)gap < 120 )
299 /* Change the reloc type from 16bit, possible 8 to 8bit
301 reloc->howto = reloc->howto + 1;
302 /* The place to relc moves back by one */
304 /* This will be two bytes smaller in the long run */
306 bfd_perform_slip(abfd, 2, input_section, address);
316 /* First phase of a relaxing link */
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
328 h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
331 struct bfd_link_info *link_info;
332 struct bfd_link_order *link_order;
335 unsigned int *src_ptr;
336 unsigned int *dst_ptr;
338 unsigned int src_address = *src_ptr;
339 unsigned int dst_address = *dst_ptr;
340 asection *input_section = link_order->u.indirect.section;
342 switch (reloc->howto->type)
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 */
348 bfd_vma dot = link_order->offset
350 + link_order->u.indirect.section->output_section->vma;
351 int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
353 if (gap > 127 || gap < -128)
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)))
362 bfd_put_8 (abfd, gap, data + dst_address);
370 bfd_vma dot = link_order->offset
372 + link_order->u.indirect.section->output_section->vma;
373 int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
375 if (gap > 32767 || gap < -32768)
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)))
384 bfd_put_16 (abfd, gap, data + dst_address);
393 unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
396 || (gap >= 0x0000ff00
397 && gap <= 0x0000ffff)
398 || ( gap >= 0x00ffff00
399 && gap <= 0x00ffffff)
400 || ( gap >= 0xffffff00
401 && gap <= 0xffffffff))
403 bfd_put_8 (abfd, gap, data + dst_address);
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)))
418 /* A relword which would have like to have been a pcrel */
420 /* A relword which would like to have been modified but
424 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
431 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
438 /* Special relaxed type, there will be a gap between where we
439 get stuff from and where we put stuff to now
441 for a mov.b @aa:16 -> mov.b @aa:8
442 opcode 0x6a 0x0y offset
445 if (data[dst_address - 1] != 0x6a)
447 switch (data[src_address] & 0xf0)
451 data[dst_address - 1] = (data[src_address] & 0xf) | 0x20;
455 data[dst_address - 1] = (data[src_address] & 0xf) | 0x30;
461 /* the offset must fit ! after all, what was all the relaxing
465 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
468 /* Note the magic - src goes up by two bytes, but dst by only
477 /* Speciial relaxed type */
479 bfd_vma dot = link_order->offset
481 + link_order->u.indirect.section->output_section->vma;
483 int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
486 if ((gap & ~0xff) != 0 && ((gap & 0xff00) != 0xff00))
489 bfd_put_8 (abfd, gap, data + dst_address);
491 switch (data[dst_address - 1])
495 bfd_put_8 (abfd, 0x55, data + dst_address - 1);
499 bfd_put_8 (abfd, 0x40, data + dst_address - 1);
512 case R_JMPL_B8: /* 24 bit branch which is now 8 bits */
514 /* Speciial relaxed type */
516 bfd_vma dot = link_order->offset
518 + link_order->u.indirect.section->output_section->vma;
520 int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
523 if ((gap & ~0xff) != 0 && ((gap & 0xff00) != 0xff00))
526 switch (data[src_address])
530 bfd_put_8 (abfd, 0x55, data + dst_address);
534 bfd_put_8 (abfd, 0x40, data + dst_address);
538 bfd_put_8 (abfd, 0xde, data + dst_address);
542 bfd_put_8 (abfd, gap, data + dst_address + 1);
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);
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 */
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);
581 *src_ptr = src_address;
582 *dst_ptr = dst_address;
586 #define coff_reloc16_extra_cases h8300_reloc16_extra_cases
587 #define coff_reloc16_estimate h8300_reloc16_estimate
589 #define COFF_LONG_FILENAMES
590 #include "coffcode.h"
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
601 const bfd_target h8300coff_vec =
603 "coff-h8300", /* name */
604 bfd_target_coff_flavour,
605 true, /* data byte order is big */
606 true, /* header byte order is big */
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 */
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 */
626 {bfd_false, coff_write_object_contents, /* bfd_write_contents */
627 _bfd_write_archive_contents, bfd_false},
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),