2006-05-11 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.
This commit is contained in:
parent
e28387c3bf
commit
b6895b4f37
13 changed files with 443 additions and 17 deletions
|
@ -1,3 +1,13 @@
|
|||
2006-05-11 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2006-05-11 Mike Bland <mbland@google.com>
|
||||
|
||||
* elf.c (_bfd_elf_init_private_section_data): Don't change
|
||||
|
|
|
@ -2897,6 +2897,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,
|
||||
|
|
101
bfd/elf32-arm.c
101
bfd/elf32-arm.c
|
@ -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
|
||||
|
|
|
@ -1208,6 +1208,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",
|
||||
|
|
18
bfd/reloc.c
18
bfd/reloc.c
|
@ -2701,6 +2701,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
|
||||
|
|
|
@ -1,3 +1,15 @@
|
|||
2006-05-11 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* 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
|
||||
|
||||
2006-05-11 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* config/tc-arm.c (arm_fix_adjustable): Return 0 for function symbols.
|
||||
|
|
|
@ -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
|
||||
|
@ -13425,8 +13500,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),
|
||||
|
@ -16761,6 +16836,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,
|
||||
|
@ -16815,6 +16931,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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2006-05-11 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2006-05-11 Mike Bland <mbland@google.com>
|
||||
|
||||
* ld-elf/stab.d: New.
|
||||
|
|
|
@ -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
|
||||
|
|
39
ld/testsuite/ld-arm/arm-movwt.d
Normal file
39
ld/testsuite/ld-arm/arm-movwt.d
Normal file
|
@ -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
|
||||
|
44
ld/testsuite/ld-arm/arm-movwt.s
Normal file
44
ld/testsuite/ld-arm/arm-movwt.s
Normal file
|
@ -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)
|
|
@ -14,5 +14,7 @@ SECTIONS
|
|||
} =0
|
||||
. = 0x9000;
|
||||
.got : { *(.got) *(.got.plt)}
|
||||
. = 0x12340000;
|
||||
.far : { *(.far) }
|
||||
.ARM.attribues 0 : { *(.ARM.atttributes) }
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue