This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]