Add to the AArch64 GAS the missing support for hexadecimal-format
floating-point literal in the FMOV instruction. gas/ * config/tc-aarch64.c (aarch64_imm_float_p): Rename 'e' to 'pattern'; add comment. (aarch64_double_precision_fmovable): New function. (parse_aarch64_imm_float): Add parameter 'dp_p'; call the new function; handle hexadecimal representation of IEEE754 encoding. (parse_operands): Update the call to parse_aarch64_imm_float. gas/testsuite/ * gas/aarch64/diagnostic.s: Add test. * gas/aarch64/diagnostic.l: Update. * gas/aarch64/illegal.s: Add test. * gas/aarch64/illegal.l: Update. * gas/aarch64/fpmov.s: New file. * gas/aarch64/fpmov.d: New file.
This commit is contained in:
parent
334ad4a8e4
commit
62b0d0d5f3
@ -1,3 +1,12 @@
|
||||
2013-03-05 Yufeng Zhang <yufeng.zhang@arm.com>
|
||||
|
||||
* config/tc-aarch64.c (aarch64_imm_float_p): Rename 'e' to 'pattern';
|
||||
add comment.
|
||||
(aarch64_double_precision_fmovable): New function.
|
||||
(parse_aarch64_imm_float): Add parameter 'dp_p'; call the new
|
||||
function; handle hexadecimal representation of IEEE754 encoding.
|
||||
(parse_operands): Update the call to parse_aarch64_imm_float.
|
||||
|
||||
2013-02-28 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* config/tc-i386.c (_i386_insn): Replace have_hle with hle_prefix.
|
||||
|
||||
@ -1989,49 +1989,140 @@ encode_imm_float_bits (uint32_t imm)
|
||||
| ((imm >> (31 - 7)) & 0x80); /* b[31] -> b[7] */
|
||||
}
|
||||
|
||||
/* Return TRUE if IMM is a valid floating-point immediate; return FALSE
|
||||
otherwise. */
|
||||
/* Return TRUE if the single-precision floating-point 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; in other words, the
|
||||
floating-point value must be expressable as
|
||||
(+/-) n / 16 * power (2, r)
|
||||
where n and r are integers such that 16 <= n <=31 and -3 <= r <= 4. */
|
||||
|
||||
static bfd_boolean
|
||||
aarch64_imm_float_p (uint32_t imm)
|
||||
{
|
||||
/* 3 32222222 2221111111111
|
||||
1 09876543 21098765432109876543210
|
||||
n Eeeeeexx xxxx0000000000000000000 */
|
||||
uint32_t e;
|
||||
/* If a single-precision floating-point value has the following bit
|
||||
pattern, it can be expressed in the AArch64 8-bit floating-point
|
||||
format:
|
||||
|
||||
e = (imm >> 30) & 0x1;
|
||||
if (e == 0)
|
||||
e = 0x3e000000;
|
||||
3 32222222 2221111111111
|
||||
1 09876543 21098765432109876543210
|
||||
n Eeeeeexx xxxx0000000000000000000
|
||||
|
||||
where n, e and each x are either 0 or 1 independently, with
|
||||
E == ~ e. */
|
||||
|
||||
uint32_t pattern;
|
||||
|
||||
/* Prepare the pattern for 'Eeeeee'. */
|
||||
if (((imm >> 30) & 0x1) == 0)
|
||||
pattern = 0x3e000000;
|
||||
else
|
||||
e = 0x40000000;
|
||||
return (imm & 0x7ffff) == 0 /* lower 19 bits are 0 */
|
||||
&& ((imm & 0x7e000000) == e); /* bits 25-29 = ~ bit 30 */
|
||||
pattern = 0x40000000;
|
||||
|
||||
return (imm & 0x7ffff) == 0 /* lower 19 bits are 0. */
|
||||
&& ((imm & 0x7e000000) == pattern); /* bits 25 - 29 == ~ bit 30. */
|
||||
}
|
||||
|
||||
/* Note: this accepts the floating-point 0 constant. */
|
||||
/* 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. */
|
||||
|
||||
static bfd_boolean
|
||||
parse_aarch64_imm_float (char **ccp, int *immed)
|
||||
aarch64_double_precision_fmovable (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:
|
||||
|
||||
6 66655555555 554444444...21111111111
|
||||
3 21098765432 109876543...098765432109876543210
|
||||
n Eeeeeeeeexx xxxx00000...000000000000000000000
|
||||
|
||||
where n, e and each x are either 0 or 1 independently, with
|
||||
E == ~ e. */
|
||||
|
||||
uint32_t pattern;
|
||||
uint32_t high32 = imm >> 32;
|
||||
|
||||
/* Lower 32 bits need to be 0s. */
|
||||
if ((imm & 0xffffffff) != 0)
|
||||
return FALSE;
|
||||
|
||||
/* Prepare the pattern for 'Eeeeeeeee'. */
|
||||
if (((high32 >> 30) & 0x1) == 0)
|
||||
pattern = 0x3fc00000;
|
||||
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
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Parse a floating-point immediate. Return TRUE on success and return the
|
||||
value in *IMMED in the format of IEEE754 single-precision encoding.
|
||||
*CCP points to the start of the string; DP_P is TRUE when the immediate
|
||||
is expected to be in double-precision (N.B. this only matters when
|
||||
hexadecimal representation is involved).
|
||||
|
||||
N.B. 0.0 is accepted by this function. */
|
||||
|
||||
static bfd_boolean
|
||||
parse_aarch64_imm_float (char **ccp, int *immed, bfd_boolean dp_p)
|
||||
{
|
||||
char *str = *ccp;
|
||||
char *fpnum;
|
||||
LITTLENUM_TYPE words[MAX_LITTLENUMS];
|
||||
int found_fpchar = 0;
|
||||
int64_t val = 0;
|
||||
unsigned fpword = 0;
|
||||
bfd_boolean hex_p = FALSE;
|
||||
|
||||
skip_past_char (&str, '#');
|
||||
|
||||
/* We must not accidentally parse an integer as a floating-point number. Make
|
||||
sure that the value we parse is not an integer by checking for special
|
||||
characters '.' or 'e'.
|
||||
FIXME: This is a hack that is not very efficient, but doing better is
|
||||
tricky because type information isn't in a very usable state at parse
|
||||
time. */
|
||||
fpnum = str;
|
||||
skip_whitespace (fpnum);
|
||||
|
||||
if (strncmp (fpnum, "0x", 2) == 0)
|
||||
return FALSE;
|
||||
{
|
||||
/* Support the hexadecimal representation of the IEEE754 encoding.
|
||||
Double-precision is expected when DP_P is TRUE, otherwise the
|
||||
representation should be in single-precision. */
|
||||
if (! parse_constant_immediate (&str, &val))
|
||||
goto invalid_fp;
|
||||
|
||||
if (dp_p)
|
||||
{
|
||||
if (! aarch64_double_precision_fmovable (val, &fpword))
|
||||
goto invalid_fp;
|
||||
}
|
||||
else if ((uint64_t) val > 0xffffffff)
|
||||
goto invalid_fp;
|
||||
else
|
||||
fpword = val;
|
||||
|
||||
hex_p = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We must not accidentally parse an integer as a floating-point number.
|
||||
Make sure that the value we parse is not an integer by checking for
|
||||
special characters '.' or 'e'. */
|
||||
for (; *fpnum != '\0' && *fpnum != ' ' && *fpnum != '\n'; fpnum++)
|
||||
if (*fpnum == '.' || *fpnum == 'e' || *fpnum == 'E')
|
||||
{
|
||||
@ -2043,25 +2134,25 @@ parse_aarch64_imm_float (char **ccp, int *immed)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((str = atof_ieee (str, 's', words)) != NULL)
|
||||
if (! hex_p)
|
||||
{
|
||||
unsigned fpword = 0;
|
||||
int i;
|
||||
|
||||
if ((str = atof_ieee (str, 's', words)) == NULL)
|
||||
goto invalid_fp;
|
||||
|
||||
/* 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 (aarch64_imm_float_p (fpword) || (fpword & 0x7fffffff) == 0)
|
||||
*immed = fpword;
|
||||
else
|
||||
goto invalid_fp;
|
||||
|
||||
if (aarch64_imm_float_p (fpword) || (fpword & 0x7fffffff) == 0)
|
||||
{
|
||||
*immed = fpword;
|
||||
*ccp = str;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -4691,7 +4782,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
|
||||
bfd_boolean res1 = FALSE, res2 = FALSE;
|
||||
/* N.B. -0.0 will be rejected; although -0.0 shouldn't be rejected,
|
||||
it is probably not worth the effort to support it. */
|
||||
if (!(res1 = parse_aarch64_imm_float (&str, &qfloat))
|
||||
if (!(res1 = parse_aarch64_imm_float (&str, &qfloat, FALSE))
|
||||
&& !(res2 = parse_constant_immediate (&str, &val)))
|
||||
goto failure;
|
||||
if ((res1 && qfloat == 0) || (res2 && val == 0))
|
||||
@ -4752,7 +4843,10 @@ parse_operands (char *str, const aarch64_opcode *opcode)
|
||||
case AARCH64_OPND_SIMD_FPIMM:
|
||||
{
|
||||
int qfloat;
|
||||
if (! parse_aarch64_imm_float (&str, &qfloat))
|
||||
bfd_boolean dp_p
|
||||
= (aarch64_get_qualifier_esize (inst.base.operands[0].qualifier)
|
||||
== 8);
|
||||
if (! parse_aarch64_imm_float (&str, &qfloat, dp_p))
|
||||
goto failure;
|
||||
if (qfloat == 0)
|
||||
{
|
||||
|
||||
@ -1,3 +1,12 @@
|
||||
2013-03-05 Yufeng Zhang <yufeng.zhang@arm.com>
|
||||
|
||||
* gas/aarch64/diagnostic.s: Add test.
|
||||
* gas/aarch64/diagnostic.l: Update.
|
||||
* gas/aarch64/illegal.s: Add test.
|
||||
* gas/aarch64/illegal.l: Update.
|
||||
* gas/aarch64/fpmov.s: New file.
|
||||
* gas/aarch64/fpmov.d: New file.
|
||||
|
||||
2013-03-01 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* gas/i386/inval.s: Add tests for invalid addresses and eiz.
|
||||
|
||||
@ -86,3 +86,4 @@
|
||||
[^:]*:88: Error: shift is not permitted at operand 2 -- `movi v1.2d,4294967295,lsl#0'
|
||||
[^:]*:89: Error: shift amount expected to be 0 at operand 2 -- `movi v1.8b,97,lsl#8'
|
||||
[^:]*:90: Error: unknown or missing system register name at operand 1 -- `msr dummy,x1'
|
||||
[^:]*:91: Error: invalid floating-point constant at operand 2 -- `fmov s0,0x42000000'
|
||||
|
||||
@ -88,3 +88,4 @@
|
||||
movi v1.2d, 4294967295, lsl #0
|
||||
movi v1.8b, 97, lsl #8
|
||||
msr dummy, x1
|
||||
fmov s0, 0x42000000
|
||||
|
||||
19
gas/testsuite/gas/aarch64/fpmov.d
Normal file
19
gas/testsuite/gas/aarch64/fpmov.d
Normal file
@ -0,0 +1,19 @@
|
||||
#objdump: -dr
|
||||
|
||||
.*: file format .*
|
||||
|
||||
Disassembly of section .*:
|
||||
|
||||
0000000000000000 <.*>:
|
||||
0: 1e251000 fmov s0, #1\.200000000000000000e\+01
|
||||
4: 1e251000 fmov s0, #1\.200000000000000000e\+01
|
||||
8: 1e251000 fmov s0, #1\.200000000000000000e\+01
|
||||
c: 1e351000 fmov s0, #-1\.200000000000000000e\+01
|
||||
10: 1e351000 fmov s0, #-1\.200000000000000000e\+01
|
||||
14: 1e351000 fmov s0, #-1\.200000000000000000e\+01
|
||||
18: 1e751000 fmov d0, #-1\.200000000000000000e\+01
|
||||
1c: 1e751000 fmov d0, #-1\.200000000000000000e\+01
|
||||
20: 1e751000 fmov d0, #-1\.200000000000000000e\+01
|
||||
24: 1e69f000 fmov d0, #2\.421875000000000000e-01
|
||||
28: 1e69f000 fmov d0, #2\.421875000000000000e-01
|
||||
2c: 1e29f000 fmov s0, #2\.421875000000000000e-01
|
||||
17
gas/testsuite/gas/aarch64/fpmov.s
Normal file
17
gas/testsuite/gas/aarch64/fpmov.s
Normal file
@ -0,0 +1,17 @@
|
||||
// fpmov.s Test file for AArch64 floating-point move instructions.
|
||||
|
||||
.text
|
||||
|
||||
// fp mov immediate
|
||||
fmov s0, 12.0
|
||||
fmov s0, 1.2e1
|
||||
fmov s0, 0x41400000
|
||||
fmov s0, -12.0
|
||||
fmov s0, -1.2e1
|
||||
fmov s0, 0xc1400000
|
||||
fmov d0, -12.0
|
||||
fmov d0, -1.2e1
|
||||
fmov d0, 0xC028000000000000
|
||||
fmov d0, 0.2421875
|
||||
fmov d0, 0x3fcf000000000000
|
||||
fmov s0, 0x3e780000
|
||||
@ -548,4 +548,7 @@
|
||||
[^:]*:538: Error: .*`mov x0,##5'
|
||||
[^:]*:540: Error: .*`msr daifset,x0'
|
||||
[^:]*:541: Error: .*`msr daifclr,x0'
|
||||
[^:]*:546: Error: .*
|
||||
[^:]*:543: Error: .*`fmov s0,#0x11'
|
||||
[^:]*:544: Error: .*`fmov s0,#0xC0280000C1400000'
|
||||
[^:]*:545: Error: .*`fmov d0,#0xC02f800000000000'
|
||||
[^:]*:550: Error: .*
|
||||
|
||||
@ -540,6 +540,10 @@
|
||||
msr daifset, x0
|
||||
msr daifclr, x0
|
||||
|
||||
fmov s0, #0x11
|
||||
fmov s0, #0xC0280000C1400000
|
||||
fmov d0, #0xC02f800000000000
|
||||
|
||||
// No 16-byte relocation
|
||||
ldr q0, =one_label
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user