Fix use of ARM ADR and ADRl pseudo-instructions with thumb function symbols.
authorNick Clifton <nickc@redhat.com>
Mon, 15 May 2017 14:29:02 +0000 (15:29 +0100)
committerNick Clifton <nickc@redhat.com>
Mon, 15 May 2017 14:29:02 +0000 (15:29 +0100)
PR gas/21458
* config/tc-arm.c (do_adr): If the ADR involves a thumb function
symbol, ensure that the T bit will be set.
(do_adrl): Likewise.
(do_t_adr): Likewise.
* testsuite/gas/arm/pr21458.s: New test.
* testsuite/gas/arm/pr21458.d: New test driver.

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

index 293930b280e8bc8a9e6baeb6068fd7fd0566e98d..9d0fa57082e2e4bd4b8c57b3db9d1e28bb4f2f70 100644 (file)
@@ -1,3 +1,13 @@
+2017-05-15  Nick Clifton  <nickc@redhat.com>
+
+       PR gas/21458
+       * config/tc-arm.c (do_adr): If the ADR involves a thumb function
+       symbol, ensure that the T bit will be set.
+       (do_adrl): Likewise.
+       (do_t_adr): Likewise.
+       * testsuite/gas/arm/pr21458.s: New test.
+       * testsuite/gas/arm/pr21458.d: New test driver.
+
 2017-05-15  Maciej W. Rozycki  <macro@imgtec.com>
 
        * testsuite/gas/mips/mips16-pcrel-1.d: Remove `-mips3' from `as'
index 7e35c348d20bf4cea466ed4b19f3349e0b203be1..08824b4c9b23f66292b4b8768da5ed23030c8252 100644 (file)
@@ -8351,6 +8351,12 @@ do_adr (void)
   inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
   inst.reloc.pc_rel = 1;
   inst.reloc.exp.X_add_number -= 8;
+
+  if (inst.reloc.exp.X_op == O_symbol
+      && inst.reloc.exp.X_add_symbol != NULL
+      && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
+      && THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
+    inst.reloc.exp.X_add_number += 1;  
 }
 
 /* This is a pseudo-op of the form "adrl rd, label" to be converted
@@ -8369,6 +8375,12 @@ do_adrl (void)
   inst.reloc.pc_rel           = 1;
   inst.size                   = INSN_SIZE * 2;
   inst.reloc.exp.X_add_number -= 8;
+
+  if (inst.reloc.exp.X_op == O_symbol
+      && inst.reloc.exp.X_add_symbol != NULL
+      && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
+      && THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
+    inst.reloc.exp.X_add_number += 1;  
 }
 
 static void
@@ -10734,9 +10746,14 @@ do_t_adr (void)
       inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
       inst.reloc.exp.X_add_number -= 4; /* PC relative adjust.  */
       inst.reloc.pc_rel = 1;
-
       inst.instruction |= Rd << 4;
     }
+
+  if (inst.reloc.exp.X_op == O_symbol
+      && inst.reloc.exp.X_add_symbol != NULL
+      && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
+      && THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
+    inst.reloc.exp.X_add_number += 1;
 }
 
 /* Arithmetic instructions for which there is just one 16-bit
diff --git a/gas/testsuite/gas/arm/pr21458.d b/gas/testsuite/gas/arm/pr21458.d
new file mode 100644 (file)
index 0000000..c0b1d12
--- /dev/null
@@ -0,0 +1,27 @@
+#objdump: -d --prefix-addresses --show-raw-insn
+#name: ADR(L) for Thumb functions
+#skip: *-*-pe *-wince-* *-*-coff *-*-vxworks
+
+# Test that using ADR(L) on thumb function symbols sets the T bit.
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+0+00000 <.*> 4770[     ]+bx[   ]+lr
+0+00002 <.*> 46c0[     ]+nop[  ]+; \(mov r8, r8\)
+0+00004 <.*> e12fff1e[         ]+bx[   ]+lr
+0+00008 <.*> f2af 000b[        ]+subw[         ]+r0, pc, #11
+0+0000c <.*> 4780[     ]+blx[  ]+r0
+0+0000e <.*> f2af 020c[        ]+subw[         ]+r2, pc, #12
+0+00012 <.*> 4790[     ]+blx[  ]+r2
+0+00014 <.*> e24f401b[         ]+sub[  ]+r4, pc, #27
+0+00018 <.*> e1a00000[         ]+nop[  ]+; \(mov r0, r0\)
+0+0001c <.*> e12fff34[         ]+blx[  ]+r4
+0+00020 <.*> e24f6024[         ]+sub[  ]+r6, pc, #36[  ]+; 0x24
+0+00024 <.*> e1a00000[         ]+nop[  ]+; \(mov r0, r0\)
+0+00028 <.*> e12fff36[         ]+blx[  ]+r6
+0+0002c <.*> e24f8033[         ]+sub[  ]+r8, pc, #51[  ]+; 0x33
+0+00030 <.*> e12fff38[         ]+blx[  ]+r8
+0+00034 <.*> e24fa038[         ]+sub[  ]+sl, pc, #56[  ]+; 0x38
+0+00038 <.*> e12fff3a[         ]+blx[  ]+sl
+0+0003c <.*> 324fc043[         ]+subcc[        ]+ip, pc, #67[  ]+; 0x43
diff --git a/gas/testsuite/gas/arm/pr21458.s b/gas/testsuite/gas/arm/pr21458.s
new file mode 100644 (file)
index 0000000..0d89b0c
--- /dev/null
@@ -0,0 +1,40 @@
+.syntax unified
+.thumb
+.text
+.align 2
+.global __thumbFn
+.type __testFn, %function
+.thumb_func
+__thumbFn:
+   bx lr
+   nop
+   
+.arm
+.global __armFn
+.type   __armFn, %function
+__armFn:
+  bx lr
+  
+.thumb
+.global __test_thumb
+.type __test_thumb, %function
+.thumb_func
+__test_thumb:
+    ADR  R0,__thumbFn
+    BLX  R0
+    ADR  R2,__armFn
+    BLX  R2
+
+.arm
+.global __test_arm
+.type   __test_arm, %function
+__test_arm:
+    ADRL R4,__thumbFn
+    BLX  R4
+    ADRL R6,__armFn
+    BLX  R6
+    ADR  r8, __thumbFn
+    blx  r8
+    ADR  r10, __armFn
+    blx  r10
+    adrlo r12, __thumbFn