summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2012-04-12 07:46:54 +0000
committerNick Clifton <nickc@redhat.com>2012-04-12 07:46:54 +0000
commit6530b175a1051db81806d031b8ab2937744ff57b (patch)
tree3af9a7137c724b8db9731019fd811e2269559d2e
parent202e23565d36f4696d5e836ec06d4c685c30fb16 (diff)
downloadbinutils-gdb-6530b175a1051db81806d031b8ab2937744ff57b.tar.gz
* config/tc-arm.c (only_one_reg_in_list): New function.
(encode_ldmstm): Ditto. (do_ldmstm): Use a different encoding when pushing or poping a single register. (A_COND_MASK): New macro. (A_PUSH_POP_OP_MASK): Ditto. (A1_OPCODE_PUSH): Ditto. (A2_OPCODE_PUSH): Ditto. (A2_OPCODE_POP): Ditto. * gas/arm/push-pop.d: New testcase. * gas/arm/push-pop.s: Ditto. * gas/arm/stm-ldm.d: Ditto. * gas/arm/stm-ldm.s: Ditto.
-rw-r--r--gas/ChangeLog13
-rw-r--r--gas/config/tc-arm.c39
-rw-r--r--gas/testsuite/ChangeLog8
3 files changed, 58 insertions, 2 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 6243dfe802d..b1d863af0f8 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,16 @@
+2012-04-12 Jie Zhang <jie@codesourcery.com>
+ Meador Inge <meadori@codesourcery.com>
+
+ * config/tc-arm.c (only_one_reg_in_list): New function.
+ (encode_ldmstm): Ditto.
+ (do_ldmstm): Use a different encoding when pushing or poping
+ a single register.
+ (A_COND_MASK): New macro.
+ (A_PUSH_POP_OP_MASK): Ditto.
+ (A1_OPCODE_PUSH): Ditto.
+ (A2_OPCODE_PUSH): Ditto.
+ (A2_OPCODE_POP): Ditto.
+
2012-04-06 Maciej W. Rozycki <macro@linux-mips.org>
* doc/c-mips.texi (MIPS Opts): Correct -no-mfix-24k to
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 585f78e0a29..545b7ec7a39 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -622,6 +622,14 @@ struct asm_opcode
#define T2_OPCODE_MASK 0xfe1fffff
#define T2_DATA_OP_SHIFT 21
+#define A_COND_MASK 0xf0000000
+#define A_PUSH_POP_OP_MASK 0x0fff0000
+
+/* Opcodes for pushing/poping registers to/from the stack. */
+#define A1_OPCODE_PUSH 0x092d0000
+#define A2_OPCODE_PUSH 0x052d0004
+#define A2_OPCODE_POP 0x049d0004
+
/* Codes to distinguish the arithmetic instructions. */
#define OPCODE_AND 0
#define OPCODE_EOR 1
@@ -7795,11 +7803,21 @@ do_it (void)
}
}
+/* If there is only one register in the register list,
+ then return its register number. Otherwise return -1. */
+static int
+only_one_reg_in_list (int range)
+{
+ int i = ffs (range) - 1;
+ return (i > 15 || range != (1 << i)) ? -1 : i;
+}
+
static void
-do_ldmstm (void)
+encode_ldmstm(int from_push_pop_mnem)
{
int base_reg = inst.operands[0].reg;
int range = inst.operands[1].imm;
+ int one_reg;
inst.instruction |= base_reg << 16;
inst.instruction |= range;
@@ -7832,6 +7850,23 @@ do_ldmstm (void)
as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
}
}
+
+ /* If PUSH/POP has only one register, then use the A2 encoding. */
+ one_reg = only_one_reg_in_list (range);
+ if (from_push_pop_mnem && one_reg >= 0)
+ {
+ int is_push = (inst.instruction & A_PUSH_POP_OP_MASK) == A1_OPCODE_PUSH;
+
+ inst.instruction &= A_COND_MASK;
+ inst.instruction |= is_push ? A2_OPCODE_PUSH : A2_OPCODE_POP;
+ inst.instruction |= one_reg << 12;
+ }
+}
+
+static void
+do_ldmstm (void)
+{
+ encode_ldmstm (/*from_push_pop_mnem=*/FALSE);
}
/* ARMv5TE load-consecutive (argument parse)
@@ -8333,7 +8368,7 @@ do_push_pop (void)
inst.operands[0].isreg = 1;
inst.operands[0].writeback = 1;
inst.operands[0].reg = REG_SP;
- do_ldmstm ();
+ encode_ldmstm (/*from_push_pop_mnem=*/TRUE);
}
/* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index d509b7d6c2c..b9e884f903c 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2012-04-12 Jie Zhang <jie@codesourcery.com>
+ Meador Inge <meadori@codesourcery.com>
+
+ * gas/arm/push-pop.d: New testcase.
+ * gas/arm/push-pop.s: Ditto.
+ * gas/arm/stm-ldm.d: Ditto.
+ * gas/arm/stm-ldm.s: Ditto.
+
2012-04-07 David S. Miller <davem@davemloft.net>
* gas/all/gas.exp: Sparc can handle BFD_RELOC_8 for constants.