* gas/config/tc-arm.c (neon_is_quarter_float): Move, and rename to...
authorJulian Brown <julian@codesourcery.com>
Wed, 26 Apr 2006 16:24:26 +0000 (16:24 +0000)
committerJulian Brown <julian@codesourcery.com>
Wed, 26 Apr 2006 16:24:26 +0000 (16:24 +0000)
(is_quarter_float): Rename from above. Simplify slightly.
(parse_qfloat_immediate): Parse a "quarter precision" floating-point
number.
(parse_neon_mov): Parse floating-point constants.
(neon_qfloat_bits): Fix encoding.
(neon_cmode_for_move_imm): Tweak to use floating-point encoding in
preference to integer encoding when using the F32 type.

    * gas/testsuite/gas/arm/neon-const.s: New testcase. Neon floating-point
constants.
* gas/testsuite/gas/arm/neon-const.d: Expected output of above.
* gas/testsuite/gas/arm/neon-cov.d: Expect floating-point disassembly
for VMOV.F32.

    * opcodes/arm-dis.c (print_insn_neon): Disassemble floating-point
constant VMOV.

ChangeLog.csl
gas/config/tc-arm.c
gas/testsuite/gas/arm/neon-cov.d
opcodes/arm-dis.c

index d0cc333..271df1d 100644 (file)
@@ -1,3 +1,23 @@
+2006-04-26  Julian Brown  <julian@codesourcery.com>
+
+       * gas/config/tc-arm.c (neon_is_quarter_float): Move, and rename to...
+       (is_quarter_float): Rename from above. Simplify slightly.
+       (parse_qfloat_immediate): Parse a "quarter precision" floating-point
+       number.
+       (parse_neon_mov): Parse floating-point constants.
+       (neon_qfloat_bits): Fix encoding.
+       (neon_cmode_for_move_imm): Tweak to use floating-point encoding in
+       preference to integer encoding when using the F32 type.
+
+       * gas/testsuite/gas/arm/neon-const.s: New testcase. Neon floating-point
+       constants.
+       * gas/testsuite/gas/arm/neon-const.d: Expected output of above.
+       * gas/testsuite/gas/arm/neon-cov.d: Expect floating-point disassembly
+       for VMOV.F32.
+
+       * opcodes/arm-dis.c (print_insn_neon): Disassemble floating-point
+       constant VMOV.
+
 2006-04-24  Julian Brown  <julian@codesourcery.com>
 
        * libiberty/floatformat.c (floatformat_to_double): Fix (biased)
index 44c7d99..1447af4 100644 (file)
@@ -3994,6 +3994,55 @@ parse_fpa_immediate (char ** str)
   return FAIL;
 }
 
+/* Returns 1 if a number has "quarter-precision" float format
+   0baBbbbbbc defgh000 00000000 00000000.  */
+
+static int
+is_quarter_float (unsigned imm)
+{
+  int bs = (imm & 0x20000000) ? 0x3e000000 : 0x40000000;
+  return (imm & 0x7ffff) == 0 && ((imm & 0x7e000000) ^ bs) == 0;
+}
+
+/* Parse an 8-bit "quarter-precision" floating point number of the form:
+   0baBbbbbbc defgh000 00000000 00000000.
+   The minus-zero case needs special handling, since it can't be encoded in the
+   "quarter-precision" float format, but can nonetheless be loaded as an integer
+   constant.  */
+
+static unsigned
+parse_qfloat_immediate (char **ccp, int *immed)
+{
+  char *str = *ccp;
+  LITTLENUM_TYPE words[MAX_LITTLENUMS];
+  
+  skip_past_char (&str, '#');
+  
+  if ((str = atof_ieee (str, 's', words)) != NULL)
+    {
+      unsigned fpword = 0;
+      int i;
+      
+      /* Our FP word must be 32 bits (single-precision FP).  */
+      for (i = 0; i < 32 / LITTLENUM_NUMBER_OF_BITS; i++)
+        {
+          fpword <<= LITTLENUM_NUMBER_OF_BITS;
+          fpword |= words[i];
+        }
+      
+      if (is_quarter_float (fpword) || fpword == 0x80000000)
+        *immed = fpword;
+      else
+        return FAIL;
+
+      *ccp = str;
+      
+      return SUCCESS;
+    }
+  
+  return FAIL;
+}
+
 /* Shift operands.  */
 enum shift_kind
 {
@@ -4702,6 +4751,13 @@ parse_neon_mov (char **str, int *which_operand)
           inst.operands[i].isreg = 1;
           inst.operands[i].present = 1;
         }
+      else if (parse_qfloat_immediate (&ptr, &inst.operands[i].imm) == SUCCESS)
+        {
+          /* Case 2: VMOV<c><q>.<dt> <Qd>, #<float-imm>
+             Case 3: VMOV<c><q>.<dt> <Dd>, #<float-imm>  */
+          if (!thumb_mode && (inst.instruction & 0xf0000000) != 0xe0000000)
+            goto bad_cond;
+        }
       else if (parse_big_immediate (&ptr, i) == SUCCESS)
         {
           /* Case 2: VMOV<c><q>.<dt> <Qd>, #<imm>
@@ -10214,25 +10270,12 @@ neon_squash_bits (unsigned imm)
          | ((imm & 0x01000000) >> 21);
 }
 
-/* Returns 1 if a number has "quarter-precision" float format
-   0baBbbbbbc defgh000 00000000 00000000.  */
-
-static int
-neon_is_quarter_float (unsigned imm)
-{
-  int b = (imm & 0x20000000) != 0;
-  int bs = (b << 25) | (b << 26) | (b << 27) | (b << 28) | (b << 29)
-           | ((!b) << 30);
-  return (imm & 0x81ffffff) == (imm & 0x81f80000)
-         && ((imm & 0x7e000000) ^ bs) == 0;
-}
-
-/* Compress above representation to 0b...000 abcdefgh.  */
+/* Compress quarter-float representation to 0b...000 abcdefgh.  */
 
 static unsigned
 neon_qfloat_bits (unsigned imm)
 {
-  return ((imm >> 19) & 0x7f) | (imm >> 24);
+  return ((imm >> 19) & 0x7f) | ((imm >> 24) & 0x80);
 }
 
 /* Returns CMODE. IMMBITS [7:0] is set to bits suitable for inserting into
@@ -10243,9 +10286,16 @@ neon_qfloat_bits (unsigned imm)
 
 static int
 neon_cmode_for_move_imm (unsigned immlo, unsigned immhi, unsigned *immbits,
-                         int *op, int size)
+                         int *op, int size, enum neon_el_type type)
 {
-  if (size == 64 && neon_bits_same_in_bytes (immhi)
+  if (type == NT_float && is_quarter_float (immlo) && immhi == 0)
+    {
+      if (size != 32 || *op == 1)
+        return FAIL;
+      *immbits = neon_qfloat_bits (immlo);
+      return 0xf;
+    }
+  else if (size == 64 && neon_bits_same_in_bytes (immhi)
       && neon_bits_same_in_bytes (immlo))
     {
       /* Check this one first so we don't have to bother with immhi in later
@@ -10303,13 +10353,6 @@ neon_cmode_for_move_imm (unsigned immlo, unsigned immhi, unsigned *immbits,
       *immbits = (immlo >> 16) & 0xff;
       return 0xd;
     }
-  else if (neon_is_quarter_float (immlo))
-    {
-      if (size != 32 || *op == 1)
-        return FAIL;
-      *immbits = neon_qfloat_bits (immlo);
-      return 0xf;
-    }
 
   return FAIL;
 }
@@ -10996,7 +11039,7 @@ neon_move_immediate (void)
               _("immediate has bits set outside the operand size"));
 
   if ((cmode = neon_cmode_for_move_imm (immlo, immhi, &immbits, &op,
-                                        et.size)) == FAIL)
+                                        et.size, et.type)) == FAIL)
     {
       /* Invert relevant bits only.  */
       neon_invert_size (&immlo, &immhi, et.size);
@@ -11005,7 +11048,7 @@ neon_move_immediate (void)
          neon_cmode_for_move_imm.  */
       op = !op;
       if ((cmode = neon_cmode_for_move_imm (immlo, immhi, &immbits, &op,
-                                            et.size)) == FAIL)
+                                            et.size, et.type)) == FAIL)
         {
           first_error (_("immediate out of range"));
           return;
index c2ef0eb..d4de661 100644 (file)
@@ -989,8 +989,8 @@ Disassembly of section \.text:
 0[0-9a-f]+ <[^>]+> f2870e17    vmov\.i8        d0, #119        ; 0x77
 0[0-9a-f]+ <[^>]+> f3810e71    vmov\.i64       q0, #0xff0000ff000000ff
 0[0-9a-f]+ <[^>]+> f3810e31    vmov\.i64       d0, #0xff0000ff000000ff
-0[0-9a-f]+ <[^>]+> f2850f51    vmov\.f32       q0, #1027866624 ; 0x3d440000
-0[0-9a-f]+ <[^>]+> f2850f11    vmov\.f32       d0, #1027866624 ; 0x3d440000
+0[0-9a-f]+ <[^>]+> f2810f51    vmov\.f32       q0, #4\.25      ; 0x40880000
+0[0-9a-f]+ <[^>]+> f2810f11    vmov\.f32       d0, #4\.25      ; 0x40880000
 0[0-9a-f]+ <[^>]+> f3b005c0    vmvn    q0, q0
 0[0-9a-f]+ <[^>]+> f3b005c0    vmvn    q0, q0
 0[0-9a-f]+ <[^>]+> f3b00580    vmvn    d0, d0
index f6cac65..6ca9333 100644 (file)
@@ -26,6 +26,7 @@
 #include "opcode/arm.h"
 #include "opintl.h"
 #include "safe-ctype.h"
+#include "floatformat.h"
 
 /* FIXME: This shouldn't be done here.  */
 #include "coff/internal.h"
@@ -2283,6 +2284,7 @@ print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb)
                        unsigned long value = 0, hival = 0;
                        unsigned shift;
                         int size = 0;
+                        int isfloat = 0;
                        
                        bits |= ((given >> 24) & 1) << 7;
                        bits |= ((given >> 16) & 7) << 4;
@@ -2339,11 +2341,12 @@ print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb)
                            /* floating point encoding */
                            int tmp;
                            
-                           value = (unsigned long)(bits & 0x7f) << (24 - 6);
+                           value = (unsigned long)(bits & 0x7f) << 19;
                            value |= (unsigned long)(bits & 0x80) << 24;
                            tmp = bits & 0x40 ? 0x3c : 0x40;
                            value |= (unsigned long)tmp << 24;
                             size = 32;
+                            isfloat = 1;
                          }
                        else
                          {
@@ -2363,7 +2366,27 @@ print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb)
                             break;
 
                           case 32:
-                            func (stream, "#%ld\t; 0x%.8lx", value, value);
+                            if (isfloat)
+                              {
+                                unsigned char valbytes[4];
+                                double fvalue;
+                                
+                                /* Do this a byte at a time so we don't have to
+                                   worry about the host's endianness.  */
+                                valbytes[0] = value & 0xff;
+                                valbytes[1] = (value >> 8) & 0xff;
+                                valbytes[2] = (value >> 16) & 0xff;
+                                valbytes[3] = (value >> 24) & 0xff;
+                                
+                                floatformat_to_double 
+                                  (&floatformat_ieee_single_little, valbytes,
+                                  &fvalue);
+                                                                
+                                func (stream, "#%.7g\t; 0x%.8lx", fvalue,
+                                      value);
+                              }
+                            else
+                              func (stream, "#%ld\t; 0x%.8lx", value, value);
                             break;
 
                           case 64: