This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]