|
@@ -446,3 +446,115 @@ static u32 vfp_double_fcvts(int sd, int unused, int dm, u32 fpscr)
|
|
vfp_double_unpack(&vdm, vfp_get_double(dm));
|
|
vfp_double_unpack(&vdm, vfp_get_double(dm));
|
|
|
|
|
|
tm = vfp_double_type(&vdm);
|
|
tm = vfp_double_type(&vdm);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * If we have a signalling NaN, signal invalid operation.
|
|
|
|
+ */
|
|
|
|
+ if (tm == VFP_SNAN)
|
|
|
|
+ exceptions = FPSCR_IOC;
|
|
|
|
+
|
|
|
|
+ if (tm & VFP_DENORMAL)
|
|
|
|
+ vfp_double_normalise_denormal(&vdm);
|
|
|
|
+
|
|
|
|
+ vsd.sign = vdm.sign;
|
|
|
|
+ vsd.significand = vfp_hi64to32jamming(vdm.significand);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * If we have an infinity or a NaN, the exponent must be 255
|
|
|
|
+ */
|
|
|
|
+ if (tm & (VFP_INFINITY|VFP_NAN)) {
|
|
|
|
+ vsd.exponent = 255;
|
|
|
|
+ if (tm == VFP_QNAN)
|
|
|
|
+ vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
|
|
|
|
+ goto pack_nan;
|
|
|
|
+ } else if (tm & VFP_ZERO)
|
|
|
|
+ vsd.exponent = 0;
|
|
|
|
+ else
|
|
|
|
+ vsd.exponent = vdm.exponent - (1023 - 127);
|
|
|
|
+
|
|
|
|
+ return vfp_single_normaliseround(sd, &vsd, fpscr, exceptions, "fcvts");
|
|
|
|
+
|
|
|
|
+ pack_nan:
|
|
|
|
+ vfp_put_float(vfp_single_pack(&vsd), sd);
|
|
|
|
+ return exceptions;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static u32 vfp_double_fuito(int dd, int unused, int dm, u32 fpscr)
|
|
|
|
+{
|
|
|
|
+ struct vfp_double vdm;
|
|
|
|
+ u32 m = vfp_get_float(dm);
|
|
|
|
+
|
|
|
|
+ vdm.sign = 0;
|
|
|
|
+ vdm.exponent = 1023 + 63 - 1;
|
|
|
|
+ vdm.significand = (u64)m;
|
|
|
|
+
|
|
|
|
+ return vfp_double_normaliseround(dd, &vdm, fpscr, 0, "fuito");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static u32 vfp_double_fsito(int dd, int unused, int dm, u32 fpscr)
|
|
|
|
+{
|
|
|
|
+ struct vfp_double vdm;
|
|
|
|
+ u32 m = vfp_get_float(dm);
|
|
|
|
+
|
|
|
|
+ vdm.sign = (m & 0x80000000) >> 16;
|
|
|
|
+ vdm.exponent = 1023 + 63 - 1;
|
|
|
|
+ vdm.significand = vdm.sign ? -m : m;
|
|
|
|
+
|
|
|
|
+ return vfp_double_normaliseround(dd, &vdm, fpscr, 0, "fsito");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static u32 vfp_double_ftoui(int sd, int unused, int dm, u32 fpscr)
|
|
|
|
+{
|
|
|
|
+ struct vfp_double vdm;
|
|
|
|
+ u32 d, exceptions = 0;
|
|
|
|
+ int rmode = fpscr & FPSCR_RMODE_MASK;
|
|
|
|
+ int tm;
|
|
|
|
+
|
|
|
|
+ vfp_double_unpack(&vdm, vfp_get_double(dm));
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Do we have a denormalised number?
|
|
|
|
+ */
|
|
|
|
+ tm = vfp_double_type(&vdm);
|
|
|
|
+ if (tm & VFP_DENORMAL)
|
|
|
|
+ exceptions |= FPSCR_IDC;
|
|
|
|
+
|
|
|
|
+ if (tm & VFP_NAN)
|
|
|
|
+ vdm.sign = 0;
|
|
|
|
+
|
|
|
|
+ if (vdm.exponent >= 1023 + 32) {
|
|
|
|
+ d = vdm.sign ? 0 : 0xffffffff;
|
|
|
|
+ exceptions = FPSCR_IOC;
|
|
|
|
+ } else if (vdm.exponent >= 1023 - 1) {
|
|
|
|
+ int shift = 1023 + 63 - vdm.exponent;
|
|
|
|
+ u64 rem, incr = 0;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * 2^0 <= m < 2^32-2^8
|
|
|
|
+ */
|
|
|
|
+ d = (vdm.significand << 1) >> shift;
|
|
|
|
+ rem = vdm.significand << (65 - shift);
|
|
|
|
+
|
|
|
|
+ if (rmode == FPSCR_ROUND_NEAREST) {
|
|
|
|
+ incr = 0x8000000000000000ULL;
|
|
|
|
+ if ((d & 1) == 0)
|
|
|
|
+ incr -= 1;
|
|
|
|
+ } else if (rmode == FPSCR_ROUND_TOZERO) {
|
|
|
|
+ incr = 0;
|
|
|
|
+ } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vdm.sign != 0)) {
|
|
|
|
+ incr = ~0ULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ((rem + incr) < rem) {
|
|
|
|
+ if (d < 0xffffffff)
|
|
|
|
+ d += 1;
|
|
|
|
+ else
|
|
|
|
+ exceptions |= FPSCR_IOC;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (d && vdm.sign) {
|
|
|
|
+ d = 0;
|
|
|
|
+ exceptions |= FPSCR_IOC;
|
|
|
|
+ } else if (rem)
|
|
|
|
+ exceptions |= FPSCR_IXC;
|
|
|
|
+ } else {
|