diff options
Diffstat (limited to 'arch/arm/vfp/vfpsingle.c')
-rw-r--r-- | arch/arm/vfp/vfpsingle.c | 55 |
1 files changed, 33 insertions, 22 deletions
diff --git a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c index dae2c2f46052..8f6c179cafbe 100644 --- a/arch/arm/vfp/vfpsingle.c +++ b/arch/arm/vfp/vfpsingle.c | |||
@@ -200,7 +200,7 @@ u32 vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exce | |||
200 | s32 d = vfp_single_pack(vs); | 200 | s32 d = vfp_single_pack(vs); |
201 | pr_debug("VFP: %s: d(s%d)=%08x exceptions=%08x\n", func, | 201 | pr_debug("VFP: %s: d(s%d)=%08x exceptions=%08x\n", func, |
202 | sd, d, exceptions); | 202 | sd, d, exceptions); |
203 | vfp_put_float(sd, d); | 203 | vfp_put_float(d, sd); |
204 | } | 204 | } |
205 | 205 | ||
206 | return exceptions; | 206 | return exceptions; |
@@ -257,19 +257,19 @@ vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn, | |||
257 | */ | 257 | */ |
258 | static u32 vfp_single_fabs(int sd, int unused, s32 m, u32 fpscr) | 258 | static u32 vfp_single_fabs(int sd, int unused, s32 m, u32 fpscr) |
259 | { | 259 | { |
260 | vfp_put_float(sd, vfp_single_packed_abs(m)); | 260 | vfp_put_float(vfp_single_packed_abs(m), sd); |
261 | return 0; | 261 | return 0; |
262 | } | 262 | } |
263 | 263 | ||
264 | static u32 vfp_single_fcpy(int sd, int unused, s32 m, u32 fpscr) | 264 | static u32 vfp_single_fcpy(int sd, int unused, s32 m, u32 fpscr) |
265 | { | 265 | { |
266 | vfp_put_float(sd, m); | 266 | vfp_put_float(m, sd); |
267 | return 0; | 267 | return 0; |
268 | } | 268 | } |
269 | 269 | ||
270 | static u32 vfp_single_fneg(int sd, int unused, s32 m, u32 fpscr) | 270 | static u32 vfp_single_fneg(int sd, int unused, s32 m, u32 fpscr) |
271 | { | 271 | { |
272 | vfp_put_float(sd, vfp_single_packed_negate(m)); | 272 | vfp_put_float(vfp_single_packed_negate(m), sd); |
273 | return 0; | 273 | return 0; |
274 | } | 274 | } |
275 | 275 | ||
@@ -333,7 +333,7 @@ static u32 vfp_single_fsqrt(int sd, int unused, s32 m, u32 fpscr) | |||
333 | vsp = &vfp_single_default_qnan; | 333 | vsp = &vfp_single_default_qnan; |
334 | ret = FPSCR_IOC; | 334 | ret = FPSCR_IOC; |
335 | } | 335 | } |
336 | vfp_put_float(sd, vfp_single_pack(vsp)); | 336 | vfp_put_float(vfp_single_pack(vsp), sd); |
337 | return ret; | 337 | return ret; |
338 | } | 338 | } |
339 | 339 | ||
@@ -506,7 +506,7 @@ static u32 vfp_single_fcvtd(int dd, int unused, s32 m, u32 fpscr) | |||
506 | */ | 506 | */ |
507 | if (tm & (VFP_INFINITY|VFP_NAN)) { | 507 | if (tm & (VFP_INFINITY|VFP_NAN)) { |
508 | vdd.exponent = 2047; | 508 | vdd.exponent = 2047; |
509 | if (tm & VFP_NAN) | 509 | if (tm == VFP_QNAN) |
510 | vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN; | 510 | vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN; |
511 | goto pack_nan; | 511 | goto pack_nan; |
512 | } else if (tm & VFP_ZERO) | 512 | } else if (tm & VFP_ZERO) |
@@ -514,14 +514,10 @@ static u32 vfp_single_fcvtd(int dd, int unused, s32 m, u32 fpscr) | |||
514 | else | 514 | else |
515 | vdd.exponent = vsm.exponent + (1023 - 127); | 515 | vdd.exponent = vsm.exponent + (1023 - 127); |
516 | 516 | ||
517 | /* | ||
518 | * Technically, if bit 0 of dd is set, this is an invalid | ||
519 | * instruction. However, we ignore this for efficiency. | ||
520 | */ | ||
521 | return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fcvtd"); | 517 | return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fcvtd"); |
522 | 518 | ||
523 | pack_nan: | 519 | pack_nan: |
524 | vfp_put_double(dd, vfp_double_pack(&vdd)); | 520 | vfp_put_double(vfp_double_pack(&vdd), dd); |
525 | return exceptions; | 521 | return exceptions; |
526 | } | 522 | } |
527 | 523 | ||
@@ -617,7 +613,7 @@ static u32 vfp_single_ftoui(int sd, int unused, s32 m, u32 fpscr) | |||
617 | 613 | ||
618 | pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); | 614 | pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); |
619 | 615 | ||
620 | vfp_put_float(sd, d); | 616 | vfp_put_float(d, sd); |
621 | 617 | ||
622 | return exceptions; | 618 | return exceptions; |
623 | } | 619 | } |
@@ -696,7 +692,7 @@ static u32 vfp_single_ftosi(int sd, int unused, s32 m, u32 fpscr) | |||
696 | 692 | ||
697 | pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); | 693 | pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions); |
698 | 694 | ||
699 | vfp_put_float(sd, (s32)d); | 695 | vfp_put_float((s32)d, sd); |
700 | 696 | ||
701 | return exceptions; | 697 | return exceptions; |
702 | } | 698 | } |
@@ -1131,7 +1127,7 @@ static u32 vfp_single_fdiv(int sd, int sn, s32 m, u32 fpscr) | |||
1131 | vsn_nan: | 1127 | vsn_nan: |
1132 | exceptions = vfp_propagate_nan(&vsd, &vsn, &vsm, fpscr); | 1128 | exceptions = vfp_propagate_nan(&vsd, &vsn, &vsm, fpscr); |
1133 | pack: | 1129 | pack: |
1134 | vfp_put_float(sd, vfp_single_pack(&vsd)); | 1130 | vfp_put_float(vfp_single_pack(&vsd), sd); |
1135 | return exceptions; | 1131 | return exceptions; |
1136 | 1132 | ||
1137 | vsm_nan: | 1133 | vsm_nan: |
@@ -1151,7 +1147,7 @@ static u32 vfp_single_fdiv(int sd, int sn, s32 m, u32 fpscr) | |||
1151 | goto pack; | 1147 | goto pack; |
1152 | 1148 | ||
1153 | invalid: | 1149 | invalid: |
1154 | vfp_put_float(sd, vfp_single_pack(&vfp_single_default_qnan)); | 1150 | vfp_put_float(vfp_single_pack(&vfp_single_default_qnan), sd); |
1155 | return FPSCR_IOC; | 1151 | return FPSCR_IOC; |
1156 | } | 1152 | } |
1157 | 1153 | ||
@@ -1174,7 +1170,7 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr) | |||
1174 | { | 1170 | { |
1175 | u32 op = inst & FOP_MASK; | 1171 | u32 op = inst & FOP_MASK; |
1176 | u32 exceptions = 0; | 1172 | u32 exceptions = 0; |
1177 | unsigned int sd = vfp_get_sd(inst); | 1173 | unsigned int dest; |
1178 | unsigned int sn = vfp_get_sn(inst); | 1174 | unsigned int sn = vfp_get_sn(inst); |
1179 | unsigned int sm = vfp_get_sm(inst); | 1175 | unsigned int sm = vfp_get_sm(inst); |
1180 | unsigned int vecitr, veclen, vecstride; | 1176 | unsigned int vecitr, veclen, vecstride; |
@@ -1184,10 +1180,22 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr) | |||
1184 | vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK); | 1180 | vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK); |
1185 | 1181 | ||
1186 | /* | 1182 | /* |
1183 | * fcvtsd takes a dN register number as destination, not sN. | ||
1184 | * Technically, if bit 0 of dd is set, this is an invalid | ||
1185 | * instruction. However, we ignore this for efficiency. | ||
1186 | * It also only operates on scalars. | ||
1187 | */ | ||
1188 | if ((inst & FEXT_MASK) == FEXT_FCVT) { | ||
1189 | veclen = 0; | ||
1190 | dest = vfp_get_dd(inst); | ||
1191 | } else | ||
1192 | dest = vfp_get_sd(inst); | ||
1193 | |||
1194 | /* | ||
1187 | * If destination bank is zero, vector length is always '1'. | 1195 | * If destination bank is zero, vector length is always '1'. |
1188 | * ARM DDI0100F C5.1.3, C5.3.2. | 1196 | * ARM DDI0100F C5.1.3, C5.3.2. |
1189 | */ | 1197 | */ |
1190 | if (FREG_BANK(sd) == 0) | 1198 | if (FREG_BANK(dest) == 0) |
1191 | veclen = 0; | 1199 | veclen = 0; |
1192 | 1200 | ||
1193 | pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride, | 1201 | pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride, |
@@ -1201,15 +1209,18 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr) | |||
1201 | s32 m = vfp_get_float(sm); | 1209 | s32 m = vfp_get_float(sm); |
1202 | u32 except; | 1210 | u32 except; |
1203 | 1211 | ||
1204 | if (op == FOP_EXT) | 1212 | if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT) |
1213 | pr_debug("VFP: itr%d (d%u) = op[%u] (s%u=%08x)\n", | ||
1214 | vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m); | ||
1215 | else if (op == FOP_EXT) | ||
1205 | pr_debug("VFP: itr%d (s%u) = op[%u] (s%u=%08x)\n", | 1216 | pr_debug("VFP: itr%d (s%u) = op[%u] (s%u=%08x)\n", |
1206 | vecitr >> FPSCR_LENGTH_BIT, sd, sn, sm, m); | 1217 | vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m); |
1207 | else | 1218 | else |
1208 | pr_debug("VFP: itr%d (s%u) = (s%u) op[%u] (s%u=%08x)\n", | 1219 | pr_debug("VFP: itr%d (s%u) = (s%u) op[%u] (s%u=%08x)\n", |
1209 | vecitr >> FPSCR_LENGTH_BIT, sd, sn, | 1220 | vecitr >> FPSCR_LENGTH_BIT, dest, sn, |
1210 | FOP_TO_IDX(op), sm, m); | 1221 | FOP_TO_IDX(op), sm, m); |
1211 | 1222 | ||
1212 | except = fop(sd, sn, m, fpscr); | 1223 | except = fop(dest, sn, m, fpscr); |
1213 | pr_debug("VFP: itr%d: exceptions=%08x\n", | 1224 | pr_debug("VFP: itr%d: exceptions=%08x\n", |
1214 | vecitr >> FPSCR_LENGTH_BIT, except); | 1225 | vecitr >> FPSCR_LENGTH_BIT, except); |
1215 | 1226 | ||
@@ -1227,7 +1238,7 @@ u32 vfp_single_cpdo(u32 inst, u32 fpscr) | |||
1227 | * we encounter an exception. We continue. | 1238 | * we encounter an exception. We continue. |
1228 | */ | 1239 | */ |
1229 | 1240 | ||
1230 | sd = FREG_BANK(sd) + ((FREG_IDX(sd) + vecstride) & 7); | 1241 | dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 7); |
1231 | sn = FREG_BANK(sn) + ((FREG_IDX(sn) + vecstride) & 7); | 1242 | sn = FREG_BANK(sn) + ((FREG_IDX(sn) + vecstride) & 7); |
1232 | if (FREG_BANK(sm) != 0) | 1243 | if (FREG_BANK(sm) != 0) |
1233 | sm = FREG_BANK(sm) + ((FREG_IDX(sm) + vecstride) & 7); | 1244 | sm = FREG_BANK(sm) + ((FREG_IDX(sm) + vecstride) & 7); |