2005-02-02 Paul Brook <paul@codesourcery.com>
authorPaul Brook <paul@codesourcery.com>
Thu, 2 Feb 2006 13:34:17 +0000 (13:34 +0000)
committerPaul Brook <paul@codesourcery.com>
Thu, 2 Feb 2006 13:34:17 +0000 (13:34 +0000)
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.

gas/ChangeLog
gas/config/tc-arm.c
gas/testsuite/ChangeLog
gas/testsuite/gas/arm/thumb2_invert.d [new file with mode: 0644]
gas/testsuite/gas/arm/thumb2_invert.s [new file with mode: 0644]

index 77d896e..e35956e 100644 (file)
@@ -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
index dc315c0..8cf49ea 100644 (file)
@@ -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.  */
index f2e907f..99cb994 100644 (file)
@@ -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 (file)
index 0000000..3880e5b
--- /dev/null
@@ -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 (file)
index 0000000..38ebcdd
--- /dev/null
@@ -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