aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-arm.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2011-10-13 08:15:17 +0000
committerNick Clifton <nickc@redhat.com>2011-10-13 08:15:17 +0000
commit1be5fd2e2f15668fcd63974800012a7bb6b636e0 (patch)
tree164187aae0c17f0a37be03a7678c875712472137 /gas/config/tc-arm.c
parentdfb4547188c61f6686d459919e38e63c1f7ef999 (diff)
downloadgdb-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.c21
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;
}