All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model
@ 2019-02-12 11:02 David Hildenbrand
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
                   ` (16 more replies)
  0 siblings, 17 replies; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:02 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 19bb8ac7f8..02f6e9f475 100644
--- a/target/s390x/gen-features.c
+++ b/target/s390x/gen-features.c
@@ -593,6 +593,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] 38+ messages in thread

* [Qemu-devel] [PATCH v1 00/15] s390x/tcg: Implement floating-point extension facility
  2019-02-12 11:02 [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
@ 2019-02-12 11:02 ` David Hildenbrand
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 01/15] s390x/tcg: Fix TEST DATA CLASS instructions David Hildenbrand
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:02 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.

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   | 547 +++++++++++++++++++++++-------------
 target/s390x/gen-features.c |   5 +
 target/s390x/helper.h       |   9 +-
 target/s390x/insn-data.def  |  12 +-
 target/s390x/internal.h     |  15 +
 target/s390x/translate.c    | 340 +++++++++++++++-------
 6 files changed, 628 insertions(+), 300 deletions(-)

-- 
2.17.2

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

* [Qemu-devel] [PATCH v1 01/15] s390x/tcg: Fix TEST DATA CLASS instructions
  2019-02-12 11:02 [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
@ 2019-02-12 11:02 ` David Hildenbrand
  2019-02-12 18:01   ` Richard Henderson
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 02/15] s390x/tcg: Fix rounding from float128 to uint64_t/uin32_t David Hildenbrand
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:02 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.

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.

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

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index e921172bc4..a3214bd546 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -645,66 +645,100 @@ uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
     return ret;
 }
 
+/*
+ * The rightmost 12 bits are the mask. The rightmost bit has the number 11.
+ */
+static inline bool test_dc_mask(uint16_t dc_mask, int bit, bool neg)
+{
+    return dc_mask & (1 << (11 - bit - neg));
+}
+
+static bool s390_tdc32(CPUS390XState *env, float32 f1, uint16_t dc_mask)
+{
+        const bool neg = float32_is_neg(f1);
+        const bool zero = float32_is_zero(f1);
+        const bool normal = float32_is_normal(f1);
+        const bool denormal = float32_is_denormal(f1);
+        const bool infinity = float32_is_infinity(f1);
+        const bool quiet_nan = float32_is_quiet_nan(f1, &env->fpu_status);
+        const bool sig_nan = float32_is_signaling_nan(f1, &env->fpu_status);
+
+        return (zero && test_dc_mask(dc_mask, 0, neg)) ||
+               (normal && test_dc_mask(dc_mask, 2, neg)) ||
+               (denormal && test_dc_mask(dc_mask, 4, neg)) ||
+               (infinity && test_dc_mask(dc_mask, 6, neg)) ||
+               (quiet_nan && test_dc_mask(dc_mask, 8, neg)) ||
+               (sig_nan && test_dc_mask(dc_mask, 10, neg));
+}
+
 /* 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 */
+    if (s390_tdc32(env, f1, m2)) {
         cc = 1;
     }
-    /* FIXME: denormalized? */
     return cc;
 }
 
+static bool s390_tdc64(CPUS390XState *env, float64 f1, uint16_t dc_mask)
+{
+        const bool neg = float64_is_neg(f1);
+        const bool zero = float64_is_zero(f1);
+        const bool normal = float64_is_normal(f1);
+        const bool denormal = float64_is_denormal(f1);
+        const bool infinity = float64_is_infinity(f1);
+        const bool quiet_nan = float64_is_quiet_nan(f1, &env->fpu_status);
+        const bool sig_nan = float64_is_signaling_nan(f1, &env->fpu_status);
+
+        return (zero && test_dc_mask(dc_mask, 0, neg)) ||
+               (normal && test_dc_mask(dc_mask, 2, neg)) ||
+               (denormal && test_dc_mask(dc_mask, 4, neg)) ||
+               (infinity && test_dc_mask(dc_mask, 6, neg)) ||
+               (quiet_nan && test_dc_mask(dc_mask, 8, neg)) ||
+               (sig_nan && test_dc_mask(dc_mask, 10, neg));
+}
+
 /* 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 */
+    if (s390_tdc64(env, v1, m2)) {
         cc = 1;
     }
-    /* FIXME: denormalized? */
     return cc;
 }
 
+static bool s390_tdc128(CPUS390XState *env, float128 f1, uint16_t dc_mask)
+{
+        const bool neg = float128_is_neg(f1);
+        const bool zero = float128_is_zero(f1);
+        const bool normal = float128_is_normal(f1);
+        const bool denormal = float128_is_denormal(f1);
+        const bool infinity = float128_is_infinity(f1);
+        const bool quiet_nan = float128_is_quiet_nan(f1, &env->fpu_status);
+        const bool sig_nan = float128_is_signaling_nan(f1, &env->fpu_status);
+
+        return (zero && test_dc_mask(dc_mask, 0, neg)) ||
+               (normal && test_dc_mask(dc_mask, 2, neg)) ||
+               (denormal && test_dc_mask(dc_mask, 4, neg)) ||
+               (infinity && test_dc_mask(dc_mask, 6, neg)) ||
+               (quiet_nan && test_dc_mask(dc_mask, 8, neg)) ||
+               (sig_nan && test_dc_mask(dc_mask, 10, neg));
+}
+
 /* 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 */
+    if (s390_tdc128(env, v1, m2)) {
         cc = 1;
     }
-    /* FIXME: denormalized? */
     return cc;
 }
 
-- 
2.17.2

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

* [Qemu-devel] [PATCH v1 02/15] s390x/tcg: Fix rounding from float128 to uint64_t/uin32_t
  2019-02-12 11:02 [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 00/15] s390x/tcg: Implement floating-point extension facility David Hildenbrand
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 01/15] s390x/tcg: Fix TEST DATA CLASS instructions David Hildenbrand
@ 2019-02-12 11:02 ` David Hildenbrand
  2019-02-12 18:03   ` Richard Henderson
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 03/15] s390x/tcg: Factor out conversion of softfloat exceptions David Hildenbrand
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:02 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 proepr conversion functions now that we have them.

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 a3214bd546..f9ec519067 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] 38+ messages in thread

* [Qemu-devel] [PATCH v1 03/15] s390x/tcg: Factor out conversion of softfloat exceptions
  2019-02-12 11:02 [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
                   ` (2 preceding siblings ...)
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 02/15] s390x/tcg: Fix rounding from float128 to uint64_t/uin32_t David Hildenbrand
@ 2019-02-12 11:02 ` David Hildenbrand
  2019-02-12 18:05   ` Richard Henderson
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 04/15] s390x/tcg: Fix parts of IEEE exception handling David Hildenbrand
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:02 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.

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 f9ec519067..60f589608e 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] 38+ messages in thread

* [Qemu-devel] [PATCH v1 04/15] s390x/tcg: Fix parts of IEEE exception handling
  2019-02-12 11:02 [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
                   ` (3 preceding siblings ...)
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 03/15] s390x/tcg: Factor out conversion of softfloat exceptions David Hildenbrand
@ 2019-02-12 11:02 ` David Hildenbrand
  2019-02-12 18:13   ` Richard Henderson
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 05/15] s390x/tcg: Hide IEEE underflows in some scenarios David Hildenbrand
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:02 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

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 60f589608e..94680053f9 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] 38+ messages in thread

* [Qemu-devel] [PATCH v1 05/15] s390x/tcg: Hide IEEE underflows in some scenarios
  2019-02-12 11:02 [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
                   ` (4 preceding siblings ...)
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 04/15] s390x/tcg: Fix parts of IEEE exception handling David Hildenbrand
@ 2019-02-12 11:02 ` David Hildenbrand
  2019-02-12 18:14   ` Richard Henderson
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 06/15] s390x/tcg: Refactor SET FPC AND SIGNAL handling David Hildenbrand
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:02 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.

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 94680053f9..2e690073ea 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] 38+ messages in thread

* [Qemu-devel] [PATCH v1 06/15] s390x/tcg: Refactor SET FPC AND SIGNAL handling
  2019-02-12 11:02 [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
                   ` (5 preceding siblings ...)
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 05/15] s390x/tcg: Hide IEEE underflows in some scenarios David Hildenbrand
@ 2019-02-12 11:02 ` David Hildenbrand
  2019-02-12 18:55   ` Richard Henderson
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 07/15] s390x/tcg: Fix simulated-IEEE exceptions David Hildenbrand
                   ` (9 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:02 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.

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 2e690073ea..7c39829352 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -820,21 +820,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] 38+ messages in thread

* [Qemu-devel] [PATCH v1 07/15] s390x/tcg: Fix simulated-IEEE exceptions
  2019-02-12 11:02 [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
                   ` (6 preceding siblings ...)
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 06/15] s390x/tcg: Refactor SET FPC AND SIGNAL handling David Hildenbrand
@ 2019-02-12 11:03 ` David Hildenbrand
  2019-02-12 18:56   ` Richard Henderson
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 08/15] s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes David Hildenbrand
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:03 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

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 7c39829352..15ede530d8 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -838,6 +838,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] 38+ messages in thread

* [Qemu-devel] [PATCH v1 08/15] s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes
  2019-02-12 11:02 [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
                   ` (7 preceding siblings ...)
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 07/15] s390x/tcg: Fix simulated-IEEE exceptions David Hildenbrand
@ 2019-02-12 11:03 ` David Hildenbrand
  2019-02-12 19:07   ` Richard Henderson
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 09/15] s390x/tcg: Check for exceptions in SET BFP ROUNDING MODE David Hildenbrand
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:03 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 | 24 ++++++++++++++++++++----
 target/s390x/helper.h     |  2 +-
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 15ede530d8..a578f849ad 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -802,21 +802,33 @@ 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_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 */
@@ -825,12 +837,16 @@ 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_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 018e9dd414..974f6bac2a 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] 38+ messages in thread

* [Qemu-devel] [PATCH v1 09/15] s390x/tcg: Check for exceptions in SET BFP ROUNDING MODE
  2019-02-12 11:02 [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
                   ` (8 preceding siblings ...)
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 08/15] s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes David Hildenbrand
@ 2019-02-12 11:03 ` David Hildenbrand
  2019-02-12 19:58   ` Richard Henderson
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 10/15] s390x/tcg: Refactor saving/restoring the bfp rounding mode David Hildenbrand
                   ` (6 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:03 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.

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 a578f849ad..a6c67527cd 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -870,3 +870,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 974f6bac2a..179c942fc8 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 dab805fd90..7ef230029e 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 639084af07..f58155f20c 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] 38+ messages in thread

* [Qemu-devel] [PATCH v1 10/15] s390x/tcg: Refactor saving/restoring the bfp rounding mode
  2019-02-12 11:02 [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
                   ` (9 preceding siblings ...)
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 09/15] s390x/tcg: Check for exceptions in SET BFP ROUNDING MODE David Hildenbrand
@ 2019-02-12 11:03 ` David Hildenbrand
  2019-02-12 20:03   ` Richard Henderson
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 11/15] s390x/tcg: Prepare for IEEE-inexact-exception control (XxC) David Hildenbrand
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:03 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.

Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/fpu_helper.c | 113 +++++++++++++++++++++++---------------
 target/s390x/internal.h   |   2 +
 2 files changed, 72 insertions(+), 43 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index a6c67527cd..518fb6365a 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,12 @@ 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 +544,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 +557,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 +568,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 +579,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 +590,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 +601,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 +612,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 +623,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 +634,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] 38+ messages in thread

* [Qemu-devel] [PATCH v1 11/15] s390x/tcg: Prepare for IEEE-inexact-exception control (XxC)
  2019-02-12 11:02 [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
                   ` (10 preceding siblings ...)
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 10/15] s390x/tcg: Refactor saving/restoring the bfp rounding mode David Hildenbrand
@ 2019-02-12 11:03 ` David Hildenbrand
  2019-02-12 20:07   ` Richard Henderson
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 12/15] s390x/tcg: Implement XxC and checks for most FP instructions David Hildenbrand
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:03 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.

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

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 518fb6365a..5136147da6 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;
 }
 
@@ -537,7 +537,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;
 }
 
@@ -550,7 +550,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;
 }
 
@@ -561,7 +561,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;
 }
 
@@ -572,7 +572,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;
 }
 
@@ -583,7 +583,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;
 }
 
@@ -594,7 +594,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;
 }
 
@@ -605,7 +605,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;
 }
 
@@ -616,7 +616,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;
 }
 
@@ -627,7 +627,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;
 }
 
@@ -639,7 +639,7 @@ uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t 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);
 }
 
@@ -647,7 +647,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);
 }
 
@@ -655,7 +655,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);
 }
 
@@ -666,7 +666,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);
 }
 
@@ -675,7 +675,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;
 }
 
@@ -684,7 +684,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;
 }
 
@@ -694,7 +694,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;
 }
 
@@ -704,7 +704,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;
 }
 
@@ -809,7 +809,7 @@ uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah,
 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;
 }
 
@@ -817,7 +817,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;
 }
 
@@ -825,7 +825,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] 38+ messages in thread

* [Qemu-devel] [PATCH v1 12/15] s390x/tcg: Implement XxC and checks for most FP instructions
  2019-02-12 11:02 [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
                   ` (11 preceding siblings ...)
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 11/15] s390x/tcg: Prepare for IEEE-inexact-exception control (XxC) David Hildenbrand
@ 2019-02-12 11:03 ` David Hildenbrand
  2019-02-12 20:23   ` Richard Henderson
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 13/15] s390x/tcg: Implement rounding mode and XxC for LOAD ROUNDED David Hildenbrand
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:03 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. 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. Mangle/unmangle on a 8bit
basis, so this can be reused for other fields later on.

Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/fpu_helper.c | 126 +++++++++----------
 target/s390x/internal.h   |   6 +
 target/s390x/translate.c  | 254 ++++++++++++++++++++++++++++----------
 3 files changed, 260 insertions(+), 126 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 5136147da6..a0501b9ee5 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -407,239 +407,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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
 
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
 
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
 
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
 
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
 
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
 
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
 
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
 
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
 
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
 
     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, (m >> 8) & 1, 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 m)
 {
-    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
 
     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, (m >> 8) & 1, GETPC());
     return RET128(ret);
 }
 
diff --git a/target/s390x/internal.h b/target/s390x/internal.h
index 122fe037bc..b7bb46404f 100644
--- a/target/s390x/internal.h
+++ b/target/s390x/internal.h
@@ -176,6 +176,12 @@ static inline uint64_t wrap_address(CPUS390XState *env, uint64_t a)
     return a;
 }
 
+/* verify a bfp rounding mode as specified e.g. via m3 field */
+static inline bool valid_bfp_rounding_mode(uint8_t mode)
+{
+    return mode != 2 && mode <= 7;
+}
+
 /* CC optimization */
 
 /* Instead of computing the condition codes after each x86 instruction,
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index f58155f20c..e7cfc80131 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -1051,6 +1051,8 @@ struct DisasFields {
 /* This is the way fields are to be accessed out of DisasFields.  */
 #define have_field(S, F)  have_field1((S), FLD_O_##F)
 #define get_field(S, F)   get_field1((S), FLD_O_##F, FLD_C_##F)
+#define get_fields2(S, F1, F2) (get_field1((S), FLD_O_##F1, FLD_C_##F1) | \
+                                get_field1((S), FLD_O_##F2, FLD_C_##F2) << 8)
 
 static bool have_field1(const DisasFields *f, enum DisasFieldIndexO c)
 {
@@ -1760,158 +1762,266 @@ static DisasJumpType op_cxb(DisasContext *s, DisasOps *o)
 
 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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_cfeb(o->out, cpu_env, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_cfdb(o->out, cpu_env, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_cfxb(o->out, cpu_env, o->in1, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_cgeb(o->out, cpu_env, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_cgdb(o->out, cpu_env, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_cgxb(o->out, cpu_env, o->in1, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_clfeb(o->out, cpu_env, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_clfdb(o->out, cpu_env, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_clfxb(o->out, cpu_env, o->in1, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_clgeb(o->out, cpu_env, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_clgdb(o->out, cpu_env, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_clgxb(o->out, cpu_env, o->in1, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_cegb(o->out, cpu_env, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_cdgb(o->out, cpu_env, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_cxgb(o->out, cpu_env, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_celgb(o->out, cpu_env, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_cdlgb(o->out, cpu_env, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_cxlgb(o->out, cpu_env, o->in2, m);
+    tcg_temp_free_i32(m);
     return_low128(o->out2);
     return DISAS_NEXT;
 }
@@ -2390,26 +2500,44 @@ 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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_fieb(o->out, cpu_env, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_fidb(o->out, cpu_env, o->in2, m);
+    tcg_temp_free_i32(m);
     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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_fixb(o->out, cpu_env, o->in1, o->in2, m);
     return_low128(o->out2);
-    tcg_temp_free_i32(m3);
+    tcg_temp_free_i32(m);
     return DISAS_NEXT;
 }
 
-- 
2.17.2

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

* [Qemu-devel] [PATCH v1 13/15] s390x/tcg: Implement rounding mode and XxC for LOAD ROUNDED
  2019-02-12 11:02 [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
                   ` (12 preceding siblings ...)
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 12/15] s390x/tcg: Implement XxC and checks for most FP instructions David Hildenbrand
@ 2019-02-12 11:03 ` David Hildenbrand
  2019-02-12 20:25   ` Richard Henderson
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 14/15] s390x/tcg: Handle all rounding modes overwritten by BFP instructions David Hildenbrand
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:03 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.

Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/fpu_helper.c  | 22 ++++++++++++++++------
 target/s390x/helper.h      |  6 +++---
 target/s390x/insn-data.def |  6 +++---
 target/s390x/translate.c   | 30 +++++++++++++++++++++++++++---
 4 files changed, 49 insertions(+), 15 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index a0501b9ee5..8ef3d2f0e4 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -306,10 +306,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 m)
 {
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
+
+    s390_restore_bfp_rounding_mode(env, old_mode);
     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, (m >> 8) & 1, GETPC());
     return ret;
 }
 
@@ -330,18 +334,24 @@ 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 m)
 {
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
     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, (m >> 8) & 1, 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 m)
 {
+    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
     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, (m >> 8) & 1, GETPC());
     return ret;
 }
 
diff --git a/target/s390x/helper.h b/target/s390x/helper.h
index 179c942fc8..b92e5c5e40 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 7ef230029e..39117c0fd4 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 e7cfc80131..d1fbd0cde1 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -2806,19 +2806,43 @@ 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 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_ledb(o->out, cpu_env, o->in2, m);
+    tcg_temp_free_i32(m);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_ldxb(DisasContext *s, DisasOps *o)
 {
-    gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2);
+    TCGv_i32 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2, m);
+    tcg_temp_free_i32(m);
     return DISAS_NEXT;
 }
 
 static DisasJumpType op_lexb(DisasContext *s, DisasOps *o)
 {
-    gen_helper_lexb(o->out, cpu_env, o->in1, o->in2);
+    TCGv_i32 m;
+
+    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
+    gen_helper_lexb(o->out, cpu_env, o->in1, o->in2, m);
+    tcg_temp_free_i32(m);
     return DISAS_NEXT;
 }
 
-- 
2.17.2

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

* [Qemu-devel] [PATCH v1 14/15] s390x/tcg: Handle all rounding modes overwritten by BFP instructions
  2019-02-12 11:02 [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
                   ` (13 preceding siblings ...)
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 13/15] s390x/tcg: Implement rounding mode and XxC for LOAD ROUNDED David Hildenbrand
@ 2019-02-12 11:03 ` David Hildenbrand
  2019-02-12 20:29   ` Richard Henderson
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 15/15] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
  2019-02-12 11:04 ` [Qemu-devel] [PATCH v1] " David Hildenbrand
  16 siblings, 1 reply; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:03 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>
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 8ef3d2f0e4..748edcc0f0 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -385,14 +385,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:
@@ -407,6 +419,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] 38+ messages in thread

* [Qemu-devel] [PATCH v1 15/15] s390x: Add floating-point extension facility to "qemu" cpu model
  2019-02-12 11:02 [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
                   ` (14 preceding siblings ...)
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 14/15] s390x/tcg: Handle all rounding modes overwritten by BFP instructions David Hildenbrand
@ 2019-02-12 11:03 ` David Hildenbrand
  2019-02-12 11:04 ` [Qemu-devel] [PATCH v1] " David Hildenbrand
  16 siblings, 0 replies; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:03 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 19bb8ac7f8..02f6e9f475 100644
--- a/target/s390x/gen-features.c
+++ b/target/s390x/gen-features.c
@@ -593,6 +593,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] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model
  2019-02-12 11:02 [Qemu-devel] [PATCH v1] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
                   ` (15 preceding siblings ...)
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 15/15] s390x: Add floating-point extension facility to "qemu" cpu model David Hildenbrand
@ 2019-02-12 11:04 ` David Hildenbrand
  16 siblings, 0 replies; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 11:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-s390x, Thomas Huth, Halil Pasic, Christian Borntraeger,
	Janosch Frank, Cornelia Huck, Richard Henderson

On 12.02.19 12:02, David Hildenbrand wrote:
> 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>

This is the same patch as 15/15, refer to 0/15 as cover letter instead.

-- 

Thanks,

David / dhildenb

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

* Re: [Qemu-devel] [PATCH v1 01/15] s390x/tcg: Fix TEST DATA CLASS instructions
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 01/15] s390x/tcg: Fix TEST DATA CLASS instructions David Hildenbrand
@ 2019-02-12 18:01   ` Richard Henderson
  2019-02-12 18:17     ` David Hildenbrand
  0 siblings, 1 reply; 38+ messages in thread
From: Richard Henderson @ 2019-02-12 18:01 UTC (permalink / raw)
  To: David Hildenbrand, qemu-devel
  Cc: Thomas Huth, Janosch Frank, Cornelia Huck, Halil Pasic,
	Christian Borntraeger, qemu-s390x, Richard Henderson

On 2/12/19 3:02 AM, David Hildenbrand wrote:
> +static bool s390_tdc32(CPUS390XState *env, float32 f1, uint16_t dc_mask)
> +{
> +        const bool neg = float32_is_neg(f1);
> +        const bool zero = float32_is_zero(f1);
> +        const bool normal = float32_is_normal(f1);
> +        const bool denormal = float32_is_denormal(f1);
> +        const bool infinity = float32_is_infinity(f1);
> +        const bool quiet_nan = float32_is_quiet_nan(f1, &env->fpu_status);
> +        const bool sig_nan = float32_is_signaling_nan(f1, &env->fpu_status);
> +
> +        return (zero && test_dc_mask(dc_mask, 0, neg)) ||
> +               (normal && test_dc_mask(dc_mask, 2, neg)) ||
> +               (denormal && test_dc_mask(dc_mask, 4, neg)) ||
> +               (infinity && test_dc_mask(dc_mask, 6, neg)) ||
> +               (quiet_nan && test_dc_mask(dc_mask, 8, neg)) ||
> +               (sig_nan && test_dc_mask(dc_mask, 10, neg));
> +}
> +

This is doing more work than necessary, since any one fp value can only be one
of these.

I think it would be better to structure this like the riscv helper_fclass_*:

static inline uint32_t dcmask(int bit, bool neg)
{
    return 1 << (11 - bit - neg);
}

static uint32_t float32_dcmask(CPUS390XState *env, float32 f1)
{
    bool neg = float32_is_neg(f1);

    /* Sorted by most common cases.  */
    if (float32_is_normal(f1)) {
        return dc_mask(2, neg);
    } else if (float32_is_zero(f1)) {
        return dc_mask(0, neg);
    } else if (float32_is_zero_or_denormal(f1)) {
        /* denormal, since zero is eliminated */
        return dc_mask(4, neg);
    } else if (float32_is_infinity(f1)) {
        return dc_mask(6, neg);
    } else if (float64_is_quiet_nan(f1, &env->fpu_status)) {
        return dc_mask(8, neg);
    } else {
        /* signaling nan, as last remaining case */
        return dc_mask(10, neg);
    }
}

uint32_t HELPER(tceb)(CPUS390XState *env, uint64_t f1, uint64_t m2)
{
    return (m2 & float32_dcmask(env, f1)) != 0;
}

You may or may not wish to macro-ise float32_dcmask for the float type.


r~

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

* Re: [Qemu-devel] [PATCH v1 02/15] s390x/tcg: Fix rounding from float128 to uint64_t/uin32_t
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 02/15] s390x/tcg: Fix rounding from float128 to uint64_t/uin32_t David Hildenbrand
@ 2019-02-12 18:03   ` Richard Henderson
  0 siblings, 0 replies; 38+ messages in thread
From: Richard Henderson @ 2019-02-12 18:03 UTC (permalink / raw)
  To: David Hildenbrand, qemu-devel
  Cc: Thomas Huth, Janosch Frank, Cornelia Huck, Halil Pasic,
	Christian Borntraeger, qemu-s390x, Richard Henderson

On 2/12/19 3:02 AM, David Hildenbrand wrote:
> Let's use the proepr conversion functions now that we have them.

"proper"

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


r~

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

* Re: [Qemu-devel] [PATCH v1 03/15] s390x/tcg: Factor out conversion of softfloat exceptions
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 03/15] s390x/tcg: Factor out conversion of softfloat exceptions David Hildenbrand
@ 2019-02-12 18:05   ` Richard Henderson
  0 siblings, 0 replies; 38+ messages in thread
From: Richard Henderson @ 2019-02-12 18:05 UTC (permalink / raw)
  To: David Hildenbrand, qemu-devel
  Cc: Thomas Huth, Janosch Frank, Cornelia Huck, Halil Pasic,
	Christian Borntraeger, qemu-s390x, Richard Henderson

On 2/12/19 3:02 AM, David Hildenbrand wrote:
> 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.
> 
> 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(-)

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


r~

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

* Re: [Qemu-devel] [PATCH v1 04/15] s390x/tcg: Fix parts of IEEE exception handling
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 04/15] s390x/tcg: Fix parts of IEEE exception handling David Hildenbrand
@ 2019-02-12 18:13   ` Richard Henderson
  0 siblings, 0 replies; 38+ messages in thread
From: Richard Henderson @ 2019-02-12 18:13 UTC (permalink / raw)
  To: David Hildenbrand, qemu-devel
  Cc: Thomas Huth, Janosch Frank, Cornelia Huck, Halil Pasic,
	Christian Borntraeger, qemu-s390x, Richard Henderson

On 2/12/19 3:02 AM, David Hildenbrand wrote:
> 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
> 
> Signed-off-by: David Hildenbrand <david@redhat.com>
> ---
>  target/s390x/fpu_helper.c | 38 ++++++++++++++++++++++++++++++++------
>  1 file changed, 32 insertions(+), 6 deletions(-)

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


r~

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

* Re: [Qemu-devel] [PATCH v1 05/15] s390x/tcg: Hide IEEE underflows in some scenarios
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 05/15] s390x/tcg: Hide IEEE underflows in some scenarios David Hildenbrand
@ 2019-02-12 18:14   ` Richard Henderson
  0 siblings, 0 replies; 38+ messages in thread
From: Richard Henderson @ 2019-02-12 18:14 UTC (permalink / raw)
  To: David Hildenbrand, qemu-devel
  Cc: Thomas Huth, Janosch Frank, Cornelia Huck, Halil Pasic,
	Christian Borntraeger, qemu-s390x, Richard Henderson

On 2/12/19 3:02 AM, David Hildenbrand wrote:
> 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.
> 
> Signed-off-by: David Hildenbrand <david@redhat.com>
> ---
>  target/s390x/fpu_helper.c | 13 +++++++++++++
>  1 file changed, 13 insertions(+)

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


r~

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

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

On 12.02.19 19:01, Richard Henderson wrote:
> On 2/12/19 3:02 AM, David Hildenbrand wrote:
>> +static bool s390_tdc32(CPUS390XState *env, float32 f1, uint16_t dc_mask)
>> +{
>> +        const bool neg = float32_is_neg(f1);
>> +        const bool zero = float32_is_zero(f1);
>> +        const bool normal = float32_is_normal(f1);
>> +        const bool denormal = float32_is_denormal(f1);
>> +        const bool infinity = float32_is_infinity(f1);
>> +        const bool quiet_nan = float32_is_quiet_nan(f1, &env->fpu_status);
>> +        const bool sig_nan = float32_is_signaling_nan(f1, &env->fpu_status);
>> +
>> +        return (zero && test_dc_mask(dc_mask, 0, neg)) ||
>> +               (normal && test_dc_mask(dc_mask, 2, neg)) ||
>> +               (denormal && test_dc_mask(dc_mask, 4, neg)) ||
>> +               (infinity && test_dc_mask(dc_mask, 6, neg)) ||
>> +               (quiet_nan && test_dc_mask(dc_mask, 8, neg)) ||
>> +               (sig_nan && test_dc_mask(dc_mask, 10, neg));
>> +}
>> +
> 
> This is doing more work than necessary, since any one fp value can only be one
> of these.
> 
> I think it would be better to structure this like the riscv helper_fclass_*:
> 
> static inline uint32_t dcmask(int bit, bool neg)
> {
>     return 1 << (11 - bit - neg);
> }
> 
> static uint32_t float32_dcmask(CPUS390XState *env, float32 f1)
> {
>     bool neg = float32_is_neg(f1);
> 
>     /* Sorted by most common cases.  */
>     if (float32_is_normal(f1)) {
>         return dc_mask(2, neg);
>     } else if (float32_is_zero(f1)) {
>         return dc_mask(0, neg);
>     } else if (float32_is_zero_or_denormal(f1)) {
>         /* denormal, since zero is eliminated */
>         return dc_mask(4, neg);
>     } else if (float32_is_infinity(f1)) {
>         return dc_mask(6, neg);
>     } else if (float64_is_quiet_nan(f1, &env->fpu_status)) {
>         return dc_mask(8, neg);
>     } else {
>         /* signaling nan, as last remaining case */
>         return dc_mask(10, neg);
>     }
> }
> 
> uint32_t HELPER(tceb)(CPUS390XState *env, uint64_t f1, uint64_t m2)
> {
>     return (m2 & float32_dcmask(env, f1)) != 0;
> }
> 
> You may or may not wish to macro-ise float32_dcmask for the float type.
> 
> 
> r~
> 

Indeed, makes sense! Also thought about macros, but I guess the huge
pile of code for vector instruction support I have lying around make me
lazy :)

Thanks!

-- 

Thanks,

David / dhildenb

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

* Re: [Qemu-devel] [PATCH v1 06/15] s390x/tcg: Refactor SET FPC AND SIGNAL handling
  2019-02-12 11:02 ` [Qemu-devel] [PATCH v1 06/15] s390x/tcg: Refactor SET FPC AND SIGNAL handling David Hildenbrand
@ 2019-02-12 18:55   ` Richard Henderson
  0 siblings, 0 replies; 38+ messages in thread
From: Richard Henderson @ 2019-02-12 18:55 UTC (permalink / raw)
  To: David Hildenbrand, qemu-devel
  Cc: Thomas Huth, Janosch Frank, Cornelia Huck, Halil Pasic,
	Christian Borntraeger, qemu-s390x, Richard Henderson

On 2/12/19 3:02 AM, David Hildenbrand wrote:
> We can directly work on the uint64_t value, no need for a temporary
> uint32_t value.
> 
> Also cleanup and shorten the comments.
> 
> Signed-off-by: David Hildenbrand <david@redhat.com>
> ---
>  target/s390x/fpu_helper.c | 22 ++++++++++++----------
>  1 file changed, 12 insertions(+), 10 deletions(-)

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


r~

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

* Re: [Qemu-devel] [PATCH v1 07/15] s390x/tcg: Fix simulated-IEEE exceptions
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 07/15] s390x/tcg: Fix simulated-IEEE exceptions David Hildenbrand
@ 2019-02-12 18:56   ` Richard Henderson
  0 siblings, 0 replies; 38+ messages in thread
From: Richard Henderson @ 2019-02-12 18:56 UTC (permalink / raw)
  To: David Hildenbrand, qemu-devel
  Cc: Thomas Huth, Janosch Frank, Cornelia Huck, Halil Pasic,
	Christian Borntraeger, qemu-s390x, Richard Henderson

On 2/12/19 3:03 AM, David Hildenbrand wrote:
> 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
> 
> Signed-off-by: David Hildenbrand <david@redhat.com>
> ---
>  target/s390x/fpu_helper.c | 13 +++++++++++++
>  1 file changed, 13 insertions(+)

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


r~

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

* Re: [Qemu-devel] [PATCH v1 08/15] s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 08/15] s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes David Hildenbrand
@ 2019-02-12 19:07   ` Richard Henderson
  2019-02-12 19:32     ` David Hildenbrand
  0 siblings, 1 reply; 38+ messages in thread
From: Richard Henderson @ 2019-02-12 19:07 UTC (permalink / raw)
  To: David Hildenbrand, qemu-devel
  Cc: Thomas Huth, Janosch Frank, Cornelia Huck, Halil Pasic,
	Christian Borntraeger, qemu-s390x, Richard Henderson

On 2/12/19 3:03 AM, David Hildenbrand wrote:
> 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.


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

> +    /*
> +     * FIXME: we actually want something like round_to_odd, but that does not
> +     * support all data types yet.
> +     */
> +    float_round_to_zero,

Yes, you want round_to_odd.  I suppose that's not valid for float128 right now?


r~

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

* Re: [Qemu-devel] [PATCH v1 08/15] s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes
  2019-02-12 19:07   ` Richard Henderson
@ 2019-02-12 19:32     ` David Hildenbrand
  2019-02-12 19:56       ` Richard Henderson
  0 siblings, 1 reply; 38+ messages in thread
From: David Hildenbrand @ 2019-02-12 19:32 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: Thomas Huth, Janosch Frank, Cornelia Huck, Halil Pasic,
	Christian Borntraeger, qemu-s390x, Richard Henderson

On 12.02.19 20:07, Richard Henderson wrote:
> On 2/12/19 3:03 AM, David Hildenbrand wrote:
>> 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.
> 
> 
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> 
>> +    /*
>> +     * FIXME: we actually want something like round_to_odd, but that does not
>> +     * support all data types yet.
>> +     */
>> +    float_round_to_zero,
> 
> Yes, you want round_to_odd.  I suppose that's not valid for float128 right now?

roundAndPackFloat64()

as well as

roundAndPackFloat128()

support it.

It's not implemented for round_canonical(), round_to_int(),
roundAndPackInt32(), roundAndPackInt64(), roundAndPackUint64(),
roundAndPackFloat32() (and roundAndPackFloatx80()).

I assume at least 32bit is missing. I can't judge if the other functions
are relevant (x80 clearly not).

> 
> 
> r~
> 


-- 

Thanks,

David / dhildenb

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

* Re: [Qemu-devel] [PATCH v1 08/15] s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes
  2019-02-12 19:32     ` David Hildenbrand
@ 2019-02-12 19:56       ` Richard Henderson
  2019-02-13 12:49         ` David Hildenbrand
  0 siblings, 1 reply; 38+ messages in thread
From: Richard Henderson @ 2019-02-12 19:56 UTC (permalink / raw)
  To: David Hildenbrand, Richard Henderson, qemu-devel
  Cc: Thomas Huth, Janosch Frank, Cornelia Huck, Halil Pasic,
	Christian Borntraeger, qemu-s390x, Alex Bennée

On 2/12/19 11:32 AM, David Hildenbrand wrote:
>> Yes, you want round_to_odd.  I suppose that's not valid for float128 right now?
> 
> roundAndPackFloat64()
> 
> as well as
> 
> roundAndPackFloat128()
> 
> support it.
> 
> It's not implemented for round_canonical(), round_to_int(),

These two are easy.  I think Alex and I didn't implement it in the float32/64
rewrite because we didn't have a user.  Now we will.

> roundAndPackInt32(), roundAndPackInt64(), roundAndPackUint64(),
> roundAndPackFloat32()

Right, these would be from the float128 side.  It shouldn't be too hard...


r~

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

* Re: [Qemu-devel] [PATCH v1 09/15] s390x/tcg: Check for exceptions in SET BFP ROUNDING MODE
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 09/15] s390x/tcg: Check for exceptions in SET BFP ROUNDING MODE David Hildenbrand
@ 2019-02-12 19:58   ` Richard Henderson
  0 siblings, 0 replies; 38+ messages in thread
From: Richard Henderson @ 2019-02-12 19:58 UTC (permalink / raw)
  To: David Hildenbrand, qemu-devel
  Cc: Thomas Huth, Janosch Frank, Cornelia Huck, Halil Pasic,
	Christian Borntraeger, qemu-s390x, Richard Henderson

On 2/12/19 3:03 AM, David Hildenbrand wrote:
> 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.
> 
> Signed-off-by: David Hildenbrand <david@redhat.com>
> ---

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


r~

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

* Re: [Qemu-devel] [PATCH v1 10/15] s390x/tcg: Refactor saving/restoring the bfp rounding mode
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 10/15] s390x/tcg: Refactor saving/restoring the bfp rounding mode David Hildenbrand
@ 2019-02-12 20:03   ` Richard Henderson
  0 siblings, 0 replies; 38+ messages in thread
From: Richard Henderson @ 2019-02-12 20:03 UTC (permalink / raw)
  To: David Hildenbrand, qemu-devel
  Cc: Thomas Huth, Janosch Frank, Cornelia Huck, Halil Pasic,
	Christian Borntraeger, qemu-s390x, Richard Henderson

On 2/12/19 3:03 AM, David Hildenbrand wrote:
> 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.
> 
> Signed-off-by: David Hildenbrand <david@redhat.com>
> ---

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


r~

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

* Re: [Qemu-devel] [PATCH v1 11/15] s390x/tcg: Prepare for IEEE-inexact-exception control (XxC)
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 11/15] s390x/tcg: Prepare for IEEE-inexact-exception control (XxC) David Hildenbrand
@ 2019-02-12 20:07   ` Richard Henderson
  0 siblings, 0 replies; 38+ messages in thread
From: Richard Henderson @ 2019-02-12 20:07 UTC (permalink / raw)
  To: David Hildenbrand, qemu-devel
  Cc: Thomas Huth, Janosch Frank, Cornelia Huck, Halil Pasic,
	Christian Borntraeger, qemu-s390x, Richard Henderson

On 2/12/19 3:03 AM, David Hildenbrand wrote:
> 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.
> 
> Signed-off-by: David Hildenbrand <david@redhat.com>
> ---
>  target/s390x/fpu_helper.c | 112 +++++++++++++++++++-------------------
>  1 file changed, 56 insertions(+), 56 deletions(-)

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


r~

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

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

On 2/12/19 3:03 AM, David Hildenbrand wrote:
> -uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
> +uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m)
>  {
> -    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
> +    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
>  
>      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, (m >> 8) & 1, GETPC());
>      return ret;
>  }

It might be helpful to have inlines for these extractions.  E.g

static inline uint32_t round_from_m34(uint32_t m);
static inline bool xxc_from_m34(uint32_t m);

>  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 m;
> +
> +    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
> +        gen_program_exception(s, PGM_SPECIFICATION);
> +        return DISAS_NORETURN;
> +    }
> +    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
> +    gen_helper_cfeb(o->out, cpu_env, o->in2, m);
> +    tcg_temp_free_i32(m);
>      gen_set_cc_nz_f32(s, o->in2);
>      return DISAS_NEXT;
>  }

The m4 field does not exist unless fp extension facility is enabled.  You
should ignore the field if not installed.

It would be good to split this out to a helper, since there are so many copies.
 E.g.

static bool extract_m3_m4(DisasContext *s, uint32_t *m34)
{
    int m3 = get_field(s->fields, m3);
    int m4 = get_field(s->fields, m4);

    if (!valid_bfp_rounding_mode(m3)) {
        gen_program_exception(s, PGM_SPECIFICATION);
        return false;
    }
    if (feature) {
        return deposit32(m3, 8, 1, m4);
    }
    return m3;
}

Hmm..  Except that I see we don't have enough stored in DisasContext to allow
you to look up the proper feature.  So perhaps just a FIXME for now?


r~

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

* Re: [Qemu-devel] [PATCH v1 13/15] s390x/tcg: Implement rounding mode and XxC for LOAD ROUNDED
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 13/15] s390x/tcg: Implement rounding mode and XxC for LOAD ROUNDED David Hildenbrand
@ 2019-02-12 20:25   ` Richard Henderson
  0 siblings, 0 replies; 38+ messages in thread
From: Richard Henderson @ 2019-02-12 20:25 UTC (permalink / raw)
  To: David Hildenbrand, qemu-devel
  Cc: Thomas Huth, Janosch Frank, Cornelia Huck, Halil Pasic,
	Christian Borntraeger, qemu-s390x, Richard Henderson

On 2/12/19 3:03 AM, David Hildenbrand wrote:
> 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.
> 
> Signed-off-by: David Hildenbrand <david@redhat.com>
> ---

Modulo the comments for patch 12,

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


r~

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

* Re: [Qemu-devel] [PATCH v1 14/15] s390x/tcg: Handle all rounding modes overwritten by BFP instructions
  2019-02-12 11:03 ` [Qemu-devel] [PATCH v1 14/15] s390x/tcg: Handle all rounding modes overwritten by BFP instructions David Hildenbrand
@ 2019-02-12 20:29   ` Richard Henderson
  0 siblings, 0 replies; 38+ messages in thread
From: Richard Henderson @ 2019-02-12 20:29 UTC (permalink / raw)
  To: David Hildenbrand, qemu-devel
  Cc: Peter Maydell, Thomas Huth, Janosch Frank, Cornelia Huck,
	Halil Pasic, Christian Borntraeger, qemu-s390x,
	Richard Henderson

On 2/12/19 3:03 AM, David Hildenbrand wrote:
> 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 ;)

Yep, that's right.

> 
> 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>
> Signed-off-by: David Hildenbrand <david@redhat.com>
> ---

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


r~

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

* Re: [Qemu-devel] [PATCH v1 08/15] s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes
  2019-02-12 19:56       ` Richard Henderson
@ 2019-02-13 12:49         ` David Hildenbrand
  2019-02-13 19:11           ` Richard Henderson
  0 siblings, 1 reply; 38+ messages in thread
From: David Hildenbrand @ 2019-02-13 12:49 UTC (permalink / raw)
  To: Richard Henderson, Richard Henderson, qemu-devel
  Cc: Thomas Huth, Janosch Frank, Cornelia Huck, Halil Pasic,
	Christian Borntraeger, qemu-s390x, Alex Bennée

On 12.02.19 20:56, Richard Henderson wrote:
> On 2/12/19 11:32 AM, David Hildenbrand wrote:
>>> Yes, you want round_to_odd.  I suppose that's not valid for float128 right now?
>>
>> roundAndPackFloat64()
>>
>> as well as
>>
>> roundAndPackFloat128()
>>
>> support it.
>>
>> It's not implemented for round_canonical(), round_to_int(),
> 
> These two are easy.  I think Alex and I didn't implement it in the float32/64
> rewrite because we didn't have a user.  Now we will.
> 
>> roundAndPackInt32(), roundAndPackInt64(), roundAndPackUint64(),
>> roundAndPackFloat32()
> 
> Right, these would be from the float128 side.  It shouldn't be too hard...
> 
> 
> r~
> 

Sounds like you are volunteering to implement them? ;)

-- 

Thanks,

David / dhildenb

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

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

On 12.02.19 21:23, Richard Henderson wrote:
> On 2/12/19 3:03 AM, David Hildenbrand wrote:
>> -uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
>> +uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m)
>>  {
>> -    int old_mode = s390_swap_bfp_rounding_mode(env, m3);
>> +    int old_mode = s390_swap_bfp_rounding_mode(env, m & 0xf);
>>  
>>      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, (m >> 8) & 1, GETPC());
>>      return ret;
>>  }
> 
> It might be helpful to have inlines for these extractions.  E.g
> 
> static inline uint32_t round_from_m34(uint32_t m);
> static inline bool xxc_from_m34(uint32_t m);
> 
>>  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 m;
>> +
>> +    if (!valid_bfp_rounding_mode(get_field(s->fields, m3))) {
>> +        gen_program_exception(s, PGM_SPECIFICATION);
>> +        return DISAS_NORETURN;
>> +    }
>> +    m = tcg_const_i32(get_fields2(s->fields, m3, m4));
>> +    gen_helper_cfeb(o->out, cpu_env, o->in2, m);
>> +    tcg_temp_free_i32(m);
>>      gen_set_cc_nz_f32(s, o->in2);
>>      return DISAS_NEXT;
>>  }
> 
> The m4 field does not exist unless fp extension facility is enabled.  You
> should ignore the field if not installed.

As all users I know already take the floating-point extension facility
for granted, I wanted to avoid faking it away for now. Old
implementations set all fields to zero either way. But I'll take another
shot if it can be easily added without uglifying the code.

> 
> It would be good to split this out to a helper, since there are so many copies.
>  E.g.
> 
> static bool extract_m3_m4(DisasContext *s, uint32_t *m34)
> {
>     int m3 = get_field(s->fields, m3);
>     int m4 = get_field(s->fields, m4);
> 
>     if (!valid_bfp_rounding_mode(m3)) {
>         gen_program_exception(s, PGM_SPECIFICATION);
>         return false;
>     }
>     if (feature) {
>         return deposit32(m3, 8, 1, m4);
>     }
>     return m3;
> }

Okay, I'll play with it to see what the end result would look like.

> 
> Hmm..  Except that I see we don't have enough stored in DisasContext to allow
> you to look up the proper feature.  So perhaps just a FIXME for now?

We do have s390_has_feat(S390_FEAT_FLOATING_POINT_EXT)

> 
> 
> r~
> 


-- 

Thanks,

David / dhildenb

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

* Re: [Qemu-devel] [PATCH v1 08/15] s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes
  2019-02-13 12:49         ` David Hildenbrand
@ 2019-02-13 19:11           ` Richard Henderson
  0 siblings, 0 replies; 38+ messages in thread
From: Richard Henderson @ 2019-02-13 19:11 UTC (permalink / raw)
  To: David Hildenbrand, Richard Henderson, qemu-devel
  Cc: Thomas Huth, Janosch Frank, Cornelia Huck, Halil Pasic,
	Christian Borntraeger, qemu-s390x, Alex Bennée

On 2/13/19 4:49 AM, David Hildenbrand wrote:
>>> It's not implemented for round_canonical(), round_to_int(),
>>
>> These two are easy.  I think Alex and I didn't implement it in the float32/64
>> rewrite because we didn't have a user.  Now we will.
>>
>>> roundAndPackInt32(), roundAndPackInt64(), roundAndPackUint64(),
>>> roundAndPackFloat32()
>>
>> Right, these would be from the float128 side.  It shouldn't be too hard...
>>
>>
>> r~
>>
> 
> Sounds like you are volunteering to implement them? ;)

Yep.


r~

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

end of thread, other threads:[~2019-02-13 19:12 UTC | newest]

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