This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[ARM][PR gas/19217] Fix wrong use of MOVT to replace LDR


Hello,

PR gas/18499 implemented an optimization in which a load-immediate (LDR
_, =<imm>) was replaced by a MOVW if the bottom half of <imm> was
non-zero or by a MOVT if the top half was non-zero

This optimization is wrong because, unlike the LDR, the MOVT leaves
the bottom half of the destination register unchanged. The
implementation also doesn't deal with the case when the immediate is
non-zero in both halves. In that case, the LDR would have to be replaced
with a MOVW+MOVT sequence.

The use of MOVT appears to be the cause of PR gas/19217. This patch
fixes that miscompilation by dropping the use of MOVT, so that the LDR _,
=<imm> will only be replaced by MOVW and only if the upper half of <imm>
is zero. It also removes a redundant feature check and fixes some
formatting in the code.

Tested arm-none-linux-gnueabihf with cross-compiled check-binutils and
check-gas.

Ok for trunk?
Matthew

gas/
2015-11-11  Matthew Wahab  <matthew.wahab@arm.com>

	* config/tc-arm.c (move_or_literal_pool): Remove redundant feature
	check.  Fix some code formatting.  Drop use of MOVT.  Add some
	comments.

gas/testsuite/
2015-11-11  Matthew Wahab  <matthew.wahab@arm.com>

	* gas/arm/thumb2_ldr_immediate_armv6t2.d: Update expected output.
>From c90d7d6435510fcac5be2c7798fc78ffe2fe7468 Mon Sep 17 00:00:00 2001
From: Matthew Wahab <matthew.wahab@arm.com>
Date: Wed, 11 Nov 2015 13:21:55 +0000
Subject: [PATCH] [ARM][PR gas/19217] Fix incorrect use of MOVT to replace LDR

Change-Id: I40dcd4fd811bde72a0712f4ec5d5bc614946051e
---
 gas/config/tc-arm.c                                | 31 ++++++++--------------
 .../gas/arm/thumb2_ldr_immediate_armv6t2.d         |  6 ++---
 2 files changed, 14 insertions(+), 23 deletions(-)

diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index de99d72..206371d 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -7847,10 +7847,10 @@ move_or_literal_pool (int i, enum lit_type t, bfd_boolean mode_3)
 		  return TRUE;
 		}
 
-	      if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_arch_t2)
-		  && ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v6t2))
+	      if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_arch_t2))
 		{
-		  /* Check if on thumb2 it can be done with a mov.w or mvn.w instruction.  */
+		  /* Check if on thumb2 it can be done with a mov.w or mvn.w
+		     instruction.  */
 		  unsigned int newimm;
 		  bfd_boolean isNegated;
 
@@ -7859,36 +7859,27 @@ move_or_literal_pool (int i, enum lit_type t, bfd_boolean mode_3)
 		    isNegated = FALSE;
 		  else
 		    {
-		      newimm = encode_thumb32_immediate (~ v);
+		      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 = (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)
+		  else if ((v & ~0xFFFF) == 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;
-			}
+		      /* The number can be loaded with a mov.w instruction.  */
+		      int imm = v & 0xFFFF;
 
+		      inst.instruction = 0xf2400000;  /* MOVW.  */
 		      inst.instruction |= (inst.operands[i].reg << 8);
 		      inst.instruction |= (imm & 0xf000) << 4;
 		      inst.instruction |= (imm & 0x0800) << 15;
diff --git a/gas/testsuite/gas/arm/thumb2_ldr_immediate_armv6t2.d b/gas/testsuite/gas/arm/thumb2_ldr_immediate_armv6t2.d
index 698371a..223fbaf 100644
--- a/gas/testsuite/gas/arm/thumb2_ldr_immediate_armv6t2.d
+++ b/gas/testsuite/gas/arm/thumb2_ldr_immediate_armv6t2.d
@@ -9,7 +9,7 @@ Disassembly of section .text:
 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]+ <[^>]+> 4a01      	ldr	r2, \[pc, #4\]	.*
 0[0-9a-f]+ <[^>]+> f241 32f1 	movw	r2, #5105	.*
-
-
+0[0-9a-f]+ <[^>]+> 0000      	.short	0x0000
+0[0-9a-f]+ <[^>]+> ff320000 	.word	0xff320000
-- 
2.1.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]