* [Qemu-devel] [PATCH v3 0/4] target/m68k: implement 680x0 FPU (part 3)
@ 2018-02-23 14:59 Laurent Vivier
2018-02-23 14:59 ` [Qemu-devel] [PATCH v3 1/4] softfloat: export some functions Laurent Vivier
` (3 more replies)
0 siblings, 4 replies; 12+ messages in thread
From: Laurent Vivier @ 2018-02-23 14:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Thomas Huth, Laurent Vivier
Implement fmod, frem, fscale, fgetman and fgetexp.
Instead of using functions of libm (v1 of this series)
and converting between host long double and floatx80 type
the new version (v2) adds new floatx80 functions in softfloat.
All the floatx80 functions are copied from "Previous",
the NeXT Computer Emulator, and written by Andreas Grabher.
v3: Move all new functions to target/m68k/softfloat.c
Exports needed functions from fpu/softfloat.c
Laurent Vivier (4):
softfloat: export some functions
target/m68k: add fmod/frem
softfloat: use floatx80_infinity in softfloat
target/m68k: add fscale, fgetman and fgetexp
fpu/softfloat-specialize.h | 17 ++-
fpu/softfloat.c | 129 +++++------------
{fpu => include/fpu}/softfloat-macros.h | 10 +-
include/fpu/softfloat.h | 129 ++++++++++++++++-
target/m68k/Makefile.objs | 3 +-
target/m68k/cpu.h | 1 +
target/m68k/fpu_helper.c | 50 ++++++-
target/m68k/helper.h | 5 +
target/m68k/softfloat.c | 249 ++++++++++++++++++++++++++++++++
target/m68k/softfloat.h | 29 ++++
target/m68k/translate.c | 15 ++
11 files changed, 533 insertions(+), 104 deletions(-)
rename {fpu => include/fpu}/softfloat-macros.h (98%)
create mode 100644 target/m68k/softfloat.c
create mode 100644 target/m68k/softfloat.h
--
2.14.3
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH v3 1/4] softfloat: export some functions
2018-02-23 14:59 [Qemu-devel] [PATCH v3 0/4] target/m68k: implement 680x0 FPU (part 3) Laurent Vivier
@ 2018-02-23 14:59 ` Laurent Vivier
2018-02-24 1:26 ` Richard Henderson
2018-02-23 14:59 ` [Qemu-devel] [PATCH v3 2/4] target/m68k: add fmod/frem Laurent Vivier
` (2 subsequent siblings)
3 siblings, 1 reply; 12+ messages in thread
From: Laurent Vivier @ 2018-02-23 14:59 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Thomas Huth, Laurent Vivier, Aurelien Jarno,
Alex Bennée, Peter Maydell
Move fpu/softfloat-macros.h to include/fpu/
Export floatx80 functions to be used by target floatx80
specific implementations.
Exports:
propagateFloatx80NaN(), extractFloatx80Frac(),
extractFloatx80Exp(), extractFloatx80Sign(),
normalizeFloatx80Subnormal(), packFloatx80(),
roundAndPackFloatx80(), normalizeRoundAndPackFloatx80()
Also exports packFloat32() that will be used to implement
m68k fsinh, fcos, fsin, ftan operations.
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
CC: Aurelien Jarno <aurelien@aurel32.net>
CC: Alex Bennée <alex.bennee@linaro.org>
CC: Peter Maydell <peter.maydell@linaro.org>
fpu/softfloat-specialize.h | 3 +-
fpu/softfloat.c | 91 +++---------------------
{fpu => include/fpu}/softfloat-macros.h | 10 +--
include/fpu/softfloat.h | 120 ++++++++++++++++++++++++++++++++
4 files changed, 136 insertions(+), 88 deletions(-)
rename {fpu => include/fpu}/softfloat-macros.h (98%)
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index e81ca001e1..46126e9e0a 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -1011,8 +1011,7 @@ static floatx80 commonNaNToFloatx80(commonNaNT a, float_status *status)
| `b' is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
-static floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b,
- float_status *status)
+floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
{
flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
flag aIsLargerSignificand;
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index e7fb0d357a..fb4853682e 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -93,7 +93,7 @@ this code that are retained.
| division and square root approximations. (Can be specialized to target if
| desired.)
*----------------------------------------------------------------------------*/
-#include "softfloat-macros.h"
+#include "fpu/softfloat-macros.h"
/*----------------------------------------------------------------------------
| Functions and definitions to determine: (1) whether tininess for underflow
@@ -2192,25 +2192,6 @@ static void
}
-/*----------------------------------------------------------------------------
-| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
-| single-precision floating-point value, returning the result. After being
-| shifted into the proper positions, the three fields are simply added
-| together to form the result. This means that any integer portion of `zSig'
-| will be added into the exponent. Since a properly normalized significand
-| will have an integer portion equal to 1, the `zExp' input should be 1 less
-| than the desired result exponent whenever `zSig' is a complete, normalized
-| significand.
-*----------------------------------------------------------------------------*/
-
-static inline float32 packFloat32(flag zSign, int zExp, uint32_t zSig)
-{
-
- return make_float32(
- ( ( (uint32_t) zSign )<<31 ) + ( ( (uint32_t) zExp )<<23 ) + zSig);
-
-}
-
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
| and significand `zSig', and returns the proper single-precision floating-
@@ -2490,42 +2471,6 @@ static float64
}
-/*----------------------------------------------------------------------------
-| Returns the fraction bits of the extended double-precision floating-point
-| value `a'.
-*----------------------------------------------------------------------------*/
-
-static inline uint64_t extractFloatx80Frac( floatx80 a )
-{
-
- return a.low;
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns the exponent bits of the extended double-precision floating-point
-| value `a'.
-*----------------------------------------------------------------------------*/
-
-static inline int32_t extractFloatx80Exp( floatx80 a )
-{
-
- return a.high & 0x7FFF;
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns the sign bit of the extended double-precision floating-point value
-| `a'.
-*----------------------------------------------------------------------------*/
-
-static inline flag extractFloatx80Sign( floatx80 a )
-{
-
- return a.high>>15;
-
-}
-
/*----------------------------------------------------------------------------
| Normalizes the subnormal extended double-precision floating-point value
| represented by the denormalized significand `aSig'. The normalized exponent
@@ -2533,30 +2478,14 @@ static inline flag extractFloatx80Sign( floatx80 a )
| `zSigPtr', respectively.
*----------------------------------------------------------------------------*/
-static void
- normalizeFloatx80Subnormal( uint64_t aSig, int32_t *zExpPtr, uint64_t *zSigPtr )
+void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
+ uint64_t *zSigPtr)
{
int8_t shiftCount;
shiftCount = countLeadingZeros64( aSig );
*zSigPtr = aSig<<shiftCount;
*zExpPtr = 1 - shiftCount;
-
-}
-
-/*----------------------------------------------------------------------------
-| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an
-| extended double-precision floating-point value, returning the result.
-*----------------------------------------------------------------------------*/
-
-static inline floatx80 packFloatx80( flag zSign, int32_t zExp, uint64_t zSig )
-{
- floatx80 z;
-
- z.low = zSig;
- z.high = ( ( (uint16_t) zSign )<<15 ) + zExp;
- return z;
-
}
/*----------------------------------------------------------------------------
@@ -2583,9 +2512,9 @@ static inline floatx80 packFloatx80( flag zSign, int32_t zExp, uint64_t zSig )
| Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-static floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign,
- int32_t zExp, uint64_t zSig0, uint64_t zSig1,
- float_status *status)
+floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign,
+ int32_t zExp, uint64_t zSig0, uint64_t zSig1,
+ float_status *status)
{
int8_t roundingMode;
flag roundNearestEven, increment, isTiny;
@@ -2779,10 +2708,10 @@ static floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign,
| normalized.
*----------------------------------------------------------------------------*/
-static floatx80 normalizeRoundAndPackFloatx80(int8_t roundingPrecision,
- flag zSign, int32_t zExp,
- uint64_t zSig0, uint64_t zSig1,
- float_status *status)
+floatx80 normalizeRoundAndPackFloatx80(int8_t roundingPrecision,
+ flag zSign, int32_t zExp,
+ uint64_t zSig0, uint64_t zSig1,
+ float_status *status)
{
int8_t shiftCount;
diff --git a/fpu/softfloat-macros.h b/include/fpu/softfloat-macros.h
similarity index 98%
rename from fpu/softfloat-macros.h
rename to include/fpu/softfloat-macros.h
index c45a23193e..35e1603a5e 100644
--- a/fpu/softfloat-macros.h
+++ b/include/fpu/softfloat-macros.h
@@ -603,7 +603,7 @@ static inline void
| unsigned integer is returned.
*----------------------------------------------------------------------------*/
-static uint64_t estimateDiv128To64( uint64_t a0, uint64_t a1, uint64_t b )
+static inline uint64_t estimateDiv128To64(uint64_t a0, uint64_t a1, uint64_t b)
{
uint64_t b0, b1;
uint64_t rem0, rem1, term0, term1;
@@ -630,7 +630,7 @@ static uint64_t estimateDiv128To64( uint64_t a0, uint64_t a1, uint64_t b )
*
* Licensed under the GPLv2/LGPLv3
*/
-static uint64_t div128To64(uint64_t n0, uint64_t n1, uint64_t d)
+static inline uint64_t div128To64(uint64_t n0, uint64_t n1, uint64_t d)
{
uint64_t d0, d1, q0, q1, r1, r0, m;
@@ -683,7 +683,7 @@ static uint64_t div128To64(uint64_t n0, uint64_t n1, uint64_t d)
| value.
*----------------------------------------------------------------------------*/
-static uint32_t estimateSqrt32(int aExp, uint32_t a)
+static inline uint32_t estimateSqrt32(int aExp, uint32_t a)
{
static const uint16_t sqrtOddAdjustments[] = {
0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
@@ -717,7 +717,7 @@ static uint32_t estimateSqrt32(int aExp, uint32_t a)
| `a'. If `a' is zero, 32 is returned.
*----------------------------------------------------------------------------*/
-static int8_t countLeadingZeros32( uint32_t a )
+static inline int8_t countLeadingZeros32(uint32_t a)
{
#if SOFTFLOAT_GNUC_PREREQ(3, 4)
if (a) {
@@ -765,7 +765,7 @@ static int8_t countLeadingZeros32( uint32_t a )
| `a'. If `a' is zero, 64 is returned.
*----------------------------------------------------------------------------*/
-static int8_t countLeadingZeros64( uint64_t a )
+static inline int8_t countLeadingZeros64(uint64_t a)
{
#if SOFTFLOAT_GNUC_PREREQ(3, 4)
if (a) {
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 9b7b5e34e2..125dcb5586 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -419,6 +419,22 @@ static inline float32 float32_set_sign(float32 a, int sign)
#define float32_half make_float32(0x3f000000)
#define float32_infinity make_float32(0x7f800000)
+/*----------------------------------------------------------------------------
+| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
+| single-precision floating-point value, returning the result. After being
+| shifted into the proper positions, the three fields are simply added
+| together to form the result. This means that any integer portion of `zSig'
+| will be added into the exponent. Since a properly normalized significand
+| will have an integer portion equal to 1, the `zExp' input should be 1 less
+| than the desired result exponent whenever `zSig' is a complete, normalized
+| significand.
+*----------------------------------------------------------------------------*/
+
+static inline float32 packFloat32(flag zSign, int zExp, uint32_t zSig)
+{
+ return make_float32(
+ (((uint32_t)zSign) << 31) + (((uint32_t)zExp) << 23) + zSig);
+}
/*----------------------------------------------------------------------------
| The pattern for a default generated single-precision NaN.
@@ -632,6 +648,110 @@ static inline bool floatx80_invalid_encoding(floatx80 a)
#define floatx80_half make_floatx80(0x3ffe, 0x8000000000000000LL)
#define floatx80_infinity make_floatx80(0x7fff, 0x8000000000000000LL)
+/*----------------------------------------------------------------------------
+| Returns the fraction bits of the extended double-precision floating-point
+| value `a'.
+*----------------------------------------------------------------------------*/
+
+static inline uint64_t extractFloatx80Frac(floatx80 a)
+{
+ return a.low;
+}
+
+/*----------------------------------------------------------------------------
+| Returns the exponent bits of the extended double-precision floating-point
+| value `a'.
+*----------------------------------------------------------------------------*/
+
+static inline int32_t extractFloatx80Exp(floatx80 a)
+{
+ return a.high & 0x7FFF;
+}
+
+/*----------------------------------------------------------------------------
+| Returns the sign bit of the extended double-precision floating-point value
+| `a'.
+*----------------------------------------------------------------------------*/
+
+static inline flag extractFloatx80Sign(floatx80 a)
+{
+ return a.high >> 15;
+}
+
+/*----------------------------------------------------------------------------
+| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an
+| extended double-precision floating-point value, returning the result.
+*----------------------------------------------------------------------------*/
+
+static inline floatx80 packFloatx80(flag zSign, int32_t zExp, uint64_t zSig)
+{
+ floatx80 z;
+
+ z.low = zSig;
+ z.high = (((uint16_t)zSign) << 15) + zExp;
+ return z;
+}
+
+/*----------------------------------------------------------------------------
+| Normalizes the subnormal extended double-precision floating-point value
+| represented by the denormalized significand `aSig'. The normalized exponent
+| and significand are stored at the locations pointed to by `zExpPtr' and
+| `zSigPtr', respectively.
+*----------------------------------------------------------------------------*/
+
+void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
+ uint64_t *zSigPtr);
+
+/*----------------------------------------------------------------------------
+| Takes two extended double-precision floating-point values `a' and `b', one
+| of which is a NaN, and returns the appropriate NaN result. If either `a' or
+| `b' is a signaling NaN, the invalid exception is raised.
+*----------------------------------------------------------------------------*/
+
+floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status);
+
+/*----------------------------------------------------------------------------
+| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+| and extended significand formed by the concatenation of `zSig0' and `zSig1',
+| and returns the proper extended double-precision floating-point value
+| corresponding to the abstract input. Ordinarily, the abstract value is
+| rounded and packed into the extended double-precision format, with the
+| inexact exception raised if the abstract input cannot be represented
+| exactly. However, if the abstract value is too large, the overflow and
+| inexact exceptions are raised and an infinity or maximal finite value is
+| returned. If the abstract value is too small, the input value is rounded to
+| a subnormal number, and the underflow and inexact exceptions are raised if
+| the abstract input cannot be represented exactly as a subnormal extended
+| double-precision floating-point number.
+| If `roundingPrecision' is 32 or 64, the result is rounded to the same
+| number of bits as single or double precision, respectively. Otherwise, the
+| result is rounded to the full precision of the extended double-precision
+| format.
+| The input significand must be normalized or smaller. If the input
+| significand is not normalized, `zExp' must be 0; in that case, the result
+| returned is a subnormal number, and it must not require rounding. The
+| handling of underflow and overflow follows the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign,
+ int32_t zExp, uint64_t zSig0, uint64_t zSig1,
+ float_status *status);
+
+/*----------------------------------------------------------------------------
+| Takes an abstract floating-point value having sign `zSign', exponent
+| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
+| and returns the proper extended double-precision floating-point value
+| corresponding to the abstract input. This routine is just like
+| `roundAndPackFloatx80' except that the input significand does not have to be
+| normalized.
+*----------------------------------------------------------------------------*/
+
+floatx80 normalizeRoundAndPackFloatx80(int8_t roundingPrecision,
+ flag zSign, int32_t zExp,
+ uint64_t zSig0, uint64_t zSig1,
+ float_status *status);
+
/*----------------------------------------------------------------------------
| The pattern for a default generated extended double-precision NaN.
*----------------------------------------------------------------------------*/
--
2.14.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH v3 2/4] target/m68k: add fmod/frem
2018-02-23 14:59 [Qemu-devel] [PATCH v3 0/4] target/m68k: implement 680x0 FPU (part 3) Laurent Vivier
2018-02-23 14:59 ` [Qemu-devel] [PATCH v3 1/4] softfloat: export some functions Laurent Vivier
@ 2018-02-23 14:59 ` Laurent Vivier
2018-02-24 1:31 ` Richard Henderson
2018-02-23 14:59 ` [Qemu-devel] [PATCH v3 3/4] softfloat: use floatx80_infinity in softfloat Laurent Vivier
2018-02-23 14:59 ` [Qemu-devel] [PATCH v3 4/4] target/m68k: add fscale, fgetman and fgetexp Laurent Vivier
3 siblings, 1 reply; 12+ messages in thread
From: Laurent Vivier @ 2018-02-23 14:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Thomas Huth, Laurent Vivier
Using a local m68k floatx80_mod()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]
The quotient byte of the FPSR is updated with
the result of the operation.
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
target/m68k/Makefile.objs | 3 +-
target/m68k/cpu.h | 1 +
target/m68k/fpu_helper.c | 35 +++++++++++++++-
target/m68k/helper.h | 2 +
target/m68k/softfloat.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++
target/m68k/softfloat.h | 26 ++++++++++++
target/m68k/translate.c | 6 +++
7 files changed, 176 insertions(+), 2 deletions(-)
create mode 100644 target/m68k/softfloat.c
create mode 100644 target/m68k/softfloat.h
diff --git a/target/m68k/Makefile.objs b/target/m68k/Makefile.objs
index d143f20270..ac61948676 100644
--- a/target/m68k/Makefile.objs
+++ b/target/m68k/Makefile.objs
@@ -1,4 +1,5 @@
obj-y += m68k-semi.o
-obj-y += translate.o op_helper.o helper.o cpu.o fpu_helper.o
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-y += fpu_helper.o softfloat.o
obj-y += gdbstub.o
obj-$(CONFIG_SOFTMMU) += monitor.o
diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
index 65f4fb95cb..2259bf22dc 100644
--- a/target/m68k/cpu.h
+++ b/target/m68k/cpu.h
@@ -427,6 +427,7 @@ typedef enum {
/* Quotient */
#define FPSR_QT_MASK 0x00ff0000
+#define FPSR_QT_SHIFT 16
/* Floating-Point Control Register */
/* Rounding mode */
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 3c5a82aaa0..8286228b81 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -23,7 +23,7 @@
#include "exec/helper-proto.h"
#include "exec/exec-all.h"
#include "exec/cpu_ldst.h"
-#include "fpu/softfloat.h"
+#include "softfloat.h"
/* Undefined offsets may be different on various FPU.
* On 68040 they return 0.0 (floatx80_zero)
@@ -509,3 +509,36 @@ uint32_t HELPER(fmovemd_ld_postinc)(CPUM68KState *env, uint32_t addr,
{
return fmovem_postinc(env, addr, mask, cpu_ld_float64_ra);
}
+
+static void make_quotient(CPUM68KState *env, floatx80 val)
+{
+ int32_t quotient;
+ int sign;
+
+ if (floatx80_is_any_nan(val)) {
+ return;
+ }
+
+ quotient = floatx80_to_int32(val, &env->fp_status);
+ sign = quotient < 0;
+ if (sign) {
+ quotient = -quotient;
+ }
+
+ quotient = (sign << 7) | (quotient & 0x7f);
+ env->fpsr = (env->fpsr & ~FPSR_QT_MASK) | (quotient << FPSR_QT_SHIFT);
+}
+
+void HELPER(fmod)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
+{
+ res->d = floatx80_mod(val1->d, val0->d, &env->fp_status);
+
+ make_quotient(env, res->d);
+}
+
+void HELPER(frem)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
+{
+ res->d = floatx80_rem(val1->d, val0->d, &env->fp_status);
+
+ make_quotient(env, res->d);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 7f400f0def..76a0590c9c 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -63,6 +63,8 @@ DEF_HELPER_3(fmovemx_ld_postinc, i32, env, i32, i32)
DEF_HELPER_3(fmovemd_st_predec, i32, env, i32, i32)
DEF_HELPER_3(fmovemd_st_postinc, i32, env, i32, i32)
DEF_HELPER_3(fmovemd_ld_postinc, i32, env, i32, i32)
+DEF_HELPER_4(fmod, void, env, fp, fp, fp)
+DEF_HELPER_4(frem, void, env, fp, fp, fp)
DEF_HELPER_3(mac_move, void, env, i32, i32)
DEF_HELPER_3(macmulf, i64, env, i32, i32)
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
new file mode 100644
index 0000000000..8c77757b4e
--- /dev/null
+++ b/target/m68k/softfloat.c
@@ -0,0 +1,105 @@
+/*
+ * Ported from a work by Andreas Grabher for Previous, NeXT Computer Emulator,
+ * derived from NetBSD M68040 FPSP functions,
+ * derived from release 2a of the SoftFloat IEC/IEEE Floating-point Arithmetic
+ * Package. Those parts of the code (and some later contributions) are
+ * provided under that license, as detailed below.
+ * It has subsequently been modified by contributors to the QEMU Project,
+ * so some portions are provided under:
+ * the SoftFloat-2a license
+ * the BSD license
+ * GPL-v2-or-later
+ *
+ * Any future contributions to this file will be taken to be licensed under
+ * the Softfloat-2a license unless specifically indicated otherwise.
+ */
+
+/* Portions of this work are licensed under the terms of the GNU GPL,
+ * version 2 or later. See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "softfloat.h"
+#include "fpu/softfloat-macros.h"
+
+/*----------------------------------------------------------------------------
+ | Returns the modulo remainder of the extended double-precision floating-point
+ | value `a' with respect to the corresponding value `b'.
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status)
+{
+ flag aSign, zSign;
+ int32_t aExp, bExp, expDiff;
+ uint64_t aSig0, aSig1, bSig;
+ uint64_t qTemp, term0, term1;
+
+ aSig0 = extractFloatx80Frac(a);
+ aExp = extractFloatx80Exp(a);
+ aSign = extractFloatx80Sign(a);
+ bSig = extractFloatx80Frac(b);
+ bExp = extractFloatx80Exp(b);
+
+ if (aExp == 0x7FFF) {
+ if ((uint64_t) (aSig0 << 1)
+ || ((bExp == 0x7FFF) && (uint64_t) (bSig << 1))) {
+ return propagateFloatx80NaN(a, b, status);
+ }
+ goto invalid;
+ }
+ if (bExp == 0x7FFF) {
+ if ((uint64_t) (bSig << 1)) {
+ return propagateFloatx80NaN(a, b, status);
+ }
+ return a;
+ }
+ if (bExp == 0) {
+ if (bSig == 0) {
+ invalid:
+ float_raise(float_flag_invalid, status);
+ return floatx80_default_nan(status);
+ }
+ normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
+ }
+ if (aExp == 0) {
+ if ((uint64_t) (aSig0 << 1) == 0) {
+ return a;
+ }
+ normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
+ }
+ bSig |= LIT64(0x8000000000000000);
+ zSign = aSign;
+ expDiff = aExp - bExp;
+ aSig1 = 0;
+ if (expDiff < 0) {
+ return a;
+ }
+ qTemp = (bSig <= aSig0);
+ if (qTemp) {
+ aSig0 -= bSig;
+ }
+ expDiff -= 64;
+ while (0 < expDiff) {
+ qTemp = estimateDiv128To64(aSig0, aSig1, bSig);
+ qTemp = (2 < qTemp) ? qTemp - 2 : 0;
+ mul64To128(bSig, qTemp, &term0, &term1);
+ sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1);
+ shortShift128Left(aSig0, aSig1, 62, &aSig0, &aSig1);
+ }
+ expDiff += 64;
+ if (0 < expDiff) {
+ qTemp = estimateDiv128To64(aSig0, aSig1, bSig);
+ qTemp = (2 < qTemp) ? qTemp - 2 : 0;
+ qTemp >>= 64 - expDiff;
+ mul64To128(bSig, qTemp << (64 - expDiff), &term0, &term1);
+ sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1);
+ shortShift128Left(0, bSig, 64 - expDiff, &term0, &term1);
+ while (le128(term0, term1, aSig0, aSig1)) {
+ ++qTemp;
+ sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1);
+ }
+ }
+ return
+ normalizeRoundAndPackFloatx80(
+ 80, zSign, bExp + expDiff, aSig0, aSig1, status);
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
new file mode 100644
index 0000000000..8d8ca0fc45
--- /dev/null
+++ b/target/m68k/softfloat.h
@@ -0,0 +1,26 @@
+/*
+ * Ported from a work by Andreas Grabher for Previous, NeXT Computer Emulator,
+ * derived from NetBSD M68040 FPSP functions,
+ * derived from release 2a of the SoftFloat IEC/IEEE Floating-point Arithmetic
+ * Package. Those parts of the code (and some later contributions) are
+ * provided under that license, as detailed below.
+ * It has subsequently been modified by contributors to the QEMU Project,
+ * so some portions are provided under:
+ * the SoftFloat-2a license
+ * the BSD license
+ * GPL-v2-or-later
+ *
+ * Any future contributions to this file will be taken to be licensed under
+ * the Softfloat-2a license unless specifically indicated otherwise.
+ */
+
+/* Portions of this work are licensed under the terms of the GNU GPL,
+ * version 2 or later. See the COPYING file in the top-level directory.
+ */
+
+#ifndef TARGET_M68K_SOFTFLOAT_H
+#define TARGET_M68K_SOFTFLOAT_H
+#include "fpu/softfloat.h"
+
+floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status);
+#endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index a22993c7ce..f8db26fa8e 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5081,6 +5081,9 @@ DISAS_INSN(fpu)
case 0x64: /* fddiv */
gen_helper_fddiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
break;
+ case 0x21: /* fmod */
+ gen_helper_fmod(cpu_env, cpu_dest, cpu_src, cpu_dest);
+ break;
case 0x22: /* fadd */
gen_helper_fadd(cpu_env, cpu_dest, cpu_src, cpu_dest);
break;
@@ -5102,6 +5105,9 @@ DISAS_INSN(fpu)
case 0x24: /* fsgldiv */
gen_helper_fsgldiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
break;
+ case 0x25: /* frem */
+ gen_helper_frem(cpu_env, cpu_dest, cpu_src, cpu_dest);
+ break;
case 0x27: /* fsglmul */
gen_helper_fsglmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
break;
--
2.14.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH v3 3/4] softfloat: use floatx80_infinity in softfloat
2018-02-23 14:59 [Qemu-devel] [PATCH v3 0/4] target/m68k: implement 680x0 FPU (part 3) Laurent Vivier
2018-02-23 14:59 ` [Qemu-devel] [PATCH v3 1/4] softfloat: export some functions Laurent Vivier
2018-02-23 14:59 ` [Qemu-devel] [PATCH v3 2/4] target/m68k: add fmod/frem Laurent Vivier
@ 2018-02-23 14:59 ` Laurent Vivier
2018-02-24 2:26 ` Richard Henderson
2018-02-23 14:59 ` [Qemu-devel] [PATCH v3 4/4] target/m68k: add fscale, fgetman and fgetexp Laurent Vivier
3 siblings, 1 reply; 12+ messages in thread
From: Laurent Vivier @ 2018-02-23 14:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Thomas Huth, Laurent Vivier, Aurelien Jarno
Since f3218a8 ("softfloat: add floatx80 constants")
floatx80_infinity is defined but never used.
This patch updates floatx80 functions to use
this definition.
This allows to define a different default Infinity
value on m68k: the m68k FPU defines infinity with
all bits set to zero in the mantissa.
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
CC: Aurelien Jarno <aurelien@aurel32.net>
fpu/softfloat-specialize.h | 14 ++++++++++++++
fpu/softfloat.c | 38 ++++++++++++++++++++++++++------------
include/fpu/softfloat.h | 9 +++++++--
3 files changed, 47 insertions(+), 14 deletions(-)
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 46126e9e0a..9ccb59422c 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -177,6 +177,20 @@ floatx80 floatx80_default_nan(float_status *status)
return r;
}
+/*----------------------------------------------------------------------------
+| The pattern for a default generated extended double-precision inf.
+*----------------------------------------------------------------------------*/
+
+#define floatx80_infinity_high 0x7FFF
+#if defined(TARGET_M68K)
+#define floatx80_infinity_low LIT64(0x0000000000000000)
+#else
+#define floatx80_infinity_low LIT64(0x8000000000000000)
+#endif
+
+const floatx80 floatx80_infinity
+ = make_floatx80_init(floatx80_infinity_high, floatx80_infinity_low);
+
/*----------------------------------------------------------------------------
| The pattern for a default generated quadruple-precision NaN.
*----------------------------------------------------------------------------*/
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index fb4853682e..70a86e156c 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -2636,7 +2636,9 @@ floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign,
) {
return packFloatx80( zSign, 0x7FFE, ~ roundMask );
}
- return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ return packFloatx80(zSign,
+ floatx80_infinity_high,
+ floatx80_infinity_low);
}
if ( zExp <= 0 ) {
isTiny =
@@ -3182,7 +3184,9 @@ floatx80 float32_to_floatx80(float32 a, float_status *status)
if (aSig) {
return commonNaNToFloatx80(float32ToCommonNaN(a, status), status);
}
- return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ return packFloatx80(aSign,
+ floatx80_infinity_high,
+ floatx80_infinity_low);
}
if ( aExp == 0 ) {
if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
@@ -4037,7 +4041,9 @@ floatx80 float64_to_floatx80(float64 a, float_status *status)
if (aSig) {
return commonNaNToFloatx80(float64ToCommonNaN(a, status), status);
}
- return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ return packFloatx80(aSign,
+ floatx80_infinity_high,
+ floatx80_infinity_low);
}
if ( aExp == 0 ) {
if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
@@ -4550,8 +4556,8 @@ int64_t floatx80_to_int64(floatx80 a, float_status *status)
if ( shiftCount ) {
float_raise(float_flag_invalid, status);
if ( ! aSign
- || ( ( aExp == 0x7FFF )
- && ( aSig != LIT64( 0x8000000000000000 ) ) )
+ || ((aExp == floatx80_infinity_high)
+ && (aSig != floatx80_infinity_low))
) {
return LIT64( 0x7FFFFFFFFFFFFFFF );
}
@@ -4858,7 +4864,9 @@ static floatx80 addFloatx80Sigs(floatx80 a, floatx80 b, flag zSign,
if ((uint64_t)(bSig << 1)) {
return propagateFloatx80NaN(a, b, status);
}
- return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ return packFloatx80(zSign,
+ floatx80_infinity_high,
+ floatx80_infinity_low);
}
if ( aExp == 0 ) ++expDiff;
shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
@@ -4933,7 +4941,8 @@ static floatx80 subFloatx80Sigs(floatx80 a, floatx80 b, flag zSign,
if ((uint64_t)(bSig << 1)) {
return propagateFloatx80NaN(a, b, status);
}
- return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ return packFloatx80(zSign ^ 1, floatx80_infinity_high,
+ floatx80_infinity_low);
}
if ( aExp == 0 ) ++expDiff;
shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
@@ -5038,7 +5047,8 @@ floatx80 floatx80_mul(floatx80 a, floatx80 b, float_status *status)
return propagateFloatx80NaN(a, b, status);
}
if ( ( bExp | bSig ) == 0 ) goto invalid;
- return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ return packFloatx80(zSign, floatx80_infinity_high,
+ floatx80_infinity_low);
}
if ( bExp == 0x7FFF ) {
if ((uint64_t)(bSig << 1)) {
@@ -5049,7 +5059,8 @@ floatx80 floatx80_mul(floatx80 a, floatx80 b, float_status *status)
float_raise(float_flag_invalid, status);
return floatx80_default_nan(status);
}
- return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ return packFloatx80(zSign, floatx80_infinity_high,
+ floatx80_infinity_low);
}
if ( aExp == 0 ) {
if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
@@ -5103,7 +5114,8 @@ floatx80 floatx80_div(floatx80 a, floatx80 b, float_status *status)
}
goto invalid;
}
- return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ return packFloatx80(zSign, floatx80_infinity_high,
+ floatx80_infinity_low);
}
if ( bExp == 0x7FFF ) {
if ((uint64_t)(bSig << 1)) {
@@ -5119,7 +5131,8 @@ floatx80 floatx80_div(floatx80 a, floatx80 b, float_status *status)
return floatx80_default_nan(status);
}
float_raise(float_flag_divbyzero, status);
- return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ return packFloatx80(zSign, floatx80_infinity_high,
+ floatx80_infinity_low);
}
normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
}
@@ -5942,7 +5955,8 @@ floatx80 float128_to_floatx80(float128 a, float_status *status)
if ( aSig0 | aSig1 ) {
return commonNaNToFloatx80(float128ToCommonNaN(a, status), status);
}
- return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ return packFloatx80(aSign, floatx80_infinity_high,
+ floatx80_infinity_low);
}
if ( aExp == 0 ) {
if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 );
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 125dcb5586..7edf407cbc 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -563,6 +563,11 @@ float32 floatx80_to_float32(floatx80, float_status *status);
float64 floatx80_to_float64(floatx80, float_status *status);
float128 floatx80_to_float128(floatx80, float_status *status);
+/*----------------------------------------------------------------------------
+| The pattern for an extended double-precision inf.
+*----------------------------------------------------------------------------*/
+extern const floatx80 floatx80_infinity;
+
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision operations.
*----------------------------------------------------------------------------*/
@@ -603,7 +608,8 @@ static inline floatx80 floatx80_chs(floatx80 a)
static inline int floatx80_is_infinity(floatx80 a)
{
- return (a.high & 0x7fff) == 0x7fff && a.low == 0x8000000000000000LL;
+ return (a.high & 0x7fff) == floatx80_infinity.high &&
+ a.low == floatx80_infinity.low;
}
static inline int floatx80_is_neg(floatx80 a)
@@ -646,7 +652,6 @@ static inline bool floatx80_invalid_encoding(floatx80 a)
#define floatx80_ln2 make_floatx80(0x3ffe, 0xb17217f7d1cf79acLL)
#define floatx80_pi make_floatx80(0x4000, 0xc90fdaa22168c235LL)
#define floatx80_half make_floatx80(0x3ffe, 0x8000000000000000LL)
-#define floatx80_infinity make_floatx80(0x7fff, 0x8000000000000000LL)
/*----------------------------------------------------------------------------
| Returns the fraction bits of the extended double-precision floating-point
--
2.14.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH v3 4/4] target/m68k: add fscale, fgetman and fgetexp
2018-02-23 14:59 [Qemu-devel] [PATCH v3 0/4] target/m68k: implement 680x0 FPU (part 3) Laurent Vivier
` (2 preceding siblings ...)
2018-02-23 14:59 ` [Qemu-devel] [PATCH v3 3/4] softfloat: use floatx80_infinity in softfloat Laurent Vivier
@ 2018-02-23 14:59 ` Laurent Vivier
2018-02-24 2:33 ` Richard Henderson
3 siblings, 1 reply; 12+ messages in thread
From: Laurent Vivier @ 2018-02-23 14:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Thomas Huth, Laurent Vivier
Using local m68k floatx80_getman(), floatx80_getexp(), floatx80_scale()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
target/m68k/fpu_helper.c | 15 +++++
target/m68k/helper.h | 3 +
target/m68k/softfloat.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++
target/m68k/softfloat.h | 3 +
target/m68k/translate.c | 9 +++
5 files changed, 174 insertions(+)
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 8286228b81..cdb9b50462 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -542,3 +542,18 @@ void HELPER(frem)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
make_quotient(env, res->d);
}
+
+void HELPER(fgetexp)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+ res->d = floatx80_getexp(val->d, &env->fp_status);
+}
+
+void HELPER(fgetman)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+ res->d = floatx80_getman(val->d, &env->fp_status);
+}
+
+void HELPER(fscale)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
+{
+ res->d = floatx80_scale(val1->d, val0->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 76a0590c9c..c348dced3a 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -65,6 +65,9 @@ DEF_HELPER_3(fmovemd_st_postinc, i32, env, i32, i32)
DEF_HELPER_3(fmovemd_ld_postinc, i32, env, i32, i32)
DEF_HELPER_4(fmod, void, env, fp, fp, fp)
DEF_HELPER_4(frem, void, env, fp, fp, fp)
+DEF_HELPER_3(fgetexp, void, env, fp, fp)
+DEF_HELPER_3(fgetman, void, env, fp, fp)
+DEF_HELPER_4(fscale, void, env, fp, fp, fp)
DEF_HELPER_3(mac_move, void, env, i32, i32)
DEF_HELPER_3(macmulf, i64, env, i32, i32)
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index 8c77757b4e..9cb141900c 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -22,6 +22,19 @@
#include "softfloat.h"
#include "fpu/softfloat-macros.h"
+static floatx80 propagateFloatx80NaNOneArg(floatx80 a, float_status *status)
+{
+ if (floatx80_is_signaling_nan(a, status)) {
+ float_raise(float_flag_invalid, status);
+ }
+
+ if (status->default_nan_mode) {
+ return floatx80_default_nan(status);
+ }
+
+ return floatx80_maybe_silence_nan(a, status);
+}
+
/*----------------------------------------------------------------------------
| Returns the modulo remainder of the extended double-precision floating-point
| value `a' with respect to the corresponding value `b'.
@@ -103,3 +116,134 @@ floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status)
normalizeRoundAndPackFloatx80(
80, zSign, bExp + expDiff, aSig0, aSig1, status);
}
+
+/*----------------------------------------------------------------------------
+ | Returns the mantissa of the extended double-precision floating-point
+ | value `a'.
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_getman(floatx80 a, float_status *status)
+{
+ flag aSign;
+ int32_t aExp;
+ uint64_t aSig;
+
+ aSig = extractFloatx80Frac(a);
+ aExp = extractFloatx80Exp(a);
+ aSign = extractFloatx80Sign(a);
+
+ if (aExp == 0x7FFF) {
+ if ((uint64_t) (aSig << 1)) {
+ return propagateFloatx80NaNOneArg(a , status);
+ }
+ float_raise(float_flag_invalid , status);
+ return floatx80_default_nan(status);
+ }
+
+ if (aExp == 0) {
+ if (aSig == 0) {
+ return packFloatx80(aSign, 0, 0);
+ }
+ normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+ }
+
+ return roundAndPackFloatx80(status->floatx80_rounding_precision, aSign,
+ 0x3FFF, aSig, 0, status);
+}
+
+/*----------------------------------------------------------------------------
+ | Returns the exponent of the extended double-precision floating-point
+ | value `a' as an extended double-precision value.
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_getexp(floatx80 a, float_status *status)
+{
+ flag aSign;
+ int32_t aExp;
+ uint64_t aSig;
+
+ aSig = extractFloatx80Frac(a);
+ aExp = extractFloatx80Exp(a);
+ aSign = extractFloatx80Sign(a);
+
+ if (aExp == 0x7FFF) {
+ if ((uint64_t) (aSig << 1)) {
+ return propagateFloatx80NaNOneArg(a , status);
+ }
+ float_raise(float_flag_invalid , status);
+ return floatx80_default_nan(status);
+ }
+
+ if (aExp == 0) {
+ if (aSig == 0) {
+ return packFloatx80(aSign, 0, 0);
+ }
+ normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+ }
+
+ return int32_to_floatx80(aExp - 0x3FFF, status);
+}
+
+/*----------------------------------------------------------------------------
+ | Scales extended double-precision floating-point value in operand `a' by
+ | value `b'. The function truncates the value in the second operand 'b' to
+ | an integral value and adds that value to the exponent of the operand 'a'.
+ | The operation performed according to the IEC/IEEE Standard for Binary
+ | Floating-Point Arithmetic.
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status)
+{
+ flag aSign, bSign;
+ int32_t aExp, bExp, shiftCount;
+ uint64_t aSig, bSig;
+
+ aSig = extractFloatx80Frac(a);
+ aExp = extractFloatx80Exp(a);
+ aSign = extractFloatx80Sign(a);
+ bSig = extractFloatx80Frac(b);
+ bExp = extractFloatx80Exp(b);
+ bSign = extractFloatx80Sign(b);
+
+ if (bExp == 0x7FFF) {
+ if ((uint64_t) (bSig << 1) ||
+ ((aExp == 0x7FFF) && (uint64_t) (aSig << 1))) {
+ return propagateFloatx80NaN(a, b, status);
+ }
+ float_raise(float_flag_invalid , status);
+ return floatx80_default_nan(status);
+ }
+ if (aExp == 0x7FFF) {
+ if ((uint64_t) (aSig << 1)) {
+ return propagateFloatx80NaN(a, b, status);
+ }
+ return packFloatx80(aSign, floatx80_infinity.high,
+ floatx80_infinity.low);
+ }
+ if (aExp == 0) {
+ if (aSig == 0) {
+ return packFloatx80(aSign, 0, 0);
+ }
+ if (bExp < 0x3FFF) {
+ return a;
+ }
+ normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+ }
+
+ if (bExp < 0x3FFF) {
+ return a;
+ }
+
+ if (0x400F < bExp) {
+ aExp = bSign ? -0x6001 : 0xE000;
+ return roundAndPackFloatx80(status->floatx80_rounding_precision,
+ aSign, aExp, aSig, 0, status);
+ }
+
+ shiftCount = 0x403E - bExp;
+ bSig >>= shiftCount;
+ aExp = bSign ? (aExp - bSig) : (aExp + bSig);
+
+ return roundAndPackFloatx80(status->floatx80_rounding_precision,
+ aSign, aExp, aSig, 0, status);
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index 8d8ca0fc45..78fbc0cd0c 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -23,4 +23,7 @@
#include "fpu/softfloat.h"
floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status);
+floatx80 floatx80_getman(floatx80 a, float_status *status);
+floatx80 floatx80_getexp(floatx80 a, float_status *status);
+floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status);
#endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index f8db26fa8e..dbb24f8d84 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5072,6 +5072,12 @@ DISAS_INSN(fpu)
case 0x5e: /* fdneg */
gen_helper_fdneg(cpu_env, cpu_dest, cpu_src);
break;
+ case 0x1e: /* fgetexp */
+ gen_helper_fgetexp(cpu_env, cpu_dest, cpu_src);
+ break;
+ case 0x1f: /* fgetman */
+ gen_helper_fgetman(cpu_env, cpu_dest, cpu_src);
+ break;
case 0x20: /* fdiv */
gen_helper_fdiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
break;
@@ -5108,6 +5114,9 @@ DISAS_INSN(fpu)
case 0x25: /* frem */
gen_helper_frem(cpu_env, cpu_dest, cpu_src, cpu_dest);
break;
+ case 0x26: /* fscale */
+ gen_helper_fscale(cpu_env, cpu_dest, cpu_src, cpu_dest);
+ break;
case 0x27: /* fsglmul */
gen_helper_fsglmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
break;
--
2.14.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH v3 1/4] softfloat: export some functions
2018-02-23 14:59 ` [Qemu-devel] [PATCH v3 1/4] softfloat: export some functions Laurent Vivier
@ 2018-02-24 1:26 ` Richard Henderson
0 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2018-02-24 1:26 UTC (permalink / raw)
To: Laurent Vivier, qemu-devel
Cc: Peter Maydell, Thomas Huth, Alex Bennée, Aurelien Jarno,
Richard Henderson
On 02/23/2018 06:59 AM, Laurent Vivier wrote:
> Move fpu/softfloat-macros.h to include/fpu/
>
> Export floatx80 functions to be used by target floatx80
> specific implementations.
>
> Exports:
> propagateFloatx80NaN(), extractFloatx80Frac(),
> extractFloatx80Exp(), extractFloatx80Sign(),
> normalizeFloatx80Subnormal(), packFloatx80(),
> roundAndPackFloatx80(), normalizeRoundAndPackFloatx80()
>
> Also exports packFloat32() that will be used to implement
> m68k fsinh, fcos, fsin, ftan operations.
>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
> CC: Aurelien Jarno <aurelien@aurel32.net>
> CC: Alex Bennée <alex.bennee@linaro.org>
> CC: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH v3 2/4] target/m68k: add fmod/frem
2018-02-23 14:59 ` [Qemu-devel] [PATCH v3 2/4] target/m68k: add fmod/frem Laurent Vivier
@ 2018-02-24 1:31 ` Richard Henderson
0 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2018-02-24 1:31 UTC (permalink / raw)
To: Laurent Vivier, qemu-devel; +Cc: Thomas Huth, Richard Henderson
On 02/23/2018 06:59 AM, Laurent Vivier wrote:
> Using a local m68k floatx80_mod()
> [copied from previous:
> Written by Andreas Grabher for Previous, NeXT Computer Emulator.]
>
> The quotient byte of the FPSR is updated with
> the result of the operation.
>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
> target/m68k/Makefile.objs | 3 +-
> target/m68k/cpu.h | 1 +
> target/m68k/fpu_helper.c | 35 +++++++++++++++-
> target/m68k/helper.h | 2 +
> target/m68k/softfloat.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++
> target/m68k/softfloat.h | 26 ++++++++++++
> target/m68k/translate.c | 6 +++
> 7 files changed, 176 insertions(+), 2 deletions(-)
> create mode 100644 target/m68k/softfloat.c
> create mode 100644 target/m68k/softfloat.h
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH v3 3/4] softfloat: use floatx80_infinity in softfloat
2018-02-23 14:59 ` [Qemu-devel] [PATCH v3 3/4] softfloat: use floatx80_infinity in softfloat Laurent Vivier
@ 2018-02-24 2:26 ` Richard Henderson
2018-02-24 17:21 ` Laurent Vivier
0 siblings, 1 reply; 12+ messages in thread
From: Richard Henderson @ 2018-02-24 2:26 UTC (permalink / raw)
To: Laurent Vivier, qemu-devel; +Cc: Thomas Huth, Aurelien Jarno, Richard Henderson
On 02/23/2018 06:59 AM, Laurent Vivier wrote:
> @@ -4550,8 +4556,8 @@ int64_t floatx80_to_int64(floatx80 a, float_status *status)
> if ( shiftCount ) {
> float_raise(float_flag_invalid, status);
> if ( ! aSign
> - || ( ( aExp == 0x7FFF )
> - && ( aSig != LIT64( 0x8000000000000000 ) ) )
> + || ((aExp == floatx80_infinity_high)
> + && (aSig != floatx80_infinity_low))
> ) {
As long as you're cleaning this up, m68k ignores the explicit integer bit when
considering an infinity. However, Intel doesn't ignore the bit -- it appears
to treat 7fff.0* as a NaN.
r~
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH v3 4/4] target/m68k: add fscale, fgetman and fgetexp
2018-02-23 14:59 ` [Qemu-devel] [PATCH v3 4/4] target/m68k: add fscale, fgetman and fgetexp Laurent Vivier
@ 2018-02-24 2:33 ` Richard Henderson
0 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2018-02-24 2:33 UTC (permalink / raw)
To: Laurent Vivier, qemu-devel; +Cc: Thomas Huth, Richard Henderson
On 02/23/2018 06:59 AM, Laurent Vivier wrote:
> Using local m68k floatx80_getman(), floatx80_getexp(), floatx80_scale()
> [copied from previous:
> Written by Andreas Grabher for Previous, NeXT Computer Emulator.]
>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
> target/m68k/fpu_helper.c | 15 +++++
> target/m68k/helper.h | 3 +
> target/m68k/softfloat.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++
> target/m68k/softfloat.h | 3 +
> target/m68k/translate.c | 9 +++
> 5 files changed, 174 insertions(+)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH v3 3/4] softfloat: use floatx80_infinity in softfloat
2018-02-24 2:26 ` Richard Henderson
@ 2018-02-24 17:21 ` Laurent Vivier
2018-02-24 17:26 ` Richard Henderson
0 siblings, 1 reply; 12+ messages in thread
From: Laurent Vivier @ 2018-02-24 17:21 UTC (permalink / raw)
To: Richard Henderson, qemu-devel
Cc: Thomas Huth, Aurelien Jarno, Richard Henderson
Le 24/02/2018 à 03:26, Richard Henderson a écrit :
> On 02/23/2018 06:59 AM, Laurent Vivier wrote:
>> @@ -4550,8 +4556,8 @@ int64_t floatx80_to_int64(floatx80 a, float_status *status)
>> if ( shiftCount ) {
>> float_raise(float_flag_invalid, status);
>> if ( ! aSign
>> - || ( ( aExp == 0x7FFF )
>> - && ( aSig != LIT64( 0x8000000000000000 ) ) )
>> + || ((aExp == floatx80_infinity_high)
>> + && (aSig != floatx80_infinity_low))
>> ) {
>
> As long as you're cleaning this up, m68k ignores the explicit integer bit when
> considering an infinity. However, Intel doesn't ignore the bit -- it appears
> to treat 7fff.0* as a NaN.
According to the comment above the function:
"... If `a' is a NaN, the largest positive integer is returned.
Otherwise, if the conversion overflows, the largest integer with the
same sign as `a' is returned."
I think the change should be in fact:
@@ -4549,10 +4555,7 @@ int64_t floatx80_to_int64(floatx80 a,
float_status *status)
if ( shiftCount <= 0 ) {
if ( shiftCount ) {
float_raise(float_flag_invalid, status);
- if ( ! aSign
- || ( ( aExp == 0x7FFF )
- && ( aSig != LIT64( 0x8000000000000000 ) ) )
- ) {
+ if (!aSign || floatx80_is_any_nan(a)) {
return LIT64( 0x7FFFFFFFFFFFFFFF );
}
return (int64_t) LIT64( 0x8000000000000000 );
Do you agree?
Thanks,
Laurent
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH v3 3/4] softfloat: use floatx80_infinity in softfloat
2018-02-24 17:21 ` Laurent Vivier
@ 2018-02-24 17:26 ` Richard Henderson
2018-02-24 17:42 ` Laurent Vivier
0 siblings, 1 reply; 12+ messages in thread
From: Richard Henderson @ 2018-02-24 17:26 UTC (permalink / raw)
To: Laurent Vivier, Richard Henderson, qemu-devel; +Cc: Thomas Huth, Aurelien Jarno
On 02/24/2018 09:21 AM, Laurent Vivier wrote:
> I think the change should be in fact:
>
> @@ -4549,10 +4555,7 @@ int64_t floatx80_to_int64(floatx80 a,
> float_status *status)
> if ( shiftCount <= 0 ) {
> if ( shiftCount ) {
> float_raise(float_flag_invalid, status);
> - if ( ! aSign
> - || ( ( aExp == 0x7FFF )
> - && ( aSig != LIT64( 0x8000000000000000 ) ) )
> - ) {
> + if (!aSign || floatx80_is_any_nan(a)) {
> return LIT64( 0x7FFFFFFFFFFFFFFF );
> }
> return (int64_t) LIT64( 0x8000000000000000 );
>
> Do you agree?
Yep, looks good.
r~
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH v3 3/4] softfloat: use floatx80_infinity in softfloat
2018-02-24 17:26 ` Richard Henderson
@ 2018-02-24 17:42 ` Laurent Vivier
0 siblings, 0 replies; 12+ messages in thread
From: Laurent Vivier @ 2018-02-24 17:42 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: Thomas Huth, Aurelien Jarno
Le 24/02/2018 à 18:26, Richard Henderson a écrit :
> On 02/24/2018 09:21 AM, Laurent Vivier wrote:
>> I think the change should be in fact:
>>
>> @@ -4549,10 +4555,7 @@ int64_t floatx80_to_int64(floatx80 a,
>> float_status *status)
>> if ( shiftCount <= 0 ) {
>> if ( shiftCount ) {
>> float_raise(float_flag_invalid, status);
>> - if ( ! aSign
>> - || ( ( aExp == 0x7FFF )
>> - && ( aSig != LIT64( 0x8000000000000000 ) ) )
>> - ) {
>> + if (!aSign || floatx80_is_any_nan(a)) {
>> return LIT64( 0x7FFFFFFFFFFFFFFF );
>> }
>> return (int64_t) LIT64( 0x8000000000000000 );
>>
>> Do you agree?
>
> Yep, looks good.
Thank you.
And according to your previous comment, floatx80_is_infinity() should
become:
static inline int floatx80_is_infinity(floatx80 a)
{
#if defined(TARGET_M68K)
return (a.high & 0x7fff) == floatx80_infinity.high && !(a.low << 1);
#else
return (a.high & 0x7fff) == floatx80_infinity.high &&
a.low == floatx80_infinity.low;
#endif
}
Laurent
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2018-02-24 17:42 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-02-23 14:59 [Qemu-devel] [PATCH v3 0/4] target/m68k: implement 680x0 FPU (part 3) Laurent Vivier
2018-02-23 14:59 ` [Qemu-devel] [PATCH v3 1/4] softfloat: export some functions Laurent Vivier
2018-02-24 1:26 ` Richard Henderson
2018-02-23 14:59 ` [Qemu-devel] [PATCH v3 2/4] target/m68k: add fmod/frem Laurent Vivier
2018-02-24 1:31 ` Richard Henderson
2018-02-23 14:59 ` [Qemu-devel] [PATCH v3 3/4] softfloat: use floatx80_infinity in softfloat Laurent Vivier
2018-02-24 2:26 ` Richard Henderson
2018-02-24 17:21 ` Laurent Vivier
2018-02-24 17:26 ` Richard Henderson
2018-02-24 17:42 ` Laurent Vivier
2018-02-23 14:59 ` [Qemu-devel] [PATCH v3 4/4] target/m68k: add fscale, fgetman and fgetexp Laurent Vivier
2018-02-24 2:33 ` Richard Henderson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).