This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
h8s relaxation patch
Richard Sandiford <rsandifo@redhat.com> writes:
> BTW, I notice that the range checks are wrong for h8s & h8sx.
> I'll try to fix that soon.
The problem was that we were relaxing h8s moves based on 24-bit rather
than 32-bit addresses. It should be fixed by the patch below.
At the moment we use a separate range check for each processor variant.
I think it's easier to fix the bug if we replace this with a single
range check and pad the address to 32 bits beforehand. This should
also deal with the FIXMEs about normal mode.
The address-padding function is common to both elf & coff. Is it OK
to add it to bfd-in.h? I notice the file already has target-specific
functions but I wasn't sure whether that was supposed to be a last resort.
A couple of related things:
- The handling of R_H8_DIR24A8 is wrong for all targets. It checks
for four combinations:
mov.b @aa:32,rnl
mov.b rnl,@aa:32
mov.b @aa:16,rnl
mov.b rnl,@aa:16
The last two aren't valid for R_H8_DIR24A8 (I think they were just
cut-&-paste from the earlier case statement). And we always skip
the relaxation for the first two cases, which are the ones we actually
care about.
- I'd like to stop the coff code from reporting an error when an 8-bit
relocation overflows. The current behaviour is inconsistent with elf
and with the coff handling of 16-bit relocations, neither of which
checks for overflow.
(8-bit relocations are used for both immediates and addresses. In the
case of immediates, it's sometimes useful to refer to the low 8 bits
of a symbol you know is bigger.)
Tested on h8300-elf and h8300-coff. OK to install?
Richard
bfd/
* bfd-in.h (bfd_h8300_pad_address): Declare.
* bfd-in2.h: Regenerate.
* cpu-h8300.c (bfd_h8300_pad_address): New function.
* coff-h8300.c (h8300_reloc16_estimate): Use it to canonicalize
addresses before checking whether they can be relaxed.
(h8300_reloc16_extra_cases): Likewise for the R_MOVL2 sanity check.
Don't complain about overflows in general 8-bit relocations.
* elf32-h8300.c (elf32_h8_relax_section): Use bfd_h8300_pad_address.
Fix handling of R_H8_DIR24A8.
ld/testsuite/
* ld-h8300/relax-3{.s,.d,-coff.d}: New test.
* ld-h8300/h8300.exp: Run it.
Index: bfd/bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.63
diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.63 bfd-in.h
--- bfd/bfd-in.h 29 Jun 2003 10:06:39 -0000 1.63
+++ bfd/bfd-in.h 11 Jul 2003 11:41:56 -0000
@@ -821,3 +821,6 @@ extern void bfd_ticoff_set_section_load_
extern int bfd_ticoff_get_section_load_page
(struct sec *);
+/* H8/300 functions. */
+extern bfd_vma bfd_h8300_pad_address
+ (bfd *, bfd_vma);
Index: bfd/cpu-h8300.c
===================================================================
RCS file: /cvs/src/src/bfd/cpu-h8300.c,v
retrieving revision 1.15
diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.15 cpu-h8300.c
--- bfd/cpu-h8300.c 11 Jul 2003 11:08:30 -0000 1.15
+++ bfd/cpu-h8300.c 11 Jul 2003 11:41:56 -0000
@@ -220,3 +220,39 @@ const bfd_arch_info_type bfd_h8300_arch
h8300_scan,
&h8300h_info_struct
};
+
+/* Pad the given address to 32 bits, converting 16-bit and 24-bit
+ addresses into the values they would have had on a h8s target. */
+
+bfd_vma
+bfd_h8300_pad_address (bfd *abfd, bfd_vma address)
+{
+ /* Cope with bfd_vma's larger than 32 bits. */
+ address &= 0xffffffffu;
+
+ switch (bfd_get_mach (abfd))
+ {
+ case bfd_mach_h8300:
+ case bfd_mach_h8300hn:
+ case bfd_mach_h8300sn:
+ case bfd_mach_h8300sxn:
+ /* Sign extend a 16-bit address. */
+ if (address >= 0x8000)
+ return address | 0xffff0000u;
+ return address;
+
+ case bfd_mach_h8300h:
+ /* Sign extend a 24-bit address. */
+ if (address >= 0x800000)
+ return address | 0xff000000u;
+ return address;
+
+ case bfd_mach_h8300s:
+ case bfd_mach_h8300sx:
+ return address;
+
+ default:
+ abort ();
+ }
+}
+
Index: bfd/coff-h8300.c
===================================================================
RCS file: /cvs/src/src/bfd/coff-h8300.c,v
retrieving revision 1.22
diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.22 coff-h8300.c
--- bfd/coff-h8300.c 11 Jul 2003 11:08:30 -0000 1.22
+++ bfd/coff-h8300.c 11 Jul 2003 11:41:56 -0000
@@ -573,17 +573,11 @@ h8300_reloc16_estimate (bfd *abfd, asect
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_h8300_pad_address (abfd, value);
- /* 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
- || bfd_get_mach (abfd) == bfd_mach_h8300s)
- && value >= 0xffff00
- && value <= 0xffffff))
+ /* If the address is in the top 256 bytes of the address space
+ then we can relax this instruction. */
+ if (value >= 0xffffff00u)
{
/* Change the reloc type. */
reloc->howto = reloc->howto + 1;
@@ -600,13 +594,9 @@ h8300_reloc16_estimate (bfd *abfd, asect
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_h8300_pad_address (abfd, value);
- /* 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
- || bfd_get_mach (abfd) == bfd_mach_h8300s)
- && value >= 0xffff00
- && value <= 0xffffff)
+ if (value >= 0xffffff00u)
{
/* Change the reloc type. */
reloc->howto = reloc->howto + 1;
@@ -627,10 +617,11 @@ h8300_reloc16_estimate (bfd *abfd, asect
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_h8300_pad_address (abfd, value);
- /* If this address is in 0x0000..0x7fff inclusive or
- 0xff8000..0xffffff inclusive, then it can be relaxed. */
- if (value <= 0x7fff || value >= 0xff8000)
+ /* If the address is a sign-extended 16-bit value then we can
+ relax this instruction. */
+ if (value <= 0x7fff || value >= 0xffff8000u)
{
/* Change the reloc type. */
reloc->howto = howto_table + 17;
@@ -737,26 +728,9 @@ h8300_reloc16_extra_cases (bfd *abfd, st
/* 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, value & 0xff, 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 ();
- }
+ bfd_put_8 (abfd, value & 0xff, data + dst_address);
+ dst_address += 1;
+ src_address += 1;
/* All done. */
break;
@@ -798,9 +772,10 @@ h8300_reloc16_extra_cases (bfd *abfd, st
absolute relocation. */
case R_MOVL2:
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
+ value = bfd_h8300_pad_address (abfd, value);
/* Sanity check. */
- if (value <= 0x7fff || value >= 0xff8000)
+ if (value <= 0x7fff || value >= 0xffff8000u)
{
/* Insert the 16bit value into the proper location. */
bfd_put_16 (abfd, value, data + dst_address);
Index: bfd/elf32-h8300.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-h8300.c,v
retrieving revision 1.30
diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.30 elf32-h8300.c
--- bfd/elf32-h8300.c 11 Jul 2003 11:08:30 -0000 1.30
+++ bfd/elf32-h8300.c 11 Jul 2003 11:41:57 -0000
@@ -1004,18 +1004,10 @@ elf32_h8_relax_section (bfd *abfd, asect
become an 8 bit absolute address if its in the right range. */
case R_H8_DIR16A8:
{
- bfd_vma value = symval + irel->r_addend;
+ bfd_vma value;
- if ((bfd_get_mach (abfd) == bfd_mach_h8300
- && value >= 0xff00
- && value <= 0xffff)
- || ((bfd_get_mach (abfd) == bfd_mach_h8300h
- /* FIXME: h8300hn? */
- || bfd_get_mach (abfd) == bfd_mach_h8300s
- /* FIXME: h8300sn? */
- || bfd_get_mach (abfd) == bfd_mach_h8300sx)
- && value >= 0xffff00
- && value <= 0xffffff))
+ value = bfd_h8300_pad_address (abfd, symval + irel->r_addend);
+ if (value >= 0xffffff00u)
{
unsigned char code;
@@ -1068,20 +1060,11 @@ elf32_h8_relax_section (bfd *abfd, asect
become an 8 bit absolute address if its in the right range. */
case R_H8_DIR24A8:
{
- bfd_vma value = symval + irel->r_addend;
+ bfd_vma value;
- if ((bfd_get_mach (abfd) == bfd_mach_h8300
- && value >= 0xff00
- && value <= 0xffff)
- || ((bfd_get_mach (abfd) == bfd_mach_h8300h
- /* FIXME: h8300hn? */
- || bfd_get_mach (abfd) == bfd_mach_h8300s
- /* FIXME: h8300sn? */
- || bfd_get_mach (abfd) == bfd_mach_h8300sx)
- && value >= 0xffff00
- && value <= 0xffffff))
+ value = bfd_h8300_pad_address (abfd, symval + irel->r_addend);
+ if (value >= 0xffffff00u)
{
- bfd_boolean skip = FALSE;
unsigned char code;
/* Note that we've changed the relocs, section contents,
@@ -1101,37 +1084,32 @@ elf32_h8_relax_section (bfd *abfd, asect
switch (code & 0xf0)
{
- case 0x00:
+ case 0x20:
bfd_put_8 (abfd, (code & 0xf) | 0x20,
contents + irel->r_offset - 2);
break;
- case 0x80:
+ case 0xa0:
bfd_put_8 (abfd, (code & 0xf) | 0x30,
contents + irel->r_offset - 2);
break;
- case 0x20:
- case 0xa0:
- /* Skip 32bit versions. */
- skip = TRUE;
- break;
default:
abort ();
}
- if (skip)
- break;
-
/* Fix the relocation's type. */
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
R_H8_DIR8);
+ irel->r_offset--;
/* Delete two bytes of data. */
- if (!elf32_h8_relax_delete_bytes (abfd, sec, irel->r_offset, 2))
+ if (!elf32_h8_relax_delete_bytes (abfd, sec,
+ irel->r_offset + 1, 4))
goto error_return;
/* That will change things, so, we should relax again.
Note that this is not required, and it may be slow. */
*again = TRUE;
+ break;
}
}
@@ -1141,9 +1119,10 @@ elf32_h8_relax_section (bfd *abfd, asect
become a 16bit absoulte address if it is in the right range. */
case R_H8_DIR32A16:
{
- bfd_vma value = symval + irel->r_addend;
+ bfd_vma value;
- if (value <= 0x7fff || value >= 0xff8000)
+ value = bfd_h8300_pad_address (abfd, symval + irel->r_addend);
+ if (value <= 0x7fff || value >= 0xffff8000u)
{
unsigned char code;
Index: ld/testsuite/ld-h8300/h8300.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-h8300/h8300.exp,v
retrieving revision 1.2
diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.2 h8300.exp
--- ld/testsuite/ld-h8300/h8300.exp 4 Jul 2003 10:25:14 -0000 1.2
+++ ld/testsuite/ld-h8300/h8300.exp 11 Jul 2003 11:41:57 -0000
@@ -28,4 +28,7 @@ run_dump_test relax
if {[istarget *-elf]} {
run_dump_test relax-2
+ run_dump_test relax-3
+} else {
+ run_dump_test relax-3-coff
}
--- /dev/null Tue Jun 17 23:06:41 2003
+++ ld/testsuite/ld-h8300/relax-3-coff.d Fri Jul 11 12:50:15 2003
@@ -0,0 +1,32 @@
+# name: H8300 Relaxation Test 3
+# source: relax-3.s
+# ld: --relax -m h8300s
+# objdump: -d --no-show-raw-insn
+
+.*: file format .*-h8300
+
+Disassembly of section .text:
+
+00000100 <_start>:
+#
+# Relaxation of aa:16
+#
+.*: 6a 08 00 00 * mov.b @0x0:16,r0l
+.*: 6a 08 7f ff * mov.b @0x7fff:16,r0l
+.*: 6a 08 80 00 * mov.b @0x8000:16,r0l
+.*: 6a 08 fe ff * mov.b @0xfeff:16,r0l
+.*: 28 00 * mov.b @0x0:8,r0l
+.*: 28 ff * mov.b @0xff:8,r0l
+#
+# Relaxation of aa:32
+#
+.*: 6a 08 00 00 * mov.b @0x0:16,r0l
+.*: 6a 08 7f ff * mov.b @0x7fff:16,r0l
+.*: 6a 28 00 00 80 00 * mov.b @0x8000:32,r0l
+.*: 6a 28 00 00 ff 00 * mov.b @0xff00:32,r0l
+.*: 6a 28 00 ff ff 00 * mov.b @0xffff00:32,r0l
+.*: 6a 28 ff ff 7f ff * mov.b @0xffff7fff:32,r0l
+.*: 6a 08 80 00 * mov.b @0x8000:16,r0l
+.*: 6a 08 fe ff * mov.b @0xfeff:16,r0l
+.*: 28 00 * mov.b @0x0:8,r0l
+.*: 28 ff * mov.b @0xff:8,r0l
--- /dev/null Tue Jun 17 23:06:41 2003
+++ ld/testsuite/ld-h8300/relax-3.d Fri Jul 11 12:50:15 2003
@@ -0,0 +1,31 @@
+# name: H8300 Relaxation Test 3
+# ld: --relax -m h8300self
+# objdump: -d --no-show-raw-insn
+
+.*: file format .*-h8300
+
+Disassembly of section .text:
+
+00000100 <_start>:
+#
+# Relaxation of aa:16
+#
+.*: 6a 08 00 00 * mov.b @0x0:16,r0l
+.*: 6a 08 7f ff * mov.b @0x7fff:16,r0l
+.*: 6a 08 80 00 * mov.b @0x8000:16,r0l
+.*: 6a 08 fe ff * mov.b @0xfeff:16,r0l
+.*: 28 00 * mov.b @0x0:8,r0l
+.*: 28 ff * mov.b @0xff:8,r0l
+#
+# Relaxation of aa:32
+#
+.*: 6a 08 00 00 * mov.b @0x0:16,r0l
+.*: 6a 08 7f ff * mov.b @0x7fff:16,r0l
+.*: 6a 28 00 00 80 00 * mov.b @0x8000:32,r0l
+.*: 6a 28 00 00 ff 00 * mov.b @0xff00:32,r0l
+.*: 6a 28 00 ff ff 00 * mov.b @0xffff00:32,r0l
+.*: 6a 28 ff ff 7f ff * mov.b @0xffff7fff:32,r0l
+.*: 6a 08 80 00 * mov.b @0x8000:16,r0l
+.*: 6a 08 fe ff * mov.b @0xfeff:16,r0l
+.*: 28 00 * mov.b @0x0:8,r0l
+.*: 28 ff * mov.b @0xff:8,r0l
--- /dev/null Tue Jun 17 23:06:41 2003
+++ ld/testsuite/ld-h8300/relax-3.s Fri Jul 11 12:50:15 2003
@@ -0,0 +1,32 @@
+ .h8300s
+ .globl _start
+_start:
+ # s3-s6 aren't valid 16-bit addresses.
+ mov.b @s1:16,r0l
+ mov.b @s2:16,r0l
+ mov.b @s7:16,r0l
+ mov.b @s8:16,r0l
+ mov.b @s9:16,r0l
+ mov.b @s10:16,r0l
+
+ mov.b @s1:32,r0l
+ mov.b @s2:32,r0l
+ mov.b @s3:32,r0l
+ mov.b @s4:32,r0l
+ mov.b @s5:32,r0l
+ mov.b @s6:32,r0l
+ mov.b @s7:32,r0l
+ mov.b @s8:32,r0l
+ mov.b @s9:32,r0l
+ mov.b @s10:32,r0l
+
+ .equ s1,0
+ .equ s2,0x7fff
+ .equ s3,0x8000
+ .equ s4,0xff00
+ .equ s5,0xffff00
+ .equ s6,0xffff7fff
+ .equ s7,0xffff8000
+ .equ s8,0xfffffeff
+ .equ s9,0xffffff00
+ .equ s10,0xffffffff