aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/vfp/vfpsingle.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/vfpsingle.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/vfpsingle.c')
-rw-r--r--arch/arm/vfp/vfpsingle.c70
1 files changed, 35 insertions, 35 deletions
diff --git a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c
index 8f6c179cafbe..4f717d72eb6b 100644
--- a/arch/arm/vfp/vfpsingle.c
+++ b/arch/arm/vfp/vfpsingle.c
@@ -702,22 +702,22 @@ static u32 vfp_single_ftosiz(int sd, int unused, s32 m, u32 fpscr)
702 return vfp_single_ftosi(sd, unused, m, FPSCR_ROUND_TOZERO); 702 return vfp_single_ftosi(sd, unused, m, FPSCR_ROUND_TOZERO);
703} 703}
704 704
705static u32 (* const fop_extfns[32])(int sd, int unused, s32 m, u32 fpscr) = { 705static struct op fops_ext[32] = {
706 [FEXT_TO_IDX(FEXT_FCPY)] = vfp_single_fcpy, 706 [FEXT_TO_IDX(FEXT_FCPY)] = {vfp_single_fcpy, 0},
707 [FEXT_TO_IDX(FEXT_FABS)] = vfp_single_fabs, 707 [FEXT_TO_IDX(FEXT_FABS)] = {vfp_single_fabs, 0},
708 [FEXT_TO_IDX(FEXT_FNEG)] = vfp_single_fneg, 708 [FEXT_TO_IDX(FEXT_FNEG)] = {vfp_single_fneg, 0},
709 [FEXT_TO_IDX(FEXT_FSQRT)] = vfp_single_fsqrt, 709 [FEXT_TO_IDX(FEXT_FSQRT)] = {vfp_single_fsqrt, 0},
710 [FEXT_TO_IDX(FEXT_FCMP)] = vfp_single_fcmp, 710 [FEXT_TO_IDX(FEXT_FCMP)] = {vfp_single_fcmp, OP_SCALAR},
711 [FEXT_TO_IDX(FEXT_FCMPE)] = vfp_single_fcmpe, 711 [FEXT_TO_IDX(FEXT_FCMPE)] = {vfp_single_fcmpe, OP_SCALAR},
712 [FEXT_TO_IDX(FEXT_FCMPZ)] = vfp_single_fcmpz, 712 [FEXT_TO_IDX(FEXT_FCMPZ)] = {vfp_single_fcmpz, OP_SCALAR},
713 [FEXT_TO_IDX(FEXT_FCMPEZ)] = vfp_single_fcmpez, 713 [FEXT_TO_IDX(FEXT_FCMPEZ)] = {vfp_single_fcmpez, OP_SCALAR},
714 [FEXT_TO_IDX(FEXT_FCVT)] = vfp_single_fcvtd, 714 [FEXT_TO_IDX(FEXT_FCVT)] = {vfp_single_fcvtd, (OP_SD|OP_SCALAR)},
715 [FEXT_TO_IDX(FEXT_FUITO)] = vfp_single_fuito, 715 [FEXT_TO_IDX(FEXT_FUITO)] = {vfp_single_fuito, OP_SCALAR},
716 [FEXT_TO_IDX(FEXT_FSITO)] = vfp_single_fsito, 716 [FEXT_TO_IDX(FEXT_FSITO)] = {vfp_single_fsito, OP_SCALAR},
717 [FEXT_TO_IDX(FEXT_FTOUI)] = vfp_single_ftoui, 717 [FEXT_TO_IDX(FEXT_FTOUI)] = {vfp_single_ftoui, OP_SCALAR},
718 [FEXT_TO_IDX(FEXT_FTOUIZ)] = vfp_single_ftouiz, 718 [FEXT_TO_IDX(FEXT_FTOUIZ)] = {vfp_single_ftouiz, OP_SCALAR},
719 [FEXT_TO_IDX(FEXT_FTOSI)] = vfp_single_ftosi, 719 [FEXT_TO_IDX(FEXT_FTOSI)] = {vfp_single_ftosi, OP_SCALAR},
720 [FEXT_TO_IDX(FEXT_FTOSIZ)] = vfp_single_ftosiz, 720 [FEXT_TO_IDX(FEXT_FTOSIZ)] = {vfp_single_ftosiz, OP_SCALAR},
721}; 721};
722 722
723 723
@@ -1151,16 +1151,16 @@ static u32 vfp_single_fdiv(int sd, int sn, s32 m, u32 fpscr)
1151 return FPSCR_IOC; 1151 return FPSCR_IOC;
1152} 1152}
1153 1153
1154static u32 (* const fop_fns[16])(int sd, int sn, s32 m, u32 fpscr) = { 1154static struct op fops[16] = {
1155 [FOP_TO_IDX(FOP_FMAC)] = vfp_single_fmac, 1155 [FOP_TO_IDX(FOP_FMAC)] = {vfp_single_fmac, 0},
1156 [FOP_TO_IDX(FOP_FNMAC)] = vfp_single_fnmac, 1156 [FOP_TO_IDX(FOP_FNMAC)] = {vfp_single_fnmac, 0},
1157 [FOP_TO_IDX(FOP_FMSC)] = vfp_single_fmsc, 1157 [FOP_TO_IDX(FOP_FMSC)] = {vfp_single_fmsc, 0},
1158 [FOP_TO_IDX(FOP_FNMSC)] = vfp_single_fnmsc, 1158 [FOP_TO_IDX(FOP_FNMSC)] = {vfp_single_fnmsc, 0},
1159 [FOP_TO_IDX(FOP_FMUL)] = vfp_single_fmul, 1159 [FOP_TO_IDX(FOP_FMUL)] = {vfp_single_fmul, 0},
1160 [FOP_TO_IDX(FOP_FNMUL)] = vfp_single_fnmul, 1160 [FOP_TO_IDX(FOP_FNMUL)] = {vfp_single_fnmul, 0},
1161 [FOP_TO_IDX(FOP_FADD)] = vfp_single_fadd, 1161 [FOP_TO_IDX(FOP_FADD)] = {vfp_single_fadd, 0},
1162 [FOP_TO_IDX(FOP_FSUB)] = vfp_single_fsub, 1162 [FOP_TO_IDX(FOP_FSUB)] = {vfp_single_fsub, 0},
1163 [FOP_TO_IDX(FOP_FDIV)] = vfp_single_fdiv, 1163 [FOP_TO_IDX(FOP_FDIV)] = {vfp_single_fdiv, 0},
1164}; 1164};
1165 1165
1166#define FREG_BANK(x) ((x) & 0x18) 1166#define FREG_BANK(x) ((x) & 0x18)
@@ -1174,19 +1174,18 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
1174 unsigned int sn = vfp_get_sn(inst); 1174 unsigned int sn = vfp_get_sn(inst);
1175 unsigned int sm = vfp_get_sm(inst); 1175 unsigned int sm = vfp_get_sm(inst);
1176 unsigned int vecitr, veclen, vecstride; 1176 unsigned int vecitr, veclen, vecstride;
1177 u32 (*fop)(int, int, s32, u32); 1177 struct op *fop;
1178 1178
1179 veclen = fpscr & FPSCR_LENGTH_MASK;
1180 vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK); 1179 vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK);
1181 1180
1181 fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)];
1182 /* 1182 /*
1183 * fcvtsd takes a dN register number as destination, not sN. 1183 * fcvtsd takes a dN register number as destination, not sN.
1184 * Technically, if bit 0 of dd is set, this is an invalid 1184 * Technically, if bit 0 of dd is set, this is an invalid
1185 * instruction. However, we ignore this for efficiency. 1185 * instruction. However, we ignore this for efficiency.
1186 * It also only operates on scalars. 1186 * It also only operates on scalars.
1187 */ 1187 */
1188 if ((inst & FEXT_MASK) == FEXT_FCVT) { 1188 if (fop->flags & OP_SD) {
1189 veclen = 0;
1190 dest = vfp_get_dd(inst); 1189 dest = vfp_get_dd(inst);
1191 } else 1190 } else
1192 dest = vfp_get_sd(inst); 1191 dest = vfp_get_sd(inst);
@@ -1195,21 +1194,22 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
1195 * If destination bank is zero, vector length is always '1'. 1194 * If destination bank is zero, vector length is always '1'.
1196 * ARM DDI0100F C5.1.3, C5.3.2. 1195 * ARM DDI0100F C5.1.3, C5.3.2.
1197 */ 1196 */
1198 if (FREG_BANK(dest) == 0) 1197 if ((fop->flags & OP_SCALAR) || (FREG_BANK(dest) == 0))
1199 veclen = 0; 1198 veclen = 0;
1199 else
1200 veclen = fpscr & FPSCR_LENGTH_MASK;
1200 1201
1201 pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride, 1202 pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
1202 (veclen >> FPSCR_LENGTH_BIT) + 1); 1203 (veclen >> FPSCR_LENGTH_BIT) + 1);
1203 1204
1204 fop = (op == FOP_EXT) ? fop_extfns[FEXT_TO_IDX(inst)] : fop_fns[FOP_TO_IDX(op)]; 1205 if (!fop->fn)
1205 if (!fop)
1206 goto invalid; 1206 goto invalid;
1207 1207
1208 for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) { 1208 for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
1209 s32 m = vfp_get_float(sm); 1209 s32 m = vfp_get_float(sm);
1210 u32 except; 1210 u32 except;
1211 1211
1212 if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT) 1212 if (op == FOP_EXT && (fop->flags & OP_SD))
1213 pr_debug("VFP: itr%d (d%u) = op[%u] (s%u=%08x)\n", 1213 pr_debug("VFP: itr%d (d%u) = op[%u] (s%u=%08x)\n",
1214 vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m); 1214 vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m);
1215 else if (op == FOP_EXT) 1215 else if (op == FOP_EXT)
@@ -1220,7 +1220,7 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr)
1220 vecitr >> FPSCR_LENGTH_BIT, dest, sn, 1220 vecitr >> FPSCR_LENGTH_BIT, dest, sn,
1221 FOP_TO_IDX(op), sm, m); 1221 FOP_TO_IDX(op), sm, m);
1222 1222
1223 except = fop(dest, sn, m, fpscr); 1223 except = fop->fn(dest, sn, m, fpscr);
1224 pr_debug("VFP: itr%d: exceptions=%08x\n", 1224 pr_debug("VFP: itr%d: exceptions=%08x\n",
1225 vecitr >> FPSCR_LENGTH_BIT, except); 1225 vecitr >> FPSCR_LENGTH_BIT, except);
1226 1226