qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 0/4] target/m68k: implement 680x0 FPU (part 3)
@ 2018-02-24 20:17 Laurent Vivier
  2018-02-24 20:17 ` [Qemu-devel] [PATCH v4 1/4] softfloat: export some functions Laurent Vivier
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Laurent Vivier @ 2018-02-24 20:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: Thomas Huth, Richard Henderson, 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.

v4: fix floatx80_to_int64() to check for NaN, not for infinity
    fix floatx80_is_infinity() to ignore mantissa's MSB

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                         | 130 +++++------------
 {fpu => include/fpu}/softfloat-macros.h |  10 +-
 include/fpu/softfloat.h                 | 133 ++++++++++++++++-
 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, 536 insertions(+), 106 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] 7+ messages in thread

* [Qemu-devel] [PATCH v4 1/4] softfloat: export some functions
  2018-02-24 20:17 [Qemu-devel] [PATCH v4 0/4] target/m68k: implement 680x0 FPU (part 3) Laurent Vivier
@ 2018-02-24 20:17 ` Laurent Vivier
  2018-02-27 14:26   ` Laurent Vivier
  2018-02-24 20:18 ` [Qemu-devel] [PATCH v4 2/4] target/m68k: add fmod/frem Laurent Vivier
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Laurent Vivier @ 2018-02-24 20:17 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, Richard Henderson, 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>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
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] 7+ messages in thread

* [Qemu-devel] [PATCH v4 2/4] target/m68k: add fmod/frem
  2018-02-24 20:17 [Qemu-devel] [PATCH v4 0/4] target/m68k: implement 680x0 FPU (part 3) Laurent Vivier
  2018-02-24 20:17 ` [Qemu-devel] [PATCH v4 1/4] softfloat: export some functions Laurent Vivier
@ 2018-02-24 20:18 ` Laurent Vivier
  2018-02-24 20:18 ` [Qemu-devel] [PATCH v4 3/4] softfloat: use floatx80_infinity in softfloat Laurent Vivier
  2018-02-24 20:18 ` [Qemu-devel] [PATCH v4 4/4] target/m68k: add fscale, fgetman and fgetexp Laurent Vivier
  3 siblings, 0 replies; 7+ messages in thread
From: Laurent Vivier @ 2018-02-24 20:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: Thomas Huth, Richard Henderson, 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>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 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] 7+ messages in thread

* [Qemu-devel] [PATCH v4 3/4] softfloat: use floatx80_infinity in softfloat
  2018-02-24 20:17 [Qemu-devel] [PATCH v4 0/4] target/m68k: implement 680x0 FPU (part 3) Laurent Vivier
  2018-02-24 20:17 ` [Qemu-devel] [PATCH v4 1/4] softfloat: export some functions Laurent Vivier
  2018-02-24 20:18 ` [Qemu-devel] [PATCH v4 2/4] target/m68k: add fmod/frem Laurent Vivier
@ 2018-02-24 20:18 ` Laurent Vivier
  2018-02-24 23:24   ` Richard Henderson
  2018-02-24 20:18 ` [Qemu-devel] [PATCH v4 4/4] target/m68k: add fscale, fgetman and fgetexp Laurent Vivier
  3 siblings, 1 reply; 7+ messages in thread
From: Laurent Vivier @ 2018-02-24 20:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: Thomas Huth, Richard Henderson, 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>
---
CC: Aurelien Jarno <aurelien@aurel32.net>
    v4: fix floatx80_to_int64() to check for NaN, not for infinity
        fix floatx80_is_infinity() to ignore mantissa's MSB

 fpu/softfloat-specialize.h | 14 ++++++++++++++
 fpu/softfloat.c            | 39 +++++++++++++++++++++++++--------------
 include/fpu/softfloat.h    | 13 +++++++++++--
 3 files changed, 50 insertions(+), 16 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..e124df9f7e 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 );
@@ -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 );
@@ -4858,7 +4861,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 +4938,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 +5044,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 +5056,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 +5111,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 +5128,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 +5952,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..873a520e3e 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,12 @@ static inline floatx80 floatx80_chs(floatx80 a)
 
 static inline int floatx80_is_infinity(floatx80 a)
 {
-    return (a.high & 0x7fff) == 0x7fff && a.low == 0x8000000000000000LL;
+#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
 }
 
 static inline int floatx80_is_neg(floatx80 a)
@@ -646,7 +656,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] 7+ messages in thread

* [Qemu-devel] [PATCH v4 4/4] target/m68k: add fscale, fgetman and fgetexp
  2018-02-24 20:17 [Qemu-devel] [PATCH v4 0/4] target/m68k: implement 680x0 FPU (part 3) Laurent Vivier
                   ` (2 preceding siblings ...)
  2018-02-24 20:18 ` [Qemu-devel] [PATCH v4 3/4] softfloat: use floatx80_infinity in softfloat Laurent Vivier
@ 2018-02-24 20:18 ` Laurent Vivier
  3 siblings, 0 replies; 7+ messages in thread
From: Laurent Vivier @ 2018-02-24 20:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: Thomas Huth, Richard Henderson, 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>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 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] 7+ messages in thread

* Re: [Qemu-devel] [PATCH v4 3/4] softfloat: use floatx80_infinity in softfloat
  2018-02-24 20:18 ` [Qemu-devel] [PATCH v4 3/4] softfloat: use floatx80_infinity in softfloat Laurent Vivier
@ 2018-02-24 23:24   ` Richard Henderson
  0 siblings, 0 replies; 7+ messages in thread
From: Richard Henderson @ 2018-02-24 23:24 UTC (permalink / raw)
  To: Laurent Vivier, qemu-devel; +Cc: Thomas Huth, Aurelien Jarno

On 02/24/2018 12:18 PM, Laurent Vivier wrote:
> 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>
> ---
> CC: Aurelien Jarno <aurelien@aurel32.net>
>     v4: fix floatx80_to_int64() to check for NaN, not for infinity
>         fix floatx80_is_infinity() to ignore mantissa's MSB
> 
>  fpu/softfloat-specialize.h | 14 ++++++++++++++
>  fpu/softfloat.c            | 39 +++++++++++++++++++++++++--------------
>  include/fpu/softfloat.h    | 13 +++++++++++--
>  3 files changed, 50 insertions(+), 16 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH v4 1/4] softfloat: export some functions
  2018-02-24 20:17 ` [Qemu-devel] [PATCH v4 1/4] softfloat: export some functions Laurent Vivier
@ 2018-02-27 14:26   ` Laurent Vivier
  0 siblings, 0 replies; 7+ messages in thread
From: Laurent Vivier @ 2018-02-27 14:26 UTC (permalink / raw)
  To: Aurelien Jarno, Peter Maydell
  Cc: qemu-devel, Thomas Huth, Richard Henderson, Alex Bennée

Aurélien, Peter,

as named maintainers in the MAINTAINERS file for FPU emulation, if you
don't argue against these changes (they are trivial), I would like to
add these softfloat changes in my next m68k pull request.

By this means, any new floatx80 function I will add for m68k emulation
will be in target/m68k directory and will not modify common FPU emulation.

If anyone will need one of the new functions, he will be free to move it
to the common part.

Thanks,
Laurent

Le 24/02/2018 à 21:17, Laurent Vivier a écrit :
> 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>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> 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.
>  *----------------------------------------------------------------------------*/
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-02-27 14:26 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-02-24 20:17 [Qemu-devel] [PATCH v4 0/4] target/m68k: implement 680x0 FPU (part 3) Laurent Vivier
2018-02-24 20:17 ` [Qemu-devel] [PATCH v4 1/4] softfloat: export some functions Laurent Vivier
2018-02-27 14:26   ` Laurent Vivier
2018-02-24 20:18 ` [Qemu-devel] [PATCH v4 2/4] target/m68k: add fmod/frem Laurent Vivier
2018-02-24 20:18 ` [Qemu-devel] [PATCH v4 3/4] softfloat: use floatx80_infinity in softfloat Laurent Vivier
2018-02-24 23:24   ` Richard Henderson
2018-02-24 20:18 ` [Qemu-devel] [PATCH v4 4/4] target/m68k: add fscale, fgetman and fgetexp Laurent Vivier

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).