diff options
author | 2014-07-02 20:28:08 +0000 | |
---|---|---|
committer | 2014-07-02 20:28:08 +0000 | |
commit | caf6d9d4ef630cc29fd681c3be2b90b96ab7cf23 (patch) | |
tree | 962da8447d5ddce2ba34077c4fa82df4b2e84330 | |
parent | Improve and test the messages about empty macros, (diff) | |
download | wireguard-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.c | 24 |
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; |