From: Alessandro Marzocchi Date: Wed, 17 Jun 2015 12:50:52 +0000 (+0100) Subject: Add support for converting LDR Rx,= to MOV or MVN in Thumb2 mode. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1256987795a7f61826c0e5cc2ee023a579bb0a80;p=binutils-gdb.git Add support for converting LDR Rx,= to MOV or MVN in Thumb2 mode. 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. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index b751117a3a2..b4e7d5fa8bd 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -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 diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 84e95d414ac..d6cd3acc120 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -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. */ diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index fae6e95e9f5..aa03f445a7f 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -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 * 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 index 00000000000..5291077e529 --- /dev/null +++ b/gas/testsuite/gas/arm/thumb2_ldr_immediate_armv6.d @@ -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 index 00000000000..22a50141ed3 --- /dev/null +++ b/gas/testsuite/gas/arm/thumb2_ldr_immediate_armv6.s @@ -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 index 00000000000..698371a7345 --- /dev/null +++ b/gas/testsuite/gas/arm/thumb2_ldr_immediate_armv6t2.d @@ -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 index 00000000000..22a50141ed3 --- /dev/null +++ b/gas/testsuite/gas/arm/thumb2_ldr_immediate_armv6t2.s @@ -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