summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormiod <miod@openbsd.org>2014-07-02 20:28:08 +0000
committermiod <miod@openbsd.org>2014-07-02 20:28:08 +0000
commitcaf6d9d4ef630cc29fd681c3be2b90b96ab7cf23 (patch)
tree962da8447d5ddce2ba34077c4fa82df4b2e84330
parentImprove and test the messages about empty macros, (diff)
downloadwireguard-openbsd-caf6d9d4ef630cc29fd681c3be2b90b96ab7cf23.tar.xz
wireguard-openbsd-caf6d9d4ef630cc29fd681c3be2b90b96ab7cf23.zip
Be more careful when recreating single-precision (float) argument to service
precise exceptions, as the actual data the FPU gives us is a 35-bit number, with the exponent sign-extended to the double-precision exponent width. Make sure we shrink it and fetch the remaining three low bits of mantissa from the LS registers.
-rw-r--r--sys/arch/m88k/m88k/m88100_fp.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/sys/arch/m88k/m88k/m88100_fp.c b/sys/arch/m88k/m88k/m88100_fp.c
index 374d29a37e6..582f0a11c62 100644
--- a/sys/arch/m88k/m88k/m88100_fp.c
+++ b/sys/arch/m88k/m88k/m88100_fp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: m88100_fp.c,v 1.2 2014/07/01 20:26:09 miod Exp $ */
+/* $OpenBSD: m88100_fp.c,v 1.3 2014/07/02 20:28:08 miod Exp $ */
/*
* Copyright (c) 2007, 2014, Miodrag Vallat.
@@ -80,6 +80,24 @@ m88100_fpu_precise_exception(struct trapframe *frame)
}
/*
+ * Convert a single floating-point argument with its exponent sign-extended
+ * to 11 bits in an fphs/fpls pair to a correct 32-bit single precision
+ * number.
+ */
+static inline uint32_t
+m88100_fpu_parse_single(uint32_t hs, uint32_t ls)
+{
+ uint32_t result;
+
+ result = hs << (DBL_EXPBITS - SNG_EXPBITS);
+ result &= ~(1U << 31); /* clear carry into sign bit */
+ result |= ls >> (DBL_FRACBITS - SNG_FRACBITS);
+ result |= hs & (1U << 31); /* sign bit */
+
+ return result;
+}
+
+/*
* Load a floating-point argument into a fparg union, then convert it to
* the required format if it is of larger precision.
*
@@ -105,7 +123,9 @@ m88100_fpu_fetch(struct trapframe *frame, u_int operandno, u_int orig_width,
}
break;
case FTYPE_SNG:
- tmp = operandno == 1 ? frame->tf_fphs1 : frame->tf_fphs2;
+ tmp = operandno == 1 ?
+ m88100_fpu_parse_single(frame->tf_fphs1, frame->tf_fpls1) :
+ m88100_fpu_parse_single(frame->tf_fphs2, frame->tf_fpls2);
switch (width) {
case FTYPE_SNG:
dest->sng = tmp;