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