aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Brook <paul@codesourcery.com>2006-02-02 13:34:17 +0000
committerPaul Brook <paul@codesourcery.com>2006-02-02 13:34:17 +0000
commitef8d22e63b889bff1ac315e95eb33b78c7ea8949 (patch)
tree04d69759355a82501c3ac39d2442de0084c0cbec
parent59f6d9d6f82ccc6c306740f7eedb613fe0f281a3 (diff)
downloadfsf-binutils-gdb-ef8d22e63b889bff1ac315e95eb33b78c7ea8949.zip
fsf-binutils-gdb-ef8d22e63b889bff1ac315e95eb33b78c7ea8949.tar.gz
fsf-binutils-gdb-ef8d22e63b889bff1ac315e95eb33b78c7ea8949.tar.bz2
2005-02-02 Paul Brook <paul@codesourcery.com>
gas/ * config/tc-arm.c (T2_OPCODE_MASK, T2_DATA_OP_SHIFT, T2_OPCODE_AND, T2_OPCODE_BIC, T2_OPCODE_ORR, T2_OPCODE_ORN, T2_OPCODE_EOR, T2_OPCODE_ADD, T2_OPCODE_ADC, T2_OPCODE_SBC, T2_OPCODE_SUB, T2_OPCODE_RSB): Define. (thumb32_negate_data_op): New function. (md_apply_fix): Use it. gas/testsuite/ * gas/arm/thumb2_invert.d: New test. * gas/arm/thumb2_invert.s: New test.
-rw-r--r--gas/ChangeLog9
-rw-r--r--gas/config/tc-arm.c96
-rw-r--r--gas/testsuite/ChangeLog5
-rw-r--r--gas/testsuite/gas/arm/thumb2_invert.d16
-rw-r--r--gas/testsuite/gas/arm/thumb2_invert.s14
5 files changed, 139 insertions, 1 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 77d896e..e35956e 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,12 @@
+2005-02-02 Paul Brook <paul@codesourcery.com>
+
+ * config/tc-arm.c (T2_OPCODE_MASK, T2_DATA_OP_SHIFT, T2_OPCODE_AND,
+ T2_OPCODE_BIC, T2_OPCODE_ORR, T2_OPCODE_ORN, T2_OPCODE_EOR,
+ T2_OPCODE_ADD, T2_OPCODE_ADC, T2_OPCODE_SBC, T2_OPCODE_SUB,
+ T2_OPCODE_RSB): Define.
+ (thumb32_negate_data_op): New function.
+ (md_apply_fix): Use it.
+
2006-01-31 Bob Wilson <bob.wilson@acm.org>
* config/xtensa-istack.h (TInsn): Remove record_fix and sub_symbol
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index dc315c0..8cf49ea 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -460,6 +460,9 @@ struct asm_opcode
#define DATA_OP_SHIFT 21
+#define T2_OPCODE_MASK 0xfe1fffff
+#define T2_DATA_OP_SHIFT 21
+
/* Codes to distinguish the arithmetic instructions. */
#define OPCODE_AND 0
#define OPCODE_EOR 1
@@ -478,6 +481,17 @@ struct asm_opcode
#define OPCODE_BIC 14
#define OPCODE_MVN 15
+#define T2_OPCODE_AND 0
+#define T2_OPCODE_BIC 1
+#define T2_OPCODE_ORR 2
+#define T2_OPCODE_ORN 3
+#define T2_OPCODE_EOR 4
+#define T2_OPCODE_ADD 8
+#define T2_OPCODE_ADC 10
+#define T2_OPCODE_SBC 11
+#define T2_OPCODE_SUB 13
+#define T2_OPCODE_RSB 14
+
#define T_OPCODE_MUL 0x4340
#define T_OPCODE_TST 0x4200
#define T_OPCODE_CMN 0x42c0
@@ -11113,6 +11127,82 @@ negate_data_op (unsigned long * instruction,
return value;
}
+/* Like negate_data_op, but for Thumb-2. */
+
+static unsigned int
+thumb32_negate_data_op (offsetT *instruction, offsetT value)
+{
+ int op, new_inst;
+ int rd;
+ offsetT negated, inverted;
+
+ negated = encode_thumb32_immediate (-value);
+ inverted = encode_thumb32_immediate (~value);
+
+ rd = (*instruction >> 8) & 0xf;
+ op = (*instruction >> T2_DATA_OP_SHIFT) & 0xf;
+ switch (op)
+ {
+ /* ADD <-> SUB. Includes CMP <-> CMN. */
+ case T2_OPCODE_SUB:
+ new_inst = T2_OPCODE_ADD;
+ value = negated;
+ break;
+
+ case T2_OPCODE_ADD:
+ new_inst = T2_OPCODE_SUB;
+ value = negated;
+ break;
+
+ /* ORR <-> ORN. Includes MOV <-> MVN. */
+ case T2_OPCODE_ORR:
+ new_inst = T2_OPCODE_ORN;
+ value = inverted;
+ break;
+
+ case T2_OPCODE_ORN:
+ new_inst = T2_OPCODE_ORR;
+ value = inverted;
+ break;
+
+ /* AND <-> BIC. TST has no inverted equivalent. */
+ case T2_OPCODE_AND:
+ new_inst = T2_OPCODE_BIC;
+ if (rd == 15)
+ value = FAIL;
+ else
+ value = inverted;
+ break;
+
+ case T2_OPCODE_BIC:
+ new_inst = T2_OPCODE_AND;
+ value = inverted;
+ break;
+
+ /* ADC <-> SBC */
+ case T2_OPCODE_ADC:
+ new_inst = T2_OPCODE_SBC;
+ value = inverted;
+ break;
+
+ case T2_OPCODE_SBC:
+ new_inst = T2_OPCODE_ADC;
+ value = inverted;
+ break;
+
+ /* We cannot do anything. */
+ default:
+ return FAIL;
+ }
+
+ if (value == FAIL)
+ return FAIL;
+
+ *instruction &= T2_OPCODE_MASK;
+ *instruction |= new_inst << T2_DATA_OP_SHIFT;
+ return value;
+}
+
/* Read a 32-bit thumb instruction from buf. */
static unsigned long
get_thumb32_insn (char * buf)
@@ -11465,7 +11555,11 @@ md_apply_fix (fixS * fixP,
/* FUTURE: Implement analogue of negate_data_op for T32. */
if (fixP->fx_r_type == BFD_RELOC_ARM_T32_IMMEDIATE)
- newimm = encode_thumb32_immediate (value);
+ {
+ newimm = encode_thumb32_immediate (value);
+ if (newimm == (unsigned int) FAIL)
+ newimm = thumb32_negate_data_op (&newval, value);
+ }
else
{
/* 12 bit immediate for addw/subw. */
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index f2e907f..99cb994 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2005-02-02 Paul Brook <paul@codesourcery.com>
+
+ * gas/arm/thumb2_invert.d: New test.
+ * gas/arm/thumb2_invert.s: New test.
+
2006-01-31 Paul Brook <paul@codesourcery.com>
* gas/testsuite/gas/arm/iwmmxt-bad.s: Add check for bad register name.
diff --git a/gas/testsuite/gas/arm/thumb2_invert.d b/gas/testsuite/gas/arm/thumb2_invert.d
new file mode 100644
index 0000000..3880e5b
--- /dev/null
+++ b/gas/testsuite/gas/arm/thumb2_invert.d
@@ -0,0 +1,16 @@
+# as: -march=armv6kt2
+# objdump: -dr --prefix-addresses --show-raw-insn
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+0+000 <[^>]+> f517 0f80 cmn.w r7, #4194304 ; 0x400000
+0+004 <[^>]+> f5b8 0f80 cmp.w r8, #4194304 ; 0x400000
+0+008 <[^>]+> f5a4 0980 sub.w r9, r4, #4194304 ; 0x400000
+0+00c <[^>]+> f506 0380 add.w r3, r6, #4194304 ; 0x400000
+0+010 <[^>]+> f160 4500 sbc.w r5, r0, #2147483648 ; 0x80000000
+0+014 <[^>]+> f147 4400 adc.w r4, r7, #2147483648 ; 0x80000000
+0+018 <[^>]+> f022 4600 bic.w r6, r2, #2147483648 ; 0x80000000
+0+01c <[^>]+> f002 4800 and.w r8, r2, #2147483648 ; 0x80000000
+0+020 <[^>]+> f06f 4300 mvn.w r3, #2147483648 ; 0x80000000
+0+024 <[^>]+> f04f 4100 mov.w r1, #2147483648 ; 0x80000000
diff --git a/gas/testsuite/gas/arm/thumb2_invert.s b/gas/testsuite/gas/arm/thumb2_invert.s
new file mode 100644
index 0000000..38ebcdd
--- /dev/null
+++ b/gas/testsuite/gas/arm/thumb2_invert.s
@@ -0,0 +1,14 @@
+ .text
+ .thumb
+ .syntax unified
+thumb2_invert:
+ cmp r7, #0xffc00000
+ cmn r8, #0xffc00000
+ add r9, r4, #0xffc00000
+ sub r3, r6, #0xffc00000
+ adc r5, r0, #0x7fffffff
+ sbc r4, r7, #0x7fffffff
+ and r6, r2, #0x7fffffff
+ bic r8, r2, #0x7fffffff
+ mov r3, 0x7fffffff
+ mvn r1, 0x7fffffff