* coff-h8300.c (h8300_reloc16_estimate): Fix many minor spacing

problems.
        (h8300_reloc16_estimate, cases R_JMP1, R_JMP2): Adjust "dot"
        correctly for the two variants.  Allow relaxing if the target
        is 128 bytes away since after relaxation it'll be 126 bytes away.
        (h8300_reloc16_estimate, case R_PCRWORD): Correctly adjust
        "dot" and "value".  Allow relaxing if the target is 128 bytes
        away since after relaxation it'll be 126 bytes away.
        * reloc16.c (bfd_coff_reloc16_relax_section): Keep relaxing
        the given section until nothing changes.
Improving corner case relaxing for jmp:16->bra:8, jmp:24->bra:8 and
bCC:16->bCC:8.

Re-relax a section if something changes; more relaxing opportunities
may be available.
This commit is contained in:
Jeff Law 1996-06-09 22:38:09 +00:00
parent f98286385f
commit fd7c5d73ce
1 changed files with 440 additions and 352 deletions

View File

@ -225,17 +225,14 @@ static reloc_howto_type howto_table[] =
HOWTO (R_PCRBYTE, 0, 0, 8, true, 0, complain_overflow_signed, special, "DISP8", false, 0x000000ff, 0x000000ff, true),
HOWTO (R_PCRWORD, 0, 1, 16, true, 0, complain_overflow_signed, special, "DISP16", false, 0x0000ffff, 0x0000ffff, true),
HOWTO (R_PCRLONG, 0, 2, 32, true, 0, complain_overflow_signed, special, "DISP32", false, 0xffffffff, 0xffffffff, true),
HOWTO (R_MOVB1, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "16/8", false, 0x0000ffff, 0x0000ffff, false),
HOWTO (R_MOVB2, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "8/16", false, 0x0000ffff, 0x0000ffff, false),
HOWTO (R_MOV16B1, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "relaxable mov.b:16", false, 0x0000ffff, 0x0000ffff, false),
HOWTO (R_MOV16B2, 0, 1, 8, false, 0, complain_overflow_bitfield, special, "relaxed mov.b:16", false, 0x000000ff, 0x000000ff, false),
HOWTO (R_JMP1, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "16/pcrel", false, 0x0000ffff, 0x0000ffff, false),
HOWTO (R_JMP2, 0, 0, 8, false, 0, complain_overflow_bitfield, special, "pcrecl/16", false, 0x000000ff, 0x000000ff, false),
HOWTO (R_JMPL1, 0, 2, 32, false, 0, complain_overflow_bitfield, special, "24/pcrell", false, 0x00ffffff, 0x00ffffff, false),
HOWTO (R_JMPL_B8, 0, 0, 8, false, 0, complain_overflow_bitfield, special, "pc8/24", false, 0x000000ff, 0x000000ff, false),
HOWTO (R_MOVLB1, 0, 1, 16, false, 0, complain_overflow_bitfield,special, "24/8", false, 0x0000ffff, 0x0000ffff, false),
HOWTO (R_MOVLB2, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "8/24", false, 0x0000ffff, 0x0000ffff, false),
HOWTO (R_JMPL2, 0, 0, 8, false, 0, complain_overflow_bitfield, special, "pc8/24", false, 0x000000ff, 0x000000ff, false),
HOWTO (R_MOV24B1, 0, 1, 32, false, 0, complain_overflow_bitfield, special, "relaxable mov.b:24", false, 0xffffffff, 0xffffffff, false),
HOWTO (R_MOV24B2, 0, 1, 8, false, 0, complain_overflow_bitfield, special, "relaxed mov.b:24", false, 0x0000ffff, 0x0000ffff, false),
/* An indirect reference to a function. This causes the function's address
to be added to the function vector in lo-mem and puts the address of
@ -244,7 +241,12 @@ static reloc_howto_type howto_table[] =
/* Internal reloc for relaxing. This is created when a 16bit pc-relative
branch is turned into an 8bit pc-relative branch. */
HOWTO (R_PCRWORD_B, 0, 0, 8, true, 0, complain_overflow_bitfield, special, "pcrecl/16", false, 0x000000ff, 0x000000ff, false),
HOWTO (R_PCRWORD_B, 0, 0, 8, true, 0, complain_overflow_bitfield, special, "relaxed bCC:16", false, 0x000000ff, 0x000000ff, false),
HOWTO (R_MOVL1, 0, 2, 32, false, 0, complain_overflow_bitfield,special, "32/24 relaxable move", false, 0xffffffff, 0xffffffff, false),
HOWTO (R_MOVL2, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "32/24 relaxed move", false, 0x0000ffff, 0x0000ffff, false),
};
@ -302,10 +304,10 @@ rtype2howto (internal, dst)
case R_PCRLONG:
internal->howto = howto_table + 5;
break;
case R_MOVB1:
case R_MOV16B1:
internal->howto = howto_table + 6;
break;
case R_MOVB2:
case R_MOV16B2:
internal->howto = howto_table + 7;
break;
case R_JMP1:
@ -317,13 +319,13 @@ rtype2howto (internal, dst)
case R_JMPL1:
internal->howto = howto_table + 10;
break;
case R_JMPL_B8:
case R_JMPL2:
internal->howto = howto_table + 11;
break;
case R_MOVLB1:
case R_MOV24B1:
internal->howto = howto_table + 12;
break;
case R_MOVLB2:
case R_MOV24B2:
internal->howto = howto_table + 13;
break;
case R_MEM_INDIRECT:
@ -332,6 +334,12 @@ rtype2howto (internal, dst)
case R_PCRWORD_B:
internal->howto = howto_table + 15;
break;
case R_MOVL1:
internal->howto = howto_table + 16;
break;
case R_MOVL2:
internal->howto = howto_table + 17;
break;
default:
abort ();
break;
@ -379,6 +387,13 @@ reloc_processing (relent, reloc, symbols, abfd, section)
/* relent->section = 0;*/
}
/* 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
section has shrunk by.
FIXME: Much of this code has knowledge of the ordering of entries
in the howto table. This needs to be fixed. */
static int
h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info)
@ -393,142 +408,158 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info)
bfd_vma gap;
/* The address of the thing to be relocated will have moved back by
the size of the shrink - but we don't change reloc->address here,
since we need it to know where the relocation lives in the source
uncooked section */
/* reloc->address -= shrink; conceptual */
the size of the shrink - but we don't change reloc->address here,
since we need it to know where the relocation lives in the source
uncooked section. */
bfd_vma address = reloc->address - shrink;
/* Only examine the relocs which might be relaxable. */
switch (reloc->howto->type)
{
case R_MOVB2:
case R_JMP2:
case R_PCRWORD_B:
shrink+=2;
break;
/* Thing is a move one byte */
case R_MOVB1:
value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
if (value >= 0xff00)
{
/* Change the reloc type from 16bit, possible 8 to 8bit
possible 16 */
reloc->howto = reloc->howto + 1;
/* The place to relc moves back by one */
/* This will be two bytes smaller in the long run */
shrink +=2 ;
bfd_perform_slip(abfd, 2, input_section, address);
}
break;
/* This is the 24 bit branch which could become an 8 bitter,
the relocation points to the first byte of the insn, not the
actual data */
case R_JMPL1:
value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
dot = input_section->output_section->vma +
input_section->output_offset + address;
/* See if the address we're looking at within 127 bytes of where
we are, if so then we can use a small branch rather than the
jump we were going to */
gap = value - dot ;
if (-120 < (long)gap && (long)gap < 120 )
{
/* Change the reloc type from 24bit, possible 8 to 8bit
possible 32 */
reloc->howto = reloc->howto + 1;
/* This will be two bytes smaller in the long run */
shrink +=2 ;
bfd_perform_slip(abfd, 2, input_section, address);
}
break;
/* 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);
/* Get the address of the next instruction (not the reloc). */
dot = (input_section->output_section->vma
+ input_section->output_offset + address);
/* Adjust for R_JMP1 vs R_JMPL1. */
dot += (reloc->howto->type == R_JMP1 ? 1 : 2);
/* 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
this jump. */
if ((int)gap >= -128 && (int)gap <= 128 )
{
/* Change the reloc type. */
reloc->howto = reloc->howto + 1;
/* This shrinks this section by two bytes. */
shrink += 2;
bfd_perform_slip(abfd, 2, input_section, address);
}
break;
/* This is the 16 bit pc-relative branch which could become an 8 bit
pc-relative branch. */
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;
/* Get the address of the next instruction if we were to relax. */
dot = input_section->output_section->vma +
input_section->output_offset + address;
/* See if the address we're looking at within 127 bytes of where
we are, if so then we can use a small branch rather than the
jump we were going to */
/* Compute the distance from this insn to the branch target. */
gap = value - dot;
gap = value - (dot - shrink);
if (-120 < (long)gap && (long)gap < 120 )
/* 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 )
{
/* Change the reloc type from 16bit, possible 8 to 8bit
possible 16 */
reloc->howto = reloc->howto + 1;
/* The place to relc moves back by one */
/* This will be two bytes smaller in the long run */
shrink +=2 ;
bfd_perform_slip(abfd, 2, input_section, address);
}
break;
case R_PCRWORD:
value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
dot = input_section->output_section->vma +
input_section->output_offset + address - 2;
/* See if the address we're looking at within 127 bytes of where
we are, if so then we can use a small branch rather than the
jump we were going to */
gap = value - (dot - shrink);
if (-120 < (long)gap && (long)gap < 120 )
{
/* Change the reloc type from 16bit, possible 8 to 8bit
possible 16 */
/* Change the reloc type. */
reloc->howto = howto_table + 15;
/* The place to relc moves back by one */
/* This will be two bytes smaller in the long run */
shrink +=2 ;
/* This shrinks this section by two bytes. */
shrink += 2;
bfd_perform_slip(abfd, 2, input_section, address);
}
break;
/* This is a 16 bit absolute address in a mov.b insn, which can
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);
/* The address is in 0xff00..0xffff inclusive on the h8300 or
0xffff00..0xffffff inclusive on the h8300h, then we can
relax this mov.b */
if ((bfd_get_mach (abfd) == bfd_mach_h8300
&& value >= 0xff00
&& value <= 0xffff)
|| (bfd_get_mach (abfd) == bfd_mach_h8300h
&& value >= 0xffff00
&& value <= 0xffffff))
{
/* Change the reloc type. */
reloc->howto = reloc->howto + 1;
/* This shrinks this section by two bytes. */
shrink += 2;
bfd_perform_slip(abfd, 2, input_section, address);
}
break;
/* Similarly for a 24 bit absolute address in a mov.b. Note that
if we can't relax this into an 8 bit absolute, we'll fall through
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);
/* The address is in 0xffff00..0xffffff inclusive on the h8300h,
then we can relax this mov.b */
if (bfd_get_mach (abfd) == bfd_mach_h8300h
&& value >= 0xffff00
&& value <= 0xffffff)
{
/* Change the reloc type. */
reloc->howto = reloc->howto + 1;
/* This shrinks this section by four bytes. */
shrink += 4;
bfd_perform_slip(abfd, 4, input_section, address);
/* Done with this reloc. */
break;
}
/* FALLTHROUGH and try to turn the 32/24 bit reloc into a 16 bit
reloc. */
/* This is a 24/32 bit absolute address in a mov insn, which can
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);
/* If this address is in 0x0000..0x7fff inclusive or
0xff8000..0xffffff inclusive, then it can be relaxed. */
if (value <= 0x7fff || value >= 0xff8000)
{
/* Change the reloc type. */
reloc->howto = howto_table + 17;
/* This shrinks this section by two bytes. */
shrink += 2;
bfd_perform_slip(abfd, 2, input_section, address);
}
break;
/* No other reloc types represent relaxing opportunities. */
default:
break;
}
return shrink;
}
/* First phase of a relaxing link */
/* Reloc types
large small
R_MOVB1 R_MOVB2 mov.b with 16bit or 8 bit address
R_JMP1 R_JMP2 jmp or pcrel branch
R_JMPL1 R_JMPL_B8 24jmp or pcrel branch
R_MOVLB1 R_MOVLB2 24 or 8 bit reloc for mov.b
R_PCRWORD R_PCRWORD_B 8 bit pcrel branch from 16bit pcrel
branch.
*/
/* Handle relocations for the H8/300, including relocs for relaxed
instructions.
FIXME: Not all relocations check for overflow! */
static void
h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
@ -544,288 +575,345 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
unsigned int src_address = *src_ptr;
unsigned int dst_address = *dst_ptr;
asection *input_section = link_order->u.indirect.section;
bfd_vma value;
bfd_vma dot;
int gap,tmp;
switch (reloc->howto->type)
{
/* A 24 bit branch which could be a 8 bit pcrel, really pointing to
the byte before the 24bit hole, so we can treat it as a 32bit pointer */
/* Generic 8bit pc-relative relocation. */
case R_PCRBYTE:
{
bfd_vma dot = link_order->offset
+ dst_address
+ link_order->u.indirect.section->output_section->vma;
int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
- dot);
if (gap > 127 || gap < -128)
{
if (! ((*link_info->callbacks->reloc_overflow)
(link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
reloc->howto->name, reloc->addend, input_section->owner,
input_section, reloc->address)))
abort ();
}
gap &= ~1;
bfd_put_8 (abfd, gap, data + dst_address);
dst_address++;
src_address++;
/* Get the address of the target of this branch. */
value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
break;
}
case R_PCRWORD:
{
bfd_vma dot = link_order->offset
+ dst_address
+ link_order->u.indirect.section->output_section->vma;
int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
- dot) - 1;
if (gap > 32767 || gap < -32768)
{
if (! ((*link_info->callbacks->reloc_overflow)
(link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
reloc->howto->name, reloc->addend, input_section->owner,
input_section, reloc->address)))
abort ();
}
dot = (link_order->offset
+ dst_address
+ link_order->u.indirect.section->output_section->vma);
bfd_put_16 (abfd, gap, data + dst_address);
dst_address+=2;
src_address+=2;
gap = value - dot;
break;
}
/* Sanity check. */
if (gap < -128 || gap > 126)
{
if (! ((*link_info->callbacks->reloc_overflow)
(link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
reloc->howto->name, reloc->addend, input_section->owner,
input_section, reloc->address)))
abort ();
}
case R_RELBYTE:
{
unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
input_section);
if (gap < 0xff
|| (gap >= 0x0000ff00
&& gap <= 0x0000ffff)
|| ( gap >= 0x00ffff00
&& gap <= 0x00ffffff)
|| ( gap >= 0xffffff00
&& gap <= 0xffffffff))
{
bfd_put_8 (abfd, gap, data + dst_address);
dst_address += 1;
src_address += 1;
}
else
{
if (! ((*link_info->callbacks->reloc_overflow)
(link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
reloc->howto->name, reloc->addend, input_section->owner,
input_section, reloc->address)))
abort ();
}
}
/* Everything looks OK. Apply the relocation and update the
src/dst address appropriately. */
bfd_put_8 (abfd, gap, data + dst_address);
dst_address++;
src_address++;
/* All done. */
break;
/* 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);
/* Get the address of the instruction (not the reloc). */
dot = (link_order->offset
+ dst_address
+ link_order->u.indirect.section->output_section->vma + 1);
gap = value - dot;
/* Sanity check. */
if (gap > 32766 || gap < -32768)
{
if (! ((*link_info->callbacks->reloc_overflow)
(link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
reloc->howto->name, reloc->addend, input_section->owner,
input_section, reloc->address)))
abort ();
}
/* Everything looks OK. Apply the relocation and update the
src/dst address appropriately. */
bfd_put_16 (abfd, gap, data + dst_address);
dst_address += 2;
src_address += 2;
/* All done. */
break;
/* Generic 8bit absolute relocation. */
case R_RELBYTE:
/* Get the address of the object referenced by this insn. */
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
/* Sanity check. */
if (value < 0xff
|| (value >= 0x0000ff00 && value <= 0x0000ffff)
|| (value >= 0x00ffff00 && value <= 0x00ffffff)
|| (value >= 0xffffff00 && value <= 0xffffffff))
{
/* Everything looks OK. Apply the relocation and update the
src/dst address appropriately. */
bfd_put_8 (abfd, gap, data + dst_address);
dst_address += 1;
src_address += 1;
}
else
{
if (! ((*link_info->callbacks->reloc_overflow)
(link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
reloc->howto->name, reloc->addend, input_section->owner,
input_section, reloc->address)))
abort ();
}
/* All done. */
break;
/* Various simple 16bit absolute relocations. */
case R_MOV16B1:
case R_JMP1:
/* A relword which would have like to have been a pcrel */
case R_MOVB1:
/* A relword which would like to have been modified but
didn't make it */
case R_RELWORD:
bfd_put_16 (abfd,
bfd_coff_reloc16_get_value (reloc, link_info, input_section),
data + dst_address);
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;
break;
/* Various simple 24/32bit absolute relocations. */
case R_MOV24B1:
case R_MOVL1:
case R_RELLONG:
bfd_put_32 (abfd,
bfd_coff_reloc16_get_value (reloc, link_info, input_section),
data + dst_address);
/* Get the address of the target of this branch. */
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;
break;
case R_MOVB2:
/* Special relaxed type, there will be a gap between where we
get stuff from and where we put stuff to now
for a mov.b @aa:16 -> mov.b @aa:8
opcode 0x6a 0x0y offset
-> 0x2y off
*/
if (data[dst_address - 1] != 0x6a)
abort ();
switch (data[src_address] & 0xf0)
/* Another 24/32bit absolute relocation. */
case R_JMPL1:
/* Get the address of the target of this branch. */
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
value = ((value & 0x00ffffff)
| (bfd_get_32 (abfd, data + src_address) & 0xff000000));
bfd_put_32 (abfd, value, data + dst_address);
dst_address += 4;
src_address += 4;
break;
/* A 16bit abolute relocation that was formerlly a 24/32bit
absolute relocation. */
case R_MOVL2:
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
/* Sanity check. */
if (value < 0x8000 || value > 0xff8000)
{
case 0x00:
/* Src is memory */
data[dst_address - 1] = (data[src_address] & 0xf) | 0x20;
/* Insert the 16bit value into the proper location. */
bfd_put_16 (abfd, value, data + dst_address);
/* Fix the opcode. For all the move insns, we simply
need to turn off bit 0x20 in the previous byte. */
data[dst_address - 1] &= ~0x20;
dst_address += 2;
src_address += 4;
}
else
{
if (! ((*link_info->callbacks->reloc_overflow)
(link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
reloc->howto->name, reloc->addend, input_section->owner,
input_section, reloc->address)))
abort ();
}
break;
/* A 16bit absolute branch that is now an 8-bit pc-relative branch. */
case R_JMP2:
/* Get the address of the target of this branch. */
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
/* Get the address of the next instruction. */
dot = (link_order->offset
+ dst_address
+ link_order->u.indirect.section->output_section->vma + 1);
gap = value - dot;
/* Sanity check. */
if (gap < -128 || gap > 126)
{
if (! ((*link_info->callbacks->reloc_overflow)
(link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
reloc->howto->name, reloc->addend, input_section->owner,
input_section, reloc->address)))
abort ();
}
/* Now fix the instruction itself. */
switch (data[dst_address - 1])
{
case 0x5e:
/* jsr -> bsr */
bfd_put_8 (abfd, 0x55, data + dst_address - 1);
break;
case 0x80:
/* Src is reg */
data[dst_address - 1] = (data[src_address] & 0xf) | 0x30;
case 0x5a:
/* jmp ->bra */
bfd_put_8 (abfd, 0x40, data + dst_address - 1);
break;
default:
abort ();
}
/* the offset must fit ! after all, what was all the relaxing
about ? */
/* Write out the 8bit value. */
bfd_put_8 (abfd, gap, data + dst_address);
bfd_put_8 (abfd,
bfd_coff_reloc16_get_value (reloc, link_info, input_section),
data + dst_address);
/* Note the magic - src goes up by two bytes, but dst by only
one */
dst_address += 1;
src_address += 3;
break;
case R_JMP2:
/* Special relaxed type */
{
bfd_vma dot = link_order->offset
+ dst_address
+ link_order->u.indirect.section->output_section->vma;
int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
- dot - 1);
if ((gap & ~0xff) != 0 && ((gap & 0xff00) != 0xff00))
abort ();
bfd_put_8 (abfd, gap, data + dst_address);
switch (data[dst_address - 1])
{
case 0x5e:
/* jsr -> bsr */
bfd_put_8 (abfd, 0x55, data + dst_address - 1);
break;
case 0x5a:
/* jmp ->bra */
bfd_put_8 (abfd, 0x40, data + dst_address - 1);
break;
default:
abort ();
}
dst_address++;
src_address += 3;
break;
}
break;
/* A 16bit pc-relative branch that is now an 8-bit pc-relative branch. */
case R_PCRWORD_B:
/* Special relaxed type */
{
bfd_vma dot = link_order->offset
+ dst_address
+ link_order->u.indirect.section->output_section->vma - 2;
/* Get the address of the target of this branch. */
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
- dot - 1);
/* Get the address of the instruction (not the reloc). */
dot = (link_order->offset
+ dst_address
+ link_order->u.indirect.section->output_section->vma - 1);
if ((gap & ~0xff) != 0 && ((gap & 0xff00) != 0xff00))
abort ();
gap = value - dot;
switch (data[dst_address - 2])
{
int tmp;
case 0x58:
/* bCC:16 -> bCC:8 */
/* Get the condition code from the original insn. */
tmp = data[dst_address - 1];
tmp &= 0xf0;
tmp >>= 4;
/* Now or in the high nibble of the opcode. */
tmp |= 0x40;
/* Write it. */
bfd_put_8 (abfd, tmp, data + dst_address - 2);
break;
default:
/* Sanity check. */
if (gap < -128 || gap > 126)
{
if (! ((*link_info->callbacks->reloc_overflow)
(link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
reloc->howto->name, reloc->addend, input_section->owner,
input_section, reloc->address)))
abort ();
}
}
/* Now fix the instruction. */
switch (data[dst_address - 2])
{
case 0x58:
/* bCC:16 -> bCC:8 */
/* Get the condition code from the original insn. */
tmp = data[dst_address - 1];
tmp &= 0xf0;
tmp >>= 4;
/* Now or in the high nibble of the opcode. */
tmp |= 0x40;
/* Write it. */
bfd_put_8 (abfd, tmp, data + dst_address - 2);
break;
default:
abort ();
}
/* Output the target. */
bfd_put_8 (abfd, gap, data + dst_address - 1);
/* We don't advance dst_address -- the 8bit reloc is applied at
dst_address - 1, so the next insn should begin at dst_address.
src_address is advanced by two (original reloc was 16bits). */
dst_address - 1, so the next insn should begin at dst_address. */
src_address += 2;
break;
}
break;
case R_JMPL_B8: /* 24 bit branch which is now 8 bits */
/* Speciial relaxed type */
{
bfd_vma dot = link_order->offset
+ dst_address
+ link_order->u.indirect.section->output_section->vma;
/* Similarly for a 24bit absolute that is now 8 bits. */
case R_JMPL2:
/* Get the address of the target of this branch. */
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
- dot - 2);
/* Get the address of the instruction (not the reloc). */
dot = (link_order->offset
+ dst_address
+ link_order->u.indirect.section->output_section->vma + 2);
if ((gap & ~0xff) != 0 && ((gap & 0xff00) != 0xff00))
gap = value - dot;
/* Fix the instruction. */
switch (data[src_address])
{
case 0x5e:
/* jsr -> bsr */
bfd_put_8 (abfd, 0x55, data + dst_address);
break;
case 0x5a:
/* jmp ->bra */
bfd_put_8 (abfd, 0x40, data + dst_address);
break;
default:
abort ();
}
switch (data[src_address])
{
case 0x5e:
/* jsr -> bsr */
bfd_put_8 (abfd, 0x55, data + dst_address);
break;
case 0x5a:
/* jmp ->bra */
bfd_put_8 (abfd, 0x40, data + dst_address);
break;
default:
bfd_put_8 (abfd, 0xde, data + dst_address);
break;
}
bfd_put_8 (abfd, gap, data + dst_address + 1);
dst_address += 2;
src_address += 4;
break;
}
case R_JMPL1:
{
int v = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
int o = bfd_get_32 (abfd, data + src_address);
v = (v & 0x00ffffff) | (o & 0xff000000);
bfd_put_32 (abfd, v, data + dst_address);
dst_address += 4;
src_address += 4;
}
bfd_put_8 (abfd, gap, data + dst_address + 1);
dst_address += 2;
src_address += 4;
break;
/* A 16bit absolute mov.b that is now an 8bit absolute mov.b. */
case R_MOV16B2:
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
/* A 24 bit mov which could be an 8 bit move, really pointing to
the byte before the 24bit hole, so we can treat it as a 32bit pointer */
case R_MOVLB1:
{
int v = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
int o = bfd_get_32 (abfd, data + dst_address);
v = (v & 0x00ffffff) | (o & 0xff000000);
bfd_put_32 (abfd, v, data + dst_address);
dst_address += 4;
src_address += 4;
}
/* Sanity check. */
if (data[dst_address - 2] != 0x6a)
abort ();
/* Fix up the opcode. */
switch (data[src_address-1] & 0xf0)
{
case 0x00:
data[dst_address - 2] = (data[src_address-1] & 0xf) | 0x20;
break;
case 0x80:
data[dst_address - 2] = (data[src_address-1] & 0xf) | 0x30;
break;
default:
abort ();
}
bfd_put_8 (abfd, value & 0xff, data + dst_address - 1);
src_address += 2;
break;
/* Similarly for a 24bit mov.b */
case R_MOV24B2:
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
/* Sanity check. */
if (data[dst_address - 2] != 0x6a)
abort ();
/* Fix up the opcode. */
switch (data[src_address-1] & 0xf0)
{
case 0x20:
data[dst_address - 2] = (data[src_address-1] & 0xf) | 0x20;
break;
case 0xa0:
data[dst_address - 2] = (data[src_address-1] & 0xf) | 0x30;
break;
default:
abort ();
}
bfd_put_8 (abfd, value & 0xff, data + dst_address - 1);
src_address += 4;
break;
/* An 8bit memory indirect instruction (jmp/jsr).