|
@@ -308,3 +308,73 @@ static inline void vfp_double_unpack(struct vfp_double *s, s64 val)
|
|
significand = (significand << (64 - VFP_DOUBLE_MANTISSA_BITS)) >> 2;
|
|
significand = (significand << (64 - VFP_DOUBLE_MANTISSA_BITS)) >> 2;
|
|
if (s->exponent && s->exponent != 2047)
|
|
if (s->exponent && s->exponent != 2047)
|
|
significand |= (1ULL << 62);
|
|
significand |= (1ULL << 62);
|
|
|
|
+ s->significand = significand;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Re-pack a double-precision float. This assumes that the float is
|
|
|
|
+ * already normalised such that the MSB is bit 30, _not_ bit 31.
|
|
|
|
+ */
|
|
|
|
+static inline s64 vfp_double_pack(struct vfp_double *s)
|
|
|
|
+{
|
|
|
|
+ u64 val;
|
|
|
|
+ val = ((u64)s->sign << 48) +
|
|
|
|
+ ((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) +
|
|
|
|
+ (s->significand >> VFP_DOUBLE_LOW_BITS);
|
|
|
|
+ return (s64)val;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline int vfp_double_type(struct vfp_double *s)
|
|
|
|
+{
|
|
|
|
+ int type = VFP_NUMBER;
|
|
|
|
+ if (s->exponent == 2047) {
|
|
|
|
+ if (s->significand == 0)
|
|
|
|
+ type = VFP_INFINITY;
|
|
|
|
+ else if (s->significand & VFP_DOUBLE_SIGNIFICAND_QNAN)
|
|
|
|
+ type = VFP_QNAN;
|
|
|
|
+ else
|
|
|
|
+ type = VFP_SNAN;
|
|
|
|
+ } else if (s->exponent == 0) {
|
|
|
|
+ if (s->significand == 0)
|
|
|
|
+ type |= VFP_ZERO;
|
|
|
|
+ else
|
|
|
|
+ type |= VFP_DENORMAL;
|
|
|
|
+ }
|
|
|
|
+ return type;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+u32 vfp_double_normaliseround(int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func);
|
|
|
|
+
|
|
|
|
+u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand);
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * A special flag to tell the normalisation code not to normalise.
|
|
|
|
+ */
|
|
|
|
+#define VFP_NAN_FLAG 0x100
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * A bit pattern used to indicate the initial (unset) value of the
|
|
|
|
+ * exception mask, in case nothing handles an instruction. This
|
|
|
|
+ * doesn't include the NAN flag, which get masked out before
|
|
|
|
+ * we check for an error.
|
|
|
|
+ */
|
|
|
|
+#define VFP_EXCEPTION_ERROR ((u32)-1 & ~VFP_NAN_FLAG)
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * A flag to tell vfp instruction type.
|
|
|
|
+ * OP_SCALAR - this operation always operates in scalar mode
|
|
|
|
+ * OP_SD - the instruction exceptionally writes to a single precision result.
|
|
|
|
+ * OP_DD - the instruction exceptionally writes to a double precision result.
|
|
|
|
+ * OP_SM - the instruction exceptionally reads from a single precision operand.
|
|
|
|
+ */
|
|
|
|
+#define OP_SCALAR (1 << 0)
|
|
|
|
+#define OP_SD (1 << 1)
|
|
|
|
+#define OP_DD (1 << 1)
|
|
|
|
+#define OP_SM (1 << 2)
|
|
|
|
+
|
|
|
|
+struct op {
|
|
|
|
+ u32 (* const fn)(int dd, int dn, int dm, u32 fpscr);
|
|
|
|
+ u32 flags;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+extern void vfp_save_state(void *location, u32 fpexc);
|