All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 00/15] s390x/tcg: Implement floating-point extension facility
@ 2019-02-13 14:33 David Hildenbrand
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 01/15] s390x/tcg: Fix TEST DATA CLASS instructions David Hildenbrand
                   ` (14 more replies)
  0 siblings, 15 replies; 21+ messages in thread
From: David Hildenbrand @ 2019-02-13 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck, Richard Henderson,
	David Hildenbrand

This series is based on the patches currently on the list:
- softfloat: Implement float128_to_uint32
- softfloat: add float128_is_{normal,denormal}
- s390x: add zPCI feature to "qemu" CPU model

For the KVM folks, only the last patch is of interest.

The floating-point extension facility seems to be used often without
checking by user space. Vector instruction support seems to somewhat also
rely on it being available. Some parts are already implemented, others
not or are broken.

Fix some stuff in fpu code, add some FIXMEs to indicate what is definetly
missing and implement all BFP stuff needed for the floating-point extension
facility. Finally, enable it for TCG, adding it to the CPU model for the
4.0 compat machine.

This series also contains some refactorings needed for floating-point
vector instruction support.

v1 -> v2:
- "s390x/tcg: Fix TEST DATA CLASS instructions"
-- Simplify + use marko
- "s390x/tcg: Prepare for IEEE-inexact-exception control (XxC)"
-- Fix some whitespace/newline issues
- "s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes"
-- If FPE is not installed, also bail out on 3rd BFP bit
- "s390x/tcg: Implement XxC and checks for most FP instructions"
-- Use helper functions to simplify checks+mangling+unmangling
-- Take care of FPE facility state
-- Fix that XxC is actually bit 1, not bit 0
- "s390x/tcg: Prepare for IEEE-inexact-exception control (XxC)"
-- Also use new helper functions

David Hildenbrand (15):
  s390x/tcg: Fix TEST DATA CLASS instructions
  s390x/tcg: Fix rounding from float128 to uint64_t/uin32_t
  s390x/tcg: Factor out conversion of softfloat exceptions
  s390x/tcg: Fix parts of IEEE exception handling
  s390x/tcg: Hide IEEE underflows in some scenarios
  s390x/tcg: Refactor SET FPC AND SIGNAL handling
  s390x/tcg: Fix simulated-IEEE exceptions
  s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes
  s390x/tcg: Check for exceptions in SET BFP ROUNDING MODE
  s390x/tcg: Refactor saving/restoring the bfp rounding mode
  s390x/tcg: Prepare for IEEE-inexact-exception control (XxC)
  s390x/tcg: Implement XxC and checks for most FP instructions
  s390x/tcg: Implement rounding mode and XxC for LOAD ROUNDED
  s390x/tcg: Handle all rounding modes overwritten by BFP instructions
  s390x: Add floating-point extension facility to "qemu" cpu model

 target/s390x/fpu_helper.c   | 550 ++++++++++++++++++++++--------------
 target/s390x/gen-features.c |   5 +
 target/s390x/helper.h       |   9 +-
 target/s390x/insn-data.def  |  12 +-
 target/s390x/internal.h     |   9 +
 target/s390x/translate.c    | 315 ++++++++++++++-------
 6 files changed, 581 insertions(+), 319 deletions(-)

-- 
2.17.2

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

* [Qemu-devel] [PATCH v2 01/15] s390x/tcg: Fix TEST DATA CLASS instructions
  2019-02-13 14:33 [Qemu-devel] [PATCH v2 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
@ 2019-02-13 14:33 ` David Hildenbrand
  2019-02-13 19:17   ` Richard Henderson
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 02/15] s390x/tcg: Fix rounding from float128 to uint64_t/uin32_t David Hildenbrand
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 21+ messages in thread
From: David Hildenbrand @ 2019-02-13 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck, Richard Henderson,
	David Hildenbrand

Let's detect normal and denormal ("subnormal") numbers reliably. Also
test for quiet NaN's. As only one class is possible, test common cases
first.

While at it, use a better check to test for the mask bits in the data
class mask. The data class mask has 12 bits, whereby bit 0 is the
leftmost bit and bit 11 the rightmost bit. In the PoP an easy to read
table with the numbers is provided for the VECTOR FP TEST DATA CLASS
IMMEDIATE instruction, the table for TEST DATA CLASS is more confusing
as it is based on 64 bit values.

Factor the checks out into separate functions, as they will also be
needed for floating point vector instructions. We can use a makro to
generate the functions.

Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/fpu_helper.c | 85 ++++++++++++++++-----------------------
 1 file changed, 35 insertions(+), 50 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index e921172bc4..0e9247bf7e 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -645,67 +645,52 @@ uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
     return ret;
 }
 
+/* The rightmost bit has the number 11. */
+static inline uint16_t dcmask(int bit, bool neg)
+{
+    return 1 << (11 - bit - neg);
+}
+
+#define DEF_FLOAT_DCMASK(_TYPE) \
+static uint16_t _TYPE##_dcmask(CPUS390XState *env, _TYPE f1)       \
+{                                                                  \
+    const bool neg = _TYPE##_is_neg(f1);                           \
+                                                                   \
+    /* Sorted by most common cases - only one class is possible */ \
+    if (_TYPE##_is_normal(f1)) {                                   \
+        return dcmask(2, neg);                                     \
+    } else if (_TYPE##_is_zero(f1)) {                              \
+        return dcmask(0, neg);                                     \
+    } else if (_TYPE##_is_denormal(f1)) {                          \
+        return dcmask(4, neg);                                     \
+    } else if (_TYPE##_is_infinity(f1)) {                          \
+        return dcmask(6, neg);                                     \
+    } else if (_TYPE##_is_quiet_nan(f1, &env->fpu_status)) {       \
+        return dcmask(8, neg);                                     \
+    }                                                              \
+    /* signaling nan, as last remaining case */                    \
+    return dcmask(10, neg);                                        \
+}
+DEF_FLOAT_DCMASK(float32)
+DEF_FLOAT_DCMASK(float64)
+DEF_FLOAT_DCMASK(float128)
+
 /* test data class 32-bit */
 uint32_t HELPER(tceb)(CPUS390XState *env, uint64_t f1, uint64_t m2)
 {
-    float32 v1 = f1;
-    int neg = float32_is_neg(v1);
-    uint32_t cc = 0;
-
-    if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
-        (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
-        (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
-        (float32_is_signaling_nan(v1, &env->fpu_status) &&
-         (m2 & (1 << (1-neg))))) {
-        cc = 1;
-    } else if (m2 & (1 << (9-neg))) {
-        /* assume normalized number */
-        cc = 1;
-    }
-    /* FIXME: denormalized? */
-    return cc;
+    return (m2 & float32_dcmask(env, f1)) != 0;
 }
 
 /* test data class 64-bit */
 uint32_t HELPER(tcdb)(CPUS390XState *env, uint64_t v1, uint64_t m2)
 {
-    int neg = float64_is_neg(v1);
-    uint32_t cc = 0;
-
-    if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
-        (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
-        (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
-        (float64_is_signaling_nan(v1, &env->fpu_status) &&
-         (m2 & (1 << (1-neg))))) {
-        cc = 1;
-    } else if (m2 & (1 << (9-neg))) {
-        /* assume normalized number */
-        cc = 1;
-    }
-    /* FIXME: denormalized? */
-    return cc;
+    return (m2 & float64_dcmask(env, v1)) != 0;
 }
 
 /* test data class 128-bit */
-uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah,
-                      uint64_t al, uint64_t m2)
-{
-    float128 v1 = make_float128(ah, al);
-    int neg = float128_is_neg(v1);
-    uint32_t cc = 0;
-
-    if ((float128_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
-        (float128_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
-        (float128_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
-        (float128_is_signaling_nan(v1, &env->fpu_status) &&
-         (m2 & (1 << (1-neg))))) {
-        cc = 1;
-    } else if (m2 & (1 << (9-neg))) {
-        /* assume normalized number */
-        cc = 1;
-    }
-    /* FIXME: denormalized? */
-    return cc;
+uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint64_t m2)
+{
+    return (m2 & float128_dcmask(env, make_float128(ah, al))) != 0;
 }
 
 /* square root 32-bit */
-- 
2.17.2

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

* [Qemu-devel] [PATCH v2 02/15] s390x/tcg: Fix rounding from float128 to uint64_t/uin32_t
  2019-02-13 14:33 [Qemu-devel] [PATCH v2 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 01/15] s390x/tcg: Fix TEST DATA CLASS instructions David Hildenbrand
@ 2019-02-13 14:33 ` David Hildenbrand
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 03/15] s390x/tcg: Factor out conversion of softfloat exceptions David Hildenbrand
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 21+ messages in thread
From: David Hildenbrand @ 2019-02-13 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck, Richard Henderson,
	David Hildenbrand

Let's use the proper conversion functions now that we have them.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/fpu_helper.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 0e9247bf7e..21236caed8 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -509,9 +509,7 @@ uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
 {
     int hold = swap_round_mode(env, m3);
-    float128 v2 = make_float128(h, l);
-    /* ??? Not 100% correct.  */
-    uint64_t ret = float128_to_int64(v2, &env->fpu_status);
+    uint64_t ret = float128_to_uint64(make_float128(h, l), &env->fpu_status);
     set_float_rounding_mode(hold, &env->fpu_status);
     handle_exceptions(env, GETPC());
     return ret;
@@ -541,9 +539,7 @@ uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
 {
     int hold = swap_round_mode(env, m3);
-    float128 v2 = make_float128(h, l);
-    /* Not 100% correct.  */
-    uint32_t ret = float128_to_int64(v2, &env->fpu_status);
+    uint32_t ret = float128_to_uint32(make_float128(h, l), &env->fpu_status);
     set_float_rounding_mode(hold, &env->fpu_status);
     handle_exceptions(env, GETPC());
     return ret;
-- 
2.17.2

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

* [Qemu-devel] [PATCH v2 03/15] s390x/tcg: Factor out conversion of softfloat exceptions
  2019-02-13 14:33 [Qemu-devel] [PATCH v2 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 01/15] s390x/tcg: Fix TEST DATA CLASS instructions David Hildenbrand
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 02/15] s390x/tcg: Fix rounding from float128 to uint64_t/uin32_t David Hildenbrand
@ 2019-02-13 14:33 ` David Hildenbrand
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 04/15] s390x/tcg: Fix parts of IEEE exception handling David Hildenbrand
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 21+ messages in thread
From: David Hildenbrand @ 2019-02-13 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck, Richard Henderson,
	David Hildenbrand

We want to reuse that function in vector instruction context. While at it,
cleanup the code, using defines for magic values and avoiding the
handcrafted bit conversion.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/fpu_helper.c | 25 +++++++++++++------------
 target/s390x/internal.h   |  7 +++++++
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 21236caed8..de02cf792d 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -36,10 +36,18 @@
 
 #define RET128(F) (env->retxl = F.low, F.high)
 
-#define convert_bit(mask, from, to) \
-    (to < from                      \
-     ? (mask / (from / to)) & to    \
-     : (mask & from) * (to / from))
+uint8_t s390_softfloat_exc_to_ieee(unsigned int exc)
+{
+    uint8_t s390_exc = 0;
+
+    s390_exc |= (exc & float_flag_invalid) ? S390_IEEE_MASK_INVALID : 0;
+    s390_exc |= (exc & float_flag_divbyzero) ? S390_IEEE_MASK_DIVBYZERO : 0;
+    s390_exc |= (exc & float_flag_overflow) ? S390_IEEE_MASK_OVERFLOW : 0;
+    s390_exc |= (exc & float_flag_underflow) ? S390_IEEE_MASK_UNDERFLOW : 0;
+    s390_exc |= (exc & float_flag_inexact) ? S390_IEEE_MASK_INEXACT : 0;
+
+    return s390_exc;
+}
 
 /* Should be called after any operation that may raise IEEE exceptions.  */
 static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
@@ -53,14 +61,7 @@ static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
         return;
     }
     env->fpu_status.float_exception_flags = 0;
-
-    /* Convert softfloat exception bits to s390 exception bits.  */
-    s390_exc = 0;
-    s390_exc |= convert_bit(qemu_exc, float_flag_invalid, 0x80);
-    s390_exc |= convert_bit(qemu_exc, float_flag_divbyzero, 0x40);
-    s390_exc |= convert_bit(qemu_exc, float_flag_overflow, 0x20);
-    s390_exc |= convert_bit(qemu_exc, float_flag_underflow, 0x10);
-    s390_exc |= convert_bit(qemu_exc, float_flag_inexact, 0x08);
+    s390_exc = s390_softfloat_exc_to_ieee(qemu_exc);
 
     /* Install the exceptions that we raised.  */
     env->fpc |= s390_exc << 16;
diff --git a/target/s390x/internal.h b/target/s390x/internal.h
index f2a771e2b4..e1c0b1bd3b 100644
--- a/target/s390x/internal.h
+++ b/target/s390x/internal.h
@@ -308,6 +308,13 @@ void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
 uint32_t set_cc_nz_f32(float32 v);
 uint32_t set_cc_nz_f64(float64 v);
 uint32_t set_cc_nz_f128(float128 v);
+#define S390_IEEE_MASK_INVALID   0x80
+#define S390_IEEE_MASK_DIVBYZERO 0x40
+#define S390_IEEE_MASK_OVERFLOW  0x20
+#define S390_IEEE_MASK_UNDERFLOW 0x10
+#define S390_IEEE_MASK_INEXACT   0x08
+#define S390_IEEE_MASK_QUANTUM   0x04
+uint8_t s390_softfloat_exc_to_ieee(unsigned int exc);
 
 
 /* gdbstub.c */
-- 
2.17.2

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

* [Qemu-devel] [PATCH v2 04/15] s390x/tcg: Fix parts of IEEE exception handling
  2019-02-13 14:33 [Qemu-devel] [PATCH v2 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
                   ` (2 preceding siblings ...)
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 03/15] s390x/tcg: Factor out conversion of softfloat exceptions David Hildenbrand
@ 2019-02-13 14:33 ` David Hildenbrand
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 05/15] s390x/tcg: Hide IEEE underflows in some scenarios David Hildenbrand
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 21+ messages in thread
From: David Hildenbrand @ 2019-02-13 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck, Richard Henderson,
	David Hildenbrand

Many things are wrong and some parts cannot be fixed yet. Fix what we
can fix easily and add two FIXMEs:

The fpc flags are not updated in case an exception is actually injected.
Inexact exceptions have to be handled separately, as they are the only
exceptions that can coexist with underflows and overflows.

I reread the horribly complicated chapters in the PoP at least 5 times
and hope I got it right.

For references:
- z14 PoP, 9-18, "IEEE Exceptions"
- z14 PoP, 19-9, Figure 19-8

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/fpu_helper.c | 38 ++++++++++++++++++++++++++++++++------
 1 file changed, 32 insertions(+), 6 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index de02cf792d..dcad9c367a 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -63,13 +63,39 @@ static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
     env->fpu_status.float_exception_flags = 0;
     s390_exc = s390_softfloat_exc_to_ieee(qemu_exc);
 
-    /* Install the exceptions that we raised.  */
-    env->fpc |= s390_exc << 16;
+    /*
+     * FIXME:
+     * 1. Right now, all inexact conditions are inidicated as
+     *    "truncated" (0) and never as "incremented" (1) in the DXC.
+     * 2. Only traps due to invalid/divbyzero are suppressing. Other traps
+     *    are completing, meaning the target register has to be written!
+     *    This, however will mean that we have to write the register before
+     *    triggering the trap - impossible right now.
+     */
+
+    /*
+     * invalid/divbyzero cannot coexist with other conditions.
+     * overflow/underflow however can coexist with inexact, we have to
+     * handle it separatly.
+     */
+    if (s390_exc & ~S390_IEEE_MASK_INEXACT) {
+        if (s390_exc & ~S390_IEEE_MASK_INEXACT & env->fpc >> 24) {
+            /* trap condition - inexact reported along */
+            tcg_s390_data_exception(env, s390_exc, retaddr);
+        }
+        /* nontrap condition - inexact handled differently */
+        env->fpc |= (s390_exc & ~S390_IEEE_MASK_INEXACT) << 16;
+    }
 
-    /* Send signals for enabled exceptions.  */
-    s390_exc &= env->fpc >> 24;
-    if (s390_exc) {
-        tcg_s390_data_exception(env, s390_exc, retaddr);
+    /* inexact handling */
+    if (s390_exc & S390_IEEE_MASK_INEXACT) {
+        /* trap condition - overflow/underflow _not_ reported along */
+        if (s390_exc & S390_IEEE_MASK_INEXACT & env->fpc >> 24) {
+            tcg_s390_data_exception(env, s390_exc & S390_IEEE_MASK_INEXACT,
+                                    retaddr);
+        }
+        /* nontrap condition */
+        env->fpc |= (s390_exc & S390_IEEE_MASK_INEXACT) << 16;
     }
 }
 
-- 
2.17.2

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

* [Qemu-devel] [PATCH v2 05/15] s390x/tcg: Hide IEEE underflows in some scenarios
  2019-02-13 14:33 [Qemu-devel] [PATCH v2 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
                   ` (3 preceding siblings ...)
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 04/15] s390x/tcg: Fix parts of IEEE exception handling David Hildenbrand
@ 2019-02-13 14:33 ` David Hildenbrand
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 06/15] s390x/tcg: Refactor SET FPC AND SIGNAL handling David Hildenbrand
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 21+ messages in thread
From: David Hildenbrand @ 2019-02-13 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck, Richard Henderson,
	David Hildenbrand

IEEE underflows are not reported when the mask bit is off and we don't
also have an inexact exception.

z14 PoP, 9-20, "IEEE Underflow":
    An IEEE-underflow exception is recognized for an
    IEEE target when the tininess condition exists and
    either: (1) the IEEE-underflow mask bit in the FPC
    register is zero and the result value is inexact, or (2)
    the IEEE-underflow mask bit in the FPC register is
    one.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/fpu_helper.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index dcad9c367a..64efab72a4 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -63,6 +63,19 @@ static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
     env->fpu_status.float_exception_flags = 0;
     s390_exc = s390_softfloat_exc_to_ieee(qemu_exc);
 
+    /*
+     * IEEE-Underflow exception recognition exists if a tininess condition
+     * (underflow) exists and
+     * - The mask bit in the FPC is zero and the result is inexact
+     * - The mask bit in the FPC is one
+     * So tininess conditions that are not inexact don't trigger any
+     * underflow action in case the mask bit is not one.
+     */
+    if (!(s390_exc & S390_IEEE_MASK_INEXACT) &&
+        !((env->fpc >> 24) & S390_IEEE_MASK_UNDERFLOW)) {
+        s390_exc &= ~S390_IEEE_MASK_UNDERFLOW;
+    }
+
     /*
      * FIXME:
      * 1. Right now, all inexact conditions are inidicated as
-- 
2.17.2

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

* [Qemu-devel] [PATCH v2 06/15] s390x/tcg: Refactor SET FPC AND SIGNAL handling
  2019-02-13 14:33 [Qemu-devel] [PATCH v2 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
                   ` (4 preceding siblings ...)
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 05/15] s390x/tcg: Hide IEEE underflows in some scenarios David Hildenbrand
@ 2019-02-13 14:33 ` David Hildenbrand
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 07/15] s390x/tcg: Fix simulated-IEEE exceptions David Hildenbrand
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 21+ messages in thread
From: David Hildenbrand @ 2019-02-13 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck, Richard Henderson,
	David Hildenbrand

We can directly work on the uint64_t value, no need for a temporary
uint32_t value.

Also cleanup and shorten the comments.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/fpu_helper.c | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 64efab72a4..ea5a37ac5e 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -771,21 +771,23 @@ void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
 }
 
 /* set fpc and signal */
-void HELPER(sfas)(CPUS390XState *env, uint64_t val)
+void HELPER(sfas)(CPUS390XState *env, uint64_t fpc)
 {
     uint32_t signalling = env->fpc;
-    uint32_t source = val;
     uint32_t s390_exc;
 
-    /* The contents of the source operand are placed in the FPC register;
-       then the flags in the FPC register are set to the logical OR of the
-       signalling flags and the source flags.  */
-    env->fpc = source | (signalling & 0x00ff0000);
-    set_float_rounding_mode(fpc_to_rnd[source & 3], &env->fpu_status);
+    /*
+     * FPC is set to the FPC operand with a bitwise OR of the signalling
+     * flags.
+     */
+    env->fpc = fpc | (signalling & 0x00ff0000);
+    set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
 
-    /* If any signalling flag is 1 and the corresponding source mask
-       is also 1, a simulated-iee-exception trap occurs.  */
-    s390_exc = (signalling >> 16) & (source >> 24);
+    /*
+     * If any signaling flag is enabled in the new FPC mask, a
+     * simulated-iee-exception exception occurs.
+     */
+    s390_exc = (signalling >> 16) & (fpc >> 24);
     if (s390_exc) {
         tcg_s390_data_exception(env, s390_exc | 3, GETPC());
     }
-- 
2.17.2

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

* [Qemu-devel] [PATCH v2 07/15] s390x/tcg: Fix simulated-IEEE exceptions
  2019-02-13 14:33 [Qemu-devel] [PATCH v2 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
                   ` (5 preceding siblings ...)
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 06/15] s390x/tcg: Refactor SET FPC AND SIGNAL handling David Hildenbrand
@ 2019-02-13 14:33 ` David Hildenbrand
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 08/15] s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes David Hildenbrand
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 21+ messages in thread
From: David Hildenbrand @ 2019-02-13 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck, Richard Henderson,
	David Hildenbrand

The trap is triggered based on priority of the enabled signaling flags.
Only overflow and underflow allow a concurrent inexact exception.

z14 PoP, 9-33, Figure 9-21

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/fpu_helper.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index ea5a37ac5e..7508c0748e 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -789,6 +789,19 @@ void HELPER(sfas)(CPUS390XState *env, uint64_t fpc)
      */
     s390_exc = (signalling >> 16) & (fpc >> 24);
     if (s390_exc) {
+        if (s390_exc & S390_IEEE_MASK_INVALID) {
+            s390_exc = S390_IEEE_MASK_INVALID;
+        } else if (s390_exc & S390_IEEE_MASK_DIVBYZERO) {
+            s390_exc = S390_IEEE_MASK_DIVBYZERO;
+        } else if (s390_exc & S390_IEEE_MASK_OVERFLOW) {
+            s390_exc &= (S390_IEEE_MASK_OVERFLOW | S390_IEEE_MASK_INEXACT);
+        } else if (s390_exc & S390_IEEE_MASK_UNDERFLOW) {
+            s390_exc &= (S390_IEEE_MASK_UNDERFLOW | S390_IEEE_MASK_INEXACT);
+        } else if (s390_exc & S390_IEEE_MASK_INEXACT) {
+            s390_exc = S390_IEEE_MASK_INEXACT;
+        } else if (s390_exc & S390_IEEE_MASK_QUANTUM) {
+            s390_exc = S390_IEEE_MASK_QUANTUM;
+        }
         tcg_s390_data_exception(env, s390_exc | 3, GETPC());
     }
 }
-- 
2.17.2

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

* [Qemu-devel] [PATCH v2 08/15] s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes
  2019-02-13 14:33 [Qemu-devel] [PATCH v2 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
                   ` (6 preceding siblings ...)
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 07/15] s390x/tcg: Fix simulated-IEEE exceptions David Hildenbrand
@ 2019-02-13 14:33 ` David Hildenbrand
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 09/15] s390x/tcg: Check for exceptions in SET BFP ROUNDING MODE David Hildenbrand
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 21+ messages in thread
From: David Hildenbrand @ 2019-02-13 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck, Richard Henderson,
	David Hildenbrand

We already forward the 3 bits correctly in the translation functions. We
also have to handle them properly and check for specification
exceptions.

Setting an invalid rounding mode (BFP only, all DFP rounding modes)
results in a specification exception. Setting unassigned bits in the
fpc, results in a specification exception.

This fixes LOAD FPC (AND SIGNAL), SET FPC (AND SIGNAL). Also for,
SET BFP ROUNDING MODE, 3-bit rounding mode is now explicitly checked.

Notes:
1. Use "float_round_to_zero" for now to handle "Round to prepare for
   shorter precision". Looking at the PoP "Summary of Rounding and Range
   Actions" for BFP. They differ when it comes to tiny values.
2. TCG_CALL_NO_WG is required for sfpc handler, as we now inject
   exceptions.

We won't be modeling abscence of the "floating-point extension facility"
for now, not necessary as most take the facility for granted without
checking.

z14 PoP, 9-23, "LOAD FPC"
    When the floating-point extension facility is
    installed, bits 29-31 of the second operand must
    specify a valid BFP rounding mode and bits 6-7,
    14-15, 24, and 28 must be zero; otherwise, a
    specification exception is recognized.

Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/fpu_helper.c | 26 ++++++++++++++++++++++----
 target/s390x/helper.h     |  2 +-
 2 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 7508c0748e..a779cfada6 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -753,21 +753,34 @@ uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
     return RET128(ret);
 }
 
-static const int fpc_to_rnd[4] = {
+static const int fpc_to_rnd[8] = {
     float_round_nearest_even,
     float_round_to_zero,
     float_round_up,
-    float_round_down
+    float_round_down,
+    -1,
+    -1,
+    -1,
+    /*
+     * FIXME: we actually want something like round_to_odd, but that does not
+     * support all data types yet.
+     */
+    float_round_to_zero,
 };
 
 /* set fpc */
 void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
 {
+    if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u ||
+        (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) {
+        s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC());
+    }
+
     /* Install everything in the main FPC.  */
     env->fpc = fpc;
 
     /* Install the rounding mode in the shadow fpu_status.  */
-    set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
+    set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status);
 }
 
 /* set fpc and signal */
@@ -776,12 +789,17 @@ void HELPER(sfas)(CPUS390XState *env, uint64_t fpc)
     uint32_t signalling = env->fpc;
     uint32_t s390_exc;
 
+    if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u ||
+        (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) {
+        s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC());
+    }
+
     /*
      * FPC is set to the FPC operand with a bitwise OR of the signalling
      * flags.
      */
     env->fpc = fpc | (signalling & 0x00ff0000);
-    set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
+    set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status);
 
     /*
      * If any signaling flag is enabled in the new FPC mask, a
diff --git a/target/s390x/helper.h b/target/s390x/helper.h
index 6260b50496..a99b067c9c 100644
--- a/target/s390x/helper.h
+++ b/target/s390x/helper.h
@@ -104,7 +104,7 @@ DEF_HELPER_4(trtr, i32, env, i32, i64, i64)
 DEF_HELPER_5(trXX, i32, env, i32, i32, i32, i32)
 DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
-DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64)
+DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_WG, void, env, i64)
 DEF_HELPER_FLAGS_2(sfas, TCG_CALL_NO_WG, void, env, i64)
 DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_NO_RWG_SE, i64, i64)
 DEF_HELPER_2(stfle, i32, env, i64)
-- 
2.17.2

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

* [Qemu-devel] [PATCH v2 09/15] s390x/tcg: Check for exceptions in SET BFP ROUNDING MODE
  2019-02-13 14:33 [Qemu-devel] [PATCH v2 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
                   ` (7 preceding siblings ...)
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 08/15] s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes David Hildenbrand
@ 2019-02-13 14:33 ` David Hildenbrand
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 10/15] s390x/tcg: Refactor saving/restoring the bfp rounding mode David Hildenbrand
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 21+ messages in thread
From: David Hildenbrand @ 2019-02-13 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck, Richard Henderson,
	David Hildenbrand

Let's split handling of BFP/DFP rounding mode configuration. Also,
let's not reuse the sfpc handler, use a separate handler so we can
properly check for specification exceptions for SRNMB.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/fpu_helper.c  | 11 ++++++++
 target/s390x/helper.h      |  1 +
 target/s390x/insn-data.def |  6 ++--
 target/s390x/translate.c   | 56 ++++++++++++++++----------------------
 4 files changed, 39 insertions(+), 35 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index a779cfada6..70fa053e8d 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -823,3 +823,14 @@ void HELPER(sfas)(CPUS390XState *env, uint64_t fpc)
         tcg_s390_data_exception(env, s390_exc | 3, GETPC());
     }
 }
+
+/* set bfp rounding mode */
+void HELPER(srnm)(CPUS390XState *env, uint64_t rnd)
+{
+    if (rnd > 0x7 || fpc_to_rnd[rnd & 0x7] == -1) {
+        s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC());
+    }
+
+    env->fpc = deposit32(env->fpc, 0, 3, rnd);
+    set_float_rounding_mode(fpc_to_rnd[rnd & 0x7], &env->fpu_status);
+}
diff --git a/target/s390x/helper.h b/target/s390x/helper.h
index a99b067c9c..d287d5dac0 100644
--- a/target/s390x/helper.h
+++ b/target/s390x/helper.h
@@ -106,6 +106,7 @@ DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
 DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_WG, void, env, i64)
 DEF_HELPER_FLAGS_2(sfas, TCG_CALL_NO_WG, void, env, i64)
+DEF_HELPER_FLAGS_2(srnm, TCG_CALL_NO_WG, void, env, i64)
 DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_NO_RWG_SE, i64, i64)
 DEF_HELPER_2(stfle, i32, env, i64)
 DEF_HELPER_FLAGS_2(lpq, TCG_CALL_NO_WG, i64, env, i64)
diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def
index 61582372ab..2c9ae503c5 100644
--- a/target/s390x/insn-data.def
+++ b/target/s390x/insn-data.def
@@ -759,10 +759,10 @@
 /* SET FPC AND SIGNAL */
     F(0xb385, SFASR,   RRE,   IEEEE_SIM, 0, r1_o, 0, 0, sfas, 0, IF_DFP)
 /* SET BFP ROUNDING MODE */
-    F(0xb299, SRNM,    S,     Z,   0, 0, 0, 0, srnm, 0, IF_BFP)
-    F(0xb2b8, SRNMB,   S,     FPE, 0, 0, 0, 0, srnm, 0, IF_BFP)
+    F(0xb299, SRNM,    S,     Z,   la2, 0, 0, 0, srnm, 0, IF_BFP)
+    F(0xb2b8, SRNMB,   S,     FPE, la2, 0, 0, 0, srnmb, 0, IF_BFP)
 /* SET DFP ROUNDING MODE */
-    F(0xb2b9, SRNMT,   S,     DFPR, 0, 0, 0, 0, srnm, 0, IF_DFP)
+    F(0xb2b9, SRNMT,   S,     DFPR, la2, 0, 0, 0, srnmt, 0, IF_DFP)
 /* SET PROGRAM MASK */
     C(0x0400, SPM,     RR_a,  Z,   r1, 0, 0, 0, spm, 0)
 
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 19072efec6..c2645891e8 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -3955,41 +3955,33 @@ static DisasJumpType op_sfas(DisasContext *s, DisasOps *o)
 
 static DisasJumpType op_srnm(DisasContext *s, DisasOps *o)
 {
-    int b2 = get_field(s->fields, b2);
-    int d2 = get_field(s->fields, d2);
-    TCGv_i64 t1 = tcg_temp_new_i64();
-    TCGv_i64 t2 = tcg_temp_new_i64();
-    int mask, pos, len;
+    /* Bits other than 62 and 63 are ignored. Bit 29 is set to zero. */
+    tcg_gen_andi_i64(o->addr1, o->addr1, 0x3ull);
+    gen_helper_srnm(cpu_env, o->addr1);
+    return DISAS_NEXT;
+}
 
-    switch (s->fields->op2) {
-    case 0x99: /* SRNM */
-        pos = 0, len = 2;
-        break;
-    case 0xb8: /* SRNMB */
-        pos = 0, len = 3;
-        break;
-    case 0xb9: /* SRNMT */
-        pos = 4, len = 3;
-        break;
-    default:
-        tcg_abort();
-    }
-    mask = (1 << len) - 1;
+static DisasJumpType op_srnmb(DisasContext *s, DisasOps *o)
+{
+    /* Bits 0-55 are are ignored. */
+    tcg_gen_andi_i64(o->addr1, o->addr1, 0xffull);
+    gen_helper_srnm(cpu_env, o->addr1);
+    return DISAS_NEXT;
+}
 
-    /* Insert the value into the appropriate field of the FPC.  */
-    if (b2 == 0) {
-        tcg_gen_movi_i64(t1, d2 & mask);
-    } else {
-        tcg_gen_addi_i64(t1, regs[b2], d2);
-        tcg_gen_andi_i64(t1, t1, mask);
-    }
-    tcg_gen_ld32u_i64(t2, cpu_env, offsetof(CPUS390XState, fpc));
-    tcg_gen_deposit_i64(t2, t2, t1, pos, len);
-    tcg_temp_free_i64(t1);
+static DisasJumpType op_srnmt(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 tmp = tcg_temp_new_i64();
 
-    /* Then install the new FPC to set the rounding mode in fpu_status.  */
-    gen_helper_sfpc(cpu_env, t2);
-    tcg_temp_free_i64(t2);
+    /* Bits other than 61-63 are ignored. */
+    tcg_gen_andi_i64(o->addr1, o->addr1, 0x7ull);
+
+    /* No need to call a helper, we don't implement dfp */
+    tcg_gen_ld32u_i64(tmp, cpu_env, offsetof(CPUS390XState, fpc));
+    tcg_gen_deposit_i64(tmp, tmp, o->addr1, 4, 3);
+    tcg_gen_st32_i64(tmp, cpu_env, offsetof(CPUS390XState, fpc));
+
+    tcg_temp_free_i64(tmp);
     return DISAS_NEXT;
 }
 
-- 
2.17.2

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

* [Qemu-devel] [PATCH v2 10/15] s390x/tcg: Refactor saving/restoring the bfp rounding mode
  2019-02-13 14:33 [Qemu-devel] [PATCH v2 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
                   ` (8 preceding siblings ...)
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 09/15] s390x/tcg: Check for exceptions in SET BFP ROUNDING MODE David Hildenbrand
@ 2019-02-13 14:33 ` David Hildenbrand
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 11/15] s390x/tcg: Prepare for IEEE-inexact-exception control (XxC) David Hildenbrand
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 21+ messages in thread
From: David Hildenbrand @ 2019-02-13 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck, Richard Henderson,
	David Hildenbrand

We want to reuse this in the context of vector instructions. So use
better matching names and introduce s390_restore_bfp_rounding_mode().

While at it, add proper newlines.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/fpu_helper.c | 112 +++++++++++++++++++++++---------------
 target/s390x/internal.h   |   2 +
 2 files changed, 71 insertions(+), 43 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 70fa053e8d..0cd6e19ce8 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -372,7 +372,7 @@ uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     return float_comp_to_cc(env, cmp);
 }
 
-static int swap_round_mode(CPUS390XState *env, int m3)
+int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3)
 {
     int ret = env->fpu_status.float_rounding_mode;
     switch (m3) {
@@ -401,12 +401,18 @@ static int swap_round_mode(CPUS390XState *env, int m3)
     return ret;
 }
 
+void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode)
+{
+    set_float_rounding_mode(old_mode, &env->fpu_status);
+}
+
 /* convert 64-bit int to 32-bit float */
 uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     float32 ret = int64_to_float32(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -414,9 +420,10 @@ uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
 /* convert 64-bit int to 64-bit float */
 uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     float64 ret = int64_to_float64(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -424,9 +431,10 @@ uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
 /* convert 64-bit int to 128-bit float */
 uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     float128 ret = int64_to_float128(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return RET128(ret);
 }
@@ -434,9 +442,10 @@ uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
 /* convert 64-bit uint to 32-bit float */
 uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     float32 ret = uint64_to_float32(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -444,9 +453,10 @@ uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 /* convert 64-bit uint to 64-bit float */
 uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     float64 ret = uint64_to_float64(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -454,9 +464,10 @@ uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 /* convert 64-bit uint to 128-bit float */
 uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     float128 ret = uint64_to_float128(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return RET128(ret);
 }
@@ -464,9 +475,10 @@ uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 /* convert 32-bit float to 64-bit int */
 uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     int64_t ret = float32_to_int64(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -474,9 +486,10 @@ uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 /* convert 64-bit float to 64-bit int */
 uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     int64_t ret = float64_to_int64(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -484,10 +497,11 @@ uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 /* convert 128-bit float to 64-bit int */
 uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     float128 v2 = make_float128(h, l);
     int64_t ret = float128_to_int64(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -495,9 +509,10 @@ uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
 /* convert 32-bit float to 32-bit int */
 uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     int32_t ret = float32_to_int32(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -505,9 +520,10 @@ uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 /* convert 64-bit float to 32-bit int */
 uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     int32_t ret = float64_to_int32(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -515,10 +531,11 @@ uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 /* convert 128-bit float to 32-bit int */
 uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     float128 v2 = make_float128(h, l);
     int32_t ret = float128_to_int32(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -526,11 +543,12 @@ uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
 /* convert 32-bit float to 64-bit uint */
 uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     uint64_t ret;
+
     v2 = float32_to_float64(v2, &env->fpu_status);
     ret = float64_to_uint64(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -538,9 +556,10 @@ uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 /* convert 64-bit float to 64-bit uint */
 uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     uint64_t ret = float64_to_uint64(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -548,9 +567,10 @@ uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 /* convert 128-bit float to 64-bit uint */
 uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     uint64_t ret = float128_to_uint64(make_float128(h, l), &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -558,9 +578,10 @@ uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
 /* convert 32-bit float to 32-bit uint */
 uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     uint32_t ret = float32_to_uint32(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -568,9 +589,10 @@ uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 /* convert 64-bit float to 32-bit uint */
 uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     uint32_t ret = float64_to_uint32(v2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -578,9 +600,10 @@ uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 /* convert 128-bit float to 32-bit uint */
 uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     uint32_t ret = float128_to_uint32(make_float128(h, l), &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -588,9 +611,10 @@ uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
 /* round to integer 32-bit */
 uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     float32 ret = float32_round_to_int(f2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -598,9 +622,10 @@ uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
 /* round to integer 64-bit */
 uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
     float64 ret = float64_round_to_int(f2, &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return ret;
 }
@@ -608,10 +633,11 @@ uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
 /* round to integer 128-bit */
 uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
 {
-    int hold = swap_round_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+
     float128 ret = float128_round_to_int(make_float128(ah, al),
                                          &env->fpu_status);
-    set_float_rounding_mode(hold, &env->fpu_status);
+    s390_restore_bfp_rounding_mode(env, old_mode);
     handle_exceptions(env, GETPC());
     return RET128(ret);
 }
diff --git a/target/s390x/internal.h b/target/s390x/internal.h
index e1c0b1bd3b..122fe037bc 100644
--- a/target/s390x/internal.h
+++ b/target/s390x/internal.h
@@ -315,6 +315,8 @@ uint32_t set_cc_nz_f128(float128 v);
 #define S390_IEEE_MASK_INEXACT   0x08
 #define S390_IEEE_MASK_QUANTUM   0x04
 uint8_t s390_softfloat_exc_to_ieee(unsigned int exc);
+int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3);
+void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode);
 
 
 /* gdbstub.c */
-- 
2.17.2

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

* [Qemu-devel] [PATCH v2 11/15] s390x/tcg: Prepare for IEEE-inexact-exception control (XxC)
  2019-02-13 14:33 [Qemu-devel] [PATCH v2 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
                   ` (9 preceding siblings ...)
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 10/15] s390x/tcg: Refactor saving/restoring the bfp rounding mode David Hildenbrand
@ 2019-02-13 14:33 ` David Hildenbrand
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 12/15] s390x/tcg: Implement XxC and checks for most FP instructions David Hildenbrand
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 21+ messages in thread
From: David Hildenbrand @ 2019-02-13 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck, Richard Henderson,
	David Hildenbrand

Some instructions allow to suppress IEEE inexact exceptions.

z14 PoP, 9-23, "Suppression of Certain IEEE Exceptions"
    IEEE-inexact-exception control (XxC): Bit 1 of
    the M4 field is the XxC bit. If XxC is zero, recogni-
    tion of IEEE-inexact exception is not suppressed;
    if XxC is one, recognition of IEEE-inexact excep-
    tion is suppressed.

Especially, handling for overflow/unerflow remains as is, inexact is
reported along

z14 PoP, 9-23, "Suppression of Certain IEEE Exceptions"
    For example, the IEEE-inexact-exception control (XxC)
    has no effect on the DXC; that is, the DXC for IEEE-
    overflow or IEEE-underflow exceptions along with the
    detail for exact, inexact and truncated, or inexact and
    incremented, is reported according to the actual con-
    dition.

Follow up patches will wire it correctly up for the applicable
instructions.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/fpu_helper.c | 114 +++++++++++++++++++-------------------
 1 file changed, 57 insertions(+), 57 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 0cd6e19ce8..f6f010ae35 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -50,7 +50,7 @@ uint8_t s390_softfloat_exc_to_ieee(unsigned int exc)
 }
 
 /* Should be called after any operation that may raise IEEE exceptions.  */
-static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
+static void handle_exceptions(CPUS390XState *env, bool XxC, uintptr_t retaddr)
 {
     unsigned s390_exc, qemu_exc;
 
@@ -101,7 +101,7 @@ static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
     }
 
     /* inexact handling */
-    if (s390_exc & S390_IEEE_MASK_INEXACT) {
+    if (s390_exc & S390_IEEE_MASK_INEXACT && !XxC) {
         /* trap condition - overflow/underflow _not_ reported along */
         if (s390_exc & S390_IEEE_MASK_INEXACT & env->fpc >> 24) {
             tcg_s390_data_exception(env, s390_exc & S390_IEEE_MASK_INEXACT,
@@ -174,7 +174,7 @@ uint32_t set_cc_nz_f128(float128 v)
 uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float32 ret = float32_add(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -182,7 +182,7 @@ uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float64 ret = float64_add(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -193,7 +193,7 @@ uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     float128 ret = float128_add(make_float128(ah, al),
                                 make_float128(bh, bl),
                                 &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
@@ -201,7 +201,7 @@ uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
 uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float32 ret = float32_sub(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -209,7 +209,7 @@ uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float64 ret = float64_sub(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -220,7 +220,7 @@ uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     float128 ret = float128_sub(make_float128(ah, al),
                                 make_float128(bh, bl),
                                 &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
@@ -228,7 +228,7 @@ uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
 uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float32 ret = float32_div(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -236,7 +236,7 @@ uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float64 ret = float64_div(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -247,7 +247,7 @@ uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     float128 ret = float128_div(make_float128(ah, al),
                                 make_float128(bh, bl),
                                 &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
@@ -255,7 +255,7 @@ uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
 uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float32 ret = float32_mul(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -263,7 +263,7 @@ uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float64 ret = float64_mul(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -272,7 +272,7 @@ uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     float64 ret = float32_to_float64(f2, &env->fpu_status);
     ret = float64_mul(f1, ret, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -283,7 +283,7 @@ uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     float128 ret = float128_mul(make_float128(ah, al),
                                 make_float128(bh, bl),
                                 &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
@@ -293,7 +293,7 @@ uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al,
 {
     float128 ret = float64_to_float128(f2, &env->fpu_status);
     ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
@@ -301,7 +301,7 @@ uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al,
 uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
 {
     float64 ret = float32_to_float64(f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -309,7 +309,7 @@ uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
 uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
 {
     float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -317,7 +317,7 @@ uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
 uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
 {
     float128 ret = float64_to_float128(f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
@@ -325,7 +325,7 @@ uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
 uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
 {
     float128 ret = float32_to_float128(f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
@@ -333,7 +333,7 @@ uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
 uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
 {
     float32 ret = float64_to_float32(f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -341,7 +341,7 @@ uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
 uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
 {
     float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -349,7 +349,7 @@ uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
 uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return float_comp_to_cc(env, cmp);
 }
 
@@ -357,7 +357,7 @@ uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return float_comp_to_cc(env, cmp);
 }
 
@@ -368,7 +368,7 @@ uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     int cmp = float128_compare_quiet(make_float128(ah, al),
                                      make_float128(bh, bl),
                                      &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return float_comp_to_cc(env, cmp);
 }
 
@@ -413,7 +413,7 @@ uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
     float32 ret = int64_to_float32(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -424,7 +424,7 @@ uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
     float64 ret = int64_to_float64(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -435,7 +435,7 @@ uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
     float128 ret = int64_to_float128(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
@@ -446,7 +446,7 @@ uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
     float32 ret = uint64_to_float32(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -457,7 +457,7 @@ uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
     float64 ret = uint64_to_float64(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -468,7 +468,7 @@ uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
     float128 ret = uint64_to_float128(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
@@ -479,7 +479,7 @@ uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
     int64_t ret = float32_to_int64(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -490,7 +490,7 @@ uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
     int64_t ret = float64_to_int64(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -502,7 +502,7 @@ uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
     int64_t ret = float128_to_int64(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -513,7 +513,7 @@ uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
     int32_t ret = float32_to_int32(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -524,7 +524,7 @@ uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
     int32_t ret = float64_to_int32(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -536,7 +536,7 @@ uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
     int32_t ret = float128_to_int32(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -549,7 +549,7 @@ uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
     v2 = float32_to_float64(v2, &env->fpu_status);
     ret = float64_to_uint64(v2, &env->fpu_status);
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -560,7 +560,7 @@ uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
     uint64_t ret = float64_to_uint64(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -571,7 +571,7 @@ uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
     uint64_t ret = float128_to_uint64(make_float128(h, l), &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -582,7 +582,7 @@ uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
     uint32_t ret = float32_to_uint32(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -593,7 +593,7 @@ uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
     uint32_t ret = float64_to_uint32(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -604,7 +604,7 @@ uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
     uint32_t ret = float128_to_uint32(make_float128(h, l), &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -615,7 +615,7 @@ uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
     float32 ret = float32_round_to_int(f2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -626,7 +626,7 @@ uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
     float64 ret = float64_round_to_int(f2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -634,11 +634,11 @@ uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
 uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
 {
     int old_mode = s390_swap_bfp_rounding_mode(env, m3);
-
     float128 ret = float128_round_to_int(make_float128(ah, al),
                                          &env->fpu_status);
+
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
@@ -646,7 +646,7 @@ uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
 uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     int cmp = float32_compare(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return float_comp_to_cc(env, cmp);
 }
 
@@ -654,7 +654,7 @@ uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
     int cmp = float64_compare(f1, f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return float_comp_to_cc(env, cmp);
 }
 
@@ -665,7 +665,7 @@ uint32_t HELPER(kxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     int cmp = float128_compare(make_float128(ah, al),
                                make_float128(bh, bl),
                                &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return float_comp_to_cc(env, cmp);
 }
 
@@ -674,7 +674,7 @@ uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
                       uint64_t f2, uint64_t f3)
 {
     float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -683,7 +683,7 @@ uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1,
                       uint64_t f2, uint64_t f3)
 {
     float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -693,7 +693,7 @@ uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1,
 {
     float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c,
                                  &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -703,7 +703,7 @@ uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
 {
     float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c,
                                  &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -759,7 +759,7 @@ uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint64_t m2)
 uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
 {
     float32 ret = float32_sqrt(f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -767,7 +767,7 @@ uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
 uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
 {
     float64 ret = float64_sqrt(f2, &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return ret;
 }
 
@@ -775,7 +775,7 @@ uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
 uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
 {
     float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status);
-    handle_exceptions(env, GETPC());
+    handle_exceptions(env, false, GETPC());
     return RET128(ret);
 }
 
-- 
2.17.2

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

* [Qemu-devel] [PATCH v2 12/15] s390x/tcg: Implement XxC and checks for most FP instructions
  2019-02-13 14:33 [Qemu-devel] [PATCH v2 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
                   ` (10 preceding siblings ...)
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 11/15] s390x/tcg: Prepare for IEEE-inexact-exception control (XxC) David Hildenbrand
@ 2019-02-13 14:33 ` David Hildenbrand
  2019-02-13 19:31   ` Richard Henderson
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 13/15] s390x/tcg: Implement rounding mode and XxC for LOAD ROUNDED David Hildenbrand
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 21+ messages in thread
From: David Hildenbrand @ 2019-02-13 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck, Richard Henderson,
	David Hildenbrand

With the floating-point extension facility
- CONVERT FROM LOGICAL
- CONVERT TO LOGICAL
- CONVERT TO FIXED
- CONVERT FROM FIXED
- LOAD FP INTEGER
have both, a rounding mode specification and the inexact-exception control
(XxC). Other instructions will be handled separatly.

Check for valid rounding modes and forward also the XxC (via m4). To avoid
a lot of boilerplate code and changes to the helpers, combine both, the
m3 and m4 field in a combined 32 bit TCG variable. Perform checks at
a central place, taking in account if the m3 or m4 field was ignore
before the floating-point extension facility was introduced.

Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/fpu_helper.c | 138 ++++++++++++----------
 target/s390x/translate.c  | 235 ++++++++++++++++++++++++++++----------
 2 files changed, 247 insertions(+), 126 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index f6f010ae35..a9fad6b3cd 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -170,6 +170,17 @@ uint32_t set_cc_nz_f128(float128 v)
     }
 }
 
+static inline uint8_t round_from_m34(uint32_t m34)
+{
+    return extract32(m34, 0, 4);
+}
+
+static inline bool xxc_from_m34(uint32_t m34)
+{
+    /* XxC is bit 1 of m4 */
+    return (extract32(m34, 4, 4) & 0x4) != 0;
+}
+
 /* 32-bit FP addition */
 uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
@@ -407,238 +418,239 @@ void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode)
 }
 
 /* convert 64-bit int to 32-bit float */
-uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float32 ret = int64_to_float32(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 64-bit int to 64-bit float */
-uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float64 ret = int64_to_float64(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 64-bit int to 128-bit float */
-uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float128 ret = int64_to_float128(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return RET128(ret);
 }
 
 /* convert 64-bit uint to 32-bit float */
-uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float32 ret = uint64_to_float32(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 64-bit uint to 64-bit float */
-uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float64 ret = uint64_to_float64(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 64-bit uint to 128-bit float */
-uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float128 ret = uint64_to_float128(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return RET128(ret);
 }
 
 /* convert 32-bit float to 64-bit int */
-uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     int64_t ret = float32_to_int64(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 64-bit float to 64-bit int */
-uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     int64_t ret = float64_to_int64(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 128-bit float to 64-bit int */
-uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float128 v2 = make_float128(h, l);
     int64_t ret = float128_to_int64(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 32-bit float to 32-bit int */
-uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     int32_t ret = float32_to_int32(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 64-bit float to 32-bit int */
-uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     int32_t ret = float64_to_int32(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 128-bit float to 32-bit int */
-uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float128 v2 = make_float128(h, l);
     int32_t ret = float128_to_int32(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 32-bit float to 64-bit uint */
-uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     uint64_t ret;
 
     v2 = float32_to_float64(v2, &env->fpu_status);
     ret = float64_to_uint64(v2, &env->fpu_status);
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 64-bit float to 64-bit uint */
-uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     uint64_t ret = float64_to_uint64(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 128-bit float to 64-bit uint */
-uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     uint64_t ret = float128_to_uint64(make_float128(h, l), &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 32-bit float to 32-bit uint */
-uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     uint32_t ret = float32_to_uint32(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 64-bit float to 32-bit uint */
-uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     uint32_t ret = float64_to_uint32(v2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 128-bit float to 32-bit uint */
-uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     uint32_t ret = float128_to_uint32(make_float128(h, l), &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* round to integer 32-bit */
-uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
+uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float32 ret = float32_round_to_int(f2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* round to integer 64-bit */
-uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
+uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float64 ret = float64_round_to_int(f2, &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* round to integer 128-bit */
-uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
+uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+                      uint32_t m34)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float128 ret = float128_round_to_int(make_float128(ah, al),
                                          &env->fpu_status);
 
     s390_restore_bfp_rounding_mode(env, old_mode);
-    handle_exceptions(env, false, GETPC());
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return RET128(ret);
 }
 
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index c2645891e8..e252ba375c 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -1758,160 +1758,257 @@ static DisasJumpType op_cxb(DisasContext *s, DisasOps *o)
     return DISAS_NEXT;
 }
 
+static TCGv_i32 fpinst_extract_m34(DisasContext *s, bool m3_with_fpe,
+                                   bool m4_with_fpe)
+{
+    const bool fpe = s390_has_feat(S390_FEAT_FLOATING_POINT_EXT);
+    uint8_t m3 = get_field(s->fields, m3);
+    uint8_t m4 = get_field(s->fields, m4);
+
+    /* m3 field was introduced with FPE */
+    if (!fpe && m3_with_fpe) {
+        m3 = 0;
+    }
+    /* m4 field was introduced with FPE */
+    if (!fpe && m4_with_fpe) {
+        m4 = 0;
+    }
+
+    /* Check for valid rounding modes. Mode 3 was introduced later. */
+    if (m3 == 2 || m3 > 7 || (!fpe && m3 == 3)) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return NULL;
+    }
+
+    return tcg_const_i32(deposit32(m3, 4, 4, m4));
+}
+
 static DisasJumpType op_cfeb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cfeb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cfeb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f32(s, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cfdb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cfdb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cfdb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f64(s, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cfxb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cfxb(o->out, cpu_env, o->in1, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cfxb(o->out, cpu_env, o->in1, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f128(s, o->in1, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cgeb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cgeb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cgeb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f32(s, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cgdb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cgdb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cgdb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f64(s, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cgxb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cgxb(o->out, cpu_env, o->in1, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cgxb(o->out, cpu_env, o->in1, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f128(s, o->in1, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_clfeb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_clfeb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_clfeb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f32(s, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_clfdb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_clfdb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_clfdb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f64(s, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_clfxb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_clfxb(o->out, cpu_env, o->in1, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_clfxb(o->out, cpu_env, o->in1, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f128(s, o->in1, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_clgeb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_clgeb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_clgeb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f32(s, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_clgdb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_clgdb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_clgdb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f64(s, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_clgxb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_clgxb(o->out, cpu_env, o->in1, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_clgxb(o->out, cpu_env, o->in1, o->in2, m34);
+    tcg_temp_free_i32(m34);
     gen_set_cc_nz_f128(s, o->in1, o->in2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cegb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cegb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cegb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cdgb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cdgb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cdgb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cxgb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cxgb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cxgb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return_low128(o->out2);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_celgb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_celgb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_celgb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cdlgb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cdlgb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cdlgb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_cxlgb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_cxlgb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_cxlgb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return_low128(o->out2);
     return DISAS_NEXT;
 }
@@ -2390,26 +2487,38 @@ static DisasJumpType op_ex(DisasContext *s, DisasOps *o)
 
 static DisasJumpType op_fieb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_fieb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_fieb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_fidb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_fidb(o->out, cpu_env, o->in2, m3);
-    tcg_temp_free_i32(m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_fidb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_fixb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
-    gen_helper_fixb(o->out, cpu_env, o->in1, o->in2, m3);
+    TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_fixb(o->out, cpu_env, o->in1, o->in2, m34);
     return_low128(o->out2);
-    tcg_temp_free_i32(m3);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
-- 
2.17.2

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

* [Qemu-devel] [PATCH v2 13/15] s390x/tcg: Implement rounding mode and XxC for LOAD ROUNDED
  2019-02-13 14:33 [Qemu-devel] [PATCH v2 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
                   ` (11 preceding siblings ...)
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 12/15] s390x/tcg: Implement XxC and checks for most FP instructions David Hildenbrand
@ 2019-02-13 14:33 ` David Hildenbrand
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 14/15] s390x/tcg: Handle all rounding modes overwritten by BFP instructions David Hildenbrand
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 15/15] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
  14 siblings, 0 replies; 21+ messages in thread
From: David Hildenbrand @ 2019-02-13 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck, Richard Henderson,
	David Hildenbrand

With the floating-point extension facility, LOAD ROUNDED has
a rounding mode specification and the inexact-exception control (XxC).

Handle them just like e.g. LOAD FP INTEGER.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/fpu_helper.c  | 23 +++++++++++++++++------
 target/s390x/helper.h      |  6 +++---
 target/s390x/insn-data.def |  6 +++---
 target/s390x/translate.c   | 24 +++++++++++++++++++++---
 4 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index a9fad6b3cd..5e4b76f4aa 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -317,10 +317,14 @@ uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
 }
 
 /* convert 128-bit float to 64-bit float */
-uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
+uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+                      uint32_t m34)
 {
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
-    handle_exceptions(env, false, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
@@ -341,18 +345,25 @@ uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
 }
 
 /* convert 64-bit float to 32-bit float */
-uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
+uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
 {
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float32 ret = float64_to_float32(f2, &env->fpu_status);
-    handle_exceptions(env, false, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
 /* convert 128-bit float to 32-bit float */
-uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
+uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+                      uint32_t m34)
 {
+    int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
     float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
-    handle_exceptions(env, false, GETPC());
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
+    handle_exceptions(env, xxc_from_m34(m34), GETPC());
     return ret;
 }
 
diff --git a/target/s390x/helper.h b/target/s390x/helper.h
index d287d5dac0..bb659257f6 100644
--- a/target/s390x/helper.h
+++ b/target/s390x/helper.h
@@ -53,11 +53,11 @@ DEF_HELPER_FLAGS_3(mdb, TCG_CALL_NO_WG, i64, env, i64, i64)
 DEF_HELPER_FLAGS_5(mxb, TCG_CALL_NO_WG, i64, env, i64, i64, i64, i64)
 DEF_HELPER_FLAGS_4(mxdb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_2(ldeb, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_3(ldxb, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_4(ldxb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
 DEF_HELPER_FLAGS_2(lxdb, TCG_CALL_NO_WG, i64, env, i64)
 DEF_HELPER_FLAGS_2(lxeb, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_2(ledb, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_3(lexb, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(ledb, TCG_CALL_NO_WG, i64, env, i64, i32)
+DEF_HELPER_FLAGS_4(lexb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
 DEF_HELPER_FLAGS_3(ceb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
 DEF_HELPER_FLAGS_3(cdb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
 DEF_HELPER_FLAGS_5(cxb, TCG_CALL_NO_WG_SE, i32, env, i64, i64, i64, i64)
diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def
index 2c9ae503c5..3a8d4f6804 100644
--- a/target/s390x/insn-data.def
+++ b/target/s390x/insn-data.def
@@ -599,9 +599,9 @@
     F(0xed05, LXDB,    RXE,   Z,   0, m2_64, new_P, x1, lxdb, 0, IF_BFP)
     F(0xed06, LXEB,    RXE,   Z,   0, m2_32u, new_P, x1, lxeb, 0, IF_BFP)
 /* LOAD ROUNDED */
-    F(0xb344, LEDBR,   RRE,   Z,   0, f2, new, e1, ledb, 0, IF_BFP)
-    F(0xb345, LDXBR,   RRE,   Z,   x2h, x2l, new, f1, ldxb, 0, IF_BFP)
-    F(0xb346, LEXBR,   RRE,   Z,   x2h, x2l, new, e1, lexb, 0, IF_BFP)
+    F(0xb344, LEDBR,   RRF_e, Z,   0, f2, new, e1, ledb, 0, IF_BFP)
+    F(0xb345, LDXBR,   RRF_e, Z,   x2h, x2l, new, f1, ldxb, 0, IF_BFP)
+    F(0xb346, LEXBR,   RRF_e, Z,   x2h, x2l, new, e1, lexb, 0, IF_BFP)
 
 /* LOAD MULTIPLE */
     C(0x9800, LM,      RS_a,  Z,   0, a2, 0, 0, lm32, 0)
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index e252ba375c..02a4bb6ac2 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -2787,19 +2787,37 @@ static DisasJumpType op_ldeb(DisasContext *s, DisasOps *o)
 
 static DisasJumpType op_ledb(DisasContext *s, DisasOps *o)
 {
-    gen_helper_ledb(o->out, cpu_env, o->in2);
+    TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_ledb(o->out, cpu_env, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_ldxb(DisasContext *s, DisasOps *o)
 {
-    gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2);
+    TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_lexb(DisasContext *s, DisasOps *o)
 {
-    gen_helper_lexb(o->out, cpu_env, o->in1, o->in2);
+    TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+    if (!m34) {
+        return DISAS_NORETURN;
+    }
+    gen_helper_lexb(o->out, cpu_env, o->in1, o->in2, m34);
+    tcg_temp_free_i32(m34);
     return DISAS_NEXT;
 }
 
-- 
2.17.2

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

* [Qemu-devel] [PATCH v2 14/15] s390x/tcg: Handle all rounding modes overwritten by BFP instructions
  2019-02-13 14:33 [Qemu-devel] [PATCH v2 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
                   ` (12 preceding siblings ...)
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 13/15] s390x/tcg: Implement rounding mode and XxC for LOAD ROUNDED David Hildenbrand
@ 2019-02-13 14:33 ` David Hildenbrand
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 15/15] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
  14 siblings, 0 replies; 21+ messages in thread
From: David Hildenbrand @ 2019-02-13 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck, Richard Henderson,
	David Hildenbrand, Peter Maydell

PoP describes "Round to nearest with ties away from 0" as
  "The candidate nearest to the input value is selected. In case of a tie,
   the candidate selected is the one that is larger in magnitude."

While float_round_ties_away is according to the introducing commit
f9288a76f181 ("softfloat: Add support for ties-away rounding")
  "roundTiesToAway: the floating-point number nearest to the infinitely
   precise result shall be delivered; if the two nearest floating-point
   numbers bracketing an unrepresentable infinitely precise result are
   equally near, the one with larger magnitude shall be delivered."

So this could be it if we're lucky ;)

Handle "round to prepare for shorter precision" just as when setting it
via SET FLOATING POINT and friends.

As all instructions properly check for valid rounding modes in translate.c
we can add an assert. Fix one missing empty line.

Cc: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/fpu_helper.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 5e4b76f4aa..f790ec0c8e 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -397,14 +397,26 @@ uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
 int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3)
 {
     int ret = env->fpu_status.float_rounding_mode;
+
     switch (m3) {
     case 0:
         /* current mode */
         break;
     case 1:
-        /* biased round no nearest */
+        /* round to nearest with ties away from 0 */
+        set_float_rounding_mode(float_round_ties_away, &env->fpu_status);
+        break;
+    case 3:
+        /*
+         * round to prepare for shorter precision
+         *
+         * FIXME: we actually want something like round_to_odd, but that
+         * does not support all data types yet.
+         */
+        set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
+        break;
     case 4:
-        /* round to nearest */
+        /* round to nearest with ties to even */
         set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
         break;
     case 5:
@@ -419,6 +431,8 @@ int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3)
         /* round to -inf */
         set_float_rounding_mode(float_round_down, &env->fpu_status);
         break;
+    default:
+        g_assert_not_reached();
     }
     return ret;
 }
-- 
2.17.2

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

* [Qemu-devel] [PATCH v2 15/15] s390x: Add floating-point extension facility to "qemu" cpu model
  2019-02-13 14:33 [Qemu-devel] [PATCH v2 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
                   ` (13 preceding siblings ...)
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 14/15] s390x/tcg: Handle all rounding modes overwritten by BFP instructions David Hildenbrand
@ 2019-02-13 14:33 ` David Hildenbrand
  14 siblings, 0 replies; 21+ messages in thread
From: David Hildenbrand @ 2019-02-13 14:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck, Richard Henderson,
	David Hildenbrand

The floating-point extension facility implemented certain changes to
BFP, HFP and DFP instructions.

As we don't implement HFP/DFP, we can ignore those completely. Related
to BFP, the changes include
- SET BFP ROUNDING MODE (SRNMB) instruction
- BFP-rounding-mode field in the FPC register is changed to 3 bits
- CONVERT FROM LOGICAL instructions
- CONVERT TO LOGICAL instructions
- Changes (rounding mode + XxC) added to
-- CONVERT TO FIXED
-- CONVERT FROM FIXED
-- LOAD FP INTEGER
-- LOAD ROUNDED
-- DIVIDE TO INTEGER

For TCG, we don't implement DIVIDE TO INTEGER, and it is harder to
implement, so skip that. Also, as we don't implement PFPO, we can skip
changes to that as well. The other parts are now implemented, we can
indicate the facility.

z14 PoP mentiones that "The floating-point extension facility is installed
in the z/Architecture architectural mode. When bit 37 is one, bit 42 is
also one.", meaning that the DFP (decimal-floating-point) facility also
has to be inidicated. We can ignore that for now.

Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/gen-features.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c
index 44eca45474..e4739a6b9f 100644
--- a/target/s390x/gen-features.c
+++ b/target/s390x/gen-features.c
@@ -601,6 +601,11 @@ static uint16_t qemu_V3_1[] = {
 };
 
 static uint16_t qemu_LATEST[] = {
+    /*
+     * Only BFP bits are implemented (HFP, DFP, PFPO and DIVIDE TO INTEGER not
+     * implemented yet).
+     */
+    S390_FEAT_FLOATING_POINT_EXT,
     S390_FEAT_ZPCI,
 };
 
-- 
2.17.2

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

* Re: [Qemu-devel] [PATCH v2 01/15] s390x/tcg: Fix TEST DATA CLASS instructions
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 01/15] s390x/tcg: Fix TEST DATA CLASS instructions David Hildenbrand
@ 2019-02-13 19:17   ` Richard Henderson
  0 siblings, 0 replies; 21+ messages in thread
From: Richard Henderson @ 2019-02-13 19:17 UTC (permalink / raw)
  To: David Hildenbrand, qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck

On 2/13/19 6:33 AM, David Hildenbrand wrote:
> Let's detect normal and denormal ("subnormal") numbers reliably. Also
> test for quiet NaN's. As only one class is possible, test common cases
> first.
> 
> While at it, use a better check to test for the mask bits in the data
> class mask. The data class mask has 12 bits, whereby bit 0 is the
> leftmost bit and bit 11 the rightmost bit. In the PoP an easy to read
> table with the numbers is provided for the VECTOR FP TEST DATA CLASS
> IMMEDIATE instruction, the table for TEST DATA CLASS is more confusing
> as it is based on 64 bit values.
> 
> Factor the checks out into separate functions, as they will also be
> needed for floating point vector instructions. We can use a makro to
> generate the functions.
> 
> Signed-off-by: David Hildenbrand <david@redhat.com>
> ---

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

r~

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

* Re: [Qemu-devel] [PATCH v2 12/15] s390x/tcg: Implement XxC and checks for most FP instructions
  2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 12/15] s390x/tcg: Implement XxC and checks for most FP instructions David Hildenbrand
@ 2019-02-13 19:31   ` Richard Henderson
  2019-02-13 19:53     ` David Hildenbrand
  0 siblings, 1 reply; 21+ messages in thread
From: Richard Henderson @ 2019-02-13 19:31 UTC (permalink / raw)
  To: David Hildenbrand, qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck

On 2/13/19 6:33 AM, David Hildenbrand wrote:
> With the floating-point extension facility
> - CONVERT FROM LOGICAL
> - CONVERT TO LOGICAL
> - CONVERT TO FIXED
> - CONVERT FROM FIXED
> - LOAD FP INTEGER
> have both, a rounding mode specification and the inexact-exception control
> (XxC). Other instructions will be handled separatly.
> 
> Check for valid rounding modes and forward also the XxC (via m4). To avoid
> a lot of boilerplate code and changes to the helpers, combine both, the
> m3 and m4 field in a combined 32 bit TCG variable. Perform checks at
> a central place, taking in account if the m3 or m4 field was ignore
> before the floating-point extension facility was introduced.
> 
> Signed-off-by: David Hildenbrand <david@redhat.com>

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

> +static inline bool xxc_from_m34(uint32_t m34)
> +{
> +    /* XxC is bit 1 of m4 */
> +    return (extract32(m34, 4, 4) & 0x4) != 0;

Better as extract32(m32, 6, 1);


r~

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

* Re: [Qemu-devel] [PATCH v2 12/15] s390x/tcg: Implement XxC and checks for most FP instructions
  2019-02-13 19:31   ` Richard Henderson
@ 2019-02-13 19:53     ` David Hildenbrand
  2019-02-14  5:25       ` Richard Henderson
  0 siblings, 1 reply; 21+ messages in thread
From: David Hildenbrand @ 2019-02-13 19:53 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck

On 13.02.19 20:31, Richard Henderson wrote:
> On 2/13/19 6:33 AM, David Hildenbrand wrote:
>> With the floating-point extension facility
>> - CONVERT FROM LOGICAL
>> - CONVERT TO LOGICAL
>> - CONVERT TO FIXED
>> - CONVERT FROM FIXED
>> - LOAD FP INTEGER
>> have both, a rounding mode specification and the inexact-exception control
>> (XxC). Other instructions will be handled separatly.
>>
>> Check for valid rounding modes and forward also the XxC (via m4). To avoid
>> a lot of boilerplate code and changes to the helpers, combine both, the
>> m3 and m4 field in a combined 32 bit TCG variable. Perform checks at
>> a central place, taking in account if the m3 or m4 field was ignore
>> before the floating-point extension facility was introduced.
>>
>> Signed-off-by: David Hildenbrand <david@redhat.com>
> 
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> 
>> +static inline bool xxc_from_m34(uint32_t m34)
>> +{
>> +    /* XxC is bit 1 of m4 */
>> +    return (extract32(m34, 4, 4) & 0x4) != 0;
> 
> Better as extract32(m32, 6, 1);

Is it "better as" that or "better written as" that?

I think "extract32(m34, 4, 4) & 0x4" is slightly easier to understand.
(get m4 field and take the bit number 1)

Thanks!

> 
> 
> r~
> 


-- 

Thanks,

David / dhildenb

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

* Re: [Qemu-devel] [PATCH v2 12/15] s390x/tcg: Implement XxC and checks for most FP instructions
  2019-02-13 19:53     ` David Hildenbrand
@ 2019-02-14  5:25       ` Richard Henderson
  2019-02-14 10:08         ` David Hildenbrand
  0 siblings, 1 reply; 21+ messages in thread
From: Richard Henderson @ 2019-02-14  5:25 UTC (permalink / raw)
  To: David Hildenbrand, qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck

On 2/13/19 11:53 AM, David Hildenbrand wrote:
> On 13.02.19 20:31, Richard Henderson wrote:
>> On 2/13/19 6:33 AM, David Hildenbrand wrote:
>>> With the floating-point extension facility
>>> - CONVERT FROM LOGICAL
>>> - CONVERT TO LOGICAL
>>> - CONVERT TO FIXED
>>> - CONVERT FROM FIXED
>>> - LOAD FP INTEGER
>>> have both, a rounding mode specification and the inexact-exception control
>>> (XxC). Other instructions will be handled separatly.
>>>
>>> Check for valid rounding modes and forward also the XxC (via m4). To avoid
>>> a lot of boilerplate code and changes to the helpers, combine both, the
>>> m3 and m4 field in a combined 32 bit TCG variable. Perform checks at
>>> a central place, taking in account if the m3 or m4 field was ignore
>>> before the floating-point extension facility was introduced.
>>>
>>> Signed-off-by: David Hildenbrand <david@redhat.com>
>>
>> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>>
>>> +static inline bool xxc_from_m34(uint32_t m34)
>>> +{
>>> +    /* XxC is bit 1 of m4 */
>>> +    return (extract32(m34, 4, 4) & 0x4) != 0;
>>
>> Better as extract32(m32, 6, 1);
> 
> Is it "better as" that or "better written as" that?
> 
> I think "extract32(m34, 4, 4) & 0x4" is slightly easier to understand.
> (get m4 field and take the bit number 1)

I don't like not extracting the bit that you want.  Do you prefer to let the
compiler fold the constant?  E.g.  4 + 3 - 1?

I hate big-endian bit numbering...


r~

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

* Re: [Qemu-devel] [PATCH v2 12/15] s390x/tcg: Implement XxC and checks for most FP instructions
  2019-02-14  5:25       ` Richard Henderson
@ 2019-02-14 10:08         ` David Hildenbrand
  0 siblings, 0 replies; 21+ messages in thread
From: David Hildenbrand @ 2019-02-14 10:08 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck

On 14.02.19 06:25, Richard Henderson wrote:
> On 2/13/19 11:53 AM, David Hildenbrand wrote:
>> On 13.02.19 20:31, Richard Henderson wrote:
>>> On 2/13/19 6:33 AM, David Hildenbrand wrote:
>>>> With the floating-point extension facility
>>>> - CONVERT FROM LOGICAL
>>>> - CONVERT TO LOGICAL
>>>> - CONVERT TO FIXED
>>>> - CONVERT FROM FIXED
>>>> - LOAD FP INTEGER
>>>> have both, a rounding mode specification and the inexact-exception control
>>>> (XxC). Other instructions will be handled separatly.
>>>>
>>>> Check for valid rounding modes and forward also the XxC (via m4). To avoid
>>>> a lot of boilerplate code and changes to the helpers, combine both, the
>>>> m3 and m4 field in a combined 32 bit TCG variable. Perform checks at
>>>> a central place, taking in account if the m3 or m4 field was ignore
>>>> before the floating-point extension facility was introduced.
>>>>
>>>> Signed-off-by: David Hildenbrand <david@redhat.com>
>>>
>>> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>>>
>>>> +static inline bool xxc_from_m34(uint32_t m34)
>>>> +{
>>>> +    /* XxC is bit 1 of m4 */
>>>> +    return (extract32(m34, 4, 4) & 0x4) != 0;
>>>
>>> Better as extract32(m32, 6, 1);
>>
>> Is it "better as" that or "better written as" that?
>>
>> I think "extract32(m34, 4, 4) & 0x4" is slightly easier to understand.
>> (get m4 field and take the bit number 1)
> 
> I don't like not extracting the bit that you want.  Do you prefer to let the
> compiler fold the constant?  E.g.  4 + 3 - 1?

Yes, that looks better.

> 
> I hate big-endian bit numbering...
> 
> 
> r~
> 


-- 

Thanks,

David / dhildenb

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

end of thread, other threads:[~2019-02-14 10:08 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-13 14:33 [Qemu-devel] [PATCH v2 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 01/15] s390x/tcg: Fix TEST DATA CLASS instructions David Hildenbrand
2019-02-13 19:17   ` Richard Henderson
2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 02/15] s390x/tcg: Fix rounding from float128 to uint64_t/uin32_t David Hildenbrand
2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 03/15] s390x/tcg: Factor out conversion of softfloat exceptions David Hildenbrand
2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 04/15] s390x/tcg: Fix parts of IEEE exception handling David Hildenbrand
2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 05/15] s390x/tcg: Hide IEEE underflows in some scenarios David Hildenbrand
2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 06/15] s390x/tcg: Refactor SET FPC AND SIGNAL handling David Hildenbrand
2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 07/15] s390x/tcg: Fix simulated-IEEE exceptions David Hildenbrand
2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 08/15] s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes David Hildenbrand
2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 09/15] s390x/tcg: Check for exceptions in SET BFP ROUNDING MODE David Hildenbrand
2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 10/15] s390x/tcg: Refactor saving/restoring the bfp rounding mode David Hildenbrand
2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 11/15] s390x/tcg: Prepare for IEEE-inexact-exception control (XxC) David Hildenbrand
2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 12/15] s390x/tcg: Implement XxC and checks for most FP instructions David Hildenbrand
2019-02-13 19:31   ` Richard Henderson
2019-02-13 19:53     ` David Hildenbrand
2019-02-14  5:25       ` Richard Henderson
2019-02-14 10:08         ` David Hildenbrand
2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 13/15] s390x/tcg: Implement rounding mode and XxC for LOAD ROUNDED David Hildenbrand
2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 14/15] s390x/tcg: Handle all rounding modes overwritten by BFP instructions David Hildenbrand
2019-02-13 14:33 ` [Qemu-devel] [PATCH v2 15/15] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.