Add support for converting VLDR <reg>,=<constant> to a VMOV instruction when appropriate.
authorAlessandro Marzocchi <alessandro.marzocchi@gmail.com>
Wed, 17 Jun 2015 11:56:17 +0000 (12:56 +0100)
committerNick Clifton <nickc@redhat.com>
Wed, 17 Jun 2015 11:56:17 +0000 (12:56 +0100)
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.

gas/ChangeLog
gas/config/tc-arm.c
gas/testsuite/ChangeLog
gas/testsuite/gas/arm/vfpv2-ldr_immediate.d [new file with mode: 0644]
gas/testsuite/gas/arm/vfpv2-ldr_immediate.s [new file with mode: 0644]
gas/testsuite/gas/arm/vfpv3-ldr_immediate.d [new file with mode: 0644]
gas/testsuite/gas/arm/vfpv3-ldr_immediate.s [new file with mode: 0644]
gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.d [new file with mode: 0644]
gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.s [new file with mode: 0644]
gas/write.c

index 7acc12a..b751117 100644 (file)
@@ -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.
index 7ad55bf..84e95d4 100644 (file)
@@ -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)
 {
index 245f6c3..fae6e95 100644 (file)
@@ -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 (file)
index 0000000..109d443
--- /dev/null
@@ -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 (file)
index 0000000..650d9b8
--- /dev/null
@@ -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 (file)
index 0000000..5f0e925
--- /dev/null
@@ -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 (file)
index 0000000..172b57d
--- /dev/null
@@ -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 (file)
index 0000000..5df3d26
--- /dev/null
@@ -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 (file)
index 0000000..130e49b
--- /dev/null
@@ -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
+       
index 894b271..a76813d 100644 (file)
@@ -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;