|
|
|
@ -192,18 +192,18 @@ h8300_coff_link_hash_table_create (abfd) |
|
|
|
return &ret->root.root; |
|
|
|
} |
|
|
|
|
|
|
|
/* special handling for H8/300 relocs.
|
|
|
|
/* Special handling for H8/300 relocs.
|
|
|
|
We only come here for pcrel stuff and return normally if not an -r link. |
|
|
|
When doing -r, we can't do any arithmetic for the pcrel stuff, because |
|
|
|
the code in reloc.c assumes that we can manipulate the targets of |
|
|
|
the pcrel branches. This isn't so, since the H8/300 can do relaxing, |
|
|
|
which means that the gap after the instruction may not be enough to |
|
|
|
contain the offset required for the branch, so we have to use the only |
|
|
|
the addend until the final link */ |
|
|
|
the addend until the final link. */ |
|
|
|
|
|
|
|
static bfd_reloc_status_type |
|
|
|
special (abfd, reloc_entry, symbol, data, input_section, output_bfd, |
|
|
|
error_message) |
|
|
|
error_message) |
|
|
|
bfd *abfd ATTRIBUTE_UNUSED; |
|
|
|
arelent *reloc_entry ATTRIBUTE_UNUSED; |
|
|
|
asymbol *symbol ATTRIBUTE_UNUSED; |
|
|
|
@ -253,8 +253,7 @@ static reloc_howto_type howto_table[] = |
|
|
|
HOWTO (R_JMP_DEL, 0, 0, 8, true, 0, complain_overflow_signed, special, "Deleted jump", false, 0x000000ff, 0x000000ff, true), |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/* Turn a howto into a reloc number */ |
|
|
|
/* Turn a howto into a reloc number. */ |
|
|
|
|
|
|
|
#define SELECT_RELOC(x,howto) \ |
|
|
|
{ x.r_type = select_reloc(howto); } |
|
|
|
@ -263,16 +262,13 @@ static reloc_howto_type howto_table[] = |
|
|
|
#define H8300 1 /* Customize coffcode.h */ |
|
|
|
#define __A_MAGIC_SET__ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Code to swap in the reloc */ |
|
|
|
/* Code to swap in the reloc. */ |
|
|
|
#define SWAP_IN_RELOC_OFFSET bfd_h_get_32 |
|
|
|
#define SWAP_OUT_RELOC_OFFSET bfd_h_put_32 |
|
|
|
#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \ |
|
|
|
dst->r_stuff[0] = 'S'; \ |
|
|
|
dst->r_stuff[1] = 'C'; |
|
|
|
|
|
|
|
|
|
|
|
static int |
|
|
|
select_reloc (howto) |
|
|
|
reloc_howto_type *howto; |
|
|
|
@ -280,8 +276,7 @@ select_reloc (howto) |
|
|
|
return howto->type; |
|
|
|
} |
|
|
|
|
|
|
|
/* Code to turn a r_type into a howto ptr, uses the above howto table
|
|
|
|
*/ |
|
|
|
/* Code to turn a r_type into a howto ptr, uses the above howto table. */ |
|
|
|
|
|
|
|
static void |
|
|
|
rtype2howto (internal, dst) |
|
|
|
@ -358,24 +353,21 @@ rtype2howto (internal, dst) |
|
|
|
|
|
|
|
#define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry) |
|
|
|
|
|
|
|
|
|
|
|
/* Perform any necessary magic to the addend in a reloc entry */ |
|
|
|
|
|
|
|
/* Perform any necessary magic to the addend in a reloc entry. */ |
|
|
|
|
|
|
|
#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \ |
|
|
|
cache_ptr->addend = ext_reloc.r_offset; |
|
|
|
|
|
|
|
|
|
|
|
#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \ |
|
|
|
reloc_processing(relent, reloc, symbols, abfd, section) |
|
|
|
|
|
|
|
static void |
|
|
|
reloc_processing (relent, reloc, symbols, abfd, section) |
|
|
|
arelent * relent; |
|
|
|
arelent *relent; |
|
|
|
struct internal_reloc *reloc; |
|
|
|
asymbol ** symbols; |
|
|
|
bfd * abfd; |
|
|
|
asection * section; |
|
|
|
asymbol **symbols; |
|
|
|
bfd *abfd; |
|
|
|
asection *section; |
|
|
|
{ |
|
|
|
relent->address = reloc->r_vaddr; |
|
|
|
rtype2howto (relent, reloc); |
|
|
|
@ -389,12 +381,12 @@ reloc_processing (relent, reloc, symbols, abfd, section) |
|
|
|
relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
relent->addend = reloc->r_offset; |
|
|
|
|
|
|
|
relent->address -= section->vma; |
|
|
|
/* relent->section = 0;*/ |
|
|
|
#if 0 |
|
|
|
relent->section = 0; |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
static boolean |
|
|
|
@ -410,7 +402,7 @@ h8300_symbol_address_p (abfd, input_section, address) |
|
|
|
|
|
|
|
/* Search all the symbols for one in INPUT_SECTION with
|
|
|
|
address ADDRESS. */ |
|
|
|
while (*s) |
|
|
|
while (*s) |
|
|
|
{ |
|
|
|
asymbol *p = *s; |
|
|
|
if (p->section == input_section |
|
|
|
@ -419,11 +411,10 @@ h8300_symbol_address_p (abfd, input_section, address) |
|
|
|
+ p->value) == address) |
|
|
|
return true; |
|
|
|
s++; |
|
|
|
} |
|
|
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* If RELOC represents a relaxable instruction/reloc, change it into
|
|
|
|
the relaxed reloc, notify the linker that symbol addresses |
|
|
|
have changed (bfd_perform_slip) and return how much the current |
|
|
|
@ -433,14 +424,14 @@ h8300_symbol_address_p (abfd, input_section, address) |
|
|
|
in the howto table. This needs to be fixed. */ |
|
|
|
|
|
|
|
static int |
|
|
|
h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info) |
|
|
|
h8300_reloc16_estimate (abfd, input_section, reloc, shrink, link_info) |
|
|
|
bfd *abfd; |
|
|
|
asection *input_section; |
|
|
|
arelent *reloc; |
|
|
|
unsigned int shrink; |
|
|
|
struct bfd_link_info *link_info; |
|
|
|
{ |
|
|
|
bfd_vma value; |
|
|
|
bfd_vma value; |
|
|
|
bfd_vma dot; |
|
|
|
bfd_vma gap; |
|
|
|
static asection *last_input_section = NULL; |
|
|
|
@ -458,13 +449,12 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info) |
|
|
|
/* Only examine the relocs which might be relaxable. */ |
|
|
|
switch (reloc->howto->type) |
|
|
|
{ |
|
|
|
|
|
|
|
/* This is the 16/24 bit absolute branch which could become an 8 bit
|
|
|
|
pc-relative branch. */ |
|
|
|
case R_JMP1: |
|
|
|
case R_JMPL1: |
|
|
|
/* Get the address of the target of this branch. */ |
|
|
|
value = bfd_coff_reloc16_get_value(reloc, link_info, input_section); |
|
|
|
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); |
|
|
|
|
|
|
|
/* Get the address of the next instruction (not the reloc). */ |
|
|
|
dot = (input_section->output_section->vma |
|
|
|
@ -475,13 +465,12 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info) |
|
|
|
|
|
|
|
/* Compute the distance from this insn to the branch target. */ |
|
|
|
gap = value - dot; |
|
|
|
|
|
|
|
|
|
|
|
/* If the distance is within -128..+128 inclusive, then we can relax
|
|
|
|
this jump. +128 is valid since the target will move two bytes |
|
|
|
closer if we do relax this branch. */ |
|
|
|
if ((int)gap >= -128 && (int)gap <= 128 ) |
|
|
|
{ |
|
|
|
|
|
|
|
/* It's possible we may be able to eliminate this branch entirely;
|
|
|
|
if the previous instruction is a branch around this instruction, |
|
|
|
and there's no label at this instruction, then we can reverse |
|
|
|
@ -505,7 +494,7 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info) |
|
|
|
|
|
|
|
if (last_value == dot + 2 |
|
|
|
&& last_reloc->address + 1 == reloc->address |
|
|
|
&& ! h8300_symbol_address_p (abfd, input_section, dot - 2)) |
|
|
|
&& !h8300_symbol_address_p (abfd, input_section, dot - 2)) |
|
|
|
{ |
|
|
|
reloc->howto = howto_table + 19; |
|
|
|
last_reloc->howto = howto_table + 18; |
|
|
|
@ -518,11 +507,11 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info) |
|
|
|
} |
|
|
|
|
|
|
|
/* Change the reloc type. */ |
|
|
|
reloc->howto = reloc->howto + 1; |
|
|
|
reloc->howto = reloc->howto + 1; |
|
|
|
|
|
|
|
/* This shrinks this section by two bytes. */ |
|
|
|
shrink += 2; |
|
|
|
bfd_perform_slip(abfd, 2, input_section, address); |
|
|
|
bfd_perform_slip (abfd, 2, input_section, address); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
@ -531,12 +520,12 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info) |
|
|
|
case R_PCRWORD: |
|
|
|
/* Get the address of the target of this branch, add one to the value
|
|
|
|
because the addend field in PCrel jumps is off by -1. */ |
|
|
|
value = bfd_coff_reloc16_get_value(reloc, link_info, input_section) + 1; |
|
|
|
|
|
|
|
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section) + 1; |
|
|
|
|
|
|
|
/* Get the address of the next instruction if we were to relax. */ |
|
|
|
dot = input_section->output_section->vma + |
|
|
|
input_section->output_offset + address; |
|
|
|
|
|
|
|
|
|
|
|
/* Compute the distance from this insn to the branch target. */ |
|
|
|
gap = value - dot; |
|
|
|
|
|
|
|
@ -550,7 +539,7 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info) |
|
|
|
|
|
|
|
/* This shrinks this section by two bytes. */ |
|
|
|
shrink += 2; |
|
|
|
bfd_perform_slip(abfd, 2, input_section, address); |
|
|
|
bfd_perform_slip (abfd, 2, input_section, address); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
@ -558,7 +547,7 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info) |
|
|
|
become an 8 bit absolute address if it's in the right range. */ |
|
|
|
case R_MOV16B1: |
|
|
|
/* Get the address of the data referenced by this mov.b insn. */ |
|
|
|
value = bfd_coff_reloc16_get_value(reloc, link_info, input_section); |
|
|
|
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); |
|
|
|
|
|
|
|
/* The address is in 0xff00..0xffff inclusive on the h8300 or
|
|
|
|
0xffff00..0xffffff inclusive on the h8300h, then we can |
|
|
|
@ -576,7 +565,7 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info) |
|
|
|
|
|
|
|
/* This shrinks this section by two bytes. */ |
|
|
|
shrink += 2; |
|
|
|
bfd_perform_slip(abfd, 2, input_section, address); |
|
|
|
bfd_perform_slip (abfd, 2, input_section, address); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
@ -585,7 +574,7 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info) |
|
|
|
and try to relax it into a 16bit absolute. */ |
|
|
|
case R_MOV24B1: |
|
|
|
/* Get the address of the data referenced by this mov.b insn. */ |
|
|
|
value = bfd_coff_reloc16_get_value(reloc, link_info, input_section); |
|
|
|
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); |
|
|
|
|
|
|
|
/* The address is in 0xffff00..0xffffff inclusive on the h8300h,
|
|
|
|
then we can relax this mov.b */ |
|
|
|
@ -599,7 +588,7 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info) |
|
|
|
|
|
|
|
/* This shrinks this section by four bytes. */ |
|
|
|
shrink += 4; |
|
|
|
bfd_perform_slip(abfd, 4, input_section, address); |
|
|
|
bfd_perform_slip (abfd, 4, input_section, address); |
|
|
|
|
|
|
|
/* Done with this reloc. */ |
|
|
|
break; |
|
|
|
@ -612,7 +601,7 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info) |
|
|
|
become an 16 bit absolute address if it's in the right range. */ |
|
|
|
case R_MOVL1: |
|
|
|
/* Get the address of the data referenced by this mov insn. */ |
|
|
|
value = bfd_coff_reloc16_get_value(reloc, link_info, input_section); |
|
|
|
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); |
|
|
|
|
|
|
|
/* If this address is in 0x0000..0x7fff inclusive or
|
|
|
|
0xff8000..0xffffff inclusive, then it can be relaxed. */ |
|
|
|
@ -623,13 +612,13 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info) |
|
|
|
|
|
|
|
/* This shrinks this section by two bytes. */ |
|
|
|
shrink += 2; |
|
|
|
bfd_perform_slip(abfd, 2, input_section, address); |
|
|
|
bfd_perform_slip (abfd, 2, input_section, address); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
/* No other reloc types represent relaxing opportunities. */ |
|
|
|
default: |
|
|
|
break; |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
last_reloc = reloc; |
|
|
|
@ -637,7 +626,6 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info) |
|
|
|
return shrink; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Handle relocations for the H8/300, including relocs for relaxed
|
|
|
|
instructions. |
|
|
|
|
|
|
|
@ -659,18 +647,17 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr, |
|
|
|
asection *input_section = link_order->u.indirect.section; |
|
|
|
bfd_vma value; |
|
|
|
bfd_vma dot; |
|
|
|
int gap,tmp; |
|
|
|
int gap, tmp; |
|
|
|
|
|
|
|
switch (reloc->howto->type) |
|
|
|
{ |
|
|
|
|
|
|
|
/* Generic 8bit pc-relative relocation. */ |
|
|
|
case R_PCRBYTE: |
|
|
|
/* Get the address of the target of this branch. */ |
|
|
|
value = bfd_coff_reloc16_get_value(reloc, link_info, input_section); |
|
|
|
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); |
|
|
|
|
|
|
|
dot = (link_order->offset |
|
|
|
+ dst_address |
|
|
|
dot = (link_order->offset |
|
|
|
+ dst_address |
|
|
|
+ link_order->u.indirect.section->output_section->vma); |
|
|
|
|
|
|
|
gap = value - dot; |
|
|
|
@ -698,7 +685,7 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr, |
|
|
|
/* Generic 16bit pc-relative relocation. */ |
|
|
|
case R_PCRWORD: |
|
|
|
/* Get the address of the target of this branch. */ |
|
|
|
value = bfd_coff_reloc16_get_value(reloc, link_info, input_section); |
|
|
|
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); |
|
|
|
|
|
|
|
/* Get the address of the instruction (not the reloc). */ |
|
|
|
dot = (link_order->offset |
|
|
|
@ -761,7 +748,7 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr, |
|
|
|
case R_MOV16B1: |
|
|
|
case R_JMP1: |
|
|
|
case R_RELWORD: |
|
|
|
value = bfd_coff_reloc16_get_value(reloc, link_info, input_section); |
|
|
|
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); |
|
|
|
bfd_put_16 (abfd, value, data + dst_address); |
|
|
|
dst_address += 2; |
|
|
|
src_address += 2; |
|
|
|
@ -772,7 +759,7 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr, |
|
|
|
case R_MOVL1: |
|
|
|
case R_RELLONG: |
|
|
|
/* Get the address of the target of this branch. */ |
|
|
|
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section), |
|
|
|
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); |
|
|
|
bfd_put_32 (abfd, value, data + dst_address); |
|
|
|
dst_address += 4; |
|
|
|
src_address += 4; |
|
|
|
@ -961,13 +948,13 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr, |
|
|
|
abort (); |
|
|
|
|
|
|
|
/* Fix up the opcode. */ |
|
|
|
switch (data[src_address-1] & 0xf0) |
|
|
|
switch (data[src_address - 1] & 0xf0) |
|
|
|
{ |
|
|
|
case 0x00: |
|
|
|
data[dst_address - 2] = (data[src_address-1] & 0xf) | 0x20; |
|
|
|
data[dst_address - 2] = (data[src_address - 1] & 0xf) | 0x20; |
|
|
|
break; |
|
|
|
case 0x80: |
|
|
|
data[dst_address - 2] = (data[src_address-1] & 0xf) | 0x30; |
|
|
|
data[dst_address - 2] = (data[src_address - 1] & 0xf) | 0x30; |
|
|
|
break; |
|
|
|
default: |
|
|
|
abort (); |
|
|
|
@ -986,13 +973,13 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr, |
|
|
|
abort (); |
|
|
|
|
|
|
|
/* Fix up the opcode. */ |
|
|
|
switch (data[src_address-1] & 0xf0) |
|
|
|
switch (data[src_address - 1] & 0xf0) |
|
|
|
{ |
|
|
|
case 0x20: |
|
|
|
data[dst_address - 2] = (data[src_address-1] & 0xf) | 0x20; |
|
|
|
data[dst_address - 2] = (data[src_address - 1] & 0xf) | 0x20; |
|
|
|
break; |
|
|
|
case 0xa0: |
|
|
|
data[dst_address - 2] = (data[src_address-1] & 0xf) | 0x30; |
|
|
|
data[dst_address - 2] = (data[src_address - 1] & 0xf) | 0x30; |
|
|
|
break; |
|
|
|
default: |
|
|
|
abort (); |
|
|
|
@ -1004,10 +991,10 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr, |
|
|
|
|
|
|
|
case R_BCC_INV: |
|
|
|
/* Get the address of the target of this branch. */ |
|
|
|
value = bfd_coff_reloc16_get_value(reloc, link_info, input_section); |
|
|
|
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); |
|
|
|
|
|
|
|
dot = (link_order->offset |
|
|
|
+ dst_address |
|
|
|
dot = (link_order->offset |
|
|
|
+ dst_address |
|
|
|
+ link_order->u.indirect.section->output_section->vma) + 1; |
|
|
|
|
|
|
|
gap = value - dot; |
|
|
|
@ -1103,7 +1090,7 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr, |
|
|
|
|
|
|
|
strcpy (new_name, name); |
|
|
|
sprintf (new_name + strlen (name), "_%08x", |
|
|
|
(int)symbol->section); |
|
|
|
(int) symbol->section); |
|
|
|
name = new_name; |
|
|
|
} |
|
|
|
|
|
|
|
@ -1162,7 +1149,6 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr, |
|
|
|
*dst_ptr = dst_address; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Routine for the h8300 linker.
|
|
|
|
|
|
|
|
This routine is necessary to handle the special R_MEM_INDIRECT |
|
|
|
@ -1175,7 +1161,7 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr, |
|
|
|
selected static symbols to the bfd linker hash table. */ |
|
|
|
|
|
|
|
static boolean |
|
|
|
h8300_bfd_link_add_symbols(abfd, info) |
|
|
|
h8300_bfd_link_add_symbols (abfd, info) |
|
|
|
bfd *abfd; |
|
|
|
struct bfd_link_info *info; |
|
|
|
{ |
|
|
|
@ -1239,7 +1225,7 @@ h8300_bfd_link_add_symbols(abfd, info) |
|
|
|
if (reloc_size <= 0) |
|
|
|
continue; |
|
|
|
|
|
|
|
relocs = (arelent **)bfd_malloc ((size_t)reloc_size); |
|
|
|
relocs = (arelent **) bfd_malloc ((size_t) reloc_size); |
|
|
|
if (!relocs) |
|
|
|
return false; |
|
|
|
|
|
|
|
@ -1282,7 +1268,7 @@ h8300_bfd_link_add_symbols(abfd, info) |
|
|
|
|
|
|
|
strcpy (new_name, name); |
|
|
|
sprintf (new_name + strlen (name), "_%08x", |
|
|
|
(int)symbol->section); |
|
|
|
(int) symbol->section); |
|
|
|
name = new_name; |
|
|
|
} |
|
|
|
|
|
|
|
@ -1342,12 +1328,10 @@ h8300_bfd_link_add_symbols(abfd, info) |
|
|
|
#define COFF_LONG_FILENAMES |
|
|
|
#include "coffcode.h" |
|
|
|
|
|
|
|
|
|
|
|
#undef coff_bfd_get_relocated_section_contents |
|
|
|
#undef coff_bfd_relax_section |
|
|
|
#define coff_bfd_get_relocated_section_contents \ |
|
|
|
bfd_coff_reloc16_get_relocated_section_contents |
|
|
|
#define coff_bfd_relax_section bfd_coff_reloc16_relax_section |
|
|
|
|
|
|
|
|
|
|
|
CREATE_BIG_COFF_TARGET_VEC (h8300coff_vec, "coff-h8300", BFD_IS_RELAXABLE, 0, '_', NULL) |
|
|
|
|