2006-05-03 Paul Brook <paul@codesourcery.com>
authorPaul Brook <paul@codesourcery.com>
Wed, 3 May 2006 14:30:24 +0000 (14:30 +0000)
committerPaul Brook <paul@codesourcery.com>
Wed, 3 May 2006 14:30:24 +0000 (14:30 +0000)
* 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.
* bfd/reloc.c: Ditto.
* bfd/bfd-in2.h: Regenerate.
* bfd/libbfd.h: Regenerate.
* bfd/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.
* gas/doc/c-arm.texi: Document relocation operators
* ld/testsuite/ld-arm/arm-elf.exp: Add arm-movwt.
* ld/testsuite/ld-arm/arm-movwt.d: New test.
* ld/testsuite/ld-arm/arm-movwt.s: New test.
* ld/testsuite/ld-arm/arm.ld: Add .far.

ChangeLog.csl
bfd/bfd-in2.h
bfd/elf32-arm.c
bfd/libbfd.h
bfd/reloc.c
gas/config/tc-arm.c
gas/doc/c-arm.texi
ld/testsuite/ld-arm/arm-elf.exp
ld/testsuite/ld-arm/arm-movwt.d [new file with mode: 0644]
ld/testsuite/ld-arm/arm-movwt.s [new file with mode: 0644]
ld/testsuite/ld-arm/arm.ld

index eaf8ce1..dc69626 100644 (file)
@@ -1,3 +1,26 @@
+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.
+       * bfd/reloc.c: Ditto.
+       * bfd/bfd-in2.h: Regenerate.
+       * bfd/libbfd.h: Regenerate.
+       * bfd/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.
+       * gas/doc/c-arm.texi: Document relocation operators
+       * ld/testsuite/ld-arm/arm-elf.exp: Add arm-movwt.
+       * ld/testsuite/ld-arm/arm-movwt.d: New test.
+       * ld/testsuite/ld-arm/arm-movwt.s: New test.
+       * ld/testsuite/ld-arm/arm.ld: Add .far.
+
 2006-05-02  Joseph Myers  <joseph@codesourcery.com>
 
        * gas/config/tc-arm.c (do_iwmmxt_wldstbh): Don't multiply offset
index 4a777ed..de564e2 100644 (file)
@@ -2893,6 +2893,16 @@ pc-relative or some form of GOT-indirect relocation.  */
 /* 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 f64f5d6..b350001 100644 (file)
@@ -1366,6 +1366,14 @@ static const struct elf32_arm_reloc_map 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_howto_type *           howto,
         }
       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 *                     abfd,
        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, struct bfd_link_info *info,
          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, struct bfd_link_info *info,
                   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 6d48036..7e61f36 100644 (file)
@@ -1198,6 +1198,14 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "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 31314e7..e7f9aed 100644 (file)
@@ -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 4e3e621..f970121 100644 (file)
@@ -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 unsigned char *pattern)
         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 unsigned char *pattern)
            }
          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)
 {
+  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;
-  /* 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;
+  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 *fixp)
          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 ca0998b..0b113f9 100644 (file)
@@ -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 to indicate immediate operands.
 @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 1a9fc00..04aa09c 100644 (file)
@@ -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
diff --git a/ld/testsuite/ld-arm/arm-movwt.d b/ld/testsuite/ld-arm/arm-movwt.d
new file mode 100644 (file)
index 0000000..bf55164
--- /dev/null
@@ -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
+
diff --git a/ld/testsuite/ld-arm/arm-movwt.s b/ld/testsuite/ld-arm/arm-movwt.s
new file mode 100644 (file)
index 0000000..ba8b1c5
--- /dev/null
@@ -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 4ef7d82..c9e01e6 100644 (file)
@@ -14,5 +14,7 @@ SECTIONS
   } =0
   . = 0x9000;
   .got            : { *(.got) *(.got.plt)}
+  . = 0x12340000;
+  .far : { *(.far) }
   .ARM.attribues 0 : { *(.ARM.atttributes) }
 }