aboutsummaryrefslogtreecommitdiff
path: root/bfd/coff-h8300.c
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>1996-06-09 22:38:09 +0000
committerJeff Law <law@redhat.com>1996-06-09 22:38:09 +0000
commitfd7c5d73cec53bfcde06bfcc3cc603c239f984d4 (patch)
treee7c8d8e9acd2f02cec65a0511e982ac66bcf96a7 /bfd/coff-h8300.c
parentf98286385f8693c0d56df7d02399b59522cbf334 (diff)
downloadgdb-fd7c5d73cec53bfcde06bfcc3cc603c239f984d4.zip
gdb-fd7c5d73cec53bfcde06bfcc3cc603c239f984d4.tar.gz
gdb-fd7c5d73cec53bfcde06bfcc3cc603c239f984d4.tar.bz2
* 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.
Diffstat (limited to 'bfd/coff-h8300.c')
-rw-r--r--bfd/coff-h8300.c736
1 files changed, 412 insertions, 324 deletions
diff --git a/bfd/coff-h8300.c b/bfd/coff-h8300.c
index 8cf73db..9e70b0e 100644
--- a/bfd/coff-h8300.c
+++ b/bfd/coff-h8300.c
@@ -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:
+ /* 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);
- if (value >= 0xff00)
- {
+ /* 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);
- /* Change the reloc type from 16bit, possible 8 to 8bit
- possible 16 */
+ /* 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;
- /* 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);
- }
+ /* This shrinks this section by two bytes. */
+ 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);
+ /* 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 ;
-
- 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. */
+ reloc->howto = howto_table + 15;
- /* 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 ;
+ /* This shrinks this section by two bytes. */
+ shrink += 2;
bfd_perform_slip(abfd, 2, input_section, address);
}
break;
- case R_JMP1:
-
+ /* 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);
-
- 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 - shrink);
-
-
- if (-120 < (long)gap && (long)gap < 120 )
- {
-
- /* 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 */
+ /* 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 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;
- case R_PCRWORD:
-
+ /* 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);
-
- 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);
-
+ /* 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;
- if (-120 < (long)gap && (long)gap < 120 )
- {
+ /* This shrinks this section by four bytes. */
+ shrink += 4;
+ bfd_perform_slip(abfd, 4, input_section, address);
- /* Change the reloc type from 16bit, possible 8 to 8bit
- possible 16 */
- reloc->howto = howto_table + 15;
- /* The place to relc moves back by one */
+ /* Done with this reloc. */
+ break;
+ }
+
+ /* FALLTHROUGH and try to turn the 32/24 bit reloc into a 16 bit
+ reloc. */
- /* This will be two bytes smaller in the long run */
- shrink +=2 ;
+ /* 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;
- }
+ dot = (link_order->offset
+ + dst_address
+ + link_order->u.indirect.section->output_section->vma);
+
+ 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 ();
+ }
+
+ /* 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:
- {
- 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 ();
- }
+ /* Get the address of the target of this branch. */
+ value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
- bfd_put_16 (abfd, gap, data + dst_address);
- dst_address+=2;
- src_address+=2;
+ /* Get the address of the instruction (not the reloc). */
+ dot = (link_order->offset
+ + dst_address
+ + link_order->u.indirect.section->output_section->vma + 1);
- break;
- }
+ 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:
- {
- 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 ();
- }
- }
+ /* 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)
- {
- case 0x00:
- /* Src is memory */
- data[dst_address - 1] = (data[src_address] & 0xf) | 0x20;
- break;
- case 0x80:
- /* Src is reg */
- data[dst_address - 1] = (data[src_address] & 0xf) | 0x30;
- break;
- default:
- abort ();
- }
-
- /* the offset must fit ! after all, what was all the relaxing
- about ? */
+ /* 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);
- bfd_put_8 (abfd,
- bfd_coff_reloc16_get_value (reloc, link_info, input_section),
- data + dst_address);
+ 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;
- /* Note the magic - src goes up by two bytes, but dst by only
- one */
- dst_address += 1;
- src_address += 3;
+ /* 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)
+ {
+ /* 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:
-
- /* Special relaxed type */
- {
- bfd_vma dot = link_order->offset
- + dst_address
- + link_order->u.indirect.section->output_section->vma;
+ /* 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 next instruction. */
+ dot = (link_order->offset
+ + dst_address
+ + link_order->u.indirect.section->output_section->vma + 1);
- if ((gap & ~0xff) != 0 && ((gap & 0xff00) != 0xff00))
- abort ();
-
- bfd_put_8 (abfd, gap, data + dst_address);
+ gap = value - dot;
- 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:
+ /* 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 ();
- }
- dst_address++;
- src_address += 3;
+ }
- break;
- }
- break;
+ /* 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 0x5a:
+ /* jmp ->bra */
+ bfd_put_8 (abfd, 0x40, data + dst_address - 1);
+ break;
- case R_PCRWORD_B:
-
- /* Special relaxed type */
- {
- bfd_vma dot = link_order->offset
- + dst_address
- + link_order->u.indirect.section->output_section->vma - 2;
+ default:
+ abort ();
+ }
- int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
- - dot - 1);
+ /* Write out the 8bit value. */
+ bfd_put_8 (abfd, gap, data + dst_address);
- if ((gap & ~0xff) != 0 && ((gap & 0xff00) != 0xff00))
- abort ();
+ dst_address += 1;
+ src_address += 3;
- switch (data[dst_address - 2])
- {
- int tmp;
+ break;
- case 0x58:
- /* bCC:16 -> bCC:8 */
- /* Get the condition code from the original insn. */
- tmp = data[dst_address - 1];
- tmp &= 0xf0;
- tmp >>= 4;
+ /* A 16bit pc-relative branch that is now an 8-bit pc-relative branch. */
+ case R_PCRWORD_B:
+ /* Get the address of the target of this branch. */
+ value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
- /* Now or in the high nibble of the opcode. */
- tmp |= 0x40;
+ /* Get the address of the instruction (not the reloc). */
+ dot = (link_order->offset
+ + dst_address
+ + link_order->u.indirect.section->output_section->vma - 1);
- /* Write it. */
- bfd_put_8 (abfd, tmp, data + dst_address - 2);
- break;
+ gap = value - dot;
- 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;
+ bfd_put_8 (abfd, gap, data + dst_address + 1);
+ dst_address += 2;
+ src_address += 4;
- default:
- bfd_put_8 (abfd, 0xde, data + dst_address);
- break;
- }
+ break;
- bfd_put_8 (abfd, gap, data + dst_address + 1);
- dst_address += 2;
- src_address += 4;
+ /* 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);
- break;
- }
+ /* Sanity check. */
+ if (data[dst_address - 2] != 0x6a)
+ abort ();
- 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;
- }
+ /* 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);
- /* 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 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).