diff options
author | Nick Clifton <nickc@redhat.com> | 2011-10-13 08:15:17 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2011-10-13 08:15:17 +0000 |
commit | 1be5fd2e2f15668fcd63974800012a7bb6b636e0 (patch) | |
tree | 164187aae0c17f0a37be03a7678c875712472137 /gas/config/tc-arm.c | |
parent | dfb4547188c61f6686d459919e38e63c1f7ef999 (diff) | |
download | gdb-1be5fd2e2f15668fcd63974800012a7bb6b636e0.zip gdb-1be5fd2e2f15668fcd63974800012a7bb6b636e0.tar.gz gdb-1be5fd2e2f15668fcd63974800012a7bb6b636e0.tar.bz2 |
* config/tc-arm.c (check_ldr_r15_aligned): New.
(do_ldst): Warn in upredictable cases.
(do_t_ldst): Likewise.
(insns): Update accordingly.
* gas/arm/ldr-bad.s: New testcase.
* gas/arm/ldr-bad.l: Likewise.
* gas/arm/ldr-bad.d: Likewise.
* gas/arm/ldr.s: Likewise.
* gas/arm/ldr.d: Likewise.
* gas/arm/ldr-t-bad.s: Likewise.
* gas/arm/ldr-t-bad.l: Likewise.
* gas/arm/ldr-t-bad.d: Likewise.
* gas/arm/ldr-t.s: Likewise.
* gas/arm/ldr-t.d: Likewise.
* gas/arm/sp-pc-usage-t.s: Correct.
* gas/arm/sp-pc-usage-t.d: Update accordingly.
Diffstat (limited to 'gas/config/tc-arm.c')
-rw-r--r-- | gas/config/tc-arm.c | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 77606a3..8189c51 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -7915,6 +7915,18 @@ do_ldrexd (void) inst.instruction |= inst.operands[2].reg << 16; } +/* In both ARM and thumb state 'ldr pc, #imm' with an immediate + which is not a multiple of four is UNPREDICTABLE. */ +static void +check_ldr_r15_aligned (void) +{ + constraint (!(inst.operands[1].immisreg) + && (inst.operands[0].reg == REG_PC + && inst.operands[1].reg == REG_PC + && (inst.reloc.exp.X_add_number & 0x3)), + _("ldr to register 15 must be 4-byte alligned")); +} + static void do_ldst (void) { @@ -7923,6 +7935,7 @@ do_ldst (void) if (move_or_literal_pool (0, /*thumb_p=*/FALSE, /*mode_3=*/FALSE)) return; encode_arm_addr_mode_2 (1, /*is_t=*/FALSE); + check_ldr_r15_aligned (); } static void @@ -10533,13 +10546,17 @@ do_t_ldst (void) } /* Do some validations regarding addressing modes. */ - if (inst.operands[1].immisreg && opcode != T_MNEM_ldr - && opcode != T_MNEM_str) + if (inst.operands[1].immisreg) reject_bad_reg (inst.operands[1].imm); + constraint (inst.operands[1].writeback == 1 + && inst.operands[0].reg == inst.operands[1].reg, + BAD_OVERLAP); + inst.instruction = THUMB_OP32 (opcode); inst.instruction |= inst.operands[0].reg << 12; encode_thumb32_addr_mode (1, /*is_t=*/FALSE, /*is_d=*/FALSE); + check_ldr_r15_aligned (); return; } |