1 /* BFD back-end for Hitachi H8/300 COFF binaries.
2 Copyright 1990, 1991, 1992, 1993, 1994 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., 675 Mass Ave, Cambridge, MA 02139, 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
;
55 if (output_bfd
== (bfd
*) NULL
)
56 return bfd_reloc_continue
;
61 static reloc_howto_type howto_table
[] =
63 HOWTO (R_RELBYTE
, 0, 0, 8, false, 0, complain_overflow_bitfield
, special
, "8", false, 0x000000ff, 0x000000ff, false),
64 HOWTO (R_RELWORD
, 0, 1, 16, false, 0, complain_overflow_bitfield
, special
, "16", false, 0x0000ffff, 0x0000ffff, false),
65 HOWTO (R_RELLONG
, 0, 2, 32, false, 0, complain_overflow_bitfield
, special
, "32", false, 0xffffffff, 0xffffffff, false),
66 HOWTO (R_PCRBYTE
, 0, 0, 8, true, 0, complain_overflow_signed
, special
, "DISP8", false, 0x000000ff, 0x000000ff, true),
67 HOWTO (R_PCRWORD
, 0, 1, 16, true, 0, complain_overflow_signed
, special
, "DISP16", false, 0x0000ffff, 0x0000ffff, true),
68 HOWTO (R_PCRLONG
, 0, 2, 32, true, 0, complain_overflow_signed
, special
, "DISP32", false, 0xffffffff, 0xffffffff, true),
69 HOWTO (R_MOVB1
, 0, 1, 16, false, 0, complain_overflow_bitfield
, special
, "16/8", false, 0x0000ffff, 0x0000ffff, false),
70 HOWTO (R_MOVB2
, 0, 1, 16, false, 0, complain_overflow_bitfield
, special
, "8/16", false, 0x0000ffff, 0x0000ffff, false),
71 HOWTO (R_JMP1
, 0, 1, 16, false, 0, complain_overflow_bitfield
, special
, "16/pcrel", false, 0x0000ffff, 0x0000ffff, false),
72 HOWTO (R_JMP2
, 0, 0, 8, false, 0, complain_overflow_bitfield
, special
, "pcrecl/16", false, 0x000000ff, 0x000000ff, false),
75 HOWTO (R_JMPL1
, 0, 2, 32, false, 0, complain_overflow_bitfield
, special
, "24/pcrell", false, 0x00ffffff, 0x00ffffff, false),
76 HOWTO (R_JMPL_B8
, 0, 0, 8, false, 0, complain_overflow_bitfield
, special
, "pc8/24", false, 0x000000ff, 0x000000ff, false),
78 HOWTO (R_MOVLB1
, 0, 1, 16, false, 0, complain_overflow_bitfield
,special
, "24/8", false, 0x0000ffff, 0x0000ffff, false),
79 HOWTO (R_MOVLB2
, 0, 1, 16, false, 0, complain_overflow_bitfield
, special
, "8/24", false, 0x0000ffff, 0x0000ffff, false),
84 /* Turn a howto into a reloc number */
86 #define SELECT_RELOC(x,howto) \
87 { x.r_type = select_reloc(howto); }
89 #define BADMAG(x) (H8300BADMAG(x)&& H8300HBADMAG(x))
90 #define H8300 1 /* Customize coffcode.h */
91 #define __A_MAGIC_SET__
95 /* Code to swap in the reloc */
96 #define SWAP_IN_RELOC_OFFSET bfd_h_get_32
97 #define SWAP_OUT_RELOC_OFFSET bfd_h_put_32
98 #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
99 dst->r_stuff[0] = 'S'; \
100 dst->r_stuff[1] = 'C';
105 reloc_howto_type
*howto
;
110 /* Code to turn a r_type into a howto ptr, uses the above howto table
114 rtype2howto (internal
, dst
)
116 struct internal_reloc
*dst
;
121 internal
->howto
= howto_table
+ 0;
124 internal
->howto
= howto_table
+ 1;
127 internal
->howto
= howto_table
+ 2;
130 internal
->howto
= howto_table
+ 3;
133 internal
->howto
= howto_table
+ 4;
136 internal
->howto
= howto_table
+ 5;
139 internal
->howto
= howto_table
+ 6;
142 internal
->howto
= howto_table
+ 7;
145 internal
->howto
= howto_table
+ 8;
148 internal
->howto
= howto_table
+ 9;
151 internal
->howto
= howto_table
+ 10;
154 internal
->howto
= howto_table
+ 11;
157 internal
->howto
= howto_table
+ 12;
160 internal
->howto
= howto_table
+ 13;
163 fprintf (stderr
, "Bad reloc\n");
168 #define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
171 /* Perform any necessaru magic to the addend in a reloc entry */
174 #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
175 cache_ptr->addend = ext_reloc.r_offset;
178 #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
179 reloc_processing(relent, reloc, symbols, abfd, section)
182 reloc_processing (relent
, reloc
, symbols
, abfd
, section
)
184 struct internal_reloc
*reloc
;
189 relent
->address
= reloc
->r_vaddr
;
190 rtype2howto (relent
, reloc
);
192 if (((int) reloc
->r_symndx
) > 0)
194 relent
->sym_ptr_ptr
= symbols
+ obj_convert (abfd
)[reloc
->r_symndx
];
198 relent
->sym_ptr_ptr
= bfd_abs_section_ptr
->symbol_ptr_ptr
;
203 relent
->addend
= reloc
->r_offset
;
205 relent
->address
-= section
->vma
;
206 /* relent->section = 0;*/
211 h8300_reloc16_estimate(abfd
, input_section
, reloc
, shrink
, link_info
)
213 asection
*input_section
;
216 struct bfd_link_info
*link_info
;
222 /* The address of the thing to be relocated will have moved back by
223 the size of the shrink - but we don't change reloc->address here,
224 since we need it to know where the relocation lives in the source
227 /* reloc->address -= shrink; conceptual */
229 bfd_vma address
= reloc
->address
- shrink
;
232 switch (reloc
->howto
->type
)
239 /* Thing is a move one byte */
241 value
= bfd_coff_reloc16_get_value(reloc
, link_info
, input_section
);
246 /* Change the reloc type from 16bit, possible 8 to 8bit
248 reloc
->howto
= reloc
->howto
+ 1;
249 /* The place to relc moves back by one */
250 /* This will be two bytes smaller in the long run */
252 bfd_perform_slip(abfd
, 2, input_section
, address
);
256 /* This is the 24 bit branch which could become an 8 bitter,
257 the relocation points to the first byte of the insn, not the
261 value
= bfd_coff_reloc16_get_value(reloc
, link_info
, input_section
);
263 dot
= input_section
->output_section
->vma
+
264 input_section
->output_offset
+ address
;
266 /* See if the address we're looking at within 127 bytes of where
267 we are, if so then we can use a small branch rather than the
268 jump we were going to */
272 if (-120 < (long)gap
&& (long)gap
< 120 )
275 /* Change the reloc type from 24bit, possible 8 to 8bit
277 reloc
->howto
= reloc
->howto
+ 1;
278 /* This will be two bytes smaller in the long run */
280 bfd_perform_slip(abfd
, 2, input_section
, address
);
286 value
= bfd_coff_reloc16_get_value(reloc
, link_info
, input_section
);
288 dot
= input_section
->output_section
->vma
+
289 input_section
->output_offset
+ address
;
291 /* See if the address we're looking at within 127 bytes of where
292 we are, if so then we can use a small branch rather than the
293 jump we were going to */
295 gap
= value
- (dot
- shrink
);
298 if (-120 < (long)gap
&& (long)gap
< 120 )
301 /* Change the reloc type from 16bit, possible 8 to 8bit
303 reloc
->howto
= reloc
->howto
+ 1;
304 /* The place to relc moves back by one */
306 /* This will be two bytes smaller in the long run */
308 bfd_perform_slip(abfd
, 2, input_section
, address
);
318 /* First phase of a relaxing link */
322 R_MOVB1 R_MOVB2 mov.b with 16bit or 8 bit address
323 R_JMP1 R_JMP2 jmp or pcrel branch
324 R_JMPL1 R_JMPL_B8 24jmp or pcrel branch
325 R_MOVLB1 R_MOVLB2 24 or 8 bit reloc for mov.b
330 h8300_reloc16_extra_cases (abfd
, link_info
, link_order
, reloc
, data
, src_ptr
,
333 struct bfd_link_info
*link_info
;
334 struct bfd_link_order
*link_order
;
337 unsigned int *src_ptr
;
338 unsigned int *dst_ptr
;
340 unsigned int src_address
= *src_ptr
;
341 unsigned int dst_address
= *dst_ptr
;
342 asection
*input_section
= link_order
->u
.indirect
.section
;
344 switch (reloc
->howto
->type
)
346 /* A 24 bit branch which could be a 8 bit pcrel, really pointing to
347 the byte before the 24bit hole, so we can treat it as a 32bit pointer */
350 bfd_vma dot
= link_order
->offset
352 + link_order
->u
.indirect
.section
->output_section
->vma
;
353 int gap
= (bfd_coff_reloc16_get_value (reloc
, link_info
, input_section
)
355 if (gap
> 127 || gap
< -128)
357 if (! ((*link_info
->callbacks
->reloc_overflow
)
358 (link_info
, bfd_asymbol_name (*reloc
->sym_ptr_ptr
),
359 reloc
->howto
->name
, reloc
->addend
, input_section
->owner
,
360 input_section
, reloc
->address
)))
364 bfd_put_8 (abfd
, gap
, data
+ dst_address
);
372 bfd_vma dot
= link_order
->offset
374 + link_order
->u
.indirect
.section
->output_section
->vma
;
375 int gap
= (bfd_coff_reloc16_get_value (reloc
, link_info
, input_section
)
377 if (gap
> 32767 || gap
< -32768)
379 if (! ((*link_info
->callbacks
->reloc_overflow
)
380 (link_info
, bfd_asymbol_name (*reloc
->sym_ptr_ptr
),
381 reloc
->howto
->name
, reloc
->addend
, input_section
->owner
,
382 input_section
, reloc
->address
)))
386 bfd_put_16 (abfd
, gap
, data
+ dst_address
);
395 unsigned int gap
= bfd_coff_reloc16_get_value (reloc
, link_info
,
398 || (gap
>= 0x0000ff00
399 && gap
<= 0x0000ffff)
400 || ( gap
>= 0x00ffff00
401 && gap
<= 0x00ffffff)
402 || ( gap
>= 0xffffff00
403 && gap
<= 0xffffffff))
405 bfd_put_8 (abfd
, gap
, data
+ dst_address
);
411 if (! ((*link_info
->callbacks
->reloc_overflow
)
412 (link_info
, bfd_asymbol_name (*reloc
->sym_ptr_ptr
),
413 reloc
->howto
->name
, reloc
->addend
, input_section
->owner
,
414 input_section
, reloc
->address
)))
420 /* A relword which would have like to have been a pcrel */
422 /* A relword which would like to have been modified but
426 bfd_coff_reloc16_get_value (reloc
, link_info
, input_section
),
433 bfd_coff_reloc16_get_value (reloc
, link_info
, input_section
),
440 /* Special relaxed type, there will be a gap between where we
441 get stuff from and where we put stuff to now
443 for a mov.b @aa:16 -> mov.b @aa:8
444 opcode 0x6a 0x0y offset
447 if (data
[dst_address
- 1] != 0x6a)
449 switch (data
[src_address
] & 0xf0)
453 data
[dst_address
- 1] = (data
[src_address
] & 0xf) | 0x20;
457 data
[dst_address
- 1] = (data
[src_address
] & 0xf) | 0x30;
463 /* the offset must fit ! after all, what was all the relaxing
467 bfd_coff_reloc16_get_value (reloc
, link_info
, input_section
),
470 /* Note the magic - src goes up by two bytes, but dst by only
479 /* Speciial relaxed type */
481 bfd_vma dot
= link_order
->offset
483 + link_order
->u
.indirect
.section
->output_section
->vma
;
485 int gap
= (bfd_coff_reloc16_get_value (reloc
, link_info
, input_section
)
488 if ((gap
& ~0xff) != 0 && ((gap
& 0xff00) != 0xff00))
491 bfd_put_8 (abfd
, gap
, data
+ dst_address
);
493 switch (data
[dst_address
- 1])
497 bfd_put_8 (abfd
, 0x55, data
+ dst_address
- 1);
501 bfd_put_8 (abfd
, 0x40, data
+ dst_address
- 1);
514 case R_JMPL_B8
: /* 24 bit branch which is now 8 bits */
516 /* Speciial relaxed type */
518 bfd_vma dot
= link_order
->offset
520 + link_order
->u
.indirect
.section
->output_section
->vma
;
522 int gap
= (bfd_coff_reloc16_get_value (reloc
, link_info
, input_section
)
525 if ((gap
& ~0xff) != 0 && ((gap
& 0xff00) != 0xff00))
528 switch (data
[src_address
])
532 bfd_put_8 (abfd
, 0x55, data
+ dst_address
);
536 bfd_put_8 (abfd
, 0x40, data
+ dst_address
);
540 bfd_put_8 (abfd
, 0xde, data
+ dst_address
);
544 bfd_put_8 (abfd
, gap
, data
+ dst_address
+ 1);
553 int v
= bfd_coff_reloc16_get_value (reloc
, link_info
, input_section
);
554 int o
= bfd_get_32 (abfd
, data
+ src_address
);
555 v
= (v
& 0x00ffffff) | (o
& 0xff000000);
556 bfd_put_32 (abfd
, v
, data
+ dst_address
);
564 /* A 24 bit mov which could be an 8 bit move, really pointing to
565 the byte before the 24bit hole, so we can treat it as a 32bit pointer */
568 int v
= bfd_coff_reloc16_get_value (reloc
, link_info
, input_section
);
569 int o
= bfd_get_32 (abfd
, data
+ dst_address
);
570 v
= (v
& 0x00ffffff) | (o
& 0xff000000);
571 bfd_put_32 (abfd
, v
, data
+ dst_address
);
583 *src_ptr
= src_address
;
584 *dst_ptr
= dst_address
;
588 #define coff_reloc16_extra_cases h8300_reloc16_extra_cases
589 #define coff_reloc16_estimate h8300_reloc16_estimate
591 #include "coffcode.h"
594 #undef coff_bfd_get_relocated_section_contents
595 #undef coff_bfd_relax_section
596 #define coff_bfd_get_relocated_section_contents \
597 bfd_coff_reloc16_get_relocated_section_contents
598 #define coff_bfd_relax_section bfd_coff_reloc16_relax_section
602 const bfd_target h8300coff_vec
=
604 "coff-h8300", /* name */
605 bfd_target_coff_flavour
,
606 true, /* data byte order is big */
607 true, /* header byte order is big */
609 (HAS_RELOC
| EXEC_P
| /* object flags */
610 HAS_LINENO
| HAS_DEBUG
|
611 HAS_SYMS
| HAS_LOCALS
| WP_TEXT
| BFD_IS_RELAXABLE
),
612 (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
), /* section flags */
613 '_', /* leading char */
614 '/', /* ar_pad_char */
615 15, /* ar_max_namelen */
616 1, /* minimum section alignment */
617 bfd_getb64
, bfd_getb_signed_64
, bfd_putb64
,
618 bfd_getb32
, bfd_getb_signed_32
, bfd_putb32
,
619 bfd_getb16
, bfd_getb_signed_16
, bfd_putb16
, /* data */
620 bfd_getb64
, bfd_getb_signed_64
, bfd_putb64
,
621 bfd_getb32
, bfd_getb_signed_32
, bfd_putb32
,
622 bfd_getb16
, bfd_getb_signed_16
, bfd_putb16
, /* hdrs */
624 {_bfd_dummy_target
, coff_object_p
, /* bfd_check_format */
625 bfd_generic_archive_p
, _bfd_dummy_target
},
626 {bfd_false
, coff_mkobject
, _bfd_generic_mkarchive
, /* bfd_set_format */
628 {bfd_false
, coff_write_object_contents
, /* bfd_write_contents */
629 _bfd_write_archive_contents
, bfd_false
},
631 BFD_JUMP_TABLE_GENERIC (coff
),
632 BFD_JUMP_TABLE_COPY (coff
),
633 BFD_JUMP_TABLE_CORE (_bfd_nocore
),
634 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff
),
635 BFD_JUMP_TABLE_SYMBOLS (coff
),
636 BFD_JUMP_TABLE_RELOCS (coff
),
637 BFD_JUMP_TABLE_WRITE (coff
),
638 BFD_JUMP_TABLE_LINK (coff
),
639 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),