public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Thumb32 assembler (65/69)
@ 2005-04-26 10:21 Zack Weinberg
  0 siblings, 0 replies; only message in thread
From: Zack Weinberg @ 2005-04-26 10:21 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 157 bytes --]


More relocations.  This adds BFD_RELOC_* constants for the new
relocations that the Thumb32 branches need, and implements final-link
support for them.

zw


[-- Attachment #2: Type: text/plain, Size: 374 bytes --]


	* reloc.c: Add BFD_RELOC_THUMB_PCREL_BRANCH7, BFD_RELOC_THUMB_BRANCH20,
	BFD_RELOC_THUMB_BRANCH25.
	* bfd-in2.h, libbfd.h: Regenerate.
	* elf32-arm.h (R_ARM_THM_JMP19, R_ARM_THM_JUMP6 howtos): Correct
	bitsize.
	(elf32_arm_reloc_map): Add entries for new relocs.
	(elf32_arm_final_link_relocate): Add support for R_ARM_THM_JUMP24,
	R_ARM_THM_JUMP19, and R_ARM_THM_JUMP6.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 65.diff.txt --]
[-- Type: text/x-patch; name=65.diff.txt, Size: 9817 bytes --]

===================================================================
Index: bfd/bfd-in2.h
--- bfd/bfd-in2.h	(revision 75)
+++ bfd/bfd-in2.h	(revision 76)
@@ -2669,11 +2669,17 @@
 field in the instruction.  */
   BFD_RELOC_THUMB_PCREL_BLX,
 
-/* Thumb 23-, 12- and 9-bit pc-relative branches.  The lowest bit must
-be zero and is not stored in the instruction.  */
+/* Thumb 7-, 9-, 12-, 20-, 23-, and 25-bit pc-relative branches.
+The lowest bit must be zero and is not stored in the instruction.
+Note that the corresponding ELF R_ARM_THM_JUMPnn constant has an
+"nn" one smaller in all cases.  Note further that BRANCH23
+corresponds to R_ARM_THM_CALL.  */
+  BFD_RELOC_THUMB_PCREL_BRANCH7,
   BFD_RELOC_THUMB_PCREL_BRANCH9,
   BFD_RELOC_THUMB_PCREL_BRANCH12,
+  BFD_RELOC_THUMB_PCREL_BRANCH20,
   BFD_RELOC_THUMB_PCREL_BRANCH23,
+  BFD_RELOC_THUMB_PCREL_BRANCH25,
 
 /* 12-bit immediate offset, used in ARM-format ldr and str instructions.  */
   BFD_RELOC_ARM_OFFSET_IMM,
===================================================================
Index: bfd/reloc.c
--- bfd/reloc.c	(revision 75)
+++ bfd/reloc.c	(revision 76)
@@ -2622,15 +2622,25 @@
   Thumb 22 bit pc-relative branch.  The lowest bit must be zero and is
   not stored in the instruction.  The 2nd lowest bit comes from a 1 bit
   field in the instruction.
+
 ENUM
+  BFD_RELOC_THUMB_PCREL_BRANCH7
+ENUMX
   BFD_RELOC_THUMB_PCREL_BRANCH9
 ENUMX
   BFD_RELOC_THUMB_PCREL_BRANCH12
 ENUMX
+  BFD_RELOC_THUMB_PCREL_BRANCH20
+ENUMX
   BFD_RELOC_THUMB_PCREL_BRANCH23
+ENUMX
+  BFD_RELOC_THUMB_PCREL_BRANCH25
 ENUMDOC
-  Thumb 23-, 12- and 9-bit pc-relative branches.  The lowest bit must
-  be zero and is not stored in the instruction.
+  Thumb 7-, 9-, 12-, 20-, 23-, and 25-bit pc-relative branches.
+  The lowest bit must be zero and is not stored in the instruction.
+  Note that the corresponding ELF R_ARM_THM_JUMPnn constant has an
+  "nn" one smaller in all cases.  Note further that BRANCH23
+  corresponds to R_ARM_THM_CALL.
 
 ENUM
   BFD_RELOC_ARM_OFFSET_IMM
===================================================================
Index: bfd/libbfd.h
--- bfd/libbfd.h	(revision 75)
+++ bfd/libbfd.h	(revision 76)
@@ -1149,9 +1149,12 @@
   "BFD_RELOC_ARM_PCREL_BRANCH",
   "BFD_RELOC_ARM_PCREL_BLX",
   "BFD_RELOC_THUMB_PCREL_BLX",
+  "BFD_RELOC_THUMB_PCREL_BRANCH7",
   "BFD_RELOC_THUMB_PCREL_BRANCH9",
   "BFD_RELOC_THUMB_PCREL_BRANCH12",
+  "BFD_RELOC_THUMB_PCREL_BRANCH20",
   "BFD_RELOC_THUMB_PCREL_BRANCH23",
+  "BFD_RELOC_THUMB_PCREL_BRANCH25",
   "BFD_RELOC_ARM_OFFSET_IMM",
   "BFD_RELOC_ARM_THUMB_OFFSET",
   "BFD_RELOC_ARM_TARGET1",
===================================================================
Index: bfd/elf32-arm.c
--- bfd/elf32-arm.c	(revision 75)
+++ bfd/elf32-arm.c	(revision 76)
@@ -778,7 +778,7 @@
   HOWTO (R_ARM_THM_JUMP19,	/* type */
 	 1,			/* rightshift */
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
-	 20,			/* bitsize */
+	 19,			/* bitsize */
 	 TRUE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_signed,/* complain_on_overflow */
@@ -792,7 +792,7 @@
   HOWTO (R_ARM_THM_JUMP6,	/* type */
 	 1,			/* rightshift */
 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
-	 7,			/* bitsize */
+	 6,			/* bitsize */
 	 TRUE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_unsigned,/* complain_on_overflow */
@@ -1312,9 +1312,12 @@
     {BFD_RELOC_16,                   R_ARM_ABS16},
     {BFD_RELOC_ARM_OFFSET_IMM,       R_ARM_ABS12},
     {BFD_RELOC_ARM_THUMB_OFFSET,     R_ARM_THM_ABS5},
+    {BFD_RELOC_THUMB_PCREL_BRANCH25, R_ARM_THM_JUMP24},
     {BFD_RELOC_THUMB_PCREL_BRANCH23, R_ARM_THM_CALL},
     {BFD_RELOC_THUMB_PCREL_BRANCH12, R_ARM_THM_JUMP11},
+    {BFD_RELOC_THUMB_PCREL_BRANCH20, R_ARM_THM_JUMP19},
     {BFD_RELOC_THUMB_PCREL_BRANCH9,  R_ARM_THM_JUMP8},
+    {BFD_RELOC_THUMB_PCREL_BRANCH7,  R_ARM_THM_JUMP6},
     {BFD_RELOC_ARM_GLOB_DAT,         R_ARM_GLOB_DAT},
     {BFD_RELOC_ARM_JUMP_SLOT,        R_ARM_JUMP_SLOT},
     {BFD_RELOC_ARM_RELATIVE,         R_ARM_RELATIVE},
@@ -3309,8 +3312,154 @@
       }
       break;
 
+    case R_ARM_THM_JUMP24:
+      /* Thumb32 unconditional branch instruction.  */
+      {
+	bfd_vma relocation;
+	bfd_boolean overflow = FALSE;
+	bfd_vma upper_insn = bfd_get_16 (input_bfd, hit_data);
+	bfd_vma lower_insn = bfd_get_16 (input_bfd, hit_data + 2);
+	bfd_signed_vma reloc_signed_max = ((1 << (howto->bitsize - 1)) - 1) >> howto->rightshift;
+	bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
+	bfd_vma check;
+	bfd_signed_vma signed_check;
+
+	/* Need to refetch the addend, reconstruct the top three bits, and glue the
+	   two pieces together.  */
+	if (globals->use_rel)
+	  {
+	    bfd_vma S     = (upper_insn & 0x0400) >> 10;
+	    bfd_vma upper = (upper_insn & 0x03ff);
+	    bfd_vma I1    = (lower_insn & 0x2000) >> 13;
+	    bfd_vma I2    = (lower_insn & 0x0800) >> 11;
+	    bfd_vma lower = (lower_insn & 0x07ff);
+
+	    upper |= ~(I2 ^ S) << 10;
+	    upper |= ~(I1 ^ S) << 11;
+	    upper |= ~S << 12;
+	    upper -= 0x1000; /* Sign extend.  */
+
+	    addend = (upper << 12) | (lower << 1);
+	    signed_addend = addend;
+	  }
+
+	/* ??? Should handle interworking?  GCC might someday try to
+	   use this for tail calls.  */
+
+      	relocation = value + signed_addend;
+	relocation -= (input_section->output_section->vma
+		       + input_section->output_offset
+		       + rel->r_offset);
+
+	check = relocation >> howto->rightshift;
+
+	/* If this is a signed value, the rightshift just dropped
+	   leading 1 bits (assuming twos complement).  */
+	if ((bfd_signed_vma) relocation >= 0)
+	  signed_check = check;
+	else
+	  signed_check = check | ~((bfd_vma) -1 >> howto->rightshift);
+
+	/* Assumes two's complement.  */
+	if (signed_check > reloc_signed_max || signed_check < reloc_signed_min)
+	  overflow = TRUE;
+
+	/* Put RELOCATION back into the insn.  */
+	{
+	  bfd_vma S  = (relocation & 0x00100000) >> 20;
+	  bfd_vma J2 = (relocation & 0x00080000) >> 19;
+	  bfd_vma J1 = (relocation & 0x00040000) >> 18;
+	  bfd_vma hi = (relocation & 0x0003f000) >> 12;
+	  bfd_vma lo = (relocation & 0x00000ffe) >>  1;
+
+	  upper_insn = (upper_insn & ~(bfd_vma) 0x043f) | (S << 10) | hi;
+	  lower_insn = (lower_insn & ~(bfd_vma) 0x2fff) | (J1 << 13) | (J2 << 11) | lo;
+	}
+
+	/* Put the relocated value back in the object file:  */
+	bfd_put_16 (input_bfd, upper_insn, hit_data);
+	bfd_put_16 (input_bfd, lower_insn, hit_data + 2);
+
+	return (overflow ? bfd_reloc_overflow : bfd_reloc_ok);
+      }
+
+    case R_ARM_THM_JUMP19:
+      /* Thumb32 conditional branch instruction.  */
+      {
+	bfd_vma relocation;
+	bfd_boolean overflow = FALSE;
+	bfd_vma upper_insn = bfd_get_16 (input_bfd, hit_data);
+	bfd_vma lower_insn = bfd_get_16 (input_bfd, hit_data + 2);
+	bfd_signed_vma reloc_signed_max = ((1 << (howto->bitsize - 1)) - 1) >> howto->rightshift;
+	bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
+	bfd_vma check;
+	bfd_signed_vma signed_check;
+
+	/* Need to refetch the addend, reconstruct the top three bits,
+	   and squish the two 11 bit pieces together.  */
+	if (globals->use_rel)
+	  {
+	    bfd_vma S     = (upper_insn & 0x0400) >> 10;
+	    bfd_vma upper = (upper_insn & 0x001f);
+	    bfd_vma J1    = (lower_insn & 0x2000) >> 13;
+	    bfd_vma J2    = (lower_insn & 0x0800) >> 11;
+	    bfd_vma lower = (lower_insn & 0x07ff);
+
+	    upper |= J2 << 6;
+	    upper |= J1 << 7;
+	    upper |= ~S << 8;
+	    upper -= 0x0100; /* Sign extend.  */
+
+	    addend = (upper << 12) | (lower << 1);
+	    signed_addend = addend;
+	  }
+
+	/* ??? Should handle interworking?  GCC might someday try to
+	   use this for tail calls.  */
+
+      	relocation = value + signed_addend;
+	relocation -= (input_section->output_section->vma
+		       + input_section->output_offset
+		       + rel->r_offset);
+
+	check = relocation >> howto->rightshift;
+
+	/* If this is a signed value, the rightshift just dropped
+	   leading 1 bits (assuming twos complement).  */
+	if ((bfd_signed_vma) relocation >= 0)
+	  signed_check = check;
+	else
+	  signed_check = check | ~((bfd_vma) -1 >> howto->rightshift);
+
+	/* Assumes two's complement.  */
+	if (signed_check > reloc_signed_max || signed_check < reloc_signed_min)
+	  overflow = TRUE;
+
+	/* Put RELOCATION back into the insn.  */
+	{
+	  bfd_vma S  = (relocation & 0x01000000) >> 24;
+	  bfd_vma I1 = (relocation & 0x00800000) >> 23;
+	  bfd_vma I2 = (relocation & 0x00400000) >> 22;
+	  bfd_vma hi = (relocation & 0x003ff000) >> 12;
+	  bfd_vma lo = (relocation & 0x00000ffe) >>  1;
+
+	  I1 ^= S;
+	  I2 ^= S;
+
+	  upper_insn = (upper_insn & ~(bfd_vma) 0x07ff) | (S << 10) | hi;
+	  lower_insn = (lower_insn & ~(bfd_vma) 0x2fff) | (I1 << 13) | (I2 << 11) | lo;
+	}
+
+	/* Put the relocated value back in the object file:  */
+	bfd_put_16 (input_bfd, upper_insn, hit_data);
+	bfd_put_16 (input_bfd, lower_insn, hit_data + 2);
+
+	return (overflow ? bfd_reloc_overflow : bfd_reloc_ok);
+      }
+
     case R_ARM_THM_JUMP11:
     case R_ARM_THM_JUMP8:
+    case R_ARM_THM_JUMP6:
       /* Thumb B (branch) instruction).  */
       {
 	bfd_signed_vma relocation;
@@ -3318,6 +3467,10 @@
 	bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
 	bfd_signed_vma signed_check;
 
+	/* CZB cannot jump backward.  */
+	if (r_type == R_ARM_THM_JUMP6)
+	  reloc_signed_min = 0;
+
 	if (globals->use_rel)
 	  {
 	    /* Need to refetch addend.  */
@@ -3343,7 +3496,11 @@
 
 	relocation >>= howto->rightshift;
 	signed_check = relocation;
-	relocation &= howto->dst_mask;
+
+	if (r_type == R_ARM_THM_JUMP6)
+	  relocation = ((relocation & 0x0020) << 4) | ((relocation & 0x001f) << 3);
+	else
+	  relocation &= howto->dst_mask;
 	relocation |= (bfd_get_16 (input_bfd, hit_data) & (~ howto->dst_mask));
 
 	bfd_put_16 (input_bfd, relocation, hit_data);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-04-26 10:21 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-04-26 10:21 Thumb32 assembler (65/69) Zack Weinberg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).