From 90e6b048365950416419c031f2f2d9a8afb5b70c Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 10 Jan 2008 17:07:08 +0000 Subject: [ARM] vfp: fix fuitod/fsitod instructions 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 --- arch/arm/vfp/vfp.h | 2 ++ arch/arm/vfp/vfpdouble.c | 14 +++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'arch/arm/vfp') diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h index 54a2ad6d9ca..791d0238c68 100644 --- a/arch/arm/vfp/vfp.h +++ b/arch/arm/vfp/vfp.h @@ -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); diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c index 190a09ad18e..6cac43bd1d8 100644 --- a/arch/arm/vfp/vfpdouble.c +++ b/arch/arm/vfp/vfpdouble.c @@ -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; @@ -1145,6 +1145,14 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr) else 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. -- cgit v1.2.3