This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH, ARM] Fix parsing of int/float immediates for Neon VMOV instructions
- From: Julian Brown <julian at codesourcery dot com>
- To: binutils at sourceware dot org
- Date: Fri, 02 Mar 2007 16:07:24 +0000
- Subject: [PATCH, ARM] Fix parsing of int/float immediates for Neon VMOV instructions
Hi,
This patch fixes a failure to parse instructions of the form:
vmov.i32 dX, #N
where N is between 1 and 31 (the valid integer values which the
floating-point VMOV variant can accept). The solution isn't very nice,
but the way things are at the moment, we don't really have coherent type
information for the instruction in the right place as we're parsing --
I've added a FIXME to that effect. (Parsing is done kind of
context-free, but context-sensitive parsing which knew about the type of
the operands for the instruction at hand would probably be nicer in this
case.)
(Floats are encoded into IEEE754-form early, during parsing. So, 10 and
10.0 look very different coming out of the parser, and the correct
immediate form to use is deduced during bit encoding.)
To use floating-point immediates, you must now explicitly use a decimal
point or exponent, i.e.
vmov.f32 dX, #10.0
not
vmov.f32 dX, #10
The handling of -0 and 0 values is tweaked for vmov.f32 also (they must
now be written 0.0 and -0.0), and the testsuite is altered accordingly.
Tested with cross to arm-none-eabi.
OK?
Cheers,
Julian
gas/
* config/tc-arm.c (parse_qfloat_immediate): Disallow integer
syntax for floating-point immediates. Fix hex immediates,
handle 0.0 and -0.0 specially.
gas/testsuite/
* gas/arm/neon-const.s: Use FP syntax for 0/-0.
* gas/arm/vfp-neon-syntax-inc.s: Likewise, for 1.
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.311
diff -c -p -r1.311 tc-arm.c
*** gas/config/tc-arm.c 25 Feb 2007 19:29:25 -0000 1.311
--- gas/config/tc-arm.c 2 Mar 2007 15:53:51 -0000
*************** is_quarter_float (unsigned imm)
*** 4177,4194 ****
/* Parse an 8-bit "quarter-precision" floating point number of the form:
0baBbbbbbc defgh000 00000000 00000000.
! The minus-zero case needs special handling, since it can't be encoded in the
! "quarter-precision" float format, but can nonetheless be loaded as an integer
! constant. */
static unsigned
parse_qfloat_immediate (char **ccp, int *immed)
{
char *str = *ccp;
LITTLENUM_TYPE words[MAX_LITTLENUMS];
skip_past_char (&str, '#');
if ((str = atof_ieee (str, 's', words)) != NULL)
{
unsigned fpword = 0;
--- 4177,4221 ----
/* Parse an 8-bit "quarter-precision" floating point number of the form:
0baBbbbbbc defgh000 00000000 00000000.
! The zero and minus-zero cases need special handling, since they can't be
! encoded in the "quarter-precision" float format, but can nonetheless be
! loaded as integer constants. */
static unsigned
parse_qfloat_immediate (char **ccp, int *immed)
{
char *str = *ccp;
+ char *fpnum;
LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ int found_fpchar = 0;
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 horrible hack, but doing better is tricky because type
+ information isn't in a very usable state at parse time. A better solution
+ should be implemented as part of the fix for allowing the full range of
+ pseudo-instructions to be used in VMOV, etc. */
+ fpnum = str;
+ skip_whitespace (fpnum);
+
+ if (strncmp (fpnum, "0x", 2) == 0)
+ return FAIL;
+ else
+ {
+ for (; *fpnum != '\0' && *fpnum != ' ' && *fpnum != '\n'; fpnum++)
+ if (*fpnum == '.' || *fpnum == 'e' || *fpnum == 'E')
+ {
+ found_fpchar = 1;
+ break;
+ }
+
+ if (!found_fpchar)
+ return FAIL;
+ }
+
if ((str = atof_ieee (str, 's', words)) != NULL)
{
unsigned fpword = 0;
*************** parse_qfloat_immediate (char **ccp, int
*** 4201,4207 ****
fpword |= words[i];
}
! if (is_quarter_float (fpword) || fpword == 0x80000000)
*immed = fpword;
else
return FAIL;
--- 4228,4234 ----
fpword |= words[i];
}
! if (is_quarter_float (fpword) || (fpword & 0x7fffffff) == 0)
*immed = fpword;
else
return FAIL;
Index: gas/testsuite/gas/arm/neon-const.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/neon-const.s,v
retrieving revision 1.1
diff -c -p -r1.1 neon-const.s
*** gas/testsuite/gas/arm/neon-const.s 26 Apr 2006 16:02:40 -0000 1.1
--- gas/testsuite/gas/arm/neon-const.s 2 Mar 2007 15:53:51 -0000
***************
*** 4,10 ****
.text
.syntax unified
! vmov.f32 q0, 0
vmov.f32 q0, 2.0
vmov.f32 q0, 4.0
--- 4,10 ----
.text
.syntax unified
! vmov.f32 q0, 0.0
vmov.f32 q0, 2.0
vmov.f32 q0, 4.0
***************
*** 150,156 ****
vmov.f32 q0, 0.96875
vmov.f32 q0, 1.9375
! vmov.f32 q0, -0
vmov.f32 q0, -2.0
vmov.f32 q0, -4.0
--- 150,156 ----
vmov.f32 q0, 0.96875
vmov.f32 q0, 1.9375
! vmov.f32 q0, -0.0
vmov.f32 q0, -2.0
vmov.f32 q0, -4.0
Index: gas/testsuite/gas/arm/vfp-neon-syntax-inc.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/vfp-neon-syntax-inc.s,v
retrieving revision 1.2
diff -c -p -r1.2 vfp-neon-syntax-inc.s
*** gas/testsuite/gas/arm/vfp-neon-syntax-inc.s 7 Jun 2006 14:31:51 -0000 1.2
--- gas/testsuite/gas/arm/vfp-neon-syntax-inc.s 2 Mar 2007 15:53:51 -0000
*************** func:
*** 9,15 ****
vmov\cond\f32 s0,s1
vmov\cond\f64 d0,d1
vmov\cond\f32 s0,#0.25
! vmov\cond\f64 d0,#1
itblock 4 \cond
vmov\cond r0,s1
vmov\cond s0,r1
--- 9,15 ----
vmov\cond\f32 s0,s1
vmov\cond\f64 d0,d1
vmov\cond\f32 s0,#0.25
! vmov\cond\f64 d0,#1.0
itblock 4 \cond
vmov\cond r0,s1
vmov\cond s0,r1