[ARM] vfp: fix fuitod/fsitod instructions
Russell King [Thu, 10 Jan 2008 17:07:08 +0000 (17:07 +0000)]
These two instructions exceptionally take a single precision register
as their operand.  This means we can't use vfp_get_dm() to read the
register number - we need to use vfp_get_sm() instead.  Add a flag to
indicate this exception to the general rule.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

arch/arm/vfp/vfp.h
arch/arm/vfp/vfpdouble.c

index 54a2ad6..791d023 100644 (file)
@@ -361,10 +361,12 @@ u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand);
  *  OP_SCALAR - this operation always operates in scalar mode
  *  OP_SD - the instruction exceptionally writes to a single precision result.
  *  OP_DD - the instruction exceptionally writes to a double precision result.
+ *  OP_SM - the instruction exceptionally reads from a single precision operand.
  */
 #define OP_SCALAR      (1 << 0)
 #define OP_SD          (1 << 1)
 #define OP_DD          (1 << 1)
+#define OP_SM          (1 << 2)
 
 struct op {
        u32 (* const fn)(int dd, int dn, int dm, u32 fpscr);
index 190a09a..6cac43b 100644 (file)
@@ -668,8 +668,8 @@ static struct op fops_ext[32] = {
        [FEXT_TO_IDX(FEXT_FCMPZ)]       = { vfp_double_fcmpz,  OP_SCALAR },
        [FEXT_TO_IDX(FEXT_FCMPEZ)]      = { vfp_double_fcmpez, OP_SCALAR },
        [FEXT_TO_IDX(FEXT_FCVT)]        = { vfp_double_fcvts,  OP_SCALAR|OP_SD },
-       [FEXT_TO_IDX(FEXT_FUITO)]       = { vfp_double_fuito,  OP_SCALAR },
-       [FEXT_TO_IDX(FEXT_FSITO)]       = { vfp_double_fsito,  OP_SCALAR },
+       [FEXT_TO_IDX(FEXT_FUITO)]       = { vfp_double_fuito,  OP_SCALAR|OP_SM },
+       [FEXT_TO_IDX(FEXT_FSITO)]       = { vfp_double_fsito,  OP_SCALAR|OP_SM },
        [FEXT_TO_IDX(FEXT_FTOUI)]       = { vfp_double_ftoui,  OP_SCALAR|OP_SD },
        [FEXT_TO_IDX(FEXT_FTOUIZ)]      = { vfp_double_ftouiz, OP_SCALAR|OP_SD },
        [FEXT_TO_IDX(FEXT_FTOSI)]       = { vfp_double_ftosi,  OP_SCALAR|OP_SD },
@@ -1128,7 +1128,7 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
        u32 exceptions = 0;
        unsigned int dest;
        unsigned int dn = vfp_get_dn(inst);
-       unsigned int dm = vfp_get_dm(inst);
+       unsigned int dm;
        unsigned int vecitr, veclen, vecstride;
        struct op *fop;
 
@@ -1146,6 +1146,14 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
                dest = vfp_get_dd(inst);
 
        /*
+        * f[us]ito takes a sN operand, not a dN operand.
+        */
+       if (fop->flags & OP_SM)
+               dm = vfp_get_sm(inst);
+       else
+               dm = vfp_get_dm(inst);
+
+       /*
         * If destination bank is zero, vector length is always '1'.
         * ARM DDI0100F C5.1.3, C5.3.2.
         */