This is the mail archive of the binutils@sourceware.org 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]

[patch] Arm MOVW and MOVT relocations


The attached patch implements the ARM MOVW and MOVT relocations.These are 
fairly conventional RISC style relocations to allow loading a 32-bit value in 
two halves.

The assembly syntax for generating there (:lower16: and :upper16:) is the same 
as used by ARM's proprietary toolchain. I'm not particularly attached to this 
syntax, but it seems as good as anything.

This patch relies on my previous (unreviewed) patch to force relocations 
against function symbols:
http://sourceware.org/ml/binutils/2006-04/msg00007.html

Tested with cross to arm-none-eabi.
Ok?

Paul

2006-05-03  Paul Brook  <paul@codesourcery.com>

bfd/
	* elf32-arm.c (elf32_arm_reloc_map): Add MOVW and MOVT relocs.
	(elf32_arm_final_link_relocate): Handle MOVW and MOVT relocs.
	(elf32_arm_gc_sweep_hook, elf32_arm_check_relocs): Ditto.
	* reloc.c: Ditto.
	* bfd-in2.h: Regenerate.
	* libbfd.h: Regenerate.
	* libcoff.h: Regenerate.
gas/
	* config/tc-arm.c (parse_half): New function.
	(operand_parse_code): Remove OP_Iffff.  Add OP_HALF.
	(parse_operands): Ditto.
	(do_mov16): Reject invalid relocations.
	(do_t_mov16): Ditto.  Use Thumb reloc numbers.
	(insns): Replace Iffff with HALF.
	(md_apply_fix): Add MOVW and MOVT relocs.
	(tc_gen_reloc): Ditto.
	* doc/c-arm.texi: Document relocation operators
ld/testsuite/
	* ld-arm/arm-elf.exp: Add arm-movwt.
	* ld-arm/arm-movwt.d: New test.
	* ld-arm/arm-movwt.s: New test.
	* ld-arm/arm.ld: Add .far.
Index: bfd/bfd-in2.h
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/bfd-in2.h,v
retrieving revision 1.384
diff -u -p -r1.384 bfd-in2.h
--- bfd/bfd-in2.h	16 Mar 2006 12:20:16 -0000	1.384
+++ bfd/bfd-in2.h	2 May 2006 21:01:52 -0000
@@ -2893,6 +2893,16 @@ pc-relative or some form of GOT-indirect
 /* 31-bit PC relative address.  */
   BFD_RELOC_ARM_PREL31,
 
+/* Low and High halfword relocations for MOVW and MOVT instructions.  */
+  BFD_RELOC_ARM_MOVW,
+  BFD_RELOC_ARM_MOVT,
+  BFD_RELOC_ARM_MOVW_PCREL,
+  BFD_RELOC_ARM_MOVT_PCREL,
+  BFD_RELOC_ARM_THUMB_MOVW,
+  BFD_RELOC_ARM_THUMB_MOVT,
+  BFD_RELOC_ARM_THUMB_MOVW_PCREL,
+  BFD_RELOC_ARM_THUMB_MOVT_PCREL,
+
 /* Relocations for setting up GOTs and PLTs for shared libraries.  */
   BFD_RELOC_ARM_JUMP_SLOT,
   BFD_RELOC_ARM_GLOB_DAT,
Index: bfd/elf32-arm.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/elf32-arm.c,v
retrieving revision 1.70.2.1
diff -u -p -r1.70.2.1 elf32-arm.c
--- bfd/elf32-arm.c	1 May 2006 16:27:16 -0000	1.70.2.1
+++ bfd/elf32-arm.c	3 May 2006 00:04:56 -0000
@@ -1366,6 +1366,14 @@ static const struct elf32_arm_reloc_map 
     {BFD_RELOC_ARM_TLS_LE32,         R_ARM_TLS_LE32},
     {BFD_RELOC_VTABLE_INHERIT,	     R_ARM_GNU_VTINHERIT},
     {BFD_RELOC_VTABLE_ENTRY,	     R_ARM_GNU_VTENTRY},
+    {BFD_RELOC_ARM_MOVW,	     R_ARM_MOVW_ABS_NC},
+    {BFD_RELOC_ARM_MOVT,	     R_ARM_MOVT_ABS},
+    {BFD_RELOC_ARM_MOVW_PCREL,	     R_ARM_MOVW_PREL_NC},
+    {BFD_RELOC_ARM_MOVT_PCREL,	     R_ARM_MOVT_PREL},
+    {BFD_RELOC_ARM_THUMB_MOVW,	     R_ARM_THM_MOVW_ABS_NC},
+    {BFD_RELOC_ARM_THUMB_MOVT,	     R_ARM_THM_MOVT_ABS},
+    {BFD_RELOC_ARM_THUMB_MOVW_PCREL, R_ARM_THM_MOVW_PREL_NC},
+    {BFD_RELOC_ARM_THUMB_MOVT_PCREL, R_ARM_THM_MOVT_PREL},
   };
 
 static reloc_howto_type *
@@ -4080,6 +4088,76 @@ elf32_arm_final_link_relocate (reloc_how
         }
       return bfd_reloc_ok;
 
+    case R_ARM_MOVW_ABS_NC:
+    case R_ARM_MOVT_ABS:
+    case R_ARM_MOVW_PREL_NC:
+    case R_ARM_MOVT_PREL:
+      {
+	bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
+
+	if (globals->use_rel)
+	  {
+	    addend = ((insn >> 4) & 0xf000) | (insn & 0xfff);
+	    signed_addend = (addend ^ 0x10000) - 0x10000;
+	  }
+	value += signed_addend;
+	if (sym_flags == STT_ARM_TFUNC)
+	  value |= 1;
+
+	if (r_type == R_ARM_MOVW_PREL_NC || r_type == R_ARM_MOVT_PREL)
+	  value -= (input_section->output_section->vma
+		    + input_section->output_offset + rel->r_offset);
+
+	if (r_type == R_ARM_MOVT_ABS || r_type == R_ARM_MOVT_PREL)
+	  value >>= 16;
+
+	insn &= 0xfff0f000;
+	insn |= value & 0xfff;
+	insn |= (value & 0xf000) << 4;
+	bfd_put_32 (input_bfd, insn, hit_data);
+      }
+      return bfd_reloc_ok;
+
+    case R_ARM_THM_MOVW_ABS_NC:
+    case R_ARM_THM_MOVT_ABS:
+    case R_ARM_THM_MOVW_PREL_NC:
+    case R_ARM_THM_MOVT_PREL:
+      {
+	bfd_vma insn;
+	
+	insn = bfd_get_16 (input_bfd, hit_data) << 16;
+	insn |= bfd_get_16 (input_bfd, hit_data + 2);
+
+	if (globals->use_rel)
+	  {
+	    addend = ((insn >> 4)  & 0xf000)
+		   | ((insn >> 15) & 0x0800)
+		   | ((insn >> 4)  & 0x0700)
+		   | (insn         & 0x00ff);
+	    signed_addend = (addend ^ 0x10000) - 0x10000;
+	  }
+	value += signed_addend;
+	if (sym_flags == STT_ARM_TFUNC)
+	  value |= 1;
+
+	if (r_type == R_ARM_THM_MOVW_PREL_NC || r_type == R_ARM_THM_MOVT_PREL)
+	  value -= (input_section->output_section->vma
+		    + input_section->output_offset + rel->r_offset);
+
+	if (r_type == R_ARM_THM_MOVT_ABS || r_type == R_ARM_THM_MOVT_PREL)
+	  value >>= 16;
+
+	insn &= 0xfbf08f00;
+	insn |= (value & 0xf000) << 4;
+	insn |= (value & 0x0800) << 15;
+	insn |= (value & 0x0700) << 4;
+	insn |= (value & 0x00ff);
+
+	bfd_put_16 (input_bfd, insn >> 16, hit_data);
+	bfd_put_16 (input_bfd, insn & 0xffff, hit_data + 2);
+      }
+      return bfd_reloc_ok;
+
     default:
       return bfd_reloc_notsupported;
     }
@@ -5651,6 +5729,14 @@ elf32_arm_gc_sweep_hook (bfd *          
 	case R_ARM_JUMP24:
 	case R_ARM_PREL31:
 	case R_ARM_THM_CALL:
+	case R_ARM_MOVW_ABS_NC:
+	case R_ARM_MOVT_ABS:
+	case R_ARM_MOVW_PREL_NC:
+	case R_ARM_MOVT_PREL:
+	case R_ARM_THM_MOVW_ABS_NC:
+	case R_ARM_THM_MOVT_ABS:
+	case R_ARM_THM_MOVW_PREL_NC:
+	case R_ARM_THM_MOVT_PREL:
 	  /* Should the interworking branches be here also?  */
 
 	  if (h != NULL)
@@ -5861,6 +5947,14 @@ elf32_arm_check_relocs (bfd *abfd, struc
 	  case R_ARM_JUMP24:
 	  case R_ARM_PREL31:
 	  case R_ARM_THM_CALL:
+	  case R_ARM_MOVW_ABS_NC:
+	  case R_ARM_MOVT_ABS:
+	  case R_ARM_MOVW_PREL_NC:
+	  case R_ARM_MOVT_PREL:
+	  case R_ARM_THM_MOVW_ABS_NC:
+	  case R_ARM_THM_MOVT_ABS:
+	  case R_ARM_THM_MOVW_PREL_NC:
+	  case R_ARM_THM_MOVT_PREL:
 	    /* Should the interworking branches be listed here?  */
 	    if (h != NULL)
 	      {
@@ -5877,12 +5971,7 @@ elf32_arm_check_relocs (bfd *abfd, struc
 		   refers to is in a different object.  We can't tell for
 		   sure yet, because something later might force the
 		   symbol local.  */
-		if (r_type == R_ARM_PC24
-		    || r_type == R_ARM_CALL
-		    || r_type == R_ARM_JUMP24
-		    || r_type == R_ARM_PREL31
-		    || r_type == R_ARM_PLT32
-		    || r_type == R_ARM_THM_CALL)
+		if (r_type != R_ARM_ABS32 && r_type != R_ARM_REL32)
 		  h->needs_plt = 1;
 
 		/* If we create a PLT entry, this relocation will reference
Index: bfd/libbfd.h
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/libbfd.h,v
retrieving revision 1.175
diff -u -p -r1.175 libbfd.h
--- bfd/libbfd.h	16 Mar 2006 12:20:16 -0000	1.175
+++ bfd/libbfd.h	2 May 2006 21:01:52 -0000
@@ -1198,6 +1198,14 @@ static const char *const bfd_reloc_code_
   "BFD_RELOC_ARM_SBREL32",
   "BFD_RELOC_ARM_TARGET2",
   "BFD_RELOC_ARM_PREL31",
+  "BFD_RELOC_ARM_MOVW",
+  "BFD_RELOC_ARM_MOVT",
+  "BFD_RELOC_ARM_MOVW_PCREL",
+  "BFD_RELOC_ARM_MOVT_PCREL",
+  "BFD_RELOC_ARM_THUMB_MOVW",
+  "BFD_RELOC_ARM_THUMB_MOVT",
+  "BFD_RELOC_ARM_THUMB_MOVW_PCREL",
+  "BFD_RELOC_ARM_THUMB_MOVT_PCREL",
   "BFD_RELOC_ARM_JUMP_SLOT",
   "BFD_RELOC_ARM_GLOB_DAT",
   "BFD_RELOC_ARM_GOT32",
Index: bfd/reloc.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/reloc.c,v
retrieving revision 1.149
diff -u -p -r1.149 reloc.c
--- bfd/reloc.c	3 Mar 2006 15:25:29 -0000	1.149
+++ bfd/reloc.c	2 May 2006 21:01:46 -0000
@@ -2683,6 +2683,24 @@ ENUM
   BFD_RELOC_ARM_PREL31
 ENUMDOC
   31-bit PC relative address.
+ENUM
+  BFD_RELOC_ARM_MOVW
+ENUMX
+  BFD_RELOC_ARM_MOVT
+ENUMX
+  BFD_RELOC_ARM_MOVW_PCREL
+ENUMX
+  BFD_RELOC_ARM_MOVT_PCREL
+ENUMX
+  BFD_RELOC_ARM_THUMB_MOVW
+ENUMX
+  BFD_RELOC_ARM_THUMB_MOVT
+ENUMX
+  BFD_RELOC_ARM_THUMB_MOVW_PCREL
+ENUMX
+  BFD_RELOC_ARM_THUMB_MOVT_PCREL
+ENUMDOC
+  Low and High halfword relocations for MOVW and MOVT instructions.
 
 ENUM
   BFD_RELOC_ARM_JUMP_SLOT
Index: gas/config/tc-arm.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/config/tc-arm.c,v
retrieving revision 1.250.2.13
diff -u -p -r1.250.2.13 tc-arm.c
--- gas/config/tc-arm.c	2 May 2006 14:51:29 -0000	1.250.2.13
+++ gas/config/tc-arm.c	2 May 2006 22:52:53 -0000
@@ -4435,6 +4435,46 @@ parse_address (char **str, int i)
   return SUCCESS;
 }
 
+/* Parse an operand for a MOVW or MOVT instruction.  */
+static int
+parse_half (char **str)
+{
+  char * p;
+  
+  p = *str;
+  skip_past_char (&p, '#');
+  if (strncasecmp (p, ":lower16:", 9) == 0) 
+    inst.reloc.type = BFD_RELOC_ARM_MOVW;
+  else if (strncasecmp (p, ":upper16:", 9) == 0)
+    inst.reloc.type = BFD_RELOC_ARM_MOVT;
+
+  if (inst.reloc.type != BFD_RELOC_UNUSED)
+    {
+      p += 9;
+      skip_whitespace(p);
+    }
+
+  if (my_get_expression (&inst.reloc.exp, &p, GE_NO_PREFIX))
+    return FAIL;
+
+  if (inst.reloc.type == BFD_RELOC_UNUSED)
+    {
+      if (inst.reloc.exp.X_op != O_constant)
+	{
+	  inst.error = _("constant expression expected");
+	  return FAIL;
+	}
+      if (inst.reloc.exp.X_add_number < 0
+	  || inst.reloc.exp.X_add_number > 0xffff)
+	{
+	  inst.error = _("immediate value out of range");
+	  return FAIL;
+	}
+    }
+  *str = p;
+  return SUCCESS;
+}
+
 /* Miscellaneous. */
 
 /* Parse a PSR flag operand.  The value returned is FAIL on syntax error,
@@ -4925,7 +4965,6 @@ enum operand_parse_code
   OP_I64,	/*		   1 .. 64 */
   OP_I64z,	/*		   0 .. 64 */
   OP_I255,	/*		   0 .. 255 */
-  OP_Iffff,	/*		   0 .. 65535 */
 
   OP_I4b,	/* immediate, prefix optional, 1 .. 4 */
   OP_I7b,	/*			       0 .. 7 */
@@ -4937,6 +4976,7 @@ enum operand_parse_code
   OP_EXP,	/* arbitrary expression */
   OP_EXPi,	/* same, with optional immediate prefix */
   OP_EXPr,	/* same, with optional relocation suffix */
+  OP_HALF,	/* 0 .. 65535 or low/high reloc.  */
 
   OP_CPSF,	/* CPS flags */
   OP_ENDI,	/* Endianness specifier */
@@ -5197,7 +5237,6 @@ parse_operands (char *str, const unsigne
         case OP_I64:	 po_imm_or_fail (  1,     64, FALSE);   break;
         case OP_I64z:	 po_imm_or_fail (  0,     64, FALSE);   break;
 	case OP_I255:	 po_imm_or_fail (  0,	 255, FALSE);	break;
-	case OP_Iffff:	 po_imm_or_fail (  0, 0xffff, FALSE);	break;
 
 	case OP_I4b:	 po_imm_or_fail (  1,	   4, TRUE);	break;
 	case OP_oI7b:
@@ -5263,6 +5302,11 @@ parse_operands (char *str, const unsigne
 	    }
 	  break;
 
+	  /* Operand for MOVW or MOVT.  */
+	case OP_HALF:
+	  po_misc_or_fail (parse_half (&str));
+	  break;
+
 	  /* Register or expression */
 	case OP_RR_EXr:	  po_reg_or_goto (REG_TYPE_RN, EXPr); break;
 	case OP_RR_EXi:	  po_reg_or_goto (REG_TYPE_RN, EXPi); break;
@@ -6438,10 +6482,22 @@ do_mov (void)
 static void
 do_mov16 (void)
 {
-  inst.instruction |= inst.operands[0].reg << 12;
-  /* The value is in two pieces: 0:11, 16:19.  */
-  inst.instruction |= (inst.operands[1].imm & 0x00000fff);
-  inst.instruction |= (inst.operands[1].imm & 0x0000f000) << 4;
+  bfd_vma imm;
+  bfd_boolean top;
+
+  top = (inst.instruction & 0x00400000) != 0;
+  constraint (top && inst.reloc.type == BFD_RELOC_ARM_MOVW,
+	      _(":lower16: not allowed this instruction"));
+  constraint (!top && inst.reloc.type == BFD_RELOC_ARM_MOVT,
+	      _(":upper16: not allowed instruction"));
+  inst.instruction |= inst.operands[0].reg << 12;
+  if (inst.reloc.type == BFD_RELOC_UNUSED)
+    {
+      imm = inst.reloc.exp.X_add_number;
+      /* The value is in two pieces: 0:11, 16:19.  */
+      inst.instruction |= (imm & 0x00000fff);
+      inst.instruction |= (imm & 0x0000f000) << 4;
+    }
 }
 
 static void
@@ -8709,11 +8765,30 @@ do_t_mov_cmp (void)
 static void
 do_t_mov16 (void)
 {
+  bfd_vma imm;
+  bfd_boolean top;
+
+  top = (inst.instruction & 0x00800000) != 0;
+  if (inst.reloc.type == BFD_RELOC_ARM_MOVW)
+    {
+      constraint (top, _(":lower16: not allowed this instruction"));
+      inst.reloc.type = BFD_RELOC_ARM_THUMB_MOVW;
+    }
+  else if (inst.reloc.type == BFD_RELOC_ARM_MOVT)
+    {
+      constraint (!top, _(":upper16: not allowed this instruction"));
+      inst.reloc.type = BFD_RELOC_ARM_THUMB_MOVT;
+    }
+
   inst.instruction |= inst.operands[0].reg << 8;
-  inst.instruction |= (inst.operands[1].imm & 0xf000) << 4;
-  inst.instruction |= (inst.operands[1].imm & 0x0800) << 15;
-  inst.instruction |= (inst.operands[1].imm & 0x0700) << 4;
-  inst.instruction |= (inst.operands[1].imm & 0x00ff);
+  if (inst.reloc.type == BFD_RELOC_UNUSED)
+    {
+      imm = inst.reloc.exp.X_add_number;
+      inst.instruction |= (imm & 0xf000) << 4;
+      inst.instruction |= (imm & 0x0800) << 15;
+      inst.instruction |= (imm & 0x0700) << 4;
+      inst.instruction |= (imm & 0x00ff);
+    }
 }
 
 static void
@@ -13407,8 +13482,8 @@ static const struct asm_opcode insns[] =
  TCE(ubfx,	7e00050, f3c00000, 4, (RR, RR, I31, I32),	   bfx, t_bfx),
 
  TCE(mls,	0600090, fb000010, 4, (RRnpc, RRnpc, RRnpc, RRnpc), mlas, t_mla),
- TCE(movw,	3000000, f2400000, 2, (RRnpc, Iffff),		    mov16, t_mov16),
- TCE(movt,	3400000, f2c00000, 2, (RRnpc, Iffff),		    mov16, t_mov16),
+ TCE(movw,	3000000, f2400000, 2, (RRnpc, HALF),		    mov16, t_mov16),
+ TCE(movt,	3400000, f2c00000, 2, (RRnpc, HALF),		    mov16, t_mov16),
  TCE(rbit,	3ff0f30, fa90f0a0, 2, (RR, RR),			    rd_rm, t_rbit),
 
  TC3(ldrht,	03000b0, f8300e00, 2, (RR, ADDR), ldsttv4, t_ldstt),
@@ -16722,6 +16797,47 @@ md_apply_fix (fixS *	fixP,
       fixP->fx_done = 0;
       return;
 
+    case BFD_RELOC_ARM_MOVW:
+    case BFD_RELOC_ARM_MOVT:
+    case BFD_RELOC_ARM_THUMB_MOVW:
+    case BFD_RELOC_ARM_THUMB_MOVT:
+      if (fixP->fx_done || !seg->use_rela_p)
+	{
+	  /* REL format relocations are limited to a 16-bit addend.  */
+	  if (!fixP->fx_done)
+	    {
+	      if (value < -0x1000 || value > 0xffff)
+		  as_bad_where (fixP->fx_file, fixP->fx_line,
+				_("offset too big"));
+	    }
+	  else if (fixP->fx_r_type == BFD_RELOC_ARM_MOVT
+		   || fixP->fx_r_type == BFD_RELOC_ARM_THUMB_MOVT)
+	    {
+	      value >>= 16;
+	    }
+
+	  if (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_MOVW
+	      || fixP->fx_r_type == BFD_RELOC_ARM_THUMB_MOVT)
+	    {
+	      newval = get_thumb32_insn (buf);
+	      newval &= 0xfbf08f00;
+	      newval |= (value & 0xf000) << 4;
+	      newval |= (value & 0x0800) << 15;
+	      newval |= (value & 0x0700) << 4;
+	      newval |= (value & 0x00ff);
+	      put_thumb32_insn (buf, newval);
+	    }
+	  else
+	    {
+	      newval = md_chars_to_number (buf, 4);
+	      newval &= 0xfff0f000;
+	      newval |= value & 0x0fff;
+	      newval |= (value & 0xf000) << 4;
+	      md_number_to_chars (buf, newval, 4);
+	    }
+	}
+      return;
+
     case BFD_RELOC_UNUSED:
     default:
       as_bad_where (fixP->fx_file, fixP->fx_line,
@@ -16776,6 +16892,34 @@ tc_gen_reloc (asection *section, fixS *f
 	  break;
 	}
 
+    case BFD_RELOC_ARM_MOVW:
+      if (fixp->fx_pcrel)
+	{
+	  code = BFD_RELOC_ARM_MOVW_PCREL;
+	  break;
+	}
+
+    case BFD_RELOC_ARM_MOVT:
+      if (fixp->fx_pcrel)
+	{
+	  code = BFD_RELOC_ARM_MOVT_PCREL;
+	  break;
+	}
+
+    case BFD_RELOC_ARM_THUMB_MOVW:
+      if (fixp->fx_pcrel)
+	{
+	  code = BFD_RELOC_ARM_THUMB_MOVW_PCREL;
+	  break;
+	}
+
+    case BFD_RELOC_ARM_THUMB_MOVT:
+      if (fixp->fx_pcrel)
+	{
+	  code = BFD_RELOC_ARM_THUMB_MOVT_PCREL;
+	  break;
+	}
+
     case BFD_RELOC_NONE:
     case BFD_RELOC_ARM_PCREL_BRANCH:
     case BFD_RELOC_ARM_PCREL_BLX:
Index: gas/doc/c-arm.texi
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/doc/c-arm.texi,v
retrieving revision 1.37
diff -u -p -r1.37 c-arm.texi
--- gas/doc/c-arm.texi	10 Mar 2006 17:20:30 -0000	1.37
+++ gas/doc/c-arm.texi	3 May 2006 13:03:00 -0000
@@ -284,6 +284,7 @@ as position-independent code (PIC).
 @menu
 * ARM-Chars::                Special Characters
 * ARM-Regs::                 Register Names
+* ARM-Relocations::	     Relocations
 @end menu
 
 @node ARM-Chars
@@ -323,7 +324,46 @@ Either @samp{#} or @samp{$} can be used 
 @cindex ARM floating point (@sc{ieee})
 The ARM family uses @sc{ieee} floating-point numbers.
 
+@node ARM-Relocations
+@subsection ARM relocation generation
 
+@cindex data relocations, ARM
+@cindex ARM data relocations
+Specific data relocations can be generated by putting the relocation name
+in parentheses after the symbol name.  For example:
+
+@smallexample
+        .word foo(TARGET1)
+@end smallexample
+
+This will generate an @samp{R_ARM_TARGET1} relocation against the symbol
+@var{foo}.
+The following relocations are supported:
+@code{GOT},
+@code{GOTOFF},
+@code{TARGET1},
+@code{TARGET2},
+@code{SBREL},
+@code{TLSGD},
+@code{TLSLDM},
+@code{TLSLDO},
+@code{GOTTPOFF}
+and
+@code{TPOFF}.
+
+For compatibility with older toolchains the assembler also accepts
+@code{(PLT)} after branch targets.  This will generate the deprecated
+@samp{R_ARM_PLT32} relocation.
+
+@cindex MOVW and MOVT relocations, ARM
+Relocations for @samp{MOVW} and @samp{MOVT} instructions can be generated
+by prefixing the value with @samp{#:lower16:} and @samp{#:upper16}
+respectively.  For example to load the 32-bit addresss of foo into r0:
+
+@smallexample
+        MOVW r0, #:lower16:foo
+        MOVT r0, #:upper16:foo
+@end smallexample
 
 @node ARM Directives
 @section ARM Machine Directives
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /var/cvsroot/src-cvs/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.11.2.1
diff -u -p -r1.11.2.1 arm-elf.exp
--- ld/testsuite/ld-arm/arm-elf.exp	1 May 2006 16:27:16 -0000	1.11.2.1
+++ ld/testsuite/ld-arm/arm-elf.exp	2 May 2006 23:52:29 -0000
@@ -122,6 +122,9 @@ set armelftests {
     {"thumb-rel32" "-static -T arm.ld" "" {thumb-rel32.s}
      {{objdump -s thumb-rel32.d}}
      "thumb-rel32"}
+    {"MOVW/MOVT" "-static -T arm.ld" "" {arm-movwt.s}
+     {{objdump -dw arm-movwt.d}}
+     "arm-movwt"}
 }
 
 run_ld_link_tests $armelftests
Index: ld/testsuite/ld-arm/arm-movwt.d
===================================================================
RCS file: ld/testsuite/ld-arm/arm-movwt.d
diff -N ld/testsuite/ld-arm/arm-movwt.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/arm-movwt.d	2 May 2006 23:59:11 -0000
@@ -0,0 +1,39 @@
+
+.*:     file format.*
+
+Disassembly of section .text:
+
+00008000 <[^>]*>:
+    8000:	e3000000 	movw	r0, #0	; 0x0
+    8004:	e3411234 	movt	r1, #4660	; 0x1234
+    8008:	e3082000 	movw	r2, #32768	; 0x8000
+    800c:	e3413233 	movt	r3, #4659	; 0x1233
+    8010:	e3004011 	movw	r4, #17	; 0x11
+    8014:	e3415234 	movt	r5, #4660	; 0x1234
+    8018:	e3086011 	movw	r6, #32785	; 0x8011
+    801c:	e3417233 	movt	r7, #4659	; 0x1233
+
+00008020 <[^>]*>:
+    8020:	f240 0700 	movw	r7, #0	; 0x0
+    8024:	f2c1 2634 	movt	r6, #4660	; 0x1234
+    8028:	f248 0500 	movw	r5, #32768	; 0x8000
+    802c:	f2c1 2433 	movt	r4, #4659	; 0x1233
+    8030:	f240 0311 	movw	r3, #17	; 0x11
+    8034:	f2c1 2234 	movt	r2, #4660	; 0x1234
+    8038:	f248 0111 	movw	r1, #32785	; 0x8011
+    803c:	f2c1 2033 	movt	r0, #4659	; 0x1233
+
+Disassembly of section .far:
+
+12340000 <[^>]*>:
+12340000:	e3080000 	movw	r0, #32768	; 0x8000
+12340004:	e34e0dcc 	movt	r0, #60876	; 0xedcc
+12340008:	e3080021 	movw	r0, #32801	; 0x8021
+1234000c:	e34e0dcc 	movt	r0, #60876	; 0xedcc
+
+12340010 <[^>]*>:
+12340010:	f248 0000 	movw	r0, #32768	; 0x8000
+12340014:	f6ce 50cc 	movt	r0, #60876	; 0xedcc
+12340018:	f248 0021 	movw	r0, #32801	; 0x8021
+1234001c:	f6ce 50cc 	movt	r0, #60876	; 0xedcc
+
Index: ld/testsuite/ld-arm/arm-movwt.s
===================================================================
RCS file: ld/testsuite/ld-arm/arm-movwt.s
diff -N ld/testsuite/ld-arm/arm-movwt.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-arm/arm-movwt.s	2 May 2006 23:59:26 -0000
@@ -0,0 +1,44 @@
+	.text
+	.arch armv6t2
+	.syntax unified
+	.global	_start
+	.type	_start, %function
+_start:
+base1:
+arm1:
+	movw r0, #:lower16:arm2
+	movt r1, #:upper16:arm2
+	movw r2, #:lower16:(arm2 - arm1)
+	movt r3, #:upper16:(arm2 - arm1)
+	movw r4, #:lower16:thumb2
+	movt r5, #:upper16:thumb2
+	movw r6, #:lower16:(thumb2 - arm1)
+	movt r7, #:upper16:(thumb2 - arm1)
+	.thumb
+	.type thumb1, %function
+	.thumb_func
+thumb1:
+	movw r7, #:lower16:arm2
+	movt r6, #:upper16:arm2
+	movw r5, #:lower16:(arm2 - arm1)
+	movt r4, #:upper16:(arm2 - arm1)
+	movw r3, #:lower16:thumb2
+	movt r2, #:upper16:thumb2
+	movw r1, #:lower16:(thumb2 - arm1)
+	movt r0, #:upper16:(thumb2 - arm1)
+
+	.section .far, "ax", %progbits
+	.arm
+arm2:
+	movw r0, #:lower16:(arm1 - arm2)
+	movt r0, #:upper16:(arm1 - arm2)
+	movw r0, #:lower16:(thumb1 - arm2)
+	movt r0, #:upper16:(thumb1 - arm2)
+	.thumb
+	.type thumb2, %function
+	.thumb_func
+thumb2:
+	movw r0, #:lower16:(arm1 - arm2)
+	movt r0, #:upper16:(arm1 - arm2)
+	movw r0, #:lower16:(thumb1 - arm2)
+	movt r0, #:upper16:(thumb1 - arm2)
Index: ld/testsuite/ld-arm/arm.ld
===================================================================
RCS file: /var/cvsroot/src-cvs/src/ld/testsuite/ld-arm/arm.ld,v
retrieving revision 1.2
diff -u -p -r1.2 arm.ld
--- ld/testsuite/ld-arm/arm.ld	12 Dec 2005 17:03:40 -0000	1.2
+++ ld/testsuite/ld-arm/arm.ld	2 May 2006 21:54:15 -0000
@@ -14,5 +14,7 @@ SECTIONS
   } =0
   . = 0x9000;
   .got            : { *(.got) *(.got.plt)}
+  . = 0x12340000;
+  .far : { *(.far) }
   .ARM.attribues 0 : { *(.ARM.atttributes) }
 }

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