mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-24 04:00:07 +08:00
[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.
This commit is contained in:
@ -1,3 +1,11 @@
|
|||||||
|
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>
|
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
|
||||||
|
|
||||||
* config/tc-aarch64.c (parse_immediate_expression): Add a
|
* config/tc-aarch64.c (parse_immediate_expression): Add a
|
||||||
|
@ -2093,56 +2093,52 @@ aarch64_imm_float_p (uint32_t imm)
|
|||||||
&& ((imm & 0x7e000000) == pattern); /* bits 25 - 29 == ~ bit 30. */
|
&& ((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 IEEE double value encoded in IMM can be expressed
|
||||||
|
as an IEEE float without any loss of precision. Store the value in
|
||||||
Return TRUE if the value encoded in IMM can be expressed in the AArch64
|
*FPWORD if so. */
|
||||||
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. */
|
|
||||||
|
|
||||||
static bfd_boolean
|
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
|
/* If a double-precision floating-point value has the following bit
|
||||||
pattern, it can be expressed in the AArch64 8-bit floating-point
|
pattern, it can be expressed in a float:
|
||||||
format:
|
|
||||||
|
|
||||||
6 66655555555 554444444...21111111111
|
6 66655555555 5544 44444444 33333333 33222222 22221111 111111
|
||||||
3 21098765432 109876543...098765432109876543210
|
3 21098765432 1098 76543210 98765432 10987654 32109876 54321098 76543210
|
||||||
n Eeeeeeeeexx xxxx00000...000000000000000000000
|
n E~~~eeeeeee ssss ssssssss ssssssss SSS00000 00000000 00000000 00000000
|
||||||
|
|
||||||
where n, e and each x are either 0 or 1 independently, with
|
-----------------------------> nEeeeeee esssssss ssssssss sssssSSS
|
||||||
E == ~ e. */
|
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 pattern;
|
||||||
uint32_t high32 = imm >> 32;
|
uint32_t high32 = imm >> 32;
|
||||||
|
uint32_t low32 = imm;
|
||||||
|
|
||||||
/* Lower 32 bits need to be 0s. */
|
/* Lower 29 bits need to be 0s. */
|
||||||
if ((imm & 0xffffffff) != 0)
|
if ((imm & 0x1fffffff) != 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Prepare the pattern for 'Eeeeeeeee'. */
|
/* Prepare the pattern for 'Eeeeeeeee'. */
|
||||||
if (((high32 >> 30) & 0x1) == 0)
|
if (((high32 >> 30) & 0x1) == 0)
|
||||||
pattern = 0x3fc00000;
|
pattern = 0x38000000;
|
||||||
else
|
else
|
||||||
pattern = 0x40000000;
|
pattern = 0x40000000;
|
||||||
|
|
||||||
if ((high32 & 0xffff) == 0 /* bits 32 - 47 are 0. */
|
/* Check E~~~. */
|
||||||
&& (high32 & 0x7fc00000) == pattern) /* bits 54 - 61 == ~ bit 62. */
|
if ((high32 & 0x78000000) != pattern)
|
||||||
{
|
|
||||||
/* 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
|
|
||||||
return FALSE;
|
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
|
/* 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 (dp_p)
|
||||||
{
|
{
|
||||||
if (! aarch64_double_precision_fmovable (val, &fpword))
|
if (!can_convert_double_to_float (val, &fpword))
|
||||||
goto invalid_fp;
|
goto invalid_fp;
|
||||||
}
|
}
|
||||||
else if ((uint64_t) val > 0xffffffff)
|
else if ((uint64_t) val > 0xffffffff)
|
||||||
|
Reference in New Issue
Block a user