From 4cc9bd2eaa1063c68341c1c00e66660adcfdf254 Mon Sep 17 00:00:00 2001 From: Gen FUKATSU Date: Thu, 21 Sep 2006 14:08:24 +0100 Subject: [ARM] 3789/4: Fix VFP emulation to ignore VECITR for scalar instruction VECITR in Floating-Point Exception register indicates the number of remaining short vector iterations after a potential exception was detected. In case of exception caused by scalar instructions, VECITR is NOT updated. Therefore emulation for VFP must ignore VECITR field and treat "veclen" as zero when recognizing scalar instructing. Signed-off-by: Gen Fukatsu Signed-off-by: Russell King --- arch/arm/vfp/vfpdouble.c | 72 ++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 36 deletions(-) (limited to 'arch/arm/vfp/vfpdouble.c') diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c index add48e3..e19a4f7 100644 --- a/arch/arm/vfp/vfpdouble.c +++ b/arch/arm/vfp/vfpdouble.c @@ -659,22 +659,22 @@ static u32 vfp_double_ftosiz(int dd, int unused, int dm, u32 fpscr) } -static u32 (* const fop_extfns[32])(int dd, int unused, int dm, u32 fpscr) = { - [FEXT_TO_IDX(FEXT_FCPY)] = vfp_double_fcpy, - [FEXT_TO_IDX(FEXT_FABS)] = vfp_double_fabs, - [FEXT_TO_IDX(FEXT_FNEG)] = vfp_double_fneg, - [FEXT_TO_IDX(FEXT_FSQRT)] = vfp_double_fsqrt, - [FEXT_TO_IDX(FEXT_FCMP)] = vfp_double_fcmp, - [FEXT_TO_IDX(FEXT_FCMPE)] = vfp_double_fcmpe, - [FEXT_TO_IDX(FEXT_FCMPZ)] = vfp_double_fcmpz, - [FEXT_TO_IDX(FEXT_FCMPEZ)] = vfp_double_fcmpez, - [FEXT_TO_IDX(FEXT_FCVT)] = vfp_double_fcvts, - [FEXT_TO_IDX(FEXT_FUITO)] = vfp_double_fuito, - [FEXT_TO_IDX(FEXT_FSITO)] = vfp_double_fsito, - [FEXT_TO_IDX(FEXT_FTOUI)] = vfp_double_ftoui, - [FEXT_TO_IDX(FEXT_FTOUIZ)] = vfp_double_ftouiz, - [FEXT_TO_IDX(FEXT_FTOSI)] = vfp_double_ftosi, - [FEXT_TO_IDX(FEXT_FTOSIZ)] = vfp_double_ftosiz, +static struct op fops_ext[32] = { + [FEXT_TO_IDX(FEXT_FCPY)] = {vfp_double_fcpy, 0}, + [FEXT_TO_IDX(FEXT_FABS)] = {vfp_double_fabs, 0}, + [FEXT_TO_IDX(FEXT_FNEG)] = {vfp_double_fneg, 0}, + [FEXT_TO_IDX(FEXT_FSQRT)] = {vfp_double_fsqrt, 0}, + [FEXT_TO_IDX(FEXT_FCMP)] = {vfp_double_fcmp, OP_SCALAR}, + [FEXT_TO_IDX(FEXT_FCMPE)] = {vfp_double_fcmpe, OP_SCALAR}, + [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_SD|OP_SCALAR)}, + [FEXT_TO_IDX(FEXT_FUITO)] = {vfp_double_fuito, OP_SCALAR}, + [FEXT_TO_IDX(FEXT_FSITO)] = {vfp_double_fsito, OP_SCALAR}, + [FEXT_TO_IDX(FEXT_FTOUI)] = {vfp_double_ftoui, (OP_SD|OP_SCALAR)}, + [FEXT_TO_IDX(FEXT_FTOUIZ)] = {vfp_double_ftouiz, (OP_SD|OP_SCALAR)}, + [FEXT_TO_IDX(FEXT_FTOSI)] = {vfp_double_ftosi, (OP_SD|OP_SCALAR)}, + [FEXT_TO_IDX(FEXT_FTOSIZ)] = {vfp_double_ftosiz, (OP_SD|OP_SCALAR)}, }; @@ -1108,16 +1108,16 @@ static u32 vfp_double_fdiv(int dd, int dn, int dm, u32 fpscr) return FPSCR_IOC; } -static u32 (* const fop_fns[16])(int dd, int dn, int dm, u32 fpscr) = { - [FOP_TO_IDX(FOP_FMAC)] = vfp_double_fmac, - [FOP_TO_IDX(FOP_FNMAC)] = vfp_double_fnmac, - [FOP_TO_IDX(FOP_FMSC)] = vfp_double_fmsc, - [FOP_TO_IDX(FOP_FNMSC)] = vfp_double_fnmsc, - [FOP_TO_IDX(FOP_FMUL)] = vfp_double_fmul, - [FOP_TO_IDX(FOP_FNMUL)] = vfp_double_fnmul, - [FOP_TO_IDX(FOP_FADD)] = vfp_double_fadd, - [FOP_TO_IDX(FOP_FSUB)] = vfp_double_fsub, - [FOP_TO_IDX(FOP_FDIV)] = vfp_double_fdiv, +static struct op fops[16] = { + [FOP_TO_IDX(FOP_FMAC)] = {vfp_double_fmac, 0}, + [FOP_TO_IDX(FOP_FNMAC)] = {vfp_double_fnmac, 0}, + [FOP_TO_IDX(FOP_FMSC)] = {vfp_double_fmsc, 0}, + [FOP_TO_IDX(FOP_FNMSC)] = {vfp_double_fnmsc, 0}, + [FOP_TO_IDX(FOP_FMUL)] = {vfp_double_fmul, 0}, + [FOP_TO_IDX(FOP_FNMUL)] = {vfp_double_fnmul, 0}, + [FOP_TO_IDX(FOP_FADD)] = {vfp_double_fadd, 0}, + [FOP_TO_IDX(FOP_FSUB)] = {vfp_double_fsub, 0}, + [FOP_TO_IDX(FOP_FDIV)] = {vfp_double_fdiv, 0}, }; #define FREG_BANK(x) ((x) & 0x0c) @@ -1131,39 +1131,39 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr) unsigned int dn = vfp_get_dn(inst); unsigned int dm = vfp_get_dm(inst); unsigned int vecitr, veclen, vecstride; - u32 (*fop)(int, int, s32, u32); + struct op *fop; - veclen = fpscr & FPSCR_LENGTH_MASK; vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)) * 2; + fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)]; /* * fcvtds takes an sN register number as destination, not dN. * It also always operates on scalars. */ - if ((inst & FEXT_MASK) == FEXT_FCVT) { - veclen = 0; + if (fop->flags & OP_SD) dest = vfp_get_sd(inst); - } else + else dest = vfp_get_dd(inst); /* * If destination bank is zero, vector length is always '1'. * ARM DDI0100F C5.1.3, C5.3.2. */ - if (FREG_BANK(dest) == 0) + if ((fop->flags & OP_SCALAR) || (FREG_BANK(dest) == 0)) veclen = 0; + else + veclen = fpscr & FPSCR_LENGTH_MASK; pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride, (veclen >> FPSCR_LENGTH_BIT) + 1); - fop = (op == FOP_EXT) ? fop_extfns[FEXT_TO_IDX(inst)] : fop_fns[FOP_TO_IDX(op)]; - if (!fop) + if (!fop->fn) goto invalid; for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) { u32 except; - if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT) + if (op == FOP_EXT && (fop->flags & OP_SD)) pr_debug("VFP: itr%d (s%u) = op[%u] (d%u)\n", vecitr >> FPSCR_LENGTH_BIT, dest, dn, dm); @@ -1176,7 +1176,7 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr) vecitr >> FPSCR_LENGTH_BIT, dest, dn, FOP_TO_IDX(op), dm); - except = fop(dest, dn, dm, fpscr); + except = fop->fn(dest, dn, dm, fpscr); pr_debug("VFP: itr%d: exceptions=%08x\n", vecitr >> FPSCR_LENGTH_BIT, except); -- cgit v1.1 From baf97ce6eda5891ee45fae9c1b06db855bb697e1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 21 Sep 2006 17:00:08 +0100 Subject: [ARM] Cleanups for 4cc9bd2eaa1063c68341c1c00e66660adcfdf254 - Document the meaning for OP_SCALAR, OP_SD and add OP_DD. - Formatting cleanups - Remove now redundant code for making compare instructions operate on scalar values. Signed-off-by: Russell King --- arch/arm/vfp/vfpdouble.c | 73 +++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 41 deletions(-) (limited to 'arch/arm/vfp/vfpdouble.c') diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c index e19a4f7..4fc05ee 100644 --- a/arch/arm/vfp/vfpdouble.c +++ b/arch/arm/vfp/vfpdouble.c @@ -660,21 +660,21 @@ static u32 vfp_double_ftosiz(int dd, int unused, int dm, u32 fpscr) static struct op fops_ext[32] = { - [FEXT_TO_IDX(FEXT_FCPY)] = {vfp_double_fcpy, 0}, - [FEXT_TO_IDX(FEXT_FABS)] = {vfp_double_fabs, 0}, - [FEXT_TO_IDX(FEXT_FNEG)] = {vfp_double_fneg, 0}, - [FEXT_TO_IDX(FEXT_FSQRT)] = {vfp_double_fsqrt, 0}, - [FEXT_TO_IDX(FEXT_FCMP)] = {vfp_double_fcmp, OP_SCALAR}, - [FEXT_TO_IDX(FEXT_FCMPE)] = {vfp_double_fcmpe, OP_SCALAR}, - [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_SD|OP_SCALAR)}, - [FEXT_TO_IDX(FEXT_FUITO)] = {vfp_double_fuito, OP_SCALAR}, - [FEXT_TO_IDX(FEXT_FSITO)] = {vfp_double_fsito, OP_SCALAR}, - [FEXT_TO_IDX(FEXT_FTOUI)] = {vfp_double_ftoui, (OP_SD|OP_SCALAR)}, - [FEXT_TO_IDX(FEXT_FTOUIZ)] = {vfp_double_ftouiz, (OP_SD|OP_SCALAR)}, - [FEXT_TO_IDX(FEXT_FTOSI)] = {vfp_double_ftosi, (OP_SD|OP_SCALAR)}, - [FEXT_TO_IDX(FEXT_FTOSIZ)] = {vfp_double_ftosiz, (OP_SD|OP_SCALAR)}, + [FEXT_TO_IDX(FEXT_FCPY)] = { vfp_double_fcpy, 0 }, + [FEXT_TO_IDX(FEXT_FABS)] = { vfp_double_fabs, 0 }, + [FEXT_TO_IDX(FEXT_FNEG)] = { vfp_double_fneg, 0 }, + [FEXT_TO_IDX(FEXT_FSQRT)] = { vfp_double_fsqrt, 0 }, + [FEXT_TO_IDX(FEXT_FCMP)] = { vfp_double_fcmp, OP_SCALAR }, + [FEXT_TO_IDX(FEXT_FCMPE)] = { vfp_double_fcmpe, OP_SCALAR }, + [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_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 }, + [FEXT_TO_IDX(FEXT_FTOSIZ)] = { vfp_double_ftosiz, OP_SCALAR|OP_SD }, }; @@ -1109,15 +1109,15 @@ static u32 vfp_double_fdiv(int dd, int dn, int dm, u32 fpscr) } static struct op fops[16] = { - [FOP_TO_IDX(FOP_FMAC)] = {vfp_double_fmac, 0}, - [FOP_TO_IDX(FOP_FNMAC)] = {vfp_double_fnmac, 0}, - [FOP_TO_IDX(FOP_FMSC)] = {vfp_double_fmsc, 0}, - [FOP_TO_IDX(FOP_FNMSC)] = {vfp_double_fnmsc, 0}, - [FOP_TO_IDX(FOP_FMUL)] = {vfp_double_fmul, 0}, - [FOP_TO_IDX(FOP_FNMUL)] = {vfp_double_fnmul, 0}, - [FOP_TO_IDX(FOP_FADD)] = {vfp_double_fadd, 0}, - [FOP_TO_IDX(FOP_FSUB)] = {vfp_double_fsub, 0}, - [FOP_TO_IDX(FOP_FDIV)] = {vfp_double_fdiv, 0}, + [FOP_TO_IDX(FOP_FMAC)] = { vfp_double_fmac, 0 }, + [FOP_TO_IDX(FOP_FNMAC)] = { vfp_double_fnmac, 0 }, + [FOP_TO_IDX(FOP_FMSC)] = { vfp_double_fmsc, 0 }, + [FOP_TO_IDX(FOP_FNMSC)] = { vfp_double_fnmsc, 0 }, + [FOP_TO_IDX(FOP_FMUL)] = { vfp_double_fmul, 0 }, + [FOP_TO_IDX(FOP_FNMUL)] = { vfp_double_fnmul, 0 }, + [FOP_TO_IDX(FOP_FADD)] = { vfp_double_fadd, 0 }, + [FOP_TO_IDX(FOP_FSUB)] = { vfp_double_fsub, 0 }, + [FOP_TO_IDX(FOP_FDIV)] = { vfp_double_fdiv, 0 }, }; #define FREG_BANK(x) ((x) & 0x0c) @@ -1136,6 +1136,7 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr) vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)) * 2; fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)]; + /* * fcvtds takes an sN register number as destination, not dN. * It also always operates on scalars. @@ -1162,19 +1163,17 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr) for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) { u32 except; + char type; - if (op == FOP_EXT && (fop->flags & OP_SD)) - pr_debug("VFP: itr%d (s%u) = op[%u] (d%u)\n", - vecitr >> FPSCR_LENGTH_BIT, - dest, dn, dm); - else if (op == FOP_EXT) - pr_debug("VFP: itr%d (d%u) = op[%u] (d%u)\n", + type = fop->flags & OP_SD ? 's' : 'd'; + if (op == FOP_EXT) + pr_debug("VFP: itr%d (%c%u) = op[%u] (d%u)\n", vecitr >> FPSCR_LENGTH_BIT, - dest, dn, dm); + type, dest, dn, dm); else - pr_debug("VFP: itr%d (d%u) = (d%u) op[%u] (d%u)\n", + pr_debug("VFP: itr%d (%c%u) = (d%u) op[%u] (d%u)\n", vecitr >> FPSCR_LENGTH_BIT, - dest, dn, FOP_TO_IDX(op), dm); + type, dest, dn, FOP_TO_IDX(op), dm); except = fop->fn(dest, dn, dm, fpscr); pr_debug("VFP: itr%d: exceptions=%08x\n", @@ -1183,17 +1182,9 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr) exceptions |= except; /* - * This ensures that comparisons only operate on scalars; - * comparisons always return with one FPSCR status bit set. - */ - if (except & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V)) - break; - - /* * CHECK: It appears to be undefined whether we stop when * we encounter an exception. We continue. */ - dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 6); dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 6); if (FREG_BANK(dm) != 0) -- cgit v1.1