aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-10-05 16:05:06 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-10-05 16:05:06 +0100
commitae7a4c0a4604bcfed40170db6cca576c44d872a2 (patch)
treed83bcc36c59924f4c1515d5cfad9a62e2bdafd9e
parentd21ee59ae5b6e3e7001b877c10c286d111bcf5b7 (diff)
parentb576d582ea2b03f4eada186fff59308d22b40a6a (diff)
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20181004' into staging
Various s390x updates: - fix several struct definitions so that sparc hosts do not trip over unaligned accesses - fence enabling huge pages for pre-3.1 machines - sysbus init -> realize conversion - fixes and improvements in tcg (instruction flags and AFP registers) # gpg: Signature made Thu 04 Oct 2018 16:22:20 BST # gpg: using RSA key DECF6B93C6F02FAF # gpg: Good signature from "Cornelia Huck <conny@cornelia-huck.de>" # gpg: aka "Cornelia Huck <huckc@linux.vnet.ibm.com>" # gpg: aka "Cornelia Huck <cornelia.huck@de.ibm.com>" # gpg: aka "Cornelia Huck <cohuck@kernel.org>" # gpg: aka "Cornelia Huck <cohuck@redhat.com>" # Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0 18CE DECF 6B93 C6F0 2FAF * remotes/cohuck/tags/s390x-20181004: hw/s390x/s390-pci-bus: Convert sysbus init function to realize function s390x/tcg: refactor specification checking s390x/tcg: fix FP register pair checks s390x/tcg: handle privileged instructions via flags s390x/tcg: check for AFP-register, BFP and DFP data exceptions s390x/tcg: add instruction flags for floating point instructions s390x/tcg: support flags for instructions s390x/tcg: store in the TB flags if AFP is enabled s390x/tcg: factor out and fix DATA exception injection s390x: move tcg_s390_program_interrupt() into TCG code and mark it noreturn target/s390x: exception on non-aligned LPSW(E) s390x: Fence huge pages prior to 3.1 hw/s390x/ioinst: Fix alignment problem in struct SubchDev hw/s390x/css: Remove QEMU_PACKED from struct SenseId hw/s390x/ipl: Fix alignment problems of S390IPLState members Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/s390x/css.c38
-rw-r--r--hw/s390x/ipl.h5
-rw-r--r--hw/s390x/s390-pci-bus.c34
-rw-r--r--hw/s390x/s390-virtio-ccw.c10
-rw-r--r--include/hw/s390x/css.h6
-rw-r--r--include/hw/s390x/ioinst.h21
-rw-r--r--include/hw/s390x/s390-virtio-ccw.h3
-rw-r--r--target/s390x/cpu.h9
-rw-r--r--target/s390x/excp_helper.c36
-rw-r--r--target/s390x/fpu_helper.c13
-rw-r--r--target/s390x/helper.h1
-rw-r--r--target/s390x/insn-data.def395
-rw-r--r--target/s390x/interrupt.c15
-rw-r--r--target/s390x/kvm.c10
-rw-r--r--target/s390x/tcg-stub.c10
-rw-r--r--target/s390x/tcg_s390x.h4
-rw-r--r--target/s390x/translate.c203
17 files changed, 430 insertions, 383 deletions
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 5a9fe45ce8..04ec5cc970 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -750,20 +750,25 @@ static void sch_handle_halt_func(SubchDev *sch)
}
-static void copy_sense_id_to_guest(SenseId *dest, SenseId *src)
+/*
+ * As the SenseId struct cannot be packed (would cause unaligned accesses), we
+ * have to copy the individual fields to an unstructured area using the correct
+ * layout (see SA22-7204-01 "Common I/O-Device Commands").
+ */
+static void copy_sense_id_to_guest(uint8_t *dest, SenseId *src)
{
int i;
- dest->reserved = src->reserved;
- dest->cu_type = cpu_to_be16(src->cu_type);
- dest->cu_model = src->cu_model;
- dest->dev_type = cpu_to_be16(src->dev_type);
- dest->dev_model = src->dev_model;
- dest->unused = src->unused;
- for (i = 0; i < ARRAY_SIZE(dest->ciw); i++) {
- dest->ciw[i].type = src->ciw[i].type;
- dest->ciw[i].command = src->ciw[i].command;
- dest->ciw[i].count = cpu_to_be16(src->ciw[i].count);
+ dest[0] = src->reserved;
+ stw_be_p(dest + 1, src->cu_type);
+ dest[3] = src->cu_model;
+ stw_be_p(dest + 4, src->dev_type);
+ dest[6] = src->dev_model;
+ dest[7] = src->unused;
+ for (i = 0; i < ARRAY_SIZE(src->ciw); i++) {
+ dest[8 + i * 4] = src->ciw[i].type;
+ dest[9 + i * 4] = src->ciw[i].command;
+ stw_be_p(dest + 10 + i * 4, src->ciw[i].count);
}
}
@@ -1044,9 +1049,10 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
break;
case CCW_CMD_SENSE_ID:
{
- SenseId sense_id;
+ /* According to SA22-7204-01, Sense-ID can store up to 256 bytes */
+ uint8_t sense_id[256];
- copy_sense_id_to_guest(&sense_id, &sch->id);
+ copy_sense_id_to_guest(sense_id, &sch->id);
/* Sense ID information is device specific. */
if (check_len) {
if (ccw.count != sizeof(sense_id)) {
@@ -1060,11 +1066,11 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
* have enough place to store at least bytes 0-3.
*/
if (len >= 4) {
- sense_id.reserved = 0xff;
+ sense_id[0] = 0xff;
} else {
- sense_id.reserved = 0;
+ sense_id[0] = 0;
}
- ccw_dstream_write_buf(&sch->cds, &sense_id, len);
+ ccw_dstream_write_buf(&sch->cds, sense_id, len);
sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds);
ret = 0;
break;
diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
index 4e87b89418..b3a07a12d8 100644
--- a/hw/s390x/ipl.h
+++ b/hw/s390x/ipl.h
@@ -132,15 +132,15 @@ typedef struct QemuIplParameters QemuIplParameters;
struct S390IPLState {
/*< private >*/
DeviceState parent_obj;
+ IplParameterBlock iplb;
+ QemuIplParameters qipl;
uint64_t start_addr;
uint64_t compat_start_addr;
uint64_t bios_start_addr;
uint64_t compat_bios_start_addr;
bool enforce_bios;
- IplParameterBlock iplb;
bool iplb_valid;
bool netboot;
- QemuIplParameters qipl;
/* reset related properties don't have to be migrated or reset */
enum s390_reset reset_type;
int reset_cpu_index;
@@ -157,6 +157,7 @@ struct S390IPLState {
bool iplbext_migration;
};
typedef struct S390IPLState S390IPLState;
+QEMU_BUILD_BUG_MSG(offsetof(S390IPLState, iplb) & 3, "alignment of iplb wrong");
#define S390_IPL_TYPE_FCP 0x00
#define S390_IPL_TYPE_CCW 0x02
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index e3e0ebb7f6..e42e1b80d6 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -692,27 +692,35 @@ static void s390_pci_iommu_free(S390pciState *s, PCIBus *bus, int32_t devfn)
object_unref(OBJECT(iommu));
}
-static int s390_pcihost_init(SysBusDevice *dev)
+static void s390_pcihost_realize(DeviceState *dev, Error **errp)
{
PCIBus *b;
BusState *bus;
PCIHostState *phb = PCI_HOST_BRIDGE(dev);
S390pciState *s = S390_PCI_HOST_BRIDGE(dev);
+ Error *local_err = NULL;
DPRINTF("host_init\n");
- b = pci_register_root_bus(DEVICE(dev), NULL,
- s390_pci_set_irq, s390_pci_map_irq, NULL,
- get_system_memory(), get_system_io(), 0, 64,
- TYPE_PCI_BUS);
+ b = pci_register_root_bus(dev, NULL, s390_pci_set_irq, s390_pci_map_irq,
+ NULL, get_system_memory(), get_system_io(), 0,
+ 64, TYPE_PCI_BUS);
pci_setup_iommu(b, s390_pci_dma_iommu, s);
bus = BUS(b);
- qbus_set_hotplug_handler(bus, DEVICE(dev), NULL);
+ qbus_set_hotplug_handler(bus, dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
phb->bus = b;
- s->bus = S390_PCI_BUS(qbus_create(TYPE_S390_PCI_BUS, DEVICE(s), NULL));
- qbus_set_hotplug_handler(BUS(s->bus), DEVICE(s), NULL);
+ s->bus = S390_PCI_BUS(qbus_create(TYPE_S390_PCI_BUS, dev, NULL));
+ qbus_set_hotplug_handler(BUS(s->bus), dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
s->iommu_table = g_hash_table_new_full(g_int64_hash, g_int64_equal,
NULL, g_free);
@@ -722,9 +730,10 @@ static int s390_pcihost_init(SysBusDevice *dev)
QTAILQ_INIT(&s->zpci_devs);
css_register_io_adapters(CSS_IO_ADAPTER_PCI, true, false,
- S390_ADAPTER_SUPPRESSIBLE, &error_abort);
-
- return 0;
+ S390_ADAPTER_SUPPRESSIBLE, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ }
}
static int s390_pci_msix_init(S390PCIBusDevice *pbdev)
@@ -1018,12 +1027,11 @@ static void s390_pcihost_reset(DeviceState *dev)
static void s390_pcihost_class_init(ObjectClass *klass, void *data)
{
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
dc->reset = s390_pcihost_reset;
- k->init = s390_pcihost_init;
+ dc->realize = s390_pcihost_realize;
hc->plug = s390_pcihost_hot_plug;
hc->unplug = s390_pcihost_hot_unplug;
msi_nonbroken = true;
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index f0f7fdcadd..53fd7c975f 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -456,6 +456,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
s390mc->ri_allowed = true;
s390mc->cpu_model_allowed = true;
s390mc->css_migration_enabled = true;
+ s390mc->hpage_1m_allowed = true;
mc->init = ccw_init;
mc->reset = s390_machine_reset;
mc->hot_add_cpu = s390_hot_add_cpu;
@@ -535,6 +536,12 @@ bool cpu_model_allowed(void)
return get_machine_class()->cpu_model_allowed;
}
+bool hpage_1m_allowed(void)
+{
+ /* for "none" machine this results in true */
+ return get_machine_class()->hpage_1m_allowed;
+}
+
static char *machine_get_loadparm(Object *obj, Error **errp)
{
S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
@@ -747,6 +754,9 @@ static void ccw_machine_3_0_instance_options(MachineState *machine)
static void ccw_machine_3_0_class_options(MachineClass *mc)
{
+ S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
+
+ s390mc->hpage_1m_allowed = false;
ccw_machine_3_1_class_options(mc);
SET_MACHINE_COMPAT(mc, CCW_COMPAT_3_0);
}
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index 9da5912921..aae19c4272 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -48,7 +48,7 @@ typedef struct SenseId {
uint8_t unused; /* padding byte */
/* extended part */
CIW ciw[MAX_CIWS]; /* variable # of CIWs */
-} QEMU_PACKED SenseId;
+} SenseId; /* Note: No QEMU_PACKED due to unaligned members */
/* Channel measurements, from linux/drivers/s390/cio/cmf.c. */
typedef struct CMB {
@@ -118,11 +118,12 @@ typedef enum IOInstEnding {
typedef struct SubchDev SubchDev;
struct SubchDev {
/* channel-subsystem related things: */
+ SCHIB curr_status; /* Needs alignment and thus must come first */
+ ORB orb;
uint8_t cssid;
uint8_t ssid;
uint16_t schid;
uint16_t devno;
- SCHIB curr_status;
uint8_t sense_data[32];
hwaddr channel_prog;
CCW1 last_cmd;
@@ -131,7 +132,6 @@ struct SubchDev {
bool thinint_active;
uint8_t ccw_no_data_cnt;
uint16_t migrated_schid; /* used for missmatch detection */
- ORB orb;
CcwDataStream cds;
/* transport-provided data: */
int (*ccw_cb) (SubchDev *, CCW1);
diff --git a/include/hw/s390x/ioinst.h b/include/hw/s390x/ioinst.h
index 5f2db6949d..c6737a30d4 100644
--- a/include/hw/s390x/ioinst.h
+++ b/include/hw/s390x/ioinst.h
@@ -25,7 +25,8 @@ typedef struct SCSW {
uint8_t dstat;
uint8_t cstat;
uint16_t count;
-} QEMU_PACKED SCSW;
+} SCSW;
+QEMU_BUILD_BUG_MSG(sizeof(SCSW) != 12, "size of SCSW is wrong");
#define SCSW_FLAGS_MASK_KEY 0xf000
#define SCSW_FLAGS_MASK_SCTL 0x0800
@@ -94,7 +95,8 @@ typedef struct PMCW {
uint8_t pam;
uint8_t chpid[8];
uint32_t chars;
-} QEMU_PACKED PMCW;
+} PMCW;
+QEMU_BUILD_BUG_MSG(sizeof(PMCW) != 28, "size of PMCW is wrong");
#define PMCW_FLAGS_MASK_QF 0x8000
#define PMCW_FLAGS_MASK_W 0x4000
@@ -127,7 +129,8 @@ typedef struct IRB {
uint32_t esw[5];
uint32_t ecw[8];
uint32_t emw[8];
-} QEMU_PACKED IRB;
+} IRB;
+QEMU_BUILD_BUG_MSG(sizeof(IRB) != 96, "size of IRB is wrong");
/* operation request block */
typedef struct ORB {
@@ -136,7 +139,8 @@ typedef struct ORB {
uint8_t lpm;
uint8_t ctrl1;
uint32_t cpa;
-} QEMU_PACKED ORB;
+} ORB;
+QEMU_BUILD_BUG_MSG(sizeof(ORB) != 12, "size of ORB is wrong");
#define ORB_CTRL0_MASK_KEY 0xf000
#define ORB_CTRL0_MASK_SPND 0x0800
@@ -165,7 +169,8 @@ typedef struct CCW0 {
uint8_t flags;
uint8_t reserved;
uint16_t count;
-} QEMU_PACKED CCW0;
+} CCW0;
+QEMU_BUILD_BUG_MSG(sizeof(CCW0) != 8, "size of CCW0 is wrong");
/* channel command word (type 1) */
typedef struct CCW1 {
@@ -173,7 +178,8 @@ typedef struct CCW1 {
uint8_t flags;
uint16_t count;
uint32_t cda;
-} QEMU_PACKED CCW1;
+} CCW1;
+QEMU_BUILD_BUG_MSG(sizeof(CCW1) != 8, "size of CCW1 is wrong");
#define CCW_FLAG_DC 0x80
#define CCW_FLAG_CC 0x40
@@ -192,7 +198,8 @@ typedef struct CCW1 {
typedef struct CRW {
uint16_t flags;
uint16_t rsid;
-} QEMU_PACKED CRW;
+} CRW;
+QEMU_BUILD_BUG_MSG(sizeof(CRW) != 4, "size of CRW is wrong");
#define CRW_FLAGS_MASK_S 0x4000
#define CRW_FLAGS_MASK_R 0x2000
diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h
index e9c4f4182b..8aa27199c9 100644
--- a/include/hw/s390x/s390-virtio-ccw.h
+++ b/include/hw/s390x/s390-virtio-ccw.h
@@ -39,12 +39,15 @@ typedef struct S390CcwMachineClass {
bool ri_allowed;
bool cpu_model_allowed;
bool css_migration_enabled;
+ bool hpage_1m_allowed;
} S390CcwMachineClass;
/* runtime-instrumentation allowed by the machine */
bool ri_allowed(void);
/* cpu model allowed by the machine */
bool cpu_model_allowed(void);
+/* 1M huge page mappings allowed by the machine */
+bool hpage_1m_allowed(void);
/**
* Returns true if (vmstate based) migration of the channel subsystem
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index 6f8861e554..8c2320e882 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -255,6 +255,7 @@ extern const struct VMStateDescription vmstate_s390_cpu;
/* PSW defines */
#undef PSW_MASK_PER
+#undef PSW_MASK_UNUSED_2
#undef PSW_MASK_DAT
#undef PSW_MASK_IO
#undef PSW_MASK_EXT
@@ -273,6 +274,7 @@ extern const struct VMStateDescription vmstate_s390_cpu;
#undef PSW_MASK_ESA_ADDR
#define PSW_MASK_PER 0x4000000000000000ULL
+#define PSW_MASK_UNUSED_2 0x2000000000000000ULL
#define PSW_MASK_DAT 0x0400000000000000ULL
#define PSW_MASK_IO 0x0200000000000000ULL
#define PSW_MASK_EXT 0x0100000000000000ULL
@@ -318,10 +320,14 @@ extern const struct VMStateDescription vmstate_s390_cpu;
#define FLAG_MASK_PSW (FLAG_MASK_PER | FLAG_MASK_DAT | FLAG_MASK_PSTATE \
| FLAG_MASK_ASC | FLAG_MASK_64 | FLAG_MASK_32)
+/* we'll use some unused PSW positions to store CR flags in tb flags */
+#define FLAG_MASK_AFP (PSW_MASK_UNUSED_2 >> FLAG_MASK_PSW_SHIFT)
+
/* Control register 0 bits */
#define CR0_LOWPROT 0x0000000010000000ULL
#define CR0_SECONDARY 0x0000000004000000ULL
#define CR0_EDAT 0x0000000000800000ULL
+#define CR0_AFP 0x0000000000040000ULL
#define CR0_EMERGENCY_SIGNAL_SC 0x0000000000004000ULL
#define CR0_EXTERNAL_CALL_SC 0x0000000000002000ULL
#define CR0_CKC_SC 0x0000000000000800ULL
@@ -363,6 +369,9 @@ static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc,
*pc = env->psw.addr;
*cs_base = env->ex_value;
*flags = (env->psw.mask >> FLAG_MASK_PSW_SHIFT) & FLAG_MASK_PSW;
+ if (env->cregs[0] & CR0_AFP) {
+ *flags |= FLAG_MASK_AFP;
+ }
}
/* PER bits from control register 9 */
diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c
index f0ce60cff2..cd76c3163a 100644
--- a/target/s390x/excp_helper.c
+++ b/target/s390x/excp_helper.c
@@ -21,11 +21,13 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "internal.h"
+#include "exec/helper-proto.h"
#include "qemu/timer.h"
#include "exec/exec-all.h"
#include "exec/cpu_ldst.h"
#include "hw/s390x/ioinst.h"
#include "exec/address-spaces.h"
+#include "tcg_s390x.h"
#ifndef CONFIG_USER_ONLY
#include "sysemu/sysemu.h"
#include "hw/s390x/s390_flic.h"
@@ -48,6 +50,40 @@
do { } while (0)
#endif
+void QEMU_NORETURN tcg_s390_program_interrupt(CPUS390XState *env, uint32_t code,
+ int ilen, uintptr_t ra)
+{
+ CPUState *cs = CPU(s390_env_get_cpu(env));
+
+ cpu_restore_state(cs, ra, true);
+ qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n",
+ env->psw.addr);
+ trigger_pgm_exception(env, code, ilen);
+ cpu_loop_exit(cs);
+}
+
+void QEMU_NORETURN tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc,
+ uintptr_t ra)
+{
+ g_assert(dxc <= 0xff);
+#if !defined(CONFIG_USER_ONLY)
+ /* Store the DXC into the lowcore */
+ stl_phys(CPU(s390_env_get_cpu(env))->as,
+ env->psa + offsetof(LowCore, data_exc_code), dxc);
+#endif
+
+ /* Store the DXC into the FPC if AFP is enabled */
+ if (env->cregs[0] & CR0_AFP) {
+ env->fpc = deposit32(env->fpc, 8, 8, dxc);
+ }
+ tcg_s390_program_interrupt(env, PGM_DATA, ILEN_AUTO, ra);
+}
+
+void HELPER(data_exception)(CPUS390XState *env, uint32_t dxc)
+{
+ tcg_s390_data_exception(env, dxc, GETPC());
+}
+
#if defined(CONFIG_USER_ONLY)
void s390_cpu_do_interrupt(CPUState *cs)
diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 5c5b451b3b..1b662d2520 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "internal.h"
+#include "tcg_s390x.h"
#include "exec/exec-all.h"
#include "exec/cpu_ldst.h"
#include "exec/helper-proto.h"
@@ -40,14 +41,6 @@
? (mask / (from / to)) & to \
: (mask & from) * (to / from))
-static void ieee_exception(CPUS390XState *env, uint32_t dxc, uintptr_t retaddr)
-{
- /* Install the DXC code. */
- env->fpc = (env->fpc & ~0xff00) | (dxc << 8);
- /* Trap. */
- s390_program_interrupt(env, PGM_DATA, ILEN_AUTO, retaddr);
-}
-
/* Should be called after any operation that may raise IEEE exceptions. */
static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
{
@@ -75,7 +68,7 @@ static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
/* Send signals for enabled exceptions. */
s390_exc &= env->fpc >> 24;
if (s390_exc) {
- ieee_exception(env, s390_exc, retaddr);
+ tcg_s390_data_exception(env, s390_exc, retaddr);
}
}
@@ -773,6 +766,6 @@ void HELPER(sfas)(CPUS390XState *env, uint64_t val)
is also 1, a simulated-iee-exception trap occurs. */
s390_exc = (signalling >> 16) & (source >> 24);
if (s390_exc) {
- ieee_exception(env, s390_exc | 3, GETPC());
+ tcg_s390_data_exception(env, s390_exc | 3, GETPC());
}
}
diff --git a/target/s390x/helper.h b/target/s390x/helper.h
index 97c60ca7bc..018e9dd414 100644
--- a/target/s390x/helper.h
+++ b/target/s390x/helper.h
@@ -1,4 +1,5 @@
DEF_HELPER_2(exception, noreturn, env, i32)
+DEF_HELPER_2(data_exception, noreturn, env, i32)
DEF_HELPER_FLAGS_4(nc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
DEF_HELPER_FLAGS_4(oc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
DEF_HELPER_FLAGS_4(xc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def
index 9c7b434fca..54e39df831 100644
--- a/target/s390x/insn-data.def
+++ b/target/s390x/insn-data.def
@@ -3,6 +3,8 @@
*
* C(OPC, NAME, FMT, FAC, I1, I2, P, W, OP, CC)
* D(OPC, NAME, FMT, FAC, I1, I2, P, W, OP, CC, DATA)
+ * E(OPC, NAME, FMT, FAC, I1, I2, P, W, OP, CC, DATA, FLAGS)
+ * F(OPC, NAME, FMT, FAC, I1, I2, P, W, OP, CC, FLAGS)
*
* OPC = (op << 8) | op2 where op is the major, op2 the minor opcode
* NAME = name of the opcode, used internally
@@ -15,6 +17,7 @@
* OP = func op_xx does the bulk of the operation
* CC = func cout_xx defines how cc should get set
* DATA = immediate argument to op_xx function
+ * FLAGS = categorize the type of instruction (e.g. for advanced checks)
*
* The helpers get called in order: I1, I2, P, OP, W, CC
*/
@@ -29,11 +32,11 @@
C(0xb9e8, AGRK, RRF_a, DO, r2, r3, r1, 0, add, adds64)
C(0xe308, AG, RXY_a, Z, r1, m2_64, r1, 0, add, adds64)
C(0xe318, AGF, RXY_a, Z, r1, m2_32s, r1, 0, add, adds64)
- C(0xb30a, AEBR, RRE, Z, e1, e2, new, e1, aeb, f32)
- C(0xb31a, ADBR, RRE, Z, f1_o, f2_o, f1, 0, adb, f64)
- C(0xb34a, AXBR, RRE, Z, 0, x2_o, x1, 0, axb, f128)
- C(0xed0a, AEB, RXE, Z, e1, m2_32u, new, e1, aeb, f32)
- C(0xed1a, ADB, RXE, Z, f1_o, m2_64, f1, 0, adb, f64)
+ F(0xb30a, AEBR, RRE, Z, e1, e2, new, e1, aeb, f32, IF_BFP)
+ F(0xb31a, ADBR, RRE, Z, f1_o, f2_o, f1, 0, adb, f64, IF_BFP)
+ F(0xb34a, AXBR, RRE, Z, 0, x2_o, x1, 0, axb, f128, IF_BFP)
+ F(0xed0a, AEB, RXE, Z, e1, m2_32u, new, e1, aeb, f32, IF_BFP)
+ F(0xed1a, ADB, RXE, Z, f1_o, m2_64, f1, 0, adb, f64, IF_BFP)
/* ADD HIGH */
C(0xb9c8, AHHHR, RRF_a, HW, r2_sr32, r3_sr32, new, r1_32h, add, adds32)
C(0xb9d8, AHHLR, RRF_a, HW, r2_sr32, r3, new, r1_32h, add, adds32)
@@ -151,7 +154,7 @@
C(0xb241, CKSM, RRE, Z, r1_o, ra2, new, r1_32, cksm, 0)
/* COPY SIGN */
- C(0xb372, CPSDR, RRF_b, FPSSH, f3_o, f2_o, f1, 0, cps, 0)
+ F(0xb372, CPSDR, RRF_b, FPSSH, f3_o, f2_o, f1, 0, cps, 0, IF_AFP1 | IF_AFP2 | IF_AFP3)
/* COMPARE */
C(0x1900, CR, RR_a, Z, r1_o, r2_o, 0, 0, 0, cmps32)
@@ -161,17 +164,17 @@
C(0xb930, CGFR, RRE, Z, r1_o, r2_32s, 0, 0, 0, cmps64)
C(0xe320, CG, RXY_a, Z, r1_o, m2_64, 0, 0, 0, cmps64)
C(0xe330, CGF, RXY_a, Z, r1_o, m2_32s, 0, 0, 0, cmps64)
- C(0xb309, CEBR, RRE, Z, e1, e2, 0, 0, ceb, 0)
- C(0xb319, CDBR, RRE, Z, f1_o, f2_o, 0, 0, cdb, 0)
- C(0xb349, CXBR, RRE, Z, x1_o, x2_o, 0, 0, cxb, 0)
- C(0xed09, CEB, RXE, Z, e1, m2_32u, 0, 0, ceb, 0)
- C(0xed19, CDB, RXE, Z, f1_o, m2_64, 0, 0, cdb, 0)
+ F(0xb309, CEBR, RRE, Z, e1, e2, 0, 0, ceb, 0, IF_BFP)
+ F(0xb319, CDBR, RRE, Z, f1_o, f2_o, 0, 0, cdb, 0, IF_BFP)
+ F(0xb349, CXBR, RRE, Z, x1_o, x2_o, 0, 0, cxb, 0, IF_BFP)
+ F(0xed09, CEB, RXE, Z, e1, m2_32u, 0, 0, ceb, 0, IF_BFP)
+ F(0xed19, CDB, RXE, Z, f1_o, m2_64, 0, 0, cdb, 0, IF_BFP)
/* COMPARE AND SIGNAL */
- C(0xb308, KEBR, RRE, Z, e1, e2, 0, 0, keb, 0)
- C(0xb318, KDBR, RRE, Z, f1_o, f2_o, 0, 0, kdb, 0)
- C(0xb348, KXBR, RRE, Z, x1_o, x2_o, 0, 0, kxb, 0)
- C(0xed08, KEB, RXE, Z, e1, m2_32u, 0, 0, keb, 0)
- C(0xed18, KDB, RXE, Z, f1_o, m2_64, 0, 0, kdb, 0)
+ F(0xb308, KEBR, RRE, Z, e1, e2, 0, 0, keb, 0, IF_BFP)
+ F(0xb318, KDBR, RRE, Z, f1_o, f2_o, 0, 0, kdb, 0, IF_BFP)
+ F(0xb348, KXBR, RRE, Z, x1_o, x2_o, 0, 0, kxb, 0, IF_BFP)
+ F(0xed08, KEB, RXE, Z, e1, m2_32u, 0, 0, keb, 0, IF_BFP)
+ F(0xed18, KDB, RXE, Z, f1_o, m2_64, 0, 0, kdb, 0, IF_BFP)
/* COMPARE IMMEDIATE */
C(0xc20d, CFI, RIL_a, EI, r1, i2, 0, 0, 0, cmps32)
C(0xc20c, CGFI, RIL_a, EI, r1, i2, 0, 0, 0, cmps64)
@@ -288,33 +291,33 @@
C(0x4e00, CVD, RX_a, Z, r1_o, a2, 0, 0, cvd, 0)
C(0xe326, CVDY, RXY_a, LD, r1_o, a2, 0, 0, cvd, 0)
/* CONVERT TO FIXED */
- C(0xb398, CFEBR, RRF_e, Z, 0, e2, new, r1_32, cfeb, 0)
- C(0xb399, CFDBR, RRF_e, Z, 0, f2_o, new, r1_32, cfdb, 0)
- C(0xb39a, CFXBR, RRF_e, Z, 0, x2_o, new, r1_32, cfxb, 0)
- C(0xb3a8, CGEBR, RRF_e, Z, 0, e2, r1, 0, cgeb, 0)
- C(0xb3a9, CGDBR, RRF_e, Z, 0, f2_o, r1, 0, cgdb, 0)
- C(0xb3aa, CGXBR, RRF_e, Z, 0, x2_o, r1, 0, cgxb, 0)
+ F(0xb398, CFEBR, RRF_e, Z, 0, e2, new, r1_32, cfeb, 0, IF_BFP)
+ F(0xb399, CFDBR, RRF_e, Z, 0, f2_o, new, r1_32, cfdb, 0, IF_BFP)
+ F(0xb39a, CFXBR, RRF_e, Z, 0, x2_o, new, r1_32, cfxb, 0, IF_BFP)
+ F(0xb3a8, CGEBR, RRF_e, Z, 0, e2, r1, 0, cgeb, 0, IF_BFP)
+ F(0xb3a9, CGDBR, RRF_e, Z, 0, f2_o, r1, 0, cgdb, 0, IF_BFP)
+ F(0xb3aa, CGXBR, RRF_e, Z, 0, x2_o, r1, 0, cgxb, 0, IF_BFP)
/* CONVERT FROM FIXED */
- C(0xb394, CEFBR, RRF_e, Z, 0, r2_32s, new, e1, cegb, 0)
- C(0xb395, CDFBR, RRF_e, Z, 0, r2_32s, f1, 0, cdgb, 0)
- C(0xb396, CXFBR, RRF_e, Z, 0, r2_32s, x1, 0, cxgb, 0)
- C(0xb3a4, CEGBR, RRF_e, Z, 0, r2_o, new, e1, cegb, 0)
- C(0xb3a5, CDGBR, RRF_e, Z, 0, r2_o, f1, 0, cdgb, 0)
- C(0xb3a6, CXGBR, RRF_e, Z, 0, r2_o, x1, 0, cxgb, 0)
+ F(0xb394, CEFBR, RRF_e, Z, 0, r2_32s, new, e1, cegb, 0, IF_BFP)
+ F(0xb395, CDFBR, RRF_e, Z, 0, r2_32s, f1, 0, cdgb, 0, IF_BFP)
+ F(0xb396, CXFBR, RRF_e, Z, 0, r2_32s, x1, 0, cxgb, 0, IF_BFP)
+ F(0xb3a4, CEGBR, RRF_e, Z, 0, r2_o, new, e1, cegb, 0, IF_BFP)
+ F(0xb3a5, CDGBR, RRF_e, Z, 0, r2_o, f1, 0, cdgb, 0, IF_BFP)
+ F(0xb3a6, CXGBR, RRF_e, Z, 0, r2_o, x1, 0, cxgb, 0, IF_BFP)
/* CONVERT TO LOGICAL */
- C(0xb39c, CLFEBR, RRF_e, FPE, 0, e2, new, r1_32, clfeb, 0)
- C(0xb39d, CLFDBR, RRF_e, FPE, 0, f2_o, new, r1_32, clfdb, 0)
- C(0xb39e, CLFXBR, RRF_e, FPE, 0, x2_o, new, r1_32, clfxb, 0)
- C(0xb3ac, CLGEBR, RRF_e, FPE, 0, e2, r1, 0, clgeb, 0)
- C(0xb3ad, CLGDBR, RRF_e, FPE, 0, f2_o, r1, 0, clgdb, 0)
- C(0xb3ae, CLGXBR, RRF_e, FPE, 0, x2_o, r1, 0, clgxb, 0)
+ F(0xb39c, CLFEBR, RRF_e, FPE, 0, e2, new, r1_32, clfeb, 0, IF_BFP)
+ F(0xb39d, CLFDBR, RRF_e, FPE, 0, f2_o, new, r1_32, clfdb, 0, IF_BFP)
+ F(0xb39e, CLFXBR, RRF_e, FPE, 0, x2_o, new, r1_32, clfxb, 0, IF_BFP)
+ F(0xb3ac, CLGEBR, RRF_e, FPE, 0, e2, r1, 0, clgeb, 0, IF_BFP)
+ F(0xb3ad, CLGDBR, RRF_e, FPE, 0, f2_o, r1, 0, clgdb, 0, IF_BFP)
+ F(0xb3ae, CLGXBR, RRF_e, FPE, 0, x2_o, r1, 0, clgxb, 0, IF_BFP)
/* CONVERT FROM LOGICAL */
- C(0xb390, CELFBR, RRF_e, FPE, 0, r2_32u, new, e1, celgb, 0)
- C(0xb391, CDLFBR, RRF_e, FPE, 0, r2_32u, f1, 0, cdlgb, 0)
- C(0xb392, CXLFBR, RRF_e, FPE, 0, r2_32u, x1, 0, cxlgb, 0)
- C(0xb3a0, CELGBR, RRF_e, FPE, 0, r2_o, new, e1, celgb, 0)
- C(0xb3a1, CDLGBR, RRF_e, FPE, 0, r2_o, f1, 0, cdlgb, 0)
- C(0xb3a2, CXLGBR, RRF_e, FPE, 0, r2_o, x1, 0, cxlgb, 0)
+ F(0xb390, CELFBR, RRF_e, FPE, 0, r2_32u, new, e1, celgb, 0, IF_BFP)
+ F(0xb391, CDLFBR, RRF_e, FPE, 0, r2_32u, f1, 0, cdlgb, 0, IF_BFP)
+ F(0xb392, CXLFBR, RRF_e, FPE, 0, r2_32u, x1, 0, cxlgb, 0, IF_BFP)
+ F(0xb3a0, CELGBR, RRF_e, FPE, 0, r2_o, new, e1, celgb, 0, IF_BFP)
+ F(0xb3a1, CDLGBR, RRF_e, FPE, 0, r2_o, f1, 0, cdlgb, 0, IF_BFP)
+ F(0xb3a2, CXLGBR, RRF_e, FPE, 0, r2_o, x1, 0, cxlgb, 0, IF_BFP)
/* CONVERT UTF-8 TO UTF-16 */
D(0xb2a7, CU12, RRF_c, Z, 0, 0, 0, 0, cuXX, 0, 12)
@@ -332,11 +335,11 @@
/* DIVIDE */
C(0x1d00, DR, RR_a, Z, r1_D32, r2_32s, new_P, r1_P32, divs32, 0)
C(0x5d00, D, RX_a, Z, r1_D32, m2_32s, new_P, r1_P32, divs32, 0)
- C(0xb30d, DEBR, RRE, Z, e1, e2, new, e1, deb, 0)
- C(0xb31d, DDBR, RRE, Z, f1_o, f2_o, f1, 0, ddb, 0)
- C(0xb34d, DXBR, RRE, Z, 0, x2_o, x1, 0, dxb, 0)
- C(0xed0d, DEB, RXE, Z, e1, m2_32u, new, e1, deb, 0)
- C(0xed1d, DDB, RXE, Z, f1_o, m2_64, f1, 0, ddb, 0)
+ F(0xb30d, DEBR, RRE, Z, e1, e2, new, e1, deb, 0, IF_BFP)
+ F(0xb31d, DDBR, RRE, Z, f1_o, f2_o, f1, 0, ddb, 0, IF_BFP)
+ F(0xb34d, DXBR, RRE, Z, 0, x2_o, x1, 0, dxb, 0, IF_BFP)
+ F(0xed0d, DEB, RXE, Z, e1, m2_32u, new, e1, deb, 0, IF_BFP)
+ F(0xed1d, DDB, RXE, Z, f1_o, m2_64, f1, 0, ddb, 0, IF_BFP)
/* DIVIDE LOGICAL */
C(0xb997, DLR, RRE, Z, r1_D32, r2_32u, new_P, r1_P32, divu32, 0)
C(0xe397, DL, RXY_a, Z, r1_D32, m2_32u, new_P, r1_P32, divu32, 0)
@@ -375,7 +378,7 @@
/* EXTRACT CPU TIME */
C(0xc801, ECTG, SSF, ECT, 0, 0, 0, 0, ectg, 0)
/* EXTRACT FPC */
- C(0xb38c, EFPC, RRE, Z, 0, 0, new, r1_32, efpc, 0)
+ F(0xb38c, EFPC, RRE, Z, 0, 0, new, r1_32, efpc, 0, IF_BFP)
/* EXTRACT PSW */
C(0xb98d, EPSW, RRE, Z, 0, 0, 0, 0, epsw, 0)
@@ -407,13 +410,13 @@
C(0xb914, LGFR, RRE, Z, 0, r2_32s, 0, r1, mov2, 0)
C(0xe304, LG, RXY_a, Z, 0, a2, r1, 0, ld64, 0)
C(0xe314, LGF, RXY_a, Z, 0, a2, r1, 0, ld32s, 0)
- C(0x2800, LDR, RR_a, Z, 0, f2_o, 0, f1, mov2, 0)
- C(0x6800, LD, RX_a, Z, 0, m2_64, 0, f1, mov2, 0)
- C(0xed65, LDY, RXY_a, LD, 0, m2_64, 0, f1, mov2, 0)
- C(0x3800, LER, RR_a, Z, 0, e2, 0, cond_e1e2, mov2, 0)
- C(0x7800, LE, RX_a, Z, 0, m2_32u, 0, e1, mov2, 0)
- C(0xed64, LEY, RXY_a, LD, 0, m2_32u, 0, e1, mov2, 0)
- C(0xb365, LXR, RRE, Z, 0, x2_o, 0, x1, movx, 0)
+ F(0x2800, LDR, RR_a, Z, 0, f2_o, 0, f1, mov2, 0, IF_AFP1 | IF_AFP2)
+ F(0x6800, LD, RX_a, Z, 0, m2_64, 0, f1, mov2, 0, IF_AFP1)
+ F(0xed65, LDY, RXY_a, LD, 0, m2_64, 0, f1, mov2, 0, IF_AFP1)
+ F(0x3800, LER, RR_a, Z, 0, e2, 0, cond_e1e2, mov2, 0, IF_AFP1 | IF_AFP2)
+ F(0x7800, LE, RX_a, Z, 0, m2_32u, 0, e1, mov2, 0, IF_AFP1)
+ F(0xed64, LEY, RXY_a, LD, 0, m2_32u, 0, e1, mov2, 0, IF_AFP1)
+ F(0xb365, LXR, RRE, Z, 0, x2_o, 0, x1, movx, 0, IF_AFP1)
/* LOAD IMMEDIATE */
C(0xc001, LGFI, RIL_a, EI, 0, i2, 0, r1, mov2, 0)
/* LOAD RELATIVE LONG */
@@ -450,9 +453,9 @@
C(0xe312, LT, RXY_a, EI, 0, a2, new, r1_32, ld32s, s64)
C(0xe302, LTG, RXY_a, EI, 0, a2, r1, 0, ld64, s64)
C(0xe332, LTGF, RXY_a, GIE, 0, a2, r1, 0, ld32s, s64)
- C(0xb302, LTEBR, RRE, Z, 0, e2, 0, cond_e1e2, mov2, f32)
- C(0xb312, LTDBR, RRE, Z, 0, f2_o, 0, f1, mov2, f64)
- C(0xb342, LTXBR, RRE, Z, 0, x2_o, 0, x1, movx, f128)
+ F(0xb302, LTEBR, RRE, Z, 0, e2, 0, cond_e1e2, mov2, f32, IF_BFP)
+ F(0xb312, LTDBR, RRE, Z, 0, f2_o, 0, f1, mov2, f64, IF_BFP)
+ F(0xb342, LTXBR, RRE, Z, 0, x2_o, 0, x1, movx, f128, IF_BFP)
/* LOAD AND TRAP */
C(0xe39f, LAT, RXY_a, LAT, 0, m2_32u, r1, 0, lat, 0)
C(0xe385, LGAT, RXY_a, LAT, 0, a2, r1, 0, lgat, 0)
@@ -472,10 +475,10 @@
C(0x1300, LCR, RR_a, Z, 0, r2, new, r1_32, neg, neg32)
C(0xb903, LCGR, RRE, Z, 0, r2, r1, 0, neg, neg64)
C(0xb913, LCGFR, RRE, Z, 0, r2_32s, r1, 0, neg, neg64)
- C(0xb303, LCEBR, RRE, Z, 0, e2, new, e1, negf32, f32)
- C(0xb313, LCDBR, RRE, Z, 0, f2_o, f1, 0, negf64, f64)
- C(0xb343, LCXBR, RRE, Z, 0, x2_o, x1, 0, negf128, f128)
- C(0xb373, LCDFR, RRE, FPSSH, 0, f2_o, f1, 0, negf64, 0)
+ F(0xb303, LCEBR, RRE, Z, 0, e2, new, e1, negf32, f32, IF_BFP)
+ F(0xb313, LCDBR, RRE, Z, 0, f2_o, f1, 0, negf64, f64, IF_BFP)
+ F(0xb343, LCXBR, RRE, Z, 0, x2_o, x1, 0, negf128, f128, IF_BFP)
+ F(0xb373, LCDFR, RRE, FPSSH, 0, f2_o, f1, 0, negf64, 0, IF_AFP1 | IF_AFP2)
/* 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)
@@ -532,17 +535,17 @@
C(0xe39c, LLGTAT, RXY_a, LAT, 0, m2_32u, r1, 0, llgtat, 0)
/* LOAD FPR FROM GR */
- C(0xb3c1, LDGR, RRE, FPRGR, 0, r2_o, 0, f1, mov2, 0)
+ F(0xb3c1, LDGR, RRE, FPRGR, 0, r2_o, 0, f1, mov2, 0, IF_AFP1)
/* LOAD GR FROM FPR */
- C(0xb3cd, LGDR, RRE, FPRGR, 0, f2_o, 0, r1, mov2, 0)
+ F(0xb3cd, LGDR, RRE, FPRGR, 0, f2_o, 0, r1, mov2, 0, IF_AFP2)
/* LOAD NEGATIVE */
C(0x1100, LNR, RR_a, Z, 0, r2_32s, new, r1_32, nabs, nabs32)
C(0xb901, LNGR, RRE, Z, 0, r2, r1, 0, nabs, nabs64)
C(0xb911, LNGFR, RRE, Z, 0, r2_32s, r1, 0, nabs, nabs64)
- C(0xb301, LNEBR, RRE, Z, 0, e2, new, e1, nabsf32, f32)
- C(0xb311, LNDBR, RRE, Z, 0, f2_o, f1, 0, nabsf64, f64)
- C(0xb341, LNXBR, RRE, Z, 0, x2_o, x1, 0, nabsf128, f128)
- C(0xb371, LNDFR, RRE, FPSSH, 0, f2_o, f1, 0, nabsf64, 0)
+ F(0xb301, LNEBR, RRE, Z, 0, e2, new, e1, nabsf32, f32, IF_BFP)
+ F(0xb311, LNDBR, RRE, Z, 0, f2_o, f1, 0, nabsf64, f64, IF_BFP)
+ F(0xb341, LNXBR, RRE, Z, 0, x2_o, x1, 0, nabsf128, f128, IF_BFP)
+ F(0xb371, LNDFR, RRE, FPSSH, 0, f2_o, f1, 0, nabsf64, 0, IF_AFP1 | IF_AFP2)
/* LOAD ON CONDITION */
C(0xb9f2, LOCR, RRF_c, LOC, r1, r2, new, r1_32, loc, 0)
C(0xb9e2, LOCGR, RRF_c, LOC, r1, r2, r1, 0, loc, 0)
@@ -564,10 +567,10 @@
C(0x1000, LPR, RR_a, Z, 0, r2_32s, new, r1_32, abs, abs32)
C(0xb900, LPGR, RRE, Z, 0, r2, r1, 0, abs, abs64)
C(0xb910, LPGFR, RRE, Z, 0, r2_32s, r1, 0, abs, abs64)
- C(0xb300, LPEBR, RRE, Z, 0, e2, new, e1, absf32, f32)
- C(0xb310, LPDBR, RRE, Z, 0, f2_o, f1, 0, absf64, f64)
- C(0xb340, LPXBR, RRE, Z, 0, x2_o, x1, 0, absf128, f128)
- C(0xb370, LPDFR, RRE, FPSSH, 0, f2_o, f1, 0, absf64, 0)
+ F(0xb300, LPEBR, RRE, Z, 0, e2, new, e1, absf32, f32, IF_BFP)
+ F(0xb310, LPDBR, RRE, Z, 0, f2_o, f1, 0, absf64, f64, IF_BFP)
+ F(0xb340, LPXBR, RRE, Z, 0, x2_o, x1, 0, absf128, f128, IF_BFP)
+ F(0xb370, LPDFR, RRE, FPSSH, 0, f2_o, f1, 0, absf64, 0, IF_AFP1 | IF_AFP2)
/* LOAD REVERSED */
C(0xb91f, LRVR, RRE, Z, 0, r2_32u, new, r1_32, rev32, 0)
C(0xb90f, LRVGR, RRE, Z, 0, r2_o, r1, 0, rev64, 0)
@@ -575,30 +578,30 @@
C(0xe31e, LRV, RXY_a, Z, 0, m2_32u, new, r1_32, rev32, 0)
C(0xe30f, LRVG, RXY_a, Z, 0, m2_64, r1, 0, rev64, 0)
/* LOAD ZERO */
- C(0xb374, LZER, RRE, Z, 0, 0, 0, e1, zero, 0)
- C(0xb375, LZDR, RRE, Z, 0, 0, 0, f1, zero, 0)
- C(0xb376, LZXR, RRE, Z, 0, 0, 0, x1, zero2, 0)
+ F(0xb374, LZER, RRE, Z, 0, 0, 0, e1, zero, 0, IF_AFP1)
+ F(0xb375, LZDR, RRE, Z, 0, 0, 0, f1, zero, 0, IF_AFP1)
+ F(0xb376, LZXR, RRE, Z, 0, 0, 0, x1, zero2, 0, IF_AFP1)
/* LOAD FPC */
- C(0xb29d, LFPC, S, Z, 0, m2_32u, 0, 0, sfpc, 0)
+ F(0xb29d, LFPC, S, Z, 0, m2_32u, 0, 0, sfpc, 0, IF_BFP)
/* LOAD FPC AND SIGNAL */
- C(0xb2bd, LFAS, S, IEEEE_SIM, 0, m2_32u, 0, 0, sfas, 0)
+ F(0xb2bd, LFAS, S, IEEEE_SIM, 0, m2_32u, 0, 0, sfas, 0, IF_DFP)
/* LOAD FP INTEGER */
- C(0xb357, FIEBR, RRF_e, Z, 0, e2, new, e1, fieb, 0)
- C(0xb35f, FIDBR, RRF_e, Z, 0, f2_o, f1, 0, fidb, 0)
- C(0xb347, FIXBR, RRF_e, Z, 0, x2_o, x1, 0, fixb, 0)
+ F(0xb357, FIEBR, RRF_e, Z, 0, e2, new, e1, fieb, 0, IF_BFP)
+ F(0xb35f, FIDBR, RRF_e, Z, 0, f2_o, f1, 0, fidb, 0, IF_BFP)
+ F(0xb347, FIXBR, RRF_e, Z, 0, x2_o, x1, 0, fixb, 0, IF_BFP)
/* LOAD LENGTHENED */
- C(0xb304, LDEBR, RRE, Z, 0, e2, f1, 0, ldeb, 0)
- C(0xb305, LXDBR, RRE, Z, 0, f2_o, x1, 0, lxdb, 0)
- C(0xb306, LXEBR, RRE, Z, 0, e2, x1, 0, lxeb, 0)
- C(0xed04, LDEB, RXE, Z, 0, m2_32u, f1, 0, ldeb, 0)
- C(0xed05, LXDB, RXE, Z, 0, m2_64, x1, 0, lxdb, 0)
- C(0xed06, LXEB, RXE, Z, 0, m2_32u, x1, 0, lxeb, 0)
+ F(0xb304, LDEBR, RRE, Z, 0, e2, f1, 0, ldeb, 0, IF_BFP)
+ F(0xb305, LXDBR, RRE, Z, 0, f2_o, x1, 0, lxdb, 0, IF_BFP)
+ F(0xb306, LXEBR, RRE, Z, 0, e2, x1, 0, lxeb, 0, IF_BFP)
+ F(0xed04, LDEB, RXE, Z, 0, m2_32u, f1, 0, ldeb, 0, IF_BFP)
+ F(0xed05, LXDB, RXE, Z, 0, m2_64, x1, 0, lxdb, 0, IF_BFP)
+ F(0xed06, LXEB, RXE, Z, 0, m2_32u, x1, 0, lxeb, 0, IF_BFP)
/* LOAD ROUNDED */
- C(0xb344, LEDBR, RRE, Z, 0, f2_o, new, e1, ledb, 0)
- C(0xb345, LDXBR, RRE, Z, 0, x2_o, f1, 0, ldxb, 0)
- C(0xb346, LEXBR, RRE, Z, 0, x2_o, new, e1, lexb, 0)
+ F(0xb344, LEDBR, RRE, Z, 0, f2_o, new, e1, ledb, 0, IF_BFP)
+ F(0xb345, LDXBR, RRE, Z, 0, x2_o, f1, 0, ldxb, 0, IF_BFP)
+ F(0xb346, LEXBR, RRE, Z, 0, x2_o, new, e1, lexb, 0, IF_BFP)
/* LOAD MULTIPLE */
C(0x9800, LM, RS_a, Z, 0, a2, 0, 0, lm32, 0)
@@ -644,15 +647,15 @@
C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0)
C(0x5c00, M, RX_a, Z, r1p1_32s, m2_32s, new, r1_D32, mul, 0)
C(0xe35c, MFY, RXY_a, GIE, r1p1_32s, m2_32s, new, r1_D32, mul, 0)
- C(0xb317, MEEBR, RRE, Z, e1, e2, new, e1, meeb, 0)
- C(0xb31c, MDBR, RRE, Z, f1_o, f2_o, f1, 0, mdb, 0)
- C(0xb34c, MXBR, RRE, Z, 0, x2_o, x1, 0, mxb, 0)
- C(0xb30c, MDEBR, RRE, Z, f1_o, e2, f1, 0, mdeb, 0)
- C(0xb307, MXDBR, RRE, Z, 0, f2_o, x1, 0, mxdb, 0)
- C(0xed17, MEEB, RXE, Z, e1, m2_32u, new, e1, meeb, 0)
- C(0xed1c, MDB, RXE, Z, f1_o, m2_64, f1, 0, mdb, 0)
- C(0xed0c, MDEB, RXE, Z, f1_o, m2_32u, f1, 0, mdeb, 0)
- C(0xed07, MXDB, RXE, Z, 0, m2_64, x1, 0, mxdb, 0)
+ F(0xb317, MEEBR, RRE, Z, e1, e2, new, e1, meeb, 0, IF_BFP)
+ F(0xb31c, MDBR, RRE, Z, f1_o, f2_o, f1, 0, mdb, 0, IF_BFP)
+ F(0xb34c, MXBR, RRE, Z, 0, x2_o, x1, 0, mxb, 0, IF_BFP)
+ F(0xb30c, MDEBR, RRE, Z, f1_o, e2, f1, 0, mdeb, 0, IF_BFP)
+ F(0xb307, MXDBR, RRE, Z, 0, f2_o, x1, 0, mxdb, 0, IF_BFP)
+ F(0xed17, MEEB, RXE, Z, e1, m2_32u, new, e1, meeb, 0, IF_BFP)
+ F(0xed1c, MDB, RXE, Z, f1_o, m2_64, f1, 0, mdb, 0, IF_BFP)
+ F(0xed0c, MDEB, RXE, Z, f1_o, m2_32u, f1, 0, mdeb, 0, IF_BFP)
+ F(0xed07, MXDB, RXE, Z, 0, m2_64, x1, 0, mxdb, 0, IF_BFP)
/* MULTIPLY HALFWORD */
C(0x4c00, MH, RX_a, Z, r1_o, m2_16s, new, r1_32, mul, 0)
C(0xe37c, MHY, RXY_a, GIE, r1_o, m2_16s, new, r1_32, mul, 0)
@@ -677,15 +680,15 @@
C(0xc200, MSGFI, RIL_a, GIE, r1_o, i2, r1, 0, mul, 0)
/* MULTIPLY AND ADD */
- C(0xb30e, MAEBR, RRD, Z, e1, e2, new, e1, maeb, 0)
- C(0xb31e, MADBR, RRD, Z, f1_o, f2_o, f1, 0, madb, 0)
- C(0xed0e, MAEB, RXF, Z, e1, m2_32u, new, e1, maeb, 0)
- C(0xed1e, MADB, RXF, Z, f1_o, m2_64, f1, 0, madb, 0)
+ F(0xb30e, MAEBR, RRD, Z, e1, e2, new, e1, maeb, 0, IF_BFP)
+ F(0xb31e, MADBR, RRD, Z, f1_o, f2_o, f1, 0, madb, 0, IF_BFP)
+ F(0xed0e, MAEB, RXF, Z, e1, m2_32u, new, e1, maeb, 0, IF_BFP)
+ F(0xed1e, MADB, RXF, Z, f1_o, m2_64, f1, 0, madb, 0, IF_BFP)
/* MULTIPLY AND SUBTRACT */
- C(0xb30f, MSEBR, RRD, Z, e1, e2, new, e1, mseb, 0)
- C(0xb31f, MSDBR, RRD, Z, f1_o, f2_o, f1, 0, msdb, 0)
- C(0xed0f, MSEB, RXF, Z, e1, m2_32u, new, e1, mseb, 0)
- C(0xed1f, MSDB, RXF, Z, f1_o, m2_64, f1, 0, msdb, 0)
+ F(0xb30f, MSEBR, RRD, Z, e1, e2, new, e1, mseb, 0, IF_BFP)
+ F(0xb31f, MSDBR, RRD, Z, f1_o, f2_o, f1, 0, msdb, 0, IF_BFP)
+ F(0xed0f, MSEB, RXF, Z, e1, m2_32u, new, e1, mseb, 0, IF_BFP)
+ F(0xed1f, MSDB, RXF, Z, f1_o, m2_64, f1, 0, msdb, 0, IF_BFP)
/* OR */
C(0x1600, OR, RR_a, Z, r1, r2, new, r1_32, or, nz32)
@@ -752,14 +755,14 @@
D(0x010d, SAM31, E, Z, 0, 0, 0, 0, sam, 0, 1)
D(0x010e, SAM64, E, Z, 0, 0, 0, 0, sam, 0, 3)
/* SET FPC */
- C(0xb384, SFPC, RRE, Z, 0, r1_o, 0, 0, sfpc, 0)
+ F(0xb384, SFPC, RRE, Z, 0, r1_o, 0, 0, sfpc, 0, IF_BFP)
/* SET FPC AND SIGNAL */
- C(0xb385, SFASR, RRE, IEEEE_SIM, 0, r1_o, 0, 0, sfas, 0)
+ F(0xb385, SFASR, RRE, IEEEE_SIM, 0, r1_o, 0, 0, sfas, 0, IF_DFP)
/* SET BFP ROUNDING MODE */
- C(0xb299, SRNM, S, Z, 0, 0, 0, 0, srnm, 0)
- C(0xb2b8, SRNMB, S, FPE, 0, 0, 0, 0, srnm, 0)
+ 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)
/* SET DFP ROUNDING MODE */
- C(0xb2b9, SRNMT, S, DFPR, 0, 0, 0, 0, srnm, 0)
+ F(0xb2b9, SRNMT, S, DFPR, 0, 0, 0, 0, srnm, 0, IF_DFP)
/* SET PROGRAM MASK */
C(0x0400, SPM, RR_a, Z, r1, 0, 0, 0, spm, 0)
@@ -789,20 +792,20 @@
C(0x8c00, SRDL, RS_a, Z, r1_D32, sh64, new, r1_D32, srl, 0)
/* SQUARE ROOT */
- C(0xb314, SQEBR, RRE, Z, 0, e2, new, e1, sqeb, 0)
- C(0xb315, SQDBR, RRE, Z, 0, f2_o, f1, 0, sqdb, 0)
- C(0xb316, SQXBR, RRE, Z, 0, x2_o, x1, 0, sqxb, 0)
- C(0xed14, SQEB, RXE, Z, 0, m2_32u, new, e1, sqeb, 0)
- C(0xed15, SQDB, RXE, Z, 0, m2_64, f1, 0, sqdb, 0)
+ F(0xb314, SQEBR, RRE, Z, 0, e2, new, e1, sqeb, 0, IF_BFP)
+ F(0xb315, SQDBR, RRE, Z, 0, f2_o, f1, 0, sqdb, 0, IF_BFP)
+ F(0xb316, SQXBR, RRE, Z, 0, x2_o, x1, 0, sqxb, 0, IF_BFP)
+ F(0xed14, SQEB, RXE, Z, 0, m2_32u, new, e1, sqeb, 0, IF_BFP)
+ F(0xed15, SQDB, RXE, Z, 0, m2_64, f1, 0, sqdb, 0, IF_BFP)
/* STORE */
C(0x5000, ST, RX_a, Z, r1_o, a2, 0, 0, st32, 0)
C(0xe350, STY, RXY_a, LD, r1_o, a2, 0, 0, st32, 0)
C(0xe324, STG, RXY_a, Z, r1_o, a2, 0, 0, st64, 0)
- C(0x6000, STD, RX_a, Z, f1_o, a2, 0, 0, st64, 0)
- C(0xed67, STDY, RXY_a, LD, f1_o, a2, 0, 0, st64, 0)
- C(0x7000, STE, RX_a, Z, e1, a2, 0, 0, st32, 0)
- C(0xed66, STEY, RXY_a, LD, e1, a2, 0, 0, st32, 0)
+ F(0x6000, STD, RX_a, Z, f1_o, a2, 0, 0, st64, 0, IF_AFP1)
+ F(0xed67, STDY, RXY_a, LD, f1_o, a2, 0, 0, st64, 0, IF_AFP1)
+ F(0x7000, STE, RX_a, Z, e1, a2, 0, 0, st32, 0, IF_AFP1)
+ F(0xed66, STEY, RXY_a, LD, e1, a2, 0, 0, st32, 0, IF_AFP1)
/* STORE RELATIVE LONG */
C(0xc40f, STRL, RIL_b, GIE, r1_o, ri2, 0, 0, st32, 0)
C(0xc40b, STGRL, RIL_b, GIE, r1_o, ri2, 0, 0, st64, 0)
@@ -837,7 +840,7 @@
/* STORE FACILITY LIST EXTENDED */
C(0xb2b0, STFLE, S, SFLE, 0, a2, 0, 0, stfle, 0)
/* STORE FPC */
- C(0xb29c, STFPC, S, Z, 0, a2, new, m2_32, efpc, 0)
+ F(0xb29c, STFPC, S, Z, 0, a2, new, m2_32, efpc, 0, IF_BFP)
/* STORE MULTIPLE */
D(0x9000, STM, RS_a, Z, 0, a2, 0, 0, stm, 0, 4)
@@ -861,11 +864,11 @@
C(0xb9e9, SGRK, RRF_a, DO, r2, r3, r1, 0, sub, subs64)
C(0xe309, SG, RXY_a, Z, r1, m2_64, r1, 0, sub, subs64)
C(0xe319, SGF, RXY_a, Z, r1, m2_32s, r1, 0, sub, subs64)
- C(0xb30b, SEBR, RRE, Z, e1, e2, new, e1, seb, f32)
- C(0xb31b, SDBR, RRE, Z, f1_o, f2_o, f1, 0, sdb, f64)
- C(0xb34b, SXBR, RRE, Z, 0, x2_o, x1, 0, sxb, f128)
- C(0xed0b, SEB, RXE, Z, e1, m2_32u, new, e1, seb, f32)
- C(0xed1b, SDB, RXE, Z, f1_o, m2_64, f1, 0, sdb, f64)
+ F(0xb30b, SEBR, RRE, Z, e1, e2, new, e1, seb, f32, IF_BFP)
+ F(0xb31b, SDBR, RRE, Z, f1_o, f2_o, f1, 0, sdb, f64, IF_BFP)
+ F(0xb34b, SXBR, RRE, Z, 0, x2_o, x1, 0, sxb, f128, IF_BFP)
+ F(0xed0b, SEB, RXE, Z, e1, m2_32u, new, e1, seb, f32, IF_BFP)
+ F(0xed1b, SDB, RXE, Z, f1_o, m2_64, f1, 0, sdb, f64, IF_BFP)
/* SUBTRACT HALFWORD */
C(0x4b00, SH, RX_a, Z, r1, m2_16s, new, r1_32, sub, subs32)
C(0xe37b, SHY, RXY_a, LD, r1, m2_16s, new, r1_32, sub, subs32)
@@ -904,9 +907,9 @@
C(0x9300, TS, S, Z, 0, a2, 0, 0, ts, 0)
/* TEST DATA CLASS */
- C(0xed10, TCEB, RXE, Z, e1, a2, 0, 0, tceb, 0)
- C(0xed11, TCDB, RXE, Z, f1_o, a2, 0, 0, tcdb, 0)
- C(0xed12, TCXB, RXE, Z, x1_o, a2, 0, 0, tcxb, 0)
+ F(0xed10, TCEB, RXE, Z, e1, a2, 0, 0, tceb, 0, IF_BFP)
+ F(0xed11, TCDB, RXE, Z, f1_o, a2, 0, 0, tcdb, 0, IF_BFP)
+ F(0xed12, TCXB, RXE, Z, x1_o, a2, 0, 0, tcxb, 0, IF_BFP)
/* TEST DECIMAL */
C(0xebc0, TP, RSL, E2, la1, 0, 0, 0, tp, 0)
@@ -961,126 +964,126 @@
#ifndef CONFIG_USER_ONLY
/* COMPARE AND SWAP AND PURGE */
- D(0xb250, CSP, RRE, Z, r1_32u, ra2, r1_P, 0, csp, 0, MO_TEUL)
- D(0xb98a, CSPG, RRE, DAT_ENH, r1_o, ra2, r1_P, 0, csp, 0, MO_TEQ)
+ E(0xb250, CSP, RRE, Z, r1_32u, ra2, r1_P, 0, csp, 0, MO_TEUL, IF_PRIV)
+ E(0xb98a, CSPG, RRE, DAT_ENH, r1_o, ra2, r1_P, 0, csp, 0, MO_TEQ, IF_PRIV)
/* DIAGNOSE (KVM hypercall) */
- C(0x8300, DIAG, RSI, Z, 0, 0, 0, 0, diag, 0)
+ F(0x8300, DIAG, RSI, Z, 0, 0, 0, 0, diag, 0, IF_PRIV)
/* INSERT STORAGE KEY EXTENDED */
- C(0xb229, ISKE, RRE, Z, 0, r2_o, new, r1_8, iske, 0)
+ F(0xb229, ISKE, RRE, Z, 0, r2_o, new, r1_8, iske, 0, IF_PRIV)
/* INVALIDATE DAT TABLE ENTRY */
- C(0xb98e, IPDE, RRF_b, Z, r1_o, r2_o, 0, 0, idte, 0)
+ F(0xb98e, IPDE, RRF_b, Z, r1_o, r2_o, 0, 0, idte, 0, IF_PRIV)
/* INVALIDATE PAGE TABLE ENTRY */
- C(0xb221, IPTE, RRF_a, Z, r1_o, r2_o, 0, 0, ipte, 0)
+ F(0xb221, IPTE, RRF_a, Z, r1_o, r2_o, 0, 0, ipte, 0, IF_PRIV)
/* LOAD CONTROL */
- C(0xb700, LCTL, RS_a, Z, 0, a2, 0, 0, lctl, 0)
- C(0xeb2f, LCTLG, RSY_a, Z, 0, a2, 0, 0, lctlg, 0)
+ F(0xb700, LCTL, RS_a, Z, 0, a2, 0, 0, lctl, 0, IF_PRIV)
+ F(0xeb2f, LCTLG, RSY_a, Z, 0, a2, 0, 0, lctlg, 0, IF_PRIV)
/* LOAD PROGRAM PARAMETER */
- C(0xb280, LPP, S, LPP, 0, m2_64, 0, 0, lpp, 0)
+ F(0xb280, LPP, S, LPP, 0, m2_64, 0, 0, lpp, 0, IF_PRIV)
/* LOAD PSW */
- C(0x8200, LPSW, S, Z, 0, a2, 0, 0, lpsw, 0)
+ F(0x8200, LPSW, S, Z, 0, a2, 0, 0, lpsw, 0, IF_PRIV)
/* LOAD PSW EXTENDED */
- C(0xb2b2, LPSWE, S, Z, 0, a2, 0, 0, lpswe, 0)
+ F(0xb2b2, LPSWE, S, Z, 0, a2, 0, 0, lpswe, 0, IF_PRIV)
/* LOAD REAL ADDRESS */
- C(0xb100, LRA, RX_a, Z, 0, a2, r1, 0, lra, 0)
- C(0xe313, LRAY, RXY_a, LD, 0, a2, r1, 0, lra, 0)
- C(0xe303, LRAG, RXY_a, Z, 0, a2, r1, 0, lra, 0)
+ F(0xb100, LRA, RX_a, Z, 0, a2, r1, 0, lra, 0, IF_PRIV)
+ F(0xe313, LRAY, RXY_a, LD, 0, a2, r1, 0, lra, 0, IF_PRIV)
+ F(0xe303, LRAG, RXY_a, Z, 0, a2, r1, 0, lra, 0, IF_PRIV)
/* LOAD USING REAL ADDRESS */
- C(0xb24b, LURA, RRE, Z, 0, r2, new, r1_32, lura, 0)
- C(0xb905, LURAG, RRE, Z, 0, r2, r1, 0, lurag, 0)
+ F(0xb24b, LURA, RRE, Z, 0, r2, new, r1_32, lura, 0, IF_PRIV)
+ F(0xb905, LURAG, RRE, Z, 0, r2, r1, 0, lurag, 0, IF_PRIV)
/* MOVE TO PRIMARY */
- C(0xda00, MVCP, SS_d, Z, la1, a2, 0, 0, mvcp, 0)
+ F(0xda00, MVCP, SS_d, Z, la1, a2, 0, 0, mvcp, 0, IF_PRIV)
/* MOVE TO SECONDARY */
- C(0xdb00, MVCS, SS_d, Z, la1, a2, 0, 0, mvcs, 0)
+ F(0xdb00, MVCS, SS_d, Z, la1, a2, 0, 0, mvcs, 0, IF_PRIV)
/* PURGE TLB */
- C(0xb20d, PTLB, S, Z, 0, 0, 0, 0, ptlb, 0)
+ F(0xb20d, PTLB, S, Z, 0, 0, 0, 0, ptlb, 0, IF_PRIV)
/* RESET REFERENCE BIT EXTENDED */
- C(0xb22a, RRBE, RRE, Z, 0, r2_o, 0, 0, rrbe, 0)
+ F(0xb22a, RRBE, RRE, Z, 0, r2_o, 0, 0, rrbe, 0, IF_PRIV)
/* SERVICE CALL LOGICAL PROCESSOR (PV hypercall) */
- C(0xb220, SERVC, RRE, Z, r1_o, r2_o, 0, 0, servc, 0)
+ F(0xb220, SERVC, RRE, Z, r1_o, r2_o, 0, 0, servc, 0, IF_PRIV)
/* SET ADDRESS SPACE CONTROL FAST */
- C(0xb279, SACF, S, Z, 0, a2, 0, 0, sacf, 0)
+ F(0xb279, SACF, S, Z, 0, a2, 0, 0, sacf, 0, IF_PRIV)
/* SET CLOCK */
- C(0xb204, SCK, S, Z, la2, 0, 0, 0, sck, 0)
+ F(0xb204, SCK, S, Z, la2, 0, 0, 0, sck, 0, IF_PRIV)
/* SET CLOCK COMPARATOR */
- C(0xb206, SCKC, S, Z, 0, m2_64a, 0, 0, sckc, 0)
+ F(0xb206, SCKC, S, Z, 0, m2_64a, 0, 0, sckc, 0, IF_PRIV)
/* SET CLOCK PROGRAMMABLE FIELD */
- C(0x0107, SCKPF, E, Z, 0, 0, 0, 0, sckpf, 0)
+ F(0x0107, SCKPF, E, Z, 0, 0, 0, 0, sckpf, 0, IF_PRIV)
/* SET CPU TIMER */
- C(0xb208, SPT, S, Z, 0, m2_64a, 0, 0, spt, 0)
+ F(0xb208, SPT, S, Z, 0, m2_64a, 0, 0, spt, 0, IF_PRIV)
/* SET PREFIX */
- C(0xb210, SPX, S, Z, 0, m2_32ua, 0, 0, spx, 0)
+ F(0xb210, SPX, S, Z, 0, m2_32ua, 0, 0, spx, 0, IF_PRIV)
/* SET PSW KEY FROM ADDRESS */
- C(0xb20a, SPKA, S, Z, 0, a2, 0, 0, spka, 0)
+ F(0xb20a, SPKA, S, Z, 0, a2, 0, 0, spka, 0, IF_PRIV)
/* SET STORAGE KEY EXTENDED */
- C(0xb22b, SSKE, RRF_c, Z, r1_o, r2_o, 0, 0, sske, 0)
+ F(0xb22b, SSKE, RRF_c, Z, r1_o, r2_o, 0, 0, sske, 0, IF_PRIV)
/* SET SYSTEM MASK */
- C(0x8000, SSM, S, Z, 0, m2_8u, 0, 0, ssm, 0)
+ F(0x8000, SSM, S, Z, 0, m2_8u, 0, 0, ssm, 0, IF_PRIV)
/* SIGNAL PROCESSOR */
- C(0xae00, SIGP, RS_a, Z, 0, a2, 0, 0, sigp, 0)
+ F(0xae00, SIGP, RS_a, Z, 0, a2, 0, 0, sigp, 0, IF_PRIV)
/* STORE CLOCK */
C(0xb205, STCK, S, Z, la2, 0, new, m1_64, stck, 0)
C(0xb27c, STCKF, S, SCF, la2, 0, new, m1_64, stck, 0)
/* STORE CLOCK EXTENDED */
C(0xb278, STCKE, S, Z, 0, a2, 0, 0, stcke, 0)
/* STORE CLOCK COMPARATOR */
- C(0xb207, STCKC, S, Z, la2, 0, new, m1_64a, stckc, 0)
+ F(0xb207, STCKC, S, Z, la2, 0, new, m1_64a, stckc, 0, IF_PRIV)
/* STORE CONTROL */
- C(0xb600, STCTL, RS_a, Z, 0, a2, 0, 0, stctl, 0)
- C(0xeb25, STCTG, RSY_a, Z, 0, a2, 0, 0, stctg, 0)
+ F(0xb600, STCTL, RS_a, Z, 0, a2, 0, 0, stctl, 0, IF_PRIV)
+ F(0xeb25, STCTG, RSY_a, Z, 0, a2, 0, 0, stctg, 0, IF_PRIV)
/* STORE CPU ADDRESS */
- C(0xb212, STAP, S, Z, la2, 0, new, m1_16a, stap, 0)
+ F(0xb212, STAP, S, Z, la2, 0, new, m1_16a, stap, 0, IF_PRIV)
/* STORE CPU ID */
- C(0xb202, STIDP, S, Z, la2, 0, new, m1_64a, stidp, 0)
+ F(0xb202, STIDP, S, Z, la2, 0, new, m1_64a, stidp, 0, IF_PRIV)
/* STORE CPU TIMER */
- C(0xb209, STPT, S, Z, la2, 0, new, m1_64a, stpt, 0)
+ F(0xb209, STPT, S, Z, la2, 0, new, m1_64a, stpt, 0, IF_PRIV)
/* STORE FACILITY LIST */
- C(0xb2b1, STFL, S, Z, 0, 0, 0, 0, stfl, 0)
+ F(0xb2b1, STFL, S, Z, 0, 0, 0, 0, stfl, 0, IF_PRIV)
/* STORE PREFIX */
- C(0xb211, STPX, S, Z, la2, 0, new, m1_32a, stpx, 0)
+ F(0xb211, STPX, S, Z, la2, 0, new, m1_32a, stpx, 0, IF_PRIV)
/* STORE SYSTEM INFORMATION */
- C(0xb27d, STSI, S, Z, 0, a2, 0, 0, stsi, 0)
+ F(0xb27d, STSI, S, Z, 0, a2, 0, 0, stsi, 0, IF_PRIV)
/* STORE THEN AND SYSTEM MASK */
- C(0xac00, STNSM, SI, Z, la1, 0, 0, 0, stnosm, 0)
+ F(0xac00, STNSM, SI, Z, la1, 0, 0, 0, stnosm, 0, IF_PRIV)
/* STORE THEN OR SYSTEM MASK */
- C(0xad00, STOSM, SI, Z, la1, 0, 0, 0, stnosm, 0)
+ F(0xad00, STOSM, SI, Z, la1, 0, 0, 0, stnosm, 0, IF_PRIV)
/* STORE USING REAL ADDRESS */
- C(0xb246, STURA, RRE, Z, r1_o, r2_o, 0, 0, stura, 0)
- C(0xb925, STURG, RRE, Z, r1_o, r2_o, 0, 0, sturg, 0)
+ F(0xb246, STURA, RRE, Z, r1_o, r2_o, 0, 0, stura, 0, IF_PRIV)
+ F(0xb925, STURG, RRE, Z, r1_o, r2_o, 0, 0, sturg, 0, IF_PRIV)
/* TEST BLOCK */
- C(0xb22c, TB, RRE, Z, 0, r2_o, 0, 0, testblock, 0)
+ F(0xb22c, TB, RRE, Z, 0, r2_o, 0, 0, testblock, 0, IF_PRIV)
/* TEST PROTECTION */
C(0xe501, TPROT, SSE, Z, la1, a2, 0, 0, tprot, 0)
/* CCW I/O Instructions */
- C(0xb276, XSCH, S, Z, 0, 0, 0, 0, xsch, 0)
- C(0xb230, CSCH, S, Z, 0, 0, 0, 0, csch, 0)
- C(0xb231, HSCH, S, Z, 0, 0, 0, 0, hsch, 0)
- C(0xb232, MSCH, S, Z, 0, insn, 0, 0, msch, 0)
- C(0xb23b, RCHP, S, Z, 0, 0, 0, 0, rchp, 0)
- C(0xb238, RSCH, S, Z, 0, 0, 0, 0, rsch, 0)
- C(0xb237, SAL, S, Z, 0, 0, 0, 0, sal, 0)
- C(0xb23c, SCHM, S, Z, 0, insn, 0, 0, schm, 0)
- C(0xb274, SIGA, S, Z, 0, 0, 0, 0, siga, 0)
- C(0xb23a, STCPS, S, Z, 0, 0, 0, 0, stcps, 0)
- C(0xb233, SSCH, S, Z, 0, insn, 0, 0, ssch, 0)
- C(0xb239, STCRW, S, Z, 0, insn, 0, 0, stcrw, 0)
- C(0xb234, STSCH, S, Z, 0, insn, 0, 0, stsch, 0)
- C(0xb236, TPI , S, Z, la2, 0, 0, 0, tpi, 0)
- C(0xb235, TSCH, S, Z, 0, insn, 0, 0, tsch, 0)
+ F(0xb276, XSCH, S, Z, 0, 0, 0, 0, xsch, 0, IF_PRIV)
+ F(0xb230, CSCH, S, Z, 0, 0, 0, 0, csch, 0, IF_PRIV)
+ F(0xb231, HSCH, S, Z, 0, 0, 0, 0, hsch, 0, IF_PRIV)
+ F(0xb232, MSCH, S, Z, 0, insn, 0, 0, msch, 0, IF_PRIV)
+ F(0xb23b, RCHP, S, Z, 0, 0, 0, 0, rchp, 0, IF_PRIV)
+ F(0xb238, RSCH, S, Z, 0, 0, 0, 0, rsch, 0, IF_PRIV)
+ F(0xb237, SAL, S, Z, 0, 0, 0, 0, sal, 0, IF_PRIV)
+ F(0xb23c, SCHM, S, Z, 0, insn, 0, 0, schm, 0, IF_PRIV)
+ F(0xb274, SIGA, S, Z, 0, 0, 0, 0, siga, 0, IF_PRIV)
+ F(0xb23a, STCPS, S, Z, 0, 0, 0, 0, stcps, 0, IF_PRIV)
+ F(0xb233, SSCH, S, Z, 0, insn, 0, 0, ssch, 0, IF_PRIV)
+ F(0xb239, STCRW, S, Z, 0, insn, 0, 0, stcrw, 0, IF_PRIV)
+ F(0xb234, STSCH, S, Z, 0, insn, 0, 0, stsch, 0, IF_PRIV)
+ F(0xb236, TPI , S, Z, la2, 0, 0, 0, tpi, 0, IF_PRIV)
+ F(0xb235, TSCH, S, Z, 0, insn, 0, 0, tsch, 0, IF_PRIV)
/* ??? Not listed in PoO ninth edition, but there's a linux driver that
uses it: "A CHSC subchannel is usually present on LPAR only." */
- C(0xb25f, CHSC, RRE, Z, 0, insn, 0, 0, chsc, 0)
+ F(0xb25f, CHSC, RRE, Z, 0, insn, 0, 0, chsc, 0, IF_PRIV)
/* zPCI Instructions */
/* None of these instructions are documented in the PoP, so this is all
based upon target/s390x/kvm.c and Linux code and likely incomplete */
- C(0xebd0, PCISTB, RSY_a, PCI, la2, 0, 0, 0, pcistb, 0)
- C(0xebd1, SIC, RSY_a, AIS, r1, r3, 0, 0, sic, 0)
- C(0xb9a0, CLP, RRF_c, PCI, 0, 0, 0, 0, clp, 0)
- C(0xb9d0, PCISTG, RRE, PCI, 0, 0, 0, 0, pcistg, 0)
- C(0xb9d2, PCILG, RRE, PCI, 0, 0, 0, 0, pcilg, 0)
- C(0xb9d3, RPCIT, RRE, PCI, 0, 0, 0, 0, rpcit, 0)
- C(0xe3d0, MPCIFC, RXY_a, PCI, la2, 0, 0, 0, mpcifc, 0)
- C(0xe3d4, STPCIFC, RXY_a, PCI, la2, 0, 0, 0, stpcifc, 0)
+ F(0xebd0, PCISTB, RSY_a, PCI, la2, 0, 0, 0, pcistb, 0, IF_PRIV)
+ F(0xebd1, SIC, RSY_a, AIS, r1, r3, 0, 0, sic, 0, IF_PRIV)
+ F(0xb9a0, CLP, RRF_c, PCI, 0, 0, 0, 0, clp, 0, IF_PRIV)
+ F(0xb9d0, PCISTG, RRE, PCI, 0, 0, 0, 0, pcistg, 0, IF_PRIV)
+ F(0xb9d2, PCILG, RRE, PCI, 0, 0, 0, 0, pcilg, 0, IF_PRIV)
+ F(0xb9d3, RPCIT, RRE, PCI, 0, 0, 0, 0, rpcit, 0, IF_PRIV)
+ F(0xe3d0, MPCIFC, RXY_a, PCI, la2, 0, 0, 0, mpcifc, 0, IF_PRIV)
+ F(0xe3d4, STPCIFC, RXY_a, PCI, la2, 0, 0, 0, stpcifc, 0, IF_PRIV)
#endif /* CONFIG_USER_ONLY */
diff --git a/target/s390x/interrupt.c b/target/s390x/interrupt.c
index 25cfb3eef8..a17eff5ebc 100644
--- a/target/s390x/interrupt.c
+++ b/target/s390x/interrupt.c
@@ -15,6 +15,7 @@
#include "exec/exec-all.h"
#include "sysemu/kvm.h"
#include "hw/s390x/ioinst.h"
+#include "tcg_s390x.h"
#if !defined(CONFIG_USER_ONLY)
#include "hw/s390x/s390_flic.h"
#endif
@@ -29,25 +30,11 @@ void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen)
env->int_pgm_ilen = ilen;
}
-static void tcg_s390_program_interrupt(CPUS390XState *env, uint32_t code,
- int ilen, uintptr_t ra)
-{
-#ifdef CONFIG_TCG
- trigger_pgm_exception(env, code, ilen);
- cpu_loop_exit_restore(CPU(s390_env_get_cpu(env)), ra);
-#else
- g_assert_not_reached();
-#endif
-}
-
void s390_program_interrupt(CPUS390XState *env, uint32_t code, int ilen,
uintptr_t ra)
{
S390CPU *cpu = s390_env_get_cpu(env);
- qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n",
- env->psw.addr);
-
if (kvm_enabled()) {
kvm_s390_program_interrupt(cpu, code);
} else if (tcg_enabled()) {
diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
index 348e8cc546..78d39b34d0 100644
--- a/target/s390x/kvm.c
+++ b/target/s390x/kvm.c
@@ -36,6 +36,7 @@
#include "qemu/timer.h"
#include "qemu/units.h"
#include "qemu/mmap-alloc.h"
+#include "qemu/log.h"
#include "sysemu/sysemu.h"
#include "sysemu/hw_accel.h"
#include "hw/hw.h"
@@ -292,6 +293,12 @@ static int kvm_s390_configure_mempath_backing(KVMState *s)
return 0;
}
+ if (!hpage_1m_allowed()) {
+ error_report("This QEMU machine does not support huge page "
+ "mappings");
+ return -EINVAL;
+ }
+
if (path_psize != 1 * MiB) {
error_report("Memory backing with 2G pages was specified, "
"but KVM does not support this memory backing");
@@ -1109,7 +1116,8 @@ void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code)
.type = KVM_S390_PROGRAM_INT,
.u.pgm.code = code,
};
-
+ qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n",
+ cpu->env.psw.addr);
kvm_s390_vcpu_interrupt(cpu, &irq);
}
diff --git a/target/s390x/tcg-stub.c b/target/s390x/tcg-stub.c
index c93501db0b..32adb7276a 100644
--- a/target/s390x/tcg-stub.c
+++ b/target/s390x/tcg-stub.c
@@ -18,3 +18,13 @@
void tcg_s390_tod_updated(CPUState *cs, run_on_cpu_data opaque)
{
}
+void QEMU_NORETURN tcg_s390_program_interrupt(CPUS390XState *env, uint32_t code,
+ int ilen, uintptr_t ra)
+{
+ g_assert_not_reached();
+}
+void QEMU_NORETURN tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc,
+ uintptr_t ra)
+{
+ g_assert_not_reached();
+}
diff --git a/target/s390x/tcg_s390x.h b/target/s390x/tcg_s390x.h
index 4e308aa0ce..ab2c4ba703 100644
--- a/target/s390x/tcg_s390x.h
+++ b/target/s390x/tcg_s390x.h
@@ -14,5 +14,9 @@
#define TCG_S390X_H
void tcg_s390_tod_updated(CPUState *cs, run_on_cpu_data opaque);
+void QEMU_NORETURN tcg_s390_program_interrupt(CPUS390XState *env, uint32_t code,
+ int ilen, uintptr_t ra);
+void QEMU_NORETURN tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc,
+ uintptr_t ra);
#endif /* TCG_S390X_H */
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 7363aabf3a..18861cd186 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -314,28 +314,18 @@ static inline void gen_illegal_opcode(DisasContext *s)
gen_program_exception(s, PGM_OPERATION);
}
-static inline void gen_trap(DisasContext *s)
+static inline void gen_data_exception(uint8_t dxc)
{
- TCGv_i32 t;
-
- /* Set DXC to 0xff. */
- t = tcg_temp_new_i32();
- tcg_gen_ld_i32(t, cpu_env, offsetof(CPUS390XState, fpc));
- tcg_gen_ori_i32(t, t, 0xff00);
- tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, fpc));
- tcg_temp_free_i32(t);
-
- gen_program_exception(s, PGM_DATA);
+ TCGv_i32 tmp = tcg_const_i32(dxc);
+ gen_helper_data_exception(cpu_env, tmp);
+ tcg_temp_free_i32(tmp);
}
-#ifndef CONFIG_USER_ONLY
-static void check_privileged(DisasContext *s)
+static inline void gen_trap(DisasContext *s)
{
- if (s->base.tb->flags & FLAG_MASK_PSTATE) {
- gen_program_exception(s, PGM_PRIVILEGED);
- }
+ /* Set DXC to 0xff */
+ gen_data_exception(0xff);
}
-#endif
static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
{
@@ -1120,8 +1110,18 @@ typedef struct {
/* We are exiting the TB to the main loop. */
#define DISAS_PC_STALE_NOCHAIN DISAS_TARGET_4
+
+/* Instruction flags */
+#define IF_AFP1 0x0001 /* r1 is a fp reg for HFP/FPS instructions */
+#define IF_AFP2 0x0002 /* r2 is a fp reg for HFP/FPS instructions */
+#define IF_AFP3 0x0004 /* r3 is a fp reg for HFP/FPS instructions */
+#define IF_BFP 0x0008 /* binary floating point instruction */
+#define IF_DFP 0x0010 /* decimal floating point instruction */
+#define IF_PRIV 0x0020 /* privileged instruction */
+
struct DisasInsn {
unsigned opc:16;
+ unsigned flags:16;
DisasFormat fmt:8;
unsigned fac:8;
unsigned spec:8;
@@ -2078,7 +2078,6 @@ static DisasJumpType op_csp(DisasContext *s, DisasOps *o)
/* Note that in1 = R1 (zero-extended expected value),
out = R1 (original reg), out2 = R1+1 (new value). */
- check_privileged(s);
addr = tcg_temp_new_i64();
old = tcg_temp_new_i64();
tcg_gen_andi_i64(addr, o->in2, -1ULL << (mop & MO_SIZE));
@@ -2202,7 +2201,6 @@ static DisasJumpType op_diag(DisasContext *s, DisasOps *o)
TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
TCGv_i32 func_code = tcg_const_i32(get_field(s->fields, i2));
- check_privileged(s);
gen_helper_diag(cpu_env, r1, r3, func_code);
tcg_temp_free_i32(func_code);
@@ -2463,7 +2461,6 @@ static DisasJumpType op_idte(DisasContext *s, DisasOps *o)
{
TCGv_i32 m4;
- check_privileged(s);
if (s390_has_feat(S390_FEAT_LOCAL_TLB_CLEARING)) {
m4 = tcg_const_i32(get_field(s->fields, m4));
} else {
@@ -2478,7 +2475,6 @@ static DisasJumpType op_ipte(DisasContext *s, DisasOps *o)
{
TCGv_i32 m4;
- check_privileged(s);
if (s390_has_feat(S390_FEAT_LOCAL_TLB_CLEARING)) {
m4 = tcg_const_i32(get_field(s->fields, m4));
} else {
@@ -2491,7 +2487,6 @@ static DisasJumpType op_ipte(DisasContext *s, DisasOps *o)
static DisasJumpType op_iske(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_iske(o->out, cpu_env, o->in2);
return DISAS_NEXT;
}
@@ -2790,7 +2785,6 @@ static DisasJumpType op_lctl(DisasContext *s, DisasOps *o)
{
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
- check_privileged(s);
gen_helper_lctl(cpu_env, r1, o->in2, r3);
tcg_temp_free_i32(r1);
tcg_temp_free_i32(r3);
@@ -2802,7 +2796,6 @@ static DisasJumpType op_lctlg(DisasContext *s, DisasOps *o)
{
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
- check_privileged(s);
gen_helper_lctlg(cpu_env, r1, o->in2, r3);
tcg_temp_free_i32(r1);
tcg_temp_free_i32(r3);
@@ -2812,7 +2805,6 @@ static DisasJumpType op_lctlg(DisasContext *s, DisasOps *o)
static DisasJumpType op_lra(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_lra(o->out, cpu_env, o->in2);
set_cc_static(s);
return DISAS_NEXT;
@@ -2820,8 +2812,6 @@ static DisasJumpType op_lra(DisasContext *s, DisasOps *o)
static DisasJumpType op_lpp(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
-
tcg_gen_st_i64(o->in2, cpu_env, offsetof(CPUS390XState, pp));
return DISAS_NEXT;
}
@@ -2830,12 +2820,12 @@ static DisasJumpType op_lpsw(DisasContext *s, DisasOps *o)
{
TCGv_i64 t1, t2;
- check_privileged(s);
per_breaking_event(s);
t1 = tcg_temp_new_i64();
t2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
+ tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s),
+ MO_TEUL | MO_ALIGN_8);
tcg_gen_addi_i64(o->in2, o->in2, 4);
tcg_gen_qemu_ld32u(t2, o->in2, get_mem_index(s));
/* Convert the 32-bit PSW_MASK into the 64-bit PSW_MASK. */
@@ -2850,12 +2840,12 @@ static DisasJumpType op_lpswe(DisasContext *s, DisasOps *o)
{
TCGv_i64 t1, t2;
- check_privileged(s);
per_breaking_event(s);
t1 = tcg_temp_new_i64();
t2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld64(t1, o->in2, get_mem_index(s));
+ tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s),
+ MO_TEQ | MO_ALIGN_8);
tcg_gen_addi_i64(o->in2, o->in2, 8);
tcg_gen_qemu_ld64(t2, o->in2, get_mem_index(s));
gen_helper_load_psw(cpu_env, t1, t2);
@@ -3048,14 +3038,12 @@ static DisasJumpType op_lpq(DisasContext *s, DisasOps *o)
#ifndef CONFIG_USER_ONLY
static DisasJumpType op_lura(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_lura(o->out, cpu_env, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_lurag(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_lurag(o->out, cpu_env, o->in2);
return DISAS_NEXT;
}
@@ -3214,7 +3202,6 @@ static DisasJumpType op_mvcos(DisasContext *s, DisasOps *o)
static DisasJumpType op_mvcp(DisasContext *s, DisasOps *o)
{
int r1 = get_field(s->fields, l1);
- check_privileged(s);
gen_helper_mvcp(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
set_cc_static(s);
return DISAS_NEXT;
@@ -3223,7 +3210,6 @@ static DisasJumpType op_mvcp(DisasContext *s, DisasOps *o)
static DisasJumpType op_mvcs(DisasContext *s, DisasOps *o)
{
int r1 = get_field(s->fields, l1);
- check_privileged(s);
gen_helper_mvcs(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
set_cc_static(s);
return DISAS_NEXT;
@@ -3509,7 +3495,6 @@ static DisasJumpType op_popcnt(DisasContext *s, DisasOps *o)
#ifndef CONFIG_USER_ONLY
static DisasJumpType op_ptlb(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_ptlb(cpu_env);
return DISAS_NEXT;
}
@@ -3700,7 +3685,6 @@ static DisasJumpType op_rll64(DisasContext *s, DisasOps *o)
#ifndef CONFIG_USER_ONLY
static DisasJumpType op_rrbe(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_rrbe(cc_op, cpu_env, o->in2);
set_cc_static(s);
return DISAS_NEXT;
@@ -3708,7 +3692,6 @@ static DisasJumpType op_rrbe(DisasContext *s, DisasOps *o)
static DisasJumpType op_sacf(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_sacf(cpu_env, o->in2);
/* Addressing mode has changed, so end the block. */
return DISAS_PC_STALE;
@@ -3798,7 +3781,6 @@ static DisasJumpType op_sqxb(DisasContext *s, DisasOps *o)
#ifndef CONFIG_USER_ONLY
static DisasJumpType op_servc(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_servc(cc_op, cpu_env, o->in2, o->in1);
set_cc_static(s);
return DISAS_NEXT;
@@ -3808,7 +3790,6 @@ static DisasJumpType op_sigp(DisasContext *s, DisasOps *o)
{
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
- check_privileged(s);
gen_helper_sigp(cc_op, cpu_env, o->in2, r1, r3);
set_cc_static(s);
tcg_temp_free_i32(r1);
@@ -3990,7 +3971,6 @@ static DisasJumpType op_ectg(DisasContext *s, DisasOps *o)
#ifndef CONFIG_USER_ONLY
static DisasJumpType op_spka(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
tcg_gen_shri_i64(o->in2, o->in2, 4);
tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, PSW_SHIFT_KEY, 4);
return DISAS_NEXT;
@@ -3998,14 +3978,12 @@ static DisasJumpType op_spka(DisasContext *s, DisasOps *o)
static DisasJumpType op_sske(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_sske(cpu_env, o->in1, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_ssm(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8);
/* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */
return DISAS_PC_STALE_NOCHAIN;
@@ -4013,7 +3991,6 @@ static DisasJumpType op_ssm(DisasContext *s, DisasOps *o)
static DisasJumpType op_stap(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, core_id));
return DISAS_NEXT;
}
@@ -4055,7 +4032,6 @@ static DisasJumpType op_stcke(DisasContext *s, DisasOps *o)
static DisasJumpType op_sck(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_TEQ | MO_ALIGN);
gen_helper_sck(cc_op, cpu_env, o->in1);
set_cc_static(s);
@@ -4064,21 +4040,18 @@ static DisasJumpType op_sck(DisasContext *s, DisasOps *o)
static DisasJumpType op_sckc(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_sckc(cpu_env, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_sckpf(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_sckpf(cpu_env, regs[0]);
return DISAS_NEXT;
}
static DisasJumpType op_stckc(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_stckc(o->out, cpu_env);
return DISAS_NEXT;
}
@@ -4087,7 +4060,6 @@ static DisasJumpType op_stctg(DisasContext *s, DisasOps *o)
{
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
- check_privileged(s);
gen_helper_stctg(cpu_env, r1, o->in2, r3);
tcg_temp_free_i32(r1);
tcg_temp_free_i32(r3);
@@ -4098,7 +4070,6 @@ static DisasJumpType op_stctl(DisasContext *s, DisasOps *o)
{
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
- check_privileged(s);
gen_helper_stctl(cpu_env, r1, o->in2, r3);
tcg_temp_free_i32(r1);
tcg_temp_free_i32(r3);
@@ -4107,35 +4078,30 @@ static DisasJumpType op_stctl(DisasContext *s, DisasOps *o)
static DisasJumpType op_stidp(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
tcg_gen_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, cpuid));
return DISAS_NEXT;
}
static DisasJumpType op_spt(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_spt(cpu_env, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_stfl(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_stfl(cpu_env);
return DISAS_NEXT;
}
static DisasJumpType op_stpt(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_stpt(o->out, cpu_env);
return DISAS_NEXT;
}
static DisasJumpType op_stsi(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_stsi(cc_op, cpu_env, o->in2, regs[0], regs[1]);
set_cc_static(s);
return DISAS_NEXT;
@@ -4143,14 +4109,12 @@ static DisasJumpType op_stsi(DisasContext *s, DisasOps *o)
static DisasJumpType op_spx(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_spx(cpu_env, o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_xsch(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_xsch(cpu_env, regs[1]);
set_cc_static(s);
return DISAS_NEXT;
@@ -4158,7 +4122,6 @@ static DisasJumpType op_xsch(DisasContext *s, DisasOps *o)
static DisasJumpType op_csch(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_csch(cpu_env, regs[1]);
set_cc_static(s);
return DISAS_NEXT;
@@ -4166,7 +4129,6 @@ static DisasJumpType op_csch(DisasContext *s, DisasOps *o)
static DisasJumpType op_hsch(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_hsch(cpu_env, regs[1]);
set_cc_static(s);
return DISAS_NEXT;
@@ -4174,7 +4136,6 @@ static DisasJumpType op_hsch(DisasContext *s, DisasOps *o)
static DisasJumpType op_msch(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_msch(cpu_env, regs[1], o->in2);
set_cc_static(s);
return DISAS_NEXT;
@@ -4182,7 +4143,6 @@ static DisasJumpType op_msch(DisasContext *s, DisasOps *o)
static DisasJumpType op_rchp(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_rchp(cpu_env, regs[1]);
set_cc_static(s);
return DISAS_NEXT;
@@ -4190,7 +4150,6 @@ static DisasJumpType op_rchp(DisasContext *s, DisasOps *o)
static DisasJumpType op_rsch(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_rsch(cpu_env, regs[1]);
set_cc_static(s);
return DISAS_NEXT;
@@ -4198,21 +4157,18 @@ static DisasJumpType op_rsch(DisasContext *s, DisasOps *o)
static DisasJumpType op_sal(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_sal(cpu_env, regs[1]);
return DISAS_NEXT;
}
static DisasJumpType op_schm(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_schm(cpu_env, regs[1], regs[2], o->in2);
return DISAS_NEXT;
}
static DisasJumpType op_siga(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
/* From KVM code: Not provided, set CC = 3 for subchannel not operational */
gen_op_movi_cc(s, 3);
return DISAS_NEXT;
@@ -4220,14 +4176,12 @@ static DisasJumpType op_siga(DisasContext *s, DisasOps *o)
static DisasJumpType op_stcps(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
/* The instruction is suppressed if not provided. */
return DISAS_NEXT;
}
static DisasJumpType op_ssch(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_ssch(cpu_env, regs[1], o->in2);
set_cc_static(s);
return DISAS_NEXT;
@@ -4235,7 +4189,6 @@ static DisasJumpType op_ssch(DisasContext *s, DisasOps *o)
static DisasJumpType op_stsch(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_stsch(cpu_env, regs[1], o->in2);
set_cc_static(s);
return DISAS_NEXT;
@@ -4243,7 +4196,6 @@ static DisasJumpType op_stsch(DisasContext *s, DisasOps *o)
static DisasJumpType op_stcrw(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_stcrw(cpu_env, o->in2);
set_cc_static(s);
return DISAS_NEXT;
@@ -4251,7 +4203,6 @@ static DisasJumpType op_stcrw(DisasContext *s, DisasOps *o)
static DisasJumpType op_tpi(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_tpi(cc_op, cpu_env, o->addr1);
set_cc_static(s);
return DISAS_NEXT;
@@ -4259,7 +4210,6 @@ static DisasJumpType op_tpi(DisasContext *s, DisasOps *o)
static DisasJumpType op_tsch(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_tsch(cpu_env, regs[1], o->in2);
set_cc_static(s);
return DISAS_NEXT;
@@ -4267,7 +4217,6 @@ static DisasJumpType op_tsch(DisasContext *s, DisasOps *o)
static DisasJumpType op_chsc(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_chsc(cpu_env, o->in2);
set_cc_static(s);
return DISAS_NEXT;
@@ -4275,7 +4224,6 @@ static DisasJumpType op_chsc(DisasContext *s, DisasOps *o)
static DisasJumpType op_stpx(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
tcg_gen_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, psa));
tcg_gen_andi_i64(o->out, o->out, 0x7fffe000);
return DISAS_NEXT;
@@ -4286,8 +4234,6 @@ static DisasJumpType op_stnosm(DisasContext *s, DisasOps *o)
uint64_t i2 = get_field(s->fields, i2);
TCGv_i64 t;
- check_privileged(s);
-
/* It is important to do what the instruction name says: STORE THEN.
If we let the output hook perform the store then if we fault and
restart, we'll have the wrong SYSTEM MASK in place. */
@@ -4309,14 +4255,12 @@ static DisasJumpType op_stnosm(DisasContext *s, DisasOps *o)
static DisasJumpType op_stura(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_stura(cpu_env, o->in2, o->in1);
return DISAS_NEXT;
}
static DisasJumpType op_sturg(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_sturg(cpu_env, o->in2, o->in1);
return DISAS_NEXT;
}
@@ -4582,7 +4526,6 @@ static DisasJumpType op_tcxb(DisasContext *s, DisasOps *o)
static DisasJumpType op_testblock(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_testblock(cc_op, cpu_env, o->in2);
set_cc_static(s);
return DISAS_NEXT;
@@ -4840,7 +4783,6 @@ static DisasJumpType op_clp(DisasContext *s, DisasOps *o)
{
TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2));
- check_privileged(s);
gen_helper_clp(cpu_env, r2);
tcg_temp_free_i32(r2);
set_cc_static(s);
@@ -4852,7 +4794,6 @@ static DisasJumpType op_pcilg(DisasContext *s, DisasOps *o)
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2));
- check_privileged(s);
gen_helper_pcilg(cpu_env, r1, r2);
tcg_temp_free_i32(r1);
tcg_temp_free_i32(r2);
@@ -4865,7 +4806,6 @@ static DisasJumpType op_pcistg(DisasContext *s, DisasOps *o)
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2));
- check_privileged(s);
gen_helper_pcistg(cpu_env, r1, r2);
tcg_temp_free_i32(r1);
tcg_temp_free_i32(r2);
@@ -4878,7 +4818,6 @@ static DisasJumpType op_stpcifc(DisasContext *s, DisasOps *o)
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 ar = tcg_const_i32(get_field(s->fields, b2));
- check_privileged(s);
gen_helper_stpcifc(cpu_env, r1, o->addr1, ar);
tcg_temp_free_i32(ar);
tcg_temp_free_i32(r1);
@@ -4888,7 +4827,6 @@ static DisasJumpType op_stpcifc(DisasContext *s, DisasOps *o)
static DisasJumpType op_sic(DisasContext *s, DisasOps *o)
{
- check_privileged(s);
gen_helper_sic(cpu_env, o->in1, o->in2);
return DISAS_NEXT;
}
@@ -4898,7 +4836,6 @@ static DisasJumpType op_rpcit(DisasContext *s, DisasOps *o)
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2));
- check_privileged(s);
gen_helper_rpcit(cpu_env, r1, r2);
tcg_temp_free_i32(r1);
tcg_temp_free_i32(r2);
@@ -4912,7 +4849,6 @@ static DisasJumpType op_pcistb(DisasContext *s, DisasOps *o)
TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
TCGv_i32 ar = tcg_const_i32(get_field(s->fields, b2));
- check_privileged(s);
gen_helper_pcistb(cpu_env, r1, r3, o->addr1, ar);
tcg_temp_free_i32(ar);
tcg_temp_free_i32(r1);
@@ -4926,7 +4862,6 @@ static DisasJumpType op_mpcifc(DisasContext *s, DisasOps *o)
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 ar = tcg_const_i32(get_field(s->fields, b2));
- check_privileged(s);
gen_helper_mpcifc(cpu_env, r1, o->addr1, ar);
tcg_temp_free_i32(ar);
tcg_temp_free_i32(r1);
@@ -5834,17 +5769,24 @@ static void in2_insn(DisasContext *s, DisasFields *f, DisasOps *o)
search tree, rather than us having to post-process the table. */
#define C(OPC, NM, FT, FC, I1, I2, P, W, OP, CC) \
- D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, 0)
+ E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, 0, 0)
-#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) insn_ ## NM,
+#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) \
+ E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D, 0)
+
+#define F(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, FL) \
+ E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, 0, FL)
+
+#define E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D, FL) insn_ ## NM,
enum DisasInsnEnum {
#include "insn-data.def"
};
-#undef D
-#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) { \
+#undef E
+#define E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D, FL) { \
.opc = OPC, \
+ .flags = FL, \
.fmt = FMT_##FT, \
.fac = FAC_##FC, \
.spec = SPEC_in1_##I1 | SPEC_in2_##I2 | SPEC_prep_##P | SPEC_wout_##W, \
@@ -5915,8 +5857,8 @@ static const DisasInsn insn_info[] = {
#include "insn-data.def"
};
-#undef D
-#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) \
+#undef E
+#define E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D, FL) \
case OPC: return &insn_info[insn_ ## NM];
static const DisasInsn *lookup_opc(uint16_t opc)
@@ -5928,6 +5870,8 @@ static const DisasInsn *lookup_opc(uint16_t opc)
}
}
+#undef F
+#undef E
#undef D
#undef C
@@ -6075,6 +6019,17 @@ static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s,
return info;
}
+static bool is_afp_reg(int reg)
+{
+ return reg % 2 || reg > 6;
+}
+
+static bool is_fp_pair(int reg)
+{
+ /* 0,1,4,5,8,9,12,13: to exclude the others, check for single bit */
+ return !(reg & 0x2);
+}
+
static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s)
{
const DisasInsn *insn;
@@ -6101,42 +6056,48 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s)
}
#endif
- /* Check for insn specification exceptions. */
- if (insn->spec) {
- int spec = insn->spec, excp = 0, r;
+ /* process flags */
+ if (insn->flags) {
+ /* privileged instruction */
+ if ((s->base.tb->flags & FLAG_MASK_PSTATE) && (insn->flags & IF_PRIV)) {
+ gen_program_exception(s, PGM_PRIVILEGED);
+ return DISAS_NORETURN;
+ }
+
+ /* if AFP is not enabled, instructions and registers are forbidden */
+ if (!(s->base.tb->flags & FLAG_MASK_AFP)) {
+ uint8_t dxc = 0;
- if (spec & SPEC_r1_even) {
- r = get_field(&f, r1);
- if (r & 1) {
- excp = PGM_SPECIFICATION;
+ if ((insn->flags & IF_AFP1) && is_afp_reg(get_field(&f, r1))) {
+ dxc = 1;
}
- }
- if (spec & SPEC_r2_even) {
- r = get_field(&f, r2);
- if (r & 1) {
- excp = PGM_SPECIFICATION;
+ if ((insn->flags & IF_AFP2) && is_afp_reg(get_field(&f, r2))) {
+ dxc = 1;
}
- }
- if (spec & SPEC_r3_even) {
- r = get_field(&f, r3);
- if (r & 1) {
- excp = PGM_SPECIFICATION;
+ if ((insn->flags & IF_AFP3) && is_afp_reg(get_field(&f, r3))) {
+ dxc = 1;
}
- }
- if (spec & SPEC_r1_f128) {
- r = get_field(&f, r1);
- if (r > 13) {
- excp = PGM_SPECIFICATION;
+ if (insn->flags & IF_BFP) {
+ dxc = 2;
}
- }
- if (spec & SPEC_r2_f128) {
- r = get_field(&f, r2);
- if (r > 13) {
- excp = PGM_SPECIFICATION;
+ if (insn->flags & IF_DFP) {
+ dxc = 3;
+ }
+ if (dxc) {
+ gen_data_exception(dxc);
+ return DISAS_NORETURN;
}
}
- if (excp) {
- gen_program_exception(s, excp);
+ }
+
+ /* Check for insn specification exceptions. */
+ if (insn->spec) {
+ if ((insn->spec & SPEC_r1_even && get_field(&f, r1) & 1) ||
+ (insn->spec & SPEC_r2_even && get_field(&f, r2) & 1) ||
+ (insn->spec & SPEC_r3_even && get_field(&f, r3) & 1) ||
+ (insn->spec & SPEC_r1_f128 && !is_fp_pair(get_field(&f, r1))) ||
+ (insn->spec & SPEC_r2_f128 && !is_fp_pair(get_field(&f, r2)))) {
+ gen_program_exception(s, PGM_SPECIFICATION);
return DISAS_NORETURN;
}
}