|
|
881b8e |
*** ../binutils-2.23.52.0.1.orig/gas/config/tc-aarch64.c 2013-12-16 17:13:40.458862152 +0000
|
|
|
881b8e |
--- gas/config/tc-aarch64.c 2014-02-19 16:24:27.743707831 +0000
|
|
|
881b8e |
*************** encode_imm_float_bits (uint32_t imm)
|
|
|
881b8e |
*** 1989,2037 ****
|
|
|
881b8e |
| ((imm >> (31 - 7)) & 0x80); /* b[31] -> b[7] */
|
|
|
881b8e |
}
|
|
|
881b8e |
|
|
|
881b8e |
! /* Return TRUE if IMM is a valid floating-point immediate; return FALSE
|
|
|
881b8e |
! otherwise. */
|
|
|
881b8e |
static bfd_boolean
|
|
|
881b8e |
aarch64_imm_float_p (uint32_t imm)
|
|
|
881b8e |
{
|
|
|
881b8e |
! /* 3 32222222 2221111111111
|
|
|
881b8e |
1 09876543 21098765432109876543210
|
|
|
881b8e |
! n Eeeeeexx xxxx0000000000000000000 */
|
|
|
881b8e |
! uint32_t e;
|
|
|
881b8e |
|
|
|
881b8e |
! e = (imm >> 30) & 0x1;
|
|
|
881b8e |
! if (e == 0)
|
|
|
881b8e |
! e = 0x3e000000;
|
|
|
881b8e |
else
|
|
|
881b8e |
! e = 0x40000000;
|
|
|
881b8e |
! return (imm & 0x7ffff) == 0 /* lower 19 bits are 0 */
|
|
|
881b8e |
! && ((imm & 0x7e000000) == e); /* bits 25-29 = ~ bit 30 */
|
|
|
881b8e |
}
|
|
|
881b8e |
|
|
|
881b8e |
! /* Note: this accepts the floating-point 0 constant. */
|
|
|
881b8e |
static bfd_boolean
|
|
|
881b8e |
! parse_aarch64_imm_float (char **ccp, int *immed)
|
|
|
881b8e |
{
|
|
|
881b8e |
char *str = *ccp;
|
|
|
881b8e |
char *fpnum;
|
|
|
881b8e |
LITTLENUM_TYPE words[MAX_LITTLENUMS];
|
|
|
881b8e |
int found_fpchar = 0;
|
|
|
881b8e |
|
|
|
881b8e |
skip_past_char (&str, '#');
|
|
|
881b8e |
|
|
|
881b8e |
- /* We must not accidentally parse an integer as a floating-point number. Make
|
|
|
881b8e |
- sure that the value we parse is not an integer by checking for special
|
|
|
881b8e |
- characters '.' or 'e'.
|
|
|
881b8e |
- FIXME: This is a hack that is not very efficient, but doing better is
|
|
|
881b8e |
- tricky because type information isn't in a very usable state at parse
|
|
|
881b8e |
- time. */
|
|
|
881b8e |
fpnum = str;
|
|
|
881b8e |
skip_whitespace (fpnum);
|
|
|
881b8e |
|
|
|
881b8e |
if (strncmp (fpnum, "0x", 2) == 0)
|
|
|
881b8e |
! return FALSE;
|
|
|
881b8e |
else
|
|
|
881b8e |
{
|
|
|
881b8e |
for (; *fpnum != '\0' && *fpnum != ' ' && *fpnum != '\n'; fpnum++)
|
|
|
881b8e |
if (*fpnum == '.' || *fpnum == 'e' || *fpnum == 'E')
|
|
|
881b8e |
{
|
|
|
881b8e |
--- 1989,2128 ----
|
|
|
881b8e |
| ((imm >> (31 - 7)) & 0x80); /* b[31] -> b[7] */
|
|
|
881b8e |
}
|
|
|
881b8e |
|
|
|
881b8e |
! /* Return TRUE if the single-precision floating-point value encoded in IMM
|
|
|
881b8e |
! can be expressed in the AArch64 8-bit signed floating-point format with
|
|
|
881b8e |
! 3-bit exponent and normalized 4 bits of precision; in other words, the
|
|
|
881b8e |
! floating-point value must be expressable as
|
|
|
881b8e |
! (+/-) n / 16 * power (2, r)
|
|
|
881b8e |
! where n and r are integers such that 16 <= n <=31 and -3 <= r <= 4. */
|
|
|
881b8e |
!
|
|
|
881b8e |
static bfd_boolean
|
|
|
881b8e |
aarch64_imm_float_p (uint32_t imm)
|
|
|
881b8e |
{
|
|
|
881b8e |
! /* If a single-precision floating-point value has the following bit
|
|
|
881b8e |
! pattern, it can be expressed in the AArch64 8-bit floating-point
|
|
|
881b8e |
! format:
|
|
|
881b8e |
!
|
|
|
881b8e |
! 3 32222222 2221111111111
|
|
|
881b8e |
1 09876543 21098765432109876543210
|
|
|
881b8e |
! n Eeeeeexx xxxx0000000000000000000
|
|
|
881b8e |
!
|
|
|
881b8e |
! where n, e and each x are either 0 or 1 independently, with
|
|
|
881b8e |
! E == ~ e. */
|
|
|
881b8e |
|
|
|
881b8e |
! uint32_t pattern;
|
|
|
881b8e |
!
|
|
|
881b8e |
! /* Prepare the pattern for 'Eeeeee'. */
|
|
|
881b8e |
! if (((imm >> 30) & 0x1) == 0)
|
|
|
881b8e |
! pattern = 0x3e000000;
|
|
|
881b8e |
else
|
|
|
881b8e |
! pattern = 0x40000000;
|
|
|
881b8e |
!
|
|
|
881b8e |
! return (imm & 0x7ffff) == 0 /* lower 19 bits are 0. */
|
|
|
881b8e |
! && ((imm & 0x7e000000) == pattern); /* bits 25 - 29 == ~ bit 30. */
|
|
|
881b8e |
}
|
|
|
881b8e |
|
|
|
881b8e |
! /* Like aarch64_imm_float_p but for a double-precision floating-point value.
|
|
|
881b8e |
!
|
|
|
881b8e |
! Return TRUE if the value encoded in IMM can be expressed in the AArch64
|
|
|
881b8e |
! 8-bit signed floating-point format with 3-bit exponent and normalized 4
|
|
|
881b8e |
! bits of precision (i.e. can be used in an FMOV instruction); return the
|
|
|
881b8e |
! equivalent single-precision encoding in *FPWORD.
|
|
|
881b8e |
!
|
|
|
881b8e |
! Otherwise return FALSE. */
|
|
|
881b8e |
!
|
|
|
881b8e |
static bfd_boolean
|
|
|
881b8e |
! aarch64_double_precision_fmovable (uint64_t imm, uint32_t *fpword)
|
|
|
881b8e |
! {
|
|
|
881b8e |
! /* If a double-precision floating-point value has the following bit
|
|
|
881b8e |
! pattern, it can be expressed in the AArch64 8-bit floating-point
|
|
|
881b8e |
! format:
|
|
|
881b8e |
!
|
|
|
881b8e |
! 6 66655555555 554444444...21111111111
|
|
|
881b8e |
! 3 21098765432 109876543...098765432109876543210
|
|
|
881b8e |
! n Eeeeeeeeexx xxxx00000...000000000000000000000
|
|
|
881b8e |
!
|
|
|
881b8e |
! where n, e and each x are either 0 or 1 independently, with
|
|
|
881b8e |
! E == ~ e. */
|
|
|
881b8e |
!
|
|
|
881b8e |
! uint32_t pattern;
|
|
|
881b8e |
! uint32_t high32 = imm >> 32;
|
|
|
881b8e |
!
|
|
|
881b8e |
! /* Lower 32 bits need to be 0s. */
|
|
|
881b8e |
! if ((imm & 0xffffffff) != 0)
|
|
|
881b8e |
! return FALSE;
|
|
|
881b8e |
!
|
|
|
881b8e |
! /* Prepare the pattern for 'Eeeeeeeee'. */
|
|
|
881b8e |
! if (((high32 >> 30) & 0x1) == 0)
|
|
|
881b8e |
! pattern = 0x3fc00000;
|
|
|
881b8e |
! else
|
|
|
881b8e |
! pattern = 0x40000000;
|
|
|
881b8e |
!
|
|
|
881b8e |
! if ((high32 & 0xffff) == 0 /* bits 32 - 47 are 0. */
|
|
|
881b8e |
! && (high32 & 0x7fc00000) == pattern) /* bits 54 - 61 == ~ bit 62. */
|
|
|
881b8e |
! {
|
|
|
881b8e |
! /* Convert to the single-precision encoding.
|
|
|
881b8e |
! i.e. convert
|
|
|
881b8e |
! n Eeeeeeeeexx xxxx00000...000000000000000000000
|
|
|
881b8e |
! to
|
|
|
881b8e |
! n Eeeeeexx xxxx0000000000000000000. */
|
|
|
881b8e |
! *fpword = ((high32 & 0xfe000000) /* nEeeeee. */
|
|
|
881b8e |
! | (((high32 >> 16) & 0x3f) << 19)); /* xxxxxx. */
|
|
|
881b8e |
! return TRUE;
|
|
|
881b8e |
! }
|
|
|
881b8e |
! else
|
|
|
881b8e |
! return FALSE;
|
|
|
881b8e |
! }
|
|
|
881b8e |
!
|
|
|
881b8e |
! /* Parse a floating-point immediate. Return TRUE on success and return the
|
|
|
881b8e |
! value in *IMMED in the format of IEEE754 single-precision encoding.
|
|
|
881b8e |
! *CCP points to the start of the string; DP_P is TRUE when the immediate
|
|
|
881b8e |
! is expected to be in double-precision (N.B. this only matters when
|
|
|
881b8e |
! hexadecimal representation is involved).
|
|
|
881b8e |
!
|
|
|
881b8e |
! N.B. 0.0 is accepted by this function. */
|
|
|
881b8e |
!
|
|
|
881b8e |
! static bfd_boolean
|
|
|
881b8e |
! parse_aarch64_imm_float (char **ccp, int *immed, bfd_boolean dp_p)
|
|
|
881b8e |
{
|
|
|
881b8e |
char *str = *ccp;
|
|
|
881b8e |
char *fpnum;
|
|
|
881b8e |
LITTLENUM_TYPE words[MAX_LITTLENUMS];
|
|
|
881b8e |
int found_fpchar = 0;
|
|
|
881b8e |
+ int64_t val = 0;
|
|
|
881b8e |
+ unsigned fpword = 0;
|
|
|
881b8e |
+ bfd_boolean hex_p = FALSE;
|
|
|
881b8e |
|
|
|
881b8e |
skip_past_char (&str, '#');
|
|
|
881b8e |
|
|
|
881b8e |
fpnum = str;
|
|
|
881b8e |
skip_whitespace (fpnum);
|
|
|
881b8e |
|
|
|
881b8e |
if (strncmp (fpnum, "0x", 2) == 0)
|
|
|
881b8e |
! {
|
|
|
881b8e |
! /* Support the hexadecimal representation of the IEEE754 encoding.
|
|
|
881b8e |
! Double-precision is expected when DP_P is TRUE, otherwise the
|
|
|
881b8e |
! representation should be in single-precision. */
|
|
|
881b8e |
! if (! parse_constant_immediate (&str, &val))
|
|
|
881b8e |
! goto invalid_fp;
|
|
|
881b8e |
!
|
|
|
881b8e |
! if (dp_p)
|
|
|
881b8e |
! {
|
|
|
881b8e |
! if (! aarch64_double_precision_fmovable (val, &fpword))
|
|
|
881b8e |
! goto invalid_fp;
|
|
|
881b8e |
! }
|
|
|
881b8e |
! else if ((uint64_t) val > 0xffffffff)
|
|
|
881b8e |
! goto invalid_fp;
|
|
|
881b8e |
! else
|
|
|
881b8e |
! fpword = val;
|
|
|
881b8e |
!
|
|
|
881b8e |
! hex_p = TRUE;
|
|
|
881b8e |
! }
|
|
|
881b8e |
else
|
|
|
881b8e |
{
|
|
|
881b8e |
+ /* We must not accidentally parse an integer as a floating-point number.
|
|
|
881b8e |
+ Make sure that the value we parse is not an integer by checking for
|
|
|
881b8e |
+ special characters '.' or 'e'. */
|
|
|
881b8e |
for (; *fpnum != '\0' && *fpnum != ' ' && *fpnum != '\n'; fpnum++)
|
|
|
881b8e |
if (*fpnum == '.' || *fpnum == 'e' || *fpnum == 'E')
|
|
|
881b8e |
{
|
|
|
881b8e |
*************** parse_aarch64_imm_float (char **ccp, int
|
|
|
881b8e |
*** 2043,2067 ****
|
|
|
881b8e |
return FALSE;
|
|
|
881b8e |
}
|
|
|
881b8e |
|
|
|
881b8e |
! if ((str = atof_ieee (str, 's', words)) != NULL)
|
|
|
881b8e |
{
|
|
|
881b8e |
- unsigned fpword = 0;
|
|
|
881b8e |
int i;
|
|
|
881b8e |
|
|
|
881b8e |
/* Our FP word must be 32 bits (single-precision FP). */
|
|
|
881b8e |
for (i = 0; i < 32 / LITTLENUM_NUMBER_OF_BITS; i++)
|
|
|
881b8e |
{
|
|
|
881b8e |
fpword <<= LITTLENUM_NUMBER_OF_BITS;
|
|
|
881b8e |
fpword |= words[i];
|
|
|
881b8e |
}
|
|
|
881b8e |
|
|
|
881b8e |
! if (aarch64_imm_float_p (fpword) || (fpword & 0x7fffffff) == 0)
|
|
|
881b8e |
! *immed = fpword;
|
|
|
881b8e |
! else
|
|
|
881b8e |
! goto invalid_fp;
|
|
|
881b8e |
!
|
|
|
881b8e |
*ccp = str;
|
|
|
881b8e |
-
|
|
|
881b8e |
return TRUE;
|
|
|
881b8e |
}
|
|
|
881b8e |
|
|
|
881b8e |
--- 2134,2158 ----
|
|
|
881b8e |
return FALSE;
|
|
|
881b8e |
}
|
|
|
881b8e |
|
|
|
881b8e |
! if (! hex_p)
|
|
|
881b8e |
{
|
|
|
881b8e |
int i;
|
|
|
881b8e |
|
|
|
881b8e |
+ if ((str = atof_ieee (str, 's', words)) == NULL)
|
|
|
881b8e |
+ goto invalid_fp;
|
|
|
881b8e |
+
|
|
|
881b8e |
/* Our FP word must be 32 bits (single-precision FP). */
|
|
|
881b8e |
for (i = 0; i < 32 / LITTLENUM_NUMBER_OF_BITS; i++)
|
|
|
881b8e |
{
|
|
|
881b8e |
fpword <<= LITTLENUM_NUMBER_OF_BITS;
|
|
|
881b8e |
fpword |= words[i];
|
|
|
881b8e |
}
|
|
|
881b8e |
+ }
|
|
|
881b8e |
|
|
|
881b8e |
! if (aarch64_imm_float_p (fpword) || (fpword & 0x7fffffff) == 0)
|
|
|
881b8e |
! {
|
|
|
881b8e |
! *immed = fpword;
|
|
|
881b8e |
*ccp = str;
|
|
|
881b8e |
return TRUE;
|
|
|
881b8e |
}
|
|
|
881b8e |
|
|
|
881b8e |
*************** parse_operands (char *str, const aarch64
|
|
|
881b8e |
*** 4687,4693 ****
|
|
|
881b8e |
bfd_boolean res1 = FALSE, res2 = FALSE;
|
|
|
881b8e |
/* N.B. -0.0 will be rejected; although -0.0 shouldn't be rejected,
|
|
|
881b8e |
it is probably not worth the effort to support it. */
|
|
|
881b8e |
! if (!(res1 = parse_aarch64_imm_float (&str, &qfloat))
|
|
|
881b8e |
&& !(res2 = parse_constant_immediate (&str, &val)))
|
|
|
881b8e |
goto failure;
|
|
|
881b8e |
if ((res1 && qfloat == 0) || (res2 && val == 0))
|
|
|
881b8e |
--- 4778,4784 ----
|
|
|
881b8e |
bfd_boolean res1 = FALSE, res2 = FALSE;
|
|
|
881b8e |
/* N.B. -0.0 will be rejected; although -0.0 shouldn't be rejected,
|
|
|
881b8e |
it is probably not worth the effort to support it. */
|
|
|
881b8e |
! if (!(res1 = parse_aarch64_imm_float (&str, &qfloat, FALSE))
|
|
|
881b8e |
&& !(res2 = parse_constant_immediate (&str, &val)))
|
|
|
881b8e |
goto failure;
|
|
|
881b8e |
if ((res1 && qfloat == 0) || (res2 && val == 0))
|
|
|
881b8e |
*************** parse_operands (char *str, const aarch64
|
|
|
881b8e |
*** 4748,4754 ****
|
|
|
881b8e |
case AARCH64_OPND_SIMD_FPIMM:
|
|
|
881b8e |
{
|
|
|
881b8e |
int qfloat;
|
|
|
881b8e |
! if (! parse_aarch64_imm_float (&str, &qfloat))
|
|
|
881b8e |
goto failure;
|
|
|
881b8e |
if (qfloat == 0)
|
|
|
881b8e |
{
|
|
|
881b8e |
--- 4839,4848 ----
|
|
|
881b8e |
case AARCH64_OPND_SIMD_FPIMM:
|
|
|
881b8e |
{
|
|
|
881b8e |
int qfloat;
|
|
|
881b8e |
! bfd_boolean dp_p
|
|
|
881b8e |
! = (aarch64_get_qualifier_esize (inst.base.operands[0].qualifier)
|
|
|
881b8e |
! == 8);
|
|
|
881b8e |
! if (! parse_aarch64_imm_float (&str, &qfloat, dp_p))
|
|
|
881b8e |
goto failure;
|
|
|
881b8e |
if (qfloat == 0)
|
|
|
881b8e |
{
|