This is the mail archive of the binutils-cvs@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]

[binutils-gdb] Add support for converting VLDR <reg>, =<constant> to a VMOV instruction when appropriate.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=ba592044bc04610d6fa14d0a95931bac303ace37

commit ba592044bc04610d6fa14d0a95931bac303ace37
Author: Alessandro Marzocchi <alessandro.marzocchi@gmail.com>
Date:   Wed Jun 17 12:56:17 2015 +0100

    Add support for converting VLDR <reg>,=<constant> to a VMOV instruction when appropriate.
    
    	PR gas/18500
    gas	* 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.
    
    tests	* gas/arm/vfpv2-ldr_immediate.s: New test case.
    	* gas/arm/vfpv2-ldr_immediate.d: Expected disassembly.
    	* gas/arm/vfpv3-ldr_immediate.s: New test case.
    	* gas/arm/vfpv3-ldr_immediate.d: Expected disassembly.
    	* gas/arm/vfpv3xd-ldr_immediate.s: New test case.
    	* gas/arm/vfpv3xd-ldr_immediate.d: Expected disassembly.

Diff:
---
 gas/ChangeLog                                 |   7 +
 gas/config/tc-arm.c                           | 217 +++++++++++++++++++-------
 gas/testsuite/ChangeLog                       |  10 ++
 gas/testsuite/gas/arm/vfpv2-ldr_immediate.d   |  50 ++++++
 gas/testsuite/gas/arm/vfpv2-ldr_immediate.s   |  48 ++++++
 gas/testsuite/gas/arm/vfpv3-ldr_immediate.d   |  35 +++++
 gas/testsuite/gas/arm/vfpv3-ldr_immediate.s   |  46 ++++++
 gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.d |  42 +++++
 gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.s |  47 ++++++
 gas/write.c                                   |  11 +-
 10 files changed, 452 insertions(+), 61 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index 7acc12a..b751117 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,10 @@
+2015-06-17  Alessandro Marzocchi  <alessandro.marzocchi@gmail.com>
+
+	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.
+
 2015-06-17  Nicolas Pitre <nico@linaro.org>
 
 	* as.c (show_usage): Document --sectname-subst.
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 7ad55bf..84e95d4 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -4924,7 +4924,9 @@ parse_fpa_immediate (char ** str)
     {
       /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
 	 Ditto for 15.	*/
-      if (gen_to_words (words, 5, (long) 15) == 0)
+#define X_PRECISION 5
+#define E_PRECISION 15L
+      if (gen_to_words (words, X_PRECISION, E_PRECISION) == 0)
 	{
 	  for (i = 0; i < NUM_FLOAT_VALS; i++)
 	    {
@@ -7750,6 +7752,52 @@ neon_cmode_for_move_imm (unsigned immlo, unsigned immhi, int float_p,
   return FAIL;
 }
 
+/* Returns TRUE if double precision value V may be cast
+   to single precision without loss of accuracy.  */
+
+static bfd_boolean
+is_double_a_single (long int v)
+{
+  int exp = (int) (v >> 52) & 0x7FF;
+  long int mantissa = (v & 0xFFFFFFFFFFFFFl);
+
+  return (exp == 0 || exp == 0x7FF
+	  || (exp >= 1023 - 126 && exp <= 1023 + 127))
+    && (mantissa & 0x1FFFFFFFl) == 0;
+}
+
+/* Returns a double precision value casted to single precision 
+   (ignoring the least significant bits in exponent and mantissa).  */
+
+static int
+double_to_single (long int v)
+{
+  int sign = (int) ((v >> 63) & 1l);
+  int exp = (int) (v >> 52) & 0x7FF;
+  long int mantissa = (v & 0xFFFFFFFFFFFFFl);
+
+  if (exp == 0x7FF)
+    exp = 0xFF;
+  else
+    {
+      exp = exp - 1023 + 127;
+      if (exp >= 0xFF)
+	{
+	  /* Infinity.  */
+	  exp = 0x7F;
+	  mantissa = 0;
+	}
+      else if (exp < 0)
+	{
+	  /* No denormalized numbers.  */
+	  exp = 0;
+	  mantissa = 0;
+	}
+    }
+  mantissa >>= 29;
+  return (sign << 31) | (exp << 23) | mantissa;
+}
+
 enum lit_type
 {
   CONST_THUMB,
@@ -7757,6 +7805,8 @@ enum lit_type
   CONST_VEC
 };
 
+static void do_vfp_nsyn_opcode (const char *);
+
 /* inst.reloc.exp describes an "=expr" load pseudo-operation.
    Determine whether it can be performed with a move instruction; if
    it can, convert inst.instruction to that move instruction and
@@ -7772,7 +7822,6 @@ move_or_literal_pool (int i, enum lit_type t, bfd_boolean mode_3)
   unsigned long tbit;
   bfd_boolean thumb_p = (t == CONST_THUMB);
   bfd_boolean arm_p   = (t == CONST_ARM);
-  bfd_boolean vec64_p = (t == CONST_VEC) && !inst.operands[i].issingle;
 
   if (thumb_p)
     tbit = (inst.instruction > 0xffff) ? THUMB2_LOAD_BIT : THUMB_LOAD_BIT;
@@ -7784,6 +7833,7 @@ move_or_literal_pool (int i, enum lit_type t, bfd_boolean mode_3)
       inst.error = _("invalid pseudo operation");
       return TRUE;
     }
+
   if (inst.reloc.exp.X_op != O_constant
       && inst.reloc.exp.X_op != O_symbol
       && inst.reloc.exp.X_op != O_big)
@@ -7791,76 +7841,129 @@ move_or_literal_pool (int i, enum lit_type t, bfd_boolean mode_3)
       inst.error = _("constant expression expected");
       return TRUE;
     }
-  if ((inst.reloc.exp.X_op == O_constant
-       || inst.reloc.exp.X_op == O_big)
-      && !inst.operands[i].issingle)
+
+  if (inst.reloc.exp.X_op == O_constant
+      || inst.reloc.exp.X_op == O_big)
     {
-      if (thumb_p && inst.reloc.exp.X_op == O_constant)
+      offsetT v;
+
+      if (inst.reloc.exp.X_op == O_big)
 	{
-	  if (!unified_syntax && (inst.reloc.exp.X_add_number & ~0xFF) == 0)
+	  LITTLENUM_TYPE w[X_PRECISION];
+	  LITTLENUM_TYPE * l;
+
+	  if (inst.reloc.exp.X_add_number == -1)
 	    {
-	      /* This can be done with a mov(1) instruction.  */
-	      inst.instruction	= T_OPCODE_MOV_I8 | (inst.operands[i].reg << 8);
-	      inst.instruction |= inst.reloc.exp.X_add_number;
-	      return TRUE;
+	      gen_to_words (w, X_PRECISION, E_PRECISION);
+	      l = w;
+	      /* FIXME: Should we check words w[2..5] ?  */
 	    }
+	  else
+	    l = generic_bignum;
+	  
+	  v = ((l[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS)
+	    |  (l[0] & LITTLENUM_MASK);
 	}
-      else if (arm_p && inst.reloc.exp.X_op == O_constant)
+      else
+	v = inst.reloc.exp.X_add_number;
+
+      if (!inst.operands[i].issingle)
 	{
-	  int value = encode_arm_immediate (inst.reloc.exp.X_add_number);
-	  if (value != FAIL)
+	  if (thumb_p && inst.reloc.exp.X_op == O_constant)
 	    {
-	      /* This can be done with a mov instruction.  */
-	      inst.instruction &= LITERAL_MASK;
-	      inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
-	      inst.instruction |= value & 0xfff;
-	      return TRUE;
+	      if (!unified_syntax && (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;
+		}
 	    }
+	  else if (arm_p && inst.reloc.exp.X_op == O_constant)
+	    {
+	      int value = encode_arm_immediate (v);
+	      if (value != FAIL)
+		{
+		  /* This can be done with a mov instruction.  */
+		  inst.instruction &= LITERAL_MASK;
+		  inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
+		  inst.instruction |= value & 0xfff;
+		  return TRUE;
+		}
 
-	  value = encode_arm_immediate (~inst.reloc.exp.X_add_number);
-	  if (value != FAIL)
+	      value = encode_arm_immediate (~ v);
+	      if (value != FAIL)
+		{
+		  /* This can be done with a mvn instruction.  */
+		  inst.instruction &= LITERAL_MASK;
+		  inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
+		  inst.instruction |= value & 0xfff;
+		  return TRUE;
+		}
+	    }
+	  else if (t == CONST_VEC)
 	    {
-	      /* This can be done with a mvn instruction.  */
-	      inst.instruction &= LITERAL_MASK;
-	      inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
-	      inst.instruction |= value & 0xfff;
-	      return TRUE;
+	      int op = 0;
+	      unsigned immbits = 0;
+	      unsigned immlo = inst.operands[1].imm;
+	      unsigned immhi = inst.operands[1].regisimm
+		? inst.operands[1].reg
+		: inst.reloc.exp.X_unsigned
+		? 0
+		: ((bfd_int64_t)((int) immlo)) >> 32;
+	      int cmode = neon_cmode_for_move_imm (immlo, immhi, FALSE, &immbits,
+						   &op, 64, NT_invtype);
+
+	      if (cmode == FAIL)
+		{
+		  neon_invert_size (&immlo, &immhi, 64);
+		  op = !op;
+		  cmode = neon_cmode_for_move_imm (immlo, immhi, FALSE, &immbits,
+						   &op, 64, NT_invtype);
+		}
+
+	      if (cmode != FAIL)
+		{
+		  inst.instruction = (inst.instruction & VLDR_VMOV_SAME)
+		    | (1 << 23)
+		    | (cmode << 8)
+		    | (op << 5)
+		    | (1 << 4);
+
+		  /* Fill other bits in vmov encoding for both thumb and arm.  */
+		  if (thumb_mode)
+		    inst.instruction |= (0x7 << 29) | (0xF << 24);
+		  else
+		    inst.instruction |= (0xF << 28) | (0x1 << 25);
+		  neon_write_immbits (immbits);
+		  return TRUE;
+		}
 	    }
 	}
-      else if (vec64_p)
-	{
-	  int op = 0;
-	  unsigned immbits = 0;
-	  unsigned immlo = inst.operands[1].imm;
-	  unsigned immhi = inst.operands[1].regisimm
-			   ? inst.operands[1].reg
-			   : inst.reloc.exp.X_unsigned
-			     ? 0
-			     : ((bfd_int64_t)((int) immlo)) >> 32;
-	  int cmode = neon_cmode_for_move_imm (immlo, immhi, FALSE, &immbits,
-					       &op, 64, NT_invtype);
 
-	  if (cmode == FAIL)
+      if (t == CONST_VEC)
+	{
+	  /* Check if vldr Rx, =constant could be optimized to vmov Rx, #constant.  */
+	  if (inst.operands[i].issingle
+	      && is_quarter_float (inst.operands[1].imm)
+	      && ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v3xd))
 	    {
-	      neon_invert_size (&immlo, &immhi, 64);
-	      op = !op;
-	      cmode = neon_cmode_for_move_imm (immlo, immhi, FALSE, &immbits,
-					       &op, 64, NT_invtype);
+	      inst.operands[1].imm =
+		neon_qfloat_bits (v);
+	      do_vfp_nsyn_opcode ("fconsts");
+	      return TRUE;
 	    }
-	  if (cmode != FAIL)
+	  else if (!inst.operands[1].issingle
+		   && ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v3))
 	    {
-	      inst.instruction = (inst.instruction & VLDR_VMOV_SAME)
-				  | (1 << 23)
-				  | (cmode << 8)
-				  | (op << 5)
-				  | (1 << 4);
-	      /* Fill other bits in vmov encoding for both thumb and arm.  */
-	      if (thumb_mode)
-		inst.instruction |= (0x7 << 29) | (0xF << 24);
-	      else
-		inst.instruction |= (0xF << 28) | (0x1 << 25);
-	      neon_write_immbits (immbits);
-	      return TRUE;
+	      if (is_double_a_single (v)
+		  && is_quarter_float (double_to_single (v)))
+		{
+		  inst.operands[1].imm =
+		    neon_qfloat_bits (double_to_single (v));
+		  do_vfp_nsyn_opcode ("fconstd");
+		  return TRUE;
+		}
 	    }
 	}
     }
@@ -8799,8 +8902,6 @@ do_mov16 (void)
     }
 }
 
-static void do_vfp_nsyn_opcode (const char *);
-
 static int
 do_vfp_nsyn_mrs (void)
 {
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index 245f6c3..fae6e95 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,3 +1,13 @@
+2015-06-17  Alessandro Marzocchi  <alessandro.marzocchi@gmail.com>
+
+	PR gas/18500
+	* gas/arm/vfpv2-ldr_immediate.s: New test case.
+	* gas/arm/vfpv2-ldr_immediate.d: Expected disassembly.
+	* gas/arm/vfpv3-ldr_immediate.s: New test case.
+	* gas/arm/vfpv3-ldr_immediate.d: Expected disassembly.
+	* gas/arm/vfpv3xd-ldr_immediate.s: New test case.
+	* gas/arm/vfpv3xd-ldr_immediate.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/vfpv2-ldr_immediate.d b/gas/testsuite/gas/arm/vfpv2-ldr_immediate.d
new file mode 100644
index 0000000..109d443
--- /dev/null
+++ b/gas/testsuite/gas/arm/vfpv2-ldr_immediate.d
@@ -0,0 +1,50 @@
+# name: VFPv2 vldr to vmov
+# as: -mfpu=vfpv2
+# objdump: -dr --prefix-addresses --show-raw-insn
+
+.*: +file format .*arm.*
+
+Disassembly of section \.text:
+
+0[0-9a-fx]+ .*ed9f0b00 	vldr	d0, \[pc\].*
+0[0-9a-fx]+ .*ed9f0a01 	vldr	s0, \[pc, #4\].*
+0[0-9a-fx]+ .*00000000 	.*
+0[0-9a-fx]+ .*3fbe0000 	.*
+0[0-9a-fx]+ .*3df00000 	.*
+.*
+0[0-9a-fx]+ .*ed9f0b00 	vldr	d0, \[pc\].*
+0[0-9a-fx]+ .*ed9f0a01 	vldr	s0, \[pc, #4\].*
+0[0-9a-fx]+ .*00000000 	.*
+0[0-9a-fx]+ .*bfc00000 	.*
+0[0-9a-fx]+ .*be000000 	.*
+.*
+0[0-9a-fx]+ .*ed9f0b00 	vldr	d0, \[pc\].*
+0[0-9a-fx]+ .*ed9f0a01 	vldr	s0, \[pc, #4\].*
+0[0-9a-fx]+ .*00000000 	.*
+0[0-9a-fx]+ .*3fc00000 	.*
+0[0-9a-fx]+ .*3e000000 	.*
+.*
+0[0-9a-fx]+ .*ed9f0b00 	vldr	d0, \[pc\].*
+0[0-9a-fx]+ .*ed9f0a01 	vldr	s0, \[pc, #4\].*
+0[0-9a-fx]+ .*00000000 	.*
+0[0-9a-fx]+ .*3fe08000 	.*
+0[0-9a-fx]+ .*3f040000 	.*
+.*
+0[0-9a-fx]+ .*ed9f0b00 	vldr	d0, \[pc\].*
+0[0-9a-fx]+ .*ed9f0a01 	vldr	s0, \[pc, #4\].*
+0[0-9a-fx]+ .*00000000 	.*
+0[0-9a-fx]+ .*3fef0000 	.*
+0[0-9a-fx]+ .*3f780000 	.*
+.*
+0[0-9a-fx]+ .*ed9f0b00 	vldr	d0, \[pc\].*
+0[0-9a-fx]+ .*ed9f0a01 	vldr	s0, \[pc, #4\].*
+0[0-9a-fx]+ .*00000000 	.*
+0[0-9a-fx]+ .*403f0000 	.*
+0[0-9a-fx]+ .*41f80000 	.*
+.*
+0[0-9a-fx]+ .*ed9f0b00 	vldr	d0, \[pc\].*
+0[0-9a-fx]+ .*ed9f0a01 	vldr	s0, \[pc, #4\].*
+0[0-9a-fx]+ .*00000000 	.*
+0[0-9a-fx]+ .*40400000 	.*
+0[0-9a-fx]+ .*42000000 	.*
+#pass
diff --git a/gas/testsuite/gas/arm/vfpv2-ldr_immediate.s b/gas/testsuite/gas/arm/vfpv2-ldr_immediate.s
new file mode 100644
index 0000000..650d9b8
--- /dev/null
+++ b/gas/testsuite/gas/arm/vfpv2-ldr_immediate.s
@@ -0,0 +1,48 @@
+.arm
+.syntax unified
+  # VFPv2 has no VMOV instruction... all vldr will be kept
+
+  # 15 * 2^-7 =0.1171875 VMOV does not exists
+  .align 3
+  vldr d0,=0x3FBE000000000000
+  vldr s0,=0x3df00000
+  .pool
+
+  # -16 * 2^-7 =0.125 VMOV does not exists
+  .align 3
+  vldr d0,=0xbfc0000000000000
+  vldr s0,=0xbe000000
+  .pool
+
+  # 16 * 2^-7 =0.125 VMOV does not exists
+  .align 3
+  vldr d0,=0x3fc0000000000000
+  vldr s0,=0x3e000000
+  .pool
+
+  # 16.5 * 2^-7 =0.125 VMOV does not exists
+  .align 3
+  vldr d0,=0x3fe0800000000000
+  vldr s0,=0x3f040000
+  .pool
+
+  # 31 * 2^-5 = 0.96875 VMOV does not exists
+  .align 3
+  vldr d0,=0x3fef000000000000
+  vldr s0,=0x3f780000
+  .pool
+
+  # 31 * 2^ 0 = 31 VMOV does not exists
+  .align 3
+  vldr d0,=0x403F000000000000 
+  vldr s0,=0x41f80000
+  .pool
+
+  # 16 * 2^ 1 = 32 VMOV does not exists
+  .align 3
+  vldr d0,=0x4040000000000000
+  vldr s0,=0x42000000
+  .pool
+	
+  nop
+	
diff --git a/gas/testsuite/gas/arm/vfpv3-ldr_immediate.d b/gas/testsuite/gas/arm/vfpv3-ldr_immediate.d
new file mode 100644
index 0000000..5f0e925
--- /dev/null
+++ b/gas/testsuite/gas/arm/vfpv3-ldr_immediate.d
@@ -0,0 +1,35 @@
+# name: VFPv3 vldr to vmov
+# as: -mfpu=vfp3
+# objdump: -dr --prefix-addresses --show-raw-insn
+
+.*: +file format .*arm.*
+
+Disassembly of section \.text:
+
+0[0-9a-fx]+ .*ed9f0b00 	vldr	d0, \[pc\].*
+0[0-9a-fx]+ .*ed9f0a01 	vldr	s0, \[pc, #4\].*
+0[0-9a-fx]+ .*00000000 	.*
+0[0-9a-fx]+ .*3fbe0000 	.*
+0[0-9a-fx]+ .*3df00000 	.*
+.*
+
+0[0-9a-fx]+ .*eebc0b00 	(vmov\.f64|fconstd)	d0, #192.*
+0[0-9a-fx]+ .*eebc0a00 	(vmov\.f32|fconsts)	s0, #192.*
+0[0-9a-fx]+ .*eeb40b00 	(vmov\.f64|fconstd)	d0, #64.*
+0[0-9a-fx]+ .*eeb40a00 	(vmov\.f32|fconsts)	s0, #64.*
+0[0-9a-fx]+ .*ed9f0b00 	vldr	d0, \[pc\].*
+0[0-9a-fx]+ .*ed9f0a01 	vldr	s0, \[pc, #4\].*
+0[0-9a-fx]+ .*00000000 	.*
+0[0-9a-fx]+ .*3fe08000 	.*
+0[0-9a-fx]+ .*3f040000 	.*
+.*
+0[0-9a-fx]+ .*eeb60b0f 	(vmov\.f64|fconstd)	d0, #111.*
+0[0-9a-fx]+ .*eeb60a0f 	(vmov\.f32|fconsts)	s0, #111.*
+0[0-9a-fx]+ .*eeb30b0f 	(vmov\.f64|fconstd)	d0, #63.*
+0[0-9a-fx]+ .*eeb30a0f 	(vmov\.f32|fconsts)	s0, #63.*
+0[0-9a-fx]+ .*ed9f0b00 	vldr	d0, \[pc\].*
+0[0-9a-fx]+ .*ed9f0a01 	vldr	s0, \[pc, #4\].*
+0[0-9a-fx]+ .*00000000 	.*
+0[0-9a-fx]+ .*40400000 	.*
+0[0-9a-fx]+ .*42000000 	.*
+#pass
diff --git a/gas/testsuite/gas/arm/vfpv3-ldr_immediate.s b/gas/testsuite/gas/arm/vfpv3-ldr_immediate.s
new file mode 100644
index 0000000..172b57d
--- /dev/null
+++ b/gas/testsuite/gas/arm/vfpv3-ldr_immediate.s
@@ -0,0 +1,46 @@
+.arm
+.syntax unified
+  # 15 * 2^-7 =0.1171875 Not convertible to VMOV
+  .align 3
+  vldr d0,=0x3FBE000000000000
+  vldr s0,=0x3df00000
+  .pool
+
+  # -16 * 2^-7 =-0.125 Convertible to VMOV
+  .align 3
+  vldr d0,=0xbfc0000000000000
+  vldr s0,=0xbe000000
+  .pool
+
+  # 16 * 2^-7 =0.125 Convertible to VMOV
+  .align 3
+  vldr d0,=0x3fc0000000000000
+  vldr s0,=0x3e000000
+  .pool
+
+  # 16.5 * 2^-7 =0.125 Not convertible to VMOV
+  .align 3
+  vldr d0,=0x3fe0800000000000
+  vldr s0,=0x3f040000
+  .pool
+
+  # 31 * 2^-5 = 0.96875 Convertible to VMOV
+  .align 3
+  vldr d0,=0x3fef000000000000
+  vldr s0,=0x3f780000
+  .pool
+
+  # 31 * 2^ 0 = 31 Convertible to VMOV
+  .align 3
+  vldr d0,=0x403F000000000000 
+  vldr s0,=0x41f80000
+  .pool
+
+  # 16 * 2^ 1 = 32 Not convertible to VMOV
+  .align 3
+  vldr d0,=0x4040000000000000
+  vldr s0,=0x42000000
+  .pool
+
+  nop
+	
diff --git a/gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.d b/gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.d
new file mode 100644
index 0000000..5df3d26
--- /dev/null
+++ b/gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.d
@@ -0,0 +1,42 @@
+# name: VFPv3xd vldr to vmov
+# as: -mfpu=vfpv3xd
+# objdump: -dr --prefix-addresses --show-raw-insn
+
+.*: +file format .*arm.*
+
+Disassembly of section \.text:
+
+0[0-9a-fx]+ .*ed9f0b00 	vldr	d0, \[pc\].*
+0[0-9a-fx]+ .*ed9f0a01 	vldr	s0, \[pc, #4\].*
+0[0-9a-fx]+ .*00000000 	.*
+0[0-9a-fx]+ .*3fbe0000 	.*
+0[0-9a-fx]+ .*3df00000 	.*
+.*
+0[0-9a-fx]+ .*ed9f0b00 	vldr	d0, \[pc\].*
+0[0-9a-fx]+ .*eebc0a00 	(vmov\.f32|fconsts)	s0, #192.*
+0[0-9a-fx]+ .*00000000 	.*
+0[0-9a-fx]+ .*bfc00000 	.*
+0[0-9a-fx]+ .*ed9f0b00 	vldr	d0, \[pc\].*
+0[0-9a-fx]+ .*eeb40a00 	(vmov\.f32|fconsts)	s0, #64.*
+0[0-9a-fx]+ .*00000000 	.*
+0[0-9a-fx]+ .*3fc00000 	.*
+0[0-9a-fx]+ .*ed9f0b00 	vldr	d0, \[pc\].*
+0[0-9a-fx]+ .*ed9f0a01 	vldr	s0, \[pc, #4\].*
+0[0-9a-fx]+ .*00000000 	.*
+0[0-9a-fx]+ .*3fe08000 	.*
+0[0-9a-fx]+ .*3f040000 	.*
+.*
+0[0-9a-fx]+ .*ed9f0b00 	vldr	d0, \[pc\].*
+0[0-9a-fx]+ .*eeb60a0f 	(vmov\.f32|fconsts)	s0, #111.*
+0[0-9a-fx]+ .*00000000 	.*
+0[0-9a-fx]+ .*3fef0000 	.*
+0[0-9a-fx]+ .*ed9f0b00 	vldr	d0, \[pc\].*
+0[0-9a-fx]+ .*eeb30a0f 	(vmov\.f32|fconsts)	s0, #63.*
+0[0-9a-fx]+ .*00000000 	.*
+0[0-9a-fx]+ .*403f0000 	.*
+0[0-9a-fx]+ .*ed9f0b00 	vldr	d0, \[pc\].*
+0[0-9a-fx]+ .*ed9f0a01 	vldr	s0, \[pc, #4\].*
+0[0-9a-fx]+ .*00000000 	.*
+0[0-9a-fx]+ .*40400000 	.*
+0[0-9a-fx]+ .*42000000 	.*
+#pass
diff --git a/gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.s b/gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.s
new file mode 100644
index 0000000..130e49b
--- /dev/null
+++ b/gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.s
@@ -0,0 +1,47 @@
+.arm
+.syntax unified
+  # VFPv3xD has no VMOV instruction for double precision registers...
+  # 15 * 2^-7 =0.1171875 Not convertible to VMOV
+  .align 3
+  vldr d0,=0x3FBE000000000000
+  vldr s0,=0x3df00000
+  .pool
+
+  # -16 * 2^-7 =0.125 Convertible to VMOV
+  .align 3
+  vldr d0,=0xbfc0000000000000
+  vldr s0,=0xbe000000
+  .pool
+
+  # 16 * 2^-7 =0.125 Convertible to VMOV
+  .align 3
+  vldr d0,=0x3fc0000000000000
+  vldr s0,=0x3e000000
+  .pool
+
+  # 16.5 * 2^-7 =0.125 Not convertible to VMOV
+  .align 3
+  vldr d0,=0x3fe0800000000000
+  vldr s0,=0x3f040000
+  .pool
+
+  # 31 * 2^-5 = 0.96875 Convertible to VMOV
+  .align 3
+  vldr d0,=0x3fef000000000000
+  vldr s0,=0x3f780000
+  .pool
+
+  # 31 * 2^ 0 = 31 Convertible to VMOV
+  .align 3
+  vldr d0,=0x403F000000000000 
+  vldr s0,=0x41f80000
+  .pool
+
+  # 16 * 2^ 1 = 32 Not convertible to VMOV
+  .align 3
+  vldr d0,=0x4040000000000000
+  vldr s0,=0x42000000
+  .pool
+
+  nop
+	
diff --git a/gas/write.c b/gas/write.c
index 894b271..a76813d 100644
--- a/gas/write.c
+++ b/gas/write.c
@@ -1585,7 +1585,9 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
 					f->fr_literal, (file_ptr) offset,
 					(bfd_size_type) f->fr_fix);
 	  if (!x)
-	    as_fatal (_("can't write %s: %s"), stdoutput->filename,
+	    as_fatal (_("can't write %ld bytes to section %s of %s because: '%s'"),
+		      (long) f->fr_fix, sec->name,
+		      stdoutput->filename,
 		      bfd_errmsg (bfd_get_error ()));
 	  offset += f->fr_fix;
 	}
@@ -1606,7 +1608,9 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
 						(file_ptr) offset,
 						(bfd_size_type) fill_size);
 		  if (!x)
-		    as_fatal (_("can't write %s: %s"), stdoutput->filename,
+		    as_fatal (_("can't fill %ld bytes in section %s of %s because '%s'"),
+			      (long) fill_size, sec->name,
+			      stdoutput->filename,
 			      bfd_errmsg (bfd_get_error ()));
 		  offset += fill_size;
 		}
@@ -1636,7 +1640,8 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
 		    (stdoutput, sec, buf, (file_ptr) offset,
 		     (bfd_size_type) n_per_buf * fill_size);
 		  if (!x)
-		    as_fatal (_("cannot write to output file '%s': %s"),
+		    as_fatal (_("cannot fill %ld bytes in section %s of %s because: '%s'"),
+			      (long)(n_per_buf * fill_size), sec->name,
 			      stdoutput->filename,
 			      bfd_errmsg (bfd_get_error ()));
 		  offset += n_per_buf * fill_size;


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