aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-arm.c
diff options
context:
space:
mode:
authorPaul Brook <paul@codesourcery.com>2007-05-25 23:13:24 +0000
committerPaul Brook <paul@codesourcery.com>2007-05-25 23:13:24 +0000
commitefd81785d9f5514e7923ad65b452d5a704989707 (patch)
treea1d0282fea6b096f0ac01e23e1b128cf89ed3fa0 /gas/config/tc-arm.c
parent4e591bc17f3673b8ce16210891aa9557e2bd5a9f (diff)
downloadgdb-efd81785d9f5514e7923ad65b452d5a704989707.zip
gdb-efd81785d9f5514e7923ad65b452d5a704989707.tar.gz
gdb-efd81785d9f5514e7923ad65b452d5a704989707.tar.bz2
2007-03-25 Paul Brook <paul@codesourcery.com>
gas/ * config/tc-arm.c (T2_SUBS_PC_LR): Define. (do_t_add_sub): Correctly encode subs pc, lr, #const. (do_t_mov_cmp): Correctly encode movs pc, lr. gas/testsulte/ * gas/arm/thumb32.s: Add tests for subs pc, lr. * gas/arm/thumb32.d: Change error-output: to stderr:. Update expected output.
Diffstat (limited to 'gas/config/tc-arm.c')
-rw-r--r--gas/config/tc-arm.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 2a9c7ab..2cb28d4 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -555,6 +555,8 @@ struct asm_opcode
#define OPCODE_MASK 0xfe1fffff
#define V4_STR_BIT 0x00000020
+#define T2_SUBS_PC_LR 0xf3de8f00
+
#define DATA_OP_SHIFT 21
#define T2_OPCODE_MASK 0xfe1fffff
@@ -8439,7 +8441,21 @@ do_t_add_sub (void)
if (inst.size_req == 4
|| (inst.size_req != 2 && !opcode))
{
- if (Rs == REG_PC)
+ if (Rd == REG_PC)
+ {
+ constraint (Rs != REG_LR || inst.instruction != T_MNEM_subs,
+ _("only SUBS PC, LR, #const allowed"));
+ constraint (inst.reloc.exp.X_op != O_constant,
+ _("expression too complex"));
+ constraint (inst.reloc.exp.X_add_number < 0
+ || inst.reloc.exp.X_add_number > 0xff,
+ _("immediate value out of range"));
+ inst.instruction = T2_SUBS_PC_LR
+ | inst.reloc.exp.X_add_number;
+ inst.reloc.type = BFD_RELOC_UNUSED;
+ return;
+ }
+ else if (Rs == REG_PC)
{
/* Always use addw/subw. */
inst.instruction = add ? 0xf20f0000 : 0xf2af0000;
@@ -9486,6 +9502,16 @@ do_t_mov_cmp (void)
|| inst.operands[1].shifted)
narrow = FALSE;
+ /* MOVS PC, LR is encoded as SUBS PC, LR, #0. */
+ if (opcode == T_MNEM_movs && inst.operands[1].isreg
+ && !inst.operands[1].shifted
+ && inst.operands[0].reg == REG_PC
+ && inst.operands[1].reg == REG_LR)
+ {
+ inst.instruction = T2_SUBS_PC_LR;
+ return;
+ }
+
if (!inst.operands[1].isreg)
{
/* Immediate operand. */