Add support for converting LDR Rx,=<imm> to MOV or MVN in Thumb2 mode.
authorAlessandro Marzocchi <alessandro.marzocchi@gmail.com>
Wed, 17 Jun 2015 12:50:52 +0000 (13:50 +0100)
committerNick Clifton <nickc@redhat.com>
Wed, 17 Jun 2015 12:50:52 +0000 (13:50 +0100)
PR gas/18499
gas * config/tc-arm.c (move_or_literal_pool): Add support for LDR Rx,=
to MOV.w or MVN.w for Thumb2.

tests * gas/arm/thumb2_ldr_immediate_armv6.s: New test case.
* gas/arm/thumb2_ldr_immediate_armv6.d: Expected disassembly.
* gas/arm/thumb2_ldr_immediate_armv6t2.s: New test case.
* gas/arm/thumb2_ldr_immediate_armv6t2.d: Expected disassembly.

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

index b751117a3a234ed334f74b53e9f3d862a54311d2..b4e7d5fa8bd55f7771661f1189db381f7a929ded 100644 (file)
@@ -3,7 +3,11 @@
        PR gas/18500
        * config/tc-arm.c (is_double_a_single): New function.
        (double_to_single): New function.
-       (move_or_literal_pool): Add support for converting VLDR to VMOV.
+       (move_or_literal_pool): Add support for converting VLDR to VMOV.
+
+       PR gas/18499
+       * config/tc-arm.c (move_or_literal_pool): Add support for LDR Rx,=
+       to MOV.w or MVN.w for Thumb2.
 
 2015-06-17  Nicolas Pitre <nico@linaro.org>
 
index 84e95d414ace01b6b44a29ef40c3140846a52dba..d6cd3acc12018d8fee40a11624e2df904f5aa081 100644 (file)
@@ -7869,19 +7869,71 @@ move_or_literal_pool (int i, enum lit_type t, bfd_boolean mode_3)
 
       if (!inst.operands[i].issingle)
        {
-         if (thumb_p && inst.reloc.exp.X_op == O_constant)
+         if (thumb_p)
            {
-             if (!unified_syntax && (v & ~0xFF) == 0)
+             if ((v & ~0xFF) == 0)
                {
                  /* This can be done with a mov(1) instruction.  */
                  inst.instruction = T_OPCODE_MOV_I8 | (inst.operands[i].reg << 8);
                  inst.instruction |= v;
                  return TRUE;
                }
+
+             if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_arch_t2)
+                 && ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v6t2))
+               {
+                 /* Check if on thumb2 it can be done with a mov.w or mvn.w instruction.  */
+                 unsigned int newimm;
+                 bfd_boolean isNegated;
+
+                 newimm = encode_thumb32_immediate (v);
+                 if (newimm != (unsigned int) FAIL)
+                   isNegated = FALSE;
+                 else
+                   {
+                     newimm = encode_thumb32_immediate (~ v);
+                     if (newimm != (unsigned int) FAIL)
+                       isNegated = TRUE;
+                   }
+
+                 if (newimm != (unsigned int) FAIL)
+                   {
+                     inst.instruction = 0xf04f0000 | (inst.operands[i].reg << 8);
+                     inst.instruction |= (isNegated?0x200000:0);
+                     inst.instruction |= (newimm & 0x800) << 15;
+                     inst.instruction |= (newimm & 0x700) << 4;
+                     inst.instruction |= (newimm & 0x0ff);
+                     return TRUE;
+                   }
+                 else if ((v & ~0xFFFF) == 0 || (v & ~0xFFFF0000) == 0)
+                   { 
+                     /* The number may be loaded with a movw/movt instruction.  */
+                     int imm;
+
+                     if ((inst.reloc.exp.X_add_number & ~0xFFFF) == 0)
+                       {
+                         inst.instruction= 0xf2400000;
+                         imm = v;
+                       }
+                     else
+                       {
+                         inst.instruction = 0xf2c00000;
+                         imm = v >> 16;
+                       }
+
+                     inst.instruction |= (inst.operands[i].reg << 8);
+                     inst.instruction |= (imm & 0xf000) << 4;
+                     inst.instruction |= (imm & 0x0800) << 15;
+                     inst.instruction |= (imm & 0x0700) << 4;
+                     inst.instruction |= (imm & 0x00ff);
+                     return TRUE;
+                   }
+               }
            }
-         else if (arm_p && inst.reloc.exp.X_op == O_constant)
+         else if (arm_p)
            {
              int value = encode_arm_immediate (v);
+
              if (value != FAIL)
                {
                  /* This can be done with a mov instruction.  */
index fae6e95e9f5975ca3ac30732a4086eea1b1795d7..aa03f445a7fcc4c24beb7dec79c4002524cc87b4 100644 (file)
@@ -8,6 +8,12 @@
        * gas/arm/vfpv3xd-ldr_immediate.s: New test case.
        * gas/arm/vfpv3xd-ldr_immediate.d: Expected disassembly.
 
+       PR gas/18499
+       * gas/arm/thumb2_ldr_immediate_armv6.s: New test case.
+       * gas/arm/thumb2_ldr_immediate_armv6.d: Expected disassembly.
+       * gas/arm/thumb2_ldr_immediate_armv6t2.s: New test case.
+       * gas/arm/thumb2_ldr_immediate_armv6t2.d: Expected disassembly.
+
 2015-06-16  Matthew Wahab  <matthew.wahab@arm.com>
 
        * sysreg.d: Add id_mmfr4_el1, update expected output.
diff --git a/gas/testsuite/gas/arm/thumb2_ldr_immediate_armv6.d b/gas/testsuite/gas/arm/thumb2_ldr_immediate_armv6.d
new file mode 100644 (file)
index 0000000..5291077
--- /dev/null
@@ -0,0 +1,21 @@
+# name: Ldr immediate on armv6
+# as: -march=armv6
+# objdump: -dr --prefix-addresses --show-raw-insn
+# not-target: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix*
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+0[0-9a-f]+ <[^>]+> 4902        ldr     r1, \[pc, #8\].*
+0[0-9a-f]+ <[^>]+> 4903        ldr     r1, \[pc, #12\] .*
+0[0-9a-f]+ <[^>]+> 4903        ldr     r1, \[pc, #12\] .*
+0[0-9a-f]+ <[^>]+> 4a04        ldr     r2, \[pc, #16\] .*
+0[0-9a-f]+ <[^>]+> 4a04        ldr     r2, \[pc, #16\] .*
+0[0-9a-f]+ <[^>]+> 4a05        ldr     r2, \[pc, #20\] .*
+0[0-9a-f]+ <[^>]+> 72727272    .*
+0[0-9a-f]+ <[^>]+> 63006300    .*
+0[0-9a-f]+ <[^>]+> 00510051    .*
+0[0-9a-f]+ <[^>]+> 00047000    .*
+0[0-9a-f]+ <[^>]+> ff320000    .*
+0[0-9a-f]+ <[^>]+> 000013f1    .*
+
diff --git a/gas/testsuite/gas/arm/thumb2_ldr_immediate_armv6.s b/gas/testsuite/gas/arm/thumb2_ldr_immediate_armv6.s
new file mode 100644 (file)
index 0000000..22a5014
--- /dev/null
@@ -0,0 +1,12 @@
+       .text
+       .thumb
+       .syntax unified
+       .thumb_func
+thumb2_ldr:
+       ldr r1,=0x72727272
+       ldr r1,=0x63006300
+       ldr r1,=0x00510051
+       ldr r2,=0x00047000
+       ldr r2,=0xFF320000
+       ldr r2,=0x000013F1
+       .pool
diff --git a/gas/testsuite/gas/arm/thumb2_ldr_immediate_armv6t2.d b/gas/testsuite/gas/arm/thumb2_ldr_immediate_armv6t2.d
new file mode 100644 (file)
index 0000000..698371a
--- /dev/null
@@ -0,0 +1,15 @@
+# name: Ldr immediate on armv6
+# as: -march=armv6t2
+# objdump: -dr --prefix-addresses --show-raw-insn
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+0[0-9a-f]+ <[^>]+> f04f 3172   mov.w   r1, #1920103026 .*
+0[0-9a-f]+ <[^>]+> f04f 2163   mov.w   r1, #1660969728 .*
+0[0-9a-f]+ <[^>]+> f04f 1151   mov.w   r1, #5308497    .*
+0[0-9a-f]+ <[^>]+> f44f 228e   mov.w   r2, #290816     .*
+0[0-9a-f]+ <[^>]+> f6cf 7232   movt    r2, #65330      .*
+0[0-9a-f]+ <[^>]+> f241 32f1   movw    r2, #5105       .*
+
+
diff --git a/gas/testsuite/gas/arm/thumb2_ldr_immediate_armv6t2.s b/gas/testsuite/gas/arm/thumb2_ldr_immediate_armv6t2.s
new file mode 100644 (file)
index 0000000..22a5014
--- /dev/null
@@ -0,0 +1,12 @@
+       .text
+       .thumb
+       .syntax unified
+       .thumb_func
+thumb2_ldr:
+       ldr r1,=0x72727272
+       ldr r1,=0x63006300
+       ldr r1,=0x00510051
+       ldr r2,=0x00047000
+       ldr r2,=0xFF320000
+       ldr r2,=0x000013F1
+       .pool