aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/vfp/vfpdouble.c
diff options
context:
space:
mode:
authorGen FUKATSU <fukatsu.gen@jp.panasonic.com>2006-09-21 09:08:24 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-09-25 05:34:06 -0400
commit4cc9bd2eaa1063c68341c1c00e66660adcfdf254 (patch)
tree3ee6d9f6b2075d4a5e340d2a3370f9e068aab723 /arch/arm/vfp/vfpdouble.c
parentf8c440b209581809c5c8acac599410f23597a7b8 (diff)
[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 <fukatsu.gen@jp.panasonic.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/vfp/vfpdouble.c')
-rw-r--r--arch/arm/vfp/vfpdouble.c72
1 files changed, 36 insertions, 36 deletions
diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c
index add48e36c2dc..e19a4f7620de 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)
659} 659}
660 660
661 661
662static u32 (* const fop_extfns[32])(int dd, int unused, int dm, u32 fpscr) = { 662static struct op fops_ext[32] = {
663 [FEXT_TO_IDX(FEXT_FCPY)] = vfp_double_fcpy, 663 [FEXT_TO_IDX(FEXT_FCPY)] = {vfp_double_fcpy, 0},
664 [FEXT_TO_IDX(FEXT_FABS)] = vfp_double_fabs, 664 [FEXT_TO_IDX(FEXT_FABS)] = {vfp_double_fabs, 0},
665 [FEXT_TO_IDX(FEXT_FNEG)] = vfp_double_fneg, 665 [FEXT_TO_IDX(FEXT_FNEG)] = {vfp_double_fneg, 0},
666 [FEXT_TO_IDX(FEXT_FSQRT)] = vfp_double_fsqrt, 666 [FEXT_TO_IDX(FEXT_FSQRT)] = {vfp_double_fsqrt, 0},
667 [FEXT_TO_IDX(FEXT_FCMP)] = vfp_double_fcmp, 667 [FEXT_TO_IDX(FEXT_FCMP)] = {vfp_double_fcmp, OP_SCALAR},
668 [FEXT_TO_IDX(FEXT_FCMPE)] = vfp_double_fcmpe, 668 [FEXT_TO_IDX(FEXT_FCMPE)] = {vfp_double_fcmpe, OP_SCALAR},
669 [FEXT_TO_IDX(FEXT_FCMPZ)] = vfp_double_fcmpz, 669 [FEXT_TO_IDX(FEXT_FCMPZ)] = {vfp_double_fcmpz, OP_SCALAR},
670 [FEXT_TO_IDX(FEXT_FCMPEZ)] = vfp_double_fcmpez, 670 [FEXT_TO_IDX(FEXT_FCMPEZ)] = {vfp_double_fcmpez, OP_SCALAR},
671 [FEXT_TO_IDX(FEXT_FCVT)] = vfp_double_fcvts, 671 [FEXT_TO_IDX(FEXT_FCVT)] = {vfp_double_fcvts, (OP_SD|OP_SCALAR)},
672 [FEXT_TO_IDX(FEXT_FUITO)] = vfp_double_fuito, 672 [FEXT_TO_IDX(FEXT_FUITO)] = {vfp_double_fuito, OP_SCALAR},
673 [FEXT_TO_IDX(FEXT_FSITO)] = vfp_double_fsito, 673 [FEXT_TO_IDX(FEXT_FSITO)] = {vfp_double_fsito, OP_SCALAR},
674 [FEXT_TO_IDX(FEXT_FTOUI)] = vfp_double_ftoui, 674 [FEXT_TO_IDX(FEXT_FTOUI)] = {vfp_double_ftoui, (OP_SD|OP_SCALAR)},
675 [FEXT_TO_IDX(FEXT_FTOUIZ)] = vfp_double_ftouiz, 675 [FEXT_TO_IDX(FEXT_FTOUIZ)] = {vfp_double_ftouiz, (OP_SD|OP_SCALAR)},
676 [FEXT_TO_IDX(FEXT_FTOSI)] = vfp_double_ftosi, 676 [FEXT_TO_IDX(FEXT_FTOSI)] = {vfp_double_ftosi, (OP_SD|OP_SCALAR)},
677 [FEXT_TO_IDX(FEXT_FTOSIZ)] = vfp_double_ftosiz, 677 [FEXT_TO_IDX(FEXT_FTOSIZ)] = {vfp_double_ftosiz, (OP_SD|OP_SCALAR)},
678}; 678};
679 679
680 680
@@ -1108,16 +1108,16 @@ static u32 vfp_double_fdiv(int dd, int dn, int dm, u32 fpscr)
1108 return FPSCR_IOC; 1108 return FPSCR_IOC;
1109} 1109}
1110 1110
1111static u32 (* const fop_fns[16])(int dd, int dn, int dm, u32 fpscr) = { 1111static struct op fops[16] = {
1112 [FOP_TO_IDX(FOP_FMAC)] = vfp_double_fmac, 1112 [FOP_TO_IDX(FOP_FMAC)] = {vfp_double_fmac, 0},
1113 [FOP_TO_IDX(FOP_FNMAC)] = vfp_double_fnmac, 1113 [FOP_TO_IDX(FOP_FNMAC)] = {vfp_double_fnmac, 0},
1114 [FOP_TO_IDX(FOP_FMSC)] = vfp_double_fmsc, 1114 [FOP_TO_IDX(FOP_FMSC)] = {vfp_double_fmsc, 0},
1115 [FOP_TO_IDX(FOP_FNMSC)] = vfp_double_fnmsc, 1115 [FOP_TO_IDX(FOP_FNMSC)] = {vfp_double_fnmsc, 0},
1116 [FOP_TO_IDX(FOP_FMUL)] = vfp_double_fmul, 1116 [FOP_TO_IDX(FOP_FMUL)] = {vfp_double_fmul, 0},
1117 [FOP_TO_IDX(FOP_FNMUL)] = vfp_double_fnmul, 1117 [FOP_TO_IDX(FOP_FNMUL)] = {vfp_double_fnmul, 0},
1118 [FOP_TO_IDX(FOP_FADD)] = vfp_double_fadd, 1118 [FOP_TO_IDX(FOP_FADD)] = {vfp_double_fadd, 0},
1119 [FOP_TO_IDX(FOP_FSUB)] = vfp_double_fsub, 1119 [FOP_TO_IDX(FOP_FSUB)] = {vfp_double_fsub, 0},
1120 [FOP_TO_IDX(FOP_FDIV)] = vfp_double_fdiv, 1120 [FOP_TO_IDX(FOP_FDIV)] = {vfp_double_fdiv, 0},
1121}; 1121};
1122 1122
1123#define FREG_BANK(x) ((x) & 0x0c) 1123#define FREG_BANK(x) ((x) & 0x0c)
@@ -1131,39 +1131,39 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
1131 unsigned int dn = vfp_get_dn(inst); 1131 unsigned int dn = vfp_get_dn(inst);
1132 unsigned int dm = vfp_get_dm(inst); 1132 unsigned int dm = vfp_get_dm(inst);
1133 unsigned int vecitr, veclen, vecstride; 1133 unsigned int vecitr, veclen, vecstride;
1134 u32 (*fop)(int, int, s32, u32); 1134 struct op *fop;
1135 1135
1136 veclen = fpscr & FPSCR_LENGTH_MASK;
1137 vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)) * 2; 1136 vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)) * 2;
1138 1137
1138 fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)];
1139 /* 1139 /*
1140 * fcvtds takes an sN register number as destination, not dN. 1140 * fcvtds takes an sN register number as destination, not dN.
1141 * It also always operates on scalars. 1141 * It also always operates on scalars.
1142 */ 1142 */
1143 if ((inst & FEXT_MASK) == FEXT_FCVT) { 1143 if (fop->flags & OP_SD)
1144 veclen = 0;
1145 dest = vfp_get_sd(inst); 1144 dest = vfp_get_sd(inst);
1146 } else 1145 else
1147 dest = vfp_get_dd(inst); 1146 dest = vfp_get_dd(inst);
1148 1147
1149 /* 1148 /*
1150 * If destination bank is zero, vector length is always '1'. 1149 * If destination bank is zero, vector length is always '1'.
1151 * ARM DDI0100F C5.1.3, C5.3.2. 1150 * ARM DDI0100F C5.1.3, C5.3.2.
1152 */ 1151 */
1153 if (FREG_BANK(dest) == 0) 1152 if ((fop->flags & OP_SCALAR) || (FREG_BANK(dest) == 0))
1154 veclen = 0; 1153 veclen = 0;
1154 else
1155 veclen = fpscr & FPSCR_LENGTH_MASK;
1155 1156
1156 pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride, 1157 pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
1157 (veclen >> FPSCR_LENGTH_BIT) + 1); 1158 (veclen >> FPSCR_LENGTH_BIT) + 1);
1158 1159
1159 fop = (op == FOP_EXT) ? fop_extfns[FEXT_TO_IDX(inst)] : fop_fns[FOP_TO_IDX(op)]; 1160 if (!fop->fn)
1160 if (!fop)
1161 goto invalid; 1161 goto invalid;
1162 1162
1163 for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) { 1163 for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
1164 u32 except; 1164 u32 except;
1165 1165
1166 if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT) 1166 if (op == FOP_EXT && (fop->flags & OP_SD))
1167 pr_debug("VFP: itr%d (s%u) = op[%u] (d%u)\n", 1167 pr_debug("VFP: itr%d (s%u) = op[%u] (d%u)\n",
1168 vecitr >> FPSCR_LENGTH_BIT, 1168 vecitr >> FPSCR_LENGTH_BIT,
1169 dest, dn, dm); 1169 dest, dn, dm);
@@ -1176,7 +1176,7 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr)
1176 vecitr >> FPSCR_LENGTH_BIT, 1176 vecitr >> FPSCR_LENGTH_BIT,
1177 dest, dn, FOP_TO_IDX(op), dm); 1177 dest, dn, FOP_TO_IDX(op), dm);
1178 1178
1179 except = fop(dest, dn, dm, fpscr); 1179 except = fop->fn(dest, dn, dm, fpscr);
1180 pr_debug("VFP: itr%d: exceptions=%08x\n", 1180 pr_debug("VFP: itr%d: exceptions=%08x\n",
1181 vecitr >> FPSCR_LENGTH_BIT, except); 1181 vecitr >> FPSCR_LENGTH_BIT, except);
1182 1182