* [Qemu-devel] [PULL 00/27] s390x updates
@ 2019-03-04 12:01 Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 01/27] s390x: Use cpu_to_be64 in SIGP STORE ADDITIONAL STATUS Cornelia Huck
` (27 more replies)
0 siblings, 28 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:01 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Cornelia Huck
The following changes since commit 20b084c4b1401b7f8fbc385649d48c67b6f43d44:
Merge remote-tracking branch 'remotes/cminyard/tags/i2c-for-release-20190228' into staging (2019-03-01 11:20:49 +0000)
are available in the Git repository at:
https://github.com/cohuck/qemu tags/s390x-20190304
for you to fetch changes up to df192fbc517a0954dda644282e52ba943e22ec18:
s390x: Add floating-point extension facility to "qemu" cpu model (2019-03-04 11:49:31 +0100)
----------------------------------------------------------------
s390x updates:
- tcg: support the floating-point extension facility
- vfio-ap: support hot(un)plug of vfio-ap device
- fixes + cleanups
----------------------------------------------------------------
David Hildenbrand (25):
s390x: Use cpu_to_be64 in SIGP STORE ADDITIONAL STATUS
s390x: use a QEMU-style typedef + name for SIGP save area struct
s390x/tcg: Save vregs to extended mchk save area
s390x/tcg: RXE has an optional M3 field
s390x/tcg: Simplify disassembler operands initialization
s390x/tcg: Clarify terminology in vec_reg_offset()
s390x/tcg: Factor out vec_full_reg_offset()
s390x/tcg: Factor out gen_addi_and_wrap_i64() from get_address()
s390x/tcg: Implement LOAD LENGTHENED short HFP to long HFP
s390x/tcg: Implement LOAD COUNT TO BLOCK BOUNDARY
s390x/tcg: Fix TEST DATA CLASS instructions
s390x/tcg: Fix rounding from float128 to uint64_t/uint32_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
Tony Krowiak (2):
s390x/vfio-ap: Implement hot plug/unplug of vfio-ap device
s390x/vfio-ap: document hot plug/unplug of vfio-ap device
docs/vfio-ap.txt | 61 +++-
hw/s390x/ap-bridge.c | 12 +-
hw/vfio/ap.c | 2 +-
target/s390x/cc_helper.c | 8 +
target/s390x/excp_helper.c | 46 ++-
target/s390x/fpu_helper.c | 541 +++++++++++++++++++++--------------
target/s390x/gen-features.c | 5 +
target/s390x/helper.c | 40 ++-
target/s390x/helper.h | 9 +-
target/s390x/insn-data.def | 16 +-
target/s390x/insn-format.def | 2 +-
target/s390x/internal.h | 14 +-
target/s390x/translate.c | 409 ++++++++++++++++++--------
13 files changed, 792 insertions(+), 373 deletions(-)
--
2.17.2
^ permalink raw reply [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 01/27] s390x: Use cpu_to_be64 in SIGP STORE ADDITIONAL STATUS
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
@ 2019-03-04 12:01 ` Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 02/27] s390x: use a QEMU-style typedef + name for SIGP save area struct Cornelia Huck
` (26 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:01 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
As we will support vector instructions soon, and vector registers are
stored in 64bit host chunks, let's use cpu_to_be64. Same applies to the
guarded storage control block.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190222081153.14206-2-david@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
target/s390x/helper.c | 31 +++++++++++++++++++++----------
1 file changed, 21 insertions(+), 10 deletions(-)
diff --git a/target/s390x/helper.c b/target/s390x/helper.c
index 3d74836a8394..f3fcf96482ef 100644
--- a/target/s390x/helper.c
+++ b/target/s390x/helper.c
@@ -272,32 +272,43 @@ int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch)
return 0;
}
-#define ADTL_GS_OFFSET 1024 /* offset of GS data in adtl save area */
+typedef struct SigpAdtlSaveArea {
+ uint64_t vregs[32][2]; /* 0x0000 */
+ uint8_t pad_0x0200[0x0400 - 0x0200]; /* 0x0200 */
+ uint64_t gscb[4]; /* 0x0400 */
+ uint8_t pad_0x0420[0x1000 - 0x0420]; /* 0x0420 */
+} SigpAdtlSaveArea;
+QEMU_BUILD_BUG_ON(sizeof(SigpAdtlSaveArea) != 4096);
+
#define ADTL_GS_MIN_SIZE 2048 /* minimal size of adtl save area for GS */
int s390_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len)
{
+ SigpAdtlSaveArea *sa;
hwaddr save = len;
- void *mem;
+ int i;
- mem = cpu_physical_memory_map(addr, &save, 1);
- if (!mem) {
+ sa = cpu_physical_memory_map(addr, &save, 1);
+ if (!sa) {
return -EFAULT;
}
if (save != len) {
- cpu_physical_memory_unmap(mem, len, 1, 0);
+ cpu_physical_memory_unmap(sa, len, 1, 0);
return -EFAULT;
}
- /* FIXME: as soon as TCG supports these features, convert cpu->be */
if (s390_has_feat(S390_FEAT_VECTOR)) {
- memcpy(mem, &cpu->env.vregs, 512);
+ for (i = 0; i < 32; i++) {
+ sa->vregs[i][0] = cpu_to_be64(cpu->env.vregs[i][0].ll);
+ sa->vregs[i][1] = cpu_to_be64(cpu->env.vregs[i][1].ll);
+ }
}
if (s390_has_feat(S390_FEAT_GUARDED_STORAGE) && len >= ADTL_GS_MIN_SIZE) {
- memcpy(mem + ADTL_GS_OFFSET, &cpu->env.gscb, 32);
+ for (i = 0; i < 4; i++) {
+ sa->gscb[i] = cpu_to_be64(cpu->env.gscb[i]);
+ }
}
- cpu_physical_memory_unmap(mem, len, 1, len);
-
+ cpu_physical_memory_unmap(sa, len, 1, len);
return 0;
}
#endif /* CONFIG_USER_ONLY */
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 02/27] s390x: use a QEMU-style typedef + name for SIGP save area struct
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 01/27] s390x: Use cpu_to_be64 in SIGP STORE ADDITIONAL STATUS Cornelia Huck
@ 2019-03-04 12:01 ` Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 03/27] s390x/tcg: Save vregs to extended mchk save area Cornelia Huck
` (25 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:01 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
Convert this to QEMU style.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190222081153.14206-3-david@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
target/s390x/helper.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/target/s390x/helper.c b/target/s390x/helper.c
index f3fcf96482ef..a7edd5df7d59 100644
--- a/target/s390x/helper.c
+++ b/target/s390x/helper.c
@@ -211,7 +211,7 @@ void s390_cpu_recompute_watchpoints(CPUState *cs)
}
}
-struct sigp_save_area {
+typedef struct SigpSaveArea {
uint64_t fprs[16]; /* 0x0000 */
uint64_t grs[16]; /* 0x0080 */
PSW psw; /* 0x0100 */
@@ -225,13 +225,13 @@ struct sigp_save_area {
uint8_t pad_0x0138[0x0140 - 0x0138]; /* 0x0138 */
uint32_t ars[16]; /* 0x0140 */
uint64_t crs[16]; /* 0x0384 */
-};
-QEMU_BUILD_BUG_ON(sizeof(struct sigp_save_area) != 512);
+} SigpSaveArea;
+QEMU_BUILD_BUG_ON(sizeof(SigpSaveArea) != 512);
int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch)
{
static const uint8_t ar_id = 1;
- struct sigp_save_area *sa;
+ SigpSaveArea *sa;
hwaddr len = sizeof(*sa);
int i;
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 03/27] s390x/tcg: Save vregs to extended mchk save area
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 01/27] s390x: Use cpu_to_be64 in SIGP STORE ADDITIONAL STATUS Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 02/27] s390x: use a QEMU-style typedef + name for SIGP save area struct Cornelia Huck
@ 2019-03-04 12:01 ` Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 04/27] s390x/vfio-ap: Implement hot plug/unplug of vfio-ap device Cornelia Huck
` (24 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:01 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
If we have vector registers and the designation is not zero, we have
to try to write the vector registers. If the designation is zero or
if storing fails, we must not indicate validity. s390_build_validity_mcic()
automatically already sets validity if the vector instruction facility
is installed.
As long as we don't support the guarded-storage facility, the alignment
and size of the area is always 1024 bytes.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190222081153.14206-4-david@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
target/s390x/excp_helper.c | 46 ++++++++++++++++++++++++++++++++++++--
target/s390x/internal.h | 4 +++-
2 files changed, 47 insertions(+), 3 deletions(-)
diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c
index a758649f47fe..f84bfb1284b4 100644
--- a/target/s390x/excp_helper.c
+++ b/target/s390x/excp_helper.c
@@ -347,10 +347,41 @@ static void do_io_interrupt(CPUS390XState *env)
load_psw(env, mask, addr);
}
+typedef struct MchkExtSaveArea {
+ uint64_t vregs[32][2]; /* 0x0000 */
+ uint8_t pad_0x0200[0x0400 - 0x0200]; /* 0x0200 */
+} MchkExtSaveArea;
+QEMU_BUILD_BUG_ON(sizeof(MchkExtSaveArea) != 1024);
+
+static int mchk_store_vregs(CPUS390XState *env, uint64_t mcesao)
+{
+ hwaddr len = sizeof(MchkExtSaveArea);
+ MchkExtSaveArea *sa;
+ int i;
+
+ sa = cpu_physical_memory_map(mcesao, &len, 1);
+ if (!sa) {
+ return -EFAULT;
+ }
+ if (len != sizeof(MchkExtSaveArea)) {
+ cpu_physical_memory_unmap(sa, len, 1, 0);
+ return -EFAULT;
+ }
+
+ for (i = 0; i < 32; i++) {
+ sa->vregs[i][0] = cpu_to_be64(env->vregs[i][0].ll);
+ sa->vregs[i][1] = cpu_to_be64(env->vregs[i][1].ll);
+ }
+
+ cpu_physical_memory_unmap(sa, len, 1, len);
+ return 0;
+}
+
static void do_mchk_interrupt(CPUS390XState *env)
{
QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
- uint64_t mask, addr;
+ uint64_t mcic = s390_build_validity_mcic() | MCIC_SC_CP;
+ uint64_t mask, addr, mcesao = 0;
LowCore *lowcore;
int i;
@@ -362,6 +393,17 @@ static void do_mchk_interrupt(CPUS390XState *env)
lowcore = cpu_map_lowcore(env);
+ /* extended save area */
+ if (mcic & MCIC_VB_VR) {
+ /* length and alignment is 1024 bytes */
+ mcesao = be64_to_cpu(lowcore->mcesad) & ~0x3ffull;
+ }
+
+ /* try to store vector registers */
+ if (!mcesao || mchk_store_vregs(env, mcesao)) {
+ mcic &= ~MCIC_VB_VR;
+ }
+
/* we are always in z/Architecture mode */
lowcore->ar_access_id = 1;
@@ -377,7 +419,7 @@ static void do_mchk_interrupt(CPUS390XState *env)
lowcore->cpu_timer_save_area = cpu_to_be64(env->cputm);
lowcore->clock_comp_save_area = cpu_to_be64(env->ckc >> 8);
- lowcore->mcic = cpu_to_be64(s390_build_validity_mcic() | MCIC_SC_CP);
+ lowcore->mcic = cpu_to_be64(mcic);
lowcore->mcck_old_psw.mask = cpu_to_be64(get_psw_mask(env));
lowcore->mcck_old_psw.addr = cpu_to_be64(env->psw.addr);
mask = be64_to_cpu(lowcore->mcck_new_psw.mask);
diff --git a/target/s390x/internal.h b/target/s390x/internal.h
index f2a771e2b444..b2966a3adcb8 100644
--- a/target/s390x/internal.h
+++ b/target/s390x/internal.h
@@ -101,7 +101,9 @@ typedef struct LowCore {
/* whether the kernel died with panic() or not */
uint32_t panic_magic; /* 0xe00 */
- uint8_t pad13[0x11b8 - 0xe04]; /* 0xe04 */
+ uint8_t pad13[0x11b0 - 0xe04]; /* 0xe04 */
+
+ uint64_t mcesad; /* 0x11B0 */
/* 64 bit extparam used for pfault, diag 250 etc */
uint64_t ext_params2; /* 0x11B8 */
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 04/27] s390x/vfio-ap: Implement hot plug/unplug of vfio-ap device
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (2 preceding siblings ...)
2019-03-04 12:01 ` [Qemu-devel] [PULL 03/27] s390x/tcg: Save vregs to extended mchk save area Cornelia Huck
@ 2019-03-04 12:01 ` Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 05/27] s390x/vfio-ap: document " Cornelia Huck
` (23 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:01 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Tony Krowiak, Cornelia Huck
From: Tony Krowiak <akrowiak@linux.ibm.com>
Introduces hot plug/unplug support for the vfio-ap device.
To hot plug a vfio-ap device using the QEMU device_add command:
(qemu) device_add vfio-ap,sysfsdev=$path-to-mdev
Where $path-to-mdev is the absolute path to the mediated matrix device
to which AP resources to be used by the guest have been assigned.
A vfio-ap device can be hot plugged only if:
1. A vfio-ap device has not been attached to the virtual machine's ap-bus
via the QEMU command line or a prior hot plug action.
2. The guest was started with the CPU model feature for AP enabled
(e.g., -cpu host,ap=on)
To hot unplug a vfio-ap device using the QEMU device_del command:
(qemu) device_del vfio-ap,sysfsdev=$path-to-mdev
Where $path-to-mdev is the absolute path to the mediated matrix device
specified when the vfio-ap device was attached to the virtual machine's
ap-bus.
A vfio-ap device can be hot unplugged only if:
1. A vfio-ap device has been attached to the virtual machine's ap-bus
via the QEMU command line or a prior hot plug action.
2. The guest was started with the CPU model feature for AP enabled
(e.g., -cpu host,ap=on)
Please note that a hot plug handler is not necessary for the vfio-ap device
because the AP matrix configuration for the guest is performed by the
kernel device driver when the vfio-ap device is realized. The vfio-ap device
represents a VFIO mediated device created in the host sysfs for use by a guest.
The mdev device is configured with an AP matrix (i.e., adapters and domains) via
its sysfs attribute interfaces prior to starting the guest or plugging a vfio-ap
device in. When the device is realized, a file descriptor is opened on the mdev
device which results in a callback to the vfio_ap kernel device driver. The
device driver then configures the AP matrix in the guest's SIE state description
from the AP matrix assigned via the mdev device's sysfs interfaces. The AP
devices will be created for the guest when the AP bus running on the guest
subsequently performs its periodic scan for AP devices.
The qdev_simple_device_unplug_cb() callback function is used for the same
reaons; namely, the vfio_ap kernel device driver will perform the AP resource
de-configuration for the guest when the vfio-ap device is unplugged. When the
vfio-ap device is unrealized, the mdev device file descriptor is closed which
results in a callback to the vfio_ap kernel device driver. The device driver
then clears the AP matrix configuration in the guest's SIE state description
and resets all of the affected queues. The AP devices created for the guest
will be removed when the AP bus running on the guest subsequently performs
its periodic scan and finds there are no longer any AP resources assigned to the
guest.
Signed-off-by: Tony Krowiak <akrowiak@linux.ibm.com>
Reviewed-by: Pierre Morel <pmorel@linux.ibm.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Halil Pasic <pasic@linux.ibm.com>
Tested-by: Pierre Morel <pmorel@linux.ibm.com>
Message-Id: <1550519397-25359-2-git-send-email-akrowiak@linux.ibm.com>
[CH: adapt to changed qbus_set_hotplug_handler() signature]
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
hw/s390x/ap-bridge.c | 12 +++++++++++-
hw/vfio/ap.c | 2 +-
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/hw/s390x/ap-bridge.c b/hw/s390x/ap-bridge.c
index 3795d30dd7c9..75ad0a66b9e2 100644
--- a/hw/s390x/ap-bridge.c
+++ b/hw/s390x/ap-bridge.c
@@ -39,6 +39,7 @@ static const TypeInfo ap_bus_info = {
void s390_init_ap(void)
{
DeviceState *dev;
+ BusState *bus;
/* If no AP instructions then no need for AP bridge */
if (!s390_has_feat(S390_FEAT_AP)) {
@@ -52,13 +53,18 @@ void s390_init_ap(void)
qdev_init_nofail(dev);
/* Create bus on bridge device */
- qbus_create(TYPE_AP_BUS, dev, TYPE_AP_BUS);
+ bus = qbus_create(TYPE_AP_BUS, dev, TYPE_AP_BUS);
+
+ /* Enable hotplugging */
+ qbus_set_hotplug_handler(bus, OBJECT(dev), &error_abort);
}
static void ap_bridge_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
+ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
+ hc->unplug = qdev_simple_device_unplug_cb;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}
@@ -67,6 +73,10 @@ static const TypeInfo ap_bridge_info = {
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = 0,
.class_init = ap_bridge_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_HOTPLUG_HANDLER },
+ { }
+ }
};
static void ap_register(void)
diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c
index 6166ccd47a4a..d8b79ebe53ae 100644
--- a/hw/vfio/ap.c
+++ b/hw/vfio/ap.c
@@ -169,7 +169,7 @@ static void vfio_ap_class_init(ObjectClass *klass, void *data)
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
dc->realize = vfio_ap_realize;
dc->unrealize = vfio_ap_unrealize;
- dc->hotpluggable = false;
+ dc->hotpluggable = true;
dc->reset = vfio_ap_reset;
dc->bus_type = TYPE_AP_BUS;
}
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 05/27] s390x/vfio-ap: document hot plug/unplug of vfio-ap device
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (3 preceding siblings ...)
2019-03-04 12:01 ` [Qemu-devel] [PULL 04/27] s390x/vfio-ap: Implement hot plug/unplug of vfio-ap device Cornelia Huck
@ 2019-03-04 12:01 ` Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 06/27] s390x/tcg: RXE has an optional M3 field Cornelia Huck
` (22 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:01 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Tony Krowiak, Cornelia Huck
From: Tony Krowiak <akrowiak@linux.ibm.com>
Let's update the vfio-ap.txt document to include the hot plug/unplug
support.
Signed-off-by: Tony Krowiak <akrowiak@linux.ibm.com>
Message-Id: <1550519397-25359-3-git-send-email-akrowiak@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
docs/vfio-ap.txt | 61 ++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 56 insertions(+), 5 deletions(-)
diff --git a/docs/vfio-ap.txt b/docs/vfio-ap.txt
index 12339684cd52..8cd060a01e10 100644
--- a/docs/vfio-ap.txt
+++ b/docs/vfio-ap.txt
@@ -440,8 +440,7 @@ unassign_control_domain
'unassign_domain' file. This may be done multiple times to unassign more than
one control domain.
-Notes: Hot plug/unplug is not currently supported for mediated AP matrix
-devices, so no changes to the AP matrix will be allowed while a guest using
+Notes: No changes to the AP matrix will be allowed while a guest using
the mediated matrix device is running. Attempts to assign an adapter,
domain or control domain will be rejected and an error (EBUSY) returned.
@@ -562,6 +561,54 @@ facilities:
for guest usage, no AP devices can be made accessible to a
guest started without APFT installed.
+Hot plug a vfio-ap device into a running guest:
+==============================================
+Only one vfio-ap device can be attached to the virtual machine's ap-bus, so a
+vfio-ap device can be hot plugged if and only if no vfio-ap device is attached
+to the bus already, whether via the QEMU command line or a prior hot plug
+action.
+
+To hot plug a vfio-ap device, use the QEMU device_add command:
+
+ (qemu) device_add vfio-ap,sysfsdev="$path-to-mdev"
+
+ Where the '$path-to-mdev' value specifies the absolute path to a mediated
+ device to which AP resources to be used by the guest have been assigned.
+
+Note that on Linux guests, the AP devices will be created in the
+/sys/bus/ap/devices directory when the AP bus subsequently performs its periodic
+scan, so there may be a short delay before the AP devices are accessible on the
+guest.
+
+The command will fail if:
+
+* A vfio-ap device has already been attached to the virtual machine's ap-bus.
+
+* The CPU model features for controlling guest access to AP facilities are not
+ enabled (see 'CPU model features' subsection in the previous section).
+
+Hot unplug a vfio-ap device from a running guest:
+================================================
+A vfio-ap device can be unplugged from a running KVM guest if a vfio-ap device
+has been attached to the virtual machine's ap-bus via the QEMU command line
+or a prior hot plug action.
+
+To hot unplug a vfio-ap device, use the QEMU device_del command:
+
+ (qemu) device_del vfio-ap,sysfsdev="$path-to-mdev"
+
+ Where $path-to-mdev is the same as the path specified when the vfio-ap
+ device was attached to the virtual machine's ap-bus.
+
+On a Linux guest, the AP devices will be removed from the /sys/bus/ap/devices
+directory on the guest when the AP bus subsequently performs its periodic scan,
+so there may be a short delay before the AP devices are no longer accessible by
+the guest.
+
+The command will fail if the $path-to-mdev specified on the device_del command
+does not match the value specified when the vfio-ap device was attached to
+the virtual machine's ap-bus.
+
Example: Configure AP Matrixes for Three Linux Guests:
=====================================================
Let's now provide an example to illustrate how KVM guests may be given
@@ -819,7 +866,11 @@ Limitations
assigned lest the host be given access to the private data of the AP queue
device, such as a private key configured specifically for the guest.
-* Dynamically modifying the AP matrix for a running guest (which would amount to
- hot(un)plug of AP devices for the guest) is currently not supported
+* Dynamically assigning AP resources to or unassigning AP resources from a
+ mediated matrix device - see 'Configuring an AP matrix for a linux guest'
+ section above - while a running guest is using it is currently not supported.
-* Live guest migration is not supported for guests using AP devices.
+* Live guest migration is not supported for guests using AP devices. If a guest
+ is using AP devices, the vfio-ap device configured for the guest must be
+ unplugged before migrating the guest (see 'Hot unplug a vfio-ap device from a
+ running guest' section above.
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 06/27] s390x/tcg: RXE has an optional M3 field
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (4 preceding siblings ...)
2019-03-04 12:01 ` [Qemu-devel] [PULL 05/27] s390x/vfio-ap: document " Cornelia Huck
@ 2019-03-04 12:01 ` Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 07/27] s390x/tcg: Simplify disassembler operands initialization Cornelia Huck
` (21 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:01 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
Will be needed, so add it to the format description.
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190225200318.16102-2-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
target/s390x/insn-format.def | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/s390x/insn-format.def b/target/s390x/insn-format.def
index a412d90fb76d..4297ff416589 100644
--- a/target/s390x/insn-format.def
+++ b/target/s390x/insn-format.def
@@ -36,7 +36,7 @@ F3(RSY_a, R(1, 8), BDL(2), R(3,12))
F3(RSY_b, R(1, 8), BDL(2), M(3,12))
F2(RX_a, R(1, 8), BXD(2))
F2(RX_b, M(1, 8), BXD(2))
-F2(RXE, R(1, 8), BXD(2))
+F3(RXE, R(1, 8), BXD(2), M(3,32))
F3(RXF, R(1,32), BXD(2), R(3, 8))
F2(RXY_a, R(1, 8), BXDL(2))
F2(RXY_b, M(1, 8), BXDL(2))
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 07/27] s390x/tcg: Simplify disassembler operands initialization
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (5 preceding siblings ...)
2019-03-04 12:01 ` [Qemu-devel] [PULL 06/27] s390x/tcg: RXE has an optional M3 field Cornelia Huck
@ 2019-03-04 12:01 ` Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 08/27] s390x/tcg: Clarify terminology in vec_reg_offset() Cornelia Huck
` (20 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:01 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
Let's simplify initialization to 0.
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190225200318.16102-3-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
target/s390x/translate.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 19072efec655..c646e50eb388 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -6091,7 +6091,7 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s)
const DisasInsn *insn;
DisasJumpType ret = DISAS_NEXT;
DisasFields f;
- DisasOps o;
+ DisasOps o = {};
/* Search for the insn in the table. */
insn = extract_insn(env, s, &f);
@@ -6161,12 +6161,6 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s)
/* Set up the strutures we use to communicate with the helpers. */
s->insn = insn;
s->fields = &f;
- o.g_out = o.g_out2 = o.g_in1 = o.g_in2 = false;
- o.out = NULL;
- o.out2 = NULL;
- o.in1 = NULL;
- o.in2 = NULL;
- o.addr1 = NULL;
/* Implement the instruction. */
if (insn->help_in1) {
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 08/27] s390x/tcg: Clarify terminology in vec_reg_offset()
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (6 preceding siblings ...)
2019-03-04 12:01 ` [Qemu-devel] [PULL 07/27] s390x/tcg: Simplify disassembler operands initialization Cornelia Huck
@ 2019-03-04 12:01 ` Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 09/27] s390x/tcg: Factor out vec_full_reg_offset() Cornelia Huck
` (19 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:01 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
We will use s390x speak "Element Size" (es) for MO_8 == 0, MO_16 == 1
... Simple rename of variables.
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190225200318.16102-4-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
target/s390x/translate.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index c646e50eb388..6647a67998ba 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -145,10 +145,11 @@ void s390x_translate_init(void)
}
}
-static inline int vec_reg_offset(uint8_t reg, uint8_t enr, TCGMemOp size)
+static inline int vec_reg_offset(uint8_t reg, uint8_t enr, TCGMemOp es)
{
- const uint8_t es = 1 << size;
- int offs = enr * es;
+ /* Convert element size (es) - e.g. MO_8 - to bytes */
+ const uint8_t bytes = 1 << es;
+ int offs = enr * bytes;
g_assert(reg < 32);
/*
@@ -173,9 +174,9 @@ static inline int vec_reg_offset(uint8_t reg, uint8_t enr, TCGMemOp size)
* the two 8 byte elements have to be loaded separately. Let's force all
* 16 byte operations to handle it in a special way.
*/
- g_assert(size <= MO_64);
+ g_assert(es <= MO_64);
#ifndef HOST_WORDS_BIGENDIAN
- offs ^= (8 - es);
+ offs ^= (8 - bytes);
#endif
return offs + offsetof(CPUS390XState, vregs[reg][0].d);
}
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 09/27] s390x/tcg: Factor out vec_full_reg_offset()
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (7 preceding siblings ...)
2019-03-04 12:01 ` [Qemu-devel] [PULL 08/27] s390x/tcg: Clarify terminology in vec_reg_offset() Cornelia Huck
@ 2019-03-04 12:01 ` Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 10/27] s390x/tcg: Factor out gen_addi_and_wrap_i64() from get_address() Cornelia Huck
` (18 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:01 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
We'll use that a lot along with gvec helpers, to calculate the start
address of a vector.
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190225200318.16102-5-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
target/s390x/translate.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 6647a67998ba..933bf29331a2 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -145,13 +145,18 @@ void s390x_translate_init(void)
}
}
+static inline int vec_full_reg_offset(uint8_t reg)
+{
+ g_assert(reg < 32);
+ return offsetof(CPUS390XState, vregs[reg][0].d);
+}
+
static inline int vec_reg_offset(uint8_t reg, uint8_t enr, TCGMemOp es)
{
/* Convert element size (es) - e.g. MO_8 - to bytes */
const uint8_t bytes = 1 << es;
int offs = enr * bytes;
- g_assert(reg < 32);
/*
* vregs[n][0] is the lowest 8 byte and vregs[n][1] the highest 8 byte
* of the 16 byte vector, on both, little and big endian systems.
@@ -178,7 +183,7 @@ static inline int vec_reg_offset(uint8_t reg, uint8_t enr, TCGMemOp es)
#ifndef HOST_WORDS_BIGENDIAN
offs ^= (8 - bytes);
#endif
- return offs + offsetof(CPUS390XState, vregs[reg][0].d);
+ return offs + vec_full_reg_offset(reg);
}
static inline int freg64_offset(uint8_t reg)
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 10/27] s390x/tcg: Factor out gen_addi_and_wrap_i64() from get_address()
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (8 preceding siblings ...)
2019-03-04 12:01 ` [Qemu-devel] [PULL 09/27] s390x/tcg: Factor out vec_full_reg_offset() Cornelia Huck
@ 2019-03-04 12:01 ` Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 11/27] s390x/tcg: Implement LOAD LENGTHENED short HFP to long HFP Cornelia Huck
` (17 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:01 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
Also properly wrap in 24bit mode. While at it, convert the comment (and
drop the comment about fundamental TCG optimizations).
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190225200318.16102-6-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
target/s390x/translate.c | 41 +++++++++++++++++++++++++---------------
1 file changed, 26 insertions(+), 15 deletions(-)
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 933bf29331a2..f7de77192c7e 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -382,32 +382,43 @@ static inline void gen_trap(DisasContext *s)
gen_data_exception(0xff);
}
+static void gen_addi_and_wrap_i64(DisasContext *s, TCGv_i64 dst, TCGv_i64 src,
+ int64_t imm)
+{
+ tcg_gen_addi_i64(dst, src, imm);
+ if (!(s->base.tb->flags & FLAG_MASK_64)) {
+ if (s->base.tb->flags & FLAG_MASK_32) {
+ tcg_gen_andi_i64(dst, dst, 0x7fffffff);
+ } else {
+ tcg_gen_andi_i64(dst, dst, 0x00ffffff);
+ }
+ }
+}
+
static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
{
TCGv_i64 tmp = tcg_temp_new_i64();
- bool need_31 = !(s->base.tb->flags & FLAG_MASK_64);
-
- /* Note that d2 is limited to 20 bits, signed. If we crop negative
- displacements early we create larger immedate addends. */
- /* Note that addi optimizes the imm==0 case. */
+ /*
+ * Note that d2 is limited to 20 bits, signed. If we crop negative
+ * displacements early we create larger immedate addends.
+ */
if (b2 && x2) {
tcg_gen_add_i64(tmp, regs[b2], regs[x2]);
- tcg_gen_addi_i64(tmp, tmp, d2);
+ gen_addi_and_wrap_i64(s, tmp, tmp, d2);
} else if (b2) {
- tcg_gen_addi_i64(tmp, regs[b2], d2);
+ gen_addi_and_wrap_i64(s, tmp, regs[b2], d2);
} else if (x2) {
- tcg_gen_addi_i64(tmp, regs[x2], d2);
- } else {
- if (need_31) {
- d2 &= 0x7fffffff;
- need_31 = false;
+ gen_addi_and_wrap_i64(s, tmp, regs[x2], d2);
+ } else if (!(s->base.tb->flags & FLAG_MASK_64)) {
+ if (s->base.tb->flags & FLAG_MASK_32) {
+ tcg_gen_movi_i64(tmp, d2 & 0x7fffffff);
+ } else {
+ tcg_gen_movi_i64(tmp, d2 & 0x00ffffff);
}
+ } else {
tcg_gen_movi_i64(tmp, d2);
}
- if (need_31) {
- tcg_gen_andi_i64(tmp, tmp, 0x7fffffff);
- }
return tmp;
}
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 11/27] s390x/tcg: Implement LOAD LENGTHENED short HFP to long HFP
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (9 preceding siblings ...)
2019-03-04 12:01 ` [Qemu-devel] [PULL 10/27] s390x/tcg: Factor out gen_addi_and_wrap_i64() from get_address() Cornelia Huck
@ 2019-03-04 12:01 ` Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 12/27] s390x/tcg: Implement LOAD COUNT TO BLOCK BOUNDARY Cornelia Huck
` (16 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:01 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
Nice trick to load a 32 bit value into vector element 0 (32 bit element
size) from memory, zeroing out element1. The short HFP to long HFP
conversion really only is a shift.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190225200318.16102-7-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
target/s390x/insn-data.def | 2 ++
target/s390x/translate.c | 6 ++++++
2 files changed, 8 insertions(+)
diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def
index 61582372abb7..fb6ee1865057 100644
--- a/target/s390x/insn-data.def
+++ b/target/s390x/insn-data.def
@@ -598,6 +598,8 @@
F(0xed04, LDEB, RXE, Z, 0, m2_32u, new, f1, ldeb, 0, IF_BFP)
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)
+ F(0xb324, LDER, RXE, Z, 0, e2, new, f1, lde, 0, IF_AFP1)
+ F(0xed24, LDE, RXE, Z, 0, m2_32u, new, f1, lde, 0, IF_AFP1)
/* 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)
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index f7de77192c7e..59e71128d2bf 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -2725,6 +2725,12 @@ static DisasJumpType op_lxeb(DisasContext *s, DisasOps *o)
return DISAS_NEXT;
}
+static DisasJumpType op_lde(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_shli_i64(o->out, o->in2, 32);
+ return DISAS_NEXT;
+}
+
static DisasJumpType op_llgt(DisasContext *s, DisasOps *o)
{
tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff);
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 12/27] s390x/tcg: Implement LOAD COUNT TO BLOCK BOUNDARY
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (10 preceding siblings ...)
2019-03-04 12:01 ` [Qemu-devel] [PULL 11/27] s390x/tcg: Implement LOAD LENGTHENED short HFP to long HFP Cornelia Huck
@ 2019-03-04 12:01 ` Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 13/27] s390x/tcg: Fix TEST DATA CLASS instructions Cornelia Huck
` (15 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:01 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
Use a new CC helper to calculate the CC lazily if needed. While the
PoP mentions that "A 32-bit unsigned binary integer" is placed into the
first operand, there is no word telling that the other 32 bits (high
part) are left untouched. Maybe the other 32-bit are unpredictable.
So store 64 bit for now.
Bit magic courtesy of Richard.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190225200318.16102-8-david@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
target/s390x/cc_helper.c | 8 ++++++++
target/s390x/helper.c | 1 +
target/s390x/insn-data.def | 2 ++
target/s390x/internal.h | 1 +
target/s390x/translate.c | 19 +++++++++++++++++++
5 files changed, 31 insertions(+)
diff --git a/target/s390x/cc_helper.c b/target/s390x/cc_helper.c
index 307ad61aee3d..0e467bf2b6a2 100644
--- a/target/s390x/cc_helper.c
+++ b/target/s390x/cc_helper.c
@@ -397,6 +397,11 @@ static uint32_t cc_calc_flogr(uint64_t dst)
return dst ? 2 : 0;
}
+static uint32_t cc_calc_lcbb(uint64_t dst)
+{
+ return dst == 16 ? 0 : 3;
+}
+
static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
uint64_t src, uint64_t dst, uint64_t vr)
{
@@ -506,6 +511,9 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
case CC_OP_FLOGR:
r = cc_calc_flogr(dst);
break;
+ case CC_OP_LCBB:
+ r = cc_calc_lcbb(dst);
+ break;
case CC_OP_NZ_F32:
r = set_cc_nz_f32(dst);
diff --git a/target/s390x/helper.c b/target/s390x/helper.c
index a7edd5df7d59..8e9573221cdb 100644
--- a/target/s390x/helper.c
+++ b/target/s390x/helper.c
@@ -417,6 +417,7 @@ const char *cc_name(enum cc_op cc_op)
[CC_OP_SLA_32] = "CC_OP_SLA_32",
[CC_OP_SLA_64] = "CC_OP_SLA_64",
[CC_OP_FLOGR] = "CC_OP_FLOGR",
+ [CC_OP_LCBB] = "CC_OP_LCBB",
};
return cc_names[cc_op];
diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def
index fb6ee1865057..f4f1d63ab44c 100644
--- a/target/s390x/insn-data.def
+++ b/target/s390x/insn-data.def
@@ -479,6 +479,8 @@
F(0xb313, LCDBR, RRE, Z, 0, f2, new, f1, negf64, f64, IF_BFP)
F(0xb343, LCXBR, RRE, Z, x2h, x2l, new_P, x1, negf128, f128, IF_BFP)
F(0xb373, LCDFR, RRE, FPSSH, 0, f2, new, f1, negf64, 0, IF_AFP1 | IF_AFP2)
+/* LOAD COUNT TO BLOCK BOUNDARY */
+ C(0xe727, LCBB, RXE, V, la2, 0, r1, 0, lcbb, 0)
/* LOAD HALFWORD */
C(0xb927, LHR, RRE, EI, 0, r2_16s, 0, r1_32, mov2, 0)
C(0xb907, LGHR, RRE, EI, 0, r2_16s, 0, r1, mov2, 0)
diff --git a/target/s390x/internal.h b/target/s390x/internal.h
index b2966a3adcb8..9d0a45d1fef7 100644
--- a/target/s390x/internal.h
+++ b/target/s390x/internal.h
@@ -236,6 +236,7 @@ enum cc_op {
CC_OP_SLA_32, /* Calculate shift left signed (32bit) */
CC_OP_SLA_64, /* Calculate shift left signed (64bit) */
CC_OP_FLOGR, /* find leftmost one */
+ CC_OP_LCBB, /* load count to block boundary */
CC_OP_MAX
};
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 59e71128d2bf..d9a89625c66c 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -557,6 +557,7 @@ static void gen_op_calc_cc(DisasContext *s)
case CC_OP_NZ_F32:
case CC_OP_NZ_F64:
case CC_OP_FLOGR:
+ case CC_OP_LCBB:
/* 1 argument */
gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy);
break;
@@ -3142,6 +3143,23 @@ static DisasJumpType op_lzrb(DisasContext *s, DisasOps *o)
return DISAS_NEXT;
}
+static DisasJumpType op_lcbb(DisasContext *s, DisasOps *o)
+{
+ const int64_t block_size = (1ull << (get_field(s->fields, m3) + 6));
+
+ if (get_field(s->fields, m3) > 6) {
+ gen_program_exception(s, PGM_SPECIFICATION);
+ return DISAS_NORETURN;
+ }
+
+ tcg_gen_ori_i64(o->addr1, o->addr1, -block_size);
+ tcg_gen_neg_i64(o->addr1, o->addr1);
+ tcg_gen_movi_i64(o->out, 16);
+ tcg_gen_umin_i64(o->out, o->out, o->addr1);
+ gen_op_update1_cc_i64(s, CC_OP_LCBB, o->out);
+ return DISAS_NEXT;
+}
+
static DisasJumpType op_mov2(DisasContext *s, DisasOps *o)
{
o->out = o->in2;
@@ -5931,6 +5949,7 @@ enum DisasInsnEnum {
#define FAC_ECT S390_FEAT_EXTRACT_CPU_TIME
#define FAC_PCI S390_FEAT_ZPCI /* z/PCI facility */
#define FAC_AIS S390_FEAT_ADAPTER_INT_SUPPRESSION
+#define FAC_V S390_FEAT_VECTOR /* vector facility */
static const DisasInsn insn_info[] = {
#include "insn-data.def"
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 13/27] s390x/tcg: Fix TEST DATA CLASS instructions
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (11 preceding siblings ...)
2019-03-04 12:01 ` [Qemu-devel] [PULL 12/27] s390x/tcg: Implement LOAD COUNT TO BLOCK BOUNDARY Cornelia Huck
@ 2019-03-04 12:01 ` Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 14/27] s390x/tcg: Fix rounding from float128 to uint64_t/uint32_t Cornelia Huck
` (14 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:01 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
Let's detect normal and denormal ("subnormal") numbers reliably. Also
test for quiet NaN's. As only one class is possible, test common cases
first.
While at it, use a better check to test for the mask bits in the data
class mask. The data class mask has 12 bits, whereby bit 0 is the
leftmost bit and bit 11 the rightmost bit. In the PoP an easy to read
table with the numbers is provided for the VECTOR FP TEST DATA CLASS
IMMEDIATE instruction, the table for TEST DATA CLASS is more confusing
as it is based on 64 bit values.
Factor the checks out into separate functions, as they will also be
needed for floating point vector instructions. We can use a makro to
generate the functions.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190218122710.23639-2-david@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
target/s390x/fpu_helper.c | 85 ++++++++++++++++-----------------------
1 file changed, 35 insertions(+), 50 deletions(-)
diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index e921172bc424..0e9247bf7ef4 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -645,67 +645,52 @@ uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
return ret;
}
+/* The rightmost bit has the number 11. */
+static inline uint16_t dcmask(int bit, bool neg)
+{
+ return 1 << (11 - bit - neg);
+}
+
+#define DEF_FLOAT_DCMASK(_TYPE) \
+static uint16_t _TYPE##_dcmask(CPUS390XState *env, _TYPE f1) \
+{ \
+ const bool neg = _TYPE##_is_neg(f1); \
+ \
+ /* Sorted by most common cases - only one class is possible */ \
+ if (_TYPE##_is_normal(f1)) { \
+ return dcmask(2, neg); \
+ } else if (_TYPE##_is_zero(f1)) { \
+ return dcmask(0, neg); \
+ } else if (_TYPE##_is_denormal(f1)) { \
+ return dcmask(4, neg); \
+ } else if (_TYPE##_is_infinity(f1)) { \
+ return dcmask(6, neg); \
+ } else if (_TYPE##_is_quiet_nan(f1, &env->fpu_status)) { \
+ return dcmask(8, neg); \
+ } \
+ /* signaling nan, as last remaining case */ \
+ return dcmask(10, neg); \
+}
+DEF_FLOAT_DCMASK(float32)
+DEF_FLOAT_DCMASK(float64)
+DEF_FLOAT_DCMASK(float128)
+
/* test data class 32-bit */
uint32_t HELPER(tceb)(CPUS390XState *env, uint64_t f1, uint64_t m2)
{
- float32 v1 = f1;
- int neg = float32_is_neg(v1);
- uint32_t cc = 0;
-
- if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
- (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
- (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
- (float32_is_signaling_nan(v1, &env->fpu_status) &&
- (m2 & (1 << (1-neg))))) {
- cc = 1;
- } else if (m2 & (1 << (9-neg))) {
- /* assume normalized number */
- cc = 1;
- }
- /* FIXME: denormalized? */
- return cc;
+ return (m2 & float32_dcmask(env, f1)) != 0;
}
/* test data class 64-bit */
uint32_t HELPER(tcdb)(CPUS390XState *env, uint64_t v1, uint64_t m2)
{
- int neg = float64_is_neg(v1);
- uint32_t cc = 0;
-
- if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
- (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
- (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
- (float64_is_signaling_nan(v1, &env->fpu_status) &&
- (m2 & (1 << (1-neg))))) {
- cc = 1;
- } else if (m2 & (1 << (9-neg))) {
- /* assume normalized number */
- cc = 1;
- }
- /* FIXME: denormalized? */
- return cc;
+ return (m2 & float64_dcmask(env, v1)) != 0;
}
/* test data class 128-bit */
-uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah,
- uint64_t al, uint64_t m2)
-{
- float128 v1 = make_float128(ah, al);
- int neg = float128_is_neg(v1);
- uint32_t cc = 0;
-
- if ((float128_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
- (float128_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
- (float128_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
- (float128_is_signaling_nan(v1, &env->fpu_status) &&
- (m2 & (1 << (1-neg))))) {
- cc = 1;
- } else if (m2 & (1 << (9-neg))) {
- /* assume normalized number */
- cc = 1;
- }
- /* FIXME: denormalized? */
- return cc;
+uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint64_t m2)
+{
+ return (m2 & float128_dcmask(env, make_float128(ah, al))) != 0;
}
/* square root 32-bit */
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 14/27] s390x/tcg: Fix rounding from float128 to uint64_t/uint32_t
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (12 preceding siblings ...)
2019-03-04 12:01 ` [Qemu-devel] [PULL 13/27] s390x/tcg: Fix TEST DATA CLASS instructions Cornelia Huck
@ 2019-03-04 12:01 ` Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 15/27] s390x/tcg: Factor out conversion of softfloat exceptions Cornelia Huck
` (13 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:01 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
Let's use the proper conversion functions now that we have them.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190218122710.23639-3-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@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 0e9247bf7ef4..21236caed869 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] 29+ messages in thread
* [Qemu-devel] [PULL 15/27] s390x/tcg: Factor out conversion of softfloat exceptions
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (13 preceding siblings ...)
2019-03-04 12:01 ` [Qemu-devel] [PULL 14/27] s390x/tcg: Fix rounding from float128 to uint64_t/uint32_t Cornelia Huck
@ 2019-03-04 12:01 ` Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 16/27] s390x/tcg: Fix parts of IEEE exception handling Cornelia Huck
` (12 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:01 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
We want to reuse that function in vector instruction context. While at it,
cleanup the code, using defines for magic values and avoiding the
handcrafted bit conversion.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190218122710.23639-4-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@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 21236caed869..de02cf792d87 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 9d0a45d1fef7..4db736b6acfd 100644
--- a/target/s390x/internal.h
+++ b/target/s390x/internal.h
@@ -311,6 +311,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] 29+ messages in thread
* [Qemu-devel] [PULL 16/27] s390x/tcg: Fix parts of IEEE exception handling
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (14 preceding siblings ...)
2019-03-04 12:01 ` [Qemu-devel] [PULL 15/27] s390x/tcg: Factor out conversion of softfloat exceptions Cornelia Huck
@ 2019-03-04 12:01 ` Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 17/27] s390x/tcg: Hide IEEE underflows in some scenarios Cornelia Huck
` (11 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:01 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
Many things are wrong and some parts cannot be fixed yet. Fix what we
can fix easily and add two FIXMEs:
The fpc flags are not updated in case an exception is actually injected.
Inexact exceptions have to be handled separately, as they are the only
exceptions that can coexist with underflows and overflows.
I reread the horribly complicated chapters in the PoP at least 5 times
and hope I got it right.
For references:
- z14 PoP, 9-18, "IEEE Exceptions"
- z14 PoP, 19-9, Figure 19-8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190218122710.23639-5-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@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 de02cf792d87..dcad9c367a5c 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] 29+ messages in thread
* [Qemu-devel] [PULL 17/27] s390x/tcg: Hide IEEE underflows in some scenarios
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (15 preceding siblings ...)
2019-03-04 12:01 ` [Qemu-devel] [PULL 16/27] s390x/tcg: Fix parts of IEEE exception handling Cornelia Huck
@ 2019-03-04 12:02 ` Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 18/27] s390x/tcg: Refactor SET FPC AND SIGNAL handling Cornelia Huck
` (10 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:02 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
IEEE underflows are not reported when the mask bit is off and we don't
also have an inexact exception.
z14 PoP, 9-20, "IEEE Underflow":
An IEEE-underflow exception is recognized for an
IEEE target when the tininess condition exists and
either: (1) the IEEE-underflow mask bit in the FPC
register is zero and the result value is inexact, or (2)
the IEEE-underflow mask bit in the FPC register is
one.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190218122710.23639-6-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@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 dcad9c367a5c..64efab72a4dc 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] 29+ messages in thread
* [Qemu-devel] [PULL 18/27] s390x/tcg: Refactor SET FPC AND SIGNAL handling
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (16 preceding siblings ...)
2019-03-04 12:02 ` [Qemu-devel] [PULL 17/27] s390x/tcg: Hide IEEE underflows in some scenarios Cornelia Huck
@ 2019-03-04 12:02 ` Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 19/27] s390x/tcg: Fix simulated-IEEE exceptions Cornelia Huck
` (9 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:02 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
We can directly work on the uint64_t value, no need for a temporary
uint32_t value.
Also cleanup and shorten the comments.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190218122710.23639-7-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@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 64efab72a4dc..ea5a37ac5e76 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -771,21 +771,23 @@ void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
}
/* set fpc and signal */
-void HELPER(sfas)(CPUS390XState *env, uint64_t val)
+void HELPER(sfas)(CPUS390XState *env, uint64_t fpc)
{
uint32_t signalling = env->fpc;
- uint32_t source = val;
uint32_t s390_exc;
- /* The contents of the source operand are placed in the FPC register;
- then the flags in the FPC register are set to the logical OR of the
- signalling flags and the source flags. */
- env->fpc = source | (signalling & 0x00ff0000);
- set_float_rounding_mode(fpc_to_rnd[source & 3], &env->fpu_status);
+ /*
+ * FPC is set to the FPC operand with a bitwise OR of the signalling
+ * flags.
+ */
+ env->fpc = fpc | (signalling & 0x00ff0000);
+ set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
- /* If any signalling flag is 1 and the corresponding source mask
- is also 1, a simulated-iee-exception trap occurs. */
- s390_exc = (signalling >> 16) & (source >> 24);
+ /*
+ * If any signaling flag is enabled in the new FPC mask, a
+ * simulated-iee-exception exception occurs.
+ */
+ s390_exc = (signalling >> 16) & (fpc >> 24);
if (s390_exc) {
tcg_s390_data_exception(env, s390_exc | 3, GETPC());
}
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 19/27] s390x/tcg: Fix simulated-IEEE exceptions
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (17 preceding siblings ...)
2019-03-04 12:02 ` [Qemu-devel] [PULL 18/27] s390x/tcg: Refactor SET FPC AND SIGNAL handling Cornelia Huck
@ 2019-03-04 12:02 ` Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 20/27] s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes Cornelia Huck
` (8 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:02 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
The trap is triggered based on priority of the enabled signaling flags.
Only overflow and underflow allow a concurrent inexact exception.
z14 PoP, 9-33, Figure 9-21
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190218122710.23639-8-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@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 ea5a37ac5e76..7508c0748e63 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -789,6 +789,19 @@ void HELPER(sfas)(CPUS390XState *env, uint64_t fpc)
*/
s390_exc = (signalling >> 16) & (fpc >> 24);
if (s390_exc) {
+ if (s390_exc & S390_IEEE_MASK_INVALID) {
+ s390_exc = S390_IEEE_MASK_INVALID;
+ } else if (s390_exc & S390_IEEE_MASK_DIVBYZERO) {
+ s390_exc = S390_IEEE_MASK_DIVBYZERO;
+ } else if (s390_exc & S390_IEEE_MASK_OVERFLOW) {
+ s390_exc &= (S390_IEEE_MASK_OVERFLOW | S390_IEEE_MASK_INEXACT);
+ } else if (s390_exc & S390_IEEE_MASK_UNDERFLOW) {
+ s390_exc &= (S390_IEEE_MASK_UNDERFLOW | S390_IEEE_MASK_INEXACT);
+ } else if (s390_exc & S390_IEEE_MASK_INEXACT) {
+ s390_exc = S390_IEEE_MASK_INEXACT;
+ } else if (s390_exc & S390_IEEE_MASK_QUANTUM) {
+ s390_exc = S390_IEEE_MASK_QUANTUM;
+ }
tcg_s390_data_exception(env, s390_exc | 3, GETPC());
}
}
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 20/27] s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (18 preceding siblings ...)
2019-03-04 12:02 ` [Qemu-devel] [PULL 19/27] s390x/tcg: Fix simulated-IEEE exceptions Cornelia Huck
@ 2019-03-04 12:02 ` Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 21/27] s390x/tcg: Check for exceptions in SET BFP ROUNDING MODE Cornelia Huck
` (7 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:02 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
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.
Note: 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>
Message-Id: <20190218122710.23639-9-david@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
target/s390x/fpu_helper.c | 22 ++++++++++++++++++----
target/s390x/helper.h | 2 +-
2 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 7508c0748e63..4dc70ec60f60 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -753,21 +753,30 @@ 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,
+ float_round_to_odd,
};
/* set fpc */
void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
{
+ if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u ||
+ (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) {
+ s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC());
+ }
+
/* Install everything in the main FPC. */
env->fpc = fpc;
/* Install the rounding mode in the shadow fpu_status. */
- set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
+ set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status);
}
/* set fpc and signal */
@@ -776,12 +785,17 @@ void HELPER(sfas)(CPUS390XState *env, uint64_t fpc)
uint32_t signalling = env->fpc;
uint32_t s390_exc;
+ if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u ||
+ (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) {
+ s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC());
+ }
+
/*
* FPC is set to the FPC operand with a bitwise OR of the signalling
* flags.
*/
env->fpc = fpc | (signalling & 0x00ff0000);
- set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
+ set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status);
/*
* If any signaling flag is enabled in the new FPC mask, a
diff --git a/target/s390x/helper.h b/target/s390x/helper.h
index 6260b5049621..a99b067c9c50 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] 29+ messages in thread
* [Qemu-devel] [PULL 21/27] s390x/tcg: Check for exceptions in SET BFP ROUNDING MODE
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (19 preceding siblings ...)
2019-03-04 12:02 ` [Qemu-devel] [PULL 20/27] s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes Cornelia Huck
@ 2019-03-04 12:02 ` Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 22/27] s390x/tcg: Refactor saving/restoring the bfp rounding mode Cornelia Huck
` (6 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:02 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
Let's split handling of BFP/DFP rounding mode configuration. Also,
let's not reuse the sfpc handler, use a separate handler so we can
properly check for specification exceptions for SRNMB.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190218122710.23639-10-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@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 4dc70ec60f60..ed9c74c42004 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -819,3 +819,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 a99b067c9c50..d287d5dac093 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 f4f1d63ab44c..d80d168d4ef6 100644
--- a/target/s390x/insn-data.def
+++ b/target/s390x/insn-data.def
@@ -763,10 +763,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 d9a89625c66c..80952a30f972 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -3996,41 +3996,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] 29+ messages in thread
* [Qemu-devel] [PULL 22/27] s390x/tcg: Refactor saving/restoring the bfp rounding mode
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (20 preceding siblings ...)
2019-03-04 12:02 ` [Qemu-devel] [PULL 21/27] s390x/tcg: Check for exceptions in SET BFP ROUNDING MODE Cornelia Huck
@ 2019-03-04 12:02 ` Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 23/27] s390x/tcg: Prepare for IEEE-inexact-exception control (XxC) Cornelia Huck
` (5 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:02 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
We want to reuse this in the context of vector instructions. So use
better matching names and introduce s390_restore_bfp_rounding_mode().
While at it, add proper newlines.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190218122710.23639-11-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
target/s390x/fpu_helper.c | 112 +++++++++++++++++++++++---------------
target/s390x/internal.h | 2 +
2 files changed, 71 insertions(+), 43 deletions(-)
diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index ed9c74c42004..8baca14650ec 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -372,7 +372,7 @@ uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
return float_comp_to_cc(env, cmp);
}
-static int swap_round_mode(CPUS390XState *env, int m3)
+int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3)
{
int ret = env->fpu_status.float_rounding_mode;
switch (m3) {
@@ -401,12 +401,18 @@ static int swap_round_mode(CPUS390XState *env, int m3)
return ret;
}
+void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode)
+{
+ set_float_rounding_mode(old_mode, &env->fpu_status);
+}
+
/* convert 64-bit int to 32-bit float */
uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
float32 ret = int64_to_float32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -414,9 +420,10 @@ uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
/* convert 64-bit int to 64-bit float */
uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
float64 ret = int64_to_float64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -424,9 +431,10 @@ uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
/* convert 64-bit int to 128-bit float */
uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
float128 ret = int64_to_float128(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return RET128(ret);
}
@@ -434,9 +442,10 @@ uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
/* convert 64-bit uint to 32-bit float */
uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
float32 ret = uint64_to_float32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -444,9 +453,10 @@ uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
/* convert 64-bit uint to 64-bit float */
uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
float64 ret = uint64_to_float64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -454,9 +464,10 @@ uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
/* convert 64-bit uint to 128-bit float */
uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
float128 ret = uint64_to_float128(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return RET128(ret);
}
@@ -464,9 +475,10 @@ uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
/* convert 32-bit float to 64-bit int */
uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
int64_t ret = float32_to_int64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -474,9 +486,10 @@ uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
/* convert 64-bit float to 64-bit int */
uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
int64_t ret = float64_to_int64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -484,10 +497,11 @@ uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
/* convert 128-bit float to 64-bit int */
uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
float128 v2 = make_float128(h, l);
int64_t ret = float128_to_int64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -495,9 +509,10 @@ uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
/* convert 32-bit float to 32-bit int */
uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
int32_t ret = float32_to_int32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -505,9 +520,10 @@ uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
/* convert 64-bit float to 32-bit int */
uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
int32_t ret = float64_to_int32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -515,10 +531,11 @@ uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
/* convert 128-bit float to 32-bit int */
uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
float128 v2 = make_float128(h, l);
int32_t ret = float128_to_int32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -526,11 +543,12 @@ uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
/* convert 32-bit float to 64-bit uint */
uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
uint64_t ret;
+
v2 = float32_to_float64(v2, &env->fpu_status);
ret = float64_to_uint64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -538,9 +556,10 @@ uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
/* convert 64-bit float to 64-bit uint */
uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
uint64_t ret = float64_to_uint64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -548,9 +567,10 @@ uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
/* convert 128-bit float to 64-bit uint */
uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
uint64_t ret = float128_to_uint64(make_float128(h, l), &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -558,9 +578,10 @@ uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
/* convert 32-bit float to 32-bit uint */
uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
uint32_t ret = float32_to_uint32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -568,9 +589,10 @@ uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
/* convert 64-bit float to 32-bit uint */
uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
uint32_t ret = float64_to_uint32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -578,9 +600,10 @@ uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
/* convert 128-bit float to 32-bit uint */
uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
uint32_t ret = float128_to_uint32(make_float128(h, l), &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -588,9 +611,10 @@ uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
/* round to integer 32-bit */
uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
float32 ret = float32_round_to_int(f2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -598,9 +622,10 @@ uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
/* round to integer 64-bit */
uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
float64 ret = float64_round_to_int(f2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return ret;
}
@@ -608,10 +633,11 @@ uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
/* round to integer 128-bit */
uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
{
- int hold = swap_round_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+
float128 ret = float128_round_to_int(make_float128(ah, al),
&env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
+ s390_restore_bfp_rounding_mode(env, old_mode);
handle_exceptions(env, GETPC());
return RET128(ret);
}
diff --git a/target/s390x/internal.h b/target/s390x/internal.h
index 4db736b6acfd..7baf0e2404b4 100644
--- a/target/s390x/internal.h
+++ b/target/s390x/internal.h
@@ -318,6 +318,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] 29+ messages in thread
* [Qemu-devel] [PULL 23/27] s390x/tcg: Prepare for IEEE-inexact-exception control (XxC)
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (21 preceding siblings ...)
2019-03-04 12:02 ` [Qemu-devel] [PULL 22/27] s390x/tcg: Refactor saving/restoring the bfp rounding mode Cornelia Huck
@ 2019-03-04 12:02 ` Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 24/27] s390x/tcg: Implement XxC and checks for most FP instructions Cornelia Huck
` (4 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:02 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
Some instructions allow to suppress IEEE inexact exceptions.
z14 PoP, 9-23, "Suppression of Certain IEEE Exceptions"
IEEE-inexact-exception control (XxC): Bit 1 of
the M4 field is the XxC bit. If XxC is zero, recogni-
tion of IEEE-inexact exception is not suppressed;
if XxC is one, recognition of IEEE-inexact excep-
tion is suppressed.
Especially, handling for overflow/unerflow remains as is, inexact is
reported along
z14 PoP, 9-23, "Suppression of Certain IEEE Exceptions"
For example, the IEEE-inexact-exception control (XxC)
has no effect on the DXC; that is, the DXC for IEEE-
overflow or IEEE-underflow exceptions along with the
detail for exact, inexact and truncated, or inexact and
incremented, is reported according to the actual con-
dition.
Follow up patches will wire it correctly up for the applicable
instructions.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190218122710.23639-12-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
target/s390x/fpu_helper.c | 114 +++++++++++++++++++-------------------
1 file changed, 57 insertions(+), 57 deletions(-)
diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 8baca14650ec..293808c318c1 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -50,7 +50,7 @@ uint8_t s390_softfloat_exc_to_ieee(unsigned int exc)
}
/* Should be called after any operation that may raise IEEE exceptions. */
-static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
+static void handle_exceptions(CPUS390XState *env, bool XxC, uintptr_t retaddr)
{
unsigned s390_exc, qemu_exc;
@@ -101,7 +101,7 @@ static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
}
/* inexact handling */
- if (s390_exc & S390_IEEE_MASK_INEXACT) {
+ if (s390_exc & S390_IEEE_MASK_INEXACT && !XxC) {
/* trap condition - overflow/underflow _not_ reported along */
if (s390_exc & S390_IEEE_MASK_INEXACT & env->fpc >> 24) {
tcg_s390_data_exception(env, s390_exc & S390_IEEE_MASK_INEXACT,
@@ -174,7 +174,7 @@ uint32_t set_cc_nz_f128(float128 v)
uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
float32 ret = float32_add(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -182,7 +182,7 @@ uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
float64 ret = float64_add(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -193,7 +193,7 @@ uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
float128 ret = float128_add(make_float128(ah, al),
make_float128(bh, bl),
&env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
@@ -201,7 +201,7 @@ uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
float32 ret = float32_sub(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -209,7 +209,7 @@ uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
float64 ret = float64_sub(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -220,7 +220,7 @@ uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
float128 ret = float128_sub(make_float128(ah, al),
make_float128(bh, bl),
&env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
@@ -228,7 +228,7 @@ uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
float32 ret = float32_div(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -236,7 +236,7 @@ uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
float64 ret = float64_div(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -247,7 +247,7 @@ uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
float128 ret = float128_div(make_float128(ah, al),
make_float128(bh, bl),
&env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
@@ -255,7 +255,7 @@ uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
float32 ret = float32_mul(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -263,7 +263,7 @@ uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
float64 ret = float64_mul(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -272,7 +272,7 @@ uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
float64 ret = float32_to_float64(f2, &env->fpu_status);
ret = float64_mul(f1, ret, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -283,7 +283,7 @@ uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
float128 ret = float128_mul(make_float128(ah, al),
make_float128(bh, bl),
&env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
@@ -293,7 +293,7 @@ uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al,
{
float128 ret = float64_to_float128(f2, &env->fpu_status);
ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
@@ -301,7 +301,7 @@ uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al,
uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
{
float64 ret = float32_to_float64(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -309,7 +309,7 @@ uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
{
float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -317,7 +317,7 @@ uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
{
float128 ret = float64_to_float128(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
@@ -325,7 +325,7 @@ uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
{
float128 ret = float32_to_float128(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
@@ -333,7 +333,7 @@ uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
{
float32 ret = float64_to_float32(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -341,7 +341,7 @@ uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
{
float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -349,7 +349,7 @@ uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
@@ -357,7 +357,7 @@ uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
@@ -368,7 +368,7 @@ uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
int cmp = float128_compare_quiet(make_float128(ah, al),
make_float128(bh, bl),
&env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
@@ -413,7 +413,7 @@ uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
float32 ret = int64_to_float32(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -424,7 +424,7 @@ uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
float64 ret = int64_to_float64(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -435,7 +435,7 @@ uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
float128 ret = int64_to_float128(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
@@ -446,7 +446,7 @@ uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
float32 ret = uint64_to_float32(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -457,7 +457,7 @@ uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
float64 ret = uint64_to_float64(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -468,7 +468,7 @@ uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
float128 ret = uint64_to_float128(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
@@ -479,7 +479,7 @@ uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
int64_t ret = float32_to_int64(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -490,7 +490,7 @@ uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
int64_t ret = float64_to_int64(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -502,7 +502,7 @@ uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
int64_t ret = float128_to_int64(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -513,7 +513,7 @@ uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
int32_t ret = float32_to_int32(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -524,7 +524,7 @@ uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
int32_t ret = float64_to_int32(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -536,7 +536,7 @@ uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
int32_t ret = float128_to_int32(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -549,7 +549,7 @@ uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
v2 = float32_to_float64(v2, &env->fpu_status);
ret = float64_to_uint64(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -560,7 +560,7 @@ uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
uint64_t ret = float64_to_uint64(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -571,7 +571,7 @@ uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
uint64_t ret = float128_to_uint64(make_float128(h, l), &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -582,7 +582,7 @@ uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
uint32_t ret = float32_to_uint32(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -593,7 +593,7 @@ uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
uint32_t ret = float64_to_uint32(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -604,7 +604,7 @@ uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
uint32_t ret = float128_to_uint32(make_float128(h, l), &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -615,7 +615,7 @@ uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
float32 ret = float32_round_to_int(f2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -626,7 +626,7 @@ uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
float64 ret = float64_round_to_int(f2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -634,11 +634,11 @@ uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
{
int old_mode = s390_swap_bfp_rounding_mode(env, m3);
-
float128 ret = float128_round_to_int(make_float128(ah, al),
&env->fpu_status);
+
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
@@ -646,7 +646,7 @@ uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
int cmp = float32_compare(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
@@ -654,7 +654,7 @@ uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
int cmp = float64_compare(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
@@ -665,7 +665,7 @@ uint32_t HELPER(kxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
int cmp = float128_compare(make_float128(ah, al),
make_float128(bh, bl),
&env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
@@ -674,7 +674,7 @@ uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
uint64_t f2, uint64_t f3)
{
float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -683,7 +683,7 @@ uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1,
uint64_t f2, uint64_t f3)
{
float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -693,7 +693,7 @@ uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1,
{
float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c,
&env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -703,7 +703,7 @@ uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
{
float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c,
&env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -759,7 +759,7 @@ uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint64_t m2)
uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
{
float32 ret = float32_sqrt(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -767,7 +767,7 @@ uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
{
float64 ret = float64_sqrt(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return ret;
}
@@ -775,7 +775,7 @@ uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
{
float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status);
- handle_exceptions(env, GETPC());
+ handle_exceptions(env, false, GETPC());
return RET128(ret);
}
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 24/27] s390x/tcg: Implement XxC and checks for most FP instructions
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (22 preceding siblings ...)
2019-03-04 12:02 ` [Qemu-devel] [PULL 23/27] s390x/tcg: Prepare for IEEE-inexact-exception control (XxC) Cornelia Huck
@ 2019-03-04 12:02 ` Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 25/27] s390x/tcg: Implement rounding mode and XxC for LOAD ROUNDED Cornelia Huck
` (3 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:02 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
With the floating-point extension facility
- CONVERT FROM LOGICAL
- CONVERT TO LOGICAL
- CONVERT TO FIXED
- CONVERT FROM FIXED
- LOAD FP INTEGER
have both, a rounding mode specification and the inexact-exception control
(XxC). Other instructions will be handled separatly.
Check for valid rounding modes and forward also the XxC (via m4). To avoid
a lot of boilerplate code and changes to the helpers, combine both, the
m3 and m4 field in a combined 32 bit TCG variable. Perform checks at
a central place, taking in account if the m3 or m4 field was ignore
before the floating-point extension facility was introduced.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190218122710.23639-13-david@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
target/s390x/fpu_helper.c | 138 ++++++++++++----------
target/s390x/translate.c | 235 ++++++++++++++++++++++++++++----------
2 files changed, 247 insertions(+), 126 deletions(-)
diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 293808c318c1..906280bfcddb 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -170,6 +170,17 @@ uint32_t set_cc_nz_f128(float128 v)
}
}
+static inline uint8_t round_from_m34(uint32_t m34)
+{
+ return extract32(m34, 0, 4);
+}
+
+static inline bool xxc_from_m34(uint32_t m34)
+{
+ /* XxC is bit 1 of m4 */
+ return extract32(m34, 4 + 3 - 1, 1);
+}
+
/* 32-bit FP addition */
uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
@@ -407,238 +418,239 @@ void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode)
}
/* convert 64-bit int to 32-bit float */
-uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float32 ret = int64_to_float32(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 64-bit int to 64-bit float */
-uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float64 ret = int64_to_float64(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 64-bit int to 128-bit float */
-uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float128 ret = int64_to_float128(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return RET128(ret);
}
/* convert 64-bit uint to 32-bit float */
-uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float32 ret = uint64_to_float32(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 64-bit uint to 64-bit float */
-uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float64 ret = uint64_to_float64(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 64-bit uint to 128-bit float */
-uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float128 ret = uint64_to_float128(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return RET128(ret);
}
/* convert 32-bit float to 64-bit int */
-uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
int64_t ret = float32_to_int64(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 64-bit float to 64-bit int */
-uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
int64_t ret = float64_to_int64(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 128-bit float to 64-bit int */
-uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float128 v2 = make_float128(h, l);
int64_t ret = float128_to_int64(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 32-bit float to 32-bit int */
-uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
int32_t ret = float32_to_int32(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 64-bit float to 32-bit int */
-uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
int32_t ret = float64_to_int32(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 128-bit float to 32-bit int */
-uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float128 v2 = make_float128(h, l);
int32_t ret = float128_to_int32(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 32-bit float to 64-bit uint */
-uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
uint64_t ret;
v2 = float32_to_float64(v2, &env->fpu_status);
ret = float64_to_uint64(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 64-bit float to 64-bit uint */
-uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
uint64_t ret = float64_to_uint64(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 128-bit float to 64-bit uint */
-uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
uint64_t ret = float128_to_uint64(make_float128(h, l), &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 32-bit float to 32-bit uint */
-uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
uint32_t ret = float32_to_uint32(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 64-bit float to 32-bit uint */
-uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
uint32_t ret = float64_to_uint32(v2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 128-bit float to 32-bit uint */
-uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
uint32_t ret = float128_to_uint32(make_float128(h, l), &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* round to integer 32-bit */
-uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
+uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float32 ret = float32_round_to_int(f2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* round to integer 64-bit */
-uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
+uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float64 ret = float64_round_to_int(f2, &env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* round to integer 128-bit */
-uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
+uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+ uint32_t m34)
{
- int old_mode = s390_swap_bfp_rounding_mode(env, m3);
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float128 ret = float128_round_to_int(make_float128(ah, al),
&env->fpu_status);
s390_restore_bfp_rounding_mode(env, old_mode);
- handle_exceptions(env, false, GETPC());
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return RET128(ret);
}
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 80952a30f972..7dc485e98925 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -1776,160 +1776,257 @@ static DisasJumpType op_cxb(DisasContext *s, DisasOps *o)
return DISAS_NEXT;
}
+static TCGv_i32 fpinst_extract_m34(DisasContext *s, bool m3_with_fpe,
+ bool m4_with_fpe)
+{
+ const bool fpe = s390_has_feat(S390_FEAT_FLOATING_POINT_EXT);
+ uint8_t m3 = get_field(s->fields, m3);
+ uint8_t m4 = get_field(s->fields, m4);
+
+ /* m3 field was introduced with FPE */
+ if (!fpe && m3_with_fpe) {
+ m3 = 0;
+ }
+ /* m4 field was introduced with FPE */
+ if (!fpe && m4_with_fpe) {
+ m4 = 0;
+ }
+
+ /* Check for valid rounding modes. Mode 3 was introduced later. */
+ if (m3 == 2 || m3 > 7 || (!fpe && m3 == 3)) {
+ gen_program_exception(s, PGM_SPECIFICATION);
+ return NULL;
+ }
+
+ return tcg_const_i32(deposit32(m3, 4, 4, m4));
+}
+
static DisasJumpType op_cfeb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cfeb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cfeb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f32(s, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_cfdb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cfdb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cfdb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f64(s, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_cfxb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cfxb(o->out, cpu_env, o->in1, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cfxb(o->out, cpu_env, o->in1, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f128(s, o->in1, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_cgeb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cgeb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cgeb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f32(s, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_cgdb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cgdb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cgdb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f64(s, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_cgxb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cgxb(o->out, cpu_env, o->in1, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cgxb(o->out, cpu_env, o->in1, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f128(s, o->in1, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_clfeb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clfeb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_clfeb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f32(s, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_clfdb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clfdb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_clfdb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f64(s, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_clfxb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clfxb(o->out, cpu_env, o->in1, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_clfxb(o->out, cpu_env, o->in1, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f128(s, o->in1, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_clgeb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clgeb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_clgeb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f32(s, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_clgdb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clgdb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_clgdb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f64(s, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_clgxb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clgxb(o->out, cpu_env, o->in1, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_clgxb(o->out, cpu_env, o->in1, o->in2, m34);
+ tcg_temp_free_i32(m34);
gen_set_cc_nz_f128(s, o->in1, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_cegb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cegb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cegb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
static DisasJumpType op_cdgb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cdgb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cdgb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
static DisasJumpType op_cxgb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cxgb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cxgb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return_low128(o->out2);
return DISAS_NEXT;
}
static DisasJumpType op_celgb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_celgb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_celgb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
static DisasJumpType op_cdlgb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cdlgb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cdlgb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
static DisasJumpType op_cxlgb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cxlgb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, false);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_cxlgb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return_low128(o->out2);
return DISAS_NEXT;
}
@@ -2408,26 +2505,38 @@ static DisasJumpType op_ex(DisasContext *s, DisasOps *o)
static DisasJumpType op_fieb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_fieb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_fieb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
static DisasJumpType op_fidb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_fidb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_fidb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
static DisasJumpType op_fixb(DisasContext *s, DisasOps *o)
{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_fixb(o->out, cpu_env, o->in1, o->in2, m3);
+ TCGv_i32 m34 = fpinst_extract_m34(s, false, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_fixb(o->out, cpu_env, o->in1, o->in2, m34);
return_low128(o->out2);
- tcg_temp_free_i32(m3);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 25/27] s390x/tcg: Implement rounding mode and XxC for LOAD ROUNDED
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (23 preceding siblings ...)
2019-03-04 12:02 ` [Qemu-devel] [PULL 24/27] s390x/tcg: Implement XxC and checks for most FP instructions Cornelia Huck
@ 2019-03-04 12:02 ` Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 26/27] s390x/tcg: Handle all rounding modes overwritten by BFP instructions Cornelia Huck
` (2 subsequent siblings)
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:02 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
With the floating-point extension facility, LOAD ROUNDED has
a rounding mode specification and the inexact-exception control (XxC).
Handle them just like e.g. LOAD FP INTEGER.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190218122710.23639-14-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
target/s390x/fpu_helper.c | 23 +++++++++++++++++------
target/s390x/helper.h | 6 +++---
target/s390x/insn-data.def | 6 +++---
target/s390x/translate.c | 24 +++++++++++++++++++++---
4 files changed, 44 insertions(+), 15 deletions(-)
diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 906280bfcddb..e258f20aa980 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -317,10 +317,14 @@ uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
}
/* convert 128-bit float to 64-bit float */
-uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
+uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+ uint32_t m34)
{
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
- handle_exceptions(env, false, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
@@ -341,18 +345,25 @@ uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
}
/* convert 64-bit float to 32-bit float */
-uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
+uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
{
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float32 ret = float64_to_float32(f2, &env->fpu_status);
- handle_exceptions(env, false, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
/* convert 128-bit float to 32-bit float */
-uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
+uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+ uint32_t m34)
{
+ int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
- handle_exceptions(env, false, GETPC());
+
+ s390_restore_bfp_rounding_mode(env, old_mode);
+ handle_exceptions(env, xxc_from_m34(m34), GETPC());
return ret;
}
diff --git a/target/s390x/helper.h b/target/s390x/helper.h
index d287d5dac093..bb659257f6cd 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 d80d168d4ef6..61b750a855e9 100644
--- a/target/s390x/insn-data.def
+++ b/target/s390x/insn-data.def
@@ -603,9 +603,9 @@
F(0xb324, LDER, RXE, Z, 0, e2, new, f1, lde, 0, IF_AFP1)
F(0xed24, LDE, RXE, Z, 0, m2_32u, new, f1, lde, 0, IF_AFP1)
/* 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 7dc485e98925..41fb466bb4fa 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -2805,19 +2805,37 @@ static DisasJumpType op_ldeb(DisasContext *s, DisasOps *o)
static DisasJumpType op_ledb(DisasContext *s, DisasOps *o)
{
- gen_helper_ledb(o->out, cpu_env, o->in2);
+ TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_ledb(o->out, cpu_env, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
static DisasJumpType op_ldxb(DisasContext *s, DisasOps *o)
{
- gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2);
+ TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
static DisasJumpType op_lexb(DisasContext *s, DisasOps *o)
{
- gen_helper_lexb(o->out, cpu_env, o->in1, o->in2);
+ TCGv_i32 m34 = fpinst_extract_m34(s, true, true);
+
+ if (!m34) {
+ return DISAS_NORETURN;
+ }
+ gen_helper_lexb(o->out, cpu_env, o->in1, o->in2, m34);
+ tcg_temp_free_i32(m34);
return DISAS_NEXT;
}
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Qemu-devel] [PULL 26/27] s390x/tcg: Handle all rounding modes overwritten by BFP instructions
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (24 preceding siblings ...)
2019-03-04 12:02 ` [Qemu-devel] [PULL 25/27] s390x/tcg: Implement rounding mode and XxC for LOAD ROUNDED Cornelia Huck
@ 2019-03-04 12:02 ` Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 27/27] s390x: Add floating-point extension facility to "qemu" cpu model Cornelia Huck
2019-03-04 14:29 ` [Qemu-devel] [PULL 00/27] s390x updates Peter Maydell
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:02 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
"round to nearest with ties away from 0" maps to float_round_ties_away.
"round to prepare for shorter precision" maps to float_round_to_odd.
As all instructions properly check for valid rounding modes in translate.c
we can add an assert. Fix one missing empty line.
Cc: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190218122710.23639-15-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
target/s390x/fpu_helper.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index e258f20aa980..1be68bafea30 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -397,14 +397,21 @@ 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 */
+ set_float_rounding_mode(float_round_to_odd, &env->fpu_status);
+ break;
case 4:
- /* round to nearest */
+ /* round to nearest with ties to even */
set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
break;
case 5:
@@ -419,6 +426,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] 29+ messages in thread
* [Qemu-devel] [PULL 27/27] s390x: Add floating-point extension facility to "qemu" cpu model
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (25 preceding siblings ...)
2019-03-04 12:02 ` [Qemu-devel] [PULL 26/27] s390x/tcg: Handle all rounding modes overwritten by BFP instructions Cornelia Huck
@ 2019-03-04 12:02 ` Cornelia Huck
2019-03-04 14:29 ` [Qemu-devel] [PULL 00/27] s390x updates Peter Maydell
27 siblings, 0 replies; 29+ messages in thread
From: Cornelia Huck @ 2019-03-04 12:02 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
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 mentions 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 indicated. We can ignore that for now.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190218122710.23639-16-david@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@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 44eca4547475..e4739a6b9f61 100644
--- a/target/s390x/gen-features.c
+++ b/target/s390x/gen-features.c
@@ -601,6 +601,11 @@ static uint16_t qemu_V3_1[] = {
};
static uint16_t qemu_LATEST[] = {
+ /*
+ * Only BFP bits are implemented (HFP, DFP, PFPO and DIVIDE TO INTEGER not
+ * implemented yet).
+ */
+ S390_FEAT_FLOATING_POINT_EXT,
S390_FEAT_ZPCI,
};
--
2.17.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [Qemu-devel] [PULL 00/27] s390x updates
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
` (26 preceding siblings ...)
2019-03-04 12:02 ` [Qemu-devel] [PULL 27/27] s390x: Add floating-point extension facility to "qemu" cpu model Cornelia Huck
@ 2019-03-04 14:29 ` Peter Maydell
27 siblings, 0 replies; 29+ messages in thread
From: Peter Maydell @ 2019-03-04 14:29 UTC (permalink / raw)
To: Cornelia Huck; +Cc: qemu-s390x, QEMU Developers
On Mon, 4 Mar 2019 at 12:02, Cornelia Huck <cohuck@redhat.com> wrote:
>
> The following changes since commit 20b084c4b1401b7f8fbc385649d48c67b6f43d44:
>
> Merge remote-tracking branch 'remotes/cminyard/tags/i2c-for-release-20190228' into staging (2019-03-01 11:20:49 +0000)
>
> are available in the Git repository at:
>
> https://github.com/cohuck/qemu tags/s390x-20190304
>
> for you to fetch changes up to df192fbc517a0954dda644282e52ba943e22ec18:
>
> s390x: Add floating-point extension facility to "qemu" cpu model (2019-03-04 11:49:31 +0100)
>
> ----------------------------------------------------------------
> s390x updates:
> - tcg: support the floating-point extension facility
> - vfio-ap: support hot(un)plug of vfio-ap device
> - fixes + cleanups
>
> ----------------------------------------------------------------
Applied, thanks.
Please update the changelog at https://wiki.qemu.org/ChangeLog/4.0
for any user-visible changes.
-- PMM
^ permalink raw reply [flat|nested] 29+ messages in thread
end of thread, other threads:[~2019-03-04 14:29 UTC | newest]
Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-03-04 12:01 [Qemu-devel] [PULL 00/27] s390x updates Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 01/27] s390x: Use cpu_to_be64 in SIGP STORE ADDITIONAL STATUS Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 02/27] s390x: use a QEMU-style typedef + name for SIGP save area struct Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 03/27] s390x/tcg: Save vregs to extended mchk save area Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 04/27] s390x/vfio-ap: Implement hot plug/unplug of vfio-ap device Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 05/27] s390x/vfio-ap: document " Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 06/27] s390x/tcg: RXE has an optional M3 field Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 07/27] s390x/tcg: Simplify disassembler operands initialization Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 08/27] s390x/tcg: Clarify terminology in vec_reg_offset() Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 09/27] s390x/tcg: Factor out vec_full_reg_offset() Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 10/27] s390x/tcg: Factor out gen_addi_and_wrap_i64() from get_address() Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 11/27] s390x/tcg: Implement LOAD LENGTHENED short HFP to long HFP Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 12/27] s390x/tcg: Implement LOAD COUNT TO BLOCK BOUNDARY Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 13/27] s390x/tcg: Fix TEST DATA CLASS instructions Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 14/27] s390x/tcg: Fix rounding from float128 to uint64_t/uint32_t Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 15/27] s390x/tcg: Factor out conversion of softfloat exceptions Cornelia Huck
2019-03-04 12:01 ` [Qemu-devel] [PULL 16/27] s390x/tcg: Fix parts of IEEE exception handling Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 17/27] s390x/tcg: Hide IEEE underflows in some scenarios Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 18/27] s390x/tcg: Refactor SET FPC AND SIGNAL handling Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 19/27] s390x/tcg: Fix simulated-IEEE exceptions Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 20/27] s390x/tcg: Handle SET FPC AND LOAD FPC 3-bit BFP rounding modes Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 21/27] s390x/tcg: Check for exceptions in SET BFP ROUNDING MODE Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 22/27] s390x/tcg: Refactor saving/restoring the bfp rounding mode Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 23/27] s390x/tcg: Prepare for IEEE-inexact-exception control (XxC) Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 24/27] s390x/tcg: Implement XxC and checks for most FP instructions Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 25/27] s390x/tcg: Implement rounding mode and XxC for LOAD ROUNDED Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 26/27] s390x/tcg: Handle all rounding modes overwritten by BFP instructions Cornelia Huck
2019-03-04 12:02 ` [Qemu-devel] [PULL 27/27] s390x: Add floating-point extension facility to "qemu" cpu model Cornelia Huck
2019-03-04 14:29 ` [Qemu-devel] [PULL 00/27] s390x updates Peter Maydell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).