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] [AArch64][SVE 08/32] Generalise aarch64_double_precision_fmovable


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

commit 04a3379aceaeb8e29f2586d756d5f2ef26c85e7e
Author: Richard Sandiford <richard.sandiford@arm.com>
Date:   Wed Sep 21 16:48:59 2016 +0100

    [AArch64][SVE 08/32] Generalise aarch64_double_precision_fmovable
    
    SVE has single-bit floating-point constants that don't really
    have any relation to the AArch64 8-bit floating-point encoding.
    (E.g. one of the constants selects between 0 and 1.)  The easiest
    way of representing them in the aarch64_opnd_info seemed to be
    to use the IEEE float representation directly, rather than invent
    some new scheme.
    
    This patch paves the way for that by making the code that converts IEEE
    doubles to IEEE floats accept any value in the range of an IEEE float,
    not just zero and 8-bit floats.  It leaves the range checking to the
    caller (which already handles it).
    
    gas/
    	* config/tc-aarch64.c (aarch64_double_precision_fmovable): Rename
    	to...
    	(can_convert_double_to_float): ...this.  Accept any double-precision
    	value that converts to single precision without loss of precision.
    	(parse_aarch64_imm_float): Update accordingly.

Diff:
---
 gas/ChangeLog           |  8 +++++++
 gas/config/tc-aarch64.c | 62 +++++++++++++++++++++++--------------------------
 2 files changed, 37 insertions(+), 33 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index 8b79b2f..6b27982 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,5 +1,13 @@
 2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
 
+	* config/tc-aarch64.c (aarch64_double_precision_fmovable): Rename
+	to...
+	(can_convert_double_to_float): ...this.  Accept any double-precision
+	value that converts to single precision without loss of precision.
+	(parse_aarch64_imm_float): Update accordingly.
+
+2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
+
 	* config/tc-aarch64.c (parse_immediate_expression): Add a
 	reg_type parameter.
 	(parse_constant_immediate): Likewise, and update calls.
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index eec08c7..40f6253 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -2093,56 +2093,52 @@ aarch64_imm_float_p (uint32_t imm)
     && ((imm & 0x7e000000) == pattern);	/* bits 25 - 29 == ~ bit 30.  */
 }
 
-/* Like aarch64_imm_float_p but for a double-precision floating-point value.
-
-   Return TRUE if the value encoded in IMM can be expressed in the AArch64
-   8-bit signed floating-point format with 3-bit exponent and normalized 4
-   bits of precision (i.e. can be used in an FMOV instruction); return the
-   equivalent single-precision encoding in *FPWORD.
-
-   Otherwise return FALSE.  */
+/* Return TRUE if the IEEE double value encoded in IMM can be expressed
+   as an IEEE float without any loss of precision.  Store the value in
+   *FPWORD if so.  */
 
 static bfd_boolean
-aarch64_double_precision_fmovable (uint64_t imm, uint32_t *fpword)
+can_convert_double_to_float (uint64_t imm, uint32_t *fpword)
 {
   /* If a double-precision floating-point value has the following bit
-     pattern, it can be expressed in the AArch64 8-bit floating-point
-     format:
+     pattern, it can be expressed in a float:
 
-     6 66655555555 554444444...21111111111
-     3 21098765432 109876543...098765432109876543210
-     n Eeeeeeeeexx xxxx00000...000000000000000000000
+     6 66655555555 5544 44444444 33333333 33222222 22221111 111111
+     3 21098765432 1098 76543210 98765432 10987654 32109876 54321098 76543210
+     n E~~~eeeeeee ssss ssssssss ssssssss SSS00000 00000000 00000000 00000000
 
-     where n, e and each x are either 0 or 1 independently, with
-     E == ~ e.  */
+       ----------------------------->     nEeeeeee esssssss ssssssss sssssSSS
+	 if Eeee_eeee != 1111_1111
+
+     where n, e, s and S are either 0 or 1 independently and where ~ is the
+     inverse of E.  */
 
   uint32_t pattern;
   uint32_t high32 = imm >> 32;
+  uint32_t low32 = imm;
 
-  /* Lower 32 bits need to be 0s.  */
-  if ((imm & 0xffffffff) != 0)
+  /* Lower 29 bits need to be 0s.  */
+  if ((imm & 0x1fffffff) != 0)
     return FALSE;
 
   /* Prepare the pattern for 'Eeeeeeeee'.  */
   if (((high32 >> 30) & 0x1) == 0)
-    pattern = 0x3fc00000;
+    pattern = 0x38000000;
   else
     pattern = 0x40000000;
 
-  if ((high32 & 0xffff) == 0			/* bits 32 - 47 are 0.  */
-      && (high32 & 0x7fc00000) == pattern)	/* bits 54 - 61 == ~ bit 62.  */
-    {
-      /* Convert to the single-precision encoding.
-         i.e. convert
-	   n Eeeeeeeeexx xxxx00000...000000000000000000000
-	 to
-	   n Eeeeeexx xxxx0000000000000000000.  */
-      *fpword = ((high32 & 0xfe000000)			/* nEeeeee.  */
-		 | (((high32 >> 16) & 0x3f) << 19));	/* xxxxxx.  */
-      return TRUE;
-    }
-  else
+  /* Check E~~~.  */
+  if ((high32 & 0x78000000) != pattern)
     return FALSE;
+
+  /* Check Eeee_eeee != 1111_1111.  */
+  if ((high32 & 0x7ff00000) == 0x47f00000)
+    return FALSE;
+
+  *fpword = ((high32 & 0xc0000000)		/* 1 n bit and 1 E bit.  */
+	     | ((high32 << 3) & 0x3ffffff8)	/* 7 e and 20 s bits.  */
+	     | (low32 >> 29));			/* 3 S bits.  */
+  return TRUE;
 }
 
 /* Parse a floating-point immediate.  Return TRUE on success and return the
@@ -2181,7 +2177,7 @@ parse_aarch64_imm_float (char **ccp, int *immed, bfd_boolean dp_p,
 
       if (dp_p)
 	{
-	  if (! aarch64_double_precision_fmovable (val, &fpword))
+	  if (!can_convert_double_to_float (val, &fpword))
 	    goto invalid_fp;
 	}
       else if ((uint64_t) val > 0xffffffff)


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