|
@@ -556,3 +556,171 @@ static u32 vfp_single_ftoui(int sd, int unused, s32 m, u32 fpscr)
|
|
|
|
|
|
/*
|
|
|
* Do we have a denormalised number?
|
|
|
+ */
|
|
|
+ tm = vfp_single_type(&vsm);
|
|
|
+ if (tm & VFP_DENORMAL)
|
|
|
+ exceptions |= FPSCR_IDC;
|
|
|
+
|
|
|
+ if (tm & VFP_NAN)
|
|
|
+ vsm.sign = 0;
|
|
|
+
|
|
|
+ if (vsm.exponent >= 127 + 32) {
|
|
|
+ d = vsm.sign ? 0 : 0xffffffff;
|
|
|
+ exceptions = FPSCR_IOC;
|
|
|
+ } else if (vsm.exponent >= 127 - 1) {
|
|
|
+ int shift = 127 + 31 - vsm.exponent;
|
|
|
+ u32 rem, incr = 0;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 2^0 <= m < 2^32-2^8
|
|
|
+ */
|
|
|
+ d = (vsm.significand << 1) >> shift;
|
|
|
+ rem = vsm.significand << (33 - shift);
|
|
|
+
|
|
|
+ if (rmode == FPSCR_ROUND_NEAREST) {
|
|
|
+ incr = 0x80000000;
|
|
|
+ if ((d & 1) == 0)
|
|
|
+ incr -= 1;
|
|
|
+ } else if (rmode == FPSCR_ROUND_TOZERO) {
|
|
|
+ incr = 0;
|
|
|
+ } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vsm.sign != 0)) {
|
|
|
+ incr = ~0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((rem + incr) < rem) {
|
|
|
+ if (d < 0xffffffff)
|
|
|
+ d += 1;
|
|
|
+ else
|
|
|
+ exceptions |= FPSCR_IOC;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (d && vsm.sign) {
|
|
|
+ d = 0;
|
|
|
+ exceptions |= FPSCR_IOC;
|
|
|
+ } else if (rem)
|
|
|
+ exceptions |= FPSCR_IXC;
|
|
|
+ } else {
|
|
|
+ d = 0;
|
|
|
+ if (vsm.exponent | vsm.significand) {
|
|
|
+ exceptions |= FPSCR_IXC;
|
|
|
+ if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0)
|
|
|
+ d = 1;
|
|
|
+ else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) {
|
|
|
+ d = 0;
|
|
|
+ exceptions |= FPSCR_IOC;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
|
|
|
+
|
|
|
+ vfp_put_float(d, sd);
|
|
|
+
|
|
|
+ return exceptions;
|
|
|
+}
|
|
|
+
|
|
|
+static u32 vfp_single_ftouiz(int sd, int unused, s32 m, u32 fpscr)
|
|
|
+{
|
|
|
+ return vfp_single_ftoui(sd, unused, m, FPSCR_ROUND_TOZERO);
|
|
|
+}
|
|
|
+
|
|
|
+static u32 vfp_single_ftosi(int sd, int unused, s32 m, u32 fpscr)
|
|
|
+{
|
|
|
+ struct vfp_single vsm;
|
|
|
+ u32 d, exceptions = 0;
|
|
|
+ int rmode = fpscr & FPSCR_RMODE_MASK;
|
|
|
+ int tm;
|
|
|
+
|
|
|
+ vfp_single_unpack(&vsm, m);
|
|
|
+ vfp_single_dump("VSM", &vsm);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Do we have a denormalised number?
|
|
|
+ */
|
|
|
+ tm = vfp_single_type(&vsm);
|
|
|
+ if (vfp_single_type(&vsm) & VFP_DENORMAL)
|
|
|
+ exceptions |= FPSCR_IDC;
|
|
|
+
|
|
|
+ if (tm & VFP_NAN) {
|
|
|
+ d = 0;
|
|
|
+ exceptions |= FPSCR_IOC;
|
|
|
+ } else if (vsm.exponent >= 127 + 32) {
|
|
|
+ /*
|
|
|
+ * m >= 2^31-2^7: invalid
|
|
|
+ */
|
|
|
+ d = 0x7fffffff;
|
|
|
+ if (vsm.sign)
|
|
|
+ d = ~d;
|
|
|
+ exceptions |= FPSCR_IOC;
|
|
|
+ } else if (vsm.exponent >= 127 - 1) {
|
|
|
+ int shift = 127 + 31 - vsm.exponent;
|
|
|
+ u32 rem, incr = 0;
|
|
|
+
|
|
|
+ /* 2^0 <= m <= 2^31-2^7 */
|
|
|
+ d = (vsm.significand << 1) >> shift;
|
|
|
+ rem = vsm.significand << (33 - shift);
|
|
|
+
|
|
|
+ if (rmode == FPSCR_ROUND_NEAREST) {
|
|
|
+ incr = 0x80000000;
|
|
|
+ if ((d & 1) == 0)
|
|
|
+ incr -= 1;
|
|
|
+ } else if (rmode == FPSCR_ROUND_TOZERO) {
|
|
|
+ incr = 0;
|
|
|
+ } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vsm.sign != 0)) {
|
|
|
+ incr = ~0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((rem + incr) < rem && d < 0xffffffff)
|
|
|
+ d += 1;
|
|
|
+ if (d > 0x7fffffff + (vsm.sign != 0)) {
|
|
|
+ d = 0x7fffffff + (vsm.sign != 0);
|
|
|
+ exceptions |= FPSCR_IOC;
|
|
|
+ } else if (rem)
|
|
|
+ exceptions |= FPSCR_IXC;
|
|
|
+
|
|
|
+ if (vsm.sign)
|
|
|
+ d = -d;
|
|
|
+ } else {
|
|
|
+ d = 0;
|
|
|
+ if (vsm.exponent | vsm.significand) {
|
|
|
+ exceptions |= FPSCR_IXC;
|
|
|
+ if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0)
|
|
|
+ d = 1;
|
|
|
+ else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign)
|
|
|
+ d = -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
|
|
|
+
|
|
|
+ vfp_put_float((s32)d, sd);
|
|
|
+
|
|
|
+ return exceptions;
|
|
|
+}
|
|
|
+
|
|
|
+static u32 vfp_single_ftosiz(int sd, int unused, s32 m, u32 fpscr)
|
|
|
+{
|
|
|
+ return vfp_single_ftosi(sd, unused, m, FPSCR_ROUND_TOZERO);
|
|
|
+}
|
|
|
+
|
|
|
+static struct op fops_ext[32] = {
|
|
|
+ [FEXT_TO_IDX(FEXT_FCPY)] = { vfp_single_fcpy, 0 },
|
|
|
+ [FEXT_TO_IDX(FEXT_FABS)] = { vfp_single_fabs, 0 },
|
|
|
+ [FEXT_TO_IDX(FEXT_FNEG)] = { vfp_single_fneg, 0 },
|
|
|
+ [FEXT_TO_IDX(FEXT_FSQRT)] = { vfp_single_fsqrt, 0 },
|
|
|
+ [FEXT_TO_IDX(FEXT_FCMP)] = { vfp_single_fcmp, OP_SCALAR },
|
|
|
+ [FEXT_TO_IDX(FEXT_FCMPE)] = { vfp_single_fcmpe, OP_SCALAR },
|
|
|
+ [FEXT_TO_IDX(FEXT_FCMPZ)] = { vfp_single_fcmpz, OP_SCALAR },
|
|
|
+ [FEXT_TO_IDX(FEXT_FCMPEZ)] = { vfp_single_fcmpez, OP_SCALAR },
|
|
|
+ [FEXT_TO_IDX(FEXT_FCVT)] = { vfp_single_fcvtd, OP_SCALAR|OP_DD },
|
|
|
+ [FEXT_TO_IDX(FEXT_FUITO)] = { vfp_single_fuito, OP_SCALAR },
|
|
|
+ [FEXT_TO_IDX(FEXT_FSITO)] = { vfp_single_fsito, OP_SCALAR },
|
|
|
+ [FEXT_TO_IDX(FEXT_FTOUI)] = { vfp_single_ftoui, OP_SCALAR },
|
|
|
+ [FEXT_TO_IDX(FEXT_FTOUIZ)] = { vfp_single_ftouiz, OP_SCALAR },
|
|
|
+ [FEXT_TO_IDX(FEXT_FTOSI)] = { vfp_single_ftosi, OP_SCALAR },
|
|
|
+ [FEXT_TO_IDX(FEXT_FTOSIZ)] = { vfp_single_ftosiz, OP_SCALAR },
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|