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)
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEEw9DWbcNiT/aowBjO3s9rk8bwL68FAlu2MCwSHGNvaHVja0By
 ZWRoYXQuY29tAAoJEN7Pa5PG8C+v4dcP/2XM7rY1s67EXgbj441n+Vj4BbXR+SLw
 rmbO6WNrOhK1NvhN96N2GveawgxA7jWU9LqTYJZPdOVZmG3ZJmDF+hnJZ6DY2pKR
 R5x0OknVtkPbkHci/uYtEfUVuvaBzCC2b4/o7Oo+9UMyyRRImxMYjSJj9YhYgtbL
 hnpa1ogLB8wJDQRjOHxvsAVM/68wFpgnh5lGTXgH0bt7tPeShWpxpWaM6e9OlHB1
 i2en+ImKHK3gLKmCvJ7UR0DCxALVDL2I4KPw0c/aqeYWNlf9HtIv7VS+EfcsqMSn
 PO9t77c1HHjXIpELuQqsm1KLxsYXYfjDF3w/iQB4hKFHxLpCIfqDEJ8rQkIIYWY4
 ad7qhu3O0OgQreeFdWJIBGfZSZfmXb89bMX4O0YiyNK0eDZ8S4Y3I2+iZQVhWhZJ
 B74OpdWmMXkzBDjbP8dkCsF045eDmu+d3aLEe0KIjuLdIDBxQgFK73xe4K0JKlvx
 SLk24rXkhCCCFPgyqfgllIHqvUWJvdKXbr/SuD+Wy09geURKxtDC3+mRuL2swGos
 YPueLsfDz282VSdcFhjxTweGEURimSW+EQF18lCHOlei1HCbscV2CNP5L3WKQ8U+
 K45lD8LOs0U6qS0QAos6c96oEBWJXMkNCP6oTreDyAvcEeYNOm2eLx2/JyGSBDJx
 Zi+IRr0kkYFG
 =0e7K
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2018-10-05 16:05:06 +01:00
commit ae7a4c0a46
17 changed files with 437 additions and 390 deletions

View File

@ -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; int i;
dest->reserved = src->reserved; dest[0] = src->reserved;
dest->cu_type = cpu_to_be16(src->cu_type); stw_be_p(dest + 1, src->cu_type);
dest->cu_model = src->cu_model; dest[3] = src->cu_model;
dest->dev_type = cpu_to_be16(src->dev_type); stw_be_p(dest + 4, src->dev_type);
dest->dev_model = src->dev_model; dest[6] = src->dev_model;
dest->unused = src->unused; dest[7] = src->unused;
for (i = 0; i < ARRAY_SIZE(dest->ciw); i++) { for (i = 0; i < ARRAY_SIZE(src->ciw); i++) {
dest->ciw[i].type = src->ciw[i].type; dest[8 + i * 4] = src->ciw[i].type;
dest->ciw[i].command = src->ciw[i].command; dest[9 + i * 4] = src->ciw[i].command;
dest->ciw[i].count = cpu_to_be16(src->ciw[i].count); 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; break;
case CCW_CMD_SENSE_ID: 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. */ /* Sense ID information is device specific. */
if (check_len) { if (check_len) {
if (ccw.count != sizeof(sense_id)) { 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. * have enough place to store at least bytes 0-3.
*/ */
if (len >= 4) { if (len >= 4) {
sense_id.reserved = 0xff; sense_id[0] = 0xff;
} else { } 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); sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds);
ret = 0; ret = 0;
break; break;

View File

@ -132,15 +132,15 @@ typedef struct QemuIplParameters QemuIplParameters;
struct S390IPLState { struct S390IPLState {
/*< private >*/ /*< private >*/
DeviceState parent_obj; DeviceState parent_obj;
IplParameterBlock iplb;
QemuIplParameters qipl;
uint64_t start_addr; uint64_t start_addr;
uint64_t compat_start_addr; uint64_t compat_start_addr;
uint64_t bios_start_addr; uint64_t bios_start_addr;
uint64_t compat_bios_start_addr; uint64_t compat_bios_start_addr;
bool enforce_bios; bool enforce_bios;
IplParameterBlock iplb;
bool iplb_valid; bool iplb_valid;
bool netboot; bool netboot;
QemuIplParameters qipl;
/* reset related properties don't have to be migrated or reset */ /* reset related properties don't have to be migrated or reset */
enum s390_reset reset_type; enum s390_reset reset_type;
int reset_cpu_index; int reset_cpu_index;
@ -157,6 +157,7 @@ struct S390IPLState {
bool iplbext_migration; bool iplbext_migration;
}; };
typedef struct S390IPLState S390IPLState; 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_FCP 0x00
#define S390_IPL_TYPE_CCW 0x02 #define S390_IPL_TYPE_CCW 0x02

View File

@ -692,27 +692,35 @@ static void s390_pci_iommu_free(S390pciState *s, PCIBus *bus, int32_t devfn)
object_unref(OBJECT(iommu)); object_unref(OBJECT(iommu));
} }
static int s390_pcihost_init(SysBusDevice *dev) static void s390_pcihost_realize(DeviceState *dev, Error **errp)
{ {
PCIBus *b; PCIBus *b;
BusState *bus; BusState *bus;
PCIHostState *phb = PCI_HOST_BRIDGE(dev); PCIHostState *phb = PCI_HOST_BRIDGE(dev);
S390pciState *s = S390_PCI_HOST_BRIDGE(dev); S390pciState *s = S390_PCI_HOST_BRIDGE(dev);
Error *local_err = NULL;
DPRINTF("host_init\n"); DPRINTF("host_init\n");
b = pci_register_root_bus(DEVICE(dev), NULL, b = pci_register_root_bus(dev, NULL, s390_pci_set_irq, s390_pci_map_irq,
s390_pci_set_irq, s390_pci_map_irq, NULL, NULL, get_system_memory(), get_system_io(), 0,
get_system_memory(), get_system_io(), 0, 64, 64, TYPE_PCI_BUS);
TYPE_PCI_BUS);
pci_setup_iommu(b, s390_pci_dma_iommu, s); pci_setup_iommu(b, s390_pci_dma_iommu, s);
bus = BUS(b); 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; phb->bus = b;
s->bus = S390_PCI_BUS(qbus_create(TYPE_S390_PCI_BUS, DEVICE(s), NULL)); s->bus = S390_PCI_BUS(qbus_create(TYPE_S390_PCI_BUS, dev, NULL));
qbus_set_hotplug_handler(BUS(s->bus), DEVICE(s), 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, s->iommu_table = g_hash_table_new_full(g_int64_hash, g_int64_equal,
NULL, g_free); NULL, g_free);
@ -722,9 +730,10 @@ static int s390_pcihost_init(SysBusDevice *dev)
QTAILQ_INIT(&s->zpci_devs); QTAILQ_INIT(&s->zpci_devs);
css_register_io_adapters(CSS_IO_ADAPTER_PCI, true, false, css_register_io_adapters(CSS_IO_ADAPTER_PCI, true, false,
S390_ADAPTER_SUPPRESSIBLE, &error_abort); S390_ADAPTER_SUPPRESSIBLE, &local_err);
if (local_err) {
return 0; error_propagate(errp, local_err);
}
} }
static int s390_pci_msix_init(S390PCIBusDevice *pbdev) 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) static void s390_pcihost_class_init(ObjectClass *klass, void *data)
{ {
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
dc->reset = s390_pcihost_reset; dc->reset = s390_pcihost_reset;
k->init = s390_pcihost_init; dc->realize = s390_pcihost_realize;
hc->plug = s390_pcihost_hot_plug; hc->plug = s390_pcihost_hot_plug;
hc->unplug = s390_pcihost_hot_unplug; hc->unplug = s390_pcihost_hot_unplug;
msi_nonbroken = true; msi_nonbroken = true;

View File

@ -456,6 +456,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
s390mc->ri_allowed = true; s390mc->ri_allowed = true;
s390mc->cpu_model_allowed = true; s390mc->cpu_model_allowed = true;
s390mc->css_migration_enabled = true; s390mc->css_migration_enabled = true;
s390mc->hpage_1m_allowed = true;
mc->init = ccw_init; mc->init = ccw_init;
mc->reset = s390_machine_reset; mc->reset = s390_machine_reset;
mc->hot_add_cpu = s390_hot_add_cpu; mc->hot_add_cpu = s390_hot_add_cpu;
@ -535,6 +536,12 @@ bool cpu_model_allowed(void)
return get_machine_class()->cpu_model_allowed; 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) static char *machine_get_loadparm(Object *obj, Error **errp)
{ {
S390CcwMachineState *ms = S390_CCW_MACHINE(obj); 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) 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); ccw_machine_3_1_class_options(mc);
SET_MACHINE_COMPAT(mc, CCW_COMPAT_3_0); SET_MACHINE_COMPAT(mc, CCW_COMPAT_3_0);
} }

View File

@ -48,7 +48,7 @@ typedef struct SenseId {
uint8_t unused; /* padding byte */ uint8_t unused; /* padding byte */
/* extended part */ /* extended part */
CIW ciw[MAX_CIWS]; /* variable # of CIWs */ 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. */ /* Channel measurements, from linux/drivers/s390/cio/cmf.c. */
typedef struct CMB { typedef struct CMB {
@ -118,11 +118,12 @@ typedef enum IOInstEnding {
typedef struct SubchDev SubchDev; typedef struct SubchDev SubchDev;
struct SubchDev { struct SubchDev {
/* channel-subsystem related things: */ /* channel-subsystem related things: */
SCHIB curr_status; /* Needs alignment and thus must come first */
ORB orb;
uint8_t cssid; uint8_t cssid;
uint8_t ssid; uint8_t ssid;
uint16_t schid; uint16_t schid;
uint16_t devno; uint16_t devno;
SCHIB curr_status;
uint8_t sense_data[32]; uint8_t sense_data[32];
hwaddr channel_prog; hwaddr channel_prog;
CCW1 last_cmd; CCW1 last_cmd;
@ -131,7 +132,6 @@ struct SubchDev {
bool thinint_active; bool thinint_active;
uint8_t ccw_no_data_cnt; uint8_t ccw_no_data_cnt;
uint16_t migrated_schid; /* used for missmatch detection */ uint16_t migrated_schid; /* used for missmatch detection */
ORB orb;
CcwDataStream cds; CcwDataStream cds;
/* transport-provided data: */ /* transport-provided data: */
int (*ccw_cb) (SubchDev *, CCW1); int (*ccw_cb) (SubchDev *, CCW1);

View File

@ -25,7 +25,8 @@ typedef struct SCSW {
uint8_t dstat; uint8_t dstat;
uint8_t cstat; uint8_t cstat;
uint16_t count; 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_KEY 0xf000
#define SCSW_FLAGS_MASK_SCTL 0x0800 #define SCSW_FLAGS_MASK_SCTL 0x0800
@ -94,7 +95,8 @@ typedef struct PMCW {
uint8_t pam; uint8_t pam;
uint8_t chpid[8]; uint8_t chpid[8];
uint32_t chars; 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_QF 0x8000
#define PMCW_FLAGS_MASK_W 0x4000 #define PMCW_FLAGS_MASK_W 0x4000
@ -127,7 +129,8 @@ typedef struct IRB {
uint32_t esw[5]; uint32_t esw[5];
uint32_t ecw[8]; uint32_t ecw[8];
uint32_t emw[8]; uint32_t emw[8];
} QEMU_PACKED IRB; } IRB;
QEMU_BUILD_BUG_MSG(sizeof(IRB) != 96, "size of IRB is wrong");
/* operation request block */ /* operation request block */
typedef struct ORB { typedef struct ORB {
@ -136,7 +139,8 @@ typedef struct ORB {
uint8_t lpm; uint8_t lpm;
uint8_t ctrl1; uint8_t ctrl1;
uint32_t cpa; 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_KEY 0xf000
#define ORB_CTRL0_MASK_SPND 0x0800 #define ORB_CTRL0_MASK_SPND 0x0800
@ -165,7 +169,8 @@ typedef struct CCW0 {
uint8_t flags; uint8_t flags;
uint8_t reserved; uint8_t reserved;
uint16_t count; uint16_t count;
} QEMU_PACKED CCW0; } CCW0;
QEMU_BUILD_BUG_MSG(sizeof(CCW0) != 8, "size of CCW0 is wrong");
/* channel command word (type 1) */ /* channel command word (type 1) */
typedef struct CCW1 { typedef struct CCW1 {
@ -173,7 +178,8 @@ typedef struct CCW1 {
uint8_t flags; uint8_t flags;
uint16_t count; uint16_t count;
uint32_t cda; 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_DC 0x80
#define CCW_FLAG_CC 0x40 #define CCW_FLAG_CC 0x40
@ -192,7 +198,8 @@ typedef struct CCW1 {
typedef struct CRW { typedef struct CRW {
uint16_t flags; uint16_t flags;
uint16_t rsid; 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_S 0x4000
#define CRW_FLAGS_MASK_R 0x2000 #define CRW_FLAGS_MASK_R 0x2000

View File

@ -39,12 +39,15 @@ typedef struct S390CcwMachineClass {
bool ri_allowed; bool ri_allowed;
bool cpu_model_allowed; bool cpu_model_allowed;
bool css_migration_enabled; bool css_migration_enabled;
bool hpage_1m_allowed;
} S390CcwMachineClass; } S390CcwMachineClass;
/* runtime-instrumentation allowed by the machine */ /* runtime-instrumentation allowed by the machine */
bool ri_allowed(void); bool ri_allowed(void);
/* cpu model allowed by the machine */ /* cpu model allowed by the machine */
bool cpu_model_allowed(void); 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 * Returns true if (vmstate based) migration of the channel subsystem

View File

@ -255,6 +255,7 @@ extern const struct VMStateDescription vmstate_s390_cpu;
/* PSW defines */ /* PSW defines */
#undef PSW_MASK_PER #undef PSW_MASK_PER
#undef PSW_MASK_UNUSED_2
#undef PSW_MASK_DAT #undef PSW_MASK_DAT
#undef PSW_MASK_IO #undef PSW_MASK_IO
#undef PSW_MASK_EXT #undef PSW_MASK_EXT
@ -273,6 +274,7 @@ extern const struct VMStateDescription vmstate_s390_cpu;
#undef PSW_MASK_ESA_ADDR #undef PSW_MASK_ESA_ADDR
#define PSW_MASK_PER 0x4000000000000000ULL #define PSW_MASK_PER 0x4000000000000000ULL
#define PSW_MASK_UNUSED_2 0x2000000000000000ULL
#define PSW_MASK_DAT 0x0400000000000000ULL #define PSW_MASK_DAT 0x0400000000000000ULL
#define PSW_MASK_IO 0x0200000000000000ULL #define PSW_MASK_IO 0x0200000000000000ULL
#define PSW_MASK_EXT 0x0100000000000000ULL #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 \ #define FLAG_MASK_PSW (FLAG_MASK_PER | FLAG_MASK_DAT | FLAG_MASK_PSTATE \
| FLAG_MASK_ASC | FLAG_MASK_64 | FLAG_MASK_32) | 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 */ /* Control register 0 bits */
#define CR0_LOWPROT 0x0000000010000000ULL #define CR0_LOWPROT 0x0000000010000000ULL
#define CR0_SECONDARY 0x0000000004000000ULL #define CR0_SECONDARY 0x0000000004000000ULL
#define CR0_EDAT 0x0000000000800000ULL #define CR0_EDAT 0x0000000000800000ULL
#define CR0_AFP 0x0000000000040000ULL
#define CR0_EMERGENCY_SIGNAL_SC 0x0000000000004000ULL #define CR0_EMERGENCY_SIGNAL_SC 0x0000000000004000ULL
#define CR0_EXTERNAL_CALL_SC 0x0000000000002000ULL #define CR0_EXTERNAL_CALL_SC 0x0000000000002000ULL
#define CR0_CKC_SC 0x0000000000000800ULL #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; *pc = env->psw.addr;
*cs_base = env->ex_value; *cs_base = env->ex_value;
*flags = (env->psw.mask >> FLAG_MASK_PSW_SHIFT) & FLAG_MASK_PSW; *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 */ /* PER bits from control register 9 */

View File

@ -21,11 +21,13 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "cpu.h" #include "cpu.h"
#include "internal.h" #include "internal.h"
#include "exec/helper-proto.h"
#include "qemu/timer.h" #include "qemu/timer.h"
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "exec/cpu_ldst.h" #include "exec/cpu_ldst.h"
#include "hw/s390x/ioinst.h" #include "hw/s390x/ioinst.h"
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
#include "tcg_s390x.h"
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "hw/s390x/s390_flic.h" #include "hw/s390x/s390_flic.h"
@ -48,6 +50,40 @@
do { } while (0) do { } while (0)
#endif #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) #if defined(CONFIG_USER_ONLY)
void s390_cpu_do_interrupt(CPUState *cs) void s390_cpu_do_interrupt(CPUState *cs)

View File

@ -21,6 +21,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "cpu.h" #include "cpu.h"
#include "internal.h" #include "internal.h"
#include "tcg_s390x.h"
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "exec/cpu_ldst.h" #include "exec/cpu_ldst.h"
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
@ -40,14 +41,6 @@
? (mask / (from / to)) & to \ ? (mask / (from / to)) & to \
: (mask & from) * (to / from)) : (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. */ /* 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, uintptr_t retaddr)
{ {
@ -75,7 +68,7 @@ static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
/* Send signals for enabled exceptions. */ /* Send signals for enabled exceptions. */
s390_exc &= env->fpc >> 24; s390_exc &= env->fpc >> 24;
if (s390_exc) { 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. */ is also 1, a simulated-iee-exception trap occurs. */
s390_exc = (signalling >> 16) & (source >> 24); s390_exc = (signalling >> 16) & (source >> 24);
if (s390_exc) { if (s390_exc) {
ieee_exception(env, s390_exc | 3, GETPC()); tcg_s390_data_exception(env, s390_exc | 3, GETPC());
} }
} }

View File

@ -1,4 +1,5 @@
DEF_HELPER_2(exception, noreturn, env, i32) 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(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(oc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
DEF_HELPER_FLAGS_4(xc, TCG_CALL_NO_WG, i32, env, i32, i64, i64) DEF_HELPER_FLAGS_4(xc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)

View File

@ -3,6 +3,8 @@
* *
* C(OPC, NAME, FMT, FAC, I1, I2, P, W, OP, CC) * C(OPC, NAME, FMT, FAC, I1, I2, P, W, OP, CC)
* D(OPC, NAME, FMT, FAC, I1, I2, P, W, OP, CC, DATA) * 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 * OPC = (op << 8) | op2 where op is the major, op2 the minor opcode
* NAME = name of the opcode, used internally * NAME = name of the opcode, used internally
@ -15,6 +17,7 @@
* OP = func op_xx does the bulk of the operation * OP = func op_xx does the bulk of the operation
* CC = func cout_xx defines how cc should get set * CC = func cout_xx defines how cc should get set
* DATA = immediate argument to op_xx function * 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 * 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(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(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(0xe318, AGF, RXY_a, Z, r1, m2_32s, r1, 0, add, adds64)
C(0xb30a, AEBR, RRE, Z, e1, e2, new, e1, aeb, f32) F(0xb30a, AEBR, RRE, Z, e1, e2, new, e1, aeb, f32, IF_BFP)
C(0xb31a, ADBR, RRE, Z, f1_o, f2_o, f1, 0, adb, f64) F(0xb31a, ADBR, RRE, Z, f1_o, f2_o, f1, 0, adb, f64, IF_BFP)
C(0xb34a, AXBR, RRE, Z, 0, x2_o, x1, 0, axb, f128) F(0xb34a, AXBR, RRE, Z, 0, x2_o, x1, 0, axb, f128, IF_BFP)
C(0xed0a, AEB, RXE, Z, e1, m2_32u, new, e1, aeb, f32) F(0xed0a, AEB, RXE, Z, e1, m2_32u, new, e1, aeb, f32, IF_BFP)
C(0xed1a, ADB, RXE, Z, f1_o, m2_64, f1, 0, adb, f64) F(0xed1a, ADB, RXE, Z, f1_o, m2_64, f1, 0, adb, f64, IF_BFP)
/* ADD HIGH */ /* ADD HIGH */
C(0xb9c8, AHHHR, RRF_a, HW, r2_sr32, r3_sr32, new, r1_32h, add, adds32) 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) 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) C(0xb241, CKSM, RRE, Z, r1_o, ra2, new, r1_32, cksm, 0)
/* COPY SIGN */ /* 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 */ /* COMPARE */
C(0x1900, CR, RR_a, Z, r1_o, r2_o, 0, 0, 0, cmps32) 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(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(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(0xe330, CGF, RXY_a, Z, r1_o, m2_32s, 0, 0, 0, cmps64)
C(0xb309, CEBR, RRE, Z, e1, e2, 0, 0, ceb, 0) F(0xb309, CEBR, RRE, Z, e1, e2, 0, 0, ceb, 0, IF_BFP)
C(0xb319, CDBR, RRE, Z, f1_o, f2_o, 0, 0, cdb, 0) F(0xb319, CDBR, RRE, Z, f1_o, f2_o, 0, 0, cdb, 0, IF_BFP)
C(0xb349, CXBR, RRE, Z, x1_o, x2_o, 0, 0, cxb, 0) F(0xb349, CXBR, RRE, Z, x1_o, x2_o, 0, 0, cxb, 0, IF_BFP)
C(0xed09, CEB, RXE, Z, e1, m2_32u, 0, 0, ceb, 0) F(0xed09, CEB, RXE, Z, e1, m2_32u, 0, 0, ceb, 0, IF_BFP)
C(0xed19, CDB, RXE, Z, f1_o, m2_64, 0, 0, cdb, 0) F(0xed19, CDB, RXE, Z, f1_o, m2_64, 0, 0, cdb, 0, IF_BFP)
/* COMPARE AND SIGNAL */ /* COMPARE AND SIGNAL */
C(0xb308, KEBR, RRE, Z, e1, e2, 0, 0, keb, 0) F(0xb308, KEBR, RRE, Z, e1, e2, 0, 0, keb, 0, IF_BFP)
C(0xb318, KDBR, RRE, Z, f1_o, f2_o, 0, 0, kdb, 0) F(0xb318, KDBR, RRE, Z, f1_o, f2_o, 0, 0, kdb, 0, IF_BFP)
C(0xb348, KXBR, RRE, Z, x1_o, x2_o, 0, 0, kxb, 0) F(0xb348, KXBR, RRE, Z, x1_o, x2_o, 0, 0, kxb, 0, IF_BFP)
C(0xed08, KEB, RXE, Z, e1, m2_32u, 0, 0, keb, 0) F(0xed08, KEB, RXE, Z, e1, m2_32u, 0, 0, keb, 0, IF_BFP)
C(0xed18, KDB, RXE, Z, f1_o, m2_64, 0, 0, kdb, 0) F(0xed18, KDB, RXE, Z, f1_o, m2_64, 0, 0, kdb, 0, IF_BFP)
/* COMPARE IMMEDIATE */ /* COMPARE IMMEDIATE */
C(0xc20d, CFI, RIL_a, EI, r1, i2, 0, 0, 0, cmps32) C(0xc20d, CFI, RIL_a, EI, r1, i2, 0, 0, 0, cmps32)
C(0xc20c, CGFI, RIL_a, EI, r1, i2, 0, 0, 0, cmps64) 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(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) C(0xe326, CVDY, RXY_a, LD, r1_o, a2, 0, 0, cvd, 0)
/* CONVERT TO FIXED */ /* CONVERT TO FIXED */
C(0xb398, CFEBR, RRF_e, Z, 0, e2, new, r1_32, cfeb, 0) F(0xb398, CFEBR, RRF_e, Z, 0, e2, new, r1_32, cfeb, 0, IF_BFP)
C(0xb399, CFDBR, RRF_e, Z, 0, f2_o, new, r1_32, cfdb, 0) F(0xb399, CFDBR, RRF_e, Z, 0, f2_o, new, r1_32, cfdb, 0, IF_BFP)
C(0xb39a, CFXBR, RRF_e, Z, 0, x2_o, new, r1_32, cfxb, 0) F(0xb39a, CFXBR, RRF_e, Z, 0, x2_o, new, r1_32, cfxb, 0, IF_BFP)
C(0xb3a8, CGEBR, RRF_e, Z, 0, e2, r1, 0, cgeb, 0) F(0xb3a8, CGEBR, RRF_e, Z, 0, e2, r1, 0, cgeb, 0, IF_BFP)
C(0xb3a9, CGDBR, RRF_e, Z, 0, f2_o, r1, 0, cgdb, 0) F(0xb3a9, CGDBR, RRF_e, Z, 0, f2_o, r1, 0, cgdb, 0, IF_BFP)
C(0xb3aa, CGXBR, RRF_e, Z, 0, x2_o, r1, 0, cgxb, 0) F(0xb3aa, CGXBR, RRF_e, Z, 0, x2_o, r1, 0, cgxb, 0, IF_BFP)
/* CONVERT FROM FIXED */ /* CONVERT FROM FIXED */
C(0xb394, CEFBR, RRF_e, Z, 0, r2_32s, new, e1, cegb, 0) F(0xb394, CEFBR, RRF_e, Z, 0, r2_32s, new, e1, cegb, 0, IF_BFP)
C(0xb395, CDFBR, RRF_e, Z, 0, r2_32s, f1, 0, cdgb, 0) F(0xb395, CDFBR, RRF_e, Z, 0, r2_32s, f1, 0, cdgb, 0, IF_BFP)
C(0xb396, CXFBR, RRF_e, Z, 0, r2_32s, x1, 0, cxgb, 0) F(0xb396, CXFBR, RRF_e, Z, 0, r2_32s, x1, 0, cxgb, 0, IF_BFP)
C(0xb3a4, CEGBR, RRF_e, Z, 0, r2_o, new, e1, cegb, 0) F(0xb3a4, CEGBR, RRF_e, Z, 0, r2_o, new, e1, cegb, 0, IF_BFP)
C(0xb3a5, CDGBR, RRF_e, Z, 0, r2_o, f1, 0, cdgb, 0) F(0xb3a5, CDGBR, RRF_e, Z, 0, r2_o, f1, 0, cdgb, 0, IF_BFP)
C(0xb3a6, CXGBR, RRF_e, Z, 0, r2_o, x1, 0, cxgb, 0) F(0xb3a6, CXGBR, RRF_e, Z, 0, r2_o, x1, 0, cxgb, 0, IF_BFP)
/* CONVERT TO LOGICAL */ /* CONVERT TO LOGICAL */
C(0xb39c, CLFEBR, RRF_e, FPE, 0, e2, new, r1_32, clfeb, 0) F(0xb39c, CLFEBR, RRF_e, FPE, 0, e2, new, r1_32, clfeb, 0, IF_BFP)
C(0xb39d, CLFDBR, RRF_e, FPE, 0, f2_o, new, r1_32, clfdb, 0) F(0xb39d, CLFDBR, RRF_e, FPE, 0, f2_o, new, r1_32, clfdb, 0, IF_BFP)
C(0xb39e, CLFXBR, RRF_e, FPE, 0, x2_o, new, r1_32, clfxb, 0) F(0xb39e, CLFXBR, RRF_e, FPE, 0, x2_o, new, r1_32, clfxb, 0, IF_BFP)
C(0xb3ac, CLGEBR, RRF_e, FPE, 0, e2, r1, 0, clgeb, 0) F(0xb3ac, CLGEBR, RRF_e, FPE, 0, e2, r1, 0, clgeb, 0, IF_BFP)
C(0xb3ad, CLGDBR, RRF_e, FPE, 0, f2_o, r1, 0, clgdb, 0) F(0xb3ad, CLGDBR, RRF_e, FPE, 0, f2_o, r1, 0, clgdb, 0, IF_BFP)
C(0xb3ae, CLGXBR, RRF_e, FPE, 0, x2_o, r1, 0, clgxb, 0) F(0xb3ae, CLGXBR, RRF_e, FPE, 0, x2_o, r1, 0, clgxb, 0, IF_BFP)
/* CONVERT FROM LOGICAL */ /* CONVERT FROM LOGICAL */
C(0xb390, CELFBR, RRF_e, FPE, 0, r2_32u, new, e1, celgb, 0) F(0xb390, CELFBR, RRF_e, FPE, 0, r2_32u, new, e1, celgb, 0, IF_BFP)
C(0xb391, CDLFBR, RRF_e, FPE, 0, r2_32u, f1, 0, cdlgb, 0) F(0xb391, CDLFBR, RRF_e, FPE, 0, r2_32u, f1, 0, cdlgb, 0, IF_BFP)
C(0xb392, CXLFBR, RRF_e, FPE, 0, r2_32u, x1, 0, cxlgb, 0) F(0xb392, CXLFBR, RRF_e, FPE, 0, r2_32u, x1, 0, cxlgb, 0, IF_BFP)
C(0xb3a0, CELGBR, RRF_e, FPE, 0, r2_o, new, e1, celgb, 0) F(0xb3a0, CELGBR, RRF_e, FPE, 0, r2_o, new, e1, celgb, 0, IF_BFP)
C(0xb3a1, CDLGBR, RRF_e, FPE, 0, r2_o, f1, 0, cdlgb, 0) F(0xb3a1, CDLGBR, RRF_e, FPE, 0, r2_o, f1, 0, cdlgb, 0, IF_BFP)
C(0xb3a2, CXLGBR, RRF_e, FPE, 0, r2_o, x1, 0, cxlgb, 0) F(0xb3a2, CXLGBR, RRF_e, FPE, 0, r2_o, x1, 0, cxlgb, 0, IF_BFP)
/* CONVERT UTF-8 TO UTF-16 */ /* CONVERT UTF-8 TO UTF-16 */
D(0xb2a7, CU12, RRF_c, Z, 0, 0, 0, 0, cuXX, 0, 12) D(0xb2a7, CU12, RRF_c, Z, 0, 0, 0, 0, cuXX, 0, 12)
@ -332,11 +335,11 @@
/* DIVIDE */ /* DIVIDE */
C(0x1d00, DR, RR_a, Z, r1_D32, r2_32s, new_P, r1_P32, divs32, 0) 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(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) F(0xb30d, DEBR, RRE, Z, e1, e2, new, e1, deb, 0, IF_BFP)
C(0xb31d, DDBR, RRE, Z, f1_o, f2_o, f1, 0, ddb, 0) F(0xb31d, DDBR, RRE, Z, f1_o, f2_o, f1, 0, ddb, 0, IF_BFP)
C(0xb34d, DXBR, RRE, Z, 0, x2_o, x1, 0, dxb, 0) F(0xb34d, DXBR, RRE, Z, 0, x2_o, x1, 0, dxb, 0, IF_BFP)
C(0xed0d, DEB, RXE, Z, e1, m2_32u, new, e1, deb, 0) F(0xed0d, DEB, RXE, Z, e1, m2_32u, new, e1, deb, 0, IF_BFP)
C(0xed1d, DDB, RXE, Z, f1_o, m2_64, f1, 0, ddb, 0) F(0xed1d, DDB, RXE, Z, f1_o, m2_64, f1, 0, ddb, 0, IF_BFP)
/* DIVIDE LOGICAL */ /* DIVIDE LOGICAL */
C(0xb997, DLR, RRE, Z, r1_D32, r2_32u, new_P, r1_P32, divu32, 0) 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) C(0xe397, DL, RXY_a, Z, r1_D32, m2_32u, new_P, r1_P32, divu32, 0)
@ -375,7 +378,7 @@
/* EXTRACT CPU TIME */ /* EXTRACT CPU TIME */
C(0xc801, ECTG, SSF, ECT, 0, 0, 0, 0, ectg, 0) C(0xc801, ECTG, SSF, ECT, 0, 0, 0, 0, ectg, 0)
/* EXTRACT FPC */ /* 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 */ /* EXTRACT PSW */
C(0xb98d, EPSW, RRE, Z, 0, 0, 0, 0, epsw, 0) 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(0xb914, LGFR, RRE, Z, 0, r2_32s, 0, r1, mov2, 0)
C(0xe304, LG, RXY_a, Z, 0, a2, r1, 0, ld64, 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(0xe314, LGF, RXY_a, Z, 0, a2, r1, 0, ld32s, 0)
C(0x2800, LDR, RR_a, Z, 0, f2_o, 0, f1, mov2, 0) F(0x2800, LDR, RR_a, Z, 0, f2_o, 0, f1, mov2, 0, IF_AFP1 | IF_AFP2)
C(0x6800, LD, RX_a, Z, 0, m2_64, 0, f1, mov2, 0) F(0x6800, LD, RX_a, Z, 0, m2_64, 0, f1, mov2, 0, IF_AFP1)
C(0xed65, LDY, RXY_a, LD, 0, m2_64, 0, f1, mov2, 0) F(0xed65, LDY, RXY_a, LD, 0, m2_64, 0, f1, mov2, 0, IF_AFP1)
C(0x3800, LER, RR_a, Z, 0, e2, 0, cond_e1e2, mov2, 0) F(0x3800, LER, RR_a, Z, 0, e2, 0, cond_e1e2, mov2, 0, IF_AFP1 | IF_AFP2)
C(0x7800, LE, RX_a, Z, 0, m2_32u, 0, e1, mov2, 0) F(0x7800, LE, RX_a, Z, 0, m2_32u, 0, e1, mov2, 0, IF_AFP1)
C(0xed64, LEY, RXY_a, LD, 0, m2_32u, 0, e1, mov2, 0) F(0xed64, LEY, RXY_a, LD, 0, m2_32u, 0, e1, mov2, 0, IF_AFP1)
C(0xb365, LXR, RRE, Z, 0, x2_o, 0, x1, movx, 0) F(0xb365, LXR, RRE, Z, 0, x2_o, 0, x1, movx, 0, IF_AFP1)
/* LOAD IMMEDIATE */ /* LOAD IMMEDIATE */
C(0xc001, LGFI, RIL_a, EI, 0, i2, 0, r1, mov2, 0) C(0xc001, LGFI, RIL_a, EI, 0, i2, 0, r1, mov2, 0)
/* LOAD RELATIVE LONG */ /* LOAD RELATIVE LONG */
@ -450,9 +453,9 @@
C(0xe312, LT, RXY_a, EI, 0, a2, new, r1_32, ld32s, s64) 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(0xe302, LTG, RXY_a, EI, 0, a2, r1, 0, ld64, s64)
C(0xe332, LTGF, RXY_a, GIE, 0, a2, r1, 0, ld32s, 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) F(0xb302, LTEBR, RRE, Z, 0, e2, 0, cond_e1e2, mov2, f32, IF_BFP)
C(0xb312, LTDBR, RRE, Z, 0, f2_o, 0, f1, mov2, f64) F(0xb312, LTDBR, RRE, Z, 0, f2_o, 0, f1, mov2, f64, IF_BFP)
C(0xb342, LTXBR, RRE, Z, 0, x2_o, 0, x1, movx, f128) F(0xb342, LTXBR, RRE, Z, 0, x2_o, 0, x1, movx, f128, IF_BFP)
/* LOAD AND TRAP */ /* LOAD AND TRAP */
C(0xe39f, LAT, RXY_a, LAT, 0, m2_32u, r1, 0, lat, 0) 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) 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(0x1300, LCR, RR_a, Z, 0, r2, new, r1_32, neg, neg32)
C(0xb903, LCGR, RRE, Z, 0, r2, r1, 0, neg, neg64) C(0xb903, LCGR, RRE, Z, 0, r2, r1, 0, neg, neg64)
C(0xb913, LCGFR, RRE, Z, 0, r2_32s, 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) F(0xb303, LCEBR, RRE, Z, 0, e2, new, e1, negf32, f32, IF_BFP)
C(0xb313, LCDBR, RRE, Z, 0, f2_o, f1, 0, negf64, f64) F(0xb313, LCDBR, RRE, Z, 0, f2_o, f1, 0, negf64, f64, IF_BFP)
C(0xb343, LCXBR, RRE, Z, 0, x2_o, x1, 0, negf128, f128) F(0xb343, LCXBR, RRE, Z, 0, x2_o, x1, 0, negf128, f128, IF_BFP)
C(0xb373, LCDFR, RRE, FPSSH, 0, f2_o, f1, 0, negf64, 0) F(0xb373, LCDFR, RRE, FPSSH, 0, f2_o, f1, 0, negf64, 0, IF_AFP1 | IF_AFP2)
/* LOAD HALFWORD */ /* LOAD HALFWORD */
C(0xb927, LHR, RRE, EI, 0, r2_16s, 0, r1_32, mov2, 0) 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) 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) C(0xe39c, LLGTAT, RXY_a, LAT, 0, m2_32u, r1, 0, llgtat, 0)
/* LOAD FPR FROM GR */ /* 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 */ /* 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 */ /* LOAD NEGATIVE */
C(0x1100, LNR, RR_a, Z, 0, r2_32s, new, r1_32, nabs, nabs32) 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(0xb901, LNGR, RRE, Z, 0, r2, r1, 0, nabs, nabs64)
C(0xb911, LNGFR, RRE, Z, 0, r2_32s, 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) F(0xb301, LNEBR, RRE, Z, 0, e2, new, e1, nabsf32, f32, IF_BFP)
C(0xb311, LNDBR, RRE, Z, 0, f2_o, f1, 0, nabsf64, f64) F(0xb311, LNDBR, RRE, Z, 0, f2_o, f1, 0, nabsf64, f64, IF_BFP)
C(0xb341, LNXBR, RRE, Z, 0, x2_o, x1, 0, nabsf128, f128) F(0xb341, LNXBR, RRE, Z, 0, x2_o, x1, 0, nabsf128, f128, IF_BFP)
C(0xb371, LNDFR, RRE, FPSSH, 0, f2_o, f1, 0, nabsf64, 0) F(0xb371, LNDFR, RRE, FPSSH, 0, f2_o, f1, 0, nabsf64, 0, IF_AFP1 | IF_AFP2)
/* LOAD ON CONDITION */ /* LOAD ON CONDITION */
C(0xb9f2, LOCR, RRF_c, LOC, r1, r2, new, r1_32, loc, 0) 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) 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(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(0xb900, LPGR, RRE, Z, 0, r2, r1, 0, abs, abs64)
C(0xb910, LPGFR, RRE, Z, 0, r2_32s, 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) F(0xb300, LPEBR, RRE, Z, 0, e2, new, e1, absf32, f32, IF_BFP)
C(0xb310, LPDBR, RRE, Z, 0, f2_o, f1, 0, absf64, f64) F(0xb310, LPDBR, RRE, Z, 0, f2_o, f1, 0, absf64, f64, IF_BFP)
C(0xb340, LPXBR, RRE, Z, 0, x2_o, x1, 0, absf128, f128) F(0xb340, LPXBR, RRE, Z, 0, x2_o, x1, 0, absf128, f128, IF_BFP)
C(0xb370, LPDFR, RRE, FPSSH, 0, f2_o, f1, 0, absf64, 0) F(0xb370, LPDFR, RRE, FPSSH, 0, f2_o, f1, 0, absf64, 0, IF_AFP1 | IF_AFP2)
/* LOAD REVERSED */ /* LOAD REVERSED */
C(0xb91f, LRVR, RRE, Z, 0, r2_32u, new, r1_32, rev32, 0) 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) 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(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) C(0xe30f, LRVG, RXY_a, Z, 0, m2_64, r1, 0, rev64, 0)
/* LOAD ZERO */ /* LOAD ZERO */
C(0xb374, LZER, RRE, Z, 0, 0, 0, e1, zero, 0) F(0xb374, LZER, RRE, Z, 0, 0, 0, e1, zero, 0, IF_AFP1)
C(0xb375, LZDR, RRE, Z, 0, 0, 0, f1, zero, 0) F(0xb375, LZDR, RRE, Z, 0, 0, 0, f1, zero, 0, IF_AFP1)
C(0xb376, LZXR, RRE, Z, 0, 0, 0, x1, zero2, 0) F(0xb376, LZXR, RRE, Z, 0, 0, 0, x1, zero2, 0, IF_AFP1)
/* LOAD FPC */ /* 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 */ /* 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 */ /* LOAD FP INTEGER */
C(0xb357, FIEBR, RRF_e, Z, 0, e2, new, e1, fieb, 0) F(0xb357, FIEBR, RRF_e, Z, 0, e2, new, e1, fieb, 0, IF_BFP)
C(0xb35f, FIDBR, RRF_e, Z, 0, f2_o, f1, 0, fidb, 0) F(0xb35f, FIDBR, RRF_e, Z, 0, f2_o, f1, 0, fidb, 0, IF_BFP)
C(0xb347, FIXBR, RRF_e, Z, 0, x2_o, x1, 0, fixb, 0) F(0xb347, FIXBR, RRF_e, Z, 0, x2_o, x1, 0, fixb, 0, IF_BFP)
/* LOAD LENGTHENED */ /* LOAD LENGTHENED */
C(0xb304, LDEBR, RRE, Z, 0, e2, f1, 0, ldeb, 0) F(0xb304, LDEBR, RRE, Z, 0, e2, f1, 0, ldeb, 0, IF_BFP)
C(0xb305, LXDBR, RRE, Z, 0, f2_o, x1, 0, lxdb, 0) F(0xb305, LXDBR, RRE, Z, 0, f2_o, x1, 0, lxdb, 0, IF_BFP)
C(0xb306, LXEBR, RRE, Z, 0, e2, x1, 0, lxeb, 0) F(0xb306, LXEBR, RRE, Z, 0, e2, x1, 0, lxeb, 0, IF_BFP)
C(0xed04, LDEB, RXE, Z, 0, m2_32u, f1, 0, ldeb, 0) F(0xed04, LDEB, RXE, Z, 0, m2_32u, f1, 0, ldeb, 0, IF_BFP)
C(0xed05, LXDB, RXE, Z, 0, m2_64, x1, 0, lxdb, 0) F(0xed05, LXDB, RXE, Z, 0, m2_64, x1, 0, lxdb, 0, IF_BFP)
C(0xed06, LXEB, RXE, Z, 0, m2_32u, x1, 0, lxeb, 0) F(0xed06, LXEB, RXE, Z, 0, m2_32u, x1, 0, lxeb, 0, IF_BFP)
/* LOAD ROUNDED */ /* LOAD ROUNDED */
C(0xb344, LEDBR, RRE, Z, 0, f2_o, new, e1, ledb, 0) F(0xb344, LEDBR, RRE, Z, 0, f2_o, new, e1, ledb, 0, IF_BFP)
C(0xb345, LDXBR, RRE, Z, 0, x2_o, f1, 0, ldxb, 0) F(0xb345, LDXBR, RRE, Z, 0, x2_o, f1, 0, ldxb, 0, IF_BFP)
C(0xb346, LEXBR, RRE, Z, 0, x2_o, new, e1, lexb, 0) F(0xb346, LEXBR, RRE, Z, 0, x2_o, new, e1, lexb, 0, IF_BFP)
/* LOAD MULTIPLE */ /* LOAD MULTIPLE */
C(0x9800, LM, RS_a, Z, 0, a2, 0, 0, lm32, 0) 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(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(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(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) F(0xb317, MEEBR, RRE, Z, e1, e2, new, e1, meeb, 0, IF_BFP)
C(0xb31c, MDBR, RRE, Z, f1_o, f2_o, f1, 0, mdb, 0) F(0xb31c, MDBR, RRE, Z, f1_o, f2_o, f1, 0, mdb, 0, IF_BFP)
C(0xb34c, MXBR, RRE, Z, 0, x2_o, x1, 0, mxb, 0) F(0xb34c, MXBR, RRE, Z, 0, x2_o, x1, 0, mxb, 0, IF_BFP)
C(0xb30c, MDEBR, RRE, Z, f1_o, e2, f1, 0, mdeb, 0) F(0xb30c, MDEBR, RRE, Z, f1_o, e2, f1, 0, mdeb, 0, IF_BFP)
C(0xb307, MXDBR, RRE, Z, 0, f2_o, x1, 0, mxdb, 0) F(0xb307, MXDBR, RRE, Z, 0, f2_o, x1, 0, mxdb, 0, IF_BFP)
C(0xed17, MEEB, RXE, Z, e1, m2_32u, new, e1, meeb, 0) F(0xed17, MEEB, RXE, Z, e1, m2_32u, new, e1, meeb, 0, IF_BFP)
C(0xed1c, MDB, RXE, Z, f1_o, m2_64, f1, 0, mdb, 0) F(0xed1c, MDB, RXE, Z, f1_o, m2_64, f1, 0, mdb, 0, IF_BFP)
C(0xed0c, MDEB, RXE, Z, f1_o, m2_32u, f1, 0, mdeb, 0) F(0xed0c, MDEB, RXE, Z, f1_o, m2_32u, f1, 0, mdeb, 0, IF_BFP)
C(0xed07, MXDB, RXE, Z, 0, m2_64, x1, 0, mxdb, 0) F(0xed07, MXDB, RXE, Z, 0, m2_64, x1, 0, mxdb, 0, IF_BFP)
/* MULTIPLY HALFWORD */ /* MULTIPLY HALFWORD */
C(0x4c00, MH, RX_a, Z, r1_o, m2_16s, new, r1_32, mul, 0) 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) 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) C(0xc200, MSGFI, RIL_a, GIE, r1_o, i2, r1, 0, mul, 0)
/* MULTIPLY AND ADD */ /* MULTIPLY AND ADD */
C(0xb30e, MAEBR, RRD, Z, e1, e2, new, e1, maeb, 0) F(0xb30e, MAEBR, RRD, Z, e1, e2, new, e1, maeb, 0, IF_BFP)
C(0xb31e, MADBR, RRD, Z, f1_o, f2_o, f1, 0, madb, 0) F(0xb31e, MADBR, RRD, Z, f1_o, f2_o, f1, 0, madb, 0, IF_BFP)
C(0xed0e, MAEB, RXF, Z, e1, m2_32u, new, e1, maeb, 0) F(0xed0e, MAEB, RXF, Z, e1, m2_32u, new, e1, maeb, 0, IF_BFP)
C(0xed1e, MADB, RXF, Z, f1_o, m2_64, f1, 0, madb, 0) F(0xed1e, MADB, RXF, Z, f1_o, m2_64, f1, 0, madb, 0, IF_BFP)
/* MULTIPLY AND SUBTRACT */ /* MULTIPLY AND SUBTRACT */
C(0xb30f, MSEBR, RRD, Z, e1, e2, new, e1, mseb, 0) F(0xb30f, MSEBR, RRD, Z, e1, e2, new, e1, mseb, 0, IF_BFP)
C(0xb31f, MSDBR, RRD, Z, f1_o, f2_o, f1, 0, msdb, 0) F(0xb31f, MSDBR, RRD, Z, f1_o, f2_o, f1, 0, msdb, 0, IF_BFP)
C(0xed0f, MSEB, RXF, Z, e1, m2_32u, new, e1, mseb, 0) F(0xed0f, MSEB, RXF, Z, e1, m2_32u, new, e1, mseb, 0, IF_BFP)
C(0xed1f, MSDB, RXF, Z, f1_o, m2_64, f1, 0, msdb, 0) F(0xed1f, MSDB, RXF, Z, f1_o, m2_64, f1, 0, msdb, 0, IF_BFP)
/* OR */ /* OR */
C(0x1600, OR, RR_a, Z, r1, r2, new, r1_32, or, nz32) 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(0x010d, SAM31, E, Z, 0, 0, 0, 0, sam, 0, 1)
D(0x010e, SAM64, E, Z, 0, 0, 0, 0, sam, 0, 3) D(0x010e, SAM64, E, Z, 0, 0, 0, 0, sam, 0, 3)
/* SET FPC */ /* 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 */ /* 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 */ /* SET BFP ROUNDING MODE */
C(0xb299, SRNM, S, Z, 0, 0, 0, 0, srnm, 0) F(0xb299, SRNM, S, Z, 0, 0, 0, 0, srnm, 0, IF_BFP)
C(0xb2b8, SRNMB, S, FPE, 0, 0, 0, 0, srnm, 0) F(0xb2b8, SRNMB, S, FPE, 0, 0, 0, 0, srnm, 0, IF_BFP)
/* SET DFP ROUNDING MODE */ /* 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 */ /* SET PROGRAM MASK */
C(0x0400, SPM, RR_a, Z, r1, 0, 0, 0, spm, 0) 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) C(0x8c00, SRDL, RS_a, Z, r1_D32, sh64, new, r1_D32, srl, 0)
/* SQUARE ROOT */ /* SQUARE ROOT */
C(0xb314, SQEBR, RRE, Z, 0, e2, new, e1, sqeb, 0) F(0xb314, SQEBR, RRE, Z, 0, e2, new, e1, sqeb, 0, IF_BFP)
C(0xb315, SQDBR, RRE, Z, 0, f2_o, f1, 0, sqdb, 0) F(0xb315, SQDBR, RRE, Z, 0, f2_o, f1, 0, sqdb, 0, IF_BFP)
C(0xb316, SQXBR, RRE, Z, 0, x2_o, x1, 0, sqxb, 0) F(0xb316, SQXBR, RRE, Z, 0, x2_o, x1, 0, sqxb, 0, IF_BFP)
C(0xed14, SQEB, RXE, Z, 0, m2_32u, new, e1, sqeb, 0) F(0xed14, SQEB, RXE, Z, 0, m2_32u, new, e1, sqeb, 0, IF_BFP)
C(0xed15, SQDB, RXE, Z, 0, m2_64, f1, 0, sqdb, 0) F(0xed15, SQDB, RXE, Z, 0, m2_64, f1, 0, sqdb, 0, IF_BFP)
/* STORE */ /* STORE */
C(0x5000, ST, RX_a, Z, r1_o, a2, 0, 0, st32, 0) 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(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(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) F(0x6000, STD, RX_a, Z, f1_o, a2, 0, 0, st64, 0, IF_AFP1)
C(0xed67, STDY, RXY_a, LD, f1_o, a2, 0, 0, st64, 0) F(0xed67, STDY, RXY_a, LD, f1_o, a2, 0, 0, st64, 0, IF_AFP1)
C(0x7000, STE, RX_a, Z, e1, a2, 0, 0, st32, 0) F(0x7000, STE, RX_a, Z, e1, a2, 0, 0, st32, 0, IF_AFP1)
C(0xed66, STEY, RXY_a, LD, e1, a2, 0, 0, st32, 0) F(0xed66, STEY, RXY_a, LD, e1, a2, 0, 0, st32, 0, IF_AFP1)
/* STORE RELATIVE LONG */ /* STORE RELATIVE LONG */
C(0xc40f, STRL, RIL_b, GIE, r1_o, ri2, 0, 0, st32, 0) 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) C(0xc40b, STGRL, RIL_b, GIE, r1_o, ri2, 0, 0, st64, 0)
@ -837,7 +840,7 @@
/* STORE FACILITY LIST EXTENDED */ /* STORE FACILITY LIST EXTENDED */
C(0xb2b0, STFLE, S, SFLE, 0, a2, 0, 0, stfle, 0) C(0xb2b0, STFLE, S, SFLE, 0, a2, 0, 0, stfle, 0)
/* STORE FPC */ /* 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 */ /* STORE MULTIPLE */
D(0x9000, STM, RS_a, Z, 0, a2, 0, 0, stm, 0, 4) 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(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(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(0xe319, SGF, RXY_a, Z, r1, m2_32s, r1, 0, sub, subs64)
C(0xb30b, SEBR, RRE, Z, e1, e2, new, e1, seb, f32) F(0xb30b, SEBR, RRE, Z, e1, e2, new, e1, seb, f32, IF_BFP)
C(0xb31b, SDBR, RRE, Z, f1_o, f2_o, f1, 0, sdb, f64) F(0xb31b, SDBR, RRE, Z, f1_o, f2_o, f1, 0, sdb, f64, IF_BFP)
C(0xb34b, SXBR, RRE, Z, 0, x2_o, x1, 0, sxb, f128) F(0xb34b, SXBR, RRE, Z, 0, x2_o, x1, 0, sxb, f128, IF_BFP)
C(0xed0b, SEB, RXE, Z, e1, m2_32u, new, e1, seb, f32) F(0xed0b, SEB, RXE, Z, e1, m2_32u, new, e1, seb, f32, IF_BFP)
C(0xed1b, SDB, RXE, Z, f1_o, m2_64, f1, 0, sdb, f64) F(0xed1b, SDB, RXE, Z, f1_o, m2_64, f1, 0, sdb, f64, IF_BFP)
/* SUBTRACT HALFWORD */ /* SUBTRACT HALFWORD */
C(0x4b00, SH, RX_a, Z, r1, m2_16s, new, r1_32, sub, subs32) 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) 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) C(0x9300, TS, S, Z, 0, a2, 0, 0, ts, 0)
/* TEST DATA CLASS */ /* TEST DATA CLASS */
C(0xed10, TCEB, RXE, Z, e1, a2, 0, 0, tceb, 0) F(0xed10, TCEB, RXE, Z, e1, a2, 0, 0, tceb, 0, IF_BFP)
C(0xed11, TCDB, RXE, Z, f1_o, a2, 0, 0, tcdb, 0) F(0xed11, TCDB, RXE, Z, f1_o, a2, 0, 0, tcdb, 0, IF_BFP)
C(0xed12, TCXB, RXE, Z, x1_o, a2, 0, 0, tcxb, 0) F(0xed12, TCXB, RXE, Z, x1_o, a2, 0, 0, tcxb, 0, IF_BFP)
/* TEST DECIMAL */ /* TEST DECIMAL */
C(0xebc0, TP, RSL, E2, la1, 0, 0, 0, tp, 0) C(0xebc0, TP, RSL, E2, la1, 0, 0, 0, tp, 0)
@ -961,126 +964,126 @@
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
/* COMPARE AND SWAP AND PURGE */ /* COMPARE AND SWAP AND PURGE */
D(0xb250, CSP, RRE, Z, r1_32u, ra2, r1_P, 0, csp, 0, MO_TEUL) E(0xb250, CSP, RRE, Z, r1_32u, ra2, r1_P, 0, csp, 0, MO_TEUL, IF_PRIV)
D(0xb98a, CSPG, RRE, DAT_ENH, r1_o, ra2, r1_P, 0, csp, 0, MO_TEQ) E(0xb98a, CSPG, RRE, DAT_ENH, r1_o, ra2, r1_P, 0, csp, 0, MO_TEQ, IF_PRIV)
/* DIAGNOSE (KVM hypercall) */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* LOAD CONTROL */
C(0xb700, LCTL, RS_a, Z, 0, a2, 0, 0, lctl, 0) F(0xb700, LCTL, RS_a, Z, 0, a2, 0, 0, lctl, 0, IF_PRIV)
C(0xeb2f, LCTLG, RSY_a, Z, 0, a2, 0, 0, lctlg, 0) F(0xeb2f, LCTLG, RSY_a, Z, 0, a2, 0, 0, lctlg, 0, IF_PRIV)
/* LOAD PROGRAM PARAMETER */ /* 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 */ /* 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 */ /* 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 */ /* LOAD REAL ADDRESS */
C(0xb100, LRA, RX_a, Z, 0, a2, r1, 0, lra, 0) F(0xb100, LRA, RX_a, Z, 0, a2, r1, 0, lra, 0, IF_PRIV)
C(0xe313, LRAY, RXY_a, LD, 0, a2, r1, 0, lra, 0) F(0xe313, LRAY, RXY_a, LD, 0, a2, r1, 0, lra, 0, IF_PRIV)
C(0xe303, LRAG, RXY_a, Z, 0, a2, r1, 0, lra, 0) F(0xe303, LRAG, RXY_a, Z, 0, a2, r1, 0, lra, 0, IF_PRIV)
/* LOAD USING REAL ADDRESS */ /* LOAD USING REAL ADDRESS */
C(0xb24b, LURA, RRE, Z, 0, r2, new, r1_32, lura, 0) F(0xb24b, LURA, RRE, Z, 0, r2, new, r1_32, lura, 0, IF_PRIV)
C(0xb905, LURAG, RRE, Z, 0, r2, r1, 0, lurag, 0) F(0xb905, LURAG, RRE, Z, 0, r2, r1, 0, lurag, 0, IF_PRIV)
/* MOVE TO PRIMARY */ /* 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 */ /* 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 */ /* 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 */ /* 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) */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* STORE CLOCK */
C(0xb205, STCK, S, Z, la2, 0, new, m1_64, stck, 0) C(0xb205, STCK, S, Z, la2, 0, new, m1_64, stck, 0)
C(0xb27c, STCKF, S, SCF, la2, 0, new, m1_64, stck, 0) C(0xb27c, STCKF, S, SCF, la2, 0, new, m1_64, stck, 0)
/* STORE CLOCK EXTENDED */ /* STORE CLOCK EXTENDED */
C(0xb278, STCKE, S, Z, 0, a2, 0, 0, stcke, 0) C(0xb278, STCKE, S, Z, 0, a2, 0, 0, stcke, 0)
/* STORE CLOCK COMPARATOR */ /* 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 */ /* STORE CONTROL */
C(0xb600, STCTL, RS_a, Z, 0, a2, 0, 0, stctl, 0) F(0xb600, STCTL, RS_a, Z, 0, a2, 0, 0, stctl, 0, IF_PRIV)
C(0xeb25, STCTG, RSY_a, Z, 0, a2, 0, 0, stctg, 0) F(0xeb25, STCTG, RSY_a, Z, 0, a2, 0, 0, stctg, 0, IF_PRIV)
/* STORE CPU ADDRESS */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* STORE USING REAL ADDRESS */
C(0xb246, STURA, RRE, Z, r1_o, r2_o, 0, 0, stura, 0) F(0xb246, STURA, RRE, Z, r1_o, r2_o, 0, 0, stura, 0, IF_PRIV)
C(0xb925, STURG, RRE, Z, r1_o, r2_o, 0, 0, sturg, 0) F(0xb925, STURG, RRE, Z, r1_o, r2_o, 0, 0, sturg, 0, IF_PRIV)
/* TEST BLOCK */ /* 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 */ /* TEST PROTECTION */
C(0xe501, TPROT, SSE, Z, la1, a2, 0, 0, tprot, 0) C(0xe501, TPROT, SSE, Z, la1, a2, 0, 0, tprot, 0)
/* CCW I/O Instructions */ /* CCW I/O Instructions */
C(0xb276, XSCH, S, Z, 0, 0, 0, 0, xsch, 0) F(0xb276, XSCH, S, Z, 0, 0, 0, 0, xsch, 0, IF_PRIV)
C(0xb230, CSCH, S, Z, 0, 0, 0, 0, csch, 0) F(0xb230, CSCH, S, Z, 0, 0, 0, 0, csch, 0, IF_PRIV)
C(0xb231, HSCH, S, Z, 0, 0, 0, 0, hsch, 0) F(0xb231, HSCH, S, Z, 0, 0, 0, 0, hsch, 0, IF_PRIV)
C(0xb232, MSCH, S, Z, 0, insn, 0, 0, msch, 0) F(0xb232, MSCH, S, Z, 0, insn, 0, 0, msch, 0, IF_PRIV)
C(0xb23b, RCHP, S, Z, 0, 0, 0, 0, rchp, 0) F(0xb23b, RCHP, S, Z, 0, 0, 0, 0, rchp, 0, IF_PRIV)
C(0xb238, RSCH, S, Z, 0, 0, 0, 0, rsch, 0) F(0xb238, RSCH, S, Z, 0, 0, 0, 0, rsch, 0, IF_PRIV)
C(0xb237, SAL, S, Z, 0, 0, 0, 0, sal, 0) F(0xb237, SAL, S, Z, 0, 0, 0, 0, sal, 0, IF_PRIV)
C(0xb23c, SCHM, S, Z, 0, insn, 0, 0, schm, 0) F(0xb23c, SCHM, S, Z, 0, insn, 0, 0, schm, 0, IF_PRIV)
C(0xb274, SIGA, S, Z, 0, 0, 0, 0, siga, 0) F(0xb274, SIGA, S, Z, 0, 0, 0, 0, siga, 0, IF_PRIV)
C(0xb23a, STCPS, S, Z, 0, 0, 0, 0, stcps, 0) F(0xb23a, STCPS, S, Z, 0, 0, 0, 0, stcps, 0, IF_PRIV)
C(0xb233, SSCH, S, Z, 0, insn, 0, 0, ssch, 0) F(0xb233, SSCH, S, Z, 0, insn, 0, 0, ssch, 0, IF_PRIV)
C(0xb239, STCRW, S, Z, 0, insn, 0, 0, stcrw, 0) F(0xb239, STCRW, S, Z, 0, insn, 0, 0, stcrw, 0, IF_PRIV)
C(0xb234, STSCH, S, Z, 0, insn, 0, 0, stsch, 0) F(0xb234, STSCH, S, Z, 0, insn, 0, 0, stsch, 0, IF_PRIV)
C(0xb236, TPI , S, Z, la2, 0, 0, 0, tpi, 0) F(0xb236, TPI , S, Z, la2, 0, 0, 0, tpi, 0, IF_PRIV)
C(0xb235, TSCH, S, Z, 0, insn, 0, 0, tsch, 0) 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 /* ??? Not listed in PoO ninth edition, but there's a linux driver that
uses it: "A CHSC subchannel is usually present on LPAR only." */ 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 */ /* zPCI Instructions */
/* None of these instructions are documented in the PoP, so this is all /* 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 */ based upon target/s390x/kvm.c and Linux code and likely incomplete */
C(0xebd0, PCISTB, RSY_a, PCI, la2, 0, 0, 0, pcistb, 0) F(0xebd0, PCISTB, RSY_a, PCI, la2, 0, 0, 0, pcistb, 0, IF_PRIV)
C(0xebd1, SIC, RSY_a, AIS, r1, r3, 0, 0, sic, 0) F(0xebd1, SIC, RSY_a, AIS, r1, r3, 0, 0, sic, 0, IF_PRIV)
C(0xb9a0, CLP, RRF_c, PCI, 0, 0, 0, 0, clp, 0) F(0xb9a0, CLP, RRF_c, PCI, 0, 0, 0, 0, clp, 0, IF_PRIV)
C(0xb9d0, PCISTG, RRE, PCI, 0, 0, 0, 0, pcistg, 0) F(0xb9d0, PCISTG, RRE, PCI, 0, 0, 0, 0, pcistg, 0, IF_PRIV)
C(0xb9d2, PCILG, RRE, PCI, 0, 0, 0, 0, pcilg, 0) F(0xb9d2, PCILG, RRE, PCI, 0, 0, 0, 0, pcilg, 0, IF_PRIV)
C(0xb9d3, RPCIT, RRE, PCI, 0, 0, 0, 0, rpcit, 0) F(0xb9d3, RPCIT, RRE, PCI, 0, 0, 0, 0, rpcit, 0, IF_PRIV)
C(0xe3d0, MPCIFC, RXY_a, PCI, la2, 0, 0, 0, mpcifc, 0) F(0xe3d0, MPCIFC, RXY_a, PCI, la2, 0, 0, 0, mpcifc, 0, IF_PRIV)
C(0xe3d4, STPCIFC, RXY_a, PCI, la2, 0, 0, 0, stpcifc, 0) F(0xe3d4, STPCIFC, RXY_a, PCI, la2, 0, 0, 0, stpcifc, 0, IF_PRIV)
#endif /* CONFIG_USER_ONLY */ #endif /* CONFIG_USER_ONLY */

View File

@ -15,6 +15,7 @@
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "sysemu/kvm.h" #include "sysemu/kvm.h"
#include "hw/s390x/ioinst.h" #include "hw/s390x/ioinst.h"
#include "tcg_s390x.h"
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
#include "hw/s390x/s390_flic.h" #include "hw/s390x/s390_flic.h"
#endif #endif
@ -29,25 +30,11 @@ void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen)
env->int_pgm_ilen = 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, void s390_program_interrupt(CPUS390XState *env, uint32_t code, int ilen,
uintptr_t ra) uintptr_t ra)
{ {
S390CPU *cpu = s390_env_get_cpu(env); S390CPU *cpu = s390_env_get_cpu(env);
qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n",
env->psw.addr);
if (kvm_enabled()) { if (kvm_enabled()) {
kvm_s390_program_interrupt(cpu, code); kvm_s390_program_interrupt(cpu, code);
} else if (tcg_enabled()) { } else if (tcg_enabled()) {

View File

@ -36,6 +36,7 @@
#include "qemu/timer.h" #include "qemu/timer.h"
#include "qemu/units.h" #include "qemu/units.h"
#include "qemu/mmap-alloc.h" #include "qemu/mmap-alloc.h"
#include "qemu/log.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "sysemu/hw_accel.h" #include "sysemu/hw_accel.h"
#include "hw/hw.h" #include "hw/hw.h"
@ -292,6 +293,12 @@ static int kvm_s390_configure_mempath_backing(KVMState *s)
return 0; return 0;
} }
if (!hpage_1m_allowed()) {
error_report("This QEMU machine does not support huge page "
"mappings");
return -EINVAL;
}
if (path_psize != 1 * MiB) { if (path_psize != 1 * MiB) {
error_report("Memory backing with 2G pages was specified, " error_report("Memory backing with 2G pages was specified, "
"but KVM does not support this memory backing"); "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, .type = KVM_S390_PROGRAM_INT,
.u.pgm.code = code, .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); kvm_s390_vcpu_interrupt(cpu, &irq);
} }

View File

@ -18,3 +18,13 @@
void tcg_s390_tod_updated(CPUState *cs, run_on_cpu_data opaque) 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();
}

View File

@ -14,5 +14,9 @@
#define TCG_S390X_H #define TCG_S390X_H
void tcg_s390_tod_updated(CPUState *cs, run_on_cpu_data opaque); 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 */ #endif /* TCG_S390X_H */

View File

@ -314,29 +314,19 @@ static inline void gen_illegal_opcode(DisasContext *s)
gen_program_exception(s, PGM_OPERATION); gen_program_exception(s, PGM_OPERATION);
} }
static inline void gen_data_exception(uint8_t dxc)
{
TCGv_i32 tmp = tcg_const_i32(dxc);
gen_helper_data_exception(cpu_env, tmp);
tcg_temp_free_i32(tmp);
}
static inline void gen_trap(DisasContext *s) static inline void gen_trap(DisasContext *s)
{ {
TCGv_i32 t; /* Set DXC to 0xff */
gen_data_exception(0xff);
/* 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);
} }
#ifndef CONFIG_USER_ONLY
static void check_privileged(DisasContext *s)
{
if (s->base.tb->flags & FLAG_MASK_PSTATE) {
gen_program_exception(s, PGM_PRIVILEGED);
}
}
#endif
static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2) static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
{ {
TCGv_i64 tmp = tcg_temp_new_i64(); TCGv_i64 tmp = tcg_temp_new_i64();
@ -1120,8 +1110,18 @@ typedef struct {
/* We are exiting the TB to the main loop. */ /* We are exiting the TB to the main loop. */
#define DISAS_PC_STALE_NOCHAIN DISAS_TARGET_4 #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 { struct DisasInsn {
unsigned opc:16; unsigned opc:16;
unsigned flags:16;
DisasFormat fmt:8; DisasFormat fmt:8;
unsigned fac:8; unsigned fac:8;
unsigned spec:8; unsigned spec:8;
@ -2078,7 +2078,6 @@ static DisasJumpType op_csp(DisasContext *s, DisasOps *o)
/* Note that in1 = R1 (zero-extended expected value), /* Note that in1 = R1 (zero-extended expected value),
out = R1 (original reg), out2 = R1+1 (new value). */ out = R1 (original reg), out2 = R1+1 (new value). */
check_privileged(s);
addr = tcg_temp_new_i64(); addr = tcg_temp_new_i64();
old = tcg_temp_new_i64(); old = tcg_temp_new_i64();
tcg_gen_andi_i64(addr, o->in2, -1ULL << (mop & MO_SIZE)); 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 r3 = tcg_const_i32(get_field(s->fields, r3));
TCGv_i32 func_code = tcg_const_i32(get_field(s->fields, i2)); TCGv_i32 func_code = tcg_const_i32(get_field(s->fields, i2));
check_privileged(s);
gen_helper_diag(cpu_env, r1, r3, func_code); gen_helper_diag(cpu_env, r1, r3, func_code);
tcg_temp_free_i32(func_code); tcg_temp_free_i32(func_code);
@ -2463,7 +2461,6 @@ static DisasJumpType op_idte(DisasContext *s, DisasOps *o)
{ {
TCGv_i32 m4; TCGv_i32 m4;
check_privileged(s);
if (s390_has_feat(S390_FEAT_LOCAL_TLB_CLEARING)) { if (s390_has_feat(S390_FEAT_LOCAL_TLB_CLEARING)) {
m4 = tcg_const_i32(get_field(s->fields, m4)); m4 = tcg_const_i32(get_field(s->fields, m4));
} else { } else {
@ -2478,7 +2475,6 @@ static DisasJumpType op_ipte(DisasContext *s, DisasOps *o)
{ {
TCGv_i32 m4; TCGv_i32 m4;
check_privileged(s);
if (s390_has_feat(S390_FEAT_LOCAL_TLB_CLEARING)) { if (s390_has_feat(S390_FEAT_LOCAL_TLB_CLEARING)) {
m4 = tcg_const_i32(get_field(s->fields, m4)); m4 = tcg_const_i32(get_field(s->fields, m4));
} else { } else {
@ -2491,7 +2487,6 @@ static DisasJumpType op_ipte(DisasContext *s, DisasOps *o)
static DisasJumpType op_iske(DisasContext *s, DisasOps *o) static DisasJumpType op_iske(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_iske(o->out, cpu_env, o->in2); gen_helper_iske(o->out, cpu_env, o->in2);
return DISAS_NEXT; 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 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
check_privileged(s);
gen_helper_lctl(cpu_env, r1, o->in2, r3); gen_helper_lctl(cpu_env, r1, o->in2, r3);
tcg_temp_free_i32(r1); tcg_temp_free_i32(r1);
tcg_temp_free_i32(r3); 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 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
check_privileged(s);
gen_helper_lctlg(cpu_env, r1, o->in2, r3); gen_helper_lctlg(cpu_env, r1, o->in2, r3);
tcg_temp_free_i32(r1); tcg_temp_free_i32(r1);
tcg_temp_free_i32(r3); 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) static DisasJumpType op_lra(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_lra(o->out, cpu_env, o->in2); gen_helper_lra(o->out, cpu_env, o->in2);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; return DISAS_NEXT;
@ -2820,8 +2812,6 @@ static DisasJumpType op_lra(DisasContext *s, DisasOps *o)
static DisasJumpType op_lpp(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)); tcg_gen_st_i64(o->in2, cpu_env, offsetof(CPUS390XState, pp));
return DISAS_NEXT; return DISAS_NEXT;
} }
@ -2830,12 +2820,12 @@ static DisasJumpType op_lpsw(DisasContext *s, DisasOps *o)
{ {
TCGv_i64 t1, t2; TCGv_i64 t1, t2;
check_privileged(s);
per_breaking_event(s); per_breaking_event(s);
t1 = tcg_temp_new_i64(); t1 = tcg_temp_new_i64();
t2 = 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_addi_i64(o->in2, o->in2, 4);
tcg_gen_qemu_ld32u(t2, o->in2, get_mem_index(s)); tcg_gen_qemu_ld32u(t2, o->in2, get_mem_index(s));
/* Convert the 32-bit PSW_MASK into the 64-bit PSW_MASK. */ /* 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; TCGv_i64 t1, t2;
check_privileged(s);
per_breaking_event(s); per_breaking_event(s);
t1 = tcg_temp_new_i64(); t1 = tcg_temp_new_i64();
t2 = 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_addi_i64(o->in2, o->in2, 8);
tcg_gen_qemu_ld64(t2, o->in2, get_mem_index(s)); tcg_gen_qemu_ld64(t2, o->in2, get_mem_index(s));
gen_helper_load_psw(cpu_env, t1, t2); gen_helper_load_psw(cpu_env, t1, t2);
@ -3048,14 +3038,12 @@ static DisasJumpType op_lpq(DisasContext *s, DisasOps *o)
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
static DisasJumpType op_lura(DisasContext *s, DisasOps *o) static DisasJumpType op_lura(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_lura(o->out, cpu_env, o->in2); gen_helper_lura(o->out, cpu_env, o->in2);
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_lurag(DisasContext *s, DisasOps *o) static DisasJumpType op_lurag(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_lurag(o->out, cpu_env, o->in2); gen_helper_lurag(o->out, cpu_env, o->in2);
return DISAS_NEXT; return DISAS_NEXT;
} }
@ -3214,7 +3202,6 @@ static DisasJumpType op_mvcos(DisasContext *s, DisasOps *o)
static DisasJumpType op_mvcp(DisasContext *s, DisasOps *o) static DisasJumpType op_mvcp(DisasContext *s, DisasOps *o)
{ {
int r1 = get_field(s->fields, l1); int r1 = get_field(s->fields, l1);
check_privileged(s);
gen_helper_mvcp(cc_op, cpu_env, regs[r1], o->addr1, o->in2); gen_helper_mvcp(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; return DISAS_NEXT;
@ -3223,7 +3210,6 @@ static DisasJumpType op_mvcp(DisasContext *s, DisasOps *o)
static DisasJumpType op_mvcs(DisasContext *s, DisasOps *o) static DisasJumpType op_mvcs(DisasContext *s, DisasOps *o)
{ {
int r1 = get_field(s->fields, l1); int r1 = get_field(s->fields, l1);
check_privileged(s);
gen_helper_mvcs(cc_op, cpu_env, regs[r1], o->addr1, o->in2); gen_helper_mvcs(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; return DISAS_NEXT;
@ -3509,7 +3495,6 @@ static DisasJumpType op_popcnt(DisasContext *s, DisasOps *o)
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
static DisasJumpType op_ptlb(DisasContext *s, DisasOps *o) static DisasJumpType op_ptlb(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_ptlb(cpu_env); gen_helper_ptlb(cpu_env);
return DISAS_NEXT; return DISAS_NEXT;
} }
@ -3700,7 +3685,6 @@ static DisasJumpType op_rll64(DisasContext *s, DisasOps *o)
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
static DisasJumpType op_rrbe(DisasContext *s, DisasOps *o) static DisasJumpType op_rrbe(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_rrbe(cc_op, cpu_env, o->in2); gen_helper_rrbe(cc_op, cpu_env, o->in2);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; return DISAS_NEXT;
@ -3708,7 +3692,6 @@ static DisasJumpType op_rrbe(DisasContext *s, DisasOps *o)
static DisasJumpType op_sacf(DisasContext *s, DisasOps *o) static DisasJumpType op_sacf(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_sacf(cpu_env, o->in2); gen_helper_sacf(cpu_env, o->in2);
/* Addressing mode has changed, so end the block. */ /* Addressing mode has changed, so end the block. */
return DISAS_PC_STALE; return DISAS_PC_STALE;
@ -3798,7 +3781,6 @@ static DisasJumpType op_sqxb(DisasContext *s, DisasOps *o)
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
static DisasJumpType op_servc(DisasContext *s, DisasOps *o) static DisasJumpType op_servc(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_servc(cc_op, cpu_env, o->in2, o->in1); gen_helper_servc(cc_op, cpu_env, o->in2, o->in1);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; 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 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); 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); gen_helper_sigp(cc_op, cpu_env, o->in2, r1, r3);
set_cc_static(s); set_cc_static(s);
tcg_temp_free_i32(r1); tcg_temp_free_i32(r1);
@ -3990,7 +3971,6 @@ static DisasJumpType op_ectg(DisasContext *s, DisasOps *o)
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
static DisasJumpType op_spka(DisasContext *s, DisasOps *o) static DisasJumpType op_spka(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
tcg_gen_shri_i64(o->in2, o->in2, 4); tcg_gen_shri_i64(o->in2, o->in2, 4);
tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, PSW_SHIFT_KEY, 4); tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, PSW_SHIFT_KEY, 4);
return DISAS_NEXT; return DISAS_NEXT;
@ -3998,14 +3978,12 @@ static DisasJumpType op_spka(DisasContext *s, DisasOps *o)
static DisasJumpType op_sske(DisasContext *s, DisasOps *o) static DisasJumpType op_sske(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_sske(cpu_env, o->in1, o->in2); gen_helper_sske(cpu_env, o->in1, o->in2);
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_ssm(DisasContext *s, DisasOps *o) static DisasJumpType op_ssm(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8); tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8);
/* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */ /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */
return DISAS_PC_STALE_NOCHAIN; 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) static DisasJumpType op_stap(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, core_id)); tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, core_id));
return DISAS_NEXT; return DISAS_NEXT;
} }
@ -4055,7 +4032,6 @@ static DisasJumpType op_stcke(DisasContext *s, DisasOps *o)
static DisasJumpType op_sck(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); 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); gen_helper_sck(cc_op, cpu_env, o->in1);
set_cc_static(s); set_cc_static(s);
@ -4064,21 +4040,18 @@ static DisasJumpType op_sck(DisasContext *s, DisasOps *o)
static DisasJumpType op_sckc(DisasContext *s, DisasOps *o) static DisasJumpType op_sckc(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_sckc(cpu_env, o->in2); gen_helper_sckc(cpu_env, o->in2);
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_sckpf(DisasContext *s, DisasOps *o) static DisasJumpType op_sckpf(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_sckpf(cpu_env, regs[0]); gen_helper_sckpf(cpu_env, regs[0]);
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_stckc(DisasContext *s, DisasOps *o) static DisasJumpType op_stckc(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_stckc(o->out, cpu_env); gen_helper_stckc(o->out, cpu_env);
return DISAS_NEXT; 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 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
check_privileged(s);
gen_helper_stctg(cpu_env, r1, o->in2, r3); gen_helper_stctg(cpu_env, r1, o->in2, r3);
tcg_temp_free_i32(r1); tcg_temp_free_i32(r1);
tcg_temp_free_i32(r3); 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 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
check_privileged(s);
gen_helper_stctl(cpu_env, r1, o->in2, r3); gen_helper_stctl(cpu_env, r1, o->in2, r3);
tcg_temp_free_i32(r1); tcg_temp_free_i32(r1);
tcg_temp_free_i32(r3); 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) static DisasJumpType op_stidp(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
tcg_gen_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, cpuid)); tcg_gen_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, cpuid));
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_spt(DisasContext *s, DisasOps *o) static DisasJumpType op_spt(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_spt(cpu_env, o->in2); gen_helper_spt(cpu_env, o->in2);
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_stfl(DisasContext *s, DisasOps *o) static DisasJumpType op_stfl(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_stfl(cpu_env); gen_helper_stfl(cpu_env);
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_stpt(DisasContext *s, DisasOps *o) static DisasJumpType op_stpt(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_stpt(o->out, cpu_env); gen_helper_stpt(o->out, cpu_env);
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_stsi(DisasContext *s, DisasOps *o) static DisasJumpType op_stsi(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_stsi(cc_op, cpu_env, o->in2, regs[0], regs[1]); gen_helper_stsi(cc_op, cpu_env, o->in2, regs[0], regs[1]);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; return DISAS_NEXT;
@ -4143,14 +4109,12 @@ static DisasJumpType op_stsi(DisasContext *s, DisasOps *o)
static DisasJumpType op_spx(DisasContext *s, DisasOps *o) static DisasJumpType op_spx(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_spx(cpu_env, o->in2); gen_helper_spx(cpu_env, o->in2);
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_xsch(DisasContext *s, DisasOps *o) static DisasJumpType op_xsch(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_xsch(cpu_env, regs[1]); gen_helper_xsch(cpu_env, regs[1]);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; return DISAS_NEXT;
@ -4158,7 +4122,6 @@ static DisasJumpType op_xsch(DisasContext *s, DisasOps *o)
static DisasJumpType op_csch(DisasContext *s, DisasOps *o) static DisasJumpType op_csch(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_csch(cpu_env, regs[1]); gen_helper_csch(cpu_env, regs[1]);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; return DISAS_NEXT;
@ -4166,7 +4129,6 @@ static DisasJumpType op_csch(DisasContext *s, DisasOps *o)
static DisasJumpType op_hsch(DisasContext *s, DisasOps *o) static DisasJumpType op_hsch(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_hsch(cpu_env, regs[1]); gen_helper_hsch(cpu_env, regs[1]);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; return DISAS_NEXT;
@ -4174,7 +4136,6 @@ static DisasJumpType op_hsch(DisasContext *s, DisasOps *o)
static DisasJumpType op_msch(DisasContext *s, DisasOps *o) static DisasJumpType op_msch(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_msch(cpu_env, regs[1], o->in2); gen_helper_msch(cpu_env, regs[1], o->in2);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; return DISAS_NEXT;
@ -4182,7 +4143,6 @@ static DisasJumpType op_msch(DisasContext *s, DisasOps *o)
static DisasJumpType op_rchp(DisasContext *s, DisasOps *o) static DisasJumpType op_rchp(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_rchp(cpu_env, regs[1]); gen_helper_rchp(cpu_env, regs[1]);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; return DISAS_NEXT;
@ -4190,7 +4150,6 @@ static DisasJumpType op_rchp(DisasContext *s, DisasOps *o)
static DisasJumpType op_rsch(DisasContext *s, DisasOps *o) static DisasJumpType op_rsch(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_rsch(cpu_env, regs[1]); gen_helper_rsch(cpu_env, regs[1]);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; return DISAS_NEXT;
@ -4198,21 +4157,18 @@ static DisasJumpType op_rsch(DisasContext *s, DisasOps *o)
static DisasJumpType op_sal(DisasContext *s, DisasOps *o) static DisasJumpType op_sal(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_sal(cpu_env, regs[1]); gen_helper_sal(cpu_env, regs[1]);
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_schm(DisasContext *s, DisasOps *o) static DisasJumpType op_schm(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_schm(cpu_env, regs[1], regs[2], o->in2); gen_helper_schm(cpu_env, regs[1], regs[2], o->in2);
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_siga(DisasContext *s, DisasOps *o) static DisasJumpType op_siga(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
/* From KVM code: Not provided, set CC = 3 for subchannel not operational */ /* From KVM code: Not provided, set CC = 3 for subchannel not operational */
gen_op_movi_cc(s, 3); gen_op_movi_cc(s, 3);
return DISAS_NEXT; return DISAS_NEXT;
@ -4220,14 +4176,12 @@ static DisasJumpType op_siga(DisasContext *s, DisasOps *o)
static DisasJumpType op_stcps(DisasContext *s, DisasOps *o) static DisasJumpType op_stcps(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
/* The instruction is suppressed if not provided. */ /* The instruction is suppressed if not provided. */
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_ssch(DisasContext *s, DisasOps *o) static DisasJumpType op_ssch(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_ssch(cpu_env, regs[1], o->in2); gen_helper_ssch(cpu_env, regs[1], o->in2);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; return DISAS_NEXT;
@ -4235,7 +4189,6 @@ static DisasJumpType op_ssch(DisasContext *s, DisasOps *o)
static DisasJumpType op_stsch(DisasContext *s, DisasOps *o) static DisasJumpType op_stsch(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_stsch(cpu_env, regs[1], o->in2); gen_helper_stsch(cpu_env, regs[1], o->in2);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; return DISAS_NEXT;
@ -4243,7 +4196,6 @@ static DisasJumpType op_stsch(DisasContext *s, DisasOps *o)
static DisasJumpType op_stcrw(DisasContext *s, DisasOps *o) static DisasJumpType op_stcrw(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_stcrw(cpu_env, o->in2); gen_helper_stcrw(cpu_env, o->in2);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; return DISAS_NEXT;
@ -4251,7 +4203,6 @@ static DisasJumpType op_stcrw(DisasContext *s, DisasOps *o)
static DisasJumpType op_tpi(DisasContext *s, DisasOps *o) static DisasJumpType op_tpi(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_tpi(cc_op, cpu_env, o->addr1); gen_helper_tpi(cc_op, cpu_env, o->addr1);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; return DISAS_NEXT;
@ -4259,7 +4210,6 @@ static DisasJumpType op_tpi(DisasContext *s, DisasOps *o)
static DisasJumpType op_tsch(DisasContext *s, DisasOps *o) static DisasJumpType op_tsch(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_tsch(cpu_env, regs[1], o->in2); gen_helper_tsch(cpu_env, regs[1], o->in2);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; return DISAS_NEXT;
@ -4267,7 +4217,6 @@ static DisasJumpType op_tsch(DisasContext *s, DisasOps *o)
static DisasJumpType op_chsc(DisasContext *s, DisasOps *o) static DisasJumpType op_chsc(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_chsc(cpu_env, o->in2); gen_helper_chsc(cpu_env, o->in2);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; return DISAS_NEXT;
@ -4275,7 +4224,6 @@ static DisasJumpType op_chsc(DisasContext *s, DisasOps *o)
static DisasJumpType op_stpx(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_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, psa));
tcg_gen_andi_i64(o->out, o->out, 0x7fffe000); tcg_gen_andi_i64(o->out, o->out, 0x7fffe000);
return DISAS_NEXT; return DISAS_NEXT;
@ -4286,8 +4234,6 @@ static DisasJumpType op_stnosm(DisasContext *s, DisasOps *o)
uint64_t i2 = get_field(s->fields, i2); uint64_t i2 = get_field(s->fields, i2);
TCGv_i64 t; TCGv_i64 t;
check_privileged(s);
/* It is important to do what the instruction name says: STORE THEN. /* 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 If we let the output hook perform the store then if we fault and
restart, we'll have the wrong SYSTEM MASK in place. */ 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) static DisasJumpType op_stura(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_stura(cpu_env, o->in2, o->in1); gen_helper_stura(cpu_env, o->in2, o->in1);
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_sturg(DisasContext *s, DisasOps *o) static DisasJumpType op_sturg(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_sturg(cpu_env, o->in2, o->in1); gen_helper_sturg(cpu_env, o->in2, o->in1);
return DISAS_NEXT; return DISAS_NEXT;
} }
@ -4582,7 +4526,6 @@ static DisasJumpType op_tcxb(DisasContext *s, DisasOps *o)
static DisasJumpType op_testblock(DisasContext *s, DisasOps *o) static DisasJumpType op_testblock(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_testblock(cc_op, cpu_env, o->in2); gen_helper_testblock(cc_op, cpu_env, o->in2);
set_cc_static(s); set_cc_static(s);
return DISAS_NEXT; 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)); TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2));
check_privileged(s);
gen_helper_clp(cpu_env, r2); gen_helper_clp(cpu_env, r2);
tcg_temp_free_i32(r2); tcg_temp_free_i32(r2);
set_cc_static(s); 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 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2)); TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2));
check_privileged(s);
gen_helper_pcilg(cpu_env, r1, r2); gen_helper_pcilg(cpu_env, r1, r2);
tcg_temp_free_i32(r1); tcg_temp_free_i32(r1);
tcg_temp_free_i32(r2); 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 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2)); TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2));
check_privileged(s);
gen_helper_pcistg(cpu_env, r1, r2); gen_helper_pcistg(cpu_env, r1, r2);
tcg_temp_free_i32(r1); tcg_temp_free_i32(r1);
tcg_temp_free_i32(r2); 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 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 ar = tcg_const_i32(get_field(s->fields, b2)); TCGv_i32 ar = tcg_const_i32(get_field(s->fields, b2));
check_privileged(s);
gen_helper_stpcifc(cpu_env, r1, o->addr1, ar); gen_helper_stpcifc(cpu_env, r1, o->addr1, ar);
tcg_temp_free_i32(ar); tcg_temp_free_i32(ar);
tcg_temp_free_i32(r1); 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) static DisasJumpType op_sic(DisasContext *s, DisasOps *o)
{ {
check_privileged(s);
gen_helper_sic(cpu_env, o->in1, o->in2); gen_helper_sic(cpu_env, o->in1, o->in2);
return DISAS_NEXT; 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 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2)); TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2));
check_privileged(s);
gen_helper_rpcit(cpu_env, r1, r2); gen_helper_rpcit(cpu_env, r1, r2);
tcg_temp_free_i32(r1); tcg_temp_free_i32(r1);
tcg_temp_free_i32(r2); 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 r3 = tcg_const_i32(get_field(s->fields, r3));
TCGv_i32 ar = tcg_const_i32(get_field(s->fields, b2)); TCGv_i32 ar = tcg_const_i32(get_field(s->fields, b2));
check_privileged(s);
gen_helper_pcistb(cpu_env, r1, r3, o->addr1, ar); gen_helper_pcistb(cpu_env, r1, r3, o->addr1, ar);
tcg_temp_free_i32(ar); tcg_temp_free_i32(ar);
tcg_temp_free_i32(r1); 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 r1 = tcg_const_i32(get_field(s->fields, r1));
TCGv_i32 ar = tcg_const_i32(get_field(s->fields, b2)); TCGv_i32 ar = tcg_const_i32(get_field(s->fields, b2));
check_privileged(s);
gen_helper_mpcifc(cpu_env, r1, o->addr1, ar); gen_helper_mpcifc(cpu_env, r1, o->addr1, ar);
tcg_temp_free_i32(ar); tcg_temp_free_i32(ar);
tcg_temp_free_i32(r1); 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. */ search tree, rather than us having to post-process the table. */
#define C(OPC, NM, FT, FC, I1, I2, P, W, OP, CC) \ #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 { enum DisasInsnEnum {
#include "insn-data.def" #include "insn-data.def"
}; };
#undef D #undef E
#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) { \ #define E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D, FL) { \
.opc = OPC, \ .opc = OPC, \
.flags = FL, \
.fmt = FMT_##FT, \ .fmt = FMT_##FT, \
.fac = FAC_##FC, \ .fac = FAC_##FC, \
.spec = SPEC_in1_##I1 | SPEC_in2_##I2 | SPEC_prep_##P | SPEC_wout_##W, \ .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" #include "insn-data.def"
}; };
#undef D #undef E
#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) \ #define E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D, FL) \
case OPC: return &insn_info[insn_ ## NM]; case OPC: return &insn_info[insn_ ## NM];
static const DisasInsn *lookup_opc(uint16_t opc) 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 D
#undef C #undef C
@ -6075,6 +6019,17 @@ static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s,
return info; 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) static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s)
{ {
const DisasInsn *insn; const DisasInsn *insn;
@ -6101,42 +6056,48 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s)
} }
#endif #endif
/* 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 ((insn->flags & IF_AFP1) && is_afp_reg(get_field(&f, r1))) {
dxc = 1;
}
if ((insn->flags & IF_AFP2) && is_afp_reg(get_field(&f, r2))) {
dxc = 1;
}
if ((insn->flags & IF_AFP3) && is_afp_reg(get_field(&f, r3))) {
dxc = 1;
}
if (insn->flags & IF_BFP) {
dxc = 2;
}
if (insn->flags & IF_DFP) {
dxc = 3;
}
if (dxc) {
gen_data_exception(dxc);
return DISAS_NORETURN;
}
}
}
/* Check for insn specification exceptions. */ /* Check for insn specification exceptions. */
if (insn->spec) { if (insn->spec) {
int spec = insn->spec, excp = 0, r; if ((insn->spec & SPEC_r1_even && get_field(&f, r1) & 1) ||
(insn->spec & SPEC_r2_even && get_field(&f, r2) & 1) ||
if (spec & SPEC_r1_even) { (insn->spec & SPEC_r3_even && get_field(&f, r3) & 1) ||
r = get_field(&f, r1); (insn->spec & SPEC_r1_f128 && !is_fp_pair(get_field(&f, r1))) ||
if (r & 1) { (insn->spec & SPEC_r2_f128 && !is_fp_pair(get_field(&f, r2)))) {
excp = PGM_SPECIFICATION; gen_program_exception(s, PGM_SPECIFICATION);
}
}
if (spec & SPEC_r2_even) {
r = get_field(&f, r2);
if (r & 1) {
excp = PGM_SPECIFICATION;
}
}
if (spec & SPEC_r3_even) {
r = get_field(&f, r3);
if (r & 1) {
excp = PGM_SPECIFICATION;
}
}
if (spec & SPEC_r1_f128) {
r = get_field(&f, r1);
if (r > 13) {
excp = PGM_SPECIFICATION;
}
}
if (spec & SPEC_r2_f128) {
r = get_field(&f, r2);
if (r > 13) {
excp = PGM_SPECIFICATION;
}
}
if (excp) {
gen_program_exception(s, excp);
return DISAS_NORETURN; return DISAS_NORETURN;
} }
} }