aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2016-09-21 16:48:59 +0100
committerRichard Sandiford <richard.sandiford@arm.com>2016-09-21 16:48:59 +0100
commit04a3379aceaeb8e29f2586d756d5f2ef26c85e7e (patch)
treed75ff53f8c84ef48b78161a9ca984342fc718789 /gas
parent1799c0d064f21e09666fd1ab19a31a957202f18b (diff)
downloadbinutils-04a3379aceaeb8e29f2586d756d5f2ef26c85e7e.zip
binutils-04a3379aceaeb8e29f2586d756d5f2ef26c85e7e.tar.gz
binutils-04a3379aceaeb8e29f2586d756d5f2ef26c85e7e.tar.bz2
[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.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog8
-rw-r--r--gas/config/tc-aarch64.c62
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)