summaryrefslogtreecommitdiffstats
path: root/qemu/target-s390x
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/target-s390x')
-rw-r--r--qemu/target-s390x/Makefile.objs5
-rw-r--r--qemu/target-s390x/arch_dump.c249
-rw-r--r--qemu/target-s390x/cc_helper.c569
-rw-r--r--qemu/target-s390x/cpu-qom.h104
-rw-r--r--qemu/target-s390x/cpu.c481
-rw-r--r--qemu/target-s390x/cpu.h1326
-rw-r--r--qemu/target-s390x/fpu_helper.c744
-rw-r--r--qemu/target-s390x/gdbstub.c311
-rw-r--r--qemu/target-s390x/helper.c692
-rw-r--r--qemu/target-s390x/helper.h133
-rw-r--r--qemu/target-s390x/insn-data.def931
-rw-r--r--qemu/target-s390x/insn-format.def55
-rw-r--r--qemu/target-s390x/int_helper.c155
-rw-r--r--qemu/target-s390x/interrupt.c56
-rw-r--r--qemu/target-s390x/ioinst.c833
-rw-r--r--qemu/target-s390x/ioinst.h246
-rw-r--r--qemu/target-s390x/kvm.c2252
-rw-r--r--qemu/target-s390x/machine.c171
-rw-r--r--qemu/target-s390x/mem_helper.c1198
-rw-r--r--qemu/target-s390x/misc_helper.c640
-rw-r--r--qemu/target-s390x/mmu_helper.c499
-rw-r--r--qemu/target-s390x/translate.c5442
22 files changed, 0 insertions, 17092 deletions
diff --git a/qemu/target-s390x/Makefile.objs b/qemu/target-s390x/Makefile.objs
deleted file mode 100644
index dd62cbda8..000000000
--- a/qemu/target-s390x/Makefile.objs
+++ /dev/null
@@ -1,5 +0,0 @@
-obj-y += translate.o helper.o cpu.o interrupt.o
-obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o
-obj-y += gdbstub.o
-obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o mmu_helper.o
-obj-$(CONFIG_KVM) += kvm.o
diff --git a/qemu/target-s390x/arch_dump.c b/qemu/target-s390x/arch_dump.c
deleted file mode 100644
index 4731869f6..000000000
--- a/qemu/target-s390x/arch_dump.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * writing ELF notes for s390x arch
- *
- *
- * Copyright IBM Corp. 2012, 2013
- *
- * Ekaterina Tumanova <tumanova@linux.vnet.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "elf.h"
-#include "exec/cpu-all.h"
-#include "sysemu/dump.h"
-#include "sysemu/kvm.h"
-
-
-struct S390xUserRegsStruct {
- uint64_t psw[2];
- uint64_t gprs[16];
- uint32_t acrs[16];
-} QEMU_PACKED;
-
-typedef struct S390xUserRegsStruct S390xUserRegs;
-
-struct S390xElfPrstatusStruct {
- uint8_t pad1[32];
- uint32_t pid;
- uint8_t pad2[76];
- S390xUserRegs regs;
- uint8_t pad3[16];
-} QEMU_PACKED;
-
-typedef struct S390xElfPrstatusStruct S390xElfPrstatus;
-
-struct S390xElfFpregsetStruct {
- uint32_t fpc;
- uint32_t pad;
- uint64_t fprs[16];
-} QEMU_PACKED;
-
-typedef struct S390xElfFpregsetStruct S390xElfFpregset;
-
-struct S390xElfVregsLoStruct {
- uint64_t vregs[16];
-} QEMU_PACKED;
-
-typedef struct S390xElfVregsLoStruct S390xElfVregsLo;
-
-struct S390xElfVregsHiStruct {
- uint64_t vregs[16][2];
-} QEMU_PACKED;
-
-typedef struct S390xElfVregsHiStruct S390xElfVregsHi;
-
-typedef struct noteStruct {
- Elf64_Nhdr hdr;
- char name[5];
- char pad3[3];
- union {
- S390xElfPrstatus prstatus;
- S390xElfFpregset fpregset;
- S390xElfVregsLo vregslo;
- S390xElfVregsHi vregshi;
- uint32_t prefix;
- uint64_t timer;
- uint64_t todcmp;
- uint32_t todpreg;
- uint64_t ctrs[16];
- } contents;
-} QEMU_PACKED Note;
-
-static void s390x_write_elf64_prstatus(Note *note, S390CPU *cpu)
-{
- int i;
- S390xUserRegs *regs;
-
- note->hdr.n_type = cpu_to_be32(NT_PRSTATUS);
-
- regs = &(note->contents.prstatus.regs);
- regs->psw[0] = cpu_to_be64(cpu->env.psw.mask);
- regs->psw[1] = cpu_to_be64(cpu->env.psw.addr);
- for (i = 0; i <= 15; i++) {
- regs->acrs[i] = cpu_to_be32(cpu->env.aregs[i]);
- regs->gprs[i] = cpu_to_be64(cpu->env.regs[i]);
- }
-}
-
-static void s390x_write_elf64_fpregset(Note *note, S390CPU *cpu)
-{
- int i;
- CPUS390XState *cs = &cpu->env;
-
- note->hdr.n_type = cpu_to_be32(NT_FPREGSET);
- note->contents.fpregset.fpc = cpu_to_be32(cpu->env.fpc);
- for (i = 0; i <= 15; i++) {
- note->contents.fpregset.fprs[i] = cpu_to_be64(get_freg(cs, i)->ll);
- }
-}
-
-static void s390x_write_elf64_vregslo(Note *note, S390CPU *cpu)
-{
- int i;
-
- note->hdr.n_type = cpu_to_be32(NT_S390_VXRS_LOW);
- for (i = 0; i <= 15; i++) {
- note->contents.vregslo.vregs[i] = cpu_to_be64(cpu->env.vregs[i][1].ll);
- }
-}
-
-static void s390x_write_elf64_vregshi(Note *note, S390CPU *cpu)
-{
- int i;
- S390xElfVregsHi *temp_vregshi;
-
- temp_vregshi = &note->contents.vregshi;
-
- note->hdr.n_type = cpu_to_be32(NT_S390_VXRS_HIGH);
- for (i = 0; i <= 15; i++) {
- temp_vregshi->vregs[i][0] = cpu_to_be64(cpu->env.vregs[i + 16][0].ll);
- temp_vregshi->vregs[i][1] = cpu_to_be64(cpu->env.vregs[i + 16][1].ll);
- }
-}
-
-static void s390x_write_elf64_timer(Note *note, S390CPU *cpu)
-{
- note->hdr.n_type = cpu_to_be32(NT_S390_TIMER);
- note->contents.timer = cpu_to_be64((uint64_t)(cpu->env.cputm));
-}
-
-static void s390x_write_elf64_todcmp(Note *note, S390CPU *cpu)
-{
- note->hdr.n_type = cpu_to_be32(NT_S390_TODCMP);
- note->contents.todcmp = cpu_to_be64((uint64_t)(cpu->env.ckc));
-}
-
-static void s390x_write_elf64_todpreg(Note *note, S390CPU *cpu)
-{
- note->hdr.n_type = cpu_to_be32(NT_S390_TODPREG);
- note->contents.todpreg = cpu_to_be32((uint32_t)(cpu->env.todpr));
-}
-
-static void s390x_write_elf64_ctrs(Note *note, S390CPU *cpu)
-{
- int i;
-
- note->hdr.n_type = cpu_to_be32(NT_S390_CTRS);
-
- for (i = 0; i <= 15; i++) {
- note->contents.ctrs[i] = cpu_to_be64(cpu->env.cregs[i]);
- }
-}
-
-static void s390x_write_elf64_prefix(Note *note, S390CPU *cpu)
-{
- note->hdr.n_type = cpu_to_be32(NT_S390_PREFIX);
- note->contents.prefix = cpu_to_be32((uint32_t)(cpu->env.psa));
-}
-
-
-static const struct NoteFuncDescStruct {
- int contents_size;
- void (*note_contents_func)(Note *note, S390CPU *cpu);
-} note_func[] = {
- {sizeof(((Note *)0)->contents.prstatus), s390x_write_elf64_prstatus},
- {sizeof(((Note *)0)->contents.prefix), s390x_write_elf64_prefix},
- {sizeof(((Note *)0)->contents.fpregset), s390x_write_elf64_fpregset},
- {sizeof(((Note *)0)->contents.ctrs), s390x_write_elf64_ctrs},
- {sizeof(((Note *)0)->contents.timer), s390x_write_elf64_timer},
- {sizeof(((Note *)0)->contents.todcmp), s390x_write_elf64_todcmp},
- {sizeof(((Note *)0)->contents.todpreg), s390x_write_elf64_todpreg},
- {sizeof(((Note *)0)->contents.vregslo), s390x_write_elf64_vregslo},
- {sizeof(((Note *)0)->contents.vregshi), s390x_write_elf64_vregshi},
- { 0, NULL}
-};
-
-typedef struct NoteFuncDescStruct NoteFuncDesc;
-
-
-static int s390x_write_all_elf64_notes(const char *note_name,
- WriteCoreDumpFunction f,
- S390CPU *cpu, int id,
- void *opaque)
-{
- Note note;
- const NoteFuncDesc *nf;
- int note_size;
- int ret = -1;
-
- for (nf = note_func; nf->note_contents_func; nf++) {
- memset(&note, 0, sizeof(note));
- note.hdr.n_namesz = cpu_to_be32(sizeof(note.name));
- note.hdr.n_descsz = cpu_to_be32(nf->contents_size);
- strncpy(note.name, note_name, sizeof(note.name));
- (*nf->note_contents_func)(&note, cpu);
-
- note_size = sizeof(note) - sizeof(note.contents) + nf->contents_size;
- ret = f(&note, note_size, opaque);
-
- if (ret < 0) {
- return -1;
- }
-
- }
-
- return 0;
-}
-
-
-int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
- int cpuid, void *opaque)
-{
- S390CPU *cpu = S390_CPU(cs);
- return s390x_write_all_elf64_notes("CORE", f, cpu, cpuid, opaque);
-}
-
-int cpu_get_dump_info(ArchDumpInfo *info,
- const struct GuestPhysBlockList *guest_phys_blocks)
-{
- info->d_machine = EM_S390;
- info->d_endian = ELFDATA2MSB;
- info->d_class = ELFCLASS64;
-
- return 0;
-}
-
-ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
-{
- int name_size = 8; /* "CORE" or "QEMU" rounded */
- size_t elf_note_size = 0;
- int note_head_size;
- const NoteFuncDesc *nf;
-
- assert(class == ELFCLASS64);
- assert(machine == EM_S390);
-
- note_head_size = sizeof(Elf64_Nhdr);
-
- for (nf = note_func; nf->note_contents_func; nf++) {
- elf_note_size = elf_note_size + note_head_size + name_size +
- nf->contents_size;
- }
-
- return (elf_note_size) * nr_cpus;
-}
diff --git a/qemu/target-s390x/cc_helper.c b/qemu/target-s390x/cc_helper.c
deleted file mode 100644
index 0d9411bdf..000000000
--- a/qemu/target-s390x/cc_helper.c
+++ /dev/null
@@ -1,569 +0,0 @@
-/*
- * S/390 condition code helper routines
- *
- * Copyright (c) 2009 Ulrich Hecht
- * Copyright (c) 2009 Alexander Graf
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "exec/helper-proto.h"
-#include "qemu/host-utils.h"
-
-/* #define DEBUG_HELPER */
-#ifdef DEBUG_HELPER
-#define HELPER_LOG(x...) qemu_log(x)
-#else
-#define HELPER_LOG(x...)
-#endif
-
-static uint32_t cc_calc_ltgt_32(int32_t src, int32_t dst)
-{
- if (src == dst) {
- return 0;
- } else if (src < dst) {
- return 1;
- } else {
- return 2;
- }
-}
-
-static uint32_t cc_calc_ltgt0_32(int32_t dst)
-{
- return cc_calc_ltgt_32(dst, 0);
-}
-
-static uint32_t cc_calc_ltgt_64(int64_t src, int64_t dst)
-{
- if (src == dst) {
- return 0;
- } else if (src < dst) {
- return 1;
- } else {
- return 2;
- }
-}
-
-static uint32_t cc_calc_ltgt0_64(int64_t dst)
-{
- return cc_calc_ltgt_64(dst, 0);
-}
-
-static uint32_t cc_calc_ltugtu_32(uint32_t src, uint32_t dst)
-{
- if (src == dst) {
- return 0;
- } else if (src < dst) {
- return 1;
- } else {
- return 2;
- }
-}
-
-static uint32_t cc_calc_ltugtu_64(uint64_t src, uint64_t dst)
-{
- if (src == dst) {
- return 0;
- } else if (src < dst) {
- return 1;
- } else {
- return 2;
- }
-}
-
-static uint32_t cc_calc_tm_32(uint32_t val, uint32_t mask)
-{
- uint32_t r = val & mask;
-
- if (r == 0) {
- return 0;
- } else if (r == mask) {
- return 3;
- } else {
- return 1;
- }
-}
-
-static uint32_t cc_calc_tm_64(uint64_t val, uint64_t mask)
-{
- uint64_t r = val & mask;
-
- if (r == 0) {
- return 0;
- } else if (r == mask) {
- return 3;
- } else {
- int top = clz64(mask);
- if ((int64_t)(val << top) < 0) {
- return 2;
- } else {
- return 1;
- }
- }
-}
-
-static uint32_t cc_calc_nz(uint64_t dst)
-{
- return !!dst;
-}
-
-static uint32_t cc_calc_add_64(int64_t a1, int64_t a2, int64_t ar)
-{
- if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
- return 3; /* overflow */
- } else {
- if (ar < 0) {
- return 1;
- } else if (ar > 0) {
- return 2;
- } else {
- return 0;
- }
- }
-}
-
-static uint32_t cc_calc_addu_64(uint64_t a1, uint64_t a2, uint64_t ar)
-{
- return (ar != 0) + 2 * (ar < a1);
-}
-
-static uint32_t cc_calc_addc_64(uint64_t a1, uint64_t a2, uint64_t ar)
-{
- /* Recover a2 + carry_in. */
- uint64_t a2c = ar - a1;
- /* Check for a2+carry_in overflow, then a1+a2c overflow. */
- int carry_out = (a2c < a2) || (ar < a1);
-
- return (ar != 0) + 2 * carry_out;
-}
-
-static uint32_t cc_calc_sub_64(int64_t a1, int64_t a2, int64_t ar)
-{
- if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
- return 3; /* overflow */
- } else {
- if (ar < 0) {
- return 1;
- } else if (ar > 0) {
- return 2;
- } else {
- return 0;
- }
- }
-}
-
-static uint32_t cc_calc_subu_64(uint64_t a1, uint64_t a2, uint64_t ar)
-{
- if (ar == 0) {
- return 2;
- } else {
- if (a2 > a1) {
- return 1;
- } else {
- return 3;
- }
- }
-}
-
-static uint32_t cc_calc_subb_64(uint64_t a1, uint64_t a2, uint64_t ar)
-{
- int borrow_out;
-
- if (ar != a1 - a2) { /* difference means borrow-in */
- borrow_out = (a2 >= a1);
- } else {
- borrow_out = (a2 > a1);
- }
-
- return (ar != 0) + 2 * !borrow_out;
-}
-
-static uint32_t cc_calc_abs_64(int64_t dst)
-{
- if ((uint64_t)dst == 0x8000000000000000ULL) {
- return 3;
- } else if (dst) {
- return 2;
- } else {
- return 0;
- }
-}
-
-static uint32_t cc_calc_nabs_64(int64_t dst)
-{
- return !!dst;
-}
-
-static uint32_t cc_calc_comp_64(int64_t dst)
-{
- if ((uint64_t)dst == 0x8000000000000000ULL) {
- return 3;
- } else if (dst < 0) {
- return 1;
- } else if (dst > 0) {
- return 2;
- } else {
- return 0;
- }
-}
-
-
-static uint32_t cc_calc_add_32(int32_t a1, int32_t a2, int32_t ar)
-{
- if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
- return 3; /* overflow */
- } else {
- if (ar < 0) {
- return 1;
- } else if (ar > 0) {
- return 2;
- } else {
- return 0;
- }
- }
-}
-
-static uint32_t cc_calc_addu_32(uint32_t a1, uint32_t a2, uint32_t ar)
-{
- return (ar != 0) + 2 * (ar < a1);
-}
-
-static uint32_t cc_calc_addc_32(uint32_t a1, uint32_t a2, uint32_t ar)
-{
- /* Recover a2 + carry_in. */
- uint32_t a2c = ar - a1;
- /* Check for a2+carry_in overflow, then a1+a2c overflow. */
- int carry_out = (a2c < a2) || (ar < a1);
-
- return (ar != 0) + 2 * carry_out;
-}
-
-static uint32_t cc_calc_sub_32(int32_t a1, int32_t a2, int32_t ar)
-{
- if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
- return 3; /* overflow */
- } else {
- if (ar < 0) {
- return 1;
- } else if (ar > 0) {
- return 2;
- } else {
- return 0;
- }
- }
-}
-
-static uint32_t cc_calc_subu_32(uint32_t a1, uint32_t a2, uint32_t ar)
-{
- if (ar == 0) {
- return 2;
- } else {
- if (a2 > a1) {
- return 1;
- } else {
- return 3;
- }
- }
-}
-
-static uint32_t cc_calc_subb_32(uint32_t a1, uint32_t a2, uint32_t ar)
-{
- int borrow_out;
-
- if (ar != a1 - a2) { /* difference means borrow-in */
- borrow_out = (a2 >= a1);
- } else {
- borrow_out = (a2 > a1);
- }
-
- return (ar != 0) + 2 * !borrow_out;
-}
-
-static uint32_t cc_calc_abs_32(int32_t dst)
-{
- if ((uint32_t)dst == 0x80000000UL) {
- return 3;
- } else if (dst) {
- return 2;
- } else {
- return 0;
- }
-}
-
-static uint32_t cc_calc_nabs_32(int32_t dst)
-{
- return !!dst;
-}
-
-static uint32_t cc_calc_comp_32(int32_t dst)
-{
- if ((uint32_t)dst == 0x80000000UL) {
- return 3;
- } else if (dst < 0) {
- return 1;
- } else if (dst > 0) {
- return 2;
- } else {
- return 0;
- }
-}
-
-/* calculate condition code for insert character under mask insn */
-static uint32_t cc_calc_icm(uint64_t mask, uint64_t val)
-{
- if ((val & mask) == 0) {
- return 0;
- } else {
- int top = clz64(mask);
- if ((int64_t)(val << top) < 0) {
- return 1;
- } else {
- return 2;
- }
- }
-}
-
-static uint32_t cc_calc_sla_32(uint32_t src, int shift)
-{
- uint32_t mask = ((1U << shift) - 1U) << (32 - shift);
- uint32_t sign = 1U << 31;
- uint32_t match;
- int32_t r;
-
- /* Check if the sign bit stays the same. */
- if (src & sign) {
- match = mask;
- } else {
- match = 0;
- }
- if ((src & mask) != match) {
- /* Overflow. */
- return 3;
- }
-
- r = ((src << shift) & ~sign) | (src & sign);
- if (r == 0) {
- return 0;
- } else if (r < 0) {
- return 1;
- }
- return 2;
-}
-
-static uint32_t cc_calc_sla_64(uint64_t src, int shift)
-{
- uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
- uint64_t sign = 1ULL << 63;
- uint64_t match;
- int64_t r;
-
- /* Check if the sign bit stays the same. */
- if (src & sign) {
- match = mask;
- } else {
- match = 0;
- }
- if ((src & mask) != match) {
- /* Overflow. */
- return 3;
- }
-
- r = ((src << shift) & ~sign) | (src & sign);
- if (r == 0) {
- return 0;
- } else if (r < 0) {
- return 1;
- }
- return 2;
-}
-
-static uint32_t cc_calc_flogr(uint64_t dst)
-{
- return dst ? 2 : 0;
-}
-
-static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
- uint64_t src, uint64_t dst, uint64_t vr)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- uint32_t r = 0;
-
- switch (cc_op) {
- case CC_OP_CONST0:
- case CC_OP_CONST1:
- case CC_OP_CONST2:
- case CC_OP_CONST3:
- /* cc_op value _is_ cc */
- r = cc_op;
- break;
- case CC_OP_LTGT0_32:
- r = cc_calc_ltgt0_32(dst);
- break;
- case CC_OP_LTGT0_64:
- r = cc_calc_ltgt0_64(dst);
- break;
- case CC_OP_LTGT_32:
- r = cc_calc_ltgt_32(src, dst);
- break;
- case CC_OP_LTGT_64:
- r = cc_calc_ltgt_64(src, dst);
- break;
- case CC_OP_LTUGTU_32:
- r = cc_calc_ltugtu_32(src, dst);
- break;
- case CC_OP_LTUGTU_64:
- r = cc_calc_ltugtu_64(src, dst);
- break;
- case CC_OP_TM_32:
- r = cc_calc_tm_32(src, dst);
- break;
- case CC_OP_TM_64:
- r = cc_calc_tm_64(src, dst);
- break;
- case CC_OP_NZ:
- r = cc_calc_nz(dst);
- break;
- case CC_OP_ADD_64:
- r = cc_calc_add_64(src, dst, vr);
- break;
- case CC_OP_ADDU_64:
- r = cc_calc_addu_64(src, dst, vr);
- break;
- case CC_OP_ADDC_64:
- r = cc_calc_addc_64(src, dst, vr);
- break;
- case CC_OP_SUB_64:
- r = cc_calc_sub_64(src, dst, vr);
- break;
- case CC_OP_SUBU_64:
- r = cc_calc_subu_64(src, dst, vr);
- break;
- case CC_OP_SUBB_64:
- r = cc_calc_subb_64(src, dst, vr);
- break;
- case CC_OP_ABS_64:
- r = cc_calc_abs_64(dst);
- break;
- case CC_OP_NABS_64:
- r = cc_calc_nabs_64(dst);
- break;
- case CC_OP_COMP_64:
- r = cc_calc_comp_64(dst);
- break;
-
- case CC_OP_ADD_32:
- r = cc_calc_add_32(src, dst, vr);
- break;
- case CC_OP_ADDU_32:
- r = cc_calc_addu_32(src, dst, vr);
- break;
- case CC_OP_ADDC_32:
- r = cc_calc_addc_32(src, dst, vr);
- break;
- case CC_OP_SUB_32:
- r = cc_calc_sub_32(src, dst, vr);
- break;
- case CC_OP_SUBU_32:
- r = cc_calc_subu_32(src, dst, vr);
- break;
- case CC_OP_SUBB_32:
- r = cc_calc_subb_32(src, dst, vr);
- break;
- case CC_OP_ABS_32:
- r = cc_calc_abs_32(dst);
- break;
- case CC_OP_NABS_32:
- r = cc_calc_nabs_32(dst);
- break;
- case CC_OP_COMP_32:
- r = cc_calc_comp_32(dst);
- break;
-
- case CC_OP_ICM:
- r = cc_calc_icm(src, dst);
- break;
- case CC_OP_SLA_32:
- r = cc_calc_sla_32(src, dst);
- break;
- case CC_OP_SLA_64:
- r = cc_calc_sla_64(src, dst);
- break;
- case CC_OP_FLOGR:
- r = cc_calc_flogr(dst);
- break;
-
- case CC_OP_NZ_F32:
- r = set_cc_nz_f32(dst);
- break;
- case CC_OP_NZ_F64:
- r = set_cc_nz_f64(dst);
- break;
- case CC_OP_NZ_F128:
- r = set_cc_nz_f128(make_float128(src, dst));
- break;
-
- default:
- cpu_abort(CPU(cpu), "Unknown CC operation: %s\n", cc_name(cc_op));
- }
-
- HELPER_LOG("%s: %15s 0x%016lx 0x%016lx 0x%016lx = %d\n", __func__,
- cc_name(cc_op), src, dst, vr, r);
- return r;
-}
-
-uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
- uint64_t vr)
-{
- return do_calc_cc(env, cc_op, src, dst, vr);
-}
-
-uint32_t HELPER(calc_cc)(CPUS390XState *env, uint32_t cc_op, uint64_t src,
- uint64_t dst, uint64_t vr)
-{
- return do_calc_cc(env, cc_op, src, dst, vr);
-}
-
-#ifndef CONFIG_USER_ONLY
-void HELPER(load_psw)(CPUS390XState *env, uint64_t mask, uint64_t addr)
-{
- load_psw(env, mask, addr);
- cpu_loop_exit(CPU(s390_env_get_cpu(env)));
-}
-
-void HELPER(sacf)(CPUS390XState *env, uint64_t a1)
-{
- HELPER_LOG("%s: %16" PRIx64 "\n", __func__, a1);
-
- switch (a1 & 0xf00) {
- case 0x000:
- env->psw.mask &= ~PSW_MASK_ASC;
- env->psw.mask |= PSW_ASC_PRIMARY;
- break;
- case 0x100:
- env->psw.mask &= ~PSW_MASK_ASC;
- env->psw.mask |= PSW_ASC_SECONDARY;
- break;
- case 0x300:
- env->psw.mask &= ~PSW_MASK_ASC;
- env->psw.mask |= PSW_ASC_HOME;
- break;
- default:
- HELPER_LOG("unknown sacf mode: %" PRIx64 "\n", a1);
- program_interrupt(env, PGM_SPECIFICATION, 2);
- break;
- }
-}
-#endif
diff --git a/qemu/target-s390x/cpu-qom.h b/qemu/target-s390x/cpu-qom.h
deleted file mode 100644
index 1c9093396..000000000
--- a/qemu/target-s390x/cpu-qom.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * QEMU S/390 CPU
- *
- * Copyright (c) 2012 SUSE LINUX Products GmbH
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/lgpl-2.1.html>
- */
-#ifndef QEMU_S390_CPU_QOM_H
-#define QEMU_S390_CPU_QOM_H
-
-#include "qom/cpu.h"
-#include "cpu.h"
-
-#define TYPE_S390_CPU "s390-cpu"
-
-#define S390_CPU_CLASS(klass) \
- OBJECT_CLASS_CHECK(S390CPUClass, (klass), TYPE_S390_CPU)
-#define S390_CPU(obj) \
- OBJECT_CHECK(S390CPU, (obj), TYPE_S390_CPU)
-#define S390_CPU_GET_CLASS(obj) \
- OBJECT_GET_CLASS(S390CPUClass, (obj), TYPE_S390_CPU)
-
-/**
- * S390CPUClass:
- * @parent_realize: The parent class' realize handler.
- * @parent_reset: The parent class' reset handler.
- * @load_normal: Performs a load normal.
- * @cpu_reset: Performs a CPU reset.
- * @initial_cpu_reset: Performs an initial CPU reset.
- *
- * An S/390 CPU model.
- */
-typedef struct S390CPUClass {
- /*< private >*/
- CPUClass parent_class;
- /*< public >*/
-
- int64_t next_cpu_id;
-
- DeviceRealize parent_realize;
- void (*parent_reset)(CPUState *cpu);
- void (*load_normal)(CPUState *cpu);
- void (*cpu_reset)(CPUState *cpu);
- void (*initial_cpu_reset)(CPUState *cpu);
-} S390CPUClass;
-
-/**
- * S390CPU:
- * @env: #CPUS390XState.
- *
- * An S/390 CPU.
- */
-typedef struct S390CPU {
- /*< private >*/
- CPUState parent_obj;
- /*< public >*/
-
- CPUS390XState env;
- int64_t id;
- /* needed for live migration */
- void *irqstate;
- uint32_t irqstate_saved_size;
-} S390CPU;
-
-static inline S390CPU *s390_env_get_cpu(CPUS390XState *env)
-{
- return container_of(env, S390CPU, env);
-}
-
-#define ENV_GET_CPU(e) CPU(s390_env_get_cpu(e))
-
-#define ENV_OFFSET offsetof(S390CPU, env)
-
-#ifndef CONFIG_USER_ONLY
-extern const struct VMStateDescription vmstate_s390_cpu;
-#endif
-
-void s390_cpu_do_interrupt(CPUState *cpu);
-bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req);
-void s390_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
- int flags);
-int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
- int cpuid, void *opaque);
-
-hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-hwaddr s390_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr);
-int s390_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
-int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
-void s390_cpu_gdb_init(CPUState *cs);
-void s390x_cpu_debug_excp_handler(CPUState *cs);
-
-#endif
diff --git a/qemu/target-s390x/cpu.c b/qemu/target-s390x/cpu.c
deleted file mode 100644
index 4bfff341d..000000000
--- a/qemu/target-s390x/cpu.c
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
- * QEMU S/390 CPU
- *
- * Copyright (c) 2009 Ulrich Hecht
- * Copyright (c) 2011 Alexander Graf
- * Copyright (c) 2012 SUSE LINUX Products GmbH
- * Copyright (c) 2012 IBM Corp.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see
- * <http://www.gnu.org/licenses/lgpl-2.1.html>
- * Contributions after 2012-12-11 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "cpu.h"
-#include "qemu-common.h"
-#include "qemu/cutils.h"
-#include "qemu/timer.h"
-#include "qemu/error-report.h"
-#include "hw/hw.h"
-#include "trace.h"
-#include "qapi/visitor.h"
-#ifndef CONFIG_USER_ONLY
-#include "sysemu/arch_init.h"
-#include "sysemu/sysemu.h"
-#include "hw/s390x/sclp.h"
-#endif
-
-#define CR0_RESET 0xE0UL
-#define CR14_RESET 0xC2000000UL;
-
-/* generate CPU information for cpu -? */
-void s390_cpu_list(FILE *f, fprintf_function cpu_fprintf)
-{
-#ifdef CONFIG_KVM
- (*cpu_fprintf)(f, "s390 %16s\n", "host");
-#endif
-}
-
-#ifndef CONFIG_USER_ONLY
-CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
-{
- CpuDefinitionInfoList *entry;
- CpuDefinitionInfo *info;
-
- info = g_malloc0(sizeof(*info));
- info->name = g_strdup("host");
-
- entry = g_malloc0(sizeof(*entry));
- entry->value = info;
-
- return entry;
-}
-#endif
-
-static void s390_cpu_set_pc(CPUState *cs, vaddr value)
-{
- S390CPU *cpu = S390_CPU(cs);
-
- cpu->env.psw.addr = value;
-}
-
-static bool s390_cpu_has_work(CPUState *cs)
-{
- S390CPU *cpu = S390_CPU(cs);
- CPUS390XState *env = &cpu->env;
-
- return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
- (env->psw.mask & PSW_MASK_EXT);
-}
-
-#if !defined(CONFIG_USER_ONLY)
-/* S390CPUClass::load_normal() */
-static void s390_cpu_load_normal(CPUState *s)
-{
- S390CPU *cpu = S390_CPU(s);
- cpu->env.psw.addr = ldl_phys(s->as, 4) & PSW_MASK_ESA_ADDR;
- cpu->env.psw.mask = PSW_MASK_32 | PSW_MASK_64;
- s390_cpu_set_state(CPU_STATE_OPERATING, cpu);
-}
-#endif
-
-/* S390CPUClass::cpu_reset() */
-static void s390_cpu_reset(CPUState *s)
-{
- S390CPU *cpu = S390_CPU(s);
- S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
- CPUS390XState *env = &cpu->env;
-
- env->pfault_token = -1UL;
- scc->parent_reset(s);
- cpu->env.sigp_order = 0;
- s390_cpu_set_state(CPU_STATE_STOPPED, cpu);
- tlb_flush(s, 1);
-}
-
-/* S390CPUClass::initial_reset() */
-static void s390_cpu_initial_reset(CPUState *s)
-{
- S390CPU *cpu = S390_CPU(s);
- CPUS390XState *env = &cpu->env;
- int i;
-
- s390_cpu_reset(s);
- /* initial reset does not touch regs,fregs and aregs */
- memset(&env->fpc, 0, offsetof(CPUS390XState, cpu_num) -
- offsetof(CPUS390XState, fpc));
-
- /* architectured initial values for CR 0 and 14 */
- env->cregs[0] = CR0_RESET;
- env->cregs[14] = CR14_RESET;
-
- /* architectured initial value for Breaking-Event-Address register */
- env->gbea = 1;
-
- env->pfault_token = -1UL;
- env->ext_index = -1;
- for (i = 0; i < ARRAY_SIZE(env->io_index); i++) {
- env->io_index[i] = -1;
- }
-
- /* tininess for underflow is detected before rounding */
- set_float_detect_tininess(float_tininess_before_rounding,
- &env->fpu_status);
-
- /* Reset state inside the kernel that we cannot access yet from QEMU. */
- if (kvm_enabled()) {
- kvm_s390_reset_vcpu(cpu);
- }
- tlb_flush(s, 1);
-}
-
-/* CPUClass:reset() */
-static void s390_cpu_full_reset(CPUState *s)
-{
- S390CPU *cpu = S390_CPU(s);
- S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
- CPUS390XState *env = &cpu->env;
- int i;
-
- scc->parent_reset(s);
- cpu->env.sigp_order = 0;
- s390_cpu_set_state(CPU_STATE_STOPPED, cpu);
-
- memset(env, 0, offsetof(CPUS390XState, cpu_num));
-
- /* architectured initial values for CR 0 and 14 */
- env->cregs[0] = CR0_RESET;
- env->cregs[14] = CR14_RESET;
-
- /* architectured initial value for Breaking-Event-Address register */
- env->gbea = 1;
-
- env->pfault_token = -1UL;
- env->ext_index = -1;
- for (i = 0; i < ARRAY_SIZE(env->io_index); i++) {
- env->io_index[i] = -1;
- }
-
- /* tininess for underflow is detected before rounding */
- set_float_detect_tininess(float_tininess_before_rounding,
- &env->fpu_status);
-
- /* Reset state inside the kernel that we cannot access yet from QEMU. */
- if (kvm_enabled()) {
- kvm_s390_reset_vcpu(cpu);
- }
- tlb_flush(s, 1);
-}
-
-#if !defined(CONFIG_USER_ONLY)
-static void s390_cpu_machine_reset_cb(void *opaque)
-{
- S390CPU *cpu = opaque;
-
- run_on_cpu(CPU(cpu), s390_do_cpu_full_reset, CPU(cpu));
-}
-#endif
-
-static void s390_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
-{
- info->mach = bfd_mach_s390_64;
- info->print_insn = print_insn_s390;
-}
-
-static void s390_cpu_realizefn(DeviceState *dev, Error **errp)
-{
- CPUState *cs = CPU(dev);
- S390CPUClass *scc = S390_CPU_GET_CLASS(dev);
- S390CPU *cpu = S390_CPU(dev);
- CPUS390XState *env = &cpu->env;
- Error *err = NULL;
-
-#if !defined(CONFIG_USER_ONLY)
- if (cpu->id >= max_cpus) {
- error_setg(&err, "Unable to add CPU: %" PRIi64
- ", max allowed: %d", cpu->id, max_cpus - 1);
- goto out;
- }
-#endif
- if (cpu_exists(cpu->id)) {
- error_setg(&err, "Unable to add CPU: %" PRIi64
- ", it already exists", cpu->id);
- goto out;
- }
- if (cpu->id != scc->next_cpu_id) {
- error_setg(&err, "Unable to add CPU: %" PRIi64
- ", The next available id is %" PRIi64, cpu->id,
- scc->next_cpu_id);
- goto out;
- }
-
- cpu_exec_init(cs, &err);
- if (err != NULL) {
- goto out;
- }
- scc->next_cpu_id++;
-
-#if !defined(CONFIG_USER_ONLY)
- qemu_register_reset(s390_cpu_machine_reset_cb, cpu);
-#endif
- env->cpu_num = cpu->id;
- s390_cpu_gdb_init(cs);
- qemu_init_vcpu(cs);
-#if !defined(CONFIG_USER_ONLY)
- run_on_cpu(cs, s390_do_cpu_full_reset, cs);
-#else
- cpu_reset(cs);
-#endif
-
- scc->parent_realize(dev, &err);
-
-#if !defined(CONFIG_USER_ONLY)
- if (dev->hotplugged) {
- raise_irq_cpu_hotplug();
- }
-#endif
-
-out:
- error_propagate(errp, err);
-}
-
-static void s390x_cpu_get_id(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- S390CPU *cpu = S390_CPU(obj);
- int64_t value = cpu->id;
-
- visit_type_int(v, name, &value, errp);
-}
-
-static void s390x_cpu_set_id(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- S390CPU *cpu = S390_CPU(obj);
- DeviceState *dev = DEVICE(obj);
- const int64_t min = 0;
- const int64_t max = UINT32_MAX;
- Error *err = NULL;
- int64_t value;
-
- if (dev->realized) {
- error_setg(errp, "Attempt to set property '%s' on '%s' after "
- "it was realized", name, object_get_typename(obj));
- return;
- }
-
- visit_type_int(v, name, &value, &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
- if (value < min || value > max) {
- error_setg(errp, "Property %s.%s doesn't take value %" PRId64
- " (minimum: %" PRId64 ", maximum: %" PRId64 ")" ,
- object_get_typename(obj), name, value, min, max);
- return;
- }
- cpu->id = value;
-}
-
-static void s390_cpu_initfn(Object *obj)
-{
- CPUState *cs = CPU(obj);
- S390CPU *cpu = S390_CPU(obj);
- CPUS390XState *env = &cpu->env;
- static bool inited;
-#if !defined(CONFIG_USER_ONLY)
- struct tm tm;
-#endif
-
- cs->env_ptr = env;
- cs->halted = 1;
- cs->exception_index = EXCP_HLT;
- object_property_add(OBJECT(cpu), "id", "int64_t", s390x_cpu_get_id,
- s390x_cpu_set_id, NULL, NULL, NULL);
-#if !defined(CONFIG_USER_ONLY)
- qemu_get_timedate(&tm, 0);
- env->tod_offset = TOD_UNIX_EPOCH +
- (time2tod(mktimegm(&tm)) * 1000000000ULL);
- env->tod_basetime = 0;
- env->tod_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_tod_timer, cpu);
- env->cpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_cpu_timer, cpu);
- s390_cpu_set_state(CPU_STATE_STOPPED, cpu);
-#endif
-
- if (tcg_enabled() && !inited) {
- inited = true;
- s390x_translate_init();
- }
-}
-
-static void s390_cpu_finalize(Object *obj)
-{
-#if !defined(CONFIG_USER_ONLY)
- S390CPU *cpu = S390_CPU(obj);
-
- qemu_unregister_reset(s390_cpu_machine_reset_cb, cpu);
- g_free(cpu->irqstate);
-#endif
-}
-
-#if !defined(CONFIG_USER_ONLY)
-static bool disabled_wait(CPUState *cpu)
-{
- return cpu->halted && !(S390_CPU(cpu)->env.psw.mask &
- (PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK));
-}
-
-static unsigned s390_count_running_cpus(void)
-{
- CPUState *cpu;
- int nr_running = 0;
-
- CPU_FOREACH(cpu) {
- uint8_t state = S390_CPU(cpu)->env.cpu_state;
- if (state == CPU_STATE_OPERATING ||
- state == CPU_STATE_LOAD) {
- if (!disabled_wait(cpu)) {
- nr_running++;
- }
- }
- }
-
- return nr_running;
-}
-
-unsigned int s390_cpu_halt(S390CPU *cpu)
-{
- CPUState *cs = CPU(cpu);
- trace_cpu_halt(cs->cpu_index);
-
- if (!cs->halted) {
- cs->halted = 1;
- cs->exception_index = EXCP_HLT;
- }
-
- return s390_count_running_cpus();
-}
-
-void s390_cpu_unhalt(S390CPU *cpu)
-{
- CPUState *cs = CPU(cpu);
- trace_cpu_unhalt(cs->cpu_index);
-
- if (cs->halted) {
- cs->halted = 0;
- cs->exception_index = -1;
- }
-}
-
-unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
- {
- trace_cpu_set_state(CPU(cpu)->cpu_index, cpu_state);
-
- switch (cpu_state) {
- case CPU_STATE_STOPPED:
- case CPU_STATE_CHECK_STOP:
- /* halt the cpu for common infrastructure */
- s390_cpu_halt(cpu);
- break;
- case CPU_STATE_OPERATING:
- case CPU_STATE_LOAD:
- /* unhalt the cpu for common infrastructure */
- s390_cpu_unhalt(cpu);
- break;
- default:
- error_report("Requested CPU state is not a valid S390 CPU state: %u",
- cpu_state);
- exit(1);
- }
- if (kvm_enabled() && cpu->env.cpu_state != cpu_state) {
- kvm_s390_set_cpu_state(cpu, cpu_state);
- }
- cpu->env.cpu_state = cpu_state;
-
- return s390_count_running_cpus();
-}
-#endif
-
-static gchar *s390_gdb_arch_name(CPUState *cs)
-{
- return g_strdup("s390:64-bit");
-}
-
-static void s390_cpu_class_init(ObjectClass *oc, void *data)
-{
- S390CPUClass *scc = S390_CPU_CLASS(oc);
- CPUClass *cc = CPU_CLASS(scc);
- DeviceClass *dc = DEVICE_CLASS(oc);
-
- scc->next_cpu_id = 0;
- scc->parent_realize = dc->realize;
- dc->realize = s390_cpu_realizefn;
-
- scc->parent_reset = cc->reset;
-#if !defined(CONFIG_USER_ONLY)
- scc->load_normal = s390_cpu_load_normal;
-#endif
- scc->cpu_reset = s390_cpu_reset;
- scc->initial_cpu_reset = s390_cpu_initial_reset;
- cc->reset = s390_cpu_full_reset;
- cc->has_work = s390_cpu_has_work;
- cc->do_interrupt = s390_cpu_do_interrupt;
- cc->dump_state = s390_cpu_dump_state;
- cc->set_pc = s390_cpu_set_pc;
- cc->gdb_read_register = s390_cpu_gdb_read_register;
- cc->gdb_write_register = s390_cpu_gdb_write_register;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = s390_cpu_handle_mmu_fault;
-#else
- cc->get_phys_page_debug = s390_cpu_get_phys_page_debug;
- cc->vmsd = &vmstate_s390_cpu;
- cc->write_elf64_note = s390_cpu_write_elf64_note;
- cc->cpu_exec_interrupt = s390_cpu_exec_interrupt;
- cc->debug_excp_handler = s390x_cpu_debug_excp_handler;
-#endif
- cc->disas_set_info = s390_cpu_disas_set_info;
-
- cc->gdb_num_core_regs = S390_NUM_CORE_REGS;
- cc->gdb_core_xml_file = "s390x-core64.xml";
- cc->gdb_arch_name = s390_gdb_arch_name;
-
- /*
- * Reason: s390_cpu_realizefn() calls cpu_exec_init(), which saves
- * the object in cpus -> dangling pointer after final
- * object_unref().
- */
- dc->cannot_destroy_with_object_finalize_yet = true;
-}
-
-static const TypeInfo s390_cpu_type_info = {
- .name = TYPE_S390_CPU,
- .parent = TYPE_CPU,
- .instance_size = sizeof(S390CPU),
- .instance_init = s390_cpu_initfn,
- .instance_finalize = s390_cpu_finalize,
- .abstract = false,
- .class_size = sizeof(S390CPUClass),
- .class_init = s390_cpu_class_init,
-};
-
-static void s390_cpu_register_types(void)
-{
- type_register_static(&s390_cpu_type_info);
-}
-
-type_init(s390_cpu_register_types)
diff --git a/qemu/target-s390x/cpu.h b/qemu/target-s390x/cpu.h
deleted file mode 100644
index 6d97c089a..000000000
--- a/qemu/target-s390x/cpu.h
+++ /dev/null
@@ -1,1326 +0,0 @@
-/*
- * S/390 virtual CPU header
- *
- * Copyright (c) 2009 Ulrich Hecht
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * Contributions after 2012-10-29 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- *
- * You should have received a copy of the GNU (Lesser) General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef CPU_S390X_H
-#define CPU_S390X_H
-
-#include "qemu-common.h"
-
-#define TARGET_LONG_BITS 64
-
-#define ELF_MACHINE_UNAME "S390X"
-
-#define CPUArchState struct CPUS390XState
-
-#include "exec/cpu-defs.h"
-#define TARGET_PAGE_BITS 12
-
-#define TARGET_PHYS_ADDR_SPACE_BITS 64
-#define TARGET_VIRT_ADDR_SPACE_BITS 64
-
-#include "exec/cpu-all.h"
-
-#include "fpu/softfloat.h"
-
-#define NB_MMU_MODES 3
-#define TARGET_INSN_START_EXTRA_WORDS 1
-
-#define MMU_MODE0_SUFFIX _primary
-#define MMU_MODE1_SUFFIX _secondary
-#define MMU_MODE2_SUFFIX _home
-
-#define MMU_USER_IDX 0
-
-#define MAX_EXT_QUEUE 16
-#define MAX_IO_QUEUE 16
-#define MAX_MCHK_QUEUE 16
-
-#define PSW_MCHK_MASK 0x0004000000000000
-#define PSW_IO_MASK 0x0200000000000000
-
-typedef struct PSW {
- uint64_t mask;
- uint64_t addr;
-} PSW;
-
-typedef struct ExtQueue {
- uint32_t code;
- uint32_t param;
- uint32_t param64;
-} ExtQueue;
-
-typedef struct IOIntQueue {
- uint16_t id;
- uint16_t nr;
- uint32_t parm;
- uint32_t word;
-} IOIntQueue;
-
-typedef struct MchkQueue {
- uint16_t type;
-} MchkQueue;
-
-typedef struct CPUS390XState {
- uint64_t regs[16]; /* GP registers */
- /*
- * The floating point registers are part of the vector registers.
- * vregs[0][0] -> vregs[15][0] are 16 floating point registers
- */
- CPU_DoubleU vregs[32][2]; /* vector registers */
- uint32_t aregs[16]; /* access registers */
-
- uint32_t fpc; /* floating-point control register */
- uint32_t cc_op;
-
- float_status fpu_status; /* passed to softfloat lib */
-
- /* The low part of a 128-bit return, or remainder of a divide. */
- uint64_t retxl;
-
- PSW psw;
-
- uint64_t cc_src;
- uint64_t cc_dst;
- uint64_t cc_vr;
-
- uint64_t __excp_addr;
- uint64_t psa;
-
- uint32_t int_pgm_code;
- uint32_t int_pgm_ilen;
-
- uint32_t int_svc_code;
- uint32_t int_svc_ilen;
-
- uint64_t per_address;
- uint16_t per_perc_atmid;
-
- uint64_t cregs[16]; /* control registers */
-
- ExtQueue ext_queue[MAX_EXT_QUEUE];
- IOIntQueue io_queue[MAX_IO_QUEUE][8];
- MchkQueue mchk_queue[MAX_MCHK_QUEUE];
-
- int pending_int;
- int ext_index;
- int io_index[8];
- int mchk_index;
-
- uint64_t ckc;
- uint64_t cputm;
- uint32_t todpr;
-
- uint64_t pfault_token;
- uint64_t pfault_compare;
- uint64_t pfault_select;
-
- uint64_t gbea;
- uint64_t pp;
-
- CPU_COMMON
-
- /* reset does memset(0) up to here */
-
- uint32_t cpu_num;
- uint32_t machine_type;
-
- uint64_t tod_offset;
- uint64_t tod_basetime;
- QEMUTimer *tod_timer;
-
- QEMUTimer *cpu_timer;
-
- /*
- * The cpu state represents the logical state of a cpu. In contrast to other
- * architectures, there is a difference between a halt and a stop on s390.
- * If all cpus are either stopped (including check stop) or in the disabled
- * wait state, the vm can be shut down.
- */
-#define CPU_STATE_UNINITIALIZED 0x00
-#define CPU_STATE_STOPPED 0x01
-#define CPU_STATE_CHECK_STOP 0x02
-#define CPU_STATE_OPERATING 0x03
-#define CPU_STATE_LOAD 0x04
- uint8_t cpu_state;
-
- /* currently processed sigp order */
- uint8_t sigp_order;
-
-} CPUS390XState;
-
-static inline CPU_DoubleU *get_freg(CPUS390XState *cs, int nr)
-{
- return &cs->vregs[nr][0];
-}
-
-#include "cpu-qom.h"
-#include <sysemu/kvm.h>
-
-/* distinguish between 24 bit and 31 bit addressing */
-#define HIGH_ORDER_BIT 0x80000000
-
-/* Interrupt Codes */
-/* Program Interrupts */
-#define PGM_OPERATION 0x0001
-#define PGM_PRIVILEGED 0x0002
-#define PGM_EXECUTE 0x0003
-#define PGM_PROTECTION 0x0004
-#define PGM_ADDRESSING 0x0005
-#define PGM_SPECIFICATION 0x0006
-#define PGM_DATA 0x0007
-#define PGM_FIXPT_OVERFLOW 0x0008
-#define PGM_FIXPT_DIVIDE 0x0009
-#define PGM_DEC_OVERFLOW 0x000a
-#define PGM_DEC_DIVIDE 0x000b
-#define PGM_HFP_EXP_OVERFLOW 0x000c
-#define PGM_HFP_EXP_UNDERFLOW 0x000d
-#define PGM_HFP_SIGNIFICANCE 0x000e
-#define PGM_HFP_DIVIDE 0x000f
-#define PGM_SEGMENT_TRANS 0x0010
-#define PGM_PAGE_TRANS 0x0011
-#define PGM_TRANS_SPEC 0x0012
-#define PGM_SPECIAL_OP 0x0013
-#define PGM_OPERAND 0x0015
-#define PGM_TRACE_TABLE 0x0016
-#define PGM_SPACE_SWITCH 0x001c
-#define PGM_HFP_SQRT 0x001d
-#define PGM_PC_TRANS_SPEC 0x001f
-#define PGM_AFX_TRANS 0x0020
-#define PGM_ASX_TRANS 0x0021
-#define PGM_LX_TRANS 0x0022
-#define PGM_EX_TRANS 0x0023
-#define PGM_PRIM_AUTH 0x0024
-#define PGM_SEC_AUTH 0x0025
-#define PGM_ALET_SPEC 0x0028
-#define PGM_ALEN_SPEC 0x0029
-#define PGM_ALE_SEQ 0x002a
-#define PGM_ASTE_VALID 0x002b
-#define PGM_ASTE_SEQ 0x002c
-#define PGM_EXT_AUTH 0x002d
-#define PGM_STACK_FULL 0x0030
-#define PGM_STACK_EMPTY 0x0031
-#define PGM_STACK_SPEC 0x0032
-#define PGM_STACK_TYPE 0x0033
-#define PGM_STACK_OP 0x0034
-#define PGM_ASCE_TYPE 0x0038
-#define PGM_REG_FIRST_TRANS 0x0039
-#define PGM_REG_SEC_TRANS 0x003a
-#define PGM_REG_THIRD_TRANS 0x003b
-#define PGM_MONITOR 0x0040
-#define PGM_PER 0x0080
-#define PGM_CRYPTO 0x0119
-
-/* External Interrupts */
-#define EXT_INTERRUPT_KEY 0x0040
-#define EXT_CLOCK_COMP 0x1004
-#define EXT_CPU_TIMER 0x1005
-#define EXT_MALFUNCTION 0x1200
-#define EXT_EMERGENCY 0x1201
-#define EXT_EXTERNAL_CALL 0x1202
-#define EXT_ETR 0x1406
-#define EXT_SERVICE 0x2401
-#define EXT_VIRTIO 0x2603
-
-/* PSW defines */
-#undef PSW_MASK_PER
-#undef PSW_MASK_DAT
-#undef PSW_MASK_IO
-#undef PSW_MASK_EXT
-#undef PSW_MASK_KEY
-#undef PSW_SHIFT_KEY
-#undef PSW_MASK_MCHECK
-#undef PSW_MASK_WAIT
-#undef PSW_MASK_PSTATE
-#undef PSW_MASK_ASC
-#undef PSW_MASK_CC
-#undef PSW_MASK_PM
-#undef PSW_MASK_64
-#undef PSW_MASK_32
-#undef PSW_MASK_ESA_ADDR
-
-#define PSW_MASK_PER 0x4000000000000000ULL
-#define PSW_MASK_DAT 0x0400000000000000ULL
-#define PSW_MASK_IO 0x0200000000000000ULL
-#define PSW_MASK_EXT 0x0100000000000000ULL
-#define PSW_MASK_KEY 0x00F0000000000000ULL
-#define PSW_SHIFT_KEY 56
-#define PSW_MASK_MCHECK 0x0004000000000000ULL
-#define PSW_MASK_WAIT 0x0002000000000000ULL
-#define PSW_MASK_PSTATE 0x0001000000000000ULL
-#define PSW_MASK_ASC 0x0000C00000000000ULL
-#define PSW_MASK_CC 0x0000300000000000ULL
-#define PSW_MASK_PM 0x00000F0000000000ULL
-#define PSW_MASK_64 0x0000000100000000ULL
-#define PSW_MASK_32 0x0000000080000000ULL
-#define PSW_MASK_ESA_ADDR 0x000000007fffffffULL
-
-#undef PSW_ASC_PRIMARY
-#undef PSW_ASC_ACCREG
-#undef PSW_ASC_SECONDARY
-#undef PSW_ASC_HOME
-
-#define PSW_ASC_PRIMARY 0x0000000000000000ULL
-#define PSW_ASC_ACCREG 0x0000400000000000ULL
-#define PSW_ASC_SECONDARY 0x0000800000000000ULL
-#define PSW_ASC_HOME 0x0000C00000000000ULL
-
-/* tb flags */
-
-#define FLAG_MASK_PER (PSW_MASK_PER >> 32)
-#define FLAG_MASK_DAT (PSW_MASK_DAT >> 32)
-#define FLAG_MASK_IO (PSW_MASK_IO >> 32)
-#define FLAG_MASK_EXT (PSW_MASK_EXT >> 32)
-#define FLAG_MASK_KEY (PSW_MASK_KEY >> 32)
-#define FLAG_MASK_MCHECK (PSW_MASK_MCHECK >> 32)
-#define FLAG_MASK_WAIT (PSW_MASK_WAIT >> 32)
-#define FLAG_MASK_PSTATE (PSW_MASK_PSTATE >> 32)
-#define FLAG_MASK_ASC (PSW_MASK_ASC >> 32)
-#define FLAG_MASK_CC (PSW_MASK_CC >> 32)
-#define FLAG_MASK_PM (PSW_MASK_PM >> 32)
-#define FLAG_MASK_64 (PSW_MASK_64 >> 32)
-#define FLAG_MASK_32 0x00001000
-
-/* Control register 0 bits */
-#define CR0_LOWPROT 0x0000000010000000ULL
-#define CR0_EDAT 0x0000000000800000ULL
-
-/* MMU */
-#define MMU_PRIMARY_IDX 0
-#define MMU_SECONDARY_IDX 1
-#define MMU_HOME_IDX 2
-
-static inline int cpu_mmu_index (CPUS390XState *env, bool ifetch)
-{
- switch (env->psw.mask & PSW_MASK_ASC) {
- case PSW_ASC_PRIMARY:
- return MMU_PRIMARY_IDX;
- case PSW_ASC_SECONDARY:
- return MMU_SECONDARY_IDX;
- case PSW_ASC_HOME:
- return MMU_HOME_IDX;
- case PSW_ASC_ACCREG:
- /* Fallthrough: access register mode is not yet supported */
- default:
- abort();
- }
-}
-
-static inline uint64_t cpu_mmu_idx_to_asc(int mmu_idx)
-{
- switch (mmu_idx) {
- case MMU_PRIMARY_IDX:
- return PSW_ASC_PRIMARY;
- case MMU_SECONDARY_IDX:
- return PSW_ASC_SECONDARY;
- case MMU_HOME_IDX:
- return PSW_ASC_HOME;
- default:
- abort();
- }
-}
-
-static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc,
- target_ulong *cs_base, int *flags)
-{
- *pc = env->psw.addr;
- *cs_base = 0;
- *flags = ((env->psw.mask >> 32) & ~FLAG_MASK_CC) |
- ((env->psw.mask & PSW_MASK_32) ? FLAG_MASK_32 : 0);
-}
-
-/* While the PoO talks about ILC (a number between 1-3) what is actually
- stored in LowCore is shifted left one bit (an even between 2-6). As
- this is the actual length of the insn and therefore more useful, that
- is what we want to pass around and manipulate. To make sure that we
- have applied this distinction universally, rename the "ILC" to "ILEN". */
-static inline int get_ilen(uint8_t opc)
-{
- switch (opc >> 6) {
- case 0:
- return 2;
- case 1:
- case 2:
- return 4;
- default:
- return 6;
- }
-}
-
-/* PER bits from control register 9 */
-#define PER_CR9_EVENT_BRANCH 0x80000000
-#define PER_CR9_EVENT_IFETCH 0x40000000
-#define PER_CR9_EVENT_STORE 0x20000000
-#define PER_CR9_EVENT_STORE_REAL 0x08000000
-#define PER_CR9_EVENT_NULLIFICATION 0x01000000
-#define PER_CR9_CONTROL_BRANCH_ADDRESS 0x00800000
-#define PER_CR9_CONTROL_ALTERATION 0x00200000
-
-/* PER bits from the PER CODE/ATMID/AI in lowcore */
-#define PER_CODE_EVENT_BRANCH 0x8000
-#define PER_CODE_EVENT_IFETCH 0x4000
-#define PER_CODE_EVENT_STORE 0x2000
-#define PER_CODE_EVENT_STORE_REAL 0x0800
-#define PER_CODE_EVENT_NULLIFICATION 0x0100
-
-/* Compute the ATMID field that is stored in the per_perc_atmid lowcore
- entry when a PER exception is triggered. */
-static inline uint8_t get_per_atmid(CPUS390XState *env)
-{
- return ((env->psw.mask & PSW_MASK_64) ? (1 << 7) : 0) |
- ( (1 << 6) ) |
- ((env->psw.mask & PSW_MASK_32) ? (1 << 5) : 0) |
- ((env->psw.mask & PSW_MASK_DAT)? (1 << 4) : 0) |
- ((env->psw.mask & PSW_ASC_SECONDARY)? (1 << 3) : 0) |
- ((env->psw.mask & PSW_ASC_ACCREG)? (1 << 2) : 0);
-}
-
-/* Check if an address is within the PER starting address and the PER
- ending address. The address range might loop. */
-static inline bool get_per_in_range(CPUS390XState *env, uint64_t addr)
-{
- if (env->cregs[10] <= env->cregs[11]) {
- return env->cregs[10] <= addr && addr <= env->cregs[11];
- } else {
- return env->cregs[10] <= addr || addr <= env->cregs[11];
- }
-}
-
-#ifndef CONFIG_USER_ONLY
-/* In several cases of runtime exceptions, we havn't recorded the true
- instruction length. Use these codes when raising exceptions in order
- to re-compute the length by examining the insn in memory. */
-#define ILEN_LATER 0x20
-#define ILEN_LATER_INC 0x21
-void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen);
-#endif
-
-S390CPU *cpu_s390x_init(const char *cpu_model);
-S390CPU *s390x_new_cpu(const char *cpu_model, int64_t id, Error **errp);
-S390CPU *cpu_s390x_create(const char *cpu_model, Error **errp);
-void s390x_translate_init(void);
-int cpu_s390x_exec(CPUState *cpu);
-
-/* you can call this signal handler from your SIGBUS and SIGSEGV
- signal handlers to inform the virtual CPU of exceptions. non zero
- is returned if the signal was handled by the virtual CPU. */
-int cpu_s390x_signal_handler(int host_signum, void *pinfo,
- void *puc);
-int s390_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
- int mmu_idx);
-
-#include "ioinst.h"
-
-
-#ifndef CONFIG_USER_ONLY
-void do_restart_interrupt(CPUS390XState *env);
-
-static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb,
- uint8_t *ar)
-{
- hwaddr addr = 0;
- uint8_t reg;
-
- reg = ipb >> 28;
- if (reg > 0) {
- addr = env->regs[reg];
- }
- addr += (ipb >> 16) & 0xfff;
- if (ar) {
- *ar = reg;
- }
-
- return addr;
-}
-
-/* Base/displacement are at the same locations. */
-#define decode_basedisp_rs decode_basedisp_s
-
-/* helper functions for run_on_cpu() */
-static inline void s390_do_cpu_reset(void *arg)
-{
- CPUState *cs = arg;
- S390CPUClass *scc = S390_CPU_GET_CLASS(cs);
-
- scc->cpu_reset(cs);
-}
-static inline void s390_do_cpu_full_reset(void *arg)
-{
- CPUState *cs = arg;
-
- cpu_reset(cs);
-}
-
-void s390x_tod_timer(void *opaque);
-void s390x_cpu_timer(void *opaque);
-
-int s390_virtio_hypercall(CPUS390XState *env);
-
-#ifdef CONFIG_KVM
-void kvm_s390_service_interrupt(uint32_t parm);
-void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq);
-void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq);
-int kvm_s390_inject_flic(struct kvm_s390_irq *irq);
-void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code);
-int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf,
- int len, bool is_write);
-int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock);
-int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_clock);
-#else
-static inline void kvm_s390_service_interrupt(uint32_t parm)
-{
-}
-static inline int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_low)
-{
- return -ENOSYS;
-}
-static inline int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
-{
- return -ENOSYS;
-}
-static inline int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar,
- void *hostbuf, int len, bool is_write)
-{
- return -ENOSYS;
-}
-static inline void kvm_s390_access_exception(S390CPU *cpu, uint16_t code,
- uint64_t te_code)
-{
-}
-#endif
-
-static inline int s390_get_clock(uint8_t *tod_high, uint64_t *tod_low)
-{
- if (kvm_enabled()) {
- return kvm_s390_get_clock(tod_high, tod_low);
- }
- /* Fixme TCG */
- *tod_high = 0;
- *tod_low = 0;
- return 0;
-}
-
-static inline int s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
-{
- if (kvm_enabled()) {
- return kvm_s390_set_clock(tod_high, tod_low);
- }
- /* Fixme TCG */
- return 0;
-}
-
-S390CPU *s390_cpu_addr2state(uint16_t cpu_addr);
-unsigned int s390_cpu_halt(S390CPU *cpu);
-void s390_cpu_unhalt(S390CPU *cpu);
-unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu);
-static inline uint8_t s390_cpu_get_state(S390CPU *cpu)
-{
- return cpu->env.cpu_state;
-}
-
-void gtod_save(QEMUFile *f, void *opaque);
-int gtod_load(QEMUFile *f, void *opaque, int version_id);
-
-/* service interrupts are floating therefore we must not pass an cpustate */
-void s390_sclp_extint(uint32_t parm);
-
-#else
-static inline unsigned int s390_cpu_halt(S390CPU *cpu)
-{
- return 0;
-}
-
-static inline void s390_cpu_unhalt(S390CPU *cpu)
-{
-}
-
-static inline unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
-{
- return 0;
-}
-#endif
-void cpu_lock(void);
-void cpu_unlock(void);
-
-typedef struct SubchDev SubchDev;
-
-#ifndef CONFIG_USER_ONLY
-extern void subsystem_reset(void);
-SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid,
- uint16_t schid);
-bool css_subch_visible(SubchDev *sch);
-void css_conditional_io_interrupt(SubchDev *sch);
-int css_do_stsch(SubchDev *sch, SCHIB *schib);
-bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid);
-int css_do_msch(SubchDev *sch, const SCHIB *schib);
-int css_do_xsch(SubchDev *sch);
-int css_do_csch(SubchDev *sch);
-int css_do_hsch(SubchDev *sch);
-int css_do_ssch(SubchDev *sch, ORB *orb);
-int css_do_tsch_get_irb(SubchDev *sch, IRB *irb, int *irb_len);
-void css_do_tsch_update_subch(SubchDev *sch);
-int css_do_stcrw(CRW *crw);
-void css_undo_stcrw(CRW *crw);
-int css_do_tpi(IOIntCode *int_code, int lowcore);
-int css_collect_chp_desc(int m, uint8_t cssid, uint8_t f_chpid, uint8_t l_chpid,
- int rfmt, void *buf);
-void css_do_schm(uint8_t mbk, int update, int dct, uint64_t mbo);
-int css_enable_mcsse(void);
-int css_enable_mss(void);
-int css_do_rsch(SubchDev *sch);
-int css_do_rchp(uint8_t cssid, uint8_t chpid);
-bool css_present(uint8_t cssid);
-#endif
-
-#define cpu_init(model) CPU(cpu_s390x_init(model))
-#define cpu_exec cpu_s390x_exec
-#define cpu_signal_handler cpu_s390x_signal_handler
-
-void s390_cpu_list(FILE *f, fprintf_function cpu_fprintf);
-#define cpu_list s390_cpu_list
-
-#include "exec/exec-all.h"
-
-#define EXCP_EXT 1 /* external interrupt */
-#define EXCP_SVC 2 /* supervisor call (syscall) */
-#define EXCP_PGM 3 /* program interruption */
-#define EXCP_IO 7 /* I/O interrupt */
-#define EXCP_MCHK 8 /* machine check */
-
-#define INTERRUPT_EXT (1 << 0)
-#define INTERRUPT_TOD (1 << 1)
-#define INTERRUPT_CPUTIMER (1 << 2)
-#define INTERRUPT_IO (1 << 3)
-#define INTERRUPT_MCHK (1 << 4)
-
-/* Program Status Word. */
-#define S390_PSWM_REGNUM 0
-#define S390_PSWA_REGNUM 1
-/* General Purpose Registers. */
-#define S390_R0_REGNUM 2
-#define S390_R1_REGNUM 3
-#define S390_R2_REGNUM 4
-#define S390_R3_REGNUM 5
-#define S390_R4_REGNUM 6
-#define S390_R5_REGNUM 7
-#define S390_R6_REGNUM 8
-#define S390_R7_REGNUM 9
-#define S390_R8_REGNUM 10
-#define S390_R9_REGNUM 11
-#define S390_R10_REGNUM 12
-#define S390_R11_REGNUM 13
-#define S390_R12_REGNUM 14
-#define S390_R13_REGNUM 15
-#define S390_R14_REGNUM 16
-#define S390_R15_REGNUM 17
-/* Total Core Registers. */
-#define S390_NUM_CORE_REGS 18
-
-/* CC optimization */
-
-enum cc_op {
- CC_OP_CONST0 = 0, /* CC is 0 */
- CC_OP_CONST1, /* CC is 1 */
- CC_OP_CONST2, /* CC is 2 */
- CC_OP_CONST3, /* CC is 3 */
-
- CC_OP_DYNAMIC, /* CC calculation defined by env->cc_op */
- CC_OP_STATIC, /* CC value is env->cc_op */
-
- CC_OP_NZ, /* env->cc_dst != 0 */
- CC_OP_LTGT_32, /* signed less/greater than (32bit) */
- CC_OP_LTGT_64, /* signed less/greater than (64bit) */
- CC_OP_LTUGTU_32, /* unsigned less/greater than (32bit) */
- CC_OP_LTUGTU_64, /* unsigned less/greater than (64bit) */
- CC_OP_LTGT0_32, /* signed less/greater than 0 (32bit) */
- CC_OP_LTGT0_64, /* signed less/greater than 0 (64bit) */
-
- CC_OP_ADD_64, /* overflow on add (64bit) */
- CC_OP_ADDU_64, /* overflow on unsigned add (64bit) */
- CC_OP_ADDC_64, /* overflow on unsigned add-carry (64bit) */
- CC_OP_SUB_64, /* overflow on subtraction (64bit) */
- CC_OP_SUBU_64, /* overflow on unsigned subtraction (64bit) */
- CC_OP_SUBB_64, /* overflow on unsigned sub-borrow (64bit) */
- CC_OP_ABS_64, /* sign eval on abs (64bit) */
- CC_OP_NABS_64, /* sign eval on nabs (64bit) */
-
- CC_OP_ADD_32, /* overflow on add (32bit) */
- CC_OP_ADDU_32, /* overflow on unsigned add (32bit) */
- CC_OP_ADDC_32, /* overflow on unsigned add-carry (32bit) */
- CC_OP_SUB_32, /* overflow on subtraction (32bit) */
- CC_OP_SUBU_32, /* overflow on unsigned subtraction (32bit) */
- CC_OP_SUBB_32, /* overflow on unsigned sub-borrow (32bit) */
- CC_OP_ABS_32, /* sign eval on abs (64bit) */
- CC_OP_NABS_32, /* sign eval on nabs (64bit) */
-
- CC_OP_COMP_32, /* complement */
- CC_OP_COMP_64, /* complement */
-
- CC_OP_TM_32, /* test under mask (32bit) */
- CC_OP_TM_64, /* test under mask (64bit) */
-
- CC_OP_NZ_F32, /* FP dst != 0 (32bit) */
- CC_OP_NZ_F64, /* FP dst != 0 (64bit) */
- CC_OP_NZ_F128, /* FP dst != 0 (128bit) */
-
- CC_OP_ICM, /* insert characters under mask */
- CC_OP_SLA_32, /* Calculate shift left signed (32bit) */
- CC_OP_SLA_64, /* Calculate shift left signed (64bit) */
- CC_OP_FLOGR, /* find leftmost one */
- CC_OP_MAX
-};
-
-static const char *cc_names[] = {
- [CC_OP_CONST0] = "CC_OP_CONST0",
- [CC_OP_CONST1] = "CC_OP_CONST1",
- [CC_OP_CONST2] = "CC_OP_CONST2",
- [CC_OP_CONST3] = "CC_OP_CONST3",
- [CC_OP_DYNAMIC] = "CC_OP_DYNAMIC",
- [CC_OP_STATIC] = "CC_OP_STATIC",
- [CC_OP_NZ] = "CC_OP_NZ",
- [CC_OP_LTGT_32] = "CC_OP_LTGT_32",
- [CC_OP_LTGT_64] = "CC_OP_LTGT_64",
- [CC_OP_LTUGTU_32] = "CC_OP_LTUGTU_32",
- [CC_OP_LTUGTU_64] = "CC_OP_LTUGTU_64",
- [CC_OP_LTGT0_32] = "CC_OP_LTGT0_32",
- [CC_OP_LTGT0_64] = "CC_OP_LTGT0_64",
- [CC_OP_ADD_64] = "CC_OP_ADD_64",
- [CC_OP_ADDU_64] = "CC_OP_ADDU_64",
- [CC_OP_ADDC_64] = "CC_OP_ADDC_64",
- [CC_OP_SUB_64] = "CC_OP_SUB_64",
- [CC_OP_SUBU_64] = "CC_OP_SUBU_64",
- [CC_OP_SUBB_64] = "CC_OP_SUBB_64",
- [CC_OP_ABS_64] = "CC_OP_ABS_64",
- [CC_OP_NABS_64] = "CC_OP_NABS_64",
- [CC_OP_ADD_32] = "CC_OP_ADD_32",
- [CC_OP_ADDU_32] = "CC_OP_ADDU_32",
- [CC_OP_ADDC_32] = "CC_OP_ADDC_32",
- [CC_OP_SUB_32] = "CC_OP_SUB_32",
- [CC_OP_SUBU_32] = "CC_OP_SUBU_32",
- [CC_OP_SUBB_32] = "CC_OP_SUBB_32",
- [CC_OP_ABS_32] = "CC_OP_ABS_32",
- [CC_OP_NABS_32] = "CC_OP_NABS_32",
- [CC_OP_COMP_32] = "CC_OP_COMP_32",
- [CC_OP_COMP_64] = "CC_OP_COMP_64",
- [CC_OP_TM_32] = "CC_OP_TM_32",
- [CC_OP_TM_64] = "CC_OP_TM_64",
- [CC_OP_NZ_F32] = "CC_OP_NZ_F32",
- [CC_OP_NZ_F64] = "CC_OP_NZ_F64",
- [CC_OP_NZ_F128] = "CC_OP_NZ_F128",
- [CC_OP_ICM] = "CC_OP_ICM",
- [CC_OP_SLA_32] = "CC_OP_SLA_32",
- [CC_OP_SLA_64] = "CC_OP_SLA_64",
- [CC_OP_FLOGR] = "CC_OP_FLOGR",
-};
-
-static inline const char *cc_name(int cc_op)
-{
- return cc_names[cc_op];
-}
-
-static inline void setcc(S390CPU *cpu, uint64_t cc)
-{
- CPUS390XState *env = &cpu->env;
-
- env->psw.mask &= ~(3ull << 44);
- env->psw.mask |= (cc & 3) << 44;
- env->cc_op = cc;
-}
-
-typedef struct LowCore
-{
- /* prefix area: defined by architecture */
- uint32_t ccw1[2]; /* 0x000 */
- uint32_t ccw2[4]; /* 0x008 */
- uint8_t pad1[0x80-0x18]; /* 0x018 */
- uint32_t ext_params; /* 0x080 */
- uint16_t cpu_addr; /* 0x084 */
- uint16_t ext_int_code; /* 0x086 */
- uint16_t svc_ilen; /* 0x088 */
- uint16_t svc_code; /* 0x08a */
- uint16_t pgm_ilen; /* 0x08c */
- uint16_t pgm_code; /* 0x08e */
- uint32_t data_exc_code; /* 0x090 */
- uint16_t mon_class_num; /* 0x094 */
- uint16_t per_perc_atmid; /* 0x096 */
- uint64_t per_address; /* 0x098 */
- uint8_t exc_access_id; /* 0x0a0 */
- uint8_t per_access_id; /* 0x0a1 */
- uint8_t op_access_id; /* 0x0a2 */
- uint8_t ar_access_id; /* 0x0a3 */
- uint8_t pad2[0xA8-0xA4]; /* 0x0a4 */
- uint64_t trans_exc_code; /* 0x0a8 */
- uint64_t monitor_code; /* 0x0b0 */
- uint16_t subchannel_id; /* 0x0b8 */
- uint16_t subchannel_nr; /* 0x0ba */
- uint32_t io_int_parm; /* 0x0bc */
- uint32_t io_int_word; /* 0x0c0 */
- uint8_t pad3[0xc8-0xc4]; /* 0x0c4 */
- uint32_t stfl_fac_list; /* 0x0c8 */
- uint8_t pad4[0xe8-0xcc]; /* 0x0cc */
- uint32_t mcck_interruption_code[2]; /* 0x0e8 */
- uint8_t pad5[0xf4-0xf0]; /* 0x0f0 */
- uint32_t external_damage_code; /* 0x0f4 */
- uint64_t failing_storage_address; /* 0x0f8 */
- uint8_t pad6[0x110-0x100]; /* 0x100 */
- uint64_t per_breaking_event_addr; /* 0x110 */
- uint8_t pad7[0x120-0x118]; /* 0x118 */
- PSW restart_old_psw; /* 0x120 */
- PSW external_old_psw; /* 0x130 */
- PSW svc_old_psw; /* 0x140 */
- PSW program_old_psw; /* 0x150 */
- PSW mcck_old_psw; /* 0x160 */
- PSW io_old_psw; /* 0x170 */
- uint8_t pad8[0x1a0-0x180]; /* 0x180 */
- PSW restart_new_psw; /* 0x1a0 */
- PSW external_new_psw; /* 0x1b0 */
- PSW svc_new_psw; /* 0x1c0 */
- PSW program_new_psw; /* 0x1d0 */
- PSW mcck_new_psw; /* 0x1e0 */
- PSW io_new_psw; /* 0x1f0 */
- PSW return_psw; /* 0x200 */
- uint8_t irb[64]; /* 0x210 */
- uint64_t sync_enter_timer; /* 0x250 */
- uint64_t async_enter_timer; /* 0x258 */
- uint64_t exit_timer; /* 0x260 */
- uint64_t last_update_timer; /* 0x268 */
- uint64_t user_timer; /* 0x270 */
- uint64_t system_timer; /* 0x278 */
- uint64_t last_update_clock; /* 0x280 */
- uint64_t steal_clock; /* 0x288 */
- PSW return_mcck_psw; /* 0x290 */
- uint8_t pad9[0xc00-0x2a0]; /* 0x2a0 */
- /* System info area */
- uint64_t save_area[16]; /* 0xc00 */
- uint8_t pad10[0xd40-0xc80]; /* 0xc80 */
- uint64_t kernel_stack; /* 0xd40 */
- uint64_t thread_info; /* 0xd48 */
- uint64_t async_stack; /* 0xd50 */
- uint64_t kernel_asce; /* 0xd58 */
- uint64_t user_asce; /* 0xd60 */
- uint64_t panic_stack; /* 0xd68 */
- uint64_t user_exec_asce; /* 0xd70 */
- uint8_t pad11[0xdc0-0xd78]; /* 0xd78 */
-
- /* SMP info area: defined by DJB */
- uint64_t clock_comparator; /* 0xdc0 */
- uint64_t ext_call_fast; /* 0xdc8 */
- uint64_t percpu_offset; /* 0xdd0 */
- uint64_t current_task; /* 0xdd8 */
- uint32_t softirq_pending; /* 0xde0 */
- uint32_t pad_0x0de4; /* 0xde4 */
- uint64_t int_clock; /* 0xde8 */
- uint8_t pad12[0xe00-0xdf0]; /* 0xdf0 */
-
- /* 0xe00 is used as indicator for dump tools */
- /* whether the kernel died with panic() or not */
- uint32_t panic_magic; /* 0xe00 */
-
- uint8_t pad13[0x11b8-0xe04]; /* 0xe04 */
-
- /* 64 bit extparam used for pfault, diag 250 etc */
- uint64_t ext_params2; /* 0x11B8 */
-
- uint8_t pad14[0x1200-0x11C0]; /* 0x11C0 */
-
- /* System info area */
-
- uint64_t floating_pt_save_area[16]; /* 0x1200 */
- uint64_t gpregs_save_area[16]; /* 0x1280 */
- uint32_t st_status_fixed_logout[4]; /* 0x1300 */
- uint8_t pad15[0x1318-0x1310]; /* 0x1310 */
- uint32_t prefixreg_save_area; /* 0x1318 */
- uint32_t fpt_creg_save_area; /* 0x131c */
- uint8_t pad16[0x1324-0x1320]; /* 0x1320 */
- uint32_t tod_progreg_save_area; /* 0x1324 */
- uint32_t cpu_timer_save_area[2]; /* 0x1328 */
- uint32_t clock_comp_save_area[2]; /* 0x1330 */
- uint8_t pad17[0x1340-0x1338]; /* 0x1338 */
- uint32_t access_regs_save_area[16]; /* 0x1340 */
- uint64_t cregs_save_area[16]; /* 0x1380 */
-
- /* align to the top of the prefix area */
-
- uint8_t pad18[0x2000-0x1400]; /* 0x1400 */
-} QEMU_PACKED LowCore;
-
-/* STSI */
-#define STSI_LEVEL_MASK 0x00000000f0000000ULL
-#define STSI_LEVEL_CURRENT 0x0000000000000000ULL
-#define STSI_LEVEL_1 0x0000000010000000ULL
-#define STSI_LEVEL_2 0x0000000020000000ULL
-#define STSI_LEVEL_3 0x0000000030000000ULL
-#define STSI_R0_RESERVED_MASK 0x000000000fffff00ULL
-#define STSI_R0_SEL1_MASK 0x00000000000000ffULL
-#define STSI_R1_RESERVED_MASK 0x00000000ffff0000ULL
-#define STSI_R1_SEL2_MASK 0x000000000000ffffULL
-
-/* Basic Machine Configuration */
-struct sysib_111 {
- uint32_t res1[8];
- uint8_t manuf[16];
- uint8_t type[4];
- uint8_t res2[12];
- uint8_t model[16];
- uint8_t sequence[16];
- uint8_t plant[4];
- uint8_t res3[156];
-};
-
-/* Basic Machine CPU */
-struct sysib_121 {
- uint32_t res1[80];
- uint8_t sequence[16];
- uint8_t plant[4];
- uint8_t res2[2];
- uint16_t cpu_addr;
- uint8_t res3[152];
-};
-
-/* Basic Machine CPUs */
-struct sysib_122 {
- uint8_t res1[32];
- uint32_t capability;
- uint16_t total_cpus;
- uint16_t active_cpus;
- uint16_t standby_cpus;
- uint16_t reserved_cpus;
- uint16_t adjustments[2026];
-};
-
-/* LPAR CPU */
-struct sysib_221 {
- uint32_t res1[80];
- uint8_t sequence[16];
- uint8_t plant[4];
- uint16_t cpu_id;
- uint16_t cpu_addr;
- uint8_t res3[152];
-};
-
-/* LPAR CPUs */
-struct sysib_222 {
- uint32_t res1[32];
- uint16_t lpar_num;
- uint8_t res2;
- uint8_t lcpuc;
- uint16_t total_cpus;
- uint16_t conf_cpus;
- uint16_t standby_cpus;
- uint16_t reserved_cpus;
- uint8_t name[8];
- uint32_t caf;
- uint8_t res3[16];
- uint16_t dedicated_cpus;
- uint16_t shared_cpus;
- uint8_t res4[180];
-};
-
-/* VM CPUs */
-struct sysib_322 {
- uint8_t res1[31];
- uint8_t count;
- struct {
- uint8_t res2[4];
- uint16_t total_cpus;
- uint16_t conf_cpus;
- uint16_t standby_cpus;
- uint16_t reserved_cpus;
- uint8_t name[8];
- uint32_t caf;
- uint8_t cpi[16];
- uint8_t res5[3];
- uint8_t ext_name_encoding;
- uint32_t res3;
- uint8_t uuid[16];
- } vm[8];
- uint8_t res4[1504];
- uint8_t ext_names[8][256];
-};
-
-/* MMU defines */
-#define _ASCE_ORIGIN ~0xfffULL /* segment table origin */
-#define _ASCE_SUBSPACE 0x200 /* subspace group control */
-#define _ASCE_PRIVATE_SPACE 0x100 /* private space control */
-#define _ASCE_ALT_EVENT 0x80 /* storage alteration event control */
-#define _ASCE_SPACE_SWITCH 0x40 /* space switch event */
-#define _ASCE_REAL_SPACE 0x20 /* real space control */
-#define _ASCE_TYPE_MASK 0x0c /* asce table type mask */
-#define _ASCE_TYPE_REGION1 0x0c /* region first table type */
-#define _ASCE_TYPE_REGION2 0x08 /* region second table type */
-#define _ASCE_TYPE_REGION3 0x04 /* region third table type */
-#define _ASCE_TYPE_SEGMENT 0x00 /* segment table type */
-#define _ASCE_TABLE_LENGTH 0x03 /* region table length */
-
-#define _REGION_ENTRY_ORIGIN ~0xfffULL /* region/segment table origin */
-#define _REGION_ENTRY_RO 0x200 /* region/segment protection bit */
-#define _REGION_ENTRY_TF 0xc0 /* region/segment table offset */
-#define _REGION_ENTRY_INV 0x20 /* invalid region table entry */
-#define _REGION_ENTRY_TYPE_MASK 0x0c /* region/segment table type mask */
-#define _REGION_ENTRY_TYPE_R1 0x0c /* region first table type */
-#define _REGION_ENTRY_TYPE_R2 0x08 /* region second table type */
-#define _REGION_ENTRY_TYPE_R3 0x04 /* region third table type */
-#define _REGION_ENTRY_LENGTH 0x03 /* region third length */
-
-#define _SEGMENT_ENTRY_ORIGIN ~0x7ffULL /* segment table origin */
-#define _SEGMENT_ENTRY_FC 0x400 /* format control */
-#define _SEGMENT_ENTRY_RO 0x200 /* page protection bit */
-#define _SEGMENT_ENTRY_INV 0x20 /* invalid segment table entry */
-
-#define _PAGE_RO 0x200 /* HW read-only bit */
-#define _PAGE_INVALID 0x400 /* HW invalid bit */
-#define _PAGE_RES0 0x800 /* bit must be zero */
-
-#define SK_C (0x1 << 1)
-#define SK_R (0x1 << 2)
-#define SK_F (0x1 << 3)
-#define SK_ACC_MASK (0xf << 4)
-
-/* SIGP order codes */
-#define SIGP_SENSE 0x01
-#define SIGP_EXTERNAL_CALL 0x02
-#define SIGP_EMERGENCY 0x03
-#define SIGP_START 0x04
-#define SIGP_STOP 0x05
-#define SIGP_RESTART 0x06
-#define SIGP_STOP_STORE_STATUS 0x09
-#define SIGP_INITIAL_CPU_RESET 0x0b
-#define SIGP_CPU_RESET 0x0c
-#define SIGP_SET_PREFIX 0x0d
-#define SIGP_STORE_STATUS_ADDR 0x0e
-#define SIGP_SET_ARCH 0x12
-#define SIGP_STORE_ADTL_STATUS 0x17
-
-/* SIGP condition codes */
-#define SIGP_CC_ORDER_CODE_ACCEPTED 0
-#define SIGP_CC_STATUS_STORED 1
-#define SIGP_CC_BUSY 2
-#define SIGP_CC_NOT_OPERATIONAL 3
-
-/* SIGP status bits */
-#define SIGP_STAT_EQUIPMENT_CHECK 0x80000000UL
-#define SIGP_STAT_INCORRECT_STATE 0x00000200UL
-#define SIGP_STAT_INVALID_PARAMETER 0x00000100UL
-#define SIGP_STAT_EXT_CALL_PENDING 0x00000080UL
-#define SIGP_STAT_STOPPED 0x00000040UL
-#define SIGP_STAT_OPERATOR_INTERV 0x00000020UL
-#define SIGP_STAT_CHECK_STOP 0x00000010UL
-#define SIGP_STAT_INOPERATIVE 0x00000004UL
-#define SIGP_STAT_INVALID_ORDER 0x00000002UL
-#define SIGP_STAT_RECEIVER_CHECK 0x00000001UL
-
-/* SIGP SET ARCHITECTURE modes */
-#define SIGP_MODE_ESA_S390 0
-#define SIGP_MODE_Z_ARCH_TRANS_ALL_PSW 1
-#define SIGP_MODE_Z_ARCH_TRANS_CUR_PSW 2
-
-void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr);
-int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
- target_ulong *raddr, int *flags, bool exc);
-int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code);
-uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
- uint64_t vr);
-void s390_cpu_recompute_watchpoints(CPUState *cs);
-
-int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf,
- int len, bool is_write);
-
-#define s390_cpu_virt_mem_read(cpu, laddr, ar, dest, len) \
- s390_cpu_virt_mem_rw(cpu, laddr, ar, dest, len, false)
-#define s390_cpu_virt_mem_write(cpu, laddr, ar, dest, len) \
- s390_cpu_virt_mem_rw(cpu, laddr, ar, dest, len, true)
-#define s390_cpu_virt_mem_check_write(cpu, laddr, ar, len) \
- s390_cpu_virt_mem_rw(cpu, laddr, ar, NULL, len, true)
-
-/* The value of the TOD clock for 1.1.1970. */
-#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
-
-/* Converts ns to s390's clock format */
-static inline uint64_t time2tod(uint64_t ns) {
- return (ns << 9) / 125;
-}
-
-/* Converts s390's clock format to ns */
-static inline uint64_t tod2time(uint64_t t) {
- return (t * 125) >> 9;
-}
-
-static inline void cpu_inject_ext(S390CPU *cpu, uint32_t code, uint32_t param,
- uint64_t param64)
-{
- CPUS390XState *env = &cpu->env;
-
- if (env->ext_index == MAX_EXT_QUEUE - 1) {
- /* ugh - can't queue anymore. Let's drop. */
- return;
- }
-
- env->ext_index++;
- assert(env->ext_index < MAX_EXT_QUEUE);
-
- env->ext_queue[env->ext_index].code = code;
- env->ext_queue[env->ext_index].param = param;
- env->ext_queue[env->ext_index].param64 = param64;
-
- env->pending_int |= INTERRUPT_EXT;
- cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
-}
-
-static inline void cpu_inject_io(S390CPU *cpu, uint16_t subchannel_id,
- uint16_t subchannel_number,
- uint32_t io_int_parm, uint32_t io_int_word)
-{
- CPUS390XState *env = &cpu->env;
- int isc = IO_INT_WORD_ISC(io_int_word);
-
- if (env->io_index[isc] == MAX_IO_QUEUE - 1) {
- /* ugh - can't queue anymore. Let's drop. */
- return;
- }
-
- env->io_index[isc]++;
- assert(env->io_index[isc] < MAX_IO_QUEUE);
-
- env->io_queue[env->io_index[isc]][isc].id = subchannel_id;
- env->io_queue[env->io_index[isc]][isc].nr = subchannel_number;
- env->io_queue[env->io_index[isc]][isc].parm = io_int_parm;
- env->io_queue[env->io_index[isc]][isc].word = io_int_word;
-
- env->pending_int |= INTERRUPT_IO;
- cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
-}
-
-static inline void cpu_inject_crw_mchk(S390CPU *cpu)
-{
- CPUS390XState *env = &cpu->env;
-
- if (env->mchk_index == MAX_MCHK_QUEUE - 1) {
- /* ugh - can't queue anymore. Let's drop. */
- return;
- }
-
- env->mchk_index++;
- assert(env->mchk_index < MAX_MCHK_QUEUE);
-
- env->mchk_queue[env->mchk_index].type = 1;
-
- env->pending_int |= INTERRUPT_MCHK;
- cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
-}
-
-/* from s390-virtio-ccw */
-#define MEM_SECTION_SIZE 0x10000000UL
-#define MAX_AVAIL_SLOTS 32
-
-/* fpu_helper.c */
-uint32_t set_cc_nz_f32(float32 v);
-uint32_t set_cc_nz_f64(float64 v);
-uint32_t set_cc_nz_f128(float128 v);
-
-/* misc_helper.c */
-#ifndef CONFIG_USER_ONLY
-int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3);
-void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3);
-#endif
-void program_interrupt(CPUS390XState *env, uint32_t code, int ilen);
-void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
- uintptr_t retaddr);
-
-#ifdef CONFIG_KVM
-void kvm_s390_io_interrupt(uint16_t subchannel_id,
- uint16_t subchannel_nr, uint32_t io_int_parm,
- uint32_t io_int_word);
-void kvm_s390_crw_mchk(void);
-void kvm_s390_enable_css_support(S390CPU *cpu);
-int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch,
- int vq, bool assign);
-int kvm_s390_cpu_restart(S390CPU *cpu);
-int kvm_s390_get_memslot_count(KVMState *s);
-void kvm_s390_cmma_reset(void);
-int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state);
-void kvm_s390_reset_vcpu(S390CPU *cpu);
-int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit);
-void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu);
-int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu);
-void kvm_s390_crypto_reset(void);
-#else
-static inline void kvm_s390_io_interrupt(uint16_t subchannel_id,
- uint16_t subchannel_nr,
- uint32_t io_int_parm,
- uint32_t io_int_word)
-{
-}
-static inline void kvm_s390_crw_mchk(void)
-{
-}
-static inline void kvm_s390_enable_css_support(S390CPU *cpu)
-{
-}
-static inline int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier,
- uint32_t sch, int vq,
- bool assign)
-{
- return -ENOSYS;
-}
-static inline int kvm_s390_cpu_restart(S390CPU *cpu)
-{
- return -ENOSYS;
-}
-static inline void kvm_s390_cmma_reset(void)
-{
-}
-static inline int kvm_s390_get_memslot_count(KVMState *s)
-{
- return MAX_AVAIL_SLOTS;
-}
-static inline int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state)
-{
- return -ENOSYS;
-}
-static inline void kvm_s390_reset_vcpu(S390CPU *cpu)
-{
-}
-static inline int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit,
- uint64_t *hw_limit)
-{
- return 0;
-}
-static inline void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu)
-{
-}
-static inline int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu)
-{
- return 0;
-}
-static inline void kvm_s390_crypto_reset(void)
-{
-}
-#endif
-
-static inline int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit)
-{
- if (kvm_enabled()) {
- return kvm_s390_set_mem_limit(kvm_state, new_limit, hw_limit);
- }
- return 0;
-}
-
-static inline void s390_cmma_reset(void)
-{
- if (kvm_enabled()) {
- kvm_s390_cmma_reset();
- }
-}
-
-static inline int s390_cpu_restart(S390CPU *cpu)
-{
- if (kvm_enabled()) {
- return kvm_s390_cpu_restart(cpu);
- }
- return -ENOSYS;
-}
-
-static inline int s390_get_memslot_count(KVMState *s)
-{
- if (kvm_enabled()) {
- return kvm_s390_get_memslot_count(s);
- } else {
- return MAX_AVAIL_SLOTS;
- }
-}
-
-void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr,
- uint32_t io_int_parm, uint32_t io_int_word);
-void s390_crw_mchk(void);
-
-static inline int s390_assign_subch_ioeventfd(EventNotifier *notifier,
- uint32_t sch_id, int vq,
- bool assign)
-{
- return kvm_s390_assign_subch_ioeventfd(notifier, sch_id, vq, assign);
-}
-
-static inline void s390_crypto_reset(void)
-{
- if (kvm_enabled()) {
- kvm_s390_crypto_reset();
- }
-}
-
-#ifdef CONFIG_KVM
-static inline bool vregs_needed(void *opaque)
-{
- if (kvm_enabled()) {
- return kvm_check_extension(kvm_state, KVM_CAP_S390_VECTOR_REGISTERS);
- }
- return 0;
-}
-#else
-static inline bool vregs_needed(void *opaque)
-{
- return 0;
-}
-#endif
-
-/* machine check interruption code */
-
-/* subclasses */
-#define MCIC_SC_SD 0x8000000000000000ULL
-#define MCIC_SC_PD 0x4000000000000000ULL
-#define MCIC_SC_SR 0x2000000000000000ULL
-#define MCIC_SC_CD 0x0800000000000000ULL
-#define MCIC_SC_ED 0x0400000000000000ULL
-#define MCIC_SC_DG 0x0100000000000000ULL
-#define MCIC_SC_W 0x0080000000000000ULL
-#define MCIC_SC_CP 0x0040000000000000ULL
-#define MCIC_SC_SP 0x0020000000000000ULL
-#define MCIC_SC_CK 0x0010000000000000ULL
-
-/* subclass modifiers */
-#define MCIC_SCM_B 0x0002000000000000ULL
-#define MCIC_SCM_DA 0x0000000020000000ULL
-#define MCIC_SCM_AP 0x0000000000080000ULL
-
-/* storage errors */
-#define MCIC_SE_SE 0x0000800000000000ULL
-#define MCIC_SE_SC 0x0000400000000000ULL
-#define MCIC_SE_KE 0x0000200000000000ULL
-#define MCIC_SE_DS 0x0000100000000000ULL
-#define MCIC_SE_IE 0x0000000080000000ULL
-
-/* validity bits */
-#define MCIC_VB_WP 0x0000080000000000ULL
-#define MCIC_VB_MS 0x0000040000000000ULL
-#define MCIC_VB_PM 0x0000020000000000ULL
-#define MCIC_VB_IA 0x0000010000000000ULL
-#define MCIC_VB_FA 0x0000008000000000ULL
-#define MCIC_VB_VR 0x0000004000000000ULL
-#define MCIC_VB_EC 0x0000002000000000ULL
-#define MCIC_VB_FP 0x0000001000000000ULL
-#define MCIC_VB_GR 0x0000000800000000ULL
-#define MCIC_VB_CR 0x0000000400000000ULL
-#define MCIC_VB_ST 0x0000000100000000ULL
-#define MCIC_VB_AR 0x0000000040000000ULL
-#define MCIC_VB_PR 0x0000000000200000ULL
-#define MCIC_VB_FC 0x0000000000100000ULL
-#define MCIC_VB_CT 0x0000000000020000ULL
-#define MCIC_VB_CC 0x0000000000010000ULL
-
-#endif
diff --git a/qemu/target-s390x/fpu_helper.c b/qemu/target-s390x/fpu_helper.c
deleted file mode 100644
index 1c7f67354..000000000
--- a/qemu/target-s390x/fpu_helper.c
+++ /dev/null
@@ -1,744 +0,0 @@
-/*
- * S/390 FPU helper routines
- *
- * Copyright (c) 2009 Ulrich Hecht
- * Copyright (c) 2009 Alexander Graf
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "exec/cpu_ldst.h"
-#include "exec/helper-proto.h"
-
-/* #define DEBUG_HELPER */
-#ifdef DEBUG_HELPER
-#define HELPER_LOG(x...) qemu_log(x)
-#else
-#define HELPER_LOG(x...)
-#endif
-
-#define RET128(F) (env->retxl = F.low, F.high)
-
-#define convert_bit(mask, from, to) \
- (to < from \
- ? (mask / (from / to)) & to \
- : (mask & from) * (to / from))
-
-static void ieee_exception(CPUS390XState *env, uint32_t dxc, uintptr_t retaddr)
-{
- /* Install the DXC code. */
- env->fpc = (env->fpc & ~0xff00) | (dxc << 8);
- /* Trap. */
- runtime_exception(env, PGM_DATA, retaddr);
-}
-
-/* Should be called after any operation that may raise IEEE exceptions. */
-static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
-{
- unsigned s390_exc, qemu_exc;
-
- /* Get the exceptions raised by the current operation. Reset the
- fpu_status contents so that the next operation has a clean slate. */
- qemu_exc = env->fpu_status.float_exception_flags;
- if (qemu_exc == 0) {
- return;
- }
- env->fpu_status.float_exception_flags = 0;
-
- /* Convert softfloat exception bits to s390 exception bits. */
- s390_exc = 0;
- s390_exc |= convert_bit(qemu_exc, float_flag_invalid, 0x80);
- s390_exc |= convert_bit(qemu_exc, float_flag_divbyzero, 0x40);
- s390_exc |= convert_bit(qemu_exc, float_flag_overflow, 0x20);
- s390_exc |= convert_bit(qemu_exc, float_flag_underflow, 0x10);
- s390_exc |= convert_bit(qemu_exc, float_flag_inexact, 0x08);
-
- /* Install the exceptions that we raised. */
- env->fpc |= s390_exc << 16;
-
- /* Send signals for enabled exceptions. */
- s390_exc &= env->fpc >> 24;
- if (s390_exc) {
- ieee_exception(env, s390_exc, retaddr);
- }
-}
-
-static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
-
- switch (float_compare) {
- case float_relation_equal:
- return 0;
- case float_relation_less:
- return 1;
- case float_relation_greater:
- return 2;
- case float_relation_unordered:
- return 3;
- default:
- cpu_abort(CPU(cpu), "unknown return value for float compare\n");
- }
-}
-
-/* condition codes for unary FP ops */
-uint32_t set_cc_nz_f32(float32 v)
-{
- if (float32_is_any_nan(v)) {
- return 3;
- } else if (float32_is_zero(v)) {
- return 0;
- } else if (float32_is_neg(v)) {
- return 1;
- } else {
- return 2;
- }
-}
-
-uint32_t set_cc_nz_f64(float64 v)
-{
- if (float64_is_any_nan(v)) {
- return 3;
- } else if (float64_is_zero(v)) {
- return 0;
- } else if (float64_is_neg(v)) {
- return 1;
- } else {
- return 2;
- }
-}
-
-uint32_t set_cc_nz_f128(float128 v)
-{
- if (float128_is_any_nan(v)) {
- return 3;
- } else if (float128_is_zero(v)) {
- return 0;
- } else if (float128_is_neg(v)) {
- return 1;
- } else {
- return 2;
- }
-}
-
-/* 32-bit FP addition */
-uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
-{
- float32 ret = float32_add(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* 64-bit FP addition */
-uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
-{
- float64 ret = float64_add(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* 128-bit FP addition */
-uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
- uint64_t bh, uint64_t bl)
-{
- float128 ret = float128_add(make_float128(ah, al),
- make_float128(bh, bl),
- &env->fpu_status);
- handle_exceptions(env, GETPC());
- return RET128(ret);
-}
-
-/* 32-bit FP subtraction */
-uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
-{
- float32 ret = float32_sub(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* 64-bit FP subtraction */
-uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
-{
- float64 ret = float64_sub(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* 128-bit FP subtraction */
-uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
- uint64_t bh, uint64_t bl)
-{
- float128 ret = float128_sub(make_float128(ah, al),
- make_float128(bh, bl),
- &env->fpu_status);
- handle_exceptions(env, GETPC());
- return RET128(ret);
-}
-
-/* 32-bit FP division */
-uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
-{
- float32 ret = float32_div(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* 64-bit FP division */
-uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
-{
- float64 ret = float64_div(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* 128-bit FP division */
-uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
- uint64_t bh, uint64_t bl)
-{
- float128 ret = float128_div(make_float128(ah, al),
- make_float128(bh, bl),
- &env->fpu_status);
- handle_exceptions(env, GETPC());
- return RET128(ret);
-}
-
-/* 32-bit FP multiplication */
-uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
-{
- float32 ret = float32_mul(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* 64-bit FP multiplication */
-uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
-{
- float64 ret = float64_mul(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* 64/32-bit FP multiplication */
-uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
-{
- float64 ret = float32_to_float64(f2, &env->fpu_status);
- ret = float64_mul(f1, ret, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* 128-bit FP multiplication */
-uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
- uint64_t bh, uint64_t bl)
-{
- float128 ret = float128_mul(make_float128(ah, al),
- make_float128(bh, bl),
- &env->fpu_status);
- handle_exceptions(env, GETPC());
- return RET128(ret);
-}
-
-/* 128/64-bit FP multiplication */
-uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al,
- uint64_t f2)
-{
- float128 ret = float64_to_float128(f2, &env->fpu_status);
- ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return RET128(ret);
-}
-
-/* convert 32-bit float to 64-bit float */
-uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
-{
- float64 ret = float32_to_float64(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return float64_maybe_silence_nan(ret);
-}
-
-/* convert 128-bit float to 64-bit float */
-uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
-{
- float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
- handle_exceptions(env, GETPC());
- return float64_maybe_silence_nan(ret);
-}
-
-/* convert 64-bit float to 128-bit float */
-uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
-{
- float128 ret = float64_to_float128(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return RET128(float128_maybe_silence_nan(ret));
-}
-
-/* convert 32-bit float to 128-bit float */
-uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
-{
- float128 ret = float32_to_float128(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return RET128(float128_maybe_silence_nan(ret));
-}
-
-/* convert 64-bit float to 32-bit float */
-uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
-{
- float32 ret = float64_to_float32(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return float32_maybe_silence_nan(ret);
-}
-
-/* convert 128-bit float to 32-bit float */
-uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
-{
- float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
- handle_exceptions(env, GETPC());
- return float32_maybe_silence_nan(ret);
-}
-
-/* 32-bit FP compare */
-uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
-{
- int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return float_comp_to_cc(env, cmp);
-}
-
-/* 64-bit FP compare */
-uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
-{
- int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return float_comp_to_cc(env, cmp);
-}
-
-/* 128-bit FP compare */
-uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
- uint64_t bh, uint64_t bl)
-{
- int cmp = float128_compare_quiet(make_float128(ah, al),
- make_float128(bh, bl),
- &env->fpu_status);
- handle_exceptions(env, GETPC());
- return float_comp_to_cc(env, cmp);
-}
-
-static int swap_round_mode(CPUS390XState *env, int m3)
-{
- int ret = env->fpu_status.float_rounding_mode;
- switch (m3) {
- case 0:
- /* current mode */
- break;
- case 1:
- /* biased round no nearest */
- case 4:
- /* round to nearest */
- set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
- break;
- case 5:
- /* round to zero */
- set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
- break;
- case 6:
- /* round to +inf */
- set_float_rounding_mode(float_round_up, &env->fpu_status);
- break;
- case 7:
- /* round to -inf */
- set_float_rounding_mode(float_round_down, &env->fpu_status);
- break;
- }
- return ret;
-}
-
-/* convert 64-bit int to 32-bit float */
-uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- float32 ret = int64_to_float32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* convert 64-bit int to 64-bit float */
-uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- float64 ret = int64_to_float64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* convert 64-bit int to 128-bit float */
-uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- float128 ret = int64_to_float128(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return RET128(ret);
-}
-
-/* convert 64-bit uint to 32-bit float */
-uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- float32 ret = uint64_to_float32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* convert 64-bit uint to 64-bit float */
-uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- float64 ret = uint64_to_float64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* convert 64-bit uint to 128-bit float */
-uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- float128 ret = uint64_to_float128(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return RET128(ret);
-}
-
-/* convert 32-bit float to 64-bit int */
-uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- int64_t ret = float32_to_int64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* convert 64-bit float to 64-bit int */
-uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- int64_t ret = float64_to_int64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* convert 128-bit float to 64-bit int */
-uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- float128 v2 = make_float128(h, l);
- int64_t ret = float128_to_int64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* convert 32-bit float to 32-bit int */
-uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- int32_t ret = float32_to_int32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* convert 64-bit float to 32-bit int */
-uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- int32_t ret = float64_to_int32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* convert 128-bit float to 32-bit int */
-uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- float128 v2 = make_float128(h, l);
- int32_t ret = float128_to_int32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* convert 32-bit float to 64-bit uint */
-uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- uint64_t ret;
- v2 = float32_to_float64(v2, &env->fpu_status);
- ret = float64_to_uint64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* convert 64-bit float to 64-bit uint */
-uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- uint64_t ret = float64_to_uint64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* convert 128-bit float to 64-bit uint */
-uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- float128 v2 = make_float128(h, l);
- /* ??? Not 100% correct. */
- uint64_t ret = float128_to_int64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* convert 32-bit float to 32-bit uint */
-uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- uint32_t ret = float32_to_uint32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* convert 64-bit float to 32-bit uint */
-uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- uint32_t ret = float64_to_uint32(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* convert 128-bit float to 32-bit uint */
-uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- float128 v2 = make_float128(h, l);
- /* Not 100% correct. */
- uint32_t ret = float128_to_int64(v2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* round to integer 32-bit */
-uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- float32 ret = float32_round_to_int(f2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* round to integer 64-bit */
-uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- float64 ret = float64_round_to_int(f2, &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* round to integer 128-bit */
-uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
-{
- int hold = swap_round_mode(env, m3);
- float128 ret = float128_round_to_int(make_float128(ah, al),
- &env->fpu_status);
- set_float_rounding_mode(hold, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return RET128(ret);
-}
-
-/* 32-bit FP multiply and add */
-uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
- uint64_t f2, uint64_t f3)
-{
- float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* 64-bit FP multiply and add */
-uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1,
- uint64_t f2, uint64_t f3)
-{
- float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* 32-bit FP multiply and subtract */
-uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1,
- uint64_t f2, uint64_t f3)
-{
- float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c,
- &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* 64-bit FP multiply and subtract */
-uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
- uint64_t f2, uint64_t f3)
-{
- float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c,
- &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* test data class 32-bit */
-uint32_t HELPER(tceb)(uint64_t f1, uint64_t m2)
-{
- float32 v1 = f1;
- int neg = float32_is_neg(v1);
- uint32_t cc = 0;
-
- if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
- (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
- (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
- (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
- cc = 1;
- } else if (m2 & (1 << (9-neg))) {
- /* assume normalized number */
- cc = 1;
- }
- /* FIXME: denormalized? */
- return cc;
-}
-
-/* test data class 64-bit */
-uint32_t HELPER(tcdb)(uint64_t v1, uint64_t m2)
-{
- int neg = float64_is_neg(v1);
- uint32_t cc = 0;
-
- if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
- (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
- (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
- (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
- cc = 1;
- } else if (m2 & (1 << (9-neg))) {
- /* assume normalized number */
- cc = 1;
- }
- /* FIXME: denormalized? */
- return cc;
-}
-
-/* test data class 128-bit */
-uint32_t HELPER(tcxb)(uint64_t ah, uint64_t al, uint64_t m2)
-{
- float128 v1 = make_float128(ah, al);
- int neg = float128_is_neg(v1);
- uint32_t cc = 0;
-
- if ((float128_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
- (float128_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
- (float128_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
- (float128_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
- cc = 1;
- } else if (m2 & (1 << (9-neg))) {
- /* assume normalized number */
- cc = 1;
- }
- /* FIXME: denormalized? */
- return cc;
-}
-
-/* square root 32-bit */
-uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
-{
- float32 ret = float32_sqrt(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* square root 64-bit */
-uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
-{
- float64 ret = float64_sqrt(f2, &env->fpu_status);
- handle_exceptions(env, GETPC());
- return ret;
-}
-
-/* square root 128-bit */
-uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
-{
- float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status);
- handle_exceptions(env, GETPC());
- return RET128(ret);
-}
-
-static const int fpc_to_rnd[4] = {
- float_round_nearest_even,
- float_round_to_zero,
- float_round_up,
- float_round_down
-};
-
-/* set fpc */
-void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
-{
- /* Install everything in the main FPC. */
- env->fpc = fpc;
-
- /* Install the rounding mode in the shadow fpu_status. */
- set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
-}
-
-/* set fpc and signal */
-void HELPER(sfas)(CPUS390XState *env, uint64_t val)
-{
- uint32_t signalling = env->fpc;
- uint32_t source = val;
- uint32_t s390_exc;
-
- /* The contents of the source operand are placed in the FPC register;
- then the flags in the FPC register are set to the logical OR of the
- signalling flags and the source flags. */
- env->fpc = source | (signalling & 0x00ff0000);
- set_float_rounding_mode(fpc_to_rnd[source & 3], &env->fpu_status);
-
- /* If any signalling flag is 1 and the corresponding source mask
- is also 1, a simulated-iee-exception trap occurs. */
- s390_exc = (signalling >> 16) & (source >> 24);
- if (s390_exc) {
- ieee_exception(env, s390_exc | 3, GETPC());
- }
-}
diff --git a/qemu/target-s390x/gdbstub.c b/qemu/target-s390x/gdbstub.c
deleted file mode 100644
index 9fc36cb54..000000000
--- a/qemu/target-s390x/gdbstub.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * s390x gdb server stub
- *
- * Copyright (c) 2003-2005 Fabrice Bellard
- * Copyright (c) 2013 SUSE LINUX Products GmbH
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "exec/gdbstub.h"
-#include "qemu/bitops.h"
-
-int s390_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
-{
- S390CPU *cpu = S390_CPU(cs);
- CPUS390XState *env = &cpu->env;
- uint64_t val;
- int cc_op;
-
- switch (n) {
- case S390_PSWM_REGNUM:
- if (tcg_enabled()) {
- cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst,
- env->cc_vr);
- val = deposit64(env->psw.mask, 44, 2, cc_op);
- return gdb_get_regl(mem_buf, val);
- }
- return gdb_get_regl(mem_buf, env->psw.mask);
- case S390_PSWA_REGNUM:
- return gdb_get_regl(mem_buf, env->psw.addr);
- case S390_R0_REGNUM ... S390_R15_REGNUM:
- return gdb_get_regl(mem_buf, env->regs[n - S390_R0_REGNUM]);
- }
- return 0;
-}
-
-int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
-{
- S390CPU *cpu = S390_CPU(cs);
- CPUS390XState *env = &cpu->env;
- target_ulong tmpl = ldtul_p(mem_buf);
-
- switch (n) {
- case S390_PSWM_REGNUM:
- env->psw.mask = tmpl;
- if (tcg_enabled()) {
- env->cc_op = extract64(tmpl, 44, 2);
- }
- break;
- case S390_PSWA_REGNUM:
- env->psw.addr = tmpl;
- break;
- case S390_R0_REGNUM ... S390_R15_REGNUM:
- env->regs[n - S390_R0_REGNUM] = tmpl;
- break;
- default:
- return 0;
- }
- return 8;
-}
-
-/* the values represent the positions in s390-acr.xml */
-#define S390_A0_REGNUM 0
-#define S390_A15_REGNUM 15
-/* total number of registers in s390-acr.xml */
-#define S390_NUM_AC_REGS 16
-
-static int cpu_read_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
-{
- switch (n) {
- case S390_A0_REGNUM ... S390_A15_REGNUM:
- return gdb_get_reg32(mem_buf, env->aregs[n]);
- default:
- return 0;
- }
-}
-
-static int cpu_write_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
-{
- switch (n) {
- case S390_A0_REGNUM ... S390_A15_REGNUM:
- env->aregs[n] = ldl_p(mem_buf);
- cpu_synchronize_post_init(ENV_GET_CPU(env));
- return 4;
- default:
- return 0;
- }
-}
-
-/* the values represent the positions in s390-fpr.xml */
-#define S390_FPC_REGNUM 0
-#define S390_F0_REGNUM 1
-#define S390_F15_REGNUM 16
-/* total number of registers in s390-fpr.xml */
-#define S390_NUM_FP_REGS 17
-
-static int cpu_read_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
-{
- switch (n) {
- case S390_FPC_REGNUM:
- return gdb_get_reg32(mem_buf, env->fpc);
- case S390_F0_REGNUM ... S390_F15_REGNUM:
- return gdb_get_reg64(mem_buf, get_freg(env, n - S390_F0_REGNUM)->ll);
- default:
- return 0;
- }
-}
-
-static int cpu_write_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
-{
- switch (n) {
- case S390_FPC_REGNUM:
- env->fpc = ldl_p(mem_buf);
- return 4;
- case S390_F0_REGNUM ... S390_F15_REGNUM:
- get_freg(env, n - S390_F0_REGNUM)->ll = ldtul_p(mem_buf);
- return 8;
- default:
- return 0;
- }
-}
-
-/* the values represent the positions in s390-vx.xml */
-#define S390_V0L_REGNUM 0
-#define S390_V15L_REGNUM 15
-#define S390_V16_REGNUM 16
-#define S390_V31_REGNUM 31
-/* total number of registers in s390-vx.xml */
-#define S390_NUM_VREGS 32
-
-static int cpu_read_vreg(CPUS390XState *env, uint8_t *mem_buf, int n)
-{
- int ret;
-
- switch (n) {
- case S390_V0L_REGNUM ... S390_V15L_REGNUM:
- ret = gdb_get_reg64(mem_buf, env->vregs[n][1].ll);
- break;
- case S390_V16_REGNUM ... S390_V31_REGNUM:
- ret = gdb_get_reg64(mem_buf, env->vregs[n][0].ll);
- ret += gdb_get_reg64(mem_buf + 8, env->vregs[n][1].ll);
- break;
- default:
- ret = 0;
- }
-
- return ret;
-}
-
-static int cpu_write_vreg(CPUS390XState *env, uint8_t *mem_buf, int n)
-{
- switch (n) {
- case S390_V0L_REGNUM ... S390_V15L_REGNUM:
- env->vregs[n][1].ll = ldtul_p(mem_buf + 8);
- return 8;
- case S390_V16_REGNUM ... S390_V31_REGNUM:
- env->vregs[n][0].ll = ldtul_p(mem_buf);
- env->vregs[n][1].ll = ldtul_p(mem_buf + 8);
- return 16;
- default:
- return 0;
- }
-}
-
-/* the values represent the positions in s390-cr.xml */
-#define S390_C0_REGNUM 0
-#define S390_C15_REGNUM 15
-/* total number of registers in s390-cr.xml */
-#define S390_NUM_C_REGS 16
-
-#ifndef CONFIG_USER_ONLY
-static int cpu_read_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
-{
- switch (n) {
- case S390_C0_REGNUM ... S390_C15_REGNUM:
- return gdb_get_regl(mem_buf, env->cregs[n]);
- default:
- return 0;
- }
-}
-
-static int cpu_write_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
-{
- switch (n) {
- case S390_C0_REGNUM ... S390_C15_REGNUM:
- env->cregs[n] = ldtul_p(mem_buf);
- if (tcg_enabled()) {
- tlb_flush(ENV_GET_CPU(env), 1);
- }
- cpu_synchronize_post_init(ENV_GET_CPU(env));
- return 8;
- default:
- return 0;
- }
-}
-
-/* the values represent the positions in s390-virt.xml */
-#define S390_VIRT_CKC_REGNUM 0
-#define S390_VIRT_CPUTM_REGNUM 1
-#define S390_VIRT_BEA_REGNUM 2
-#define S390_VIRT_PREFIX_REGNUM 3
-#define S390_VIRT_PP_REGNUM 4
-#define S390_VIRT_PFT_REGNUM 5
-#define S390_VIRT_PFS_REGNUM 6
-#define S390_VIRT_PFC_REGNUM 7
-/* total number of registers in s390-virt.xml */
-#define S390_NUM_VIRT_REGS 8
-
-static int cpu_read_virt_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
-{
- switch (n) {
- case S390_VIRT_CKC_REGNUM:
- return gdb_get_regl(mem_buf, env->ckc);
- case S390_VIRT_CPUTM_REGNUM:
- return gdb_get_regl(mem_buf, env->cputm);
- case S390_VIRT_BEA_REGNUM:
- return gdb_get_regl(mem_buf, env->gbea);
- case S390_VIRT_PREFIX_REGNUM:
- return gdb_get_regl(mem_buf, env->psa);
- case S390_VIRT_PP_REGNUM:
- return gdb_get_regl(mem_buf, env->pp);
- case S390_VIRT_PFT_REGNUM:
- return gdb_get_regl(mem_buf, env->pfault_token);
- case S390_VIRT_PFS_REGNUM:
- return gdb_get_regl(mem_buf, env->pfault_select);
- case S390_VIRT_PFC_REGNUM:
- return gdb_get_regl(mem_buf, env->pfault_compare);
- default:
- return 0;
- }
-}
-
-static int cpu_write_virt_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
-{
- switch (n) {
- case S390_VIRT_CKC_REGNUM:
- env->ckc = ldtul_p(mem_buf);
- cpu_synchronize_post_init(ENV_GET_CPU(env));
- return 8;
- case S390_VIRT_CPUTM_REGNUM:
- env->cputm = ldtul_p(mem_buf);
- cpu_synchronize_post_init(ENV_GET_CPU(env));
- return 8;
- case S390_VIRT_BEA_REGNUM:
- env->gbea = ldtul_p(mem_buf);
- cpu_synchronize_post_init(ENV_GET_CPU(env));
- return 8;
- case S390_VIRT_PREFIX_REGNUM:
- env->psa = ldtul_p(mem_buf);
- cpu_synchronize_post_init(ENV_GET_CPU(env));
- return 8;
- case S390_VIRT_PP_REGNUM:
- env->pp = ldtul_p(mem_buf);
- cpu_synchronize_post_init(ENV_GET_CPU(env));
- return 8;
- case S390_VIRT_PFT_REGNUM:
- env->pfault_token = ldtul_p(mem_buf);
- cpu_synchronize_post_init(ENV_GET_CPU(env));
- return 8;
- case S390_VIRT_PFS_REGNUM:
- env->pfault_select = ldtul_p(mem_buf);
- cpu_synchronize_post_init(ENV_GET_CPU(env));
- return 8;
- case S390_VIRT_PFC_REGNUM:
- env->pfault_compare = ldtul_p(mem_buf);
- cpu_synchronize_post_init(ENV_GET_CPU(env));
- return 8;
- default:
- return 0;
- }
-}
-#endif
-
-void s390_cpu_gdb_init(CPUState *cs)
-{
- gdb_register_coprocessor(cs, cpu_read_ac_reg,
- cpu_write_ac_reg,
- S390_NUM_AC_REGS, "s390-acr.xml", 0);
-
- gdb_register_coprocessor(cs, cpu_read_fp_reg,
- cpu_write_fp_reg,
- S390_NUM_FP_REGS, "s390-fpr.xml", 0);
-
- gdb_register_coprocessor(cs, cpu_read_vreg,
- cpu_write_vreg,
- S390_NUM_VREGS, "s390-vx.xml", 0);
-
-#ifndef CONFIG_USER_ONLY
- gdb_register_coprocessor(cs, cpu_read_c_reg,
- cpu_write_c_reg,
- S390_NUM_C_REGS, "s390-cr.xml", 0);
-
- if (kvm_enabled()) {
- gdb_register_coprocessor(cs, cpu_read_virt_reg,
- cpu_write_virt_reg,
- S390_NUM_VIRT_REGS, "s390-virt.xml", 0);
- }
-#endif
-}
diff --git a/qemu/target-s390x/helper.c b/qemu/target-s390x/helper.c
deleted file mode 100644
index 92abe7e67..000000000
--- a/qemu/target-s390x/helper.c
+++ /dev/null
@@ -1,692 +0,0 @@
-/*
- * S/390 helpers
- *
- * Copyright (c) 2009 Ulrich Hecht
- * Copyright (c) 2011 Alexander Graf
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "cpu.h"
-#include "exec/gdbstub.h"
-#include "qemu/timer.h"
-#include "exec/cpu_ldst.h"
-#ifndef CONFIG_USER_ONLY
-#include "sysemu/sysemu.h"
-#endif
-
-//#define DEBUG_S390
-//#define DEBUG_S390_STDOUT
-
-#ifdef DEBUG_S390
-#ifdef DEBUG_S390_STDOUT
-#define DPRINTF(fmt, ...) \
- do { fprintf(stderr, fmt, ## __VA_ARGS__); \
- if (qemu_log_separate()) qemu_log(fmt, ##__VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
- do { qemu_log(fmt, ## __VA_ARGS__); } while (0)
-#endif
-#else
-#define DPRINTF(fmt, ...) \
- do { } while (0)
-#endif
-
-
-#ifndef CONFIG_USER_ONLY
-void s390x_tod_timer(void *opaque)
-{
- S390CPU *cpu = opaque;
- CPUS390XState *env = &cpu->env;
-
- env->pending_int |= INTERRUPT_TOD;
- cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
-}
-
-void s390x_cpu_timer(void *opaque)
-{
- S390CPU *cpu = opaque;
- CPUS390XState *env = &cpu->env;
-
- env->pending_int |= INTERRUPT_CPUTIMER;
- cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
-}
-#endif
-
-S390CPU *cpu_s390x_create(const char *cpu_model, Error **errp)
-{
- S390CPU *cpu;
-
- cpu = S390_CPU(object_new(TYPE_S390_CPU));
-
- return cpu;
-}
-
-S390CPU *s390x_new_cpu(const char *cpu_model, int64_t id, Error **errp)
-{
- S390CPU *cpu;
- Error *err = NULL;
-
- cpu = cpu_s390x_create(cpu_model, &err);
- if (err != NULL) {
- goto out;
- }
-
- object_property_set_int(OBJECT(cpu), id, "id", &err);
- if (err != NULL) {
- goto out;
- }
- object_property_set_bool(OBJECT(cpu), true, "realized", &err);
-
-out:
- if (err) {
- error_propagate(errp, err);
- object_unref(OBJECT(cpu));
- cpu = NULL;
- }
- return cpu;
-}
-
-S390CPU *cpu_s390x_init(const char *cpu_model)
-{
- Error *err = NULL;
- S390CPU *cpu;
- /* Use to track CPU ID for linux-user only */
- static int64_t next_cpu_id;
-
- cpu = s390x_new_cpu(cpu_model, next_cpu_id++, &err);
- if (err) {
- error_report_err(err);
- }
- return cpu;
-}
-
-#if defined(CONFIG_USER_ONLY)
-
-void s390_cpu_do_interrupt(CPUState *cs)
-{
- cs->exception_index = -1;
-}
-
-int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
- int rw, int mmu_idx)
-{
- S390CPU *cpu = S390_CPU(cs);
-
- cs->exception_index = EXCP_PGM;
- cpu->env.int_pgm_code = PGM_ADDRESSING;
- /* On real machines this value is dropped into LowMem. Since this
- is userland, simply put this someplace that cpu_loop can find it. */
- cpu->env.__excp_addr = address;
- return 1;
-}
-
-#else /* !CONFIG_USER_ONLY */
-
-/* Ensure to exit the TB after this call! */
-void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen)
-{
- CPUState *cs = CPU(s390_env_get_cpu(env));
-
- cs->exception_index = EXCP_PGM;
- env->int_pgm_code = code;
- env->int_pgm_ilen = ilen;
-}
-
-int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr,
- int rw, int mmu_idx)
-{
- S390CPU *cpu = S390_CPU(cs);
- CPUS390XState *env = &cpu->env;
- uint64_t asc = cpu_mmu_idx_to_asc(mmu_idx);
- target_ulong vaddr, raddr;
- int prot;
-
- DPRINTF("%s: address 0x%" VADDR_PRIx " rw %d mmu_idx %d\n",
- __func__, orig_vaddr, rw, mmu_idx);
-
- orig_vaddr &= TARGET_PAGE_MASK;
- vaddr = orig_vaddr;
-
- /* 31-Bit mode */
- if (!(env->psw.mask & PSW_MASK_64)) {
- vaddr &= 0x7fffffff;
- }
-
- if (mmu_translate(env, vaddr, rw, asc, &raddr, &prot, true)) {
- /* Translation ended in exception */
- return 1;
- }
-
- /* check out of RAM access */
- if (raddr > ram_size) {
- DPRINTF("%s: raddr %" PRIx64 " > ram_size %" PRIx64 "\n", __func__,
- (uint64_t)raddr, (uint64_t)ram_size);
- trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_LATER);
- return 1;
- }
-
- qemu_log_mask(CPU_LOG_MMU, "%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x)\n",
- __func__, (uint64_t)vaddr, (uint64_t)raddr, prot);
-
- tlb_set_page(cs, orig_vaddr, raddr, prot,
- mmu_idx, TARGET_PAGE_SIZE);
-
- return 0;
-}
-
-hwaddr s390_cpu_get_phys_page_debug(CPUState *cs, vaddr vaddr)
-{
- S390CPU *cpu = S390_CPU(cs);
- CPUS390XState *env = &cpu->env;
- target_ulong raddr;
- int prot;
- uint64_t asc = env->psw.mask & PSW_MASK_ASC;
-
- /* 31-Bit mode */
- if (!(env->psw.mask & PSW_MASK_64)) {
- vaddr &= 0x7fffffff;
- }
-
- if (mmu_translate(env, vaddr, MMU_INST_FETCH, asc, &raddr, &prot, false)) {
- return -1;
- }
- return raddr;
-}
-
-hwaddr s390_cpu_get_phys_addr_debug(CPUState *cs, vaddr vaddr)
-{
- hwaddr phys_addr;
- target_ulong page;
-
- page = vaddr & TARGET_PAGE_MASK;
- phys_addr = cpu_get_phys_page_debug(cs, page);
- phys_addr += (vaddr & ~TARGET_PAGE_MASK);
-
- return phys_addr;
-}
-
-void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
-{
- uint64_t old_mask = env->psw.mask;
-
- env->psw.addr = addr;
- env->psw.mask = mask;
- if (tcg_enabled()) {
- env->cc_op = (mask >> 44) & 3;
- }
-
- if ((old_mask ^ mask) & PSW_MASK_PER) {
- s390_cpu_recompute_watchpoints(CPU(s390_env_get_cpu(env)));
- }
-
- if (mask & PSW_MASK_WAIT) {
- S390CPU *cpu = s390_env_get_cpu(env);
- if (s390_cpu_halt(cpu) == 0) {
-#ifndef CONFIG_USER_ONLY
- qemu_system_shutdown_request();
-#endif
- }
- }
-}
-
-static uint64_t get_psw_mask(CPUS390XState *env)
-{
- uint64_t r = env->psw.mask;
-
- if (tcg_enabled()) {
- env->cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst,
- env->cc_vr);
-
- r &= ~PSW_MASK_CC;
- assert(!(env->cc_op & ~3));
- r |= (uint64_t)env->cc_op << 44;
- }
-
- return r;
-}
-
-static LowCore *cpu_map_lowcore(CPUS390XState *env)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- LowCore *lowcore;
- hwaddr len = sizeof(LowCore);
-
- lowcore = cpu_physical_memory_map(env->psa, &len, 1);
-
- if (len < sizeof(LowCore)) {
- cpu_abort(CPU(cpu), "Could not map lowcore\n");
- }
-
- return lowcore;
-}
-
-static void cpu_unmap_lowcore(LowCore *lowcore)
-{
- cpu_physical_memory_unmap(lowcore, sizeof(LowCore), 1, sizeof(LowCore));
-}
-
-void do_restart_interrupt(CPUS390XState *env)
-{
- uint64_t mask, addr;
- LowCore *lowcore;
-
- lowcore = cpu_map_lowcore(env);
-
- lowcore->restart_old_psw.mask = cpu_to_be64(get_psw_mask(env));
- lowcore->restart_old_psw.addr = cpu_to_be64(env->psw.addr);
- mask = be64_to_cpu(lowcore->restart_new_psw.mask);
- addr = be64_to_cpu(lowcore->restart_new_psw.addr);
-
- cpu_unmap_lowcore(lowcore);
-
- load_psw(env, mask, addr);
-}
-
-static void do_program_interrupt(CPUS390XState *env)
-{
- uint64_t mask, addr;
- LowCore *lowcore;
- int ilen = env->int_pgm_ilen;
-
- switch (ilen) {
- case ILEN_LATER:
- ilen = get_ilen(cpu_ldub_code(env, env->psw.addr));
- break;
- case ILEN_LATER_INC:
- ilen = get_ilen(cpu_ldub_code(env, env->psw.addr));
- env->psw.addr += ilen;
- break;
- default:
- assert(ilen == 2 || ilen == 4 || ilen == 6);
- }
-
- qemu_log_mask(CPU_LOG_INT, "%s: code=0x%x ilen=%d\n",
- __func__, env->int_pgm_code, ilen);
-
- lowcore = cpu_map_lowcore(env);
-
- /* Signal PER events with the exception. */
- if (env->per_perc_atmid) {
- env->int_pgm_code |= PGM_PER;
- lowcore->per_address = cpu_to_be64(env->per_address);
- lowcore->per_perc_atmid = cpu_to_be16(env->per_perc_atmid);
- env->per_perc_atmid = 0;
- }
-
- lowcore->pgm_ilen = cpu_to_be16(ilen);
- lowcore->pgm_code = cpu_to_be16(env->int_pgm_code);
- lowcore->program_old_psw.mask = cpu_to_be64(get_psw_mask(env));
- lowcore->program_old_psw.addr = cpu_to_be64(env->psw.addr);
- mask = be64_to_cpu(lowcore->program_new_psw.mask);
- addr = be64_to_cpu(lowcore->program_new_psw.addr);
- lowcore->per_breaking_event_addr = cpu_to_be64(env->gbea);
-
- cpu_unmap_lowcore(lowcore);
-
- DPRINTF("%s: %x %x %" PRIx64 " %" PRIx64 "\n", __func__,
- env->int_pgm_code, ilen, env->psw.mask,
- env->psw.addr);
-
- load_psw(env, mask, addr);
-}
-
-static void do_svc_interrupt(CPUS390XState *env)
-{
- uint64_t mask, addr;
- LowCore *lowcore;
-
- lowcore = cpu_map_lowcore(env);
-
- lowcore->svc_code = cpu_to_be16(env->int_svc_code);
- lowcore->svc_ilen = cpu_to_be16(env->int_svc_ilen);
- lowcore->svc_old_psw.mask = cpu_to_be64(get_psw_mask(env));
- lowcore->svc_old_psw.addr = cpu_to_be64(env->psw.addr + env->int_svc_ilen);
- mask = be64_to_cpu(lowcore->svc_new_psw.mask);
- addr = be64_to_cpu(lowcore->svc_new_psw.addr);
-
- cpu_unmap_lowcore(lowcore);
-
- load_psw(env, mask, addr);
-
- /* When a PER event is pending, the PER exception has to happen
- immediately after the SERVICE CALL one. */
- if (env->per_perc_atmid) {
- env->int_pgm_code = PGM_PER;
- env->int_pgm_ilen = env->int_svc_ilen;
- do_program_interrupt(env);
- }
-}
-
-#define VIRTIO_SUBCODE_64 0x0D00
-
-static void do_ext_interrupt(CPUS390XState *env)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- uint64_t mask, addr;
- LowCore *lowcore;
- ExtQueue *q;
-
- if (!(env->psw.mask & PSW_MASK_EXT)) {
- cpu_abort(CPU(cpu), "Ext int w/o ext mask\n");
- }
-
- if (env->ext_index < 0 || env->ext_index >= MAX_EXT_QUEUE) {
- cpu_abort(CPU(cpu), "Ext queue overrun: %d\n", env->ext_index);
- }
-
- q = &env->ext_queue[env->ext_index];
- lowcore = cpu_map_lowcore(env);
-
- lowcore->ext_int_code = cpu_to_be16(q->code);
- lowcore->ext_params = cpu_to_be32(q->param);
- lowcore->ext_params2 = cpu_to_be64(q->param64);
- lowcore->external_old_psw.mask = cpu_to_be64(get_psw_mask(env));
- lowcore->external_old_psw.addr = cpu_to_be64(env->psw.addr);
- lowcore->cpu_addr = cpu_to_be16(env->cpu_num | VIRTIO_SUBCODE_64);
- mask = be64_to_cpu(lowcore->external_new_psw.mask);
- addr = be64_to_cpu(lowcore->external_new_psw.addr);
-
- cpu_unmap_lowcore(lowcore);
-
- env->ext_index--;
- if (env->ext_index == -1) {
- env->pending_int &= ~INTERRUPT_EXT;
- }
-
- DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__,
- env->psw.mask, env->psw.addr);
-
- load_psw(env, mask, addr);
-}
-
-static void do_io_interrupt(CPUS390XState *env)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- LowCore *lowcore;
- IOIntQueue *q;
- uint8_t isc;
- int disable = 1;
- int found = 0;
-
- if (!(env->psw.mask & PSW_MASK_IO)) {
- cpu_abort(CPU(cpu), "I/O int w/o I/O mask\n");
- }
-
- for (isc = 0; isc < ARRAY_SIZE(env->io_index); isc++) {
- uint64_t isc_bits;
-
- if (env->io_index[isc] < 0) {
- continue;
- }
- if (env->io_index[isc] >= MAX_IO_QUEUE) {
- cpu_abort(CPU(cpu), "I/O queue overrun for isc %d: %d\n",
- isc, env->io_index[isc]);
- }
-
- q = &env->io_queue[env->io_index[isc]][isc];
- isc_bits = ISC_TO_ISC_BITS(IO_INT_WORD_ISC(q->word));
- if (!(env->cregs[6] & isc_bits)) {
- disable = 0;
- continue;
- }
- if (!found) {
- uint64_t mask, addr;
-
- found = 1;
- lowcore = cpu_map_lowcore(env);
-
- lowcore->subchannel_id = cpu_to_be16(q->id);
- lowcore->subchannel_nr = cpu_to_be16(q->nr);
- lowcore->io_int_parm = cpu_to_be32(q->parm);
- lowcore->io_int_word = cpu_to_be32(q->word);
- lowcore->io_old_psw.mask = cpu_to_be64(get_psw_mask(env));
- lowcore->io_old_psw.addr = cpu_to_be64(env->psw.addr);
- mask = be64_to_cpu(lowcore->io_new_psw.mask);
- addr = be64_to_cpu(lowcore->io_new_psw.addr);
-
- cpu_unmap_lowcore(lowcore);
-
- env->io_index[isc]--;
-
- DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__,
- env->psw.mask, env->psw.addr);
- load_psw(env, mask, addr);
- }
- if (env->io_index[isc] >= 0) {
- disable = 0;
- }
- continue;
- }
-
- if (disable) {
- env->pending_int &= ~INTERRUPT_IO;
- }
-
-}
-
-static void do_mchk_interrupt(CPUS390XState *env)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- uint64_t mask, addr;
- LowCore *lowcore;
- MchkQueue *q;
- int i;
-
- if (!(env->psw.mask & PSW_MASK_MCHECK)) {
- cpu_abort(CPU(cpu), "Machine check w/o mchk mask\n");
- }
-
- if (env->mchk_index < 0 || env->mchk_index >= MAX_MCHK_QUEUE) {
- cpu_abort(CPU(cpu), "Mchk queue overrun: %d\n", env->mchk_index);
- }
-
- q = &env->mchk_queue[env->mchk_index];
-
- if (q->type != 1) {
- /* Don't know how to handle this... */
- cpu_abort(CPU(cpu), "Unknown machine check type %d\n", q->type);
- }
- if (!(env->cregs[14] & (1 << 28))) {
- /* CRW machine checks disabled */
- return;
- }
-
- lowcore = cpu_map_lowcore(env);
-
- for (i = 0; i < 16; i++) {
- lowcore->floating_pt_save_area[i] = cpu_to_be64(get_freg(env, i)->ll);
- lowcore->gpregs_save_area[i] = cpu_to_be64(env->regs[i]);
- lowcore->access_regs_save_area[i] = cpu_to_be32(env->aregs[i]);
- lowcore->cregs_save_area[i] = cpu_to_be64(env->cregs[i]);
- }
- lowcore->prefixreg_save_area = cpu_to_be32(env->psa);
- lowcore->fpt_creg_save_area = cpu_to_be32(env->fpc);
- lowcore->tod_progreg_save_area = cpu_to_be32(env->todpr);
- lowcore->cpu_timer_save_area[0] = cpu_to_be32(env->cputm >> 32);
- lowcore->cpu_timer_save_area[1] = cpu_to_be32((uint32_t)env->cputm);
- lowcore->clock_comp_save_area[0] = cpu_to_be32(env->ckc >> 32);
- lowcore->clock_comp_save_area[1] = cpu_to_be32((uint32_t)env->ckc);
-
- lowcore->mcck_interruption_code[0] = cpu_to_be32(0x00400f1d);
- lowcore->mcck_interruption_code[1] = cpu_to_be32(0x40330000);
- lowcore->mcck_old_psw.mask = cpu_to_be64(get_psw_mask(env));
- lowcore->mcck_old_psw.addr = cpu_to_be64(env->psw.addr);
- mask = be64_to_cpu(lowcore->mcck_new_psw.mask);
- addr = be64_to_cpu(lowcore->mcck_new_psw.addr);
-
- cpu_unmap_lowcore(lowcore);
-
- env->mchk_index--;
- if (env->mchk_index == -1) {
- env->pending_int &= ~INTERRUPT_MCHK;
- }
-
- DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__,
- env->psw.mask, env->psw.addr);
-
- load_psw(env, mask, addr);
-}
-
-void s390_cpu_do_interrupt(CPUState *cs)
-{
- S390CPU *cpu = S390_CPU(cs);
- CPUS390XState *env = &cpu->env;
-
- qemu_log_mask(CPU_LOG_INT, "%s: %d at pc=%" PRIx64 "\n",
- __func__, cs->exception_index, env->psw.addr);
-
- s390_cpu_set_state(CPU_STATE_OPERATING, cpu);
- /* handle machine checks */
- if ((env->psw.mask & PSW_MASK_MCHECK) &&
- (cs->exception_index == -1)) {
- if (env->pending_int & INTERRUPT_MCHK) {
- cs->exception_index = EXCP_MCHK;
- }
- }
- /* handle external interrupts */
- if ((env->psw.mask & PSW_MASK_EXT) &&
- cs->exception_index == -1) {
- if (env->pending_int & INTERRUPT_EXT) {
- /* code is already in env */
- cs->exception_index = EXCP_EXT;
- } else if (env->pending_int & INTERRUPT_TOD) {
- cpu_inject_ext(cpu, 0x1004, 0, 0);
- cs->exception_index = EXCP_EXT;
- env->pending_int &= ~INTERRUPT_EXT;
- env->pending_int &= ~INTERRUPT_TOD;
- } else if (env->pending_int & INTERRUPT_CPUTIMER) {
- cpu_inject_ext(cpu, 0x1005, 0, 0);
- cs->exception_index = EXCP_EXT;
- env->pending_int &= ~INTERRUPT_EXT;
- env->pending_int &= ~INTERRUPT_TOD;
- }
- }
- /* handle I/O interrupts */
- if ((env->psw.mask & PSW_MASK_IO) &&
- (cs->exception_index == -1)) {
- if (env->pending_int & INTERRUPT_IO) {
- cs->exception_index = EXCP_IO;
- }
- }
-
- switch (cs->exception_index) {
- case EXCP_PGM:
- do_program_interrupt(env);
- break;
- case EXCP_SVC:
- do_svc_interrupt(env);
- break;
- case EXCP_EXT:
- do_ext_interrupt(env);
- break;
- case EXCP_IO:
- do_io_interrupt(env);
- break;
- case EXCP_MCHK:
- do_mchk_interrupt(env);
- break;
- }
- cs->exception_index = -1;
-
- if (!env->pending_int) {
- cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
- }
-}
-
-bool s390_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
-{
- if (interrupt_request & CPU_INTERRUPT_HARD) {
- S390CPU *cpu = S390_CPU(cs);
- CPUS390XState *env = &cpu->env;
-
- if (env->psw.mask & PSW_MASK_EXT) {
- s390_cpu_do_interrupt(cs);
- return true;
- }
- }
- return false;
-}
-
-void s390_cpu_recompute_watchpoints(CPUState *cs)
-{
- const int wp_flags = BP_CPU | BP_MEM_WRITE | BP_STOP_BEFORE_ACCESS;
- S390CPU *cpu = S390_CPU(cs);
- CPUS390XState *env = &cpu->env;
-
- /* We are called when the watchpoints have changed. First
- remove them all. */
- cpu_watchpoint_remove_all(cs, BP_CPU);
-
- /* Return if PER is not enabled */
- if (!(env->psw.mask & PSW_MASK_PER)) {
- return;
- }
-
- /* Return if storage-alteration event is not enabled. */
- if (!(env->cregs[9] & PER_CR9_EVENT_STORE)) {
- return;
- }
-
- if (env->cregs[10] == 0 && env->cregs[11] == -1LL) {
- /* We can't create a watchoint spanning the whole memory range, so
- split it in two parts. */
- cpu_watchpoint_insert(cs, 0, 1ULL << 63, wp_flags, NULL);
- cpu_watchpoint_insert(cs, 1ULL << 63, 1ULL << 63, wp_flags, NULL);
- } else if (env->cregs[10] > env->cregs[11]) {
- /* The address range loops, create two watchpoints. */
- cpu_watchpoint_insert(cs, env->cregs[10], -env->cregs[10],
- wp_flags, NULL);
- cpu_watchpoint_insert(cs, 0, env->cregs[11] + 1, wp_flags, NULL);
-
- } else {
- /* Default case, create a single watchpoint. */
- cpu_watchpoint_insert(cs, env->cregs[10],
- env->cregs[11] - env->cregs[10] + 1,
- wp_flags, NULL);
- }
-}
-
-void s390x_cpu_debug_excp_handler(CPUState *cs)
-{
- S390CPU *cpu = S390_CPU(cs);
- CPUS390XState *env = &cpu->env;
- CPUWatchpoint *wp_hit = cs->watchpoint_hit;
-
- if (wp_hit && wp_hit->flags & BP_CPU) {
- /* FIXME: When the storage-alteration-space control bit is set,
- the exception should only be triggered if the memory access
- is done using an address space with the storage-alteration-event
- bit set. We have no way to detect that with the current
- watchpoint code. */
- cs->watchpoint_hit = NULL;
-
- env->per_address = env->psw.addr;
- env->per_perc_atmid |= PER_CODE_EVENT_STORE | get_per_atmid(env);
- /* FIXME: We currently no way to detect the address space used
- to trigger the watchpoint. For now just consider it is the
- current default ASC. This turn to be true except when MVCP
- and MVCS instrutions are not used. */
- env->per_perc_atmid |= env->psw.mask & (PSW_MASK_ASC) >> 46;
-
- /* Remove all watchpoints to re-execute the code. A PER exception
- will be triggered, it will call load_psw which will recompute
- the watchpoints. */
- cpu_watchpoint_remove_all(cs, BP_CPU);
- cpu_resume_from_signal(cs, NULL);
- }
-}
-#endif /* CONFIG_USER_ONLY */
diff --git a/qemu/target-s390x/helper.h b/qemu/target-s390x/helper.h
deleted file mode 100644
index 7e06119e9..000000000
--- a/qemu/target-s390x/helper.h
+++ /dev/null
@@ -1,133 +0,0 @@
-DEF_HELPER_2(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)
-DEF_HELPER_FLAGS_4(mvc, TCG_CALL_NO_WG, void, env, i32, i64, i64)
-DEF_HELPER_FLAGS_4(clc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
-DEF_HELPER_3(mvcl, i32, env, i32, i32)
-DEF_HELPER_FLAGS_4(clm, TCG_CALL_NO_WG, i32, env, i32, i32, i64)
-DEF_HELPER_FLAGS_3(divs32, TCG_CALL_NO_WG, s64, env, s64, s64)
-DEF_HELPER_FLAGS_3(divu32, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_3(divs64, TCG_CALL_NO_WG, s64, env, s64, s64)
-DEF_HELPER_FLAGS_4(divu64, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
-DEF_HELPER_4(srst, i64, env, i64, i64, i64)
-DEF_HELPER_4(clst, i64, env, i64, i64, i64)
-DEF_HELPER_4(mvpg, void, env, i64, i64, i64)
-DEF_HELPER_4(mvst, i64, env, i64, i64, i64)
-DEF_HELPER_5(ex, i32, env, i32, i64, i64, i64)
-DEF_HELPER_FLAGS_4(stam, TCG_CALL_NO_WG, void, env, i32, i64, i32)
-DEF_HELPER_FLAGS_4(lam, TCG_CALL_NO_WG, void, env, i32, i64, i32)
-DEF_HELPER_4(mvcle, i32, env, i32, i64, i32)
-DEF_HELPER_4(clcle, i32, env, i32, i64, i32)
-DEF_HELPER_3(cegb, i64, env, s64, i32)
-DEF_HELPER_3(cdgb, i64, env, s64, i32)
-DEF_HELPER_3(cxgb, i64, env, s64, i32)
-DEF_HELPER_3(celgb, i64, env, i64, i32)
-DEF_HELPER_3(cdlgb, i64, env, i64, i32)
-DEF_HELPER_3(cxlgb, i64, env, i64, i32)
-DEF_HELPER_FLAGS_3(aeb, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_3(adb, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_5(axb, TCG_CALL_NO_WG, i64, env, i64, i64, i64, i64)
-DEF_HELPER_FLAGS_3(seb, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_3(sdb, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_5(sxb, TCG_CALL_NO_WG, i64, env, i64, i64, i64, i64)
-DEF_HELPER_FLAGS_3(deb, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_3(ddb, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_5(dxb, TCG_CALL_NO_WG, i64, env, i64, i64, i64, i64)
-DEF_HELPER_FLAGS_3(meeb, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_3(mdeb, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_3(mdb, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_5(mxb, TCG_CALL_NO_WG, i64, env, i64, i64, i64, i64)
-DEF_HELPER_FLAGS_4(mxdb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
-DEF_HELPER_FLAGS_2(ldeb, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_3(ldxb, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_2(lxdb, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_2(lxeb, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_2(ledb, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_3(lexb, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_3(ceb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
-DEF_HELPER_FLAGS_3(cdb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
-DEF_HELPER_FLAGS_5(cxb, TCG_CALL_NO_WG_SE, i32, env, i64, i64, i64, i64)
-DEF_HELPER_FLAGS_3(cgeb, TCG_CALL_NO_WG, i64, env, i64, i32)
-DEF_HELPER_FLAGS_3(cgdb, TCG_CALL_NO_WG, i64, env, i64, i32)
-DEF_HELPER_FLAGS_4(cgxb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
-DEF_HELPER_FLAGS_3(cfeb, TCG_CALL_NO_WG, i64, env, i64, i32)
-DEF_HELPER_FLAGS_3(cfdb, TCG_CALL_NO_WG, i64, env, i64, i32)
-DEF_HELPER_FLAGS_4(cfxb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
-DEF_HELPER_FLAGS_3(clgeb, TCG_CALL_NO_WG, i64, env, i64, i32)
-DEF_HELPER_FLAGS_3(clgdb, TCG_CALL_NO_WG, i64, env, i64, i32)
-DEF_HELPER_FLAGS_4(clgxb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
-DEF_HELPER_FLAGS_3(clfeb, TCG_CALL_NO_WG, i64, env, i64, i32)
-DEF_HELPER_FLAGS_3(clfdb, TCG_CALL_NO_WG, i64, env, i64, i32)
-DEF_HELPER_FLAGS_4(clfxb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
-DEF_HELPER_FLAGS_3(fieb, TCG_CALL_NO_WG, i64, env, i64, i32)
-DEF_HELPER_FLAGS_3(fidb, TCG_CALL_NO_WG, i64, env, i64, i32)
-DEF_HELPER_FLAGS_4(fixb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
-DEF_HELPER_FLAGS_4(maeb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
-DEF_HELPER_FLAGS_4(madb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
-DEF_HELPER_FLAGS_4(mseb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
-DEF_HELPER_FLAGS_4(msdb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
-DEF_HELPER_FLAGS_2(tceb, TCG_CALL_NO_RWG_SE, i32, i64, i64)
-DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_NO_RWG_SE, i32, i64, i64)
-DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_NO_RWG_SE, i32, i64, i64, i64)
-DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, i64, i64)
-DEF_HELPER_FLAGS_2(sqeb, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_2(sqdb, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_3(sqxb, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32)
-DEF_HELPER_FLAGS_4(unpk, TCG_CALL_NO_WG, void, env, i32, i64, i64)
-DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64)
-DEF_HELPER_4(tre, i64, env, i64, i64, i64)
-DEF_HELPER_4(trt, i32, env, i32, i64, i64)
-DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
-DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
-DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64)
-DEF_HELPER_FLAGS_2(sfas, TCG_CALL_NO_WG, void, env, i64)
-DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_NO_RWG_SE, i64, i64)
-
-#ifndef CONFIG_USER_ONLY
-DEF_HELPER_3(servc, i32, env, i64, i64)
-DEF_HELPER_4(diag, void, env, i32, i32, i32)
-DEF_HELPER_3(load_psw, noreturn, env, i64, i64)
-DEF_HELPER_FLAGS_2(spx, TCG_CALL_NO_RWG, void, env, i64)
-DEF_HELPER_FLAGS_1(stck, TCG_CALL_NO_RWG_SE, i64, env)
-DEF_HELPER_FLAGS_2(sckc, TCG_CALL_NO_RWG, void, env, i64)
-DEF_HELPER_FLAGS_1(stckc, TCG_CALL_NO_RWG, i64, env)
-DEF_HELPER_FLAGS_2(spt, TCG_CALL_NO_RWG, void, env, i64)
-DEF_HELPER_FLAGS_1(stpt, TCG_CALL_NO_RWG, i64, env)
-DEF_HELPER_4(stsi, i32, env, i64, i64, i64)
-DEF_HELPER_FLAGS_4(lctl, TCG_CALL_NO_WG, void, env, i32, i64, i32)
-DEF_HELPER_FLAGS_4(lctlg, TCG_CALL_NO_WG, void, env, i32, i64, i32)
-DEF_HELPER_FLAGS_4(stctl, TCG_CALL_NO_WG, void, env, i32, i64, i32)
-DEF_HELPER_FLAGS_4(stctg, TCG_CALL_NO_WG, void, env, i32, i64, i32)
-DEF_HELPER_FLAGS_2(tprot, TCG_CALL_NO_RWG, i32, i64, i64)
-DEF_HELPER_FLAGS_2(iske, TCG_CALL_NO_RWG_SE, i64, env, i64)
-DEF_HELPER_FLAGS_3(sske, TCG_CALL_NO_RWG, void, env, i64, i64)
-DEF_HELPER_FLAGS_2(rrbe, TCG_CALL_NO_RWG, i32, env, i64)
-DEF_HELPER_3(csp, i32, env, i32, i64)
-DEF_HELPER_4(mvcs, i32, env, i64, i64, i64)
-DEF_HELPER_4(mvcp, i32, env, i64, i64, i64)
-DEF_HELPER_4(sigp, i32, env, i64, i32, i64)
-DEF_HELPER_FLAGS_2(sacf, TCG_CALL_NO_WG, void, env, i64)
-DEF_HELPER_FLAGS_3(ipte, TCG_CALL_NO_RWG, void, env, i64, i64)
-DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_NO_RWG, void, env)
-DEF_HELPER_2(lra, i64, env, i64)
-DEF_HELPER_FLAGS_2(lura, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_2(lurag, TCG_CALL_NO_WG, i64, env, i64)
-DEF_HELPER_FLAGS_3(stura, TCG_CALL_NO_WG, void, env, i64, i64)
-DEF_HELPER_FLAGS_3(sturg, TCG_CALL_NO_WG, void, env, i64, i64)
-DEF_HELPER_1(per_check_exception, void, env)
-DEF_HELPER_FLAGS_3(per_branch, TCG_CALL_NO_RWG, void, env, i64, i64)
-DEF_HELPER_FLAGS_2(per_ifetch, TCG_CALL_NO_RWG, void, env, i64)
-
-DEF_HELPER_2(xsch, void, env, i64)
-DEF_HELPER_2(csch, void, env, i64)
-DEF_HELPER_2(hsch, void, env, i64)
-DEF_HELPER_3(msch, void, env, i64, i64)
-DEF_HELPER_2(rchp, void, env, i64)
-DEF_HELPER_2(rsch, void, env, i64)
-DEF_HELPER_3(ssch, void, env, i64, i64)
-DEF_HELPER_3(stsch, void, env, i64, i64)
-DEF_HELPER_3(tsch, void, env, i64, i64)
-DEF_HELPER_2(chsc, void, env, i64)
-#endif
diff --git a/qemu/target-s390x/insn-data.def b/qemu/target-s390x/insn-data.def
deleted file mode 100644
index 075ff597c..000000000
--- a/qemu/target-s390x/insn-data.def
+++ /dev/null
@@ -1,931 +0,0 @@
-/*
- * Arguments to the opcode prototypes
- *
- * C(OPC, NAME, FMT, FAC, I1, I2, P, W, OP, CC)
- * D(OPC, NAME, FMT, FAC, I1, I2, P, W, OP, CC, DATA)
- *
- * OPC = (op << 8) | op2 where op is the major, op2 the minor opcode
- * NAME = name of the opcode, used internally
- * FMT = format of the opcode (defined in insn-format.def)
- * FAC = facility the opcode is available in (defined in DisasFacility)
- * I1 = func in1_xx fills o->in1
- * I2 = func in2_xx fills o->in2
- * P = func prep_xx initializes o->*out*
- * W = func wout_xx writes o->*out* somewhere
- * 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
- *
- * The helpers get called in order: I1, I2, P, OP, W, CC
- */
-
-/* ADD */
- C(0x1a00, AR, RR_a, Z, r1, r2, new, r1_32, add, adds32)
- C(0xb9f8, ARK, RRF_a, DO, r2, r3, new, r1_32, add, adds32)
- C(0x5a00, A, RX_a, Z, r1, m2_32s, new, r1_32, add, adds32)
- C(0xe35a, AY, RXY_a, LD, r1, m2_32s, new, r1_32, add, adds32)
- C(0xb908, AGR, RRE, Z, r1, r2, r1, 0, add, adds64)
- C(0xb918, AGFR, RRE, Z, r1, r2_32s, 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(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)
-/* 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)
-/* ADD IMMEDIATE */
- C(0xc209, AFI, RIL_a, EI, r1, i2, new, r1_32, add, adds32)
- C(0xeb6a, ASI, SIY, GIE, m1_32s, i2, new, m1_32, add, adds32)
- C(0xecd8, AHIK, RIE_d, DO, r3, i2, new, r1_32, add, adds32)
- C(0xc208, AGFI, RIL_a, EI, r1, i2, r1, 0, add, adds64)
- C(0xeb7a, AGSI, SIY, GIE, m1_64, i2, new, m1_64, add, adds64)
- C(0xecd9, AGHIK, RIE_d, DO, r3, i2, r1, 0, add, adds64)
-/* ADD IMMEDIATE HIGH */
- C(0xcc08, AIH, RIL_a, HW, r1_sr32, i2, new, r1_32h, add, adds32)
-/* ADD HALFWORD */
- C(0x4a00, AH, RX_a, Z, r1, m2_16s, new, r1_32, add, adds32)
- C(0xe37a, AHY, RXY_a, LD, r1, m2_16s, new, r1_32, add, adds32)
-/* ADD HALFWORD IMMEDIATE */
- C(0xa70a, AHI, RI_a, Z, r1, i2, new, r1_32, add, adds32)
- C(0xa70b, AGHI, RI_a, Z, r1, i2, r1, 0, add, adds64)
-
-/* ADD LOGICAL */
- C(0x1e00, ALR, RR_a, Z, r1, r2, new, r1_32, add, addu32)
- C(0xb9fa, ALRK, RRF_a, DO, r2, r3, new, r1_32, add, addu32)
- C(0x5e00, AL, RX_a, Z, r1, m2_32u, new, r1_32, add, addu32)
- C(0xe35e, ALY, RXY_a, LD, r1, m2_32u, new, r1_32, add, addu32)
- C(0xb90a, ALGR, RRE, Z, r1, r2, r1, 0, add, addu64)
- C(0xb91a, ALGFR, RRE, Z, r1, r2_32u, r1, 0, add, addu64)
- C(0xb9ea, ALGRK, RRF_a, DO, r2, r3, r1, 0, add, addu64)
- C(0xe30a, ALG, RXY_a, Z, r1, m2_64, r1, 0, add, addu64)
- C(0xe31a, ALGF, RXY_a, Z, r1, m2_32u, r1, 0, add, addu64)
-/* ADD LOGICAL HIGH */
- C(0xb9ca, ALHHHR, RRF_a, HW, r2_sr32, r3_sr32, new, r1_32h, add, addu32)
- C(0xb9da, ALHHLR, RRF_a, HW, r2_sr32, r3, new, r1_32h, add, addu32)
-/* ADD LOGICAL IMMEDIATE */
- C(0xc20b, ALFI, RIL_a, EI, r1, i2_32u, new, r1_32, add, addu32)
- C(0xc20a, ALGFI, RIL_a, EI, r1, i2_32u, r1, 0, add, addu64)
-/* ADD LOGICAL WITH SIGNED IMMEDIATE */
- C(0xeb6e, ALSI, SIY, GIE, m1_32u, i2, new, m1_32, add, addu32)
- C(0xecda, ALHSIK, RIE_d, DO, r3, i2, new, r1_32, add, addu32)
- C(0xeb7e, ALGSI, SIY, GIE, m1_64, i2, new, m1_64, add, addu64)
- C(0xecdb, ALGHSIK, RIE_d, DO, r3, i2, r1, 0, add, addu64)
-/* ADD LOGICAL WITH SIGNED IMMEDIATE HIGH */
- C(0xcc0a, ALSIH, RIL_a, HW, r1_sr32, i2, new, r1_32h, add, addu32)
- C(0xcc0b, ALSIHN, RIL_a, HW, r1_sr32, i2, new, r1_32h, add, 0)
-/* ADD LOGICAL WITH CARRY */
- C(0xb998, ALCR, RRE, Z, r1, r2, new, r1_32, addc, addc32)
- C(0xb988, ALCGR, RRE, Z, r1, r2, r1, 0, addc, addc64)
- C(0xe398, ALC, RXY_a, Z, r1, m2_32u, new, r1_32, addc, addc32)
- C(0xe388, ALCG, RXY_a, Z, r1, m2_64, r1, 0, addc, addc64)
-
-/* AND */
- C(0x1400, NR, RR_a, Z, r1, r2, new, r1_32, and, nz32)
- C(0xb9f4, NRK, RRF_a, DO, r2, r3, new, r1_32, and, nz32)
- C(0x5400, N, RX_a, Z, r1, m2_32s, new, r1_32, and, nz32)
- C(0xe354, NY, RXY_a, LD, r1, m2_32s, new, r1_32, and, nz32)
- C(0xb980, NGR, RRE, Z, r1, r2, r1, 0, and, nz64)
- C(0xb9e4, NGRK, RRF_a, DO, r2, r3, r1, 0, and, nz64)
- C(0xe380, NG, RXY_a, Z, r1, m2_64, r1, 0, and, nz64)
- C(0xd400, NC, SS_a, Z, la1, a2, 0, 0, nc, 0)
-/* AND IMMEDIATE */
- D(0xc00a, NIHF, RIL_a, EI, r1_o, i2_32u, r1, 0, andi, 0, 0x2020)
- D(0xc00b, NILF, RIL_a, EI, r1_o, i2_32u, r1, 0, andi, 0, 0x2000)
- D(0xa504, NIHH, RI_a, Z, r1_o, i2_16u, r1, 0, andi, 0, 0x1030)
- D(0xa505, NIHL, RI_a, Z, r1_o, i2_16u, r1, 0, andi, 0, 0x1020)
- D(0xa506, NILH, RI_a, Z, r1_o, i2_16u, r1, 0, andi, 0, 0x1010)
- D(0xa507, NILL, RI_a, Z, r1_o, i2_16u, r1, 0, andi, 0, 0x1000)
- C(0x9400, NI, SI, Z, m1_8u, i2_8u, new, m1_8, and, nz64)
- C(0xeb54, NIY, SIY, LD, m1_8u, i2_8u, new, m1_8, and, nz64)
-
-/* BRANCH AND SAVE */
- C(0x0d00, BASR, RR_a, Z, 0, r2_nz, r1, 0, bas, 0)
- C(0x4d00, BAS, RX_a, Z, 0, a2, r1, 0, bas, 0)
-/* BRANCH RELATIVE AND SAVE */
- C(0xa705, BRAS, RI_b, Z, 0, 0, r1, 0, basi, 0)
- C(0xc005, BRASL, RIL_b, Z, 0, 0, r1, 0, basi, 0)
-/* BRANCH ON CONDITION */
- C(0x0700, BCR, RR_b, Z, 0, r2_nz, 0, 0, bc, 0)
- C(0x4700, BC, RX_b, Z, 0, a2, 0, 0, bc, 0)
-/* BRANCH RELATIVE ON CONDITION */
- C(0xa704, BRC, RI_c, Z, 0, 0, 0, 0, bc, 0)
- C(0xc004, BRCL, RIL_c, Z, 0, 0, 0, 0, bc, 0)
-/* BRANCH ON COUNT */
- C(0x0600, BCTR, RR_a, Z, 0, r2_nz, 0, 0, bct32, 0)
- C(0xb946, BCTGR, RRE, Z, 0, r2_nz, 0, 0, bct64, 0)
- C(0x4600, BCT, RX_a, Z, 0, a2, 0, 0, bct32, 0)
- C(0xe346, BCTG, RXY_a, Z, 0, a2, 0, 0, bct64, 0)
-/* BRANCH RELATIVE ON COUNT */
- C(0xa706, BRCT, RI_b, Z, 0, 0, 0, 0, bct32, 0)
- C(0xa707, BRCTG, RI_b, Z, 0, 0, 0, 0, bct64, 0)
-/* BRANCH RELATIVE ON COUNT HIGH */
- C(0xcc06, BRCTH, RIL_b, HW, 0, 0, 0, 0, bcth, 0)
-/* BRANCH ON INDEX */
- D(0x8600, BXH, RS_a, Z, 0, a2, 0, 0, bx32, 0, 0)
- D(0x8700, BXLE, RS_a, Z, 0, a2, 0, 0, bx32, 0, 1)
- D(0xeb44, BXHG, RSY_a, Z, 0, a2, 0, 0, bx64, 0, 0)
- D(0xeb45, BXLEG, RSY_a, Z, 0, a2, 0, 0, bx64, 0, 1)
-/* BRANCH RELATIVE ON INDEX */
- D(0x8400, BRXH, RSI, Z, 0, 0, 0, 0, bx32, 0, 0)
- D(0x8500, BRXLE, RSI, Z, 0, 0, 0, 0, bx32, 0, 1)
- D(0xec44, BRXHG, RIE_e, Z, 0, 0, 0, 0, bx64, 0, 0)
- D(0xec45, BRXHLE, RIE_e, Z, 0, 0, 0, 0, bx64, 0, 1)
-
-/* CHECKSUM */
- 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)
-
-/* COMPARE */
- C(0x1900, CR, RR_a, Z, r1_o, r2_o, 0, 0, 0, cmps32)
- C(0x5900, C, RX_a, Z, r1_o, m2_32s, 0, 0, 0, cmps32)
- C(0xe359, CY, RXY_a, LD, r1_o, m2_32s, 0, 0, 0, cmps32)
- C(0xb920, CGR, RRE, Z, r1_o, r2_o, 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(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)
-/* 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)
-/* COMPARE RELATIVE LONG */
- C(0xc60d, CRL, RIL_b, GIE, r1, mri2_32s, 0, 0, 0, cmps32)
- C(0xc608, CGRL, RIL_b, GIE, r1, mri2_64, 0, 0, 0, cmps64)
- C(0xc60c, CGFRL, RIL_b, GIE, r1, mri2_32s, 0, 0, 0, cmps64)
-/* COMPARE HALFWORD */
- C(0x4900, CH, RX_a, Z, r1_o, m2_16s, 0, 0, 0, cmps32)
- C(0xe379, CHY, RXY_a, LD, r1_o, m2_16s, 0, 0, 0, cmps32)
- C(0xe334, CGH, RXY_a, GIE, r1_o, m2_16s, 0, 0, 0, cmps64)
-/* COMPARE HALFWORD IMMEDIATE */
- C(0xa70e, CHI, RI_a, Z, r1_o, i2, 0, 0, 0, cmps32)
- C(0xa70f, CGHI, RI_a, Z, r1_o, i2, 0, 0, 0, cmps64)
- C(0xe554, CHHSI, SIL, GIE, m1_16s, i2, 0, 0, 0, cmps64)
- C(0xe55c, CHSI, SIL, GIE, m1_32s, i2, 0, 0, 0, cmps64)
- C(0xe558, CGHSI, SIL, GIE, m1_64, i2, 0, 0, 0, cmps64)
-/* COMPARE HALFWORD RELATIVE LONG */
- C(0xc605, CHRL, RIL_b, GIE, r1_o, mri2_32s, 0, 0, 0, cmps32)
- C(0xc604, CGHRL, RIL_b, GIE, r1_o, mri2_64, 0, 0, 0, cmps64)
-/* COMPARE HIGH */
- C(0xb9cd, CHHR, RRE, HW, r1_sr32, r2_sr32, 0, 0, 0, cmps32)
- C(0xb9dd, CHLR, RRE, HW, r1_sr32, r2_o, 0, 0, 0, cmps32)
- C(0xe3cd, CHF, RXY_a, HW, r1_sr32, m2_32s, 0, 0, 0, cmps32)
-/* COMPARE IMMEDIATE HIGH */
- C(0xcc0d, CIH, RIL_a, HW, r1_sr32, i2, 0, 0, 0, cmps32)
-
-/* COMPARE LOGICAL */
- C(0x1500, CLR, RR_a, Z, r1, r2, 0, 0, 0, cmpu32)
- C(0x5500, CL, RX_a, Z, r1, m2_32s, 0, 0, 0, cmpu32)
- C(0xe355, CLY, RXY_a, LD, r1, m2_32s, 0, 0, 0, cmpu32)
- C(0xb921, CLGR, RRE, Z, r1, r2, 0, 0, 0, cmpu64)
- C(0xb931, CLGFR, RRE, Z, r1, r2_32u, 0, 0, 0, cmpu64)
- C(0xe321, CLG, RXY_a, Z, r1, m2_64, 0, 0, 0, cmpu64)
- C(0xe331, CLGF, RXY_a, Z, r1, m2_32u, 0, 0, 0, cmpu64)
- C(0xd500, CLC, SS_a, Z, la1, a2, 0, 0, clc, 0)
-/* COMPARE LOGICAL HIGH */
- C(0xb9cf, CLHHR, RRE, HW, r1_sr32, r2_sr32, 0, 0, 0, cmpu32)
- C(0xb9df, CLHLR, RRE, HW, r1_sr32, r2_o, 0, 0, 0, cmpu32)
- C(0xe3cf, CLHF, RXY_a, HW, r1_sr32, m2_32s, 0, 0, 0, cmpu32)
-/* COMPARE LOGICAL IMMEDIATE */
- C(0xc20f, CLFI, RIL_a, EI, r1, i2, 0, 0, 0, cmpu32)
- C(0xc20e, CLGFI, RIL_a, EI, r1, i2_32u, 0, 0, 0, cmpu64)
- C(0x9500, CLI, SI, Z, m1_8u, i2_8u, 0, 0, 0, cmpu64)
- C(0xeb55, CLIY, SIY, LD, m1_8u, i2_8u, 0, 0, 0, cmpu64)
- C(0xe555, CLHHSI, SIL, GIE, m1_16u, i2_16u, 0, 0, 0, cmpu64)
- C(0xe55d, CLFHSI, SIL, GIE, m1_32u, i2_16u, 0, 0, 0, cmpu64)
- C(0xe559, CLGHSI, SIL, GIE, m1_64, i2_16u, 0, 0, 0, cmpu64)
-/* COMPARE LOGICAL IMMEDIATE HIGH */
- C(0xcc0f, CLIH, RIL_a, HW, r1_sr32, i2, 0, 0, 0, cmpu32)
-/* COMPARE LOGICAL RELATIVE LONG */
- C(0xc60f, CLRL, RIL_b, GIE, r1_o, mri2_32u, 0, 0, 0, cmpu32)
- C(0xc60a, CLGRL, RIL_b, GIE, r1_o, mri2_64, 0, 0, 0, cmpu64)
- C(0xc60e, CLGFRL, RIL_b, GIE, r1_o, mri2_32u, 0, 0, 0, cmpu64)
- C(0xc607, CLHRL, RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu32)
- C(0xc606, CLGHRL, RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu64)
-/* COMPARE LOGICAL LONG EXTENDED */
- C(0xa900, CLCLE, RS_a, Z, 0, a2, 0, 0, clcle, 0)
-/* COMPARE LOGICAL CHARACTERS UNDER MASK */
- C(0xbd00, CLM, RS_b, Z, r1_o, a2, 0, 0, clm, 0)
- C(0xeb21, CLMY, RSY_b, LD, r1_o, a2, 0, 0, clm, 0)
- C(0xeb20, CLMH, RSY_b, Z, r1_sr32, a2, 0, 0, clm, 0)
-/* COMPARE LOGICAL STRING */
- C(0xb25d, CLST, RRE, Z, r1_o, r2_o, 0, 0, clst, 0)
-
-/* COMPARE AND BRANCH */
- D(0xecf6, CRB, RRS, GIE, r1_32s, r2_32s, 0, 0, cj, 0, 0)
- D(0xece4, CGRB, RRS, GIE, r1_o, r2_o, 0, 0, cj, 0, 0)
- D(0xec76, CRJ, RIE_b, GIE, r1_32s, r2_32s, 0, 0, cj, 0, 0)
- D(0xec64, CGRJ, RIE_b, GIE, r1_o, r2_o, 0, 0, cj, 0, 0)
- D(0xecfe, CIB, RIS, GIE, r1_32s, i2, 0, 0, cj, 0, 0)
- D(0xecfc, CGIB, RIS, GIE, r1_o, i2, 0, 0, cj, 0, 0)
- D(0xec7e, CIJ, RIE_c, GIE, r1_32s, i2, 0, 0, cj, 0, 0)
- D(0xec7c, CGIJ, RIE_c, GIE, r1_o, i2, 0, 0, cj, 0, 0)
-/* COMPARE LOGICAL AND BRANCH */
- D(0xecf7, CLRB, RRS, GIE, r1_32u, r2_32u, 0, 0, cj, 0, 1)
- D(0xece5, CLGRB, RRS, GIE, r1_o, r2_o, 0, 0, cj, 0, 1)
- D(0xec77, CLRJ, RIE_b, GIE, r1_32u, r2_32u, 0, 0, cj, 0, 1)
- D(0xec65, CLGRJ, RIE_b, GIE, r1_o, r2_o, 0, 0, cj, 0, 1)
- D(0xecff, CLIB, RIS, GIE, r1_32u, i2_8u, 0, 0, cj, 0, 1)
- D(0xecfd, CLGIB, RIS, GIE, r1_o, i2_8u, 0, 0, cj, 0, 1)
- D(0xec7f, CLIJ, RIE_c, GIE, r1_32u, i2_8u, 0, 0, cj, 0, 1)
- D(0xec7d, CLGIJ, RIE_c, GIE, r1_o, i2_8u, 0, 0, cj, 0, 1)
-
-/* COMPARE AND SWAP */
- D(0xba00, CS, RS_a, Z, r3_32u, r1_32u, new, r1_32, cs, 0, 0)
- D(0xeb14, CSY, RSY_a, LD, r3_32u, r1_32u, new, r1_32, cs, 0, 0)
- D(0xeb30, CSG, RSY_a, Z, r3_o, r1_o, new, r1, cs, 0, 1)
-/* COMPARE DOUBLE AND SWAP */
- D(0xbb00, CDS, RS_a, Z, r3_D32, r1_D32, new, r1_D32, cs, 0, 1)
- D(0xeb31, CDSY, RSY_a, LD, r3_D32, r1_D32, new, r1_D32, cs, 0, 1)
- C(0xeb3e, CDSG, RSY_a, Z, 0, 0, 0, 0, cdsg, 0)
-
-/* COMPARE AND TRAP */
- D(0xb972, CRT, RRF_c, GIE, r1_32s, r2_32s, 0, 0, ct, 0, 0)
- D(0xb960, CGRT, RRF_c, GIE, r1_o, r2_o, 0, 0, ct, 0, 0)
- D(0xec72, CIT, RIE_a, GIE, r1_32s, i2, 0, 0, ct, 0, 0)
- D(0xec70, CGIT, RIE_a, GIE, r1_o, i2, 0, 0, ct, 0, 0)
-/* COMPARE LOGICAL AND TRAP */
- D(0xb973, CLRT, RRF_c, GIE, r1_32u, r2_32u, 0, 0, ct, 0, 1)
- D(0xb961, CLGRT, RRF_c, GIE, r1_o, r2_o, 0, 0, ct, 0, 1)
- D(0xeb23, CLT, RSY_b, MIE, r1_32u, m2_32u, 0, 0, ct, 0, 1)
- D(0xeb2b, CLGT, RSY_b, MIE, r1_o, m2_64, 0, 0, ct, 0, 1)
- D(0xec73, CLFIT, RIE_a, GIE, r1_32u, i2_32u, 0, 0, ct, 0, 1)
- D(0xec71, CLGIT, RIE_a, GIE, r1_o, i2_32u, 0, 0, ct, 0, 1)
-
-/* CONVERT TO DECIMAL */
- 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)
-/* 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)
-/* 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)
-/* 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)
-
-/* 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)
-/* 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)
- C(0xb987, DLGR, RRE, Z, 0, r2_o, r1_P, 0, divu64, 0)
- C(0xe387, DLG, RXY_a, Z, 0, m2_64, r1_P, 0, divu64, 0)
-/* DIVIDE SINGLE */
- C(0xb90d, DSGR, RRE, Z, r1p1, r2, r1_P, 0, divs64, 0)
- C(0xb91d, DSGFR, RRE, Z, r1p1, r2_32s, r1_P, 0, divs64, 0)
- C(0xe30d, DSG, RXY_a, Z, r1p1, m2_64, r1_P, 0, divs64, 0)
- C(0xe31d, DSGF, RXY_a, Z, r1p1, m2_32s, r1_P, 0, divs64, 0)
-
-/* EXCLUSIVE OR */
- C(0x1700, XR, RR_a, Z, r1, r2, new, r1_32, xor, nz32)
- C(0xb9f7, XRK, RRF_a, DO, r2, r3, new, r1_32, xor, nz32)
- C(0x5700, X, RX_a, Z, r1, m2_32s, new, r1_32, xor, nz32)
- C(0xe357, XY, RXY_a, LD, r1, m2_32s, new, r1_32, xor, nz32)
- C(0xb982, XGR, RRE, Z, r1, r2, r1, 0, xor, nz64)
- C(0xb9e7, XGRK, RRF_a, DO, r2, r3, r1, 0, xor, nz64)
- C(0xe382, XG, RXY_a, Z, r1, m2_64, r1, 0, xor, nz64)
- C(0xd700, XC, SS_a, Z, 0, 0, 0, 0, xc, 0)
-/* EXCLUSIVE OR IMMEDIATE */
- D(0xc006, XIHF, RIL_a, EI, r1_o, i2_32u, r1, 0, xori, 0, 0x2020)
- D(0xc007, XILF, RIL_a, EI, r1_o, i2_32u, r1, 0, xori, 0, 0x2000)
- C(0x9700, XI, SI, Z, m1_8u, i2_8u, new, m1_8, xor, nz64)
- C(0xeb57, XIY, SIY, LD, m1_8u, i2_8u, new, m1_8, xor, nz64)
-
-/* EXECUTE */
- C(0x4400, EX, RX_a, Z, r1_o, a2, 0, 0, ex, 0)
-/* EXECUTE RELATIVE LONG */
- C(0xc600, EXRL, RIL_b, EE, r1_o, ri2, 0, 0, ex, 0)
-
-/* EXTRACT ACCESS */
- C(0xb24f, EAR, RRE, Z, 0, 0, new, r1_32, ear, 0)
-/* EXTRACT CPU ATTRIBUTE */
- C(0xeb4c, ECAG, RSY_a, GIE, 0, a2, r1, 0, ecag, 0)
-/* EXTRACT FPC */
- C(0xb38c, EFPC, RRE, Z, 0, 0, new, r1_32, efpc, 0)
-/* EXTRACT PSW */
- C(0xb98d, EPSW, RRE, Z, 0, 0, 0, 0, epsw, 0)
-
-/* FIND LEFTMOST ONE */
- C(0xb983, FLOGR, RRE, EI, 0, r2_o, r1_P, 0, flogr, 0)
-
-/* INSERT CHARACTER */
- C(0x4300, IC, RX_a, Z, 0, m2_8u, 0, r1_8, mov2, 0)
- C(0xe373, ICY, RXY_a, LD, 0, m2_8u, 0, r1_8, mov2, 0)
-/* INSERT CHARACTERS UNDER MASK */
- D(0xbf00, ICM, RS_b, Z, 0, a2, r1, 0, icm, 0, 0)
- D(0xeb81, ICMY, RSY_b, LD, 0, a2, r1, 0, icm, 0, 0)
- D(0xeb80, ICMH, RSY_b, Z, 0, a2, r1, 0, icm, 0, 32)
-/* INSERT IMMEDIATE */
- D(0xc008, IIHF, RIL_a, EI, r1_o, i2_32u, r1, 0, insi, 0, 0x2020)
- D(0xc009, IILF, RIL_a, EI, r1_o, i2_32u, r1, 0, insi, 0, 0x2000)
- D(0xa500, IIHH, RI_a, Z, r1_o, i2_16u, r1, 0, insi, 0, 0x1030)
- D(0xa501, IIHL, RI_a, Z, r1_o, i2_16u, r1, 0, insi, 0, 0x1020)
- D(0xa502, IILH, RI_a, Z, r1_o, i2_16u, r1, 0, insi, 0, 0x1010)
- D(0xa503, IILL, RI_a, Z, r1_o, i2_16u, r1, 0, insi, 0, 0x1000)
-/* INSERT PROGRAM MASK */
- C(0xb222, IPM, RRE, Z, 0, 0, r1, 0, ipm, 0)
-
-/* LOAD */
- C(0x1800, LR, RR_a, Z, 0, r2_o, 0, cond_r1r2_32, mov2, 0)
- C(0x5800, L, RX_a, Z, 0, a2, new, r1_32, ld32s, 0)
- C(0xe358, LY, RXY_a, LD, 0, a2, new, r1_32, ld32s, 0)
- C(0xb904, LGR, RRE, Z, 0, r2_o, 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(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)
-/* LOAD IMMEDIATE */
- C(0xc001, LGFI, RIL_a, EI, 0, i2, 0, r1, mov2, 0)
-/* LOAD RELATIVE LONG */
- C(0xc40d, LRL, RIL_b, GIE, 0, ri2, new, r1_32, ld32s, 0)
- C(0xc408, LGRL, RIL_b, GIE, 0, ri2, r1, 0, ld64, 0)
- C(0xc40c, LGFRL, RIL_b, GIE, 0, ri2, r1, 0, ld32s, 0)
-/* LOAD ADDRESS */
- C(0x4100, LA, RX_a, Z, 0, a2, 0, r1, mov2, 0)
- C(0xe371, LAY, RXY_a, LD, 0, a2, 0, r1, mov2, 0)
-/* LOAD ADDRESS EXTENDED */
- C(0x5100, LAE, RX_a, Z, 0, a2, 0, r1, mov2e, 0)
- C(0xe375, LAEY, RXY_a, GIE, 0, a2, 0, r1, mov2e, 0)
-/* LOAD ADDRESS RELATIVE LONG */
- C(0xc000, LARL, RIL_b, Z, 0, ri2, 0, r1, mov2, 0)
-/* LOAD AND ADD */
- C(0xebf8, LAA, RSY_a, ILA, r3_32s, m2_32s_atomic, new, m2_32_r1_atomic, add, adds32)
- C(0xebe8, LAAG, RSY_a, ILA, r3, m2_64_atomic, new, m2_64_r1_atomic, add, adds64)
-/* LOAD AND ADD LOGICAL */
- C(0xebfa, LAAL, RSY_a, ILA, r3_32s, m2_32s_atomic, new, m2_32_r1_atomic, add, addu32)
- C(0xebea, LAALG, RSY_a, ILA, r3, m2_64_atomic, new, m2_64_r1_atomic, add, addu64)
-/* LOAD AND AND */
- C(0xebf4, LAN, RSY_a, ILA, r3_32s, m2_32s_atomic, new, m2_32_r1_atomic, and, nz32)
- C(0xebe4, LANG, RSY_a, ILA, r3, m2_64_atomic, new, m2_64_r1_atomic, and, nz64)
-/* LOAD AND EXCLUSIVE OR */
- C(0xebf7, LAX, RSY_a, ILA, r3_32s, m2_32s_atomic, new, m2_32_r1_atomic, xor, nz32)
- C(0xebe7, LAXG, RSY_a, ILA, r3, m2_64_atomic, new, m2_64_r1_atomic, xor, nz64)
-/* LOAD AND OR */
- C(0xebf6, LAO, RSY_a, ILA, r3_32s, m2_32s_atomic, new, m2_32_r1_atomic, or, nz32)
- C(0xebe6, LAOG, RSY_a, ILA, r3, m2_64_atomic, new, m2_64_r1_atomic, or, nz64)
-/* LOAD AND TEST */
- C(0x1200, LTR, RR_a, Z, 0, r2_o, 0, cond_r1r2_32, mov2, s32)
- C(0xb902, LTGR, RRE, Z, 0, r2_o, 0, r1, mov2, s64)
- C(0xb912, LTGFR, RRE, Z, 0, r2_32s, 0, r1, mov2, 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(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)
-/* 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)
-/* LOAD BYTE */
- C(0xb926, LBR, RRE, EI, 0, r2_8s, 0, r1_32, mov2, 0)
- C(0xb906, LGBR, RRE, EI, 0, r2_8s, 0, r1, mov2, 0)
- C(0xe376, LB, RXY_a, LD, 0, a2, new, r1_32, ld8s, 0)
- C(0xe377, LGB, RXY_a, LD, 0, a2, r1, 0, ld8s, 0)
-/* LOAD BYTE HIGH */
- C(0xe3c0, LBH, RXY_a, HW, 0, a2, new, r1_32h, ld8s, 0)
-/* LOAD COMPLEMENT */
- 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)
-/* 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)
- C(0x4800, LH, RX_a, Z, 0, a2, new, r1_32, ld16s, 0)
- C(0xe378, LHY, RXY_a, LD, 0, a2, new, r1_32, ld16s, 0)
- C(0xe315, LGH, RXY_a, Z, 0, a2, r1, 0, ld16s, 0)
-/* LOAD HALFWORD HIGH */
- C(0xe3c4, LHH, RXY_a, HW, 0, a2, new, r1_32h, ld16s, 0)
-/* LOAD HALFWORD IMMEDIATE */
- C(0xa708, LHI, RI_a, Z, 0, i2, 0, r1_32, mov2, 0)
- C(0xa709, LGHI, RI_a, Z, 0, i2, 0, r1, mov2, 0)
-/* LOAD HALFWORD RELATIVE LONG */
- C(0xc405, LHRL, RIL_b, GIE, 0, ri2, new, r1_32, ld16s, 0)
- C(0xc404, LGHRL, RIL_b, GIE, 0, ri2, r1, 0, ld16s, 0)
-/* LOAD HIGH */
- C(0xe3ca, LFH, RXY_a, HW, 0, a2, new, r1_32h, ld32u, 0)
-/* LOAG HIGH AND TRAP */
- C(0xe3c8, LFHAT, RXY_a, LAT, 0, m2_32u, r1, 0, lfhat, 0)
-/* LOAD LOGICAL */
- C(0xb916, LLGFR, RRE, Z, 0, r2_32u, 0, r1, mov2, 0)
- C(0xe316, LLGF, RXY_a, Z, 0, a2, r1, 0, ld32u, 0)
-/* LOAD LOGICAL AND TRAP */
- C(0xe39d, LLGFAT, RXY_a, LAT, 0, a2, r1, 0, llgfat, 0)
-/* LOAD LOGICAL RELATIVE LONG */
- C(0xc40e, LLGFRL, RIL_b, GIE, 0, ri2, r1, 0, ld32u, 0)
-/* LOAD LOGICAL CHARACTER */
- C(0xb994, LLCR, RRE, EI, 0, r2_8u, 0, r1_32, mov2, 0)
- C(0xb984, LLGCR, RRE, EI, 0, r2_8u, 0, r1, mov2, 0)
- C(0xe394, LLC, RXY_a, EI, 0, a2, new, r1_32, ld8u, 0)
- C(0xe390, LLGC, RXY_a, Z, 0, a2, r1, 0, ld8u, 0)
-/* LOAD LOGICAL CHARACTER HIGH */
- C(0xe3c2, LLCH, RXY_a, HW, 0, a2, new, r1_32h, ld8u, 0)
-/* LOAD LOGICAL HALFWORD */
- C(0xb995, LLHR, RRE, EI, 0, r2_16u, 0, r1_32, mov2, 0)
- C(0xb985, LLGHR, RRE, EI, 0, r2_16u, 0, r1, mov2, 0)
- C(0xe395, LLH, RXY_a, EI, 0, a2, new, r1_32, ld16u, 0)
- C(0xe391, LLGH, RXY_a, Z, 0, a2, r1, 0, ld16u, 0)
-/* LOAD LOGICAL HALFWORD HIGH */
- C(0xe3c6, LLHH, RXY_a, HW, 0, a2, new, r1_32h, ld16u, 0)
-/* LOAD LOGICAL HALFWORD RELATIVE LONG */
- C(0xc402, LLHRL, RIL_b, GIE, 0, ri2, new, r1_32, ld16u, 0)
- C(0xc406, LLGHRL, RIL_b, GIE, 0, ri2, r1, 0, ld16u, 0)
-/* LOAD LOGICAL IMMEDATE */
- D(0xc00e, LLIHF, RIL_a, EI, 0, i2_32u_shl, 0, r1, mov2, 0, 32)
- D(0xc00f, LLILF, RIL_a, EI, 0, i2_32u_shl, 0, r1, mov2, 0, 0)
- D(0xa50c, LLIHH, RI_a, Z, 0, i2_16u_shl, 0, r1, mov2, 0, 48)
- D(0xa50d, LLIHL, RI_a, Z, 0, i2_16u_shl, 0, r1, mov2, 0, 32)
- D(0xa50e, LLILH, RI_a, Z, 0, i2_16u_shl, 0, r1, mov2, 0, 16)
- D(0xa50f, LLILL, RI_a, Z, 0, i2_16u_shl, 0, r1, mov2, 0, 0)
-/* LOAD LOGICAL THIRTY ONE BITS */
- C(0xb917, LLGTR, RRE, Z, 0, r2_o, r1, 0, llgt, 0)
- C(0xe317, LLGT, RXY_a, Z, 0, m2_32u, r1, 0, llgt, 0)
-/* LOAD LOGICAL THIRTY ONE BITS AND TRAP */
- 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)
-/* LOAD GR FROM FPR */
- C(0xb3cd, LGDR, RRE, FPRGR, 0, f2_o, 0, r1, mov2, 0)
-/* 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)
-/* 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)
- C(0xebf2, LOC, RSY_b, LOC, r1, m2_32u, new, r1_32, loc, 0)
- C(0xebe2, LOCG, RSY_b, LOC, r1, m2_64, r1, 0, loc, 0)
-/* LOAD PAIR DISJOINT TODO */
-/* LOAD POSITIVE */
- 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)
-/* 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)
- C(0xe31f, LRVH, RXY_a, Z, 0, m2_16u, new, r1_16, rev16, 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)
-/* 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)
-
-/* LOAD FPC */
- C(0xb29d, LFPC, S, Z, 0, m2_32u, 0, 0, sfpc, 0)
-/* LOAD FPC AND SIGNAL */
- C(0xb2bd, LFAS, S, IEEEE_SIM, 0, m2_32u, 0, 0, sfas, 0)
-/* 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)
-
-/* 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)
-/* 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)
-
-/* LOAD MULTIPLE */
- C(0x9800, LM, RS_a, Z, 0, a2, 0, 0, lm32, 0)
- C(0xeb98, LMY, RSY_a, LD, 0, a2, 0, 0, lm32, 0)
- C(0xeb04, LMG, RSY_a, Z, 0, a2, 0, 0, lm64, 0)
-/* LOAD MULTIPLE HIGH */
- C(0xeb96, LMH, RSY_a, Z, 0, a2, 0, 0, lmh, 0)
-/* LOAD ACCESS MULTIPLE */
- C(0x9a00, LAM, RS_a, Z, 0, a2, 0, 0, lam, 0)
- C(0xeb9a, LAMY, RSY_a, LD, 0, a2, 0, 0, lam, 0)
-
-/* MOVE */
- C(0xd200, MVC, SS_a, Z, la1, a2, 0, 0, mvc, 0)
- C(0xe544, MVHHI, SIL, GIE, la1, i2, 0, m1_16, mov2, 0)
- C(0xe54c, MVHI, SIL, GIE, la1, i2, 0, m1_32, mov2, 0)
- C(0xe548, MVGHI, SIL, GIE, la1, i2, 0, m1_64, mov2, 0)
- C(0x9200, MVI, SI, Z, la1, i2, 0, m1_8, mov2, 0)
- C(0xeb52, MVIY, SIY, LD, la1, i2, 0, m1_8, mov2, 0)
-/* MOVE LONG */
- C(0x0e00, MVCL, RR_a, Z, 0, 0, 0, 0, mvcl, 0)
-/* MOVE LONG EXTENDED */
- C(0xa800, MVCLE, RS_a, Z, 0, a2, 0, 0, mvcle, 0)
-/* MOVE PAGE */
- C(0xb254, MVPG, RRE, Z, r1_o, r2_o, 0, 0, mvpg, 0)
-/* MOVE STRING */
- C(0xb255, MVST, RRE, Z, r1_o, r2_o, 0, 0, mvst, 0)
-
-/* MULTIPLY */
- 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)
-/* 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)
-/* MULTIPLY HALFWORD IMMEDIATE */
- C(0xa70c, MHI, RI_a, Z, r1_o, i2, new, r1_32, mul, 0)
- C(0xa70d, MGHI, RI_a, Z, r1_o, i2, r1, 0, mul, 0)
-/* MULTIPLY LOGICAL */
- C(0xb996, MLR, RRE, Z, r1p1_32u, r2_32u, new, r1_D32, mul, 0)
- C(0xe396, ML, RXY_a, Z, r1p1_32u, m2_32u, new, r1_D32, mul, 0)
- C(0xb986, MLGR, RRE, Z, r1p1, r2_o, r1_P, 0, mul128, 0)
- C(0xe386, MLG, RXY_a, Z, r1p1, m2_64, r1_P, 0, mul128, 0)
-/* MULTIPLY SINGLE */
- C(0xb252, MSR, RRE, Z, r1_o, r2_o, new, r1_32, mul, 0)
- C(0x7100, MS, RX_a, Z, r1_o, m2_32s, new, r1_32, mul, 0)
- C(0xe351, MSY, RXY_a, LD, r1_o, m2_32s, new, r1_32, mul, 0)
- C(0xb90c, MSGR, RRE, Z, r1_o, r2_o, r1, 0, mul, 0)
- C(0xb91c, MSGFR, RRE, Z, r1_o, r2_32s, r1, 0, mul, 0)
- C(0xe30c, MSG, RXY_a, Z, r1_o, m2_64, r1, 0, mul, 0)
- C(0xe31c, MSGF, RXY_a, Z, r1_o, m2_32s, r1, 0, mul, 0)
-/* MULTIPLY SINGLE IMMEDIATE */
- C(0xc201, MSFI, RIL_a, GIE, r1_o, i2, new, r1_32, mul, 0)
- 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)
-/* 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)
-
-/* OR */
- C(0x1600, OR, RR_a, Z, r1, r2, new, r1_32, or, nz32)
- C(0xb9f6, ORK, RRF_a, DO, r2, r3, new, r1_32, or, nz32)
- C(0x5600, O, RX_a, Z, r1, m2_32s, new, r1_32, or, nz32)
- C(0xe356, OY, RXY_a, LD, r1, m2_32s, new, r1_32, or, nz32)
- C(0xb981, OGR, RRE, Z, r1, r2, r1, 0, or, nz64)
- C(0xb9e6, OGRK, RRF_a, DO, r2, r3, r1, 0, or, nz64)
- C(0xe381, OG, RXY_a, Z, r1, m2_64, r1, 0, or, nz64)
- C(0xd600, OC, SS_a, Z, la1, a2, 0, 0, oc, 0)
-/* OR IMMEDIATE */
- D(0xc00c, OIHF, RIL_a, EI, r1_o, i2_32u, r1, 0, ori, 0, 0x2020)
- D(0xc00d, OILF, RIL_a, EI, r1_o, i2_32u, r1, 0, ori, 0, 0x2000)
- D(0xa508, OIHH, RI_a, Z, r1_o, i2_16u, r1, 0, ori, 0, 0x1030)
- D(0xa509, OIHL, RI_a, Z, r1_o, i2_16u, r1, 0, ori, 0, 0x1020)
- D(0xa50a, OILH, RI_a, Z, r1_o, i2_16u, r1, 0, ori, 0, 0x1010)
- D(0xa50b, OILL, RI_a, Z, r1_o, i2_16u, r1, 0, ori, 0, 0x1000)
- C(0x9600, OI, SI, Z, m1_8u, i2_8u, new, m1_8, or, nz64)
- C(0xeb56, OIY, SIY, LD, m1_8u, i2_8u, new, m1_8, or, nz64)
-
-/* PREFETCH */
- /* Implemented as nops of course. */
- C(0xe336, PFD, RXY_b, GIE, 0, 0, 0, 0, 0, 0)
- C(0xc602, PFDRL, RIL_c, GIE, 0, 0, 0, 0, 0, 0)
-
-/* POPULATION COUNT */
- C(0xb9e1, POPCNT, RRE, PC, 0, r2_o, r1, 0, popcnt, nz64)
-
-/* ROTATE LEFT SINGLE LOGICAL */
- C(0xeb1d, RLL, RSY_a, Z, r3_o, sh32, new, r1_32, rll32, 0)
- C(0xeb1c, RLLG, RSY_a, Z, r3_o, sh64, r1, 0, rll64, 0)
-
-/* ROTATE THEN INSERT SELECTED BITS */
- C(0xec55, RISBG, RIE_f, GIE, 0, r2, r1, 0, risbg, s64)
- C(0xec59, RISBGN, RIE_f, MIE, 0, r2, r1, 0, risbg, 0)
- C(0xec5d, RISBHG, RIE_f, HW, 0, r2, r1, 0, risbg, 0)
- C(0xec51, RISBLG, RIE_f, HW, 0, r2, r1, 0, risbg, 0)
-/* ROTATE_THEN <OP> SELECTED BITS */
- C(0xec54, RNSBG, RIE_f, GIE, 0, r2, r1, 0, rosbg, 0)
- C(0xec56, ROSBG, RIE_f, GIE, 0, r2, r1, 0, rosbg, 0)
- C(0xec57, RXSBG, RIE_f, GIE, 0, r2, r1, 0, rosbg, 0)
-
-/* SEARCH STRING */
- C(0xb25e, SRST, RRE, Z, r1_o, r2_o, 0, 0, srst, 0)
-
-/* SET ACCESS */
- C(0xb24e, SAR, RRE, Z, 0, r2_o, 0, 0, sar, 0)
-/* SET ADDRESSING MODE */
- D(0x010c, SAM24, E, Z, 0, 0, 0, 0, sam, 0, 0)
- 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)
-/* SET FPC AND SIGNAL */
- C(0xb385, SFASR, RRE, IEEEE_SIM, 0, r1_o, 0, 0, sfas, 0)
-/* 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)
-/* SET DFP ROUNDING MODE */
- C(0xb2b9, SRNMT, S, DFPR, 0, 0, 0, 0, srnm, 0)
-
-/* SHIFT LEFT SINGLE */
- D(0x8b00, SLA, RS_a, Z, r1, sh32, new, r1_32, sla, 0, 31)
- D(0xebdd, SLAK, RSY_a, DO, r3, sh32, new, r1_32, sla, 0, 31)
- D(0xeb0b, SLAG, RSY_a, Z, r3, sh64, r1, 0, sla, 0, 63)
-/* SHIFT LEFT SINGLE LOGICAL */
- C(0x8900, SLL, RS_a, Z, r1_o, sh32, new, r1_32, sll, 0)
- C(0xebdf, SLLK, RSY_a, DO, r3_o, sh32, new, r1_32, sll, 0)
- C(0xeb0d, SLLG, RSY_a, Z, r3_o, sh64, r1, 0, sll, 0)
-/* SHIFT RIGHT SINGLE */
- C(0x8a00, SRA, RS_a, Z, r1_32s, sh32, new, r1_32, sra, s32)
- C(0xebdc, SRAK, RSY_a, DO, r3_32s, sh32, new, r1_32, sra, s32)
- C(0xeb0a, SRAG, RSY_a, Z, r3_o, sh64, r1, 0, sra, s64)
-/* SHIFT RIGHT SINGLE LOGICAL */
- C(0x8800, SRL, RS_a, Z, r1_32u, sh32, new, r1_32, srl, 0)
- C(0xebde, SRLK, RSY_a, DO, r3_32u, sh32, new, r1_32, srl, 0)
- C(0xeb0c, SRLG, RSY_a, Z, r3_o, sh64, r1, 0, srl, 0)
-/* SHIFT LEFT DOUBLE */
- D(0x8f00, SLDA, RS_a, Z, r1_D32, sh64, new, r1_D32, sla, 0, 31)
-/* SHIFT LEFT DOUBLE LOGICAL */
- C(0x8d00, SLDL, RS_a, Z, r1_D32, sh64, new, r1_D32, sll, 0)
-/* SHIFT RIGHT DOUBLE */
- C(0x8e00, SRDA, RS_a, Z, r1_D32, sh64, new, r1_D32, sra, s64)
-/* SHIFT RIGHT DOUBLE LOGICAL */
- 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)
-
-/* 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)
-/* 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)
-/* STORE CHARACTER */
- C(0x4200, STC, RX_a, Z, r1_o, a2, 0, 0, st8, 0)
- C(0xe372, STCY, RXY_a, LD, r1_o, a2, 0, 0, st8, 0)
-/* STORE CHARACTER HIGH */
- C(0xe3c3, STCH, RXY_a, HW, r1_sr32, a2, 0, 0, st8, 0)
-/* STORE CHARACTERS UNDER MASK */
- D(0xbe00, STCM, RS_b, Z, r1_o, a2, 0, 0, stcm, 0, 0)
- D(0xeb2d, STCMY, RSY_b, LD, r1_o, a2, 0, 0, stcm, 0, 0)
- D(0xeb2c, STCMH, RSY_b, Z, r1_o, a2, 0, 0, stcm, 0, 32)
-/* STORE HALFWORD */
- C(0x4000, STH, RX_a, Z, r1_o, a2, 0, 0, st16, 0)
- C(0xe370, STHY, RXY_a, LD, r1_o, a2, 0, 0, st16, 0)
-/* STORE HALFWORD HIGH */
- C(0xe3c7, STHH, RXY_a, HW, r1_sr32, a2, 0, 0, st16, 0)
-/* STORE HALFWORD RELATIVE LONG */
- C(0xc407, STHRL, RIL_b, GIE, r1_o, ri2, 0, 0, st16, 0)
-/* STORE HIGH */
- C(0xe3cb, STFH, RXY_a, HW, r1_sr32, a2, 0, 0, st32, 0)
-/* STORE ON CONDITION */
- D(0xebf3, STOC, RSY_b, LOC, 0, 0, 0, 0, soc, 0, 0)
- D(0xebe3, STOCG, RSY_b, LOC, 0, 0, 0, 0, soc, 0, 1)
-/* STORE REVERSED */
- C(0xe33f, STRVH, RXY_a, Z, la2, r1_16u, new, m1_16, rev16, 0)
- C(0xe33e, STRV, RXY_a, Z, la2, r1_32u, new, m1_32, rev32, 0)
- C(0xe32f, STRVG, RXY_a, Z, la2, r1_o, new, m1_64, rev64, 0)
-
-/* STORE FPC */
- C(0xb29c, STFPC, S, Z, 0, a2, new, m2_32, efpc, 0)
-
-/* STORE MULTIPLE */
- D(0x9000, STM, RS_a, Z, 0, a2, 0, 0, stm, 0, 4)
- D(0xeb90, STMY, RSY_a, LD, 0, a2, 0, 0, stm, 0, 4)
- D(0xeb24, STMG, RSY_a, Z, 0, a2, 0, 0, stm, 0, 8)
-/* STORE MULTIPLE HIGH */
- C(0xeb26, STMH, RSY_a, Z, 0, a2, 0, 0, stmh, 0)
-/* STORE ACCESS MULTIPLE */
- C(0x9b00, STAM, RS_a, Z, 0, a2, 0, 0, stam, 0)
- C(0xeb9b, STAMY, RSY_a, LD, 0, a2, 0, 0, stam, 0)
-
-/* SUBTRACT */
- C(0x1b00, SR, RR_a, Z, r1, r2, new, r1_32, sub, subs32)
- C(0xb9f9, SRK, RRF_a, DO, r2, r3, new, r1_32, sub, subs32)
- C(0x5b00, S, RX_a, Z, r1, m2_32s, new, r1_32, sub, subs32)
- C(0xe35b, SY, RXY_a, LD, r1, m2_32s, new, r1_32, sub, subs32)
- C(0xb909, SGR, RRE, Z, r1, r2, r1, 0, sub, subs64)
- C(0xb919, SGFR, RRE, Z, r1, r2_32s, 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(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)
-/* 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)
-/* SUBTRACT HIGH */
- C(0xb9c9, SHHHR, RRF_a, HW, r2_sr32, r3_sr32, new, r1_32h, sub, subs32)
- C(0xb9d9, SHHLR, RRF_a, HW, r2_sr32, r3, new, r1_32h, sub, subs32)
-/* SUBTRACT LOGICAL */
- C(0x1f00, SLR, RR_a, Z, r1, r2, new, r1_32, sub, subu32)
- C(0xb9fb, SLRK, RRF_a, DO, r2, r3, new, r1_32, sub, subu32)
- C(0x5f00, SL, RX_a, Z, r1, m2_32u, new, r1_32, sub, subu32)
- C(0xe35f, SLY, RXY_a, LD, r1, m2_32u, new, r1_32, sub, subu32)
- C(0xb90b, SLGR, RRE, Z, r1, r2, r1, 0, sub, subu64)
- C(0xb91b, SLGFR, RRE, Z, r1, r2_32u, r1, 0, sub, subu64)
- C(0xb9eb, SLGRK, RRF_a, DO, r2, r3, r1, 0, sub, subu64)
- C(0xe30b, SLG, RXY_a, Z, r1, m2_64, r1, 0, sub, subu64)
- C(0xe31b, SLGF, RXY_a, Z, r1, m2_32u, r1, 0, sub, subu64)
-/* SUBTRACT LOCICAL HIGH */
- C(0xb9cb, SLHHHR, RRF_a, HW, r2_sr32, r3_sr32, new, r1_32h, sub, subu32)
- C(0xb9db, SLHHLR, RRF_a, HW, r2_sr32, r3, new, r1_32h, sub, subu32)
-/* SUBTRACT LOGICAL IMMEDIATE */
- C(0xc205, SLFI, RIL_a, EI, r1, i2_32u, new, r1_32, sub, subu32)
- C(0xc204, SLGFI, RIL_a, EI, r1, i2_32u, r1, 0, sub, subu64)
-/* SUBTRACT LOGICAL WITH BORROW */
- C(0xb999, SLBR, RRE, Z, r1, r2, new, r1_32, subb, subb32)
- C(0xb989, SLBGR, RRE, Z, r1, r2, r1, 0, subb, subb64)
- C(0xe399, SLB, RXY_a, Z, r1, m2_32u, new, r1_32, subb, subb32)
- C(0xe389, SLBG, RXY_a, Z, r1, m2_64, r1, 0, subb, subb64)
-
-/* SUPERVISOR CALL */
- C(0x0a00, SVC, I, Z, 0, 0, 0, 0, svc, 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)
-
-/* TEST UNDER MASK */
- C(0x9100, TM, SI, Z, m1_8u, i2_8u, 0, 0, 0, tm32)
- C(0xeb51, TMY, SIY, LD, m1_8u, i2_8u, 0, 0, 0, tm32)
- D(0xa702, TMHH, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 48)
- D(0xa703, TMHL, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 32)
- D(0xa700, TMLH, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 16)
- D(0xa701, TMLL, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 0)
-
-/* TRANSLATE */
- C(0xdc00, TR, SS_a, Z, la1, a2, 0, 0, tr, 0)
-/* TRANSLATE AND TEST */
- C(0xdd00, TRT, SS_a, Z, la1, a2, 0, 0, trt, 0)
-/* TRANSLATE EXTENDED */
- C(0xb2a5, TRE, RRE, Z, 0, r2, r1_P, 0, tre, 0)
-
-/* UNPACK */
- /* Really format SS_b, but we pack both lengths into one argument
- for the helper call, so we might as well leave one 8-bit field. */
- C(0xf300, UNPK, SS_a, Z, la1, a2, 0, 0, unpk, 0)
-
-#ifndef CONFIG_USER_ONLY
-/* COMPARE AND SWAP AND PURGE */
- C(0xb250, CSP, RRE, Z, 0, ra2, 0, 0, csp, 0)
-/* DIAGNOSE (KVM hypercall) */
- C(0x8300, DIAG, RSI, Z, 0, 0, 0, 0, diag, 0)
-/* INSERT STORAGE KEY EXTENDED */
- C(0xb229, ISKE, RRE, Z, 0, r2_o, new, r1_8, iske, 0)
-/* INVALIDATE PAGE TABLE ENTRY */
- C(0xb221, IPTE, RRF_a, Z, r1_o, r2_o, 0, 0, ipte, 0)
-/* 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)
-/* LOAD PSW */
- C(0x8200, LPSW, S, Z, 0, a2, 0, 0, lpsw, 0)
-/* LOAD PSW EXTENDED */
- C(0xb2b2, LPSWE, S, Z, 0, a2, 0, 0, lpswe, 0)
-/* 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)
-/* 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)
-/* MOVE TO PRIMARY */
- C(0xda00, MVCP, SS_d, Z, la1, a2, 0, 0, mvcp, 0)
-/* MOVE TO SECONDARY */
- C(0xdb00, MVCS, SS_d, Z, la1, a2, 0, 0, mvcs, 0)
-/* PURGE TLB */
- C(0xb20d, PTLB, S, Z, 0, 0, 0, 0, ptlb, 0)
-/* RESET REFERENCE BIT EXTENDED */
- C(0xb22a, RRBE, RRE, Z, 0, r2_o, 0, 0, rrbe, 0)
-/* SERVICE CALL LOGICAL PROCESSOR (PV hypercall) */
- C(0xb220, SERVC, RRE, Z, r1_o, r2_o, 0, 0, servc, 0)
-/* SET ADDRESS SPACE CONTROL FAST */
- C(0xb279, SACF, S, Z, 0, a2, 0, 0, sacf, 0)
-/* SET CLOCK */
- /* ??? Not implemented - is it necessary? */
- C(0xb204, SCK, S, Z, 0, 0, 0, 0, 0, 0)
-/* SET CLOCK COMPARATOR */
- C(0xb206, SCKC, S, Z, 0, m2_64, 0, 0, sckc, 0)
-/* SET CPU TIMER */
- C(0xb208, SPT, S, Z, 0, m2_64, 0, 0, spt, 0)
-/* SET PREFIX */
- C(0xb210, SPX, S, Z, 0, m2_32u, 0, 0, spx, 0)
-/* SET PSW KEY FROM ADDRESS */
- C(0xb20a, SPKA, S, Z, 0, a2, 0, 0, spka, 0)
-/* SET STORAGE KEY EXTENDED */
- C(0xb22b, SSKE, RRF_c, Z, r1_o, r2_o, 0, 0, sske, 0)
-/* SET SYSTEM MASK */
- C(0x8000, SSM, S, Z, 0, m2_8u, 0, 0, ssm, 0)
-/* SIGNAL PROCESSOR */
- C(0xae00, SIGP, RS_a, Z, r3_o, a2, 0, 0, sigp, 0)
-/* 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_64, stckc, 0)
-/* 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)
-/* STORE CPU ADDRESS */
- C(0xb212, STAP, S, Z, la2, 0, new, m1_16, stap, 0)
-/* STORE CPU ID */
- C(0xb202, STIDP, S, Z, la2, 0, new, m1_64, stidp, 0)
-/* STORE CPU TIMER */
- C(0xb209, STPT, S, Z, la2, 0, new, m1_64, stpt, 0)
-/* STORE FACILITY LIST */
- C(0xb2b1, STFL, S, Z, 0, 0, 0, 0, stfl, 0)
-/* STORE PREFIX */
- C(0xb211, STPX, S, Z, la2, 0, new, m1_32, stpx, 0)
-/* STORE SYSTEM INFORMATION */
- C(0xb27d, STSI, S, Z, 0, a2, 0, 0, stsi, 0)
-/* STORE THEN AND SYSTEM MASK */
- C(0xac00, STNSM, SI, Z, la1, 0, 0, 0, stnosm, 0)
-/* STORE THEN OR SYSTEM MASK */
- C(0xad00, STOSM, SI, Z, la1, 0, 0, 0, stnosm, 0)
-/* 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)
-/* 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(0xb233, SSCH, S, Z, 0, insn, 0, 0, ssch, 0)
- C(0xb234, STSCH, S, Z, 0, insn, 0, 0, stsch, 0)
- C(0xb235, TSCH, S, Z, 0, insn, 0, 0, tsch, 0)
- /* ??? 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)
-#endif /* CONFIG_USER_ONLY */
diff --git a/qemu/target-s390x/insn-format.def b/qemu/target-s390x/insn-format.def
deleted file mode 100644
index 0e898b90b..000000000
--- a/qemu/target-s390x/insn-format.def
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Description of s390 insn formats. */
-/* NAME F1, F2... */
-F0(E)
-F1(I, I(1, 8, 8))
-F2(RI_a, R(1, 8), I(2,16,16))
-F2(RI_b, R(1, 8), I(2,16,16))
-F2(RI_c, M(1, 8), I(2,16,16))
-F3(RIE_a, R(1, 8), I(2,16,16), M(3,32))
-F4(RIE_b, R(1, 8), R(2,12), M(3,32), I(4,16,16))
-F4(RIE_c, R(1, 8), I(2,32, 8), M(3,12), I(4,16,16))
-F3(RIE_d, R(1, 8), I(2,16,16), R(3,12))
-F3(RIE_e, R(1, 8), I(2,16,16), R(3,12))
-F5(RIE_f, R(1, 8), R(2,12), I(3,16,8), I(4,24,8), I(5,32,8))
-F2(RIL_a, R(1, 8), I(2,16,32))
-F2(RIL_b, R(1, 8), I(2,16,32))
-F2(RIL_c, M(1, 8), I(2,16,32))
-F4(RIS, R(1, 8), I(2,32, 8), M(3,12), BD(4,16,20))
-/* ??? The PoO does not call out subtypes _a and _b for RR, as it does
- for e.g. RX. Our checking requires this for e.g. BCR. */
-F2(RR_a, R(1, 8), R(2,12))
-F2(RR_b, M(1, 8), R(2,12))
-F2(RRE, R(1,24), R(2,28))
-F3(RRD, R(1,16), R(2,28), R(3,24))
-F4(RRF_a, R(1,24), R(2,28), R(3,16), M(4,20))
-F4(RRF_b, R(1,24), R(2,28), R(3,16), M(4,20))
-F4(RRF_c, R(1,24), R(2,28), M(3,16), M(4,20))
-F4(RRF_d, R(1,24), R(2,28), M(3,16), M(4,20))
-F4(RRF_e, R(1,24), R(2,28), M(3,16), M(4,20))
-F4(RRS, R(1, 8), R(2,12), M(3,32), BD(4,16,20))
-F3(RS_a, R(1, 8), BD(2,16,20), R(3,12))
-F3(RS_b, R(1, 8), BD(2,16,20), M(3,12))
-F3(RSI, R(1, 8), I(2,16,16), R(3,12))
-F2(RSL, L(1, 8, 4), BD(1,16,20))
-F3(RSY_a, R(1, 8), BDL(2), R(3,12))
-F3(RSY_b, R(1, 8), BDL(2), M(3,12))
-F2(RX_a, R(1, 8), BXD(2))
-F2(RX_b, M(1, 8), BXD(2))
-F2(RXE, R(1, 8), BXD(2))
-F3(RXF, R(1,32), BXD(2), R(3, 8))
-F2(RXY_a, R(1, 8), BXDL(2))
-F2(RXY_b, M(1, 8), BXDL(2))
-F1(S, BD(2,16,20))
-F2(SI, BD(1,16,20), I(2,8,8))
-F2(SIL, BD(1,16,20), I(2,32,16))
-F2(SIY, BDL(1), I(2, 8, 8))
-F3(SS_a, L(1, 8, 8), BD(1,16,20), BD(2,32,36))
-F4(SS_b, L(1, 8, 4), BD(1,16,20), L(2,12,4), BD(2,32,36))
-F4(SS_c, L(1, 8, 4), BD(1,16,20), BD(2,32,36), I(3,12, 4))
-/* ??? Odd man out. The L1 field here is really a register, but the
- easy way to compress the fields has R1 and B1 overlap. */
-F4(SS_d, L(1, 8, 4), BD(1,16,20), BD(2,32,36), R(3,12))
-F4(SS_e, R(1, 8), BD(2,16,20), R(3,12), BD(4,32,36))
-F3(SS_f, BD(1,16,20), L(2,8,8), BD(2,32,36))
-F2(SSE, BD(1,16,20), BD(2,32,36))
-F3(SSF, BD(1,16,20), BD(2,32,36), R(3,8))
diff --git a/qemu/target-s390x/int_helper.c b/qemu/target-s390x/int_helper.c
deleted file mode 100644
index cc1071eea..000000000
--- a/qemu/target-s390x/int_helper.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * S/390 integer helper routines
- *
- * Copyright (c) 2009 Ulrich Hecht
- * Copyright (c) 2009 Alexander Graf
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "qemu/host-utils.h"
-#include "exec/helper-proto.h"
-
-/* #define DEBUG_HELPER */
-#ifdef DEBUG_HELPER
-#define HELPER_LOG(x...) qemu_log(x)
-#else
-#define HELPER_LOG(x...)
-#endif
-
-/* 64/32 -> 32 signed division */
-int64_t HELPER(divs32)(CPUS390XState *env, int64_t a, int64_t b64)
-{
- int32_t ret, b = b64;
- int64_t q;
-
- if (b == 0) {
- runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
- }
-
- ret = q = a / b;
- env->retxl = a % b;
-
- /* Catch non-representable quotient. */
- if (ret != q) {
- runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
- }
-
- return ret;
-}
-
-/* 64/32 -> 32 unsigned division */
-uint64_t HELPER(divu32)(CPUS390XState *env, uint64_t a, uint64_t b64)
-{
- uint32_t ret, b = b64;
- uint64_t q;
-
- if (b == 0) {
- runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
- }
-
- ret = q = a / b;
- env->retxl = a % b;
-
- /* Catch non-representable quotient. */
- if (ret != q) {
- runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
- }
-
- return ret;
-}
-
-/* 64/64 -> 64 signed division */
-int64_t HELPER(divs64)(CPUS390XState *env, int64_t a, int64_t b)
-{
- /* Catch divide by zero, and non-representable quotient (MIN / -1). */
- if (b == 0 || (b == -1 && a == (1ll << 63))) {
- runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
- }
- env->retxl = a % b;
- return a / b;
-}
-
-/* 128 -> 64/64 unsigned division */
-uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al,
- uint64_t b)
-{
- uint64_t ret;
- /* Signal divide by zero. */
- if (b == 0) {
- runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
- }
- if (ah == 0) {
- /* 64 -> 64/64 case */
- env->retxl = al % b;
- ret = al / b;
- } else {
- /* ??? Move i386 idivq helper to host-utils. */
-#ifdef CONFIG_INT128
- __uint128_t a = ((__uint128_t)ah << 64) | al;
- __uint128_t q = a / b;
- env->retxl = a % b;
- ret = q;
- if (ret != q) {
- runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
- }
-#else
- S390CPU *cpu = s390_env_get_cpu(env);
- /* 32-bit hosts would need special wrapper functionality - just abort if
- we encounter such a case; it's very unlikely anyways. */
- cpu_abort(CPU(cpu), "128 -> 64/64 division not implemented\n");
-#endif
- }
- return ret;
-}
-
-/* count leading zeros, for find leftmost one */
-uint64_t HELPER(clz)(uint64_t v)
-{
- return clz64(v);
-}
-
-uint64_t HELPER(cvd)(int32_t reg)
-{
- /* positive 0 */
- uint64_t dec = 0x0c;
- int64_t bin = reg;
- int shift;
-
- if (bin < 0) {
- bin = -bin;
- dec = 0x0d;
- }
-
- for (shift = 4; (shift < 64) && bin; shift += 4) {
- dec |= (bin % 10) << shift;
- bin /= 10;
- }
-
- return dec;
-}
-
-uint64_t HELPER(popcnt)(uint64_t r2)
-{
- uint64_t ret = 0;
- int i;
-
- for (i = 0; i < 64; i += 8) {
- uint64_t t = ctpop32((r2 >> i) & 0xff);
- ret |= t << i;
- }
- return ret;
-}
diff --git a/qemu/target-s390x/interrupt.c b/qemu/target-s390x/interrupt.c
deleted file mode 100644
index bad60a7e1..000000000
--- a/qemu/target-s390x/interrupt.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * QEMU S/390 Interrupt support
- *
- * Copyright IBM Corp. 2012, 2014
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or (at your
- * option) any later version. See the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "sysemu/kvm.h"
-
-/*
- * All of the following interrupts are floating, i.e. not per-vcpu.
- * We just need a dummy cpustate in order to be able to inject in the
- * non-kvm case.
- */
-#if !defined(CONFIG_USER_ONLY)
-void s390_sclp_extint(uint32_t parm)
-{
- if (kvm_enabled()) {
- kvm_s390_service_interrupt(parm);
- } else {
- S390CPU *dummy_cpu = s390_cpu_addr2state(0);
-
- cpu_inject_ext(dummy_cpu, EXT_SERVICE, parm, 0);
- }
-}
-
-void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr,
- uint32_t io_int_parm, uint32_t io_int_word)
-{
- if (kvm_enabled()) {
- kvm_s390_io_interrupt(subchannel_id, subchannel_nr, io_int_parm,
- io_int_word);
- } else {
- S390CPU *dummy_cpu = s390_cpu_addr2state(0);
-
- cpu_inject_io(dummy_cpu, subchannel_id, subchannel_nr, io_int_parm,
- io_int_word);
- }
-}
-
-void s390_crw_mchk(void)
-{
- if (kvm_enabled()) {
- kvm_s390_crw_mchk();
- } else {
- S390CPU *dummy_cpu = s390_cpu_addr2state(0);
-
- cpu_inject_crw_mchk(dummy_cpu);
- }
-}
-
-#endif
diff --git a/qemu/target-s390x/ioinst.c b/qemu/target-s390x/ioinst.c
deleted file mode 100644
index 142ff9384..000000000
--- a/qemu/target-s390x/ioinst.c
+++ /dev/null
@@ -1,833 +0,0 @@
-/*
- * I/O instructions for S/390
- *
- * Copyright 2012, 2015 IBM Corp.
- * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or (at
- * your option) any later version. See the COPYING file in the top-level
- * directory.
- */
-
-#include "qemu/osdep.h"
-
-#include "cpu.h"
-#include "ioinst.h"
-#include "trace.h"
-#include "hw/s390x/s390-pci-bus.h"
-
-int ioinst_disassemble_sch_ident(uint32_t value, int *m, int *cssid, int *ssid,
- int *schid)
-{
- if (!IOINST_SCHID_ONE(value)) {
- return -EINVAL;
- }
- if (!IOINST_SCHID_M(value)) {
- if (IOINST_SCHID_CSSID(value)) {
- return -EINVAL;
- }
- *cssid = 0;
- *m = 0;
- } else {
- *cssid = IOINST_SCHID_CSSID(value);
- *m = 1;
- }
- *ssid = IOINST_SCHID_SSID(value);
- *schid = IOINST_SCHID_NR(value);
- return 0;
-}
-
-void ioinst_handle_xsch(S390CPU *cpu, uint64_t reg1)
-{
- int cssid, ssid, schid, m;
- SubchDev *sch;
- int ret = -ENODEV;
- int cc;
-
- if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
- program_interrupt(&cpu->env, PGM_OPERAND, 2);
- return;
- }
- trace_ioinst_sch_id("xsch", cssid, ssid, schid);
- sch = css_find_subch(m, cssid, ssid, schid);
- if (sch && css_subch_visible(sch)) {
- ret = css_do_xsch(sch);
- }
- switch (ret) {
- case -ENODEV:
- cc = 3;
- break;
- case -EBUSY:
- cc = 2;
- break;
- case 0:
- cc = 0;
- break;
- default:
- cc = 1;
- break;
- }
- setcc(cpu, cc);
-}
-
-void ioinst_handle_csch(S390CPU *cpu, uint64_t reg1)
-{
- int cssid, ssid, schid, m;
- SubchDev *sch;
- int ret = -ENODEV;
- int cc;
-
- if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
- program_interrupt(&cpu->env, PGM_OPERAND, 2);
- return;
- }
- trace_ioinst_sch_id("csch", cssid, ssid, schid);
- sch = css_find_subch(m, cssid, ssid, schid);
- if (sch && css_subch_visible(sch)) {
- ret = css_do_csch(sch);
- }
- if (ret == -ENODEV) {
- cc = 3;
- } else {
- cc = 0;
- }
- setcc(cpu, cc);
-}
-
-void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1)
-{
- int cssid, ssid, schid, m;
- SubchDev *sch;
- int ret = -ENODEV;
- int cc;
-
- if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
- program_interrupt(&cpu->env, PGM_OPERAND, 2);
- return;
- }
- trace_ioinst_sch_id("hsch", cssid, ssid, schid);
- sch = css_find_subch(m, cssid, ssid, schid);
- if (sch && css_subch_visible(sch)) {
- ret = css_do_hsch(sch);
- }
- switch (ret) {
- case -ENODEV:
- cc = 3;
- break;
- case -EBUSY:
- cc = 2;
- break;
- case 0:
- cc = 0;
- break;
- default:
- cc = 1;
- break;
- }
- setcc(cpu, cc);
-}
-
-static int ioinst_schib_valid(SCHIB *schib)
-{
- if ((be16_to_cpu(schib->pmcw.flags) & PMCW_FLAGS_MASK_INVALID) ||
- (be32_to_cpu(schib->pmcw.chars) & PMCW_CHARS_MASK_INVALID)) {
- return 0;
- }
- /* Disallow extended measurements for now. */
- if (be32_to_cpu(schib->pmcw.chars) & PMCW_CHARS_MASK_XMWME) {
- return 0;
- }
- return 1;
-}
-
-void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
-{
- int cssid, ssid, schid, m;
- SubchDev *sch;
- SCHIB schib;
- uint64_t addr;
- int ret = -ENODEV;
- int cc;
- CPUS390XState *env = &cpu->env;
- uint8_t ar;
-
- addr = decode_basedisp_s(env, ipb, &ar);
- if (addr & 3) {
- program_interrupt(env, PGM_SPECIFICATION, 2);
- return;
- }
- if (s390_cpu_virt_mem_read(cpu, addr, ar, &schib, sizeof(schib))) {
- return;
- }
- if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
- !ioinst_schib_valid(&schib)) {
- program_interrupt(env, PGM_OPERAND, 2);
- return;
- }
- trace_ioinst_sch_id("msch", cssid, ssid, schid);
- sch = css_find_subch(m, cssid, ssid, schid);
- if (sch && css_subch_visible(sch)) {
- ret = css_do_msch(sch, &schib);
- }
- switch (ret) {
- case -ENODEV:
- cc = 3;
- break;
- case -EBUSY:
- cc = 2;
- break;
- case 0:
- cc = 0;
- break;
- default:
- cc = 1;
- break;
- }
- setcc(cpu, cc);
-}
-
-static void copy_orb_from_guest(ORB *dest, const ORB *src)
-{
- dest->intparm = be32_to_cpu(src->intparm);
- dest->ctrl0 = be16_to_cpu(src->ctrl0);
- dest->lpm = src->lpm;
- dest->ctrl1 = src->ctrl1;
- dest->cpa = be32_to_cpu(src->cpa);
-}
-
-static int ioinst_orb_valid(ORB *orb)
-{
- if ((orb->ctrl0 & ORB_CTRL0_MASK_INVALID) ||
- (orb->ctrl1 & ORB_CTRL1_MASK_INVALID)) {
- return 0;
- }
- if ((orb->cpa & HIGH_ORDER_BIT) != 0) {
- return 0;
- }
- return 1;
-}
-
-void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
-{
- int cssid, ssid, schid, m;
- SubchDev *sch;
- ORB orig_orb, orb;
- uint64_t addr;
- int ret = -ENODEV;
- int cc;
- CPUS390XState *env = &cpu->env;
- uint8_t ar;
-
- addr = decode_basedisp_s(env, ipb, &ar);
- if (addr & 3) {
- program_interrupt(env, PGM_SPECIFICATION, 2);
- return;
- }
- if (s390_cpu_virt_mem_read(cpu, addr, ar, &orig_orb, sizeof(orb))) {
- return;
- }
- copy_orb_from_guest(&orb, &orig_orb);
- if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
- !ioinst_orb_valid(&orb)) {
- program_interrupt(env, PGM_OPERAND, 2);
- return;
- }
- trace_ioinst_sch_id("ssch", cssid, ssid, schid);
- sch = css_find_subch(m, cssid, ssid, schid);
- if (sch && css_subch_visible(sch)) {
- ret = css_do_ssch(sch, &orb);
- }
- switch (ret) {
- case -ENODEV:
- cc = 3;
- break;
- case -EBUSY:
- cc = 2;
- break;
- case 0:
- cc = 0;
- break;
- default:
- cc = 1;
- break;
- }
- setcc(cpu, cc);
-}
-
-void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb)
-{
- CRW crw;
- uint64_t addr;
- int cc;
- CPUS390XState *env = &cpu->env;
- uint8_t ar;
-
- addr = decode_basedisp_s(env, ipb, &ar);
- if (addr & 3) {
- program_interrupt(env, PGM_SPECIFICATION, 2);
- return;
- }
-
- cc = css_do_stcrw(&crw);
- /* 0 - crw stored, 1 - zeroes stored */
-
- if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) {
- setcc(cpu, cc);
- } else if (cc == 0) {
- /* Write failed: requeue CRW since STCRW is a suppressing instruction */
- css_undo_stcrw(&crw);
- }
-}
-
-void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
-{
- int cssid, ssid, schid, m;
- SubchDev *sch;
- uint64_t addr;
- int cc;
- SCHIB schib;
- CPUS390XState *env = &cpu->env;
- uint8_t ar;
-
- addr = decode_basedisp_s(env, ipb, &ar);
- if (addr & 3) {
- program_interrupt(env, PGM_SPECIFICATION, 2);
- return;
- }
-
- if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
- /*
- * As operand exceptions have a lower priority than access exceptions,
- * we check whether the memory area is writeable (injecting the
- * access execption if it is not) first.
- */
- if (!s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib))) {
- program_interrupt(env, PGM_OPERAND, 2);
- }
- return;
- }
- trace_ioinst_sch_id("stsch", cssid, ssid, schid);
- sch = css_find_subch(m, cssid, ssid, schid);
- if (sch) {
- if (css_subch_visible(sch)) {
- css_do_stsch(sch, &schib);
- cc = 0;
- } else {
- /* Indicate no more subchannels in this css/ss */
- cc = 3;
- }
- } else {
- if (css_schid_final(m, cssid, ssid, schid)) {
- cc = 3; /* No more subchannels in this css/ss */
- } else {
- /* Store an empty schib. */
- memset(&schib, 0, sizeof(schib));
- cc = 0;
- }
- }
- if (cc != 3) {
- if (s390_cpu_virt_mem_write(cpu, addr, ar, &schib,
- sizeof(schib)) != 0) {
- return;
- }
- } else {
- /* Access exceptions have a higher priority than cc3 */
- if (s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib)) != 0) {
- return;
- }
- }
- setcc(cpu, cc);
-}
-
-int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
-{
- CPUS390XState *env = &cpu->env;
- int cssid, ssid, schid, m;
- SubchDev *sch;
- IRB irb;
- uint64_t addr;
- int cc, irb_len;
- uint8_t ar;
-
- if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
- program_interrupt(env, PGM_OPERAND, 2);
- return -EIO;
- }
- trace_ioinst_sch_id("tsch", cssid, ssid, schid);
- addr = decode_basedisp_s(env, ipb, &ar);
- if (addr & 3) {
- program_interrupt(env, PGM_SPECIFICATION, 2);
- return -EIO;
- }
-
- sch = css_find_subch(m, cssid, ssid, schid);
- if (sch && css_subch_visible(sch)) {
- cc = css_do_tsch_get_irb(sch, &irb, &irb_len);
- } else {
- cc = 3;
- }
- /* 0 - status pending, 1 - not status pending, 3 - not operational */
- if (cc != 3) {
- if (s390_cpu_virt_mem_write(cpu, addr, ar, &irb, irb_len) != 0) {
- return -EFAULT;
- }
- css_do_tsch_update_subch(sch);
- } else {
- irb_len = sizeof(irb) - sizeof(irb.emw);
- /* Access exceptions have a higher priority than cc3 */
- if (s390_cpu_virt_mem_check_write(cpu, addr, ar, irb_len) != 0) {
- return -EFAULT;
- }
- }
-
- setcc(cpu, cc);
- return 0;
-}
-
-typedef struct ChscReq {
- uint16_t len;
- uint16_t command;
- uint32_t param0;
- uint32_t param1;
- uint32_t param2;
-} QEMU_PACKED ChscReq;
-
-typedef struct ChscResp {
- uint16_t len;
- uint16_t code;
- uint32_t param;
- char data[0];
-} QEMU_PACKED ChscResp;
-
-#define CHSC_MIN_RESP_LEN 0x0008
-
-#define CHSC_SCPD 0x0002
-#define CHSC_SCSC 0x0010
-#define CHSC_SDA 0x0031
-#define CHSC_SEI 0x000e
-
-#define CHSC_SCPD_0_M 0x20000000
-#define CHSC_SCPD_0_C 0x10000000
-#define CHSC_SCPD_0_FMT 0x0f000000
-#define CHSC_SCPD_0_CSSID 0x00ff0000
-#define CHSC_SCPD_0_RFMT 0x00000f00
-#define CHSC_SCPD_0_RES 0xc000f000
-#define CHSC_SCPD_1_RES 0xffffff00
-#define CHSC_SCPD_01_CHPID 0x000000ff
-static void ioinst_handle_chsc_scpd(ChscReq *req, ChscResp *res)
-{
- uint16_t len = be16_to_cpu(req->len);
- uint32_t param0 = be32_to_cpu(req->param0);
- uint32_t param1 = be32_to_cpu(req->param1);
- uint16_t resp_code;
- int rfmt;
- uint16_t cssid;
- uint8_t f_chpid, l_chpid;
- int desc_size;
- int m;
-
- rfmt = (param0 & CHSC_SCPD_0_RFMT) >> 8;
- if ((rfmt == 0) || (rfmt == 1)) {
- rfmt = !!(param0 & CHSC_SCPD_0_C);
- }
- if ((len != 0x0010) || (param0 & CHSC_SCPD_0_RES) ||
- (param1 & CHSC_SCPD_1_RES) || req->param2) {
- resp_code = 0x0003;
- goto out_err;
- }
- if (param0 & CHSC_SCPD_0_FMT) {
- resp_code = 0x0007;
- goto out_err;
- }
- cssid = (param0 & CHSC_SCPD_0_CSSID) >> 16;
- m = param0 & CHSC_SCPD_0_M;
- if (cssid != 0) {
- if (!m || !css_present(cssid)) {
- resp_code = 0x0008;
- goto out_err;
- }
- }
- f_chpid = param0 & CHSC_SCPD_01_CHPID;
- l_chpid = param1 & CHSC_SCPD_01_CHPID;
- if (l_chpid < f_chpid) {
- resp_code = 0x0003;
- goto out_err;
- }
- /* css_collect_chp_desc() is endian-aware */
- desc_size = css_collect_chp_desc(m, cssid, f_chpid, l_chpid, rfmt,
- &res->data);
- res->code = cpu_to_be16(0x0001);
- res->len = cpu_to_be16(8 + desc_size);
- res->param = cpu_to_be32(rfmt);
- return;
-
- out_err:
- res->code = cpu_to_be16(resp_code);
- res->len = cpu_to_be16(CHSC_MIN_RESP_LEN);
- res->param = cpu_to_be32(rfmt);
-}
-
-#define CHSC_SCSC_0_M 0x20000000
-#define CHSC_SCSC_0_FMT 0x000f0000
-#define CHSC_SCSC_0_CSSID 0x0000ff00
-#define CHSC_SCSC_0_RES 0xdff000ff
-static void ioinst_handle_chsc_scsc(ChscReq *req, ChscResp *res)
-{
- uint16_t len = be16_to_cpu(req->len);
- uint32_t param0 = be32_to_cpu(req->param0);
- uint8_t cssid;
- uint16_t resp_code;
- uint32_t general_chars[510];
- uint32_t chsc_chars[508];
-
- if (len != 0x0010) {
- resp_code = 0x0003;
- goto out_err;
- }
-
- if (param0 & CHSC_SCSC_0_FMT) {
- resp_code = 0x0007;
- goto out_err;
- }
- cssid = (param0 & CHSC_SCSC_0_CSSID) >> 8;
- if (cssid != 0) {
- if (!(param0 & CHSC_SCSC_0_M) || !css_present(cssid)) {
- resp_code = 0x0008;
- goto out_err;
- }
- }
- if ((param0 & CHSC_SCSC_0_RES) || req->param1 || req->param2) {
- resp_code = 0x0003;
- goto out_err;
- }
- res->code = cpu_to_be16(0x0001);
- res->len = cpu_to_be16(4080);
- res->param = 0;
-
- memset(general_chars, 0, sizeof(general_chars));
- memset(chsc_chars, 0, sizeof(chsc_chars));
-
- general_chars[0] = cpu_to_be32(0x03000000);
- general_chars[1] = cpu_to_be32(0x00059000);
-
- chsc_chars[0] = cpu_to_be32(0x40000000);
- chsc_chars[3] = cpu_to_be32(0x00040000);
-
- memcpy(res->data, general_chars, sizeof(general_chars));
- memcpy(res->data + sizeof(general_chars), chsc_chars, sizeof(chsc_chars));
- return;
-
- out_err:
- res->code = cpu_to_be16(resp_code);
- res->len = cpu_to_be16(CHSC_MIN_RESP_LEN);
- res->param = 0;
-}
-
-#define CHSC_SDA_0_FMT 0x0f000000
-#define CHSC_SDA_0_OC 0x0000ffff
-#define CHSC_SDA_0_RES 0xf0ff0000
-#define CHSC_SDA_OC_MCSSE 0x0
-#define CHSC_SDA_OC_MSS 0x2
-static void ioinst_handle_chsc_sda(ChscReq *req, ChscResp *res)
-{
- uint16_t resp_code = 0x0001;
- uint16_t len = be16_to_cpu(req->len);
- uint32_t param0 = be32_to_cpu(req->param0);
- uint16_t oc;
- int ret;
-
- if ((len != 0x0400) || (param0 & CHSC_SDA_0_RES)) {
- resp_code = 0x0003;
- goto out;
- }
-
- if (param0 & CHSC_SDA_0_FMT) {
- resp_code = 0x0007;
- goto out;
- }
-
- oc = param0 & CHSC_SDA_0_OC;
- switch (oc) {
- case CHSC_SDA_OC_MCSSE:
- ret = css_enable_mcsse();
- if (ret == -EINVAL) {
- resp_code = 0x0101;
- goto out;
- }
- break;
- case CHSC_SDA_OC_MSS:
- ret = css_enable_mss();
- if (ret == -EINVAL) {
- resp_code = 0x0101;
- goto out;
- }
- break;
- default:
- resp_code = 0x0003;
- goto out;
- }
-
-out:
- res->code = cpu_to_be16(resp_code);
- res->len = cpu_to_be16(CHSC_MIN_RESP_LEN);
- res->param = 0;
-}
-
-static int chsc_sei_nt0_get_event(void *res)
-{
- /* no events yet */
- return 1;
-}
-
-static int chsc_sei_nt0_have_event(void)
-{
- /* no events yet */
- return 0;
-}
-
-#define CHSC_SEI_NT0 (1ULL << 63)
-#define CHSC_SEI_NT2 (1ULL << 61)
-static void ioinst_handle_chsc_sei(ChscReq *req, ChscResp *res)
-{
- uint64_t selection_mask = ldq_p(&req->param1);
- uint8_t *res_flags = (uint8_t *)res->data;
- int have_event = 0;
- int have_more = 0;
-
- /* regarding architecture nt0 can not be masked */
- have_event = !chsc_sei_nt0_get_event(res);
- have_more = chsc_sei_nt0_have_event();
-
- if (selection_mask & CHSC_SEI_NT2) {
- if (!have_event) {
- have_event = !chsc_sei_nt2_get_event(res);
- }
-
- if (!have_more) {
- have_more = chsc_sei_nt2_have_event();
- }
- }
-
- if (have_event) {
- res->code = cpu_to_be16(0x0001);
- if (have_more) {
- (*res_flags) |= 0x80;
- } else {
- (*res_flags) &= ~0x80;
- css_clear_sei_pending();
- }
- } else {
- res->code = cpu_to_be16(0x0005);
- res->len = cpu_to_be16(CHSC_MIN_RESP_LEN);
- }
-}
-
-static void ioinst_handle_chsc_unimplemented(ChscResp *res)
-{
- res->len = cpu_to_be16(CHSC_MIN_RESP_LEN);
- res->code = cpu_to_be16(0x0004);
- res->param = 0;
-}
-
-void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb)
-{
- ChscReq *req;
- ChscResp *res;
- uint64_t addr;
- int reg;
- uint16_t len;
- uint16_t command;
- CPUS390XState *env = &cpu->env;
- uint8_t buf[TARGET_PAGE_SIZE];
-
- trace_ioinst("chsc");
- reg = (ipb >> 20) & 0x00f;
- addr = env->regs[reg];
- /* Page boundary? */
- if (addr & 0xfff) {
- program_interrupt(env, PGM_SPECIFICATION, 2);
- return;
- }
- /*
- * Reading sizeof(ChscReq) bytes is currently enough for all of our
- * present CHSC sub-handlers ... if we ever need more, we should take
- * care of req->len here first.
- */
- if (s390_cpu_virt_mem_read(cpu, addr, reg, buf, sizeof(ChscReq))) {
- return;
- }
- req = (ChscReq *)buf;
- len = be16_to_cpu(req->len);
- /* Length field valid? */
- if ((len < 16) || (len > 4088) || (len & 7)) {
- program_interrupt(env, PGM_OPERAND, 2);
- return;
- }
- memset((char *)req + len, 0, TARGET_PAGE_SIZE - len);
- res = (void *)((char *)req + len);
- command = be16_to_cpu(req->command);
- trace_ioinst_chsc_cmd(command, len);
- switch (command) {
- case CHSC_SCSC:
- ioinst_handle_chsc_scsc(req, res);
- break;
- case CHSC_SCPD:
- ioinst_handle_chsc_scpd(req, res);
- break;
- case CHSC_SDA:
- ioinst_handle_chsc_sda(req, res);
- break;
- case CHSC_SEI:
- ioinst_handle_chsc_sei(req, res);
- break;
- default:
- ioinst_handle_chsc_unimplemented(res);
- break;
- }
-
- if (!s390_cpu_virt_mem_write(cpu, addr + len, reg, res,
- be16_to_cpu(res->len))) {
- setcc(cpu, 0); /* Command execution complete */
- }
-}
-
-int ioinst_handle_tpi(S390CPU *cpu, uint32_t ipb)
-{
- CPUS390XState *env = &cpu->env;
- uint64_t addr;
- int lowcore;
- IOIntCode int_code;
- hwaddr len;
- int ret;
- uint8_t ar;
-
- trace_ioinst("tpi");
- addr = decode_basedisp_s(env, ipb, &ar);
- if (addr & 3) {
- program_interrupt(env, PGM_SPECIFICATION, 2);
- return -EIO;
- }
-
- lowcore = addr ? 0 : 1;
- len = lowcore ? 8 /* two words */ : 12 /* three words */;
- ret = css_do_tpi(&int_code, lowcore);
- if (ret == 1) {
- s390_cpu_virt_mem_write(cpu, lowcore ? 184 : addr, ar, &int_code, len);
- }
- return ret;
-}
-
-#define SCHM_REG1_RES(_reg) (_reg & 0x000000000ffffffc)
-#define SCHM_REG1_MBK(_reg) ((_reg & 0x00000000f0000000) >> 28)
-#define SCHM_REG1_UPD(_reg) ((_reg & 0x0000000000000002) >> 1)
-#define SCHM_REG1_DCT(_reg) (_reg & 0x0000000000000001)
-
-void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2,
- uint32_t ipb)
-{
- uint8_t mbk;
- int update;
- int dct;
- CPUS390XState *env = &cpu->env;
-
- trace_ioinst("schm");
-
- if (SCHM_REG1_RES(reg1)) {
- program_interrupt(env, PGM_OPERAND, 2);
- return;
- }
-
- mbk = SCHM_REG1_MBK(reg1);
- update = SCHM_REG1_UPD(reg1);
- dct = SCHM_REG1_DCT(reg1);
-
- if (update && (reg2 & 0x000000000000001f)) {
- program_interrupt(env, PGM_OPERAND, 2);
- return;
- }
-
- css_do_schm(mbk, update, dct, update ? reg2 : 0);
-}
-
-void ioinst_handle_rsch(S390CPU *cpu, uint64_t reg1)
-{
- int cssid, ssid, schid, m;
- SubchDev *sch;
- int ret = -ENODEV;
- int cc;
-
- if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
- program_interrupt(&cpu->env, PGM_OPERAND, 2);
- return;
- }
- trace_ioinst_sch_id("rsch", cssid, ssid, schid);
- sch = css_find_subch(m, cssid, ssid, schid);
- if (sch && css_subch_visible(sch)) {
- ret = css_do_rsch(sch);
- }
- switch (ret) {
- case -ENODEV:
- cc = 3;
- break;
- case -EINVAL:
- cc = 2;
- break;
- case 0:
- cc = 0;
- break;
- default:
- cc = 1;
- break;
- }
- setcc(cpu, cc);
-}
-
-#define RCHP_REG1_RES(_reg) (_reg & 0x00000000ff00ff00)
-#define RCHP_REG1_CSSID(_reg) ((_reg & 0x0000000000ff0000) >> 16)
-#define RCHP_REG1_CHPID(_reg) (_reg & 0x00000000000000ff)
-void ioinst_handle_rchp(S390CPU *cpu, uint64_t reg1)
-{
- int cc;
- uint8_t cssid;
- uint8_t chpid;
- int ret;
- CPUS390XState *env = &cpu->env;
-
- if (RCHP_REG1_RES(reg1)) {
- program_interrupt(env, PGM_OPERAND, 2);
- return;
- }
-
- cssid = RCHP_REG1_CSSID(reg1);
- chpid = RCHP_REG1_CHPID(reg1);
-
- trace_ioinst_chp_id("rchp", cssid, chpid);
-
- ret = css_do_rchp(cssid, chpid);
-
- switch (ret) {
- case -ENODEV:
- cc = 3;
- break;
- case -EBUSY:
- cc = 2;
- break;
- case 0:
- cc = 0;
- break;
- default:
- /* Invalid channel subsystem. */
- program_interrupt(env, PGM_OPERAND, 2);
- return;
- }
- setcc(cpu, cc);
-}
-
-#define SAL_REG1_INVALID(_reg) (_reg & 0x0000000080000000)
-void ioinst_handle_sal(S390CPU *cpu, uint64_t reg1)
-{
- /* We do not provide address limit checking, so let's suppress it. */
- if (SAL_REG1_INVALID(reg1) || reg1 & 0x000000000000ffff) {
- program_interrupt(&cpu->env, PGM_OPERAND, 2);
- }
-}
diff --git a/qemu/target-s390x/ioinst.h b/qemu/target-s390x/ioinst.h
deleted file mode 100644
index 013cc9148..000000000
--- a/qemu/target-s390x/ioinst.h
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * S/390 channel I/O instructions
- *
- * Copyright 2012 IBM Corp.
- * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or (at
- * your option) any later version. See the COPYING file in the top-level
- * directory.
-*/
-
-#ifndef IOINST_S390X_H
-#define IOINST_S390X_H
-/*
- * Channel I/O related definitions, as defined in the Principles
- * Of Operation (and taken from the Linux implementation).
- */
-
-/* subchannel status word (command mode only) */
-typedef struct SCSW {
- uint16_t flags;
- uint16_t ctrl;
- uint32_t cpa;
- uint8_t dstat;
- uint8_t cstat;
- uint16_t count;
-} QEMU_PACKED SCSW;
-
-#define SCSW_FLAGS_MASK_KEY 0xf000
-#define SCSW_FLAGS_MASK_SCTL 0x0800
-#define SCSW_FLAGS_MASK_ESWF 0x0400
-#define SCSW_FLAGS_MASK_CC 0x0300
-#define SCSW_FLAGS_MASK_FMT 0x0080
-#define SCSW_FLAGS_MASK_PFCH 0x0040
-#define SCSW_FLAGS_MASK_ISIC 0x0020
-#define SCSW_FLAGS_MASK_ALCC 0x0010
-#define SCSW_FLAGS_MASK_SSI 0x0008
-#define SCSW_FLAGS_MASK_ZCC 0x0004
-#define SCSW_FLAGS_MASK_ECTL 0x0002
-#define SCSW_FLAGS_MASK_PNO 0x0001
-
-#define SCSW_CTRL_MASK_FCTL 0x7000
-#define SCSW_CTRL_MASK_ACTL 0x0fe0
-#define SCSW_CTRL_MASK_STCTL 0x001f
-
-#define SCSW_FCTL_CLEAR_FUNC 0x1000
-#define SCSW_FCTL_HALT_FUNC 0x2000
-#define SCSW_FCTL_START_FUNC 0x4000
-
-#define SCSW_ACTL_SUSP 0x0020
-#define SCSW_ACTL_DEVICE_ACTIVE 0x0040
-#define SCSW_ACTL_SUBCH_ACTIVE 0x0080
-#define SCSW_ACTL_CLEAR_PEND 0x0100
-#define SCSW_ACTL_HALT_PEND 0x0200
-#define SCSW_ACTL_START_PEND 0x0400
-#define SCSW_ACTL_RESUME_PEND 0x0800
-
-#define SCSW_STCTL_STATUS_PEND 0x0001
-#define SCSW_STCTL_SECONDARY 0x0002
-#define SCSW_STCTL_PRIMARY 0x0004
-#define SCSW_STCTL_INTERMEDIATE 0x0008
-#define SCSW_STCTL_ALERT 0x0010
-
-#define SCSW_DSTAT_ATTENTION 0x80
-#define SCSW_DSTAT_STAT_MOD 0x40
-#define SCSW_DSTAT_CU_END 0x20
-#define SCSW_DSTAT_BUSY 0x10
-#define SCSW_DSTAT_CHANNEL_END 0x08
-#define SCSW_DSTAT_DEVICE_END 0x04
-#define SCSW_DSTAT_UNIT_CHECK 0x02
-#define SCSW_DSTAT_UNIT_EXCEP 0x01
-
-#define SCSW_CSTAT_PCI 0x80
-#define SCSW_CSTAT_INCORR_LEN 0x40
-#define SCSW_CSTAT_PROG_CHECK 0x20
-#define SCSW_CSTAT_PROT_CHECK 0x10
-#define SCSW_CSTAT_DATA_CHECK 0x08
-#define SCSW_CSTAT_CHN_CTRL_CHK 0x04
-#define SCSW_CSTAT_INTF_CTRL_CHK 0x02
-#define SCSW_CSTAT_CHAIN_CHECK 0x01
-
-/* path management control word */
-typedef struct PMCW {
- uint32_t intparm;
- uint16_t flags;
- uint16_t devno;
- uint8_t lpm;
- uint8_t pnom;
- uint8_t lpum;
- uint8_t pim;
- uint16_t mbi;
- uint8_t pom;
- uint8_t pam;
- uint8_t chpid[8];
- uint32_t chars;
-} QEMU_PACKED PMCW;
-
-#define PMCW_FLAGS_MASK_QF 0x8000
-#define PMCW_FLAGS_MASK_W 0x4000
-#define PMCW_FLAGS_MASK_ISC 0x3800
-#define PMCW_FLAGS_MASK_ENA 0x0080
-#define PMCW_FLAGS_MASK_LM 0x0060
-#define PMCW_FLAGS_MASK_MME 0x0018
-#define PMCW_FLAGS_MASK_MP 0x0004
-#define PMCW_FLAGS_MASK_TF 0x0002
-#define PMCW_FLAGS_MASK_DNV 0x0001
-#define PMCW_FLAGS_MASK_INVALID 0x0700
-
-#define PMCW_CHARS_MASK_ST 0x00e00000
-#define PMCW_CHARS_MASK_MBFC 0x00000004
-#define PMCW_CHARS_MASK_XMWME 0x00000002
-#define PMCW_CHARS_MASK_CSENSE 0x00000001
-#define PMCW_CHARS_MASK_INVALID 0xff1ffff8
-
-/* subchannel information block */
-typedef struct SCHIB {
- PMCW pmcw;
- SCSW scsw;
- uint64_t mba;
- uint8_t mda[4];
-} QEMU_PACKED SCHIB;
-
-/* interruption response block */
-typedef struct IRB {
- SCSW scsw;
- uint32_t esw[5];
- uint32_t ecw[8];
- uint32_t emw[8];
-} QEMU_PACKED IRB;
-
-/* operation request block */
-typedef struct ORB {
- uint32_t intparm;
- uint16_t ctrl0;
- uint8_t lpm;
- uint8_t ctrl1;
- uint32_t cpa;
-} QEMU_PACKED ORB;
-
-#define ORB_CTRL0_MASK_KEY 0xf000
-#define ORB_CTRL0_MASK_SPND 0x0800
-#define ORB_CTRL0_MASK_STR 0x0400
-#define ORB_CTRL0_MASK_MOD 0x0200
-#define ORB_CTRL0_MASK_SYNC 0x0100
-#define ORB_CTRL0_MASK_FMT 0x0080
-#define ORB_CTRL0_MASK_PFCH 0x0040
-#define ORB_CTRL0_MASK_ISIC 0x0020
-#define ORB_CTRL0_MASK_ALCC 0x0010
-#define ORB_CTRL0_MASK_SSIC 0x0008
-#define ORB_CTRL0_MASK_C64 0x0002
-#define ORB_CTRL0_MASK_I2K 0x0001
-#define ORB_CTRL0_MASK_INVALID 0x0004
-
-#define ORB_CTRL1_MASK_ILS 0x80
-#define ORB_CTRL1_MASK_MIDAW 0x40
-#define ORB_CTRL1_MASK_ORBX 0x01
-#define ORB_CTRL1_MASK_INVALID 0x3e
-
-/* channel command word (type 0) */
-typedef struct CCW0 {
- uint8_t cmd_code;
- uint8_t cda0;
- uint16_t cda1;
- uint8_t flags;
- uint8_t reserved;
- uint16_t count;
-} QEMU_PACKED CCW0;
-
-/* channel command word (type 1) */
-typedef struct CCW1 {
- uint8_t cmd_code;
- uint8_t flags;
- uint16_t count;
- uint32_t cda;
-} QEMU_PACKED CCW1;
-
-#define CCW_FLAG_DC 0x80
-#define CCW_FLAG_CC 0x40
-#define CCW_FLAG_SLI 0x20
-#define CCW_FLAG_SKIP 0x10
-#define CCW_FLAG_PCI 0x08
-#define CCW_FLAG_IDA 0x04
-#define CCW_FLAG_SUSPEND 0x02
-
-#define CCW_CMD_NOOP 0x03
-#define CCW_CMD_BASIC_SENSE 0x04
-#define CCW_CMD_TIC 0x08
-#define CCW_CMD_SENSE_ID 0xe4
-
-typedef struct CRW {
- uint16_t flags;
- uint16_t rsid;
-} QEMU_PACKED CRW;
-
-#define CRW_FLAGS_MASK_S 0x4000
-#define CRW_FLAGS_MASK_R 0x2000
-#define CRW_FLAGS_MASK_C 0x1000
-#define CRW_FLAGS_MASK_RSC 0x0f00
-#define CRW_FLAGS_MASK_A 0x0080
-#define CRW_FLAGS_MASK_ERC 0x003f
-
-#define CRW_ERC_INIT 0x02
-#define CRW_ERC_IPI 0x04
-
-#define CRW_RSC_SUBCH 0x3
-#define CRW_RSC_CHP 0x4
-#define CRW_RSC_CSS 0xb
-
-/* I/O interruption code */
-typedef struct IOIntCode {
- uint32_t subsys_id;
- uint32_t intparm;
- uint32_t interrupt_id;
-} QEMU_PACKED IOIntCode;
-
-/* schid disintegration */
-#define IOINST_SCHID_ONE(_schid) ((_schid & 0x00010000) >> 16)
-#define IOINST_SCHID_M(_schid) ((_schid & 0x00080000) >> 19)
-#define IOINST_SCHID_CSSID(_schid) ((_schid & 0xff000000) >> 24)
-#define IOINST_SCHID_SSID(_schid) ((_schid & 0x00060000) >> 17)
-#define IOINST_SCHID_NR(_schid) (_schid & 0x0000ffff)
-
-#define IO_INT_WORD_ISC(_int_word) ((_int_word & 0x38000000) >> 27)
-#define ISC_TO_ISC_BITS(_isc) ((0x80 >> _isc) << 24)
-
-#define IO_INT_WORD_AI 0x80000000
-
-int ioinst_disassemble_sch_ident(uint32_t value, int *m, int *cssid, int *ssid,
- int *schid);
-void ioinst_handle_xsch(S390CPU *cpu, uint64_t reg1);
-void ioinst_handle_csch(S390CPU *cpu, uint64_t reg1);
-void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1);
-void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
-void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
-void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb);
-void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
-int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
-void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb);
-int ioinst_handle_tpi(S390CPU *cpu, uint32_t ipb);
-void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2,
- uint32_t ipb);
-void ioinst_handle_rsch(S390CPU *cpu, uint64_t reg1);
-void ioinst_handle_rchp(S390CPU *cpu, uint64_t reg1);
-void ioinst_handle_sal(S390CPU *cpu, uint64_t reg1);
-
-#endif
diff --git a/qemu/target-s390x/kvm.c b/qemu/target-s390x/kvm.c
deleted file mode 100644
index e1859cae0..000000000
--- a/qemu/target-s390x/kvm.c
+++ /dev/null
@@ -1,2252 +0,0 @@
-/*
- * QEMU S390x KVM implementation
- *
- * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
- * Copyright IBM Corp. 2012
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * Contributions after 2012-10-29 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- *
- * You should have received a copy of the GNU (Lesser) General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-
-#include <linux/kvm.h>
-#include <asm/ptrace.h>
-
-#include "qemu-common.h"
-#include "qemu/error-report.h"
-#include "qemu/timer.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/kvm.h"
-#include "hw/hw.h"
-#include "cpu.h"
-#include "sysemu/device_tree.h"
-#include "qapi/qmp/qjson.h"
-#include "exec/gdbstub.h"
-#include "exec/address-spaces.h"
-#include "trace.h"
-#include "qapi-event.h"
-#include "hw/s390x/s390-pci-inst.h"
-#include "hw/s390x/s390-pci-bus.h"
-#include "hw/s390x/ipl.h"
-#include "hw/s390x/ebcdic.h"
-#include "exec/memattrs.h"
-
-/* #define DEBUG_KVM */
-
-#ifdef DEBUG_KVM
-#define DPRINTF(fmt, ...) \
- do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
- do { } while (0)
-#endif
-
-#define kvm_vm_check_mem_attr(s, attr) \
- kvm_vm_check_attr(s, KVM_S390_VM_MEM_CTRL, attr)
-
-#define IPA0_DIAG 0x8300
-#define IPA0_SIGP 0xae00
-#define IPA0_B2 0xb200
-#define IPA0_B9 0xb900
-#define IPA0_EB 0xeb00
-#define IPA0_E3 0xe300
-
-#define PRIV_B2_SCLP_CALL 0x20
-#define PRIV_B2_CSCH 0x30
-#define PRIV_B2_HSCH 0x31
-#define PRIV_B2_MSCH 0x32
-#define PRIV_B2_SSCH 0x33
-#define PRIV_B2_STSCH 0x34
-#define PRIV_B2_TSCH 0x35
-#define PRIV_B2_TPI 0x36
-#define PRIV_B2_SAL 0x37
-#define PRIV_B2_RSCH 0x38
-#define PRIV_B2_STCRW 0x39
-#define PRIV_B2_STCPS 0x3a
-#define PRIV_B2_RCHP 0x3b
-#define PRIV_B2_SCHM 0x3c
-#define PRIV_B2_CHSC 0x5f
-#define PRIV_B2_SIGA 0x74
-#define PRIV_B2_XSCH 0x76
-
-#define PRIV_EB_SQBS 0x8a
-#define PRIV_EB_PCISTB 0xd0
-#define PRIV_EB_SIC 0xd1
-
-#define PRIV_B9_EQBS 0x9c
-#define PRIV_B9_CLP 0xa0
-#define PRIV_B9_PCISTG 0xd0
-#define PRIV_B9_PCILG 0xd2
-#define PRIV_B9_RPCIT 0xd3
-
-#define PRIV_E3_MPCIFC 0xd0
-#define PRIV_E3_STPCIFC 0xd4
-
-#define DIAG_TIMEREVENT 0x288
-#define DIAG_IPL 0x308
-#define DIAG_KVM_HYPERCALL 0x500
-#define DIAG_KVM_BREAKPOINT 0x501
-
-#define ICPT_INSTRUCTION 0x04
-#define ICPT_PROGRAM 0x08
-#define ICPT_EXT_INT 0x14
-#define ICPT_WAITPSW 0x1c
-#define ICPT_SOFT_INTERCEPT 0x24
-#define ICPT_CPU_STOP 0x28
-#define ICPT_IO 0x40
-
-#define NR_LOCAL_IRQS 32
-/*
- * Needs to be big enough to contain max_cpus emergency signals
- * and in addition NR_LOCAL_IRQS interrupts
- */
-#define VCPU_IRQ_BUF_SIZE (sizeof(struct kvm_s390_irq) * \
- (max_cpus + NR_LOCAL_IRQS))
-
-static CPUWatchpoint hw_watchpoint;
-/*
- * We don't use a list because this structure is also used to transmit the
- * hardware breakpoints to the kernel.
- */
-static struct kvm_hw_breakpoint *hw_breakpoints;
-static int nb_hw_breakpoints;
-
-const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
- KVM_CAP_LAST_INFO
-};
-
-static int cap_sync_regs;
-static int cap_async_pf;
-static int cap_mem_op;
-static int cap_s390_irq;
-
-static void *legacy_s390_alloc(size_t size, uint64_t *align);
-
-static int kvm_s390_query_mem_limit(KVMState *s, uint64_t *memory_limit)
-{
- struct kvm_device_attr attr = {
- .group = KVM_S390_VM_MEM_CTRL,
- .attr = KVM_S390_VM_MEM_LIMIT_SIZE,
- .addr = (uint64_t) memory_limit,
- };
-
- return kvm_vm_ioctl(s, KVM_GET_DEVICE_ATTR, &attr);
-}
-
-int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit)
-{
- int rc;
-
- struct kvm_device_attr attr = {
- .group = KVM_S390_VM_MEM_CTRL,
- .attr = KVM_S390_VM_MEM_LIMIT_SIZE,
- .addr = (uint64_t) &new_limit,
- };
-
- if (!kvm_vm_check_mem_attr(s, KVM_S390_VM_MEM_LIMIT_SIZE)) {
- return 0;
- }
-
- rc = kvm_s390_query_mem_limit(s, hw_limit);
- if (rc) {
- return rc;
- } else if (*hw_limit < new_limit) {
- return -E2BIG;
- }
-
- return kvm_vm_ioctl(s, KVM_SET_DEVICE_ATTR, &attr);
-}
-
-void kvm_s390_cmma_reset(void)
-{
- int rc;
- struct kvm_device_attr attr = {
- .group = KVM_S390_VM_MEM_CTRL,
- .attr = KVM_S390_VM_MEM_CLR_CMMA,
- };
-
- rc = kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
- trace_kvm_clear_cmma(rc);
-}
-
-static void kvm_s390_enable_cmma(KVMState *s)
-{
- int rc;
- struct kvm_device_attr attr = {
- .group = KVM_S390_VM_MEM_CTRL,
- .attr = KVM_S390_VM_MEM_ENABLE_CMMA,
- };
-
- if (!kvm_vm_check_mem_attr(s, KVM_S390_VM_MEM_ENABLE_CMMA) ||
- !kvm_vm_check_mem_attr(s, KVM_S390_VM_MEM_CLR_CMMA)) {
- return;
- }
-
- rc = kvm_vm_ioctl(s, KVM_SET_DEVICE_ATTR, &attr);
- trace_kvm_enable_cmma(rc);
-}
-
-static void kvm_s390_set_attr(uint64_t attr)
-{
- struct kvm_device_attr attribute = {
- .group = KVM_S390_VM_CRYPTO,
- .attr = attr,
- };
-
- int ret = kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attribute);
-
- if (ret) {
- error_report("Failed to set crypto device attribute %lu: %s",
- attr, strerror(-ret));
- }
-}
-
-static void kvm_s390_init_aes_kw(void)
-{
- uint64_t attr = KVM_S390_VM_CRYPTO_DISABLE_AES_KW;
-
- if (object_property_get_bool(OBJECT(qdev_get_machine()), "aes-key-wrap",
- NULL)) {
- attr = KVM_S390_VM_CRYPTO_ENABLE_AES_KW;
- }
-
- if (kvm_vm_check_attr(kvm_state, KVM_S390_VM_CRYPTO, attr)) {
- kvm_s390_set_attr(attr);
- }
-}
-
-static void kvm_s390_init_dea_kw(void)
-{
- uint64_t attr = KVM_S390_VM_CRYPTO_DISABLE_DEA_KW;
-
- if (object_property_get_bool(OBJECT(qdev_get_machine()), "dea-key-wrap",
- NULL)) {
- attr = KVM_S390_VM_CRYPTO_ENABLE_DEA_KW;
- }
-
- if (kvm_vm_check_attr(kvm_state, KVM_S390_VM_CRYPTO, attr)) {
- kvm_s390_set_attr(attr);
- }
-}
-
-void kvm_s390_crypto_reset(void)
-{
- kvm_s390_init_aes_kw();
- kvm_s390_init_dea_kw();
-}
-
-int kvm_arch_init(MachineState *ms, KVMState *s)
-{
- cap_sync_regs = kvm_check_extension(s, KVM_CAP_SYNC_REGS);
- cap_async_pf = kvm_check_extension(s, KVM_CAP_ASYNC_PF);
- cap_mem_op = kvm_check_extension(s, KVM_CAP_S390_MEM_OP);
- cap_s390_irq = kvm_check_extension(s, KVM_CAP_S390_INJECT_IRQ);
-
- if (!mem_path) {
- kvm_s390_enable_cmma(s);
- }
-
- if (!kvm_check_extension(s, KVM_CAP_S390_GMAP)
- || !kvm_check_extension(s, KVM_CAP_S390_COW)) {
- phys_mem_set_alloc(legacy_s390_alloc);
- }
-
- kvm_vm_enable_cap(s, KVM_CAP_S390_USER_SIGP, 0);
- kvm_vm_enable_cap(s, KVM_CAP_S390_VECTOR_REGISTERS, 0);
- kvm_vm_enable_cap(s, KVM_CAP_S390_USER_STSI, 0);
-
- return 0;
-}
-
-unsigned long kvm_arch_vcpu_id(CPUState *cpu)
-{
- return cpu->cpu_index;
-}
-
-int kvm_arch_init_vcpu(CPUState *cs)
-{
- S390CPU *cpu = S390_CPU(cs);
- kvm_s390_set_cpu_state(cpu, cpu->env.cpu_state);
- cpu->irqstate = g_malloc0(VCPU_IRQ_BUF_SIZE);
- return 0;
-}
-
-void kvm_s390_reset_vcpu(S390CPU *cpu)
-{
- CPUState *cs = CPU(cpu);
-
- /* The initial reset call is needed here to reset in-kernel
- * vcpu data that we can't access directly from QEMU
- * (i.e. with older kernels which don't support sync_regs/ONE_REG).
- * Before this ioctl cpu_synchronize_state() is called in common kvm
- * code (kvm-all) */
- if (kvm_vcpu_ioctl(cs, KVM_S390_INITIAL_RESET, NULL)) {
- error_report("Initial CPU reset failed on CPU %i", cs->cpu_index);
- }
-}
-
-static int can_sync_regs(CPUState *cs, int regs)
-{
- return cap_sync_regs && (cs->kvm_run->kvm_valid_regs & regs) == regs;
-}
-
-int kvm_arch_put_registers(CPUState *cs, int level)
-{
- S390CPU *cpu = S390_CPU(cs);
- CPUS390XState *env = &cpu->env;
- struct kvm_sregs sregs;
- struct kvm_regs regs;
- struct kvm_fpu fpu = {};
- int r;
- int i;
-
- /* always save the PSW and the GPRS*/
- cs->kvm_run->psw_addr = env->psw.addr;
- cs->kvm_run->psw_mask = env->psw.mask;
-
- if (can_sync_regs(cs, KVM_SYNC_GPRS)) {
- for (i = 0; i < 16; i++) {
- cs->kvm_run->s.regs.gprs[i] = env->regs[i];
- cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_GPRS;
- }
- } else {
- for (i = 0; i < 16; i++) {
- regs.gprs[i] = env->regs[i];
- }
- r = kvm_vcpu_ioctl(cs, KVM_SET_REGS, &regs);
- if (r < 0) {
- return r;
- }
- }
-
- if (can_sync_regs(cs, KVM_SYNC_VRS)) {
- for (i = 0; i < 32; i++) {
- cs->kvm_run->s.regs.vrs[i][0] = env->vregs[i][0].ll;
- cs->kvm_run->s.regs.vrs[i][1] = env->vregs[i][1].ll;
- }
- cs->kvm_run->s.regs.fpc = env->fpc;
- cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_VRS;
- } else if (can_sync_regs(cs, KVM_SYNC_FPRS)) {
- for (i = 0; i < 16; i++) {
- cs->kvm_run->s.regs.fprs[i] = get_freg(env, i)->ll;
- }
- cs->kvm_run->s.regs.fpc = env->fpc;
- cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_FPRS;
- } else {
- /* Floating point */
- for (i = 0; i < 16; i++) {
- fpu.fprs[i] = get_freg(env, i)->ll;
- }
- fpu.fpc = env->fpc;
-
- r = kvm_vcpu_ioctl(cs, KVM_SET_FPU, &fpu);
- if (r < 0) {
- return r;
- }
- }
-
- /* Do we need to save more than that? */
- if (level == KVM_PUT_RUNTIME_STATE) {
- return 0;
- }
-
- if (can_sync_regs(cs, KVM_SYNC_ARCH0)) {
- cs->kvm_run->s.regs.cputm = env->cputm;
- cs->kvm_run->s.regs.ckc = env->ckc;
- cs->kvm_run->s.regs.todpr = env->todpr;
- cs->kvm_run->s.regs.gbea = env->gbea;
- cs->kvm_run->s.regs.pp = env->pp;
- cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_ARCH0;
- } else {
- /*
- * These ONE_REGS are not protected by a capability. As they are only
- * necessary for migration we just trace a possible error, but don't
- * return with an error return code.
- */
- kvm_set_one_reg(cs, KVM_REG_S390_CPU_TIMER, &env->cputm);
- kvm_set_one_reg(cs, KVM_REG_S390_CLOCK_COMP, &env->ckc);
- kvm_set_one_reg(cs, KVM_REG_S390_TODPR, &env->todpr);
- kvm_set_one_reg(cs, KVM_REG_S390_GBEA, &env->gbea);
- kvm_set_one_reg(cs, KVM_REG_S390_PP, &env->pp);
- }
-
- /* pfault parameters */
- if (can_sync_regs(cs, KVM_SYNC_PFAULT)) {
- cs->kvm_run->s.regs.pft = env->pfault_token;
- cs->kvm_run->s.regs.pfs = env->pfault_select;
- cs->kvm_run->s.regs.pfc = env->pfault_compare;
- cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_PFAULT;
- } else if (cap_async_pf) {
- r = kvm_set_one_reg(cs, KVM_REG_S390_PFTOKEN, &env->pfault_token);
- if (r < 0) {
- return r;
- }
- r = kvm_set_one_reg(cs, KVM_REG_S390_PFCOMPARE, &env->pfault_compare);
- if (r < 0) {
- return r;
- }
- r = kvm_set_one_reg(cs, KVM_REG_S390_PFSELECT, &env->pfault_select);
- if (r < 0) {
- return r;
- }
- }
-
- /* access registers and control registers*/
- if (can_sync_regs(cs, KVM_SYNC_ACRS | KVM_SYNC_CRS)) {
- for (i = 0; i < 16; i++) {
- cs->kvm_run->s.regs.acrs[i] = env->aregs[i];
- cs->kvm_run->s.regs.crs[i] = env->cregs[i];
- }
- cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_ACRS;
- cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_CRS;
- } else {
- for (i = 0; i < 16; i++) {
- sregs.acrs[i] = env->aregs[i];
- sregs.crs[i] = env->cregs[i];
- }
- r = kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs);
- if (r < 0) {
- return r;
- }
- }
-
- /* Finally the prefix */
- if (can_sync_regs(cs, KVM_SYNC_PREFIX)) {
- cs->kvm_run->s.regs.prefix = env->psa;
- cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_PREFIX;
- } else {
- /* prefix is only supported via sync regs */
- }
- return 0;
-}
-
-int kvm_arch_get_registers(CPUState *cs)
-{
- S390CPU *cpu = S390_CPU(cs);
- CPUS390XState *env = &cpu->env;
- struct kvm_sregs sregs;
- struct kvm_regs regs;
- struct kvm_fpu fpu;
- int i, r;
-
- /* get the PSW */
- env->psw.addr = cs->kvm_run->psw_addr;
- env->psw.mask = cs->kvm_run->psw_mask;
-
- /* the GPRS */
- if (can_sync_regs(cs, KVM_SYNC_GPRS)) {
- for (i = 0; i < 16; i++) {
- env->regs[i] = cs->kvm_run->s.regs.gprs[i];
- }
- } else {
- r = kvm_vcpu_ioctl(cs, KVM_GET_REGS, &regs);
- if (r < 0) {
- return r;
- }
- for (i = 0; i < 16; i++) {
- env->regs[i] = regs.gprs[i];
- }
- }
-
- /* The ACRS and CRS */
- if (can_sync_regs(cs, KVM_SYNC_ACRS | KVM_SYNC_CRS)) {
- for (i = 0; i < 16; i++) {
- env->aregs[i] = cs->kvm_run->s.regs.acrs[i];
- env->cregs[i] = cs->kvm_run->s.regs.crs[i];
- }
- } else {
- r = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs);
- if (r < 0) {
- return r;
- }
- for (i = 0; i < 16; i++) {
- env->aregs[i] = sregs.acrs[i];
- env->cregs[i] = sregs.crs[i];
- }
- }
-
- /* Floating point and vector registers */
- if (can_sync_regs(cs, KVM_SYNC_VRS)) {
- for (i = 0; i < 32; i++) {
- env->vregs[i][0].ll = cs->kvm_run->s.regs.vrs[i][0];
- env->vregs[i][1].ll = cs->kvm_run->s.regs.vrs[i][1];
- }
- env->fpc = cs->kvm_run->s.regs.fpc;
- } else if (can_sync_regs(cs, KVM_SYNC_FPRS)) {
- for (i = 0; i < 16; i++) {
- get_freg(env, i)->ll = cs->kvm_run->s.regs.fprs[i];
- }
- env->fpc = cs->kvm_run->s.regs.fpc;
- } else {
- r = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu);
- if (r < 0) {
- return r;
- }
- for (i = 0; i < 16; i++) {
- get_freg(env, i)->ll = fpu.fprs[i];
- }
- env->fpc = fpu.fpc;
- }
-
- /* The prefix */
- if (can_sync_regs(cs, KVM_SYNC_PREFIX)) {
- env->psa = cs->kvm_run->s.regs.prefix;
- }
-
- if (can_sync_regs(cs, KVM_SYNC_ARCH0)) {
- env->cputm = cs->kvm_run->s.regs.cputm;
- env->ckc = cs->kvm_run->s.regs.ckc;
- env->todpr = cs->kvm_run->s.regs.todpr;
- env->gbea = cs->kvm_run->s.regs.gbea;
- env->pp = cs->kvm_run->s.regs.pp;
- } else {
- /*
- * These ONE_REGS are not protected by a capability. As they are only
- * necessary for migration we just trace a possible error, but don't
- * return with an error return code.
- */
- kvm_get_one_reg(cs, KVM_REG_S390_CPU_TIMER, &env->cputm);
- kvm_get_one_reg(cs, KVM_REG_S390_CLOCK_COMP, &env->ckc);
- kvm_get_one_reg(cs, KVM_REG_S390_TODPR, &env->todpr);
- kvm_get_one_reg(cs, KVM_REG_S390_GBEA, &env->gbea);
- kvm_get_one_reg(cs, KVM_REG_S390_PP, &env->pp);
- }
-
- /* pfault parameters */
- if (can_sync_regs(cs, KVM_SYNC_PFAULT)) {
- env->pfault_token = cs->kvm_run->s.regs.pft;
- env->pfault_select = cs->kvm_run->s.regs.pfs;
- env->pfault_compare = cs->kvm_run->s.regs.pfc;
- } else if (cap_async_pf) {
- r = kvm_get_one_reg(cs, KVM_REG_S390_PFTOKEN, &env->pfault_token);
- if (r < 0) {
- return r;
- }
- r = kvm_get_one_reg(cs, KVM_REG_S390_PFCOMPARE, &env->pfault_compare);
- if (r < 0) {
- return r;
- }
- r = kvm_get_one_reg(cs, KVM_REG_S390_PFSELECT, &env->pfault_select);
- if (r < 0) {
- return r;
- }
- }
-
- return 0;
-}
-
-int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_low)
-{
- int r;
- struct kvm_device_attr attr = {
- .group = KVM_S390_VM_TOD,
- .attr = KVM_S390_VM_TOD_LOW,
- .addr = (uint64_t)tod_low,
- };
-
- r = kvm_vm_ioctl(kvm_state, KVM_GET_DEVICE_ATTR, &attr);
- if (r) {
- return r;
- }
-
- attr.attr = KVM_S390_VM_TOD_HIGH;
- attr.addr = (uint64_t)tod_high;
- return kvm_vm_ioctl(kvm_state, KVM_GET_DEVICE_ATTR, &attr);
-}
-
-int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
-{
- int r;
-
- struct kvm_device_attr attr = {
- .group = KVM_S390_VM_TOD,
- .attr = KVM_S390_VM_TOD_LOW,
- .addr = (uint64_t)tod_low,
- };
-
- r = kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
- if (r) {
- return r;
- }
-
- attr.attr = KVM_S390_VM_TOD_HIGH;
- attr.addr = (uint64_t)tod_high;
- return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
-}
-
-/**
- * kvm_s390_mem_op:
- * @addr: the logical start address in guest memory
- * @ar: the access register number
- * @hostbuf: buffer in host memory. NULL = do only checks w/o copying
- * @len: length that should be transferred
- * @is_write: true = write, false = read
- * Returns: 0 on success, non-zero if an exception or error occurred
- *
- * Use KVM ioctl to read/write from/to guest memory. An access exception
- * is injected into the vCPU in case of translation errors.
- */
-int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf,
- int len, bool is_write)
-{
- struct kvm_s390_mem_op mem_op = {
- .gaddr = addr,
- .flags = KVM_S390_MEMOP_F_INJECT_EXCEPTION,
- .size = len,
- .op = is_write ? KVM_S390_MEMOP_LOGICAL_WRITE
- : KVM_S390_MEMOP_LOGICAL_READ,
- .buf = (uint64_t)hostbuf,
- .ar = ar,
- };
- int ret;
-
- if (!cap_mem_op) {
- return -ENOSYS;
- }
- if (!hostbuf) {
- mem_op.flags |= KVM_S390_MEMOP_F_CHECK_ONLY;
- }
-
- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_S390_MEM_OP, &mem_op);
- if (ret < 0) {
- error_printf("KVM_S390_MEM_OP failed: %s\n", strerror(-ret));
- }
- return ret;
-}
-
-/*
- * Legacy layout for s390:
- * Older S390 KVM requires the topmost vma of the RAM to be
- * smaller than an system defined value, which is at least 256GB.
- * Larger systems have larger values. We put the guest between
- * the end of data segment (system break) and this value. We
- * use 32GB as a base to have enough room for the system break
- * to grow. We also have to use MAP parameters that avoid
- * read-only mapping of guest pages.
- */
-static void *legacy_s390_alloc(size_t size, uint64_t *align)
-{
- void *mem;
-
- mem = mmap((void *) 0x800000000ULL, size,
- PROT_EXEC|PROT_READ|PROT_WRITE,
- MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
- return mem == MAP_FAILED ? NULL : mem;
-}
-
-/* DIAG 501 is used for sw breakpoints */
-static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01};
-
-int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
-{
-
- if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn,
- sizeof(diag_501), 0) ||
- cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)diag_501,
- sizeof(diag_501), 1)) {
- return -EINVAL;
- }
- return 0;
-}
-
-int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
-{
- uint8_t t[sizeof(diag_501)];
-
- if (cpu_memory_rw_debug(cs, bp->pc, t, sizeof(diag_501), 0)) {
- return -EINVAL;
- } else if (memcmp(t, diag_501, sizeof(diag_501))) {
- return -EINVAL;
- } else if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn,
- sizeof(diag_501), 1)) {
- return -EINVAL;
- }
-
- return 0;
-}
-
-static struct kvm_hw_breakpoint *find_hw_breakpoint(target_ulong addr,
- int len, int type)
-{
- int n;
-
- for (n = 0; n < nb_hw_breakpoints; n++) {
- if (hw_breakpoints[n].addr == addr && hw_breakpoints[n].type == type &&
- (hw_breakpoints[n].len == len || len == -1)) {
- return &hw_breakpoints[n];
- }
- }
-
- return NULL;
-}
-
-static int insert_hw_breakpoint(target_ulong addr, int len, int type)
-{
- int size;
-
- if (find_hw_breakpoint(addr, len, type)) {
- return -EEXIST;
- }
-
- size = (nb_hw_breakpoints + 1) * sizeof(struct kvm_hw_breakpoint);
-
- if (!hw_breakpoints) {
- nb_hw_breakpoints = 0;
- hw_breakpoints = (struct kvm_hw_breakpoint *)g_try_malloc(size);
- } else {
- hw_breakpoints =
- (struct kvm_hw_breakpoint *)g_try_realloc(hw_breakpoints, size);
- }
-
- if (!hw_breakpoints) {
- nb_hw_breakpoints = 0;
- return -ENOMEM;
- }
-
- hw_breakpoints[nb_hw_breakpoints].addr = addr;
- hw_breakpoints[nb_hw_breakpoints].len = len;
- hw_breakpoints[nb_hw_breakpoints].type = type;
-
- nb_hw_breakpoints++;
-
- return 0;
-}
-
-int kvm_arch_insert_hw_breakpoint(target_ulong addr,
- target_ulong len, int type)
-{
- switch (type) {
- case GDB_BREAKPOINT_HW:
- type = KVM_HW_BP;
- break;
- case GDB_WATCHPOINT_WRITE:
- if (len < 1) {
- return -EINVAL;
- }
- type = KVM_HW_WP_WRITE;
- break;
- default:
- return -ENOSYS;
- }
- return insert_hw_breakpoint(addr, len, type);
-}
-
-int kvm_arch_remove_hw_breakpoint(target_ulong addr,
- target_ulong len, int type)
-{
- int size;
- struct kvm_hw_breakpoint *bp = find_hw_breakpoint(addr, len, type);
-
- if (bp == NULL) {
- return -ENOENT;
- }
-
- nb_hw_breakpoints--;
- if (nb_hw_breakpoints > 0) {
- /*
- * In order to trim the array, move the last element to the position to
- * be removed - if necessary.
- */
- if (bp != &hw_breakpoints[nb_hw_breakpoints]) {
- *bp = hw_breakpoints[nb_hw_breakpoints];
- }
- size = nb_hw_breakpoints * sizeof(struct kvm_hw_breakpoint);
- hw_breakpoints =
- (struct kvm_hw_breakpoint *)g_realloc(hw_breakpoints, size);
- } else {
- g_free(hw_breakpoints);
- hw_breakpoints = NULL;
- }
-
- return 0;
-}
-
-void kvm_arch_remove_all_hw_breakpoints(void)
-{
- nb_hw_breakpoints = 0;
- g_free(hw_breakpoints);
- hw_breakpoints = NULL;
-}
-
-void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg)
-{
- int i;
-
- if (nb_hw_breakpoints > 0) {
- dbg->arch.nr_hw_bp = nb_hw_breakpoints;
- dbg->arch.hw_bp = hw_breakpoints;
-
- for (i = 0; i < nb_hw_breakpoints; ++i) {
- hw_breakpoints[i].phys_addr = s390_cpu_get_phys_addr_debug(cpu,
- hw_breakpoints[i].addr);
- }
- dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP;
- } else {
- dbg->arch.nr_hw_bp = 0;
- dbg->arch.hw_bp = NULL;
- }
-}
-
-void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
-{
-}
-
-MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
-{
- return MEMTXATTRS_UNSPECIFIED;
-}
-
-int kvm_arch_process_async_events(CPUState *cs)
-{
- return cs->halted;
-}
-
-static int s390_kvm_irq_to_interrupt(struct kvm_s390_irq *irq,
- struct kvm_s390_interrupt *interrupt)
-{
- int r = 0;
-
- interrupt->type = irq->type;
- switch (irq->type) {
- case KVM_S390_INT_VIRTIO:
- interrupt->parm = irq->u.ext.ext_params;
- /* fall through */
- case KVM_S390_INT_PFAULT_INIT:
- case KVM_S390_INT_PFAULT_DONE:
- interrupt->parm64 = irq->u.ext.ext_params2;
- break;
- case KVM_S390_PROGRAM_INT:
- interrupt->parm = irq->u.pgm.code;
- break;
- case KVM_S390_SIGP_SET_PREFIX:
- interrupt->parm = irq->u.prefix.address;
- break;
- case KVM_S390_INT_SERVICE:
- interrupt->parm = irq->u.ext.ext_params;
- break;
- case KVM_S390_MCHK:
- interrupt->parm = irq->u.mchk.cr14;
- interrupt->parm64 = irq->u.mchk.mcic;
- break;
- case KVM_S390_INT_EXTERNAL_CALL:
- interrupt->parm = irq->u.extcall.code;
- break;
- case KVM_S390_INT_EMERGENCY:
- interrupt->parm = irq->u.emerg.code;
- break;
- case KVM_S390_SIGP_STOP:
- case KVM_S390_RESTART:
- break; /* These types have no parameters */
- case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
- interrupt->parm = irq->u.io.subchannel_id << 16;
- interrupt->parm |= irq->u.io.subchannel_nr;
- interrupt->parm64 = (uint64_t)irq->u.io.io_int_parm << 32;
- interrupt->parm64 |= irq->u.io.io_int_word;
- break;
- default:
- r = -EINVAL;
- break;
- }
- return r;
-}
-
-static void inject_vcpu_irq_legacy(CPUState *cs, struct kvm_s390_irq *irq)
-{
- struct kvm_s390_interrupt kvmint = {};
- int r;
-
- r = s390_kvm_irq_to_interrupt(irq, &kvmint);
- if (r < 0) {
- fprintf(stderr, "%s called with bogus interrupt\n", __func__);
- exit(1);
- }
-
- r = kvm_vcpu_ioctl(cs, KVM_S390_INTERRUPT, &kvmint);
- if (r < 0) {
- fprintf(stderr, "KVM failed to inject interrupt\n");
- exit(1);
- }
-}
-
-void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq)
-{
- CPUState *cs = CPU(cpu);
- int r;
-
- if (cap_s390_irq) {
- r = kvm_vcpu_ioctl(cs, KVM_S390_IRQ, irq);
- if (!r) {
- return;
- }
- error_report("KVM failed to inject interrupt %llx", irq->type);
- exit(1);
- }
-
- inject_vcpu_irq_legacy(cs, irq);
-}
-
-static void __kvm_s390_floating_interrupt(struct kvm_s390_irq *irq)
-{
- struct kvm_s390_interrupt kvmint = {};
- int r;
-
- r = s390_kvm_irq_to_interrupt(irq, &kvmint);
- if (r < 0) {
- fprintf(stderr, "%s called with bogus interrupt\n", __func__);
- exit(1);
- }
-
- r = kvm_vm_ioctl(kvm_state, KVM_S390_INTERRUPT, &kvmint);
- if (r < 0) {
- fprintf(stderr, "KVM failed to inject interrupt\n");
- exit(1);
- }
-}
-
-void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq)
-{
- static bool use_flic = true;
- int r;
-
- if (use_flic) {
- r = kvm_s390_inject_flic(irq);
- if (r == -ENOSYS) {
- use_flic = false;
- }
- if (!r) {
- return;
- }
- }
- __kvm_s390_floating_interrupt(irq);
-}
-
-void kvm_s390_service_interrupt(uint32_t parm)
-{
- struct kvm_s390_irq irq = {
- .type = KVM_S390_INT_SERVICE,
- .u.ext.ext_params = parm,
- };
-
- kvm_s390_floating_interrupt(&irq);
-}
-
-static void enter_pgmcheck(S390CPU *cpu, uint16_t code)
-{
- struct kvm_s390_irq irq = {
- .type = KVM_S390_PROGRAM_INT,
- .u.pgm.code = code,
- };
-
- kvm_s390_vcpu_interrupt(cpu, &irq);
-}
-
-void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code)
-{
- struct kvm_s390_irq irq = {
- .type = KVM_S390_PROGRAM_INT,
- .u.pgm.code = code,
- .u.pgm.trans_exc_code = te_code,
- .u.pgm.exc_access_id = te_code & 3,
- };
-
- kvm_s390_vcpu_interrupt(cpu, &irq);
-}
-
-static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run,
- uint16_t ipbh0)
-{
- CPUS390XState *env = &cpu->env;
- uint64_t sccb;
- uint32_t code;
- int r = 0;
-
- cpu_synchronize_state(CPU(cpu));
- sccb = env->regs[ipbh0 & 0xf];
- code = env->regs[(ipbh0 & 0xf0) >> 4];
-
- r = sclp_service_call(env, sccb, code);
- if (r < 0) {
- enter_pgmcheck(cpu, -r);
- } else {
- setcc(cpu, r);
- }
-
- return 0;
-}
-
-static int handle_b2(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
-{
- CPUS390XState *env = &cpu->env;
- int rc = 0;
- uint16_t ipbh0 = (run->s390_sieic.ipb & 0xffff0000) >> 16;
-
- cpu_synchronize_state(CPU(cpu));
-
- switch (ipa1) {
- case PRIV_B2_XSCH:
- ioinst_handle_xsch(cpu, env->regs[1]);
- break;
- case PRIV_B2_CSCH:
- ioinst_handle_csch(cpu, env->regs[1]);
- break;
- case PRIV_B2_HSCH:
- ioinst_handle_hsch(cpu, env->regs[1]);
- break;
- case PRIV_B2_MSCH:
- ioinst_handle_msch(cpu, env->regs[1], run->s390_sieic.ipb);
- break;
- case PRIV_B2_SSCH:
- ioinst_handle_ssch(cpu, env->regs[1], run->s390_sieic.ipb);
- break;
- case PRIV_B2_STCRW:
- ioinst_handle_stcrw(cpu, run->s390_sieic.ipb);
- break;
- case PRIV_B2_STSCH:
- ioinst_handle_stsch(cpu, env->regs[1], run->s390_sieic.ipb);
- break;
- case PRIV_B2_TSCH:
- /* We should only get tsch via KVM_EXIT_S390_TSCH. */
- fprintf(stderr, "Spurious tsch intercept\n");
- break;
- case PRIV_B2_CHSC:
- ioinst_handle_chsc(cpu, run->s390_sieic.ipb);
- break;
- case PRIV_B2_TPI:
- /* This should have been handled by kvm already. */
- fprintf(stderr, "Spurious tpi intercept\n");
- break;
- case PRIV_B2_SCHM:
- ioinst_handle_schm(cpu, env->regs[1], env->regs[2],
- run->s390_sieic.ipb);
- break;
- case PRIV_B2_RSCH:
- ioinst_handle_rsch(cpu, env->regs[1]);
- break;
- case PRIV_B2_RCHP:
- ioinst_handle_rchp(cpu, env->regs[1]);
- break;
- case PRIV_B2_STCPS:
- /* We do not provide this instruction, it is suppressed. */
- break;
- case PRIV_B2_SAL:
- ioinst_handle_sal(cpu, env->regs[1]);
- break;
- case PRIV_B2_SIGA:
- /* Not provided, set CC = 3 for subchannel not operational */
- setcc(cpu, 3);
- break;
- case PRIV_B2_SCLP_CALL:
- rc = kvm_sclp_service_call(cpu, run, ipbh0);
- break;
- default:
- rc = -1;
- DPRINTF("KVM: unhandled PRIV: 0xb2%x\n", ipa1);
- break;
- }
-
- return rc;
-}
-
-static uint64_t get_base_disp_rxy(S390CPU *cpu, struct kvm_run *run,
- uint8_t *ar)
-{
- CPUS390XState *env = &cpu->env;
- uint32_t x2 = (run->s390_sieic.ipa & 0x000f);
- uint32_t base2 = run->s390_sieic.ipb >> 28;
- uint32_t disp2 = ((run->s390_sieic.ipb & 0x0fff0000) >> 16) +
- ((run->s390_sieic.ipb & 0xff00) << 4);
-
- if (disp2 & 0x80000) {
- disp2 += 0xfff00000;
- }
- if (ar) {
- *ar = base2;
- }
-
- return (base2 ? env->regs[base2] : 0) +
- (x2 ? env->regs[x2] : 0) + (long)(int)disp2;
-}
-
-static uint64_t get_base_disp_rsy(S390CPU *cpu, struct kvm_run *run,
- uint8_t *ar)
-{
- CPUS390XState *env = &cpu->env;
- uint32_t base2 = run->s390_sieic.ipb >> 28;
- uint32_t disp2 = ((run->s390_sieic.ipb & 0x0fff0000) >> 16) +
- ((run->s390_sieic.ipb & 0xff00) << 4);
-
- if (disp2 & 0x80000) {
- disp2 += 0xfff00000;
- }
- if (ar) {
- *ar = base2;
- }
-
- return (base2 ? env->regs[base2] : 0) + (long)(int)disp2;
-}
-
-static int kvm_clp_service_call(S390CPU *cpu, struct kvm_run *run)
-{
- uint8_t r2 = (run->s390_sieic.ipb & 0x000f0000) >> 16;
-
- return clp_service_call(cpu, r2);
-}
-
-static int kvm_pcilg_service_call(S390CPU *cpu, struct kvm_run *run)
-{
- uint8_t r1 = (run->s390_sieic.ipb & 0x00f00000) >> 20;
- uint8_t r2 = (run->s390_sieic.ipb & 0x000f0000) >> 16;
-
- return pcilg_service_call(cpu, r1, r2);
-}
-
-static int kvm_pcistg_service_call(S390CPU *cpu, struct kvm_run *run)
-{
- uint8_t r1 = (run->s390_sieic.ipb & 0x00f00000) >> 20;
- uint8_t r2 = (run->s390_sieic.ipb & 0x000f0000) >> 16;
-
- return pcistg_service_call(cpu, r1, r2);
-}
-
-static int kvm_stpcifc_service_call(S390CPU *cpu, struct kvm_run *run)
-{
- uint8_t r1 = (run->s390_sieic.ipa & 0x00f0) >> 4;
- uint64_t fiba;
- uint8_t ar;
-
- cpu_synchronize_state(CPU(cpu));
- fiba = get_base_disp_rxy(cpu, run, &ar);
-
- return stpcifc_service_call(cpu, r1, fiba, ar);
-}
-
-static int kvm_sic_service_call(S390CPU *cpu, struct kvm_run *run)
-{
- /* NOOP */
- return 0;
-}
-
-static int kvm_rpcit_service_call(S390CPU *cpu, struct kvm_run *run)
-{
- uint8_t r1 = (run->s390_sieic.ipb & 0x00f00000) >> 20;
- uint8_t r2 = (run->s390_sieic.ipb & 0x000f0000) >> 16;
-
- return rpcit_service_call(cpu, r1, r2);
-}
-
-static int kvm_pcistb_service_call(S390CPU *cpu, struct kvm_run *run)
-{
- uint8_t r1 = (run->s390_sieic.ipa & 0x00f0) >> 4;
- uint8_t r3 = run->s390_sieic.ipa & 0x000f;
- uint64_t gaddr;
- uint8_t ar;
-
- cpu_synchronize_state(CPU(cpu));
- gaddr = get_base_disp_rsy(cpu, run, &ar);
-
- return pcistb_service_call(cpu, r1, r3, gaddr, ar);
-}
-
-static int kvm_mpcifc_service_call(S390CPU *cpu, struct kvm_run *run)
-{
- uint8_t r1 = (run->s390_sieic.ipa & 0x00f0) >> 4;
- uint64_t fiba;
- uint8_t ar;
-
- cpu_synchronize_state(CPU(cpu));
- fiba = get_base_disp_rxy(cpu, run, &ar);
-
- return mpcifc_service_call(cpu, r1, fiba, ar);
-}
-
-static int handle_b9(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
-{
- int r = 0;
-
- switch (ipa1) {
- case PRIV_B9_CLP:
- r = kvm_clp_service_call(cpu, run);
- break;
- case PRIV_B9_PCISTG:
- r = kvm_pcistg_service_call(cpu, run);
- break;
- case PRIV_B9_PCILG:
- r = kvm_pcilg_service_call(cpu, run);
- break;
- case PRIV_B9_RPCIT:
- r = kvm_rpcit_service_call(cpu, run);
- break;
- case PRIV_B9_EQBS:
- /* just inject exception */
- r = -1;
- break;
- default:
- r = -1;
- DPRINTF("KVM: unhandled PRIV: 0xb9%x\n", ipa1);
- break;
- }
-
- return r;
-}
-
-static int handle_eb(S390CPU *cpu, struct kvm_run *run, uint8_t ipbl)
-{
- int r = 0;
-
- switch (ipbl) {
- case PRIV_EB_PCISTB:
- r = kvm_pcistb_service_call(cpu, run);
- break;
- case PRIV_EB_SIC:
- r = kvm_sic_service_call(cpu, run);
- break;
- case PRIV_EB_SQBS:
- /* just inject exception */
- r = -1;
- break;
- default:
- r = -1;
- DPRINTF("KVM: unhandled PRIV: 0xeb%x\n", ipbl);
- break;
- }
-
- return r;
-}
-
-static int handle_e3(S390CPU *cpu, struct kvm_run *run, uint8_t ipbl)
-{
- int r = 0;
-
- switch (ipbl) {
- case PRIV_E3_MPCIFC:
- r = kvm_mpcifc_service_call(cpu, run);
- break;
- case PRIV_E3_STPCIFC:
- r = kvm_stpcifc_service_call(cpu, run);
- break;
- default:
- r = -1;
- DPRINTF("KVM: unhandled PRIV: 0xe3%x\n", ipbl);
- break;
- }
-
- return r;
-}
-
-static int handle_hypercall(S390CPU *cpu, struct kvm_run *run)
-{
- CPUS390XState *env = &cpu->env;
- int ret;
-
- cpu_synchronize_state(CPU(cpu));
- ret = s390_virtio_hypercall(env);
- if (ret == -EINVAL) {
- enter_pgmcheck(cpu, PGM_SPECIFICATION);
- return 0;
- }
-
- return ret;
-}
-
-static void kvm_handle_diag_288(S390CPU *cpu, struct kvm_run *run)
-{
- uint64_t r1, r3;
- int rc;
-
- cpu_synchronize_state(CPU(cpu));
- r1 = (run->s390_sieic.ipa & 0x00f0) >> 4;
- r3 = run->s390_sieic.ipa & 0x000f;
- rc = handle_diag_288(&cpu->env, r1, r3);
- if (rc) {
- enter_pgmcheck(cpu, PGM_SPECIFICATION);
- }
-}
-
-static void kvm_handle_diag_308(S390CPU *cpu, struct kvm_run *run)
-{
- uint64_t r1, r3;
-
- cpu_synchronize_state(CPU(cpu));
- r1 = (run->s390_sieic.ipa & 0x00f0) >> 4;
- r3 = run->s390_sieic.ipa & 0x000f;
- handle_diag_308(&cpu->env, r1, r3);
-}
-
-static int handle_sw_breakpoint(S390CPU *cpu, struct kvm_run *run)
-{
- CPUS390XState *env = &cpu->env;
- unsigned long pc;
-
- cpu_synchronize_state(CPU(cpu));
-
- pc = env->psw.addr - 4;
- if (kvm_find_sw_breakpoint(CPU(cpu), pc)) {
- env->psw.addr = pc;
- return EXCP_DEBUG;
- }
-
- return -ENOENT;
-}
-
-#define DIAG_KVM_CODE_MASK 0x000000000000ffff
-
-static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb)
-{
- int r = 0;
- uint16_t func_code;
-
- /*
- * For any diagnose call we support, bits 48-63 of the resulting
- * address specify the function code; the remainder is ignored.
- */
- func_code = decode_basedisp_rs(&cpu->env, ipb, NULL) & DIAG_KVM_CODE_MASK;
- switch (func_code) {
- case DIAG_TIMEREVENT:
- kvm_handle_diag_288(cpu, run);
- break;
- case DIAG_IPL:
- kvm_handle_diag_308(cpu, run);
- break;
- case DIAG_KVM_HYPERCALL:
- r = handle_hypercall(cpu, run);
- break;
- case DIAG_KVM_BREAKPOINT:
- r = handle_sw_breakpoint(cpu, run);
- break;
- default:
- DPRINTF("KVM: unknown DIAG: 0x%x\n", func_code);
- enter_pgmcheck(cpu, PGM_SPECIFICATION);
- break;
- }
-
- return r;
-}
-
-typedef struct SigpInfo {
- S390CPU *cpu;
- uint64_t param;
- int cc;
- uint64_t *status_reg;
-} SigpInfo;
-
-static void set_sigp_status(SigpInfo *si, uint64_t status)
-{
- *si->status_reg &= 0xffffffff00000000ULL;
- *si->status_reg |= status;
- si->cc = SIGP_CC_STATUS_STORED;
-}
-
-static void sigp_start(void *arg)
-{
- SigpInfo *si = arg;
-
- if (s390_cpu_get_state(si->cpu) != CPU_STATE_STOPPED) {
- si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
- return;
- }
-
- s390_cpu_set_state(CPU_STATE_OPERATING, si->cpu);
- si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
-}
-
-static void sigp_stop(void *arg)
-{
- SigpInfo *si = arg;
- struct kvm_s390_irq irq = {
- .type = KVM_S390_SIGP_STOP,
- };
-
- if (s390_cpu_get_state(si->cpu) != CPU_STATE_OPERATING) {
- si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
- return;
- }
-
- /* disabled wait - sleeping in user space */
- if (CPU(si->cpu)->halted) {
- s390_cpu_set_state(CPU_STATE_STOPPED, si->cpu);
- } else {
- /* execute the stop function */
- si->cpu->env.sigp_order = SIGP_STOP;
- kvm_s390_vcpu_interrupt(si->cpu, &irq);
- }
- si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
-}
-
-#define ADTL_SAVE_AREA_SIZE 1024
-static int kvm_s390_store_adtl_status(S390CPU *cpu, hwaddr addr)
-{
- void *mem;
- hwaddr len = ADTL_SAVE_AREA_SIZE;
-
- mem = cpu_physical_memory_map(addr, &len, 1);
- if (!mem) {
- return -EFAULT;
- }
- if (len != ADTL_SAVE_AREA_SIZE) {
- cpu_physical_memory_unmap(mem, len, 1, 0);
- return -EFAULT;
- }
-
- memcpy(mem, &cpu->env.vregs, 512);
-
- cpu_physical_memory_unmap(mem, len, 1, len);
-
- return 0;
-}
-
-#define KVM_S390_STORE_STATUS_DEF_ADDR offsetof(LowCore, floating_pt_save_area)
-#define SAVE_AREA_SIZE 512
-static int kvm_s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch)
-{
- static const uint8_t ar_id = 1;
- uint64_t ckc = cpu->env.ckc >> 8;
- void *mem;
- int i;
- hwaddr len = SAVE_AREA_SIZE;
-
- mem = cpu_physical_memory_map(addr, &len, 1);
- if (!mem) {
- return -EFAULT;
- }
- if (len != SAVE_AREA_SIZE) {
- cpu_physical_memory_unmap(mem, len, 1, 0);
- return -EFAULT;
- }
-
- if (store_arch) {
- cpu_physical_memory_write(offsetof(LowCore, ar_access_id), &ar_id, 1);
- }
- for (i = 0; i < 16; ++i) {
- *((uint64_t *)mem + i) = get_freg(&cpu->env, i)->ll;
- }
- memcpy(mem + 128, &cpu->env.regs, 128);
- memcpy(mem + 256, &cpu->env.psw, 16);
- memcpy(mem + 280, &cpu->env.psa, 4);
- memcpy(mem + 284, &cpu->env.fpc, 4);
- memcpy(mem + 292, &cpu->env.todpr, 4);
- memcpy(mem + 296, &cpu->env.cputm, 8);
- memcpy(mem + 304, &ckc, 8);
- memcpy(mem + 320, &cpu->env.aregs, 64);
- memcpy(mem + 384, &cpu->env.cregs, 128);
-
- cpu_physical_memory_unmap(mem, len, 1, len);
-
- return 0;
-}
-
-static void sigp_stop_and_store_status(void *arg)
-{
- SigpInfo *si = arg;
- struct kvm_s390_irq irq = {
- .type = KVM_S390_SIGP_STOP,
- };
-
- /* disabled wait - sleeping in user space */
- if (s390_cpu_get_state(si->cpu) == CPU_STATE_OPERATING &&
- CPU(si->cpu)->halted) {
- s390_cpu_set_state(CPU_STATE_STOPPED, si->cpu);
- }
-
- switch (s390_cpu_get_state(si->cpu)) {
- case CPU_STATE_OPERATING:
- si->cpu->env.sigp_order = SIGP_STOP_STORE_STATUS;
- kvm_s390_vcpu_interrupt(si->cpu, &irq);
- /* store will be performed when handling the stop intercept */
- break;
- case CPU_STATE_STOPPED:
- /* already stopped, just store the status */
- cpu_synchronize_state(CPU(si->cpu));
- kvm_s390_store_status(si->cpu, KVM_S390_STORE_STATUS_DEF_ADDR, true);
- break;
- }
- si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
-}
-
-static void sigp_store_status_at_address(void *arg)
-{
- SigpInfo *si = arg;
- uint32_t address = si->param & 0x7ffffe00u;
-
- /* cpu has to be stopped */
- if (s390_cpu_get_state(si->cpu) != CPU_STATE_STOPPED) {
- set_sigp_status(si, SIGP_STAT_INCORRECT_STATE);
- return;
- }
-
- cpu_synchronize_state(CPU(si->cpu));
-
- if (kvm_s390_store_status(si->cpu, address, false)) {
- set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER);
- return;
- }
- si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
-}
-
-static void sigp_store_adtl_status(void *arg)
-{
- SigpInfo *si = arg;
-
- if (!kvm_check_extension(kvm_state, KVM_CAP_S390_VECTOR_REGISTERS)) {
- set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
- return;
- }
-
- /* cpu has to be stopped */
- if (s390_cpu_get_state(si->cpu) != CPU_STATE_STOPPED) {
- set_sigp_status(si, SIGP_STAT_INCORRECT_STATE);
- return;
- }
-
- /* parameter must be aligned to 1024-byte boundary */
- if (si->param & 0x3ff) {
- set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER);
- return;
- }
-
- cpu_synchronize_state(CPU(si->cpu));
-
- if (kvm_s390_store_adtl_status(si->cpu, si->param)) {
- set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER);
- return;
- }
- si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
-}
-
-static void sigp_restart(void *arg)
-{
- SigpInfo *si = arg;
- struct kvm_s390_irq irq = {
- .type = KVM_S390_RESTART,
- };
-
- switch (s390_cpu_get_state(si->cpu)) {
- case CPU_STATE_STOPPED:
- /* the restart irq has to be delivered prior to any other pending irq */
- cpu_synchronize_state(CPU(si->cpu));
- do_restart_interrupt(&si->cpu->env);
- s390_cpu_set_state(CPU_STATE_OPERATING, si->cpu);
- break;
- case CPU_STATE_OPERATING:
- kvm_s390_vcpu_interrupt(si->cpu, &irq);
- break;
- }
- si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
-}
-
-int kvm_s390_cpu_restart(S390CPU *cpu)
-{
- SigpInfo si = {
- .cpu = cpu,
- };
-
- run_on_cpu(CPU(cpu), sigp_restart, &si);
- DPRINTF("DONE: KVM cpu restart: %p\n", &cpu->env);
- return 0;
-}
-
-static void sigp_initial_cpu_reset(void *arg)
-{
- SigpInfo *si = arg;
- CPUState *cs = CPU(si->cpu);
- S390CPUClass *scc = S390_CPU_GET_CLASS(si->cpu);
-
- cpu_synchronize_state(cs);
- scc->initial_cpu_reset(cs);
- cpu_synchronize_post_reset(cs);
- si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
-}
-
-static void sigp_cpu_reset(void *arg)
-{
- SigpInfo *si = arg;
- CPUState *cs = CPU(si->cpu);
- S390CPUClass *scc = S390_CPU_GET_CLASS(si->cpu);
-
- cpu_synchronize_state(cs);
- scc->cpu_reset(cs);
- cpu_synchronize_post_reset(cs);
- si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
-}
-
-static void sigp_set_prefix(void *arg)
-{
- SigpInfo *si = arg;
- uint32_t addr = si->param & 0x7fffe000u;
-
- cpu_synchronize_state(CPU(si->cpu));
-
- if (!address_space_access_valid(&address_space_memory, addr,
- sizeof(struct LowCore), false)) {
- set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER);
- return;
- }
-
- /* cpu has to be stopped */
- if (s390_cpu_get_state(si->cpu) != CPU_STATE_STOPPED) {
- set_sigp_status(si, SIGP_STAT_INCORRECT_STATE);
- return;
- }
-
- si->cpu->env.psa = addr;
- cpu_synchronize_post_init(CPU(si->cpu));
- si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
-}
-
-static int handle_sigp_single_dst(S390CPU *dst_cpu, uint8_t order,
- uint64_t param, uint64_t *status_reg)
-{
- SigpInfo si = {
- .cpu = dst_cpu,
- .param = param,
- .status_reg = status_reg,
- };
-
- /* cpu available? */
- if (dst_cpu == NULL) {
- return SIGP_CC_NOT_OPERATIONAL;
- }
-
- /* only resets can break pending orders */
- if (dst_cpu->env.sigp_order != 0 &&
- order != SIGP_CPU_RESET &&
- order != SIGP_INITIAL_CPU_RESET) {
- return SIGP_CC_BUSY;
- }
-
- switch (order) {
- case SIGP_START:
- run_on_cpu(CPU(dst_cpu), sigp_start, &si);
- break;
- case SIGP_STOP:
- run_on_cpu(CPU(dst_cpu), sigp_stop, &si);
- break;
- case SIGP_RESTART:
- run_on_cpu(CPU(dst_cpu), sigp_restart, &si);
- break;
- case SIGP_STOP_STORE_STATUS:
- run_on_cpu(CPU(dst_cpu), sigp_stop_and_store_status, &si);
- break;
- case SIGP_STORE_STATUS_ADDR:
- run_on_cpu(CPU(dst_cpu), sigp_store_status_at_address, &si);
- break;
- case SIGP_STORE_ADTL_STATUS:
- run_on_cpu(CPU(dst_cpu), sigp_store_adtl_status, &si);
- break;
- case SIGP_SET_PREFIX:
- run_on_cpu(CPU(dst_cpu), sigp_set_prefix, &si);
- break;
- case SIGP_INITIAL_CPU_RESET:
- run_on_cpu(CPU(dst_cpu), sigp_initial_cpu_reset, &si);
- break;
- case SIGP_CPU_RESET:
- run_on_cpu(CPU(dst_cpu), sigp_cpu_reset, &si);
- break;
- default:
- DPRINTF("KVM: unknown SIGP: 0x%x\n", order);
- set_sigp_status(&si, SIGP_STAT_INVALID_ORDER);
- }
-
- return si.cc;
-}
-
-static int sigp_set_architecture(S390CPU *cpu, uint32_t param,
- uint64_t *status_reg)
-{
- CPUState *cur_cs;
- S390CPU *cur_cpu;
-
- /* due to the BQL, we are the only active cpu */
- CPU_FOREACH(cur_cs) {
- cur_cpu = S390_CPU(cur_cs);
- if (cur_cpu->env.sigp_order != 0) {
- return SIGP_CC_BUSY;
- }
- cpu_synchronize_state(cur_cs);
- /* all but the current one have to be stopped */
- if (cur_cpu != cpu &&
- s390_cpu_get_state(cur_cpu) != CPU_STATE_STOPPED) {
- *status_reg &= 0xffffffff00000000ULL;
- *status_reg |= SIGP_STAT_INCORRECT_STATE;
- return SIGP_CC_STATUS_STORED;
- }
- }
-
- switch (param & 0xff) {
- case SIGP_MODE_ESA_S390:
- /* not supported */
- return SIGP_CC_NOT_OPERATIONAL;
- case SIGP_MODE_Z_ARCH_TRANS_ALL_PSW:
- case SIGP_MODE_Z_ARCH_TRANS_CUR_PSW:
- CPU_FOREACH(cur_cs) {
- cur_cpu = S390_CPU(cur_cs);
- cur_cpu->env.pfault_token = -1UL;
- }
- break;
- default:
- *status_reg &= 0xffffffff00000000ULL;
- *status_reg |= SIGP_STAT_INVALID_PARAMETER;
- return SIGP_CC_STATUS_STORED;
- }
-
- return SIGP_CC_ORDER_CODE_ACCEPTED;
-}
-
-#define SIGP_ORDER_MASK 0x000000ff
-
-static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
-{
- CPUS390XState *env = &cpu->env;
- const uint8_t r1 = ipa1 >> 4;
- const uint8_t r3 = ipa1 & 0x0f;
- int ret;
- uint8_t order;
- uint64_t *status_reg;
- uint64_t param;
- S390CPU *dst_cpu = NULL;
-
- cpu_synchronize_state(CPU(cpu));
-
- /* get order code */
- order = decode_basedisp_rs(env, run->s390_sieic.ipb, NULL)
- & SIGP_ORDER_MASK;
- status_reg = &env->regs[r1];
- param = (r1 % 2) ? env->regs[r1] : env->regs[r1 + 1];
-
- switch (order) {
- case SIGP_SET_ARCH:
- ret = sigp_set_architecture(cpu, param, status_reg);
- break;
- default:
- /* all other sigp orders target a single vcpu */
- dst_cpu = s390_cpu_addr2state(env->regs[r3]);
- ret = handle_sigp_single_dst(dst_cpu, order, param, status_reg);
- }
-
- trace_kvm_sigp_finished(order, CPU(cpu)->cpu_index,
- dst_cpu ? CPU(dst_cpu)->cpu_index : -1, ret);
-
- if (ret >= 0) {
- setcc(cpu, ret);
- return 0;
- }
-
- return ret;
-}
-
-static int handle_instruction(S390CPU *cpu, struct kvm_run *run)
-{
- unsigned int ipa0 = (run->s390_sieic.ipa & 0xff00);
- uint8_t ipa1 = run->s390_sieic.ipa & 0x00ff;
- int r = -1;
-
- DPRINTF("handle_instruction 0x%x 0x%x\n",
- run->s390_sieic.ipa, run->s390_sieic.ipb);
- switch (ipa0) {
- case IPA0_B2:
- r = handle_b2(cpu, run, ipa1);
- break;
- case IPA0_B9:
- r = handle_b9(cpu, run, ipa1);
- break;
- case IPA0_EB:
- r = handle_eb(cpu, run, run->s390_sieic.ipb & 0xff);
- break;
- case IPA0_E3:
- r = handle_e3(cpu, run, run->s390_sieic.ipb & 0xff);
- break;
- case IPA0_DIAG:
- r = handle_diag(cpu, run, run->s390_sieic.ipb);
- break;
- case IPA0_SIGP:
- r = handle_sigp(cpu, run, ipa1);
- break;
- }
-
- if (r < 0) {
- r = 0;
- enter_pgmcheck(cpu, 0x0001);
- }
-
- return r;
-}
-
-static bool is_special_wait_psw(CPUState *cs)
-{
- /* signal quiesce */
- return cs->kvm_run->psw_addr == 0xfffUL;
-}
-
-static void unmanageable_intercept(S390CPU *cpu, const char *str, int pswoffset)
-{
- CPUState *cs = CPU(cpu);
-
- error_report("Unmanageable %s! CPU%i new PSW: 0x%016lx:%016lx",
- str, cs->cpu_index, ldq_phys(cs->as, cpu->env.psa + pswoffset),
- ldq_phys(cs->as, cpu->env.psa + pswoffset + 8));
- s390_cpu_halt(cpu);
- qemu_system_guest_panicked();
-}
-
-static int handle_intercept(S390CPU *cpu)
-{
- CPUState *cs = CPU(cpu);
- struct kvm_run *run = cs->kvm_run;
- int icpt_code = run->s390_sieic.icptcode;
- int r = 0;
-
- DPRINTF("intercept: 0x%x (at 0x%lx)\n", icpt_code,
- (long)cs->kvm_run->psw_addr);
- switch (icpt_code) {
- case ICPT_INSTRUCTION:
- r = handle_instruction(cpu, run);
- break;
- case ICPT_PROGRAM:
- unmanageable_intercept(cpu, "program interrupt",
- offsetof(LowCore, program_new_psw));
- r = EXCP_HALTED;
- break;
- case ICPT_EXT_INT:
- unmanageable_intercept(cpu, "external interrupt",
- offsetof(LowCore, external_new_psw));
- r = EXCP_HALTED;
- break;
- case ICPT_WAITPSW:
- /* disabled wait, since enabled wait is handled in kernel */
- cpu_synchronize_state(cs);
- if (s390_cpu_halt(cpu) == 0) {
- if (is_special_wait_psw(cs)) {
- qemu_system_shutdown_request();
- } else {
- qemu_system_guest_panicked();
- }
- }
- r = EXCP_HALTED;
- break;
- case ICPT_CPU_STOP:
- if (s390_cpu_set_state(CPU_STATE_STOPPED, cpu) == 0) {
- qemu_system_shutdown_request();
- }
- if (cpu->env.sigp_order == SIGP_STOP_STORE_STATUS) {
- kvm_s390_store_status(cpu, KVM_S390_STORE_STATUS_DEF_ADDR,
- true);
- }
- cpu->env.sigp_order = 0;
- r = EXCP_HALTED;
- break;
- case ICPT_SOFT_INTERCEPT:
- fprintf(stderr, "KVM unimplemented icpt SOFT\n");
- exit(1);
- break;
- case ICPT_IO:
- fprintf(stderr, "KVM unimplemented icpt IO\n");
- exit(1);
- break;
- default:
- fprintf(stderr, "Unknown intercept code: %d\n", icpt_code);
- exit(1);
- break;
- }
-
- return r;
-}
-
-static int handle_tsch(S390CPU *cpu)
-{
- CPUState *cs = CPU(cpu);
- struct kvm_run *run = cs->kvm_run;
- int ret;
-
- cpu_synchronize_state(cs);
-
- ret = ioinst_handle_tsch(cpu, cpu->env.regs[1], run->s390_tsch.ipb);
- if (ret < 0) {
- /*
- * Failure.
- * If an I/O interrupt had been dequeued, we have to reinject it.
- */
- if (run->s390_tsch.dequeued) {
- kvm_s390_io_interrupt(run->s390_tsch.subchannel_id,
- run->s390_tsch.subchannel_nr,
- run->s390_tsch.io_int_parm,
- run->s390_tsch.io_int_word);
- }
- ret = 0;
- }
- return ret;
-}
-
-static void insert_stsi_3_2_2(S390CPU *cpu, __u64 addr, uint8_t ar)
-{
- struct sysib_322 sysib;
- int del;
-
- if (s390_cpu_virt_mem_read(cpu, addr, ar, &sysib, sizeof(sysib))) {
- return;
- }
- /* Shift the stack of Extended Names to prepare for our own data */
- memmove(&sysib.ext_names[1], &sysib.ext_names[0],
- sizeof(sysib.ext_names[0]) * (sysib.count - 1));
- /* First virt level, that doesn't provide Ext Names delimits stack. It is
- * assumed it's not capable of managing Extended Names for lower levels.
- */
- for (del = 1; del < sysib.count; del++) {
- if (!sysib.vm[del].ext_name_encoding || !sysib.ext_names[del][0]) {
- break;
- }
- }
- if (del < sysib.count) {
- memset(sysib.ext_names[del], 0,
- sizeof(sysib.ext_names[0]) * (sysib.count - del));
- }
- /* Insert short machine name in EBCDIC, padded with blanks */
- if (qemu_name) {
- memset(sysib.vm[0].name, 0x40, sizeof(sysib.vm[0].name));
- ebcdic_put(sysib.vm[0].name, qemu_name, MIN(sizeof(sysib.vm[0].name),
- strlen(qemu_name)));
- }
- sysib.vm[0].ext_name_encoding = 2; /* 2 = UTF-8 */
- memset(sysib.ext_names[0], 0, sizeof(sysib.ext_names[0]));
- /* If hypervisor specifies zero Extended Name in STSI322 SYSIB, it's
- * considered by s390 as not capable of providing any Extended Name.
- * Therefore if no name was specified on qemu invocation, we go with the
- * same "KVMguest" default, which KVM has filled into short name field.
- */
- if (qemu_name) {
- strncpy((char *)sysib.ext_names[0], qemu_name,
- sizeof(sysib.ext_names[0]));
- } else {
- strcpy((char *)sysib.ext_names[0], "KVMguest");
- }
- /* Insert UUID */
- memcpy(sysib.vm[0].uuid, qemu_uuid, sizeof(sysib.vm[0].uuid));
-
- s390_cpu_virt_mem_write(cpu, addr, ar, &sysib, sizeof(sysib));
-}
-
-static int handle_stsi(S390CPU *cpu)
-{
- CPUState *cs = CPU(cpu);
- struct kvm_run *run = cs->kvm_run;
-
- switch (run->s390_stsi.fc) {
- case 3:
- if (run->s390_stsi.sel1 != 2 || run->s390_stsi.sel2 != 2) {
- return 0;
- }
- /* Only sysib 3.2.2 needs post-handling for now. */
- insert_stsi_3_2_2(cpu, run->s390_stsi.addr, run->s390_stsi.ar);
- return 0;
- default:
- return 0;
- }
-}
-
-static int kvm_arch_handle_debug_exit(S390CPU *cpu)
-{
- CPUState *cs = CPU(cpu);
- struct kvm_run *run = cs->kvm_run;
-
- int ret = 0;
- struct kvm_debug_exit_arch *arch_info = &run->debug.arch;
-
- switch (arch_info->type) {
- case KVM_HW_WP_WRITE:
- if (find_hw_breakpoint(arch_info->addr, -1, arch_info->type)) {
- cs->watchpoint_hit = &hw_watchpoint;
- hw_watchpoint.vaddr = arch_info->addr;
- hw_watchpoint.flags = BP_MEM_WRITE;
- ret = EXCP_DEBUG;
- }
- break;
- case KVM_HW_BP:
- if (find_hw_breakpoint(arch_info->addr, -1, arch_info->type)) {
- ret = EXCP_DEBUG;
- }
- break;
- case KVM_SINGLESTEP:
- if (cs->singlestep_enabled) {
- ret = EXCP_DEBUG;
- }
- break;
- default:
- ret = -ENOSYS;
- }
-
- return ret;
-}
-
-int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
-{
- S390CPU *cpu = S390_CPU(cs);
- int ret = 0;
-
- qemu_mutex_lock_iothread();
-
- switch (run->exit_reason) {
- case KVM_EXIT_S390_SIEIC:
- ret = handle_intercept(cpu);
- break;
- case KVM_EXIT_S390_RESET:
- s390_reipl_request();
- break;
- case KVM_EXIT_S390_TSCH:
- ret = handle_tsch(cpu);
- break;
- case KVM_EXIT_S390_STSI:
- ret = handle_stsi(cpu);
- break;
- case KVM_EXIT_DEBUG:
- ret = kvm_arch_handle_debug_exit(cpu);
- break;
- default:
- fprintf(stderr, "Unknown KVM exit: %d\n", run->exit_reason);
- break;
- }
- qemu_mutex_unlock_iothread();
-
- if (ret == 0) {
- ret = EXCP_INTERRUPT;
- }
- return ret;
-}
-
-bool kvm_arch_stop_on_emulation_error(CPUState *cpu)
-{
- return true;
-}
-
-int kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr)
-{
- return 1;
-}
-
-int kvm_arch_on_sigbus(int code, void *addr)
-{
- return 1;
-}
-
-void kvm_s390_io_interrupt(uint16_t subchannel_id,
- uint16_t subchannel_nr, uint32_t io_int_parm,
- uint32_t io_int_word)
-{
- struct kvm_s390_irq irq = {
- .u.io.subchannel_id = subchannel_id,
- .u.io.subchannel_nr = subchannel_nr,
- .u.io.io_int_parm = io_int_parm,
- .u.io.io_int_word = io_int_word,
- };
-
- if (io_int_word & IO_INT_WORD_AI) {
- irq.type = KVM_S390_INT_IO(1, 0, 0, 0);
- } else {
- irq.type = ((subchannel_id & 0xff00) << 24) |
- ((subchannel_id & 0x00060) << 22) | (subchannel_nr << 16);
- }
- kvm_s390_floating_interrupt(&irq);
-}
-
-static uint64_t build_channel_report_mcic(void)
-{
- uint64_t mcic;
-
- /* subclass: indicate channel report pending */
- mcic = MCIC_SC_CP |
- /* subclass modifiers: none */
- /* storage errors: none */
- /* validity bits: no damage */
- MCIC_VB_WP | MCIC_VB_MS | MCIC_VB_PM | MCIC_VB_IA | MCIC_VB_FP |
- MCIC_VB_GR | MCIC_VB_CR | MCIC_VB_ST | MCIC_VB_AR | MCIC_VB_PR |
- MCIC_VB_FC | MCIC_VB_CT | MCIC_VB_CC;
- if (kvm_check_extension(kvm_state, KVM_CAP_S390_VECTOR_REGISTERS)) {
- mcic |= MCIC_VB_VR;
- }
- return mcic;
-}
-
-void kvm_s390_crw_mchk(void)
-{
- struct kvm_s390_irq irq = {
- .type = KVM_S390_MCHK,
- .u.mchk.cr14 = 1 << 28,
- .u.mchk.mcic = build_channel_report_mcic(),
- };
- kvm_s390_floating_interrupt(&irq);
-}
-
-void kvm_s390_enable_css_support(S390CPU *cpu)
-{
- int r;
-
- /* Activate host kernel channel subsystem support. */
- r = kvm_vcpu_enable_cap(CPU(cpu), KVM_CAP_S390_CSS_SUPPORT, 0);
- assert(r == 0);
-}
-
-void kvm_arch_init_irq_routing(KVMState *s)
-{
- /*
- * Note that while irqchip capabilities generally imply that cpustates
- * are handled in-kernel, it is not true for s390 (yet); therefore, we
- * have to override the common code kvm_halt_in_kernel_allowed setting.
- */
- if (kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) {
- kvm_gsi_routing_allowed = true;
- kvm_halt_in_kernel_allowed = false;
- }
-}
-
-int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch,
- int vq, bool assign)
-{
- struct kvm_ioeventfd kick = {
- .flags = KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY |
- KVM_IOEVENTFD_FLAG_DATAMATCH,
- .fd = event_notifier_get_fd(notifier),
- .datamatch = vq,
- .addr = sch,
- .len = 8,
- };
- if (!kvm_check_extension(kvm_state, KVM_CAP_IOEVENTFD)) {
- return -ENOSYS;
- }
- if (!assign) {
- kick.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
- }
- return kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &kick);
-}
-
-int kvm_s390_get_memslot_count(KVMState *s)
-{
- return kvm_check_extension(s, KVM_CAP_NR_MEMSLOTS);
-}
-
-int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state)
-{
- struct kvm_mp_state mp_state = {};
- int ret;
-
- /* the kvm part might not have been initialized yet */
- if (CPU(cpu)->kvm_state == NULL) {
- return 0;
- }
-
- switch (cpu_state) {
- case CPU_STATE_STOPPED:
- mp_state.mp_state = KVM_MP_STATE_STOPPED;
- break;
- case CPU_STATE_CHECK_STOP:
- mp_state.mp_state = KVM_MP_STATE_CHECK_STOP;
- break;
- case CPU_STATE_OPERATING:
- mp_state.mp_state = KVM_MP_STATE_OPERATING;
- break;
- case CPU_STATE_LOAD:
- mp_state.mp_state = KVM_MP_STATE_LOAD;
- break;
- default:
- error_report("Requested CPU state is not a valid S390 CPU state: %u",
- cpu_state);
- exit(1);
- }
-
- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MP_STATE, &mp_state);
- if (ret) {
- trace_kvm_failed_cpu_state_set(CPU(cpu)->cpu_index, cpu_state,
- strerror(-ret));
- }
-
- return ret;
-}
-
-void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu)
-{
- struct kvm_s390_irq_state irq_state;
- CPUState *cs = CPU(cpu);
- int32_t bytes;
-
- if (!kvm_check_extension(kvm_state, KVM_CAP_S390_IRQ_STATE)) {
- return;
- }
-
- irq_state.buf = (uint64_t) cpu->irqstate;
- irq_state.len = VCPU_IRQ_BUF_SIZE;
-
- bytes = kvm_vcpu_ioctl(cs, KVM_S390_GET_IRQ_STATE, &irq_state);
- if (bytes < 0) {
- cpu->irqstate_saved_size = 0;
- error_report("Migration of interrupt state failed");
- return;
- }
-
- cpu->irqstate_saved_size = bytes;
-}
-
-int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu)
-{
- CPUState *cs = CPU(cpu);
- struct kvm_s390_irq_state irq_state;
- int r;
-
- if (cpu->irqstate_saved_size == 0) {
- return 0;
- }
-
- if (!kvm_check_extension(kvm_state, KVM_CAP_S390_IRQ_STATE)) {
- return -ENOSYS;
- }
-
- irq_state.buf = (uint64_t) cpu->irqstate;
- irq_state.len = cpu->irqstate_saved_size;
-
- r = kvm_vcpu_ioctl(cs, KVM_S390_SET_IRQ_STATE, &irq_state);
- if (r) {
- error_report("Setting interrupt state failed %d", r);
- }
- return r;
-}
-
-int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
- uint64_t address, uint32_t data, PCIDevice *dev)
-{
- S390PCIBusDevice *pbdev;
- uint32_t fid = data >> ZPCI_MSI_VEC_BITS;
- uint32_t vec = data & ZPCI_MSI_VEC_MASK;
-
- pbdev = s390_pci_find_dev_by_fid(fid);
- if (!pbdev) {
- DPRINTF("add_msi_route no dev\n");
- return -ENODEV;
- }
-
- pbdev->routes.adapter.ind_offset = vec;
-
- route->type = KVM_IRQ_ROUTING_S390_ADAPTER;
- route->flags = 0;
- route->u.adapter.summary_addr = pbdev->routes.adapter.summary_addr;
- route->u.adapter.ind_addr = pbdev->routes.adapter.ind_addr;
- route->u.adapter.summary_offset = pbdev->routes.adapter.summary_offset;
- route->u.adapter.ind_offset = pbdev->routes.adapter.ind_offset;
- route->u.adapter.adapter_id = pbdev->routes.adapter.adapter_id;
- return 0;
-}
-
-int kvm_arch_msi_data_to_gsi(uint32_t data)
-{
- abort();
-}
diff --git a/qemu/target-s390x/machine.c b/qemu/target-s390x/machine.c
deleted file mode 100644
index 6b2609054..000000000
--- a/qemu/target-s390x/machine.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * S390x machine definitions and functions
- *
- * Copyright IBM Corp. 2014
- *
- * Authors:
- * Thomas Huth <thuth@linux.vnet.ibm.com>
- * Christian Borntraeger <borntraeger@de.ibm.com>
- * Jason J. Herne <jjherne@us.ibm.com>
- *
- * This work is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- */
-
-#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "cpu.h"
-#include "sysemu/kvm.h"
-
-static int cpu_post_load(void *opaque, int version_id)
-{
- S390CPU *cpu = opaque;
-
- /*
- * As the cpu state is pushed to kvm via kvm_set_mp_state rather
- * than via cpu_synchronize_state, we need update kvm here.
- */
- if (kvm_enabled()) {
- kvm_s390_set_cpu_state(cpu, cpu->env.cpu_state);
- return kvm_s390_vcpu_interrupt_post_load(cpu);
- }
-
- return 0;
-}
-static void cpu_pre_save(void *opaque)
-{
- S390CPU *cpu = opaque;
-
- if (kvm_enabled()) {
- kvm_s390_vcpu_interrupt_pre_save(cpu);
- }
-}
-
-static inline bool fpu_needed(void *opaque)
-{
- /* This looks odd, but we might want to NOT transfer fprs in the future */
- return true;
-}
-
-static const VMStateDescription vmstate_fpu = {
- .name = "cpu/fpu",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = fpu_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(env.vregs[0][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[1][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[2][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[3][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[4][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[5][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[6][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[7][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[8][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[9][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[10][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[11][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[12][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[13][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[14][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[15][0].ll, S390CPU),
- VMSTATE_UINT32(env.fpc, S390CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_vregs = {
- .name = "cpu/vregs",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = vregs_needed,
- .fields = (VMStateField[]) {
- /* vregs[0][0] -> vregs[15][0] and fregs are overlays */
- VMSTATE_UINT64(env.vregs[16][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[17][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[18][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[19][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[20][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[21][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[22][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[23][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[24][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[25][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[26][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[27][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[28][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[29][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[30][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[31][0].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[0][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[1][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[2][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[3][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[4][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[5][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[6][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[7][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[8][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[9][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[10][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[11][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[12][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[13][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[14][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[15][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[16][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[17][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[18][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[19][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[20][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[21][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[22][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[23][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[24][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[25][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[26][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[27][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[28][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[29][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[30][1].ll, S390CPU),
- VMSTATE_UINT64(env.vregs[31][1].ll, S390CPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-const VMStateDescription vmstate_s390_cpu = {
- .name = "cpu",
- .post_load = cpu_post_load,
- .pre_save = cpu_pre_save,
- .version_id = 4,
- .minimum_version_id = 3,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64_ARRAY(env.regs, S390CPU, 16),
- VMSTATE_UINT64(env.psw.mask, S390CPU),
- VMSTATE_UINT64(env.psw.addr, S390CPU),
- VMSTATE_UINT64(env.psa, S390CPU),
- VMSTATE_UINT32(env.todpr, S390CPU),
- VMSTATE_UINT64(env.pfault_token, S390CPU),
- VMSTATE_UINT64(env.pfault_compare, S390CPU),
- VMSTATE_UINT64(env.pfault_select, S390CPU),
- VMSTATE_UINT64(env.cputm, S390CPU),
- VMSTATE_UINT64(env.ckc, S390CPU),
- VMSTATE_UINT64(env.gbea, S390CPU),
- VMSTATE_UINT64(env.pp, S390CPU),
- VMSTATE_UINT32_ARRAY(env.aregs, S390CPU, 16),
- VMSTATE_UINT64_ARRAY(env.cregs, S390CPU, 16),
- VMSTATE_UINT8(env.cpu_state, S390CPU),
- VMSTATE_UINT8(env.sigp_order, S390CPU),
- VMSTATE_UINT32_V(irqstate_saved_size, S390CPU, 4),
- VMSTATE_VBUFFER_UINT32(irqstate, S390CPU, 4, NULL, 0,
- irqstate_saved_size),
- VMSTATE_END_OF_LIST()
- },
- .subsections = (const VMStateDescription*[]) {
- &vmstate_fpu,
- &vmstate_vregs,
- NULL
- },
-};
diff --git a/qemu/target-s390x/mem_helper.c b/qemu/target-s390x/mem_helper.c
deleted file mode 100644
index 707862203..000000000
--- a/qemu/target-s390x/mem_helper.c
+++ /dev/null
@@ -1,1198 +0,0 @@
-/*
- * S/390 memory access helper routines
- *
- * Copyright (c) 2009 Ulrich Hecht
- * Copyright (c) 2009 Alexander Graf
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "exec/helper-proto.h"
-#include "exec/cpu_ldst.h"
-#include "hw/s390x/storage-keys.h"
-
-/*****************************************************************************/
-/* Softmmu support */
-#if !defined(CONFIG_USER_ONLY)
-
-/* try to fill the TLB and return an exception if error. If retaddr is
- NULL, it means that the function was called in C code (i.e. not
- from generated code or from helper.c) */
-/* XXX: fix it to restore all registers */
-void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx,
- uintptr_t retaddr)
-{
- int ret;
-
- ret = s390_cpu_handle_mmu_fault(cs, addr, is_write, mmu_idx);
- if (unlikely(ret != 0)) {
- if (likely(retaddr)) {
- /* now we have a real cpu fault */
- cpu_restore_state(cs, retaddr);
- }
- cpu_loop_exit(cs);
- }
-}
-
-#endif
-
-/* #define DEBUG_HELPER */
-#ifdef DEBUG_HELPER
-#define HELPER_LOG(x...) qemu_log(x)
-#else
-#define HELPER_LOG(x...)
-#endif
-
-/* Reduce the length so that addr + len doesn't cross a page boundary. */
-static inline uint64_t adj_len_to_page(uint64_t len, uint64_t addr)
-{
-#ifndef CONFIG_USER_ONLY
- if ((addr & ~TARGET_PAGE_MASK) + len - 1 >= TARGET_PAGE_SIZE) {
- return -addr & ~TARGET_PAGE_MASK;
- }
-#endif
- return len;
-}
-
-static void fast_memset(CPUS390XState *env, uint64_t dest, uint8_t byte,
- uint32_t l)
-{
- int mmu_idx = cpu_mmu_index(env, false);
-
- while (l > 0) {
- void *p = tlb_vaddr_to_host(env, dest, MMU_DATA_STORE, mmu_idx);
- if (p) {
- /* Access to the whole page in write mode granted. */
- int l_adj = adj_len_to_page(l, dest);
- memset(p, byte, l_adj);
- dest += l_adj;
- l -= l_adj;
- } else {
- /* We failed to get access to the whole page. The next write
- access will likely fill the QEMU TLB for the next iteration. */
- cpu_stb_data(env, dest, byte);
- dest++;
- l--;
- }
- }
-}
-
-static void fast_memmove(CPUS390XState *env, uint64_t dest, uint64_t src,
- uint32_t l)
-{
- int mmu_idx = cpu_mmu_index(env, false);
-
- while (l > 0) {
- void *src_p = tlb_vaddr_to_host(env, src, MMU_DATA_LOAD, mmu_idx);
- void *dest_p = tlb_vaddr_to_host(env, dest, MMU_DATA_STORE, mmu_idx);
- if (src_p && dest_p) {
- /* Access to both whole pages granted. */
- int l_adj = adj_len_to_page(l, src);
- l_adj = adj_len_to_page(l_adj, dest);
- memmove(dest_p, src_p, l_adj);
- src += l_adj;
- dest += l_adj;
- l -= l_adj;
- } else {
- /* We failed to get access to one or both whole pages. The next
- read or write access will likely fill the QEMU TLB for the
- next iteration. */
- cpu_stb_data(env, dest, cpu_ldub_data(env, src));
- src++;
- dest++;
- l--;
- }
- }
-}
-
-/* and on array */
-uint32_t HELPER(nc)(CPUS390XState *env, uint32_t l, uint64_t dest,
- uint64_t src)
-{
- int i;
- unsigned char x;
- uint32_t cc = 0;
-
- HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
- __func__, l, dest, src);
- for (i = 0; i <= l; i++) {
- x = cpu_ldub_data(env, dest + i) & cpu_ldub_data(env, src + i);
- if (x) {
- cc = 1;
- }
- cpu_stb_data(env, dest + i, x);
- }
- return cc;
-}
-
-/* xor on array */
-uint32_t HELPER(xc)(CPUS390XState *env, uint32_t l, uint64_t dest,
- uint64_t src)
-{
- int i;
- unsigned char x;
- uint32_t cc = 0;
-
- HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
- __func__, l, dest, src);
-
- /* xor with itself is the same as memset(0) */
- if (src == dest) {
- fast_memset(env, dest, 0, l + 1);
- return 0;
- }
-
- for (i = 0; i <= l; i++) {
- x = cpu_ldub_data(env, dest + i) ^ cpu_ldub_data(env, src + i);
- if (x) {
- cc = 1;
- }
- cpu_stb_data(env, dest + i, x);
- }
- return cc;
-}
-
-/* or on array */
-uint32_t HELPER(oc)(CPUS390XState *env, uint32_t l, uint64_t dest,
- uint64_t src)
-{
- int i;
- unsigned char x;
- uint32_t cc = 0;
-
- HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
- __func__, l, dest, src);
- for (i = 0; i <= l; i++) {
- x = cpu_ldub_data(env, dest + i) | cpu_ldub_data(env, src + i);
- if (x) {
- cc = 1;
- }
- cpu_stb_data(env, dest + i, x);
- }
- return cc;
-}
-
-/* memmove */
-void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
-{
- int i = 0;
-
- HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
- __func__, l, dest, src);
-
- /* mvc with source pointing to the byte after the destination is the
- same as memset with the first source byte */
- if (dest == (src + 1)) {
- fast_memset(env, dest, cpu_ldub_data(env, src), l + 1);
- return;
- }
-
- /* mvc and memmove do not behave the same when areas overlap! */
- if ((dest < src) || (src + l < dest)) {
- fast_memmove(env, dest, src, l + 1);
- return;
- }
-
- /* slow version with byte accesses which always work */
- for (i = 0; i <= l; i++) {
- cpu_stb_data(env, dest + i, cpu_ldub_data(env, src + i));
- }
-}
-
-/* compare unsigned byte arrays */
-uint32_t HELPER(clc)(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2)
-{
- int i;
- unsigned char x, y;
- uint32_t cc;
-
- HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n",
- __func__, l, s1, s2);
- for (i = 0; i <= l; i++) {
- x = cpu_ldub_data(env, s1 + i);
- y = cpu_ldub_data(env, s2 + i);
- HELPER_LOG("%02x (%c)/%02x (%c) ", x, x, y, y);
- if (x < y) {
- cc = 1;
- goto done;
- } else if (x > y) {
- cc = 2;
- goto done;
- }
- }
- cc = 0;
- done:
- HELPER_LOG("\n");
- return cc;
-}
-
-/* compare logical under mask */
-uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask,
- uint64_t addr)
-{
- uint8_t r, d;
- uint32_t cc;
-
- HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __func__, r1,
- mask, addr);
- cc = 0;
- while (mask) {
- if (mask & 8) {
- d = cpu_ldub_data(env, addr);
- r = (r1 & 0xff000000UL) >> 24;
- HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d,
- addr);
- if (r < d) {
- cc = 1;
- break;
- } else if (r > d) {
- cc = 2;
- break;
- }
- addr++;
- }
- mask = (mask << 1) & 0xf;
- r1 <<= 8;
- }
- HELPER_LOG("\n");
- return cc;
-}
-
-static inline uint64_t fix_address(CPUS390XState *env, uint64_t a)
-{
- /* 31-Bit mode */
- if (!(env->psw.mask & PSW_MASK_64)) {
- a &= 0x7fffffff;
- }
- return a;
-}
-
-static inline uint64_t get_address(CPUS390XState *env, int x2, int b2, int d2)
-{
- uint64_t r = d2;
- if (x2) {
- r += env->regs[x2];
- }
- if (b2) {
- r += env->regs[b2];
- }
- return fix_address(env, r);
-}
-
-static inline uint64_t get_address_31fix(CPUS390XState *env, int reg)
-{
- return fix_address(env, env->regs[reg]);
-}
-
-/* search string (c is byte to search, r2 is string, r1 end of string) */
-uint64_t HELPER(srst)(CPUS390XState *env, uint64_t r0, uint64_t end,
- uint64_t str)
-{
- uint32_t len;
- uint8_t v, c = r0;
-
- str = fix_address(env, str);
- end = fix_address(env, end);
-
- /* Assume for now that R2 is unmodified. */
- env->retxl = str;
-
- /* Lest we fail to service interrupts in a timely manner, limit the
- amount of work we're willing to do. For now, let's cap at 8k. */
- for (len = 0; len < 0x2000; ++len) {
- if (str + len == end) {
- /* Character not found. R1 & R2 are unmodified. */
- env->cc_op = 2;
- return end;
- }
- v = cpu_ldub_data(env, str + len);
- if (v == c) {
- /* Character found. Set R1 to the location; R2 is unmodified. */
- env->cc_op = 1;
- return str + len;
- }
- }
-
- /* CPU-determined bytes processed. Advance R2 to next byte to process. */
- env->retxl = str + len;
- env->cc_op = 3;
- return end;
-}
-
-/* unsigned string compare (c is string terminator) */
-uint64_t HELPER(clst)(CPUS390XState *env, uint64_t c, uint64_t s1, uint64_t s2)
-{
- uint32_t len;
-
- c = c & 0xff;
- s1 = fix_address(env, s1);
- s2 = fix_address(env, s2);
-
- /* Lest we fail to service interrupts in a timely manner, limit the
- amount of work we're willing to do. For now, let's cap at 8k. */
- for (len = 0; len < 0x2000; ++len) {
- uint8_t v1 = cpu_ldub_data(env, s1 + len);
- uint8_t v2 = cpu_ldub_data(env, s2 + len);
- if (v1 == v2) {
- if (v1 == c) {
- /* Equal. CC=0, and don't advance the registers. */
- env->cc_op = 0;
- env->retxl = s2;
- return s1;
- }
- } else {
- /* Unequal. CC={1,2}, and advance the registers. Note that
- the terminator need not be zero, but the string that contains
- the terminator is by definition "low". */
- env->cc_op = (v1 == c ? 1 : v2 == c ? 2 : v1 < v2 ? 1 : 2);
- env->retxl = s2 + len;
- return s1 + len;
- }
- }
-
- /* CPU-determined bytes equal; advance the registers. */
- env->cc_op = 3;
- env->retxl = s2 + len;
- return s1 + len;
-}
-
-/* move page */
-void HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2)
-{
- /* XXX missing r0 handling */
- env->cc_op = 0;
- fast_memmove(env, r1, r2, TARGET_PAGE_SIZE);
-}
-
-/* string copy (c is string terminator) */
-uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, uint64_t d, uint64_t s)
-{
- uint32_t len;
-
- c = c & 0xff;
- d = fix_address(env, d);
- s = fix_address(env, s);
-
- /* Lest we fail to service interrupts in a timely manner, limit the
- amount of work we're willing to do. For now, let's cap at 8k. */
- for (len = 0; len < 0x2000; ++len) {
- uint8_t v = cpu_ldub_data(env, s + len);
- cpu_stb_data(env, d + len, v);
- if (v == c) {
- /* Complete. Set CC=1 and advance R1. */
- env->cc_op = 1;
- env->retxl = s;
- return d + len;
- }
- }
-
- /* Incomplete. Set CC=3 and signal to advance R1 and R2. */
- env->cc_op = 3;
- env->retxl = s + len;
- return d + len;
-}
-
-static uint32_t helper_icm(CPUS390XState *env, uint32_t r1, uint64_t address,
- uint32_t mask)
-{
- int pos = 24; /* top of the lower half of r1 */
- uint64_t rmask = 0xff000000ULL;
- uint8_t val = 0;
- int ccd = 0;
- uint32_t cc = 0;
-
- while (mask) {
- if (mask & 8) {
- env->regs[r1] &= ~rmask;
- val = cpu_ldub_data(env, address);
- if ((val & 0x80) && !ccd) {
- cc = 1;
- }
- ccd = 1;
- if (val && cc == 0) {
- cc = 2;
- }
- env->regs[r1] |= (uint64_t)val << pos;
- address++;
- }
- mask = (mask << 1) & 0xf;
- pos -= 8;
- rmask >>= 8;
- }
-
- return cc;
-}
-
-/* execute instruction
- this instruction executes an insn modified with the contents of r1
- it does not change the executed instruction in memory
- it does not change the program counter
- in other words: tricky...
- currently implemented by interpreting the cases it is most commonly used in
-*/
-uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1,
- uint64_t addr, uint64_t ret)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- uint16_t insn = cpu_lduw_code(env, addr);
-
- HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __func__, v1, addr,
- insn);
- if ((insn & 0xf0ff) == 0xd000) {
- uint32_t l, insn2, b1, b2, d1, d2;
-
- l = v1 & 0xff;
- insn2 = cpu_ldl_code(env, addr + 2);
- b1 = (insn2 >> 28) & 0xf;
- b2 = (insn2 >> 12) & 0xf;
- d1 = (insn2 >> 16) & 0xfff;
- d2 = insn2 & 0xfff;
- switch (insn & 0xf00) {
- case 0x200:
- helper_mvc(env, l, get_address(env, 0, b1, d1),
- get_address(env, 0, b2, d2));
- break;
- case 0x400:
- cc = helper_nc(env, l, get_address(env, 0, b1, d1),
- get_address(env, 0, b2, d2));
- break;
- case 0x500:
- cc = helper_clc(env, l, get_address(env, 0, b1, d1),
- get_address(env, 0, b2, d2));
- break;
- case 0x600:
- cc = helper_oc(env, l, get_address(env, 0, b1, d1),
- get_address(env, 0, b2, d2));
- break;
- case 0x700:
- cc = helper_xc(env, l, get_address(env, 0, b1, d1),
- get_address(env, 0, b2, d2));
- break;
- case 0xc00:
- helper_tr(env, l, get_address(env, 0, b1, d1),
- get_address(env, 0, b2, d2));
- break;
- case 0xd00:
- cc = helper_trt(env, l, get_address(env, 0, b1, d1),
- get_address(env, 0, b2, d2));
- break;
- default:
- goto abort;
- }
- } else if ((insn & 0xff00) == 0x0a00) {
- /* supervisor call */
- HELPER_LOG("%s: svc %ld via execute\n", __func__, (insn | v1) & 0xff);
- env->psw.addr = ret - 4;
- env->int_svc_code = (insn | v1) & 0xff;
- env->int_svc_ilen = 4;
- helper_exception(env, EXCP_SVC);
- } else if ((insn & 0xff00) == 0xbf00) {
- uint32_t insn2, r1, r3, b2, d2;
-
- insn2 = cpu_ldl_code(env, addr + 2);
- r1 = (insn2 >> 20) & 0xf;
- r3 = (insn2 >> 16) & 0xf;
- b2 = (insn2 >> 12) & 0xf;
- d2 = insn2 & 0xfff;
- cc = helper_icm(env, r1, get_address(env, 0, b2, d2), r3);
- } else {
- abort:
- cpu_abort(CPU(cpu), "EXECUTE on instruction prefix 0x%x not implemented\n",
- insn);
- }
- return cc;
-}
-
-/* load access registers r1 to r3 from memory at a2 */
-void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
-{
- int i;
-
- for (i = r1;; i = (i + 1) % 16) {
- env->aregs[i] = cpu_ldl_data(env, a2);
- a2 += 4;
-
- if (i == r3) {
- break;
- }
- }
-}
-
-/* store access registers r1 to r3 in memory at a2 */
-void HELPER(stam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
-{
- int i;
-
- for (i = r1;; i = (i + 1) % 16) {
- cpu_stl_data(env, a2, env->aregs[i]);
- a2 += 4;
-
- if (i == r3) {
- break;
- }
- }
-}
-
-/* move long */
-uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2)
-{
- uint64_t destlen = env->regs[r1 + 1] & 0xffffff;
- uint64_t dest = get_address_31fix(env, r1);
- uint64_t srclen = env->regs[r2 + 1] & 0xffffff;
- uint64_t src = get_address_31fix(env, r2);
- uint8_t pad = env->regs[r2 + 1] >> 24;
- uint8_t v;
- uint32_t cc;
-
- if (destlen == srclen) {
- cc = 0;
- } else if (destlen < srclen) {
- cc = 1;
- } else {
- cc = 2;
- }
-
- if (srclen > destlen) {
- srclen = destlen;
- }
-
- for (; destlen && srclen; src++, dest++, destlen--, srclen--) {
- v = cpu_ldub_data(env, src);
- cpu_stb_data(env, dest, v);
- }
-
- for (; destlen; dest++, destlen--) {
- cpu_stb_data(env, dest, pad);
- }
-
- env->regs[r1 + 1] = destlen;
- /* can't use srclen here, we trunc'ed it */
- env->regs[r2 + 1] -= src - env->regs[r2];
- env->regs[r1] = dest;
- env->regs[r2] = src;
-
- return cc;
-}
-
-/* move long extended another memcopy insn with more bells and whistles */
-uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2,
- uint32_t r3)
-{
- uint64_t destlen = env->regs[r1 + 1];
- uint64_t dest = env->regs[r1];
- uint64_t srclen = env->regs[r3 + 1];
- uint64_t src = env->regs[r3];
- uint8_t pad = a2 & 0xff;
- uint8_t v;
- uint32_t cc;
-
- if (!(env->psw.mask & PSW_MASK_64)) {
- destlen = (uint32_t)destlen;
- srclen = (uint32_t)srclen;
- dest &= 0x7fffffff;
- src &= 0x7fffffff;
- }
-
- if (destlen == srclen) {
- cc = 0;
- } else if (destlen < srclen) {
- cc = 1;
- } else {
- cc = 2;
- }
-
- if (srclen > destlen) {
- srclen = destlen;
- }
-
- for (; destlen && srclen; src++, dest++, destlen--, srclen--) {
- v = cpu_ldub_data(env, src);
- cpu_stb_data(env, dest, v);
- }
-
- for (; destlen; dest++, destlen--) {
- cpu_stb_data(env, dest, pad);
- }
-
- env->regs[r1 + 1] = destlen;
- /* can't use srclen here, we trunc'ed it */
- /* FIXME: 31-bit mode! */
- env->regs[r3 + 1] -= src - env->regs[r3];
- env->regs[r1] = dest;
- env->regs[r3] = src;
-
- return cc;
-}
-
-/* compare logical long extended memcompare insn with padding */
-uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2,
- uint32_t r3)
-{
- uint64_t destlen = env->regs[r1 + 1];
- uint64_t dest = get_address_31fix(env, r1);
- uint64_t srclen = env->regs[r3 + 1];
- uint64_t src = get_address_31fix(env, r3);
- uint8_t pad = a2 & 0xff;
- uint8_t v1 = 0, v2 = 0;
- uint32_t cc = 0;
-
- if (!(destlen || srclen)) {
- return cc;
- }
-
- if (srclen > destlen) {
- srclen = destlen;
- }
-
- for (; destlen || srclen; src++, dest++, destlen--, srclen--) {
- v1 = srclen ? cpu_ldub_data(env, src) : pad;
- v2 = destlen ? cpu_ldub_data(env, dest) : pad;
- if (v1 != v2) {
- cc = (v1 < v2) ? 1 : 2;
- break;
- }
- }
-
- env->regs[r1 + 1] = destlen;
- /* can't use srclen here, we trunc'ed it */
- env->regs[r3 + 1] -= src - env->regs[r3];
- env->regs[r1] = dest;
- env->regs[r3] = src;
-
- return cc;
-}
-
-/* checksum */
-uint64_t HELPER(cksm)(CPUS390XState *env, uint64_t r1,
- uint64_t src, uint64_t src_len)
-{
- uint64_t max_len, len;
- uint64_t cksm = (uint32_t)r1;
-
- /* Lest we fail to service interrupts in a timely manner, limit the
- amount of work we're willing to do. For now, let's cap at 8k. */
- max_len = (src_len > 0x2000 ? 0x2000 : src_len);
-
- /* Process full words as available. */
- for (len = 0; len + 4 <= max_len; len += 4, src += 4) {
- cksm += (uint32_t)cpu_ldl_data(env, src);
- }
-
- switch (max_len - len) {
- case 1:
- cksm += cpu_ldub_data(env, src) << 24;
- len += 1;
- break;
- case 2:
- cksm += cpu_lduw_data(env, src) << 16;
- len += 2;
- break;
- case 3:
- cksm += cpu_lduw_data(env, src) << 16;
- cksm += cpu_ldub_data(env, src + 2) << 8;
- len += 3;
- break;
- }
-
- /* Fold the carry from the checksum. Note that we can see carry-out
- during folding more than once (but probably not more than twice). */
- while (cksm > 0xffffffffull) {
- cksm = (uint32_t)cksm + (cksm >> 32);
- }
-
- /* Indicate whether or not we've processed everything. */
- env->cc_op = (len == src_len ? 0 : 3);
-
- /* Return both cksm and processed length. */
- env->retxl = cksm;
- return len;
-}
-
-void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest,
- uint64_t src)
-{
- int len_dest = len >> 4;
- int len_src = len & 0xf;
- uint8_t b;
- int second_nibble = 0;
-
- dest += len_dest;
- src += len_src;
-
- /* last byte is special, it only flips the nibbles */
- b = cpu_ldub_data(env, src);
- cpu_stb_data(env, dest, (b << 4) | (b >> 4));
- src--;
- len_src--;
-
- /* now pad every nibble with 0xf0 */
-
- while (len_dest > 0) {
- uint8_t cur_byte = 0;
-
- if (len_src > 0) {
- cur_byte = cpu_ldub_data(env, src);
- }
-
- len_dest--;
- dest--;
-
- /* only advance one nibble at a time */
- if (second_nibble) {
- cur_byte >>= 4;
- len_src--;
- src--;
- }
- second_nibble = !second_nibble;
-
- /* digit */
- cur_byte = (cur_byte & 0xf);
- /* zone bits */
- cur_byte |= 0xf0;
-
- cpu_stb_data(env, dest, cur_byte);
- }
-}
-
-void HELPER(tr)(CPUS390XState *env, uint32_t len, uint64_t array,
- uint64_t trans)
-{
- int i;
-
- for (i = 0; i <= len; i++) {
- uint8_t byte = cpu_ldub_data(env, array + i);
- uint8_t new_byte = cpu_ldub_data(env, trans + byte);
-
- cpu_stb_data(env, array + i, new_byte);
- }
-}
-
-uint64_t HELPER(tre)(CPUS390XState *env, uint64_t array,
- uint64_t len, uint64_t trans)
-{
- uint8_t end = env->regs[0] & 0xff;
- uint64_t l = len;
- uint64_t i;
-
- if (!(env->psw.mask & PSW_MASK_64)) {
- array &= 0x7fffffff;
- l = (uint32_t)l;
- }
-
- /* Lest we fail to service interrupts in a timely manner, limit the
- amount of work we're willing to do. For now, let's cap at 8k. */
- if (l > 0x2000) {
- l = 0x2000;
- env->cc_op = 3;
- } else {
- env->cc_op = 0;
- }
-
- for (i = 0; i < l; i++) {
- uint8_t byte, new_byte;
-
- byte = cpu_ldub_data(env, array + i);
-
- if (byte == end) {
- env->cc_op = 1;
- break;
- }
-
- new_byte = cpu_ldub_data(env, trans + byte);
- cpu_stb_data(env, array + i, new_byte);
- }
-
- env->retxl = len - i;
- return array + i;
-}
-
-uint32_t HELPER(trt)(CPUS390XState *env, uint32_t len, uint64_t array,
- uint64_t trans)
-{
- uint32_t cc = 0;
- int i;
-
- for (i = 0; i <= len; i++) {
- uint8_t byte = cpu_ldub_data(env, array + i);
- uint8_t sbyte = cpu_ldub_data(env, trans + byte);
-
- if (sbyte != 0) {
- env->regs[1] = array + i;
- env->regs[2] = (env->regs[2] & ~0xff) | sbyte;
- cc = (i == len) ? 2 : 1;
- break;
- }
- }
-
- return cc;
-}
-
-#if !defined(CONFIG_USER_ONLY)
-void HELPER(lctlg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- bool PERchanged = false;
- int i;
- uint64_t src = a2;
- uint64_t val;
-
- for (i = r1;; i = (i + 1) % 16) {
- val = cpu_ldq_data(env, src);
- if (env->cregs[i] != val && i >= 9 && i <= 11) {
- PERchanged = true;
- }
- env->cregs[i] = val;
- HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%" PRIx64 "\n",
- i, src, env->cregs[i]);
- src += sizeof(uint64_t);
-
- if (i == r3) {
- break;
- }
- }
-
- if (PERchanged && env->psw.mask & PSW_MASK_PER) {
- s390_cpu_recompute_watchpoints(CPU(cpu));
- }
-
- tlb_flush(CPU(cpu), 1);
-}
-
-void HELPER(lctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- bool PERchanged = false;
- int i;
- uint64_t src = a2;
- uint32_t val;
-
- for (i = r1;; i = (i + 1) % 16) {
- val = cpu_ldl_data(env, src);
- if ((uint32_t)env->cregs[i] != val && i >= 9 && i <= 11) {
- PERchanged = true;
- }
- env->cregs[i] = (env->cregs[i] & 0xFFFFFFFF00000000ULL) | val;
- src += sizeof(uint32_t);
-
- if (i == r3) {
- break;
- }
- }
-
- if (PERchanged && env->psw.mask & PSW_MASK_PER) {
- s390_cpu_recompute_watchpoints(CPU(cpu));
- }
-
- tlb_flush(CPU(cpu), 1);
-}
-
-void HELPER(stctg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
-{
- int i;
- uint64_t dest = a2;
-
- for (i = r1;; i = (i + 1) % 16) {
- cpu_stq_data(env, dest, env->cregs[i]);
- dest += sizeof(uint64_t);
-
- if (i == r3) {
- break;
- }
- }
-}
-
-void HELPER(stctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
-{
- int i;
- uint64_t dest = a2;
-
- for (i = r1;; i = (i + 1) % 16) {
- cpu_stl_data(env, dest, env->cregs[i]);
- dest += sizeof(uint32_t);
-
- if (i == r3) {
- break;
- }
- }
-}
-
-uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2)
-{
- /* XXX implement */
-
- return 0;
-}
-
-/* insert storage key extended */
-uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2)
-{
- static S390SKeysState *ss;
- static S390SKeysClass *skeyclass;
- uint64_t addr = get_address(env, 0, 0, r2);
- uint8_t key;
-
- if (addr > ram_size) {
- return 0;
- }
-
- if (unlikely(!ss)) {
- ss = s390_get_skeys_device();
- skeyclass = S390_SKEYS_GET_CLASS(ss);
- }
-
- if (skeyclass->get_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key)) {
- return 0;
- }
- return key;
-}
-
-/* set storage key extended */
-void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2)
-{
- static S390SKeysState *ss;
- static S390SKeysClass *skeyclass;
- uint64_t addr = get_address(env, 0, 0, r2);
- uint8_t key;
-
- if (addr > ram_size) {
- return;
- }
-
- if (unlikely(!ss)) {
- ss = s390_get_skeys_device();
- skeyclass = S390_SKEYS_GET_CLASS(ss);
- }
-
- key = (uint8_t) r1;
- skeyclass->set_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key);
-}
-
-/* reset reference bit extended */
-uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2)
-{
- static S390SKeysState *ss;
- static S390SKeysClass *skeyclass;
- uint8_t re, key;
-
- if (r2 > ram_size) {
- return 0;
- }
-
- if (unlikely(!ss)) {
- ss = s390_get_skeys_device();
- skeyclass = S390_SKEYS_GET_CLASS(ss);
- }
-
- if (skeyclass->get_skeys(ss, r2 / TARGET_PAGE_SIZE, 1, &key)) {
- return 0;
- }
-
- re = key & (SK_R | SK_C);
- key &= ~SK_R;
-
- if (skeyclass->set_skeys(ss, r2 / TARGET_PAGE_SIZE, 1, &key)) {
- return 0;
- }
-
- /*
- * cc
- *
- * 0 Reference bit zero; change bit zero
- * 1 Reference bit zero; change bit one
- * 2 Reference bit one; change bit zero
- * 3 Reference bit one; change bit one
- */
-
- return re >> 1;
-}
-
-/* compare and swap and purge */
-uint32_t HELPER(csp)(CPUS390XState *env, uint32_t r1, uint64_t r2)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- uint32_t cc;
- uint32_t o1 = env->regs[r1];
- uint64_t a2 = r2 & ~3ULL;
- uint32_t o2 = cpu_ldl_data(env, a2);
-
- if (o1 == o2) {
- cpu_stl_data(env, a2, env->regs[(r1 + 1) & 15]);
- if (r2 & 0x3) {
- /* flush TLB / ALB */
- tlb_flush(CPU(cpu), 1);
- }
- cc = 0;
- } else {
- env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | o2;
- cc = 1;
- }
-
- return cc;
-}
-
-uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2)
-{
- int cc = 0, i;
-
- HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
- __func__, l, a1, a2);
-
- if (l > 256) {
- /* max 256 */
- l = 256;
- cc = 3;
- }
-
- /* XXX replace w/ memcpy */
- for (i = 0; i < l; i++) {
- cpu_stb_secondary(env, a1 + i, cpu_ldub_primary(env, a2 + i));
- }
-
- return cc;
-}
-
-uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2)
-{
- int cc = 0, i;
-
- HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
- __func__, l, a1, a2);
-
- if (l > 256) {
- /* max 256 */
- l = 256;
- cc = 3;
- }
-
- /* XXX replace w/ memcpy */
- for (i = 0; i < l; i++) {
- cpu_stb_primary(env, a1 + i, cpu_ldub_secondary(env, a2 + i));
- }
-
- return cc;
-}
-
-/* invalidate pte */
-void HELPER(ipte)(CPUS390XState *env, uint64_t pte_addr, uint64_t vaddr)
-{
- CPUState *cs = CPU(s390_env_get_cpu(env));
- uint64_t page = vaddr & TARGET_PAGE_MASK;
- uint64_t pte = 0;
-
- /* XXX broadcast to other CPUs */
-
- /* XXX Linux is nice enough to give us the exact pte address.
- According to spec we'd have to find it out ourselves */
- /* XXX Linux is fine with overwriting the pte, the spec requires
- us to only set the invalid bit */
- stq_phys(cs->as, pte_addr, pte | _PAGE_INVALID);
-
- /* XXX we exploit the fact that Linux passes the exact virtual
- address here - it's not obliged to! */
- tlb_flush_page(cs, page);
-
- /* XXX 31-bit hack */
- if (page & 0x80000000) {
- tlb_flush_page(cs, page & ~0x80000000);
- } else {
- tlb_flush_page(cs, page | 0x80000000);
- }
-}
-
-/* flush local tlb */
-void HELPER(ptlb)(CPUS390XState *env)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
-
- tlb_flush(CPU(cpu), 1);
-}
-
-/* load using real address */
-uint64_t HELPER(lura)(CPUS390XState *env, uint64_t addr)
-{
- CPUState *cs = CPU(s390_env_get_cpu(env));
-
- return (uint32_t)ldl_phys(cs->as, get_address(env, 0, 0, addr));
-}
-
-uint64_t HELPER(lurag)(CPUS390XState *env, uint64_t addr)
-{
- CPUState *cs = CPU(s390_env_get_cpu(env));
-
- return ldq_phys(cs->as, get_address(env, 0, 0, addr));
-}
-
-/* store using real address */
-void HELPER(stura)(CPUS390XState *env, uint64_t addr, uint64_t v1)
-{
- CPUState *cs = CPU(s390_env_get_cpu(env));
-
- stl_phys(cs->as, get_address(env, 0, 0, addr), (uint32_t)v1);
-
- if ((env->psw.mask & PSW_MASK_PER) &&
- (env->cregs[9] & PER_CR9_EVENT_STORE) &&
- (env->cregs[9] & PER_CR9_EVENT_STORE_REAL)) {
- /* PSW is saved just before calling the helper. */
- env->per_address = env->psw.addr;
- env->per_perc_atmid = PER_CODE_EVENT_STORE_REAL | get_per_atmid(env);
- }
-}
-
-void HELPER(sturg)(CPUS390XState *env, uint64_t addr, uint64_t v1)
-{
- CPUState *cs = CPU(s390_env_get_cpu(env));
-
- stq_phys(cs->as, get_address(env, 0, 0, addr), v1);
-
- if ((env->psw.mask & PSW_MASK_PER) &&
- (env->cregs[9] & PER_CR9_EVENT_STORE) &&
- (env->cregs[9] & PER_CR9_EVENT_STORE_REAL)) {
- /* PSW is saved just before calling the helper. */
- env->per_address = env->psw.addr;
- env->per_perc_atmid = PER_CODE_EVENT_STORE_REAL | get_per_atmid(env);
- }
-}
-
-/* load real address */
-uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr)
-{
- CPUState *cs = CPU(s390_env_get_cpu(env));
- uint32_t cc = 0;
- int old_exc = cs->exception_index;
- uint64_t asc = env->psw.mask & PSW_MASK_ASC;
- uint64_t ret;
- int flags;
-
- /* XXX incomplete - has more corner cases */
- if (!(env->psw.mask & PSW_MASK_64) && (addr >> 32)) {
- program_interrupt(env, PGM_SPECIAL_OP, 2);
- }
-
- cs->exception_index = old_exc;
- if (mmu_translate(env, addr, 0, asc, &ret, &flags, true)) {
- cc = 3;
- }
- if (cs->exception_index == EXCP_PGM) {
- ret = env->int_pgm_code | 0x80000000;
- } else {
- ret |= addr & ~TARGET_PAGE_MASK;
- }
- cs->exception_index = old_exc;
-
- env->cc_op = cc;
- return ret;
-}
-#endif
diff --git a/qemu/target-s390x/misc_helper.c b/qemu/target-s390x/misc_helper.c
deleted file mode 100644
index 71cbe34e0..000000000
--- a/qemu/target-s390x/misc_helper.c
+++ /dev/null
@@ -1,640 +0,0 @@
-/*
- * S/390 misc helper routines
- *
- * Copyright (c) 2009 Ulrich Hecht
- * Copyright (c) 2009 Alexander Graf
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "exec/memory.h"
-#include "qemu/host-utils.h"
-#include "exec/helper-proto.h"
-#include "sysemu/kvm.h"
-#include "qemu/timer.h"
-#include "exec/address-spaces.h"
-#ifdef CONFIG_KVM
-#include <linux/kvm.h>
-#endif
-#include "exec/cpu_ldst.h"
-#include "hw/watchdog/wdt_diag288.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "sysemu/cpus.h"
-#include "sysemu/sysemu.h"
-#include "hw/s390x/ebcdic.h"
-#include "hw/s390x/ipl.h"
-#endif
-
-/* #define DEBUG_HELPER */
-#ifdef DEBUG_HELPER
-#define HELPER_LOG(x...) qemu_log(x)
-#else
-#define HELPER_LOG(x...)
-#endif
-
-/* Raise an exception dynamically from a helper function. */
-void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
- uintptr_t retaddr)
-{
- CPUState *cs = CPU(s390_env_get_cpu(env));
- int t;
-
- cs->exception_index = EXCP_PGM;
- env->int_pgm_code = excp;
-
- /* Use the (ultimate) callers address to find the insn that trapped. */
- cpu_restore_state(cs, retaddr);
-
- /* Advance past the insn. */
- t = cpu_ldub_code(env, env->psw.addr);
- env->int_pgm_ilen = t = get_ilen(t);
- env->psw.addr += t;
-
- cpu_loop_exit(cs);
-}
-
-/* Raise an exception statically from a TB. */
-void HELPER(exception)(CPUS390XState *env, uint32_t excp)
-{
- CPUState *cs = CPU(s390_env_get_cpu(env));
-
- HELPER_LOG("%s: exception %d\n", __func__, excp);
- cs->exception_index = excp;
- cpu_loop_exit(cs);
-}
-
-#ifndef CONFIG_USER_ONLY
-
-void program_interrupt(CPUS390XState *env, uint32_t code, int ilen)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
-
- qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n",
- env->psw.addr);
-
- if (kvm_enabled()) {
-#ifdef CONFIG_KVM
- struct kvm_s390_irq irq = {
- .type = KVM_S390_PROGRAM_INT,
- .u.pgm.code = code,
- };
-
- kvm_s390_vcpu_interrupt(cpu, &irq);
-#endif
- } else {
- CPUState *cs = CPU(cpu);
-
- env->int_pgm_code = code;
- env->int_pgm_ilen = ilen;
- cs->exception_index = EXCP_PGM;
- cpu_loop_exit(cs);
- }
-}
-
-/* SCLP service call */
-uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2)
-{
- int r = sclp_service_call(env, r1, r2);
- if (r < 0) {
- program_interrupt(env, -r, 4);
- return 0;
- }
- return r;
-}
-
-#ifndef CONFIG_USER_ONLY
-static int modified_clear_reset(S390CPU *cpu)
-{
- S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
- CPUState *t;
-
- pause_all_vcpus();
- cpu_synchronize_all_states();
- CPU_FOREACH(t) {
- run_on_cpu(t, s390_do_cpu_full_reset, t);
- }
- s390_cmma_reset();
- subsystem_reset();
- s390_crypto_reset();
- scc->load_normal(CPU(cpu));
- cpu_synchronize_all_post_reset();
- resume_all_vcpus();
- return 0;
-}
-
-static int load_normal_reset(S390CPU *cpu)
-{
- S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
- CPUState *t;
-
- pause_all_vcpus();
- cpu_synchronize_all_states();
- CPU_FOREACH(t) {
- run_on_cpu(t, s390_do_cpu_reset, t);
- }
- s390_cmma_reset();
- subsystem_reset();
- scc->initial_cpu_reset(CPU(cpu));
- scc->load_normal(CPU(cpu));
- cpu_synchronize_all_post_reset();
- resume_all_vcpus();
- return 0;
-}
-
-int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3)
-{
- uint64_t func = env->regs[r1];
- uint64_t timeout = env->regs[r1 + 1];
- uint64_t action = env->regs[r3];
- Object *obj;
- DIAG288State *diag288;
- DIAG288Class *diag288_class;
-
- if (r1 % 2 || action != 0) {
- return -1;
- }
-
- /* Timeout must be more than 15 seconds except for timer deletion */
- if (func != WDT_DIAG288_CANCEL && timeout < 15) {
- return -1;
- }
-
- obj = object_resolve_path_type("", TYPE_WDT_DIAG288, NULL);
- if (!obj) {
- return -1;
- }
-
- diag288 = DIAG288(obj);
- diag288_class = DIAG288_GET_CLASS(diag288);
- return diag288_class->handle_timer(diag288, func, timeout);
-}
-
-#define DIAG_308_RC_OK 0x0001
-#define DIAG_308_RC_NO_CONF 0x0102
-#define DIAG_308_RC_INVALID 0x0402
-
-void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3)
-{
- uint64_t addr = env->regs[r1];
- uint64_t subcode = env->regs[r3];
- IplParameterBlock *iplb;
-
- if (env->psw.mask & PSW_MASK_PSTATE) {
- program_interrupt(env, PGM_PRIVILEGED, ILEN_LATER_INC);
- return;
- }
-
- if ((subcode & ~0x0ffffULL) || (subcode > 6)) {
- program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC);
- return;
- }
-
- switch (subcode) {
- case 0:
- modified_clear_reset(s390_env_get_cpu(env));
- if (tcg_enabled()) {
- cpu_loop_exit(CPU(s390_env_get_cpu(env)));
- }
- break;
- case 1:
- load_normal_reset(s390_env_get_cpu(env));
- if (tcg_enabled()) {
- cpu_loop_exit(CPU(s390_env_get_cpu(env)));
- }
- break;
- case 3:
- s390_reipl_request();
- if (tcg_enabled()) {
- cpu_loop_exit(CPU(s390_env_get_cpu(env)));
- }
- break;
- case 5:
- if ((r1 & 1) || (addr & 0x0fffULL)) {
- program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC);
- return;
- }
- if (!address_space_access_valid(&address_space_memory, addr,
- sizeof(IplParameterBlock), false)) {
- program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC);
- return;
- }
- iplb = g_malloc0(sizeof(struct IplParameterBlock));
- cpu_physical_memory_read(addr, iplb, sizeof(struct IplParameterBlock));
- s390_ipl_update_diag308(iplb);
- env->regs[r1 + 1] = DIAG_308_RC_OK;
- g_free(iplb);
- return;
- case 6:
- if ((r1 & 1) || (addr & 0x0fffULL)) {
- program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC);
- return;
- }
- if (!address_space_access_valid(&address_space_memory, addr,
- sizeof(IplParameterBlock), true)) {
- program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC);
- return;
- }
- iplb = s390_ipl_get_iplb();
- if (iplb) {
- cpu_physical_memory_write(addr, iplb,
- sizeof(struct IplParameterBlock));
- env->regs[r1 + 1] = DIAG_308_RC_OK;
- } else {
- env->regs[r1 + 1] = DIAG_308_RC_NO_CONF;
- }
- return;
- default:
- hw_error("Unhandled diag308 subcode %" PRIx64, subcode);
- break;
- }
-}
-#endif
-
-void HELPER(diag)(CPUS390XState *env, uint32_t r1, uint32_t r3, uint32_t num)
-{
- uint64_t r;
-
- switch (num) {
- case 0x500:
- /* KVM hypercall */
- r = s390_virtio_hypercall(env);
- break;
- case 0x44:
- /* yield */
- r = 0;
- break;
- case 0x308:
- /* ipl */
- handle_diag_308(env, r1, r3);
- r = 0;
- break;
- default:
- r = -1;
- break;
- }
-
- if (r) {
- program_interrupt(env, PGM_OPERATION, ILEN_LATER_INC);
- }
-}
-
-/* Set Prefix */
-void HELPER(spx)(CPUS390XState *env, uint64_t a1)
-{
- CPUState *cs = CPU(s390_env_get_cpu(env));
- uint32_t prefix = a1 & 0x7fffe000;
-
- env->psa = prefix;
- HELPER_LOG("prefix: %#x\n", prefix);
- tlb_flush_page(cs, 0);
- tlb_flush_page(cs, TARGET_PAGE_SIZE);
-}
-
-/* Store Clock */
-uint64_t HELPER(stck)(CPUS390XState *env)
-{
- uint64_t time;
-
- time = env->tod_offset +
- time2tod(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - env->tod_basetime);
-
- return time;
-}
-
-/* Set Clock Comparator */
-void HELPER(sckc)(CPUS390XState *env, uint64_t time)
-{
- if (time == -1ULL) {
- return;
- }
-
- env->ckc = time;
-
- /* difference between origins */
- time -= env->tod_offset;
-
- /* nanoseconds */
- time = tod2time(time);
-
- timer_mod(env->tod_timer, env->tod_basetime + time);
-}
-
-/* Store Clock Comparator */
-uint64_t HELPER(stckc)(CPUS390XState *env)
-{
- return env->ckc;
-}
-
-/* Set CPU Timer */
-void HELPER(spt)(CPUS390XState *env, uint64_t time)
-{
- if (time == -1ULL) {
- return;
- }
-
- /* nanoseconds */
- time = tod2time(time);
-
- env->cputm = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + time;
-
- timer_mod(env->cpu_timer, env->cputm);
-}
-
-/* Store CPU Timer */
-uint64_t HELPER(stpt)(CPUS390XState *env)
-{
- return time2tod(env->cputm - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
-}
-
-/* Store System Information */
-uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
- uint64_t r0, uint64_t r1)
-{
- int cc = 0;
- int sel1, sel2;
-
- if ((r0 & STSI_LEVEL_MASK) <= STSI_LEVEL_3 &&
- ((r0 & STSI_R0_RESERVED_MASK) || (r1 & STSI_R1_RESERVED_MASK))) {
- /* valid function code, invalid reserved bits */
- program_interrupt(env, PGM_SPECIFICATION, 2);
- }
-
- sel1 = r0 & STSI_R0_SEL1_MASK;
- sel2 = r1 & STSI_R1_SEL2_MASK;
-
- /* XXX: spec exception if sysib is not 4k-aligned */
-
- switch (r0 & STSI_LEVEL_MASK) {
- case STSI_LEVEL_1:
- if ((sel1 == 1) && (sel2 == 1)) {
- /* Basic Machine Configuration */
- struct sysib_111 sysib;
-
- memset(&sysib, 0, sizeof(sysib));
- ebcdic_put(sysib.manuf, "QEMU ", 16);
- /* same as machine type number in STORE CPU ID */
- ebcdic_put(sysib.type, "QEMU", 4);
- /* same as model number in STORE CPU ID */
- ebcdic_put(sysib.model, "QEMU ", 16);
- ebcdic_put(sysib.sequence, "QEMU ", 16);
- ebcdic_put(sysib.plant, "QEMU", 4);
- cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
- } else if ((sel1 == 2) && (sel2 == 1)) {
- /* Basic Machine CPU */
- struct sysib_121 sysib;
-
- memset(&sysib, 0, sizeof(sysib));
- /* XXX make different for different CPUs? */
- ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
- ebcdic_put(sysib.plant, "QEMU", 4);
- stw_p(&sysib.cpu_addr, env->cpu_num);
- cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
- } else if ((sel1 == 2) && (sel2 == 2)) {
- /* Basic Machine CPUs */
- struct sysib_122 sysib;
-
- memset(&sysib, 0, sizeof(sysib));
- stl_p(&sysib.capability, 0x443afc29);
- /* XXX change when SMP comes */
- stw_p(&sysib.total_cpus, 1);
- stw_p(&sysib.active_cpus, 1);
- stw_p(&sysib.standby_cpus, 0);
- stw_p(&sysib.reserved_cpus, 0);
- cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
- } else {
- cc = 3;
- }
- break;
- case STSI_LEVEL_2:
- {
- if ((sel1 == 2) && (sel2 == 1)) {
- /* LPAR CPU */
- struct sysib_221 sysib;
-
- memset(&sysib, 0, sizeof(sysib));
- /* XXX make different for different CPUs? */
- ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
- ebcdic_put(sysib.plant, "QEMU", 4);
- stw_p(&sysib.cpu_addr, env->cpu_num);
- stw_p(&sysib.cpu_id, 0);
- cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
- } else if ((sel1 == 2) && (sel2 == 2)) {
- /* LPAR CPUs */
- struct sysib_222 sysib;
-
- memset(&sysib, 0, sizeof(sysib));
- stw_p(&sysib.lpar_num, 0);
- sysib.lcpuc = 0;
- /* XXX change when SMP comes */
- stw_p(&sysib.total_cpus, 1);
- stw_p(&sysib.conf_cpus, 1);
- stw_p(&sysib.standby_cpus, 0);
- stw_p(&sysib.reserved_cpus, 0);
- ebcdic_put(sysib.name, "QEMU ", 8);
- stl_p(&sysib.caf, 1000);
- stw_p(&sysib.dedicated_cpus, 0);
- stw_p(&sysib.shared_cpus, 0);
- cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
- } else {
- cc = 3;
- }
- break;
- }
- case STSI_LEVEL_3:
- {
- if ((sel1 == 2) && (sel2 == 2)) {
- /* VM CPUs */
- struct sysib_322 sysib;
-
- memset(&sysib, 0, sizeof(sysib));
- sysib.count = 1;
- /* XXX change when SMP comes */
- stw_p(&sysib.vm[0].total_cpus, 1);
- stw_p(&sysib.vm[0].conf_cpus, 1);
- stw_p(&sysib.vm[0].standby_cpus, 0);
- stw_p(&sysib.vm[0].reserved_cpus, 0);
- ebcdic_put(sysib.vm[0].name, "KVMguest", 8);
- stl_p(&sysib.vm[0].caf, 1000);
- ebcdic_put(sysib.vm[0].cpi, "KVM/Linux ", 16);
- cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
- } else {
- cc = 3;
- }
- break;
- }
- case STSI_LEVEL_CURRENT:
- env->regs[0] = STSI_LEVEL_3;
- break;
- default:
- cc = 3;
- break;
- }
-
- return cc;
-}
-
-uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1,
- uint64_t cpu_addr)
-{
- int cc = SIGP_CC_ORDER_CODE_ACCEPTED;
-
- HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n",
- __func__, order_code, r1, cpu_addr);
-
- /* Remember: Use "R1 or R1 + 1, whichever is the odd-numbered register"
- as parameter (input). Status (output) is always R1. */
-
- switch (order_code) {
- case SIGP_SET_ARCH:
- /* switch arch */
- break;
- case SIGP_SENSE:
- /* enumerate CPU status */
- if (cpu_addr) {
- /* XXX implement when SMP comes */
- return 3;
- }
- env->regs[r1] &= 0xffffffff00000000ULL;
- cc = 1;
- break;
-#if !defined(CONFIG_USER_ONLY)
- case SIGP_RESTART:
- qemu_system_reset_request();
- cpu_loop_exit(CPU(s390_env_get_cpu(env)));
- break;
- case SIGP_STOP:
- qemu_system_shutdown_request();
- cpu_loop_exit(CPU(s390_env_get_cpu(env)));
- break;
-#endif
- default:
- /* unknown sigp */
- fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code);
- cc = SIGP_CC_NOT_OPERATIONAL;
- }
-
- return cc;
-}
-#endif
-
-#ifndef CONFIG_USER_ONLY
-void HELPER(xsch)(CPUS390XState *env, uint64_t r1)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- ioinst_handle_xsch(cpu, r1);
-}
-
-void HELPER(csch)(CPUS390XState *env, uint64_t r1)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- ioinst_handle_csch(cpu, r1);
-}
-
-void HELPER(hsch)(CPUS390XState *env, uint64_t r1)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- ioinst_handle_hsch(cpu, r1);
-}
-
-void HELPER(msch)(CPUS390XState *env, uint64_t r1, uint64_t inst)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- ioinst_handle_msch(cpu, r1, inst >> 16);
-}
-
-void HELPER(rchp)(CPUS390XState *env, uint64_t r1)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- ioinst_handle_rchp(cpu, r1);
-}
-
-void HELPER(rsch)(CPUS390XState *env, uint64_t r1)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- ioinst_handle_rsch(cpu, r1);
-}
-
-void HELPER(ssch)(CPUS390XState *env, uint64_t r1, uint64_t inst)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- ioinst_handle_ssch(cpu, r1, inst >> 16);
-}
-
-void HELPER(stsch)(CPUS390XState *env, uint64_t r1, uint64_t inst)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- ioinst_handle_stsch(cpu, r1, inst >> 16);
-}
-
-void HELPER(tsch)(CPUS390XState *env, uint64_t r1, uint64_t inst)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- ioinst_handle_tsch(cpu, r1, inst >> 16);
-}
-
-void HELPER(chsc)(CPUS390XState *env, uint64_t inst)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- ioinst_handle_chsc(cpu, inst >> 16);
-}
-#endif
-
-#ifndef CONFIG_USER_ONLY
-void HELPER(per_check_exception)(CPUS390XState *env)
-{
- CPUState *cs = CPU(s390_env_get_cpu(env));
-
- if (env->per_perc_atmid) {
- env->int_pgm_code = PGM_PER;
- env->int_pgm_ilen = get_ilen(cpu_ldub_code(env, env->per_address));
-
- cs->exception_index = EXCP_PGM;
- cpu_loop_exit(cs);
- }
-}
-
-void HELPER(per_branch)(CPUS390XState *env, uint64_t from, uint64_t to)
-{
- if ((env->cregs[9] & PER_CR9_EVENT_BRANCH)) {
- if (!(env->cregs[9] & PER_CR9_CONTROL_BRANCH_ADDRESS)
- || get_per_in_range(env, to)) {
- env->per_address = from;
- env->per_perc_atmid = PER_CODE_EVENT_BRANCH | get_per_atmid(env);
- }
- }
-}
-
-void HELPER(per_ifetch)(CPUS390XState *env, uint64_t addr)
-{
- if ((env->cregs[9] & PER_CR9_EVENT_IFETCH) && get_per_in_range(env, addr)) {
- env->per_address = addr;
- env->per_perc_atmid = PER_CODE_EVENT_IFETCH | get_per_atmid(env);
-
- /* If the instruction has to be nullified, trigger the
- exception immediately. */
- if (env->cregs[9] & PER_CR9_EVENT_NULLIFICATION) {
- CPUState *cs = CPU(s390_env_get_cpu(env));
-
- env->int_pgm_code = PGM_PER;
- env->int_pgm_ilen = get_ilen(cpu_ldub_code(env, addr));
-
- cs->exception_index = EXCP_PGM;
- cpu_loop_exit(cs);
- }
- }
-}
-#endif
diff --git a/qemu/target-s390x/mmu_helper.c b/qemu/target-s390x/mmu_helper.c
deleted file mode 100644
index b11a02706..000000000
--- a/qemu/target-s390x/mmu_helper.c
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
- * S390x MMU related functions
- *
- * Copyright (c) 2011 Alexander Graf
- * Copyright (c) 2015 Thomas Huth, IBM Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "qemu/osdep.h"
-#include "qemu/error-report.h"
-#include "exec/address-spaces.h"
-#include "cpu.h"
-#include "sysemu/kvm.h"
-#include "trace.h"
-#include "hw/s390x/storage-keys.h"
-
-/* #define DEBUG_S390 */
-/* #define DEBUG_S390_PTE */
-/* #define DEBUG_S390_STDOUT */
-
-#ifdef DEBUG_S390
-#ifdef DEBUG_S390_STDOUT
-#define DPRINTF(fmt, ...) \
- do { fprintf(stderr, fmt, ## __VA_ARGS__); \
- if (qemu_log_separate()) qemu_log(fmt, ##__VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
- do { qemu_log(fmt, ## __VA_ARGS__); } while (0)
-#endif
-#else
-#define DPRINTF(fmt, ...) \
- do { } while (0)
-#endif
-
-#ifdef DEBUG_S390_PTE
-#define PTE_DPRINTF DPRINTF
-#else
-#define PTE_DPRINTF(fmt, ...) \
- do { } while (0)
-#endif
-
-/* Fetch/store bits in the translation exception code: */
-#define FS_READ 0x800
-#define FS_WRITE 0x400
-
-static void trigger_access_exception(CPUS390XState *env, uint32_t type,
- uint32_t ilen, uint64_t tec)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
-
- if (kvm_enabled()) {
- kvm_s390_access_exception(cpu, type, tec);
- } else {
- CPUState *cs = CPU(cpu);
- stq_phys(cs->as, env->psa + offsetof(LowCore, trans_exc_code), tec);
- trigger_pgm_exception(env, type, ilen);
- }
-}
-
-static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr,
- uint64_t asc, int rw, bool exc)
-{
- uint64_t tec;
-
- tec = vaddr | (rw == MMU_DATA_STORE ? FS_WRITE : FS_READ) | 4 | asc >> 46;
-
- DPRINTF("%s: trans_exc_code=%016" PRIx64 "\n", __func__, tec);
-
- if (!exc) {
- return;
- }
-
- trigger_access_exception(env, PGM_PROTECTION, ILEN_LATER_INC, tec);
-}
-
-static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
- uint32_t type, uint64_t asc, int rw, bool exc)
-{
- int ilen = ILEN_LATER;
- uint64_t tec;
-
- tec = vaddr | (rw == MMU_DATA_STORE ? FS_WRITE : FS_READ) | asc >> 46;
-
- DPRINTF("%s: trans_exc_code=%016" PRIx64 "\n", __func__, tec);
-
- if (!exc) {
- return;
- }
-
- /* Code accesses have an undefined ilc. */
- if (rw == MMU_INST_FETCH) {
- ilen = 2;
- }
-
- trigger_access_exception(env, type, ilen, tec);
-}
-
-/**
- * Translate real address to absolute (= physical)
- * address by taking care of the prefix mapping.
- */
-static target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr)
-{
- if (raddr < 0x2000) {
- return raddr + env->psa; /* Map the lowcore. */
- } else if (raddr >= env->psa && raddr < env->psa + 0x2000) {
- return raddr - env->psa; /* Map the 0 page. */
- }
- return raddr;
-}
-
-/* Decode page table entry (normal 4KB page) */
-static int mmu_translate_pte(CPUS390XState *env, target_ulong vaddr,
- uint64_t asc, uint64_t pt_entry,
- target_ulong *raddr, int *flags, int rw, bool exc)
-{
- if (pt_entry & _PAGE_INVALID) {
- DPRINTF("%s: PTE=0x%" PRIx64 " invalid\n", __func__, pt_entry);
- trigger_page_fault(env, vaddr, PGM_PAGE_TRANS, asc, rw, exc);
- return -1;
- }
- if (pt_entry & _PAGE_RES0) {
- trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw, exc);
- return -1;
- }
- if (pt_entry & _PAGE_RO) {
- *flags &= ~PAGE_WRITE;
- }
-
- *raddr = pt_entry & _ASCE_ORIGIN;
-
- PTE_DPRINTF("%s: PTE=0x%" PRIx64 "\n", __func__, pt_entry);
-
- return 0;
-}
-
-#define VADDR_PX 0xff000 /* Page index bits */
-
-/* Decode segment table entry */
-static int mmu_translate_segment(CPUS390XState *env, target_ulong vaddr,
- uint64_t asc, uint64_t st_entry,
- target_ulong *raddr, int *flags, int rw,
- bool exc)
-{
- CPUState *cs = CPU(s390_env_get_cpu(env));
- uint64_t origin, offs, pt_entry;
-
- if (st_entry & _SEGMENT_ENTRY_RO) {
- *flags &= ~PAGE_WRITE;
- }
-
- if ((st_entry & _SEGMENT_ENTRY_FC) && (env->cregs[0] & CR0_EDAT)) {
- /* Decode EDAT1 segment frame absolute address (1MB page) */
- *raddr = (st_entry & 0xfffffffffff00000ULL) | (vaddr & 0xfffff);
- PTE_DPRINTF("%s: SEG=0x%" PRIx64 "\n", __func__, st_entry);
- return 0;
- }
-
- /* Look up 4KB page entry */
- origin = st_entry & _SEGMENT_ENTRY_ORIGIN;
- offs = (vaddr & VADDR_PX) >> 9;
- pt_entry = ldq_phys(cs->as, origin + offs);
- PTE_DPRINTF("%s: 0x%" PRIx64 " + 0x%" PRIx64 " => 0x%016" PRIx64 "\n",
- __func__, origin, offs, pt_entry);
- return mmu_translate_pte(env, vaddr, asc, pt_entry, raddr, flags, rw, exc);
-}
-
-/* Decode region table entries */
-static int mmu_translate_region(CPUS390XState *env, target_ulong vaddr,
- uint64_t asc, uint64_t entry, int level,
- target_ulong *raddr, int *flags, int rw,
- bool exc)
-{
- CPUState *cs = CPU(s390_env_get_cpu(env));
- uint64_t origin, offs, new_entry;
- const int pchks[4] = {
- PGM_SEGMENT_TRANS, PGM_REG_THIRD_TRANS,
- PGM_REG_SEC_TRANS, PGM_REG_FIRST_TRANS
- };
-
- PTE_DPRINTF("%s: 0x%" PRIx64 "\n", __func__, entry);
-
- origin = entry & _REGION_ENTRY_ORIGIN;
- offs = (vaddr >> (17 + 11 * level / 4)) & 0x3ff8;
-
- new_entry = ldq_phys(cs->as, origin + offs);
- PTE_DPRINTF("%s: 0x%" PRIx64 " + 0x%" PRIx64 " => 0x%016" PRIx64 "\n",
- __func__, origin, offs, new_entry);
-
- if ((new_entry & _REGION_ENTRY_INV) != 0) {
- DPRINTF("%s: invalid region\n", __func__);
- trigger_page_fault(env, vaddr, pchks[level / 4], asc, rw, exc);
- return -1;
- }
-
- if ((new_entry & _REGION_ENTRY_TYPE_MASK) != level) {
- trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw, exc);
- return -1;
- }
-
- if (level == _ASCE_TYPE_SEGMENT) {
- return mmu_translate_segment(env, vaddr, asc, new_entry, raddr, flags,
- rw, exc);
- }
-
- /* Check region table offset and length */
- offs = (vaddr >> (28 + 11 * (level - 4) / 4)) & 3;
- if (offs < ((new_entry & _REGION_ENTRY_TF) >> 6)
- || offs > (new_entry & _REGION_ENTRY_LENGTH)) {
- DPRINTF("%s: invalid offset or len (%lx)\n", __func__, new_entry);
- trigger_page_fault(env, vaddr, pchks[level / 4 - 1], asc, rw, exc);
- return -1;
- }
-
- if ((env->cregs[0] & CR0_EDAT) && (new_entry & _REGION_ENTRY_RO)) {
- *flags &= ~PAGE_WRITE;
- }
-
- /* yet another region */
- return mmu_translate_region(env, vaddr, asc, new_entry, level - 4,
- raddr, flags, rw, exc);
-}
-
-static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
- uint64_t asc, uint64_t asce, target_ulong *raddr,
- int *flags, int rw, bool exc)
-{
- int level;
- int r;
-
- if (asce & _ASCE_REAL_SPACE) {
- /* direct mapping */
- *raddr = vaddr;
- return 0;
- }
-
- level = asce & _ASCE_TYPE_MASK;
- switch (level) {
- case _ASCE_TYPE_REGION1:
- if ((vaddr >> 62) > (asce & _ASCE_TABLE_LENGTH)) {
- trigger_page_fault(env, vaddr, PGM_REG_FIRST_TRANS, asc, rw, exc);
- return -1;
- }
- break;
- case _ASCE_TYPE_REGION2:
- if (vaddr & 0xffe0000000000000ULL) {
- DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
- " 0xffe0000000000000ULL\n", __func__, vaddr);
- trigger_page_fault(env, vaddr, PGM_ASCE_TYPE, asc, rw, exc);
- return -1;
- }
- if ((vaddr >> 51 & 3) > (asce & _ASCE_TABLE_LENGTH)) {
- trigger_page_fault(env, vaddr, PGM_REG_SEC_TRANS, asc, rw, exc);
- return -1;
- }
- break;
- case _ASCE_TYPE_REGION3:
- if (vaddr & 0xfffffc0000000000ULL) {
- DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
- " 0xfffffc0000000000ULL\n", __func__, vaddr);
- trigger_page_fault(env, vaddr, PGM_ASCE_TYPE, asc, rw, exc);
- return -1;
- }
- if ((vaddr >> 40 & 3) > (asce & _ASCE_TABLE_LENGTH)) {
- trigger_page_fault(env, vaddr, PGM_REG_THIRD_TRANS, asc, rw, exc);
- return -1;
- }
- break;
- case _ASCE_TYPE_SEGMENT:
- if (vaddr & 0xffffffff80000000ULL) {
- DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
- " 0xffffffff80000000ULL\n", __func__, vaddr);
- trigger_page_fault(env, vaddr, PGM_ASCE_TYPE, asc, rw, exc);
- return -1;
- }
- if ((vaddr >> 29 & 3) > (asce & _ASCE_TABLE_LENGTH)) {
- trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw, exc);
- return -1;
- }
- break;
- }
-
- r = mmu_translate_region(env, vaddr, asc, asce, level, raddr, flags, rw,
- exc);
- if (rw == MMU_DATA_STORE && !(*flags & PAGE_WRITE)) {
- trigger_prot_fault(env, vaddr, asc, rw, exc);
- return -1;
- }
-
- return r;
-}
-
-/**
- * Translate a virtual (logical) address into a physical (absolute) address.
- * @param vaddr the virtual address
- * @param rw 0 = read, 1 = write, 2 = code fetch
- * @param asc address space control (one of the PSW_ASC_* modes)
- * @param raddr the translated address is stored to this pointer
- * @param flags the PAGE_READ/WRITE/EXEC flags are stored to this pointer
- * @param exc true = inject a program check if a fault occurred
- * @return 0 if the translation was successful, -1 if a fault occurred
- */
-int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
- target_ulong *raddr, int *flags, bool exc)
-{
- static S390SKeysState *ss;
- static S390SKeysClass *skeyclass;
- int r = -1;
- uint8_t key;
-
- if (unlikely(!ss)) {
- ss = s390_get_skeys_device();
- skeyclass = S390_SKEYS_GET_CLASS(ss);
- }
-
- *flags = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
- vaddr &= TARGET_PAGE_MASK;
-
- if (!(env->psw.mask & PSW_MASK_DAT)) {
- *raddr = vaddr;
- r = 0;
- goto out;
- }
-
- switch (asc) {
- case PSW_ASC_PRIMARY:
- PTE_DPRINTF("%s: asc=primary\n", __func__);
- r = mmu_translate_asce(env, vaddr, asc, env->cregs[1], raddr, flags,
- rw, exc);
- break;
- case PSW_ASC_HOME:
- PTE_DPRINTF("%s: asc=home\n", __func__);
- r = mmu_translate_asce(env, vaddr, asc, env->cregs[13], raddr, flags,
- rw, exc);
- break;
- case PSW_ASC_SECONDARY:
- PTE_DPRINTF("%s: asc=secondary\n", __func__);
- /*
- * Instruction: Primary
- * Data: Secondary
- */
- if (rw == MMU_INST_FETCH) {
- r = mmu_translate_asce(env, vaddr, PSW_ASC_PRIMARY, env->cregs[1],
- raddr, flags, rw, exc);
- *flags &= ~(PAGE_READ | PAGE_WRITE);
- } else {
- r = mmu_translate_asce(env, vaddr, PSW_ASC_SECONDARY, env->cregs[7],
- raddr, flags, rw, exc);
- *flags &= ~(PAGE_EXEC);
- }
- break;
- case PSW_ASC_ACCREG:
- default:
- hw_error("guest switched to unknown asc mode\n");
- break;
- }
-
- out:
- /* Convert real address -> absolute address */
- *raddr = mmu_real2abs(env, *raddr);
-
- if (r == 0 && *raddr < ram_size) {
- if (skeyclass->get_skeys(ss, *raddr / TARGET_PAGE_SIZE, 1, &key)) {
- trace_get_skeys_nonzero(r);
- return 0;
- }
-
- if (*flags & PAGE_READ) {
- key |= SK_R;
- }
-
- if (*flags & PAGE_WRITE) {
- key |= SK_C;
- }
-
- if (skeyclass->set_skeys(ss, *raddr / TARGET_PAGE_SIZE, 1, &key)) {
- trace_set_skeys_nonzero(r);
- return 0;
- }
- }
-
- return r;
-}
-
-/**
- * lowprot_enabled: Check whether low-address protection is enabled
- */
-static bool lowprot_enabled(const CPUS390XState *env)
-{
- if (!(env->cregs[0] & CR0_LOWPROT)) {
- return false;
- }
- if (!(env->psw.mask & PSW_MASK_DAT)) {
- return true;
- }
-
- /* Check the private-space control bit */
- switch (env->psw.mask & PSW_MASK_ASC) {
- case PSW_ASC_PRIMARY:
- return !(env->cregs[1] & _ASCE_PRIVATE_SPACE);
- case PSW_ASC_SECONDARY:
- return !(env->cregs[7] & _ASCE_PRIVATE_SPACE);
- case PSW_ASC_HOME:
- return !(env->cregs[13] & _ASCE_PRIVATE_SPACE);
- default:
- /* We don't support access register mode */
- error_report("unsupported addressing mode");
- exit(1);
- }
-}
-
-/**
- * translate_pages: Translate a set of consecutive logical page addresses
- * to absolute addresses
- */
-static int translate_pages(S390CPU *cpu, vaddr addr, int nr_pages,
- target_ulong *pages, bool is_write)
-{
- bool lowprot = is_write && lowprot_enabled(&cpu->env);
- uint64_t asc = cpu->env.psw.mask & PSW_MASK_ASC;
- CPUS390XState *env = &cpu->env;
- int ret, i, pflags;
-
- for (i = 0; i < nr_pages; i++) {
- /* Low-address protection? */
- if (lowprot && (addr < 512 || (addr >= 4096 && addr < 4096 + 512))) {
- trigger_access_exception(env, PGM_PROTECTION, ILEN_LATER_INC, 0);
- return -EACCES;
- }
- ret = mmu_translate(env, addr, is_write, asc, &pages[i], &pflags, true);
- if (ret) {
- return ret;
- }
- if (!address_space_access_valid(&address_space_memory, pages[i],
- TARGET_PAGE_SIZE, is_write)) {
- program_interrupt(env, PGM_ADDRESSING, 0);
- return -EFAULT;
- }
- addr += TARGET_PAGE_SIZE;
- }
-
- return 0;
-}
-
-/**
- * s390_cpu_virt_mem_rw:
- * @laddr: the logical start address
- * @ar: the access register number
- * @hostbuf: buffer in host memory. NULL = do only checks w/o copying
- * @len: length that should be transferred
- * @is_write: true = write, false = read
- * Returns: 0 on success, non-zero if an exception occurred
- *
- * Copy from/to guest memory using logical addresses. Note that we inject a
- * program interrupt in case there is an error while accessing the memory.
- */
-int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf,
- int len, bool is_write)
-{
- int currlen, nr_pages, i;
- target_ulong *pages;
- int ret;
-
- if (kvm_enabled()) {
- ret = kvm_s390_mem_op(cpu, laddr, ar, hostbuf, len, is_write);
- if (ret >= 0) {
- return ret;
- }
- }
-
- nr_pages = (((laddr & ~TARGET_PAGE_MASK) + len - 1) >> TARGET_PAGE_BITS)
- + 1;
- pages = g_malloc(nr_pages * sizeof(*pages));
-
- ret = translate_pages(cpu, laddr, nr_pages, pages, is_write);
- if (ret == 0 && hostbuf != NULL) {
- /* Copy data by stepping through the area page by page */
- for (i = 0; i < nr_pages; i++) {
- currlen = MIN(len, TARGET_PAGE_SIZE - (laddr % TARGET_PAGE_SIZE));
- cpu_physical_memory_rw(pages[i] | (laddr & ~TARGET_PAGE_MASK),
- hostbuf, currlen, is_write);
- laddr += currlen;
- hostbuf += currlen;
- len -= currlen;
- }
- }
-
- g_free(pages);
- return ret;
-}
diff --git a/qemu/target-s390x/translate.c b/qemu/target-s390x/translate.c
deleted file mode 100644
index c871ef2bb..000000000
--- a/qemu/target-s390x/translate.c
+++ /dev/null
@@ -1,5442 +0,0 @@
-/*
- * S/390 translation
- *
- * Copyright (c) 2009 Ulrich Hecht
- * Copyright (c) 2010 Alexander Graf
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* #define DEBUG_INLINE_BRANCHES */
-#define S390X_DEBUG_DISAS
-/* #define S390X_DEBUG_DISAS_VERBOSE */
-
-#ifdef S390X_DEBUG_DISAS_VERBOSE
-# define LOG_DISAS(...) qemu_log(__VA_ARGS__)
-#else
-# define LOG_DISAS(...) do { } while (0)
-#endif
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "disas/disas.h"
-#include "tcg-op.h"
-#include "qemu/log.h"
-#include "qemu/host-utils.h"
-#include "exec/cpu_ldst.h"
-
-/* global register indexes */
-static TCGv_env cpu_env;
-
-#include "exec/gen-icount.h"
-#include "exec/helper-proto.h"
-#include "exec/helper-gen.h"
-
-#include "trace-tcg.h"
-#include "exec/log.h"
-
-
-/* Information that (most) every instruction needs to manipulate. */
-typedef struct DisasContext DisasContext;
-typedef struct DisasInsn DisasInsn;
-typedef struct DisasFields DisasFields;
-
-struct DisasContext {
- struct TranslationBlock *tb;
- const DisasInsn *insn;
- DisasFields *fields;
- uint64_t pc, next_pc;
- enum cc_op cc_op;
- bool singlestep_enabled;
-};
-
-/* Information carried about a condition to be evaluated. */
-typedef struct {
- TCGCond cond:8;
- bool is_64;
- bool g1;
- bool g2;
- union {
- struct { TCGv_i64 a, b; } s64;
- struct { TCGv_i32 a, b; } s32;
- } u;
-} DisasCompare;
-
-#define DISAS_EXCP 4
-
-#ifdef DEBUG_INLINE_BRANCHES
-static uint64_t inline_branch_hit[CC_OP_MAX];
-static uint64_t inline_branch_miss[CC_OP_MAX];
-#endif
-
-static uint64_t pc_to_link_info(DisasContext *s, uint64_t pc)
-{
- if (!(s->tb->flags & FLAG_MASK_64)) {
- if (s->tb->flags & FLAG_MASK_32) {
- return pc | 0x80000000;
- }
- }
- return pc;
-}
-
-void s390_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
- int flags)
-{
- S390CPU *cpu = S390_CPU(cs);
- CPUS390XState *env = &cpu->env;
- int i;
-
- if (env->cc_op > 3) {
- cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %15s\n",
- env->psw.mask, env->psw.addr, cc_name(env->cc_op));
- } else {
- cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %02x\n",
- env->psw.mask, env->psw.addr, env->cc_op);
- }
-
- for (i = 0; i < 16; i++) {
- cpu_fprintf(f, "R%02d=%016" PRIx64, i, env->regs[i]);
- if ((i % 4) == 3) {
- cpu_fprintf(f, "\n");
- } else {
- cpu_fprintf(f, " ");
- }
- }
-
- for (i = 0; i < 16; i++) {
- cpu_fprintf(f, "F%02d=%016" PRIx64, i, get_freg(env, i)->ll);
- if ((i % 4) == 3) {
- cpu_fprintf(f, "\n");
- } else {
- cpu_fprintf(f, " ");
- }
- }
-
- for (i = 0; i < 32; i++) {
- cpu_fprintf(f, "V%02d=%016" PRIx64 "%016" PRIx64, i,
- env->vregs[i][0].ll, env->vregs[i][1].ll);
- cpu_fprintf(f, (i % 2) ? "\n" : " ");
- }
-
-#ifndef CONFIG_USER_ONLY
- for (i = 0; i < 16; i++) {
- cpu_fprintf(f, "C%02d=%016" PRIx64, i, env->cregs[i]);
- if ((i % 4) == 3) {
- cpu_fprintf(f, "\n");
- } else {
- cpu_fprintf(f, " ");
- }
- }
-#endif
-
-#ifdef DEBUG_INLINE_BRANCHES
- for (i = 0; i < CC_OP_MAX; i++) {
- cpu_fprintf(f, " %15s = %10ld\t%10ld\n", cc_name(i),
- inline_branch_miss[i], inline_branch_hit[i]);
- }
-#endif
-
- cpu_fprintf(f, "\n");
-}
-
-static TCGv_i64 psw_addr;
-static TCGv_i64 psw_mask;
-static TCGv_i64 gbea;
-
-static TCGv_i32 cc_op;
-static TCGv_i64 cc_src;
-static TCGv_i64 cc_dst;
-static TCGv_i64 cc_vr;
-
-static char cpu_reg_names[32][4];
-static TCGv_i64 regs[16];
-static TCGv_i64 fregs[16];
-
-void s390x_translate_init(void)
-{
- int i;
-
- cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
- psw_addr = tcg_global_mem_new_i64(cpu_env,
- offsetof(CPUS390XState, psw.addr),
- "psw_addr");
- psw_mask = tcg_global_mem_new_i64(cpu_env,
- offsetof(CPUS390XState, psw.mask),
- "psw_mask");
- gbea = tcg_global_mem_new_i64(cpu_env,
- offsetof(CPUS390XState, gbea),
- "gbea");
-
- cc_op = tcg_global_mem_new_i32(cpu_env, offsetof(CPUS390XState, cc_op),
- "cc_op");
- cc_src = tcg_global_mem_new_i64(cpu_env, offsetof(CPUS390XState, cc_src),
- "cc_src");
- cc_dst = tcg_global_mem_new_i64(cpu_env, offsetof(CPUS390XState, cc_dst),
- "cc_dst");
- cc_vr = tcg_global_mem_new_i64(cpu_env, offsetof(CPUS390XState, cc_vr),
- "cc_vr");
-
- for (i = 0; i < 16; i++) {
- snprintf(cpu_reg_names[i], sizeof(cpu_reg_names[0]), "r%d", i);
- regs[i] = tcg_global_mem_new(cpu_env,
- offsetof(CPUS390XState, regs[i]),
- cpu_reg_names[i]);
- }
-
- for (i = 0; i < 16; i++) {
- snprintf(cpu_reg_names[i + 16], sizeof(cpu_reg_names[0]), "f%d", i);
- fregs[i] = tcg_global_mem_new(cpu_env,
- offsetof(CPUS390XState, vregs[i][0].d),
- cpu_reg_names[i + 16]);
- }
-}
-
-static TCGv_i64 load_reg(int reg)
-{
- TCGv_i64 r = tcg_temp_new_i64();
- tcg_gen_mov_i64(r, regs[reg]);
- return r;
-}
-
-static TCGv_i64 load_freg32_i64(int reg)
-{
- TCGv_i64 r = tcg_temp_new_i64();
- tcg_gen_shri_i64(r, fregs[reg], 32);
- return r;
-}
-
-static void store_reg(int reg, TCGv_i64 v)
-{
- tcg_gen_mov_i64(regs[reg], v);
-}
-
-static void store_freg(int reg, TCGv_i64 v)
-{
- tcg_gen_mov_i64(fregs[reg], v);
-}
-
-static void store_reg32_i64(int reg, TCGv_i64 v)
-{
- /* 32 bit register writes keep the upper half */
- tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 32);
-}
-
-static void store_reg32h_i64(int reg, TCGv_i64 v)
-{
- tcg_gen_deposit_i64(regs[reg], regs[reg], v, 32, 32);
-}
-
-static void store_freg32_i64(int reg, TCGv_i64 v)
-{
- tcg_gen_deposit_i64(fregs[reg], fregs[reg], v, 32, 32);
-}
-
-static void return_low128(TCGv_i64 dest)
-{
- tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUS390XState, retxl));
-}
-
-static void update_psw_addr(DisasContext *s)
-{
- /* psw.addr */
- tcg_gen_movi_i64(psw_addr, s->pc);
-}
-
-static void per_branch(DisasContext *s, bool to_next)
-{
-#ifndef CONFIG_USER_ONLY
- tcg_gen_movi_i64(gbea, s->pc);
-
- if (s->tb->flags & FLAG_MASK_PER) {
- TCGv_i64 next_pc = to_next ? tcg_const_i64(s->next_pc) : psw_addr;
- gen_helper_per_branch(cpu_env, gbea, next_pc);
- if (to_next) {
- tcg_temp_free_i64(next_pc);
- }
- }
-#endif
-}
-
-static void per_branch_cond(DisasContext *s, TCGCond cond,
- TCGv_i64 arg1, TCGv_i64 arg2)
-{
-#ifndef CONFIG_USER_ONLY
- if (s->tb->flags & FLAG_MASK_PER) {
- TCGLabel *lab = gen_new_label();
- tcg_gen_brcond_i64(tcg_invert_cond(cond), arg1, arg2, lab);
-
- tcg_gen_movi_i64(gbea, s->pc);
- gen_helper_per_branch(cpu_env, gbea, psw_addr);
-
- gen_set_label(lab);
- } else {
- TCGv_i64 pc = tcg_const_i64(s->pc);
- tcg_gen_movcond_i64(cond, gbea, arg1, arg2, gbea, pc);
- tcg_temp_free_i64(pc);
- }
-#endif
-}
-
-static void per_breaking_event(DisasContext *s)
-{
- tcg_gen_movi_i64(gbea, s->pc);
-}
-
-static void update_cc_op(DisasContext *s)
-{
- if (s->cc_op != CC_OP_DYNAMIC && s->cc_op != CC_OP_STATIC) {
- tcg_gen_movi_i32(cc_op, s->cc_op);
- }
-}
-
-static void potential_page_fault(DisasContext *s)
-{
- update_psw_addr(s);
- update_cc_op(s);
-}
-
-static inline uint64_t ld_code2(CPUS390XState *env, uint64_t pc)
-{
- return (uint64_t)cpu_lduw_code(env, pc);
-}
-
-static inline uint64_t ld_code4(CPUS390XState *env, uint64_t pc)
-{
- return (uint64_t)(uint32_t)cpu_ldl_code(env, pc);
-}
-
-static int get_mem_index(DisasContext *s)
-{
- switch (s->tb->flags & FLAG_MASK_ASC) {
- case PSW_ASC_PRIMARY >> 32:
- return 0;
- case PSW_ASC_SECONDARY >> 32:
- return 1;
- case PSW_ASC_HOME >> 32:
- return 2;
- default:
- tcg_abort();
- break;
- }
-}
-
-static void gen_exception(int excp)
-{
- TCGv_i32 tmp = tcg_const_i32(excp);
- gen_helper_exception(cpu_env, tmp);
- tcg_temp_free_i32(tmp);
-}
-
-static void gen_program_exception(DisasContext *s, int code)
-{
- TCGv_i32 tmp;
-
- /* Remember what pgm exeption this was. */
- tmp = tcg_const_i32(code);
- tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code));
- tcg_temp_free_i32(tmp);
-
- tmp = tcg_const_i32(s->next_pc - s->pc);
- tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilen));
- tcg_temp_free_i32(tmp);
-
- /* Advance past instruction. */
- s->pc = s->next_pc;
- update_psw_addr(s);
-
- /* Save off cc. */
- update_cc_op(s);
-
- /* Trigger exception. */
- gen_exception(EXCP_PGM);
-}
-
-static inline void gen_illegal_opcode(DisasContext *s)
-{
- gen_program_exception(s, PGM_OPERATION);
-}
-
-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);
-}
-
-#ifndef CONFIG_USER_ONLY
-static void check_privileged(DisasContext *s)
-{
- if (s->tb->flags & (PSW_MASK_PSTATE >> 32)) {
- 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();
- bool need_31 = !(s->tb->flags & FLAG_MASK_64);
-
- /* Note that d2 is limited to 20 bits, signed. If we crop negative
- displacements early we create larger immedate addends. */
-
- /* Note that addi optimizes the imm==0 case. */
- if (b2 && x2) {
- tcg_gen_add_i64(tmp, regs[b2], regs[x2]);
- tcg_gen_addi_i64(tmp, tmp, d2);
- } else if (b2) {
- tcg_gen_addi_i64(tmp, regs[b2], d2);
- } else if (x2) {
- tcg_gen_addi_i64(tmp, regs[x2], d2);
- } else {
- if (need_31) {
- d2 &= 0x7fffffff;
- need_31 = false;
- }
- tcg_gen_movi_i64(tmp, d2);
- }
- if (need_31) {
- tcg_gen_andi_i64(tmp, tmp, 0x7fffffff);
- }
-
- return tmp;
-}
-
-static inline bool live_cc_data(DisasContext *s)
-{
- return (s->cc_op != CC_OP_DYNAMIC
- && s->cc_op != CC_OP_STATIC
- && s->cc_op > 3);
-}
-
-static inline void gen_op_movi_cc(DisasContext *s, uint32_t val)
-{
- if (live_cc_data(s)) {
- tcg_gen_discard_i64(cc_src);
- tcg_gen_discard_i64(cc_dst);
- tcg_gen_discard_i64(cc_vr);
- }
- s->cc_op = CC_OP_CONST0 + val;
-}
-
-static void gen_op_update1_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 dst)
-{
- if (live_cc_data(s)) {
- tcg_gen_discard_i64(cc_src);
- tcg_gen_discard_i64(cc_vr);
- }
- tcg_gen_mov_i64(cc_dst, dst);
- s->cc_op = op;
-}
-
-static void gen_op_update2_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
- TCGv_i64 dst)
-{
- if (live_cc_data(s)) {
- tcg_gen_discard_i64(cc_vr);
- }
- tcg_gen_mov_i64(cc_src, src);
- tcg_gen_mov_i64(cc_dst, dst);
- s->cc_op = op;
-}
-
-static void gen_op_update3_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
- TCGv_i64 dst, TCGv_i64 vr)
-{
- tcg_gen_mov_i64(cc_src, src);
- tcg_gen_mov_i64(cc_dst, dst);
- tcg_gen_mov_i64(cc_vr, vr);
- s->cc_op = op;
-}
-
-static void set_cc_nz_u64(DisasContext *s, TCGv_i64 val)
-{
- gen_op_update1_cc_i64(s, CC_OP_NZ, val);
-}
-
-static void gen_set_cc_nz_f32(DisasContext *s, TCGv_i64 val)
-{
- gen_op_update1_cc_i64(s, CC_OP_NZ_F32, val);
-}
-
-static void gen_set_cc_nz_f64(DisasContext *s, TCGv_i64 val)
-{
- gen_op_update1_cc_i64(s, CC_OP_NZ_F64, val);
-}
-
-static void gen_set_cc_nz_f128(DisasContext *s, TCGv_i64 vh, TCGv_i64 vl)
-{
- gen_op_update2_cc_i64(s, CC_OP_NZ_F128, vh, vl);
-}
-
-/* CC value is in env->cc_op */
-static void set_cc_static(DisasContext *s)
-{
- if (live_cc_data(s)) {
- tcg_gen_discard_i64(cc_src);
- tcg_gen_discard_i64(cc_dst);
- tcg_gen_discard_i64(cc_vr);
- }
- s->cc_op = CC_OP_STATIC;
-}
-
-/* calculates cc into cc_op */
-static void gen_op_calc_cc(DisasContext *s)
-{
- TCGv_i32 local_cc_op;
- TCGv_i64 dummy;
-
- TCGV_UNUSED_I32(local_cc_op);
- TCGV_UNUSED_I64(dummy);
- switch (s->cc_op) {
- default:
- dummy = tcg_const_i64(0);
- /* FALLTHRU */
- case CC_OP_ADD_64:
- case CC_OP_ADDU_64:
- case CC_OP_ADDC_64:
- case CC_OP_SUB_64:
- case CC_OP_SUBU_64:
- case CC_OP_SUBB_64:
- case CC_OP_ADD_32:
- case CC_OP_ADDU_32:
- case CC_OP_ADDC_32:
- case CC_OP_SUB_32:
- case CC_OP_SUBU_32:
- case CC_OP_SUBB_32:
- local_cc_op = tcg_const_i32(s->cc_op);
- break;
- case CC_OP_CONST0:
- case CC_OP_CONST1:
- case CC_OP_CONST2:
- case CC_OP_CONST3:
- case CC_OP_STATIC:
- case CC_OP_DYNAMIC:
- break;
- }
-
- switch (s->cc_op) {
- case CC_OP_CONST0:
- case CC_OP_CONST1:
- case CC_OP_CONST2:
- case CC_OP_CONST3:
- /* s->cc_op is the cc value */
- tcg_gen_movi_i32(cc_op, s->cc_op - CC_OP_CONST0);
- break;
- case CC_OP_STATIC:
- /* env->cc_op already is the cc value */
- break;
- case CC_OP_NZ:
- case CC_OP_ABS_64:
- case CC_OP_NABS_64:
- case CC_OP_ABS_32:
- case CC_OP_NABS_32:
- case CC_OP_LTGT0_32:
- case CC_OP_LTGT0_64:
- case CC_OP_COMP_32:
- case CC_OP_COMP_64:
- case CC_OP_NZ_F32:
- case CC_OP_NZ_F64:
- case CC_OP_FLOGR:
- /* 1 argument */
- gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy);
- break;
- case CC_OP_ICM:
- case CC_OP_LTGT_32:
- case CC_OP_LTGT_64:
- case CC_OP_LTUGTU_32:
- case CC_OP_LTUGTU_64:
- case CC_OP_TM_32:
- case CC_OP_TM_64:
- case CC_OP_SLA_32:
- case CC_OP_SLA_64:
- case CC_OP_NZ_F128:
- /* 2 arguments */
- gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy);
- break;
- case CC_OP_ADD_64:
- case CC_OP_ADDU_64:
- case CC_OP_ADDC_64:
- case CC_OP_SUB_64:
- case CC_OP_SUBU_64:
- case CC_OP_SUBB_64:
- case CC_OP_ADD_32:
- case CC_OP_ADDU_32:
- case CC_OP_ADDC_32:
- case CC_OP_SUB_32:
- case CC_OP_SUBU_32:
- case CC_OP_SUBB_32:
- /* 3 arguments */
- gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, cc_vr);
- break;
- case CC_OP_DYNAMIC:
- /* unknown operation - assume 3 arguments and cc_op in env */
- gen_helper_calc_cc(cc_op, cpu_env, cc_op, cc_src, cc_dst, cc_vr);
- break;
- default:
- tcg_abort();
- }
-
- if (!TCGV_IS_UNUSED_I32(local_cc_op)) {
- tcg_temp_free_i32(local_cc_op);
- }
- if (!TCGV_IS_UNUSED_I64(dummy)) {
- tcg_temp_free_i64(dummy);
- }
-
- /* We now have cc in cc_op as constant */
- set_cc_static(s);
-}
-
-static int use_goto_tb(DisasContext *s, uint64_t dest)
-{
- /* NOTE: we handle the case where the TB spans two pages here */
- return (((dest & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK)
- || (dest & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK))
- && !s->singlestep_enabled
- && !(s->tb->cflags & CF_LAST_IO)
- && !(s->tb->flags & FLAG_MASK_PER));
-}
-
-static void account_noninline_branch(DisasContext *s, int cc_op)
-{
-#ifdef DEBUG_INLINE_BRANCHES
- inline_branch_miss[cc_op]++;
-#endif
-}
-
-static void account_inline_branch(DisasContext *s, int cc_op)
-{
-#ifdef DEBUG_INLINE_BRANCHES
- inline_branch_hit[cc_op]++;
-#endif
-}
-
-/* Table of mask values to comparison codes, given a comparison as input.
- For such, CC=3 should not be possible. */
-static const TCGCond ltgt_cond[16] = {
- TCG_COND_NEVER, TCG_COND_NEVER, /* | | | x */
- TCG_COND_GT, TCG_COND_GT, /* | | GT | x */
- TCG_COND_LT, TCG_COND_LT, /* | LT | | x */
- TCG_COND_NE, TCG_COND_NE, /* | LT | GT | x */
- TCG_COND_EQ, TCG_COND_EQ, /* EQ | | | x */
- TCG_COND_GE, TCG_COND_GE, /* EQ | | GT | x */
- TCG_COND_LE, TCG_COND_LE, /* EQ | LT | | x */
- TCG_COND_ALWAYS, TCG_COND_ALWAYS, /* EQ | LT | GT | x */
-};
-
-/* Table of mask values to comparison codes, given a logic op as input.
- For such, only CC=0 and CC=1 should be possible. */
-static const TCGCond nz_cond[16] = {
- TCG_COND_NEVER, TCG_COND_NEVER, /* | | x | x */
- TCG_COND_NEVER, TCG_COND_NEVER,
- TCG_COND_NE, TCG_COND_NE, /* | NE | x | x */
- TCG_COND_NE, TCG_COND_NE,
- TCG_COND_EQ, TCG_COND_EQ, /* EQ | | x | x */
- TCG_COND_EQ, TCG_COND_EQ,
- TCG_COND_ALWAYS, TCG_COND_ALWAYS, /* EQ | NE | x | x */
- TCG_COND_ALWAYS, TCG_COND_ALWAYS,
-};
-
-/* Interpret MASK in terms of S->CC_OP, and fill in C with all the
- details required to generate a TCG comparison. */
-static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
-{
- TCGCond cond;
- enum cc_op old_cc_op = s->cc_op;
-
- if (mask == 15 || mask == 0) {
- c->cond = (mask ? TCG_COND_ALWAYS : TCG_COND_NEVER);
- c->u.s32.a = cc_op;
- c->u.s32.b = cc_op;
- c->g1 = c->g2 = true;
- c->is_64 = false;
- return;
- }
-
- /* Find the TCG condition for the mask + cc op. */
- switch (old_cc_op) {
- case CC_OP_LTGT0_32:
- case CC_OP_LTGT0_64:
- case CC_OP_LTGT_32:
- case CC_OP_LTGT_64:
- cond = ltgt_cond[mask];
- if (cond == TCG_COND_NEVER) {
- goto do_dynamic;
- }
- account_inline_branch(s, old_cc_op);
- break;
-
- case CC_OP_LTUGTU_32:
- case CC_OP_LTUGTU_64:
- cond = tcg_unsigned_cond(ltgt_cond[mask]);
- if (cond == TCG_COND_NEVER) {
- goto do_dynamic;
- }
- account_inline_branch(s, old_cc_op);
- break;
-
- case CC_OP_NZ:
- cond = nz_cond[mask];
- if (cond == TCG_COND_NEVER) {
- goto do_dynamic;
- }
- account_inline_branch(s, old_cc_op);
- break;
-
- case CC_OP_TM_32:
- case CC_OP_TM_64:
- switch (mask) {
- case 8:
- cond = TCG_COND_EQ;
- break;
- case 4 | 2 | 1:
- cond = TCG_COND_NE;
- break;
- default:
- goto do_dynamic;
- }
- account_inline_branch(s, old_cc_op);
- break;
-
- case CC_OP_ICM:
- switch (mask) {
- case 8:
- cond = TCG_COND_EQ;
- break;
- case 4 | 2 | 1:
- case 4 | 2:
- cond = TCG_COND_NE;
- break;
- default:
- goto do_dynamic;
- }
- account_inline_branch(s, old_cc_op);
- break;
-
- case CC_OP_FLOGR:
- switch (mask & 0xa) {
- case 8: /* src == 0 -> no one bit found */
- cond = TCG_COND_EQ;
- break;
- case 2: /* src != 0 -> one bit found */
- cond = TCG_COND_NE;
- break;
- default:
- goto do_dynamic;
- }
- account_inline_branch(s, old_cc_op);
- break;
-
- case CC_OP_ADDU_32:
- case CC_OP_ADDU_64:
- switch (mask) {
- case 8 | 2: /* vr == 0 */
- cond = TCG_COND_EQ;
- break;
- case 4 | 1: /* vr != 0 */
- cond = TCG_COND_NE;
- break;
- case 8 | 4: /* no carry -> vr >= src */
- cond = TCG_COND_GEU;
- break;
- case 2 | 1: /* carry -> vr < src */
- cond = TCG_COND_LTU;
- break;
- default:
- goto do_dynamic;
- }
- account_inline_branch(s, old_cc_op);
- break;
-
- case CC_OP_SUBU_32:
- case CC_OP_SUBU_64:
- /* Note that CC=0 is impossible; treat it as dont-care. */
- switch (mask & 7) {
- case 2: /* zero -> op1 == op2 */
- cond = TCG_COND_EQ;
- break;
- case 4 | 1: /* !zero -> op1 != op2 */
- cond = TCG_COND_NE;
- break;
- case 4: /* borrow (!carry) -> op1 < op2 */
- cond = TCG_COND_LTU;
- break;
- case 2 | 1: /* !borrow (carry) -> op1 >= op2 */
- cond = TCG_COND_GEU;
- break;
- default:
- goto do_dynamic;
- }
- account_inline_branch(s, old_cc_op);
- break;
-
- default:
- do_dynamic:
- /* Calculate cc value. */
- gen_op_calc_cc(s);
- /* FALLTHRU */
-
- case CC_OP_STATIC:
- /* Jump based on CC. We'll load up the real cond below;
- the assignment here merely avoids a compiler warning. */
- account_noninline_branch(s, old_cc_op);
- old_cc_op = CC_OP_STATIC;
- cond = TCG_COND_NEVER;
- break;
- }
-
- /* Load up the arguments of the comparison. */
- c->is_64 = true;
- c->g1 = c->g2 = false;
- switch (old_cc_op) {
- case CC_OP_LTGT0_32:
- c->is_64 = false;
- c->u.s32.a = tcg_temp_new_i32();
- tcg_gen_extrl_i64_i32(c->u.s32.a, cc_dst);
- c->u.s32.b = tcg_const_i32(0);
- break;
- case CC_OP_LTGT_32:
- case CC_OP_LTUGTU_32:
- case CC_OP_SUBU_32:
- c->is_64 = false;
- c->u.s32.a = tcg_temp_new_i32();
- tcg_gen_extrl_i64_i32(c->u.s32.a, cc_src);
- c->u.s32.b = tcg_temp_new_i32();
- tcg_gen_extrl_i64_i32(c->u.s32.b, cc_dst);
- break;
-
- case CC_OP_LTGT0_64:
- case CC_OP_NZ:
- case CC_OP_FLOGR:
- c->u.s64.a = cc_dst;
- c->u.s64.b = tcg_const_i64(0);
- c->g1 = true;
- break;
- case CC_OP_LTGT_64:
- case CC_OP_LTUGTU_64:
- case CC_OP_SUBU_64:
- c->u.s64.a = cc_src;
- c->u.s64.b = cc_dst;
- c->g1 = c->g2 = true;
- break;
-
- case CC_OP_TM_32:
- case CC_OP_TM_64:
- case CC_OP_ICM:
- c->u.s64.a = tcg_temp_new_i64();
- c->u.s64.b = tcg_const_i64(0);
- tcg_gen_and_i64(c->u.s64.a, cc_src, cc_dst);
- break;
-
- case CC_OP_ADDU_32:
- c->is_64 = false;
- c->u.s32.a = tcg_temp_new_i32();
- c->u.s32.b = tcg_temp_new_i32();
- tcg_gen_extrl_i64_i32(c->u.s32.a, cc_vr);
- if (cond == TCG_COND_EQ || cond == TCG_COND_NE) {
- tcg_gen_movi_i32(c->u.s32.b, 0);
- } else {
- tcg_gen_extrl_i64_i32(c->u.s32.b, cc_src);
- }
- break;
-
- case CC_OP_ADDU_64:
- c->u.s64.a = cc_vr;
- c->g1 = true;
- if (cond == TCG_COND_EQ || cond == TCG_COND_NE) {
- c->u.s64.b = tcg_const_i64(0);
- } else {
- c->u.s64.b = cc_src;
- c->g2 = true;
- }
- break;
-
- case CC_OP_STATIC:
- c->is_64 = false;
- c->u.s32.a = cc_op;
- c->g1 = true;
- switch (mask) {
- case 0x8 | 0x4 | 0x2: /* cc != 3 */
- cond = TCG_COND_NE;
- c->u.s32.b = tcg_const_i32(3);
- break;
- case 0x8 | 0x4 | 0x1: /* cc != 2 */
- cond = TCG_COND_NE;
- c->u.s32.b = tcg_const_i32(2);
- break;
- case 0x8 | 0x2 | 0x1: /* cc != 1 */
- cond = TCG_COND_NE;
- c->u.s32.b = tcg_const_i32(1);
- break;
- case 0x8 | 0x2: /* cc == 0 || cc == 2 => (cc & 1) == 0 */
- cond = TCG_COND_EQ;
- c->g1 = false;
- c->u.s32.a = tcg_temp_new_i32();
- c->u.s32.b = tcg_const_i32(0);
- tcg_gen_andi_i32(c->u.s32.a, cc_op, 1);
- break;
- case 0x8 | 0x4: /* cc < 2 */
- cond = TCG_COND_LTU;
- c->u.s32.b = tcg_const_i32(2);
- break;
- case 0x8: /* cc == 0 */
- cond = TCG_COND_EQ;
- c->u.s32.b = tcg_const_i32(0);
- break;
- case 0x4 | 0x2 | 0x1: /* cc != 0 */
- cond = TCG_COND_NE;
- c->u.s32.b = tcg_const_i32(0);
- break;
- case 0x4 | 0x1: /* cc == 1 || cc == 3 => (cc & 1) != 0 */
- cond = TCG_COND_NE;
- c->g1 = false;
- c->u.s32.a = tcg_temp_new_i32();
- c->u.s32.b = tcg_const_i32(0);
- tcg_gen_andi_i32(c->u.s32.a, cc_op, 1);
- break;
- case 0x4: /* cc == 1 */
- cond = TCG_COND_EQ;
- c->u.s32.b = tcg_const_i32(1);
- break;
- case 0x2 | 0x1: /* cc > 1 */
- cond = TCG_COND_GTU;
- c->u.s32.b = tcg_const_i32(1);
- break;
- case 0x2: /* cc == 2 */
- cond = TCG_COND_EQ;
- c->u.s32.b = tcg_const_i32(2);
- break;
- case 0x1: /* cc == 3 */
- cond = TCG_COND_EQ;
- c->u.s32.b = tcg_const_i32(3);
- break;
- default:
- /* CC is masked by something else: (8 >> cc) & mask. */
- cond = TCG_COND_NE;
- c->g1 = false;
- c->u.s32.a = tcg_const_i32(8);
- c->u.s32.b = tcg_const_i32(0);
- tcg_gen_shr_i32(c->u.s32.a, c->u.s32.a, cc_op);
- tcg_gen_andi_i32(c->u.s32.a, c->u.s32.a, mask);
- break;
- }
- break;
-
- default:
- abort();
- }
- c->cond = cond;
-}
-
-static void free_compare(DisasCompare *c)
-{
- if (!c->g1) {
- if (c->is_64) {
- tcg_temp_free_i64(c->u.s64.a);
- } else {
- tcg_temp_free_i32(c->u.s32.a);
- }
- }
- if (!c->g2) {
- if (c->is_64) {
- tcg_temp_free_i64(c->u.s64.b);
- } else {
- tcg_temp_free_i32(c->u.s32.b);
- }
- }
-}
-
-/* ====================================================================== */
-/* Define the insn format enumeration. */
-#define F0(N) FMT_##N,
-#define F1(N, X1) F0(N)
-#define F2(N, X1, X2) F0(N)
-#define F3(N, X1, X2, X3) F0(N)
-#define F4(N, X1, X2, X3, X4) F0(N)
-#define F5(N, X1, X2, X3, X4, X5) F0(N)
-
-typedef enum {
-#include "insn-format.def"
-} DisasFormat;
-
-#undef F0
-#undef F1
-#undef F2
-#undef F3
-#undef F4
-#undef F5
-
-/* Define a structure to hold the decoded fields. We'll store each inside
- an array indexed by an enum. In order to conserve memory, we'll arrange
- for fields that do not exist at the same time to overlap, thus the "C"
- for compact. For checking purposes there is an "O" for original index
- as well that will be applied to availability bitmaps. */
-
-enum DisasFieldIndexO {
- FLD_O_r1,
- FLD_O_r2,
- FLD_O_r3,
- FLD_O_m1,
- FLD_O_m3,
- FLD_O_m4,
- FLD_O_b1,
- FLD_O_b2,
- FLD_O_b4,
- FLD_O_d1,
- FLD_O_d2,
- FLD_O_d4,
- FLD_O_x2,
- FLD_O_l1,
- FLD_O_l2,
- FLD_O_i1,
- FLD_O_i2,
- FLD_O_i3,
- FLD_O_i4,
- FLD_O_i5
-};
-
-enum DisasFieldIndexC {
- FLD_C_r1 = 0,
- FLD_C_m1 = 0,
- FLD_C_b1 = 0,
- FLD_C_i1 = 0,
-
- FLD_C_r2 = 1,
- FLD_C_b2 = 1,
- FLD_C_i2 = 1,
-
- FLD_C_r3 = 2,
- FLD_C_m3 = 2,
- FLD_C_i3 = 2,
-
- FLD_C_m4 = 3,
- FLD_C_b4 = 3,
- FLD_C_i4 = 3,
- FLD_C_l1 = 3,
-
- FLD_C_i5 = 4,
- FLD_C_d1 = 4,
-
- FLD_C_d2 = 5,
-
- FLD_C_d4 = 6,
- FLD_C_x2 = 6,
- FLD_C_l2 = 6,
-
- NUM_C_FIELD = 7
-};
-
-struct DisasFields {
- uint64_t raw_insn;
- unsigned op:8;
- unsigned op2:8;
- unsigned presentC:16;
- unsigned int presentO;
- int c[NUM_C_FIELD];
-};
-
-/* This is the way fields are to be accessed out of DisasFields. */
-#define have_field(S, F) have_field1((S), FLD_O_##F)
-#define get_field(S, F) get_field1((S), FLD_O_##F, FLD_C_##F)
-
-static bool have_field1(const DisasFields *f, enum DisasFieldIndexO c)
-{
- return (f->presentO >> c) & 1;
-}
-
-static int get_field1(const DisasFields *f, enum DisasFieldIndexO o,
- enum DisasFieldIndexC c)
-{
- assert(have_field1(f, o));
- return f->c[c];
-}
-
-/* Describe the layout of each field in each format. */
-typedef struct DisasField {
- unsigned int beg:8;
- unsigned int size:8;
- unsigned int type:2;
- unsigned int indexC:6;
- enum DisasFieldIndexO indexO:8;
-} DisasField;
-
-typedef struct DisasFormatInfo {
- DisasField op[NUM_C_FIELD];
-} DisasFormatInfo;
-
-#define R(N, B) { B, 4, 0, FLD_C_r##N, FLD_O_r##N }
-#define M(N, B) { B, 4, 0, FLD_C_m##N, FLD_O_m##N }
-#define BD(N, BB, BD) { BB, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
- { BD, 12, 0, FLD_C_d##N, FLD_O_d##N }
-#define BXD(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
- { 12, 4, 0, FLD_C_x##N, FLD_O_x##N }, \
- { 20, 12, 0, FLD_C_d##N, FLD_O_d##N }
-#define BDL(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
- { 20, 20, 2, FLD_C_d##N, FLD_O_d##N }
-#define BXDL(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
- { 12, 4, 0, FLD_C_x##N, FLD_O_x##N }, \
- { 20, 20, 2, FLD_C_d##N, FLD_O_d##N }
-#define I(N, B, S) { B, S, 1, FLD_C_i##N, FLD_O_i##N }
-#define L(N, B, S) { B, S, 0, FLD_C_l##N, FLD_O_l##N }
-
-#define F0(N) { { } },
-#define F1(N, X1) { { X1 } },
-#define F2(N, X1, X2) { { X1, X2 } },
-#define F3(N, X1, X2, X3) { { X1, X2, X3 } },
-#define F4(N, X1, X2, X3, X4) { { X1, X2, X3, X4 } },
-#define F5(N, X1, X2, X3, X4, X5) { { X1, X2, X3, X4, X5 } },
-
-static const DisasFormatInfo format_info[] = {
-#include "insn-format.def"
-};
-
-#undef F0
-#undef F1
-#undef F2
-#undef F3
-#undef F4
-#undef F5
-#undef R
-#undef M
-#undef BD
-#undef BXD
-#undef BDL
-#undef BXDL
-#undef I
-#undef L
-
-/* Generally, we'll extract operands into this structures, operate upon
- them, and store them back. See the "in1", "in2", "prep", "wout" sets
- of routines below for more details. */
-typedef struct {
- bool g_out, g_out2, g_in1, g_in2;
- TCGv_i64 out, out2, in1, in2;
- TCGv_i64 addr1;
-} DisasOps;
-
-/* Instructions can place constraints on their operands, raising specification
- exceptions if they are violated. To make this easy to automate, each "in1",
- "in2", "prep", "wout" helper will have a SPEC_<name> define that equals one
- of the following, or 0. To make this easy to document, we'll put the
- SPEC_<name> defines next to <name>. */
-
-#define SPEC_r1_even 1
-#define SPEC_r2_even 2
-#define SPEC_r3_even 4
-#define SPEC_r1_f128 8
-#define SPEC_r2_f128 16
-
-/* Return values from translate_one, indicating the state of the TB. */
-typedef enum {
- /* Continue the TB. */
- NO_EXIT,
- /* We have emitted one or more goto_tb. No fixup required. */
- EXIT_GOTO_TB,
- /* We are not using a goto_tb (for whatever reason), but have updated
- the PC (for whatever reason), so there's no need to do it again on
- exiting the TB. */
- EXIT_PC_UPDATED,
- /* We are exiting the TB, but have neither emitted a goto_tb, nor
- updated the PC for the next instruction to be executed. */
- EXIT_PC_STALE,
- /* We are ending the TB with a noreturn function call, e.g. longjmp.
- No following code will be executed. */
- EXIT_NORETURN,
-} ExitStatus;
-
-typedef enum DisasFacility {
- FAC_Z, /* zarch (default) */
- FAC_CASS, /* compare and swap and store */
- FAC_CASS2, /* compare and swap and store 2*/
- FAC_DFP, /* decimal floating point */
- FAC_DFPR, /* decimal floating point rounding */
- FAC_DO, /* distinct operands */
- FAC_EE, /* execute extensions */
- FAC_EI, /* extended immediate */
- FAC_FPE, /* floating point extension */
- FAC_FPSSH, /* floating point support sign handling */
- FAC_FPRGR, /* FPR-GR transfer */
- FAC_GIE, /* general instructions extension */
- FAC_HFP_MA, /* HFP multiply-and-add/subtract */
- FAC_HW, /* high-word */
- FAC_IEEEE_SIM, /* IEEE exception sumilation */
- FAC_MIE, /* miscellaneous-instruction-extensions */
- FAC_LAT, /* load-and-trap */
- FAC_LOC, /* load/store on condition */
- FAC_LD, /* long displacement */
- FAC_PC, /* population count */
- FAC_SCF, /* store clock fast */
- FAC_SFLE, /* store facility list extended */
- FAC_ILA, /* interlocked access facility 1 */
-} DisasFacility;
-
-struct DisasInsn {
- unsigned opc:16;
- DisasFormat fmt:8;
- DisasFacility fac:8;
- unsigned spec:8;
-
- const char *name;
-
- void (*help_in1)(DisasContext *, DisasFields *, DisasOps *);
- void (*help_in2)(DisasContext *, DisasFields *, DisasOps *);
- void (*help_prep)(DisasContext *, DisasFields *, DisasOps *);
- void (*help_wout)(DisasContext *, DisasFields *, DisasOps *);
- void (*help_cout)(DisasContext *, DisasOps *);
- ExitStatus (*help_op)(DisasContext *, DisasOps *);
-
- uint64_t data;
-};
-
-/* ====================================================================== */
-/* Miscellaneous helpers, used by several operations. */
-
-static void help_l2_shift(DisasContext *s, DisasFields *f,
- DisasOps *o, int mask)
-{
- int b2 = get_field(f, b2);
- int d2 = get_field(f, d2);
-
- if (b2 == 0) {
- o->in2 = tcg_const_i64(d2 & mask);
- } else {
- o->in2 = get_address(s, 0, b2, d2);
- tcg_gen_andi_i64(o->in2, o->in2, mask);
- }
-}
-
-static ExitStatus help_goto_direct(DisasContext *s, uint64_t dest)
-{
- if (dest == s->next_pc) {
- per_branch(s, true);
- return NO_EXIT;
- }
- if (use_goto_tb(s, dest)) {
- update_cc_op(s);
- per_breaking_event(s);
- tcg_gen_goto_tb(0);
- tcg_gen_movi_i64(psw_addr, dest);
- tcg_gen_exit_tb((uintptr_t)s->tb);
- return EXIT_GOTO_TB;
- } else {
- tcg_gen_movi_i64(psw_addr, dest);
- per_branch(s, false);
- return EXIT_PC_UPDATED;
- }
-}
-
-static ExitStatus help_branch(DisasContext *s, DisasCompare *c,
- bool is_imm, int imm, TCGv_i64 cdest)
-{
- ExitStatus ret;
- uint64_t dest = s->pc + 2 * imm;
- TCGLabel *lab;
-
- /* Take care of the special cases first. */
- if (c->cond == TCG_COND_NEVER) {
- ret = NO_EXIT;
- goto egress;
- }
- if (is_imm) {
- if (dest == s->next_pc) {
- /* Branch to next. */
- per_branch(s, true);
- ret = NO_EXIT;
- goto egress;
- }
- if (c->cond == TCG_COND_ALWAYS) {
- ret = help_goto_direct(s, dest);
- goto egress;
- }
- } else {
- if (TCGV_IS_UNUSED_I64(cdest)) {
- /* E.g. bcr %r0 -> no branch. */
- ret = NO_EXIT;
- goto egress;
- }
- if (c->cond == TCG_COND_ALWAYS) {
- tcg_gen_mov_i64(psw_addr, cdest);
- per_branch(s, false);
- ret = EXIT_PC_UPDATED;
- goto egress;
- }
- }
-
- if (use_goto_tb(s, s->next_pc)) {
- if (is_imm && use_goto_tb(s, dest)) {
- /* Both exits can use goto_tb. */
- update_cc_op(s);
-
- lab = gen_new_label();
- if (c->is_64) {
- tcg_gen_brcond_i64(c->cond, c->u.s64.a, c->u.s64.b, lab);
- } else {
- tcg_gen_brcond_i32(c->cond, c->u.s32.a, c->u.s32.b, lab);
- }
-
- /* Branch not taken. */
- tcg_gen_goto_tb(0);
- tcg_gen_movi_i64(psw_addr, s->next_pc);
- tcg_gen_exit_tb((uintptr_t)s->tb + 0);
-
- /* Branch taken. */
- gen_set_label(lab);
- per_breaking_event(s);
- tcg_gen_goto_tb(1);
- tcg_gen_movi_i64(psw_addr, dest);
- tcg_gen_exit_tb((uintptr_t)s->tb + 1);
-
- ret = EXIT_GOTO_TB;
- } else {
- /* Fallthru can use goto_tb, but taken branch cannot. */
- /* Store taken branch destination before the brcond. This
- avoids having to allocate a new local temp to hold it.
- We'll overwrite this in the not taken case anyway. */
- if (!is_imm) {
- tcg_gen_mov_i64(psw_addr, cdest);
- }
-
- lab = gen_new_label();
- if (c->is_64) {
- tcg_gen_brcond_i64(c->cond, c->u.s64.a, c->u.s64.b, lab);
- } else {
- tcg_gen_brcond_i32(c->cond, c->u.s32.a, c->u.s32.b, lab);
- }
-
- /* Branch not taken. */
- update_cc_op(s);
- tcg_gen_goto_tb(0);
- tcg_gen_movi_i64(psw_addr, s->next_pc);
- tcg_gen_exit_tb((uintptr_t)s->tb + 0);
-
- gen_set_label(lab);
- if (is_imm) {
- tcg_gen_movi_i64(psw_addr, dest);
- }
- per_breaking_event(s);
- ret = EXIT_PC_UPDATED;
- }
- } else {
- /* Fallthru cannot use goto_tb. This by itself is vanishingly rare.
- Most commonly we're single-stepping or some other condition that
- disables all use of goto_tb. Just update the PC and exit. */
-
- TCGv_i64 next = tcg_const_i64(s->next_pc);
- if (is_imm) {
- cdest = tcg_const_i64(dest);
- }
-
- if (c->is_64) {
- tcg_gen_movcond_i64(c->cond, psw_addr, c->u.s64.a, c->u.s64.b,
- cdest, next);
- per_branch_cond(s, c->cond, c->u.s64.a, c->u.s64.b);
- } else {
- TCGv_i32 t0 = tcg_temp_new_i32();
- TCGv_i64 t1 = tcg_temp_new_i64();
- TCGv_i64 z = tcg_const_i64(0);
- tcg_gen_setcond_i32(c->cond, t0, c->u.s32.a, c->u.s32.b);
- tcg_gen_extu_i32_i64(t1, t0);
- tcg_temp_free_i32(t0);
- tcg_gen_movcond_i64(TCG_COND_NE, psw_addr, t1, z, cdest, next);
- per_branch_cond(s, TCG_COND_NE, t1, z);
- tcg_temp_free_i64(t1);
- tcg_temp_free_i64(z);
- }
-
- if (is_imm) {
- tcg_temp_free_i64(cdest);
- }
- tcg_temp_free_i64(next);
-
- ret = EXIT_PC_UPDATED;
- }
-
- egress:
- free_compare(c);
- return ret;
-}
-
-/* ====================================================================== */
-/* The operations. These perform the bulk of the work for any insn,
- usually after the operands have been loaded and output initialized. */
-
-static ExitStatus op_abs(DisasContext *s, DisasOps *o)
-{
- TCGv_i64 z, n;
- z = tcg_const_i64(0);
- n = tcg_temp_new_i64();
- tcg_gen_neg_i64(n, o->in2);
- tcg_gen_movcond_i64(TCG_COND_LT, o->out, o->in2, z, n, o->in2);
- tcg_temp_free_i64(n);
- tcg_temp_free_i64(z);
- return NO_EXIT;
-}
-
-static ExitStatus op_absf32(DisasContext *s, DisasOps *o)
-{
- tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffull);
- return NO_EXIT;
-}
-
-static ExitStatus op_absf64(DisasContext *s, DisasOps *o)
-{
- tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffffffffffull);
- return NO_EXIT;
-}
-
-static ExitStatus op_absf128(DisasContext *s, DisasOps *o)
-{
- tcg_gen_andi_i64(o->out, o->in1, 0x7fffffffffffffffull);
- tcg_gen_mov_i64(o->out2, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_add(DisasContext *s, DisasOps *o)
-{
- tcg_gen_add_i64(o->out, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_addc(DisasContext *s, DisasOps *o)
-{
- DisasCompare cmp;
- TCGv_i64 carry;
-
- tcg_gen_add_i64(o->out, o->in1, o->in2);
-
- /* The carry flag is the msb of CC, therefore the branch mask that would
- create that comparison is 3. Feeding the generated comparison to
- setcond produces the carry flag that we desire. */
- disas_jcc(s, &cmp, 3);
- carry = tcg_temp_new_i64();
- if (cmp.is_64) {
- tcg_gen_setcond_i64(cmp.cond, carry, cmp.u.s64.a, cmp.u.s64.b);
- } else {
- TCGv_i32 t = tcg_temp_new_i32();
- tcg_gen_setcond_i32(cmp.cond, t, cmp.u.s32.a, cmp.u.s32.b);
- tcg_gen_extu_i32_i64(carry, t);
- tcg_temp_free_i32(t);
- }
- free_compare(&cmp);
-
- tcg_gen_add_i64(o->out, o->out, carry);
- tcg_temp_free_i64(carry);
- return NO_EXIT;
-}
-
-static ExitStatus op_aeb(DisasContext *s, DisasOps *o)
-{
- gen_helper_aeb(o->out, cpu_env, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_adb(DisasContext *s, DisasOps *o)
-{
- gen_helper_adb(o->out, cpu_env, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_axb(DisasContext *s, DisasOps *o)
-{
- gen_helper_axb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
- return_low128(o->out2);
- return NO_EXIT;
-}
-
-static ExitStatus op_and(DisasContext *s, DisasOps *o)
-{
- tcg_gen_and_i64(o->out, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_andi(DisasContext *s, DisasOps *o)
-{
- int shift = s->insn->data & 0xff;
- int size = s->insn->data >> 8;
- uint64_t mask = ((1ull << size) - 1) << shift;
-
- assert(!o->g_in2);
- tcg_gen_shli_i64(o->in2, o->in2, shift);
- tcg_gen_ori_i64(o->in2, o->in2, ~mask);
- tcg_gen_and_i64(o->out, o->in1, o->in2);
-
- /* Produce the CC from only the bits manipulated. */
- tcg_gen_andi_i64(cc_dst, o->out, mask);
- set_cc_nz_u64(s, cc_dst);
- return NO_EXIT;
-}
-
-static ExitStatus op_bas(DisasContext *s, DisasOps *o)
-{
- tcg_gen_movi_i64(o->out, pc_to_link_info(s, s->next_pc));
- if (!TCGV_IS_UNUSED_I64(o->in2)) {
- tcg_gen_mov_i64(psw_addr, o->in2);
- per_branch(s, false);
- return EXIT_PC_UPDATED;
- } else {
- return NO_EXIT;
- }
-}
-
-static ExitStatus op_basi(DisasContext *s, DisasOps *o)
-{
- tcg_gen_movi_i64(o->out, pc_to_link_info(s, s->next_pc));
- return help_goto_direct(s, s->pc + 2 * get_field(s->fields, i2));
-}
-
-static ExitStatus op_bc(DisasContext *s, DisasOps *o)
-{
- int m1 = get_field(s->fields, m1);
- bool is_imm = have_field(s->fields, i2);
- int imm = is_imm ? get_field(s->fields, i2) : 0;
- DisasCompare c;
-
- disas_jcc(s, &c, m1);
- return help_branch(s, &c, is_imm, imm, o->in2);
-}
-
-static ExitStatus op_bct32(DisasContext *s, DisasOps *o)
-{
- int r1 = get_field(s->fields, r1);
- bool is_imm = have_field(s->fields, i2);
- int imm = is_imm ? get_field(s->fields, i2) : 0;
- DisasCompare c;
- TCGv_i64 t;
-
- c.cond = TCG_COND_NE;
- c.is_64 = false;
- c.g1 = false;
- c.g2 = false;
-
- t = tcg_temp_new_i64();
- tcg_gen_subi_i64(t, regs[r1], 1);
- store_reg32_i64(r1, t);
- c.u.s32.a = tcg_temp_new_i32();
- c.u.s32.b = tcg_const_i32(0);
- tcg_gen_extrl_i64_i32(c.u.s32.a, t);
- tcg_temp_free_i64(t);
-
- return help_branch(s, &c, is_imm, imm, o->in2);
-}
-
-static ExitStatus op_bcth(DisasContext *s, DisasOps *o)
-{
- int r1 = get_field(s->fields, r1);
- int imm = get_field(s->fields, i2);
- DisasCompare c;
- TCGv_i64 t;
-
- c.cond = TCG_COND_NE;
- c.is_64 = false;
- c.g1 = false;
- c.g2 = false;
-
- t = tcg_temp_new_i64();
- tcg_gen_shri_i64(t, regs[r1], 32);
- tcg_gen_subi_i64(t, t, 1);
- store_reg32h_i64(r1, t);
- c.u.s32.a = tcg_temp_new_i32();
- c.u.s32.b = tcg_const_i32(0);
- tcg_gen_extrl_i64_i32(c.u.s32.a, t);
- tcg_temp_free_i64(t);
-
- return help_branch(s, &c, 1, imm, o->in2);
-}
-
-static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
-{
- int r1 = get_field(s->fields, r1);
- bool is_imm = have_field(s->fields, i2);
- int imm = is_imm ? get_field(s->fields, i2) : 0;
- DisasCompare c;
-
- c.cond = TCG_COND_NE;
- c.is_64 = true;
- c.g1 = true;
- c.g2 = false;
-
- tcg_gen_subi_i64(regs[r1], regs[r1], 1);
- c.u.s64.a = regs[r1];
- c.u.s64.b = tcg_const_i64(0);
-
- return help_branch(s, &c, is_imm, imm, o->in2);
-}
-
-static ExitStatus op_bx32(DisasContext *s, DisasOps *o)
-{
- int r1 = get_field(s->fields, r1);
- int r3 = get_field(s->fields, r3);
- bool is_imm = have_field(s->fields, i2);
- int imm = is_imm ? get_field(s->fields, i2) : 0;
- DisasCompare c;
- TCGv_i64 t;
-
- c.cond = (s->insn->data ? TCG_COND_LE : TCG_COND_GT);
- c.is_64 = false;
- c.g1 = false;
- c.g2 = false;
-
- t = tcg_temp_new_i64();
- tcg_gen_add_i64(t, regs[r1], regs[r3]);
- c.u.s32.a = tcg_temp_new_i32();
- c.u.s32.b = tcg_temp_new_i32();
- tcg_gen_extrl_i64_i32(c.u.s32.a, t);
- tcg_gen_extrl_i64_i32(c.u.s32.b, regs[r3 | 1]);
- store_reg32_i64(r1, t);
- tcg_temp_free_i64(t);
-
- return help_branch(s, &c, is_imm, imm, o->in2);
-}
-
-static ExitStatus op_bx64(DisasContext *s, DisasOps *o)
-{
- int r1 = get_field(s->fields, r1);
- int r3 = get_field(s->fields, r3);
- bool is_imm = have_field(s->fields, i2);
- int imm = is_imm ? get_field(s->fields, i2) : 0;
- DisasCompare c;
-
- c.cond = (s->insn->data ? TCG_COND_LE : TCG_COND_GT);
- c.is_64 = true;
-
- if (r1 == (r3 | 1)) {
- c.u.s64.b = load_reg(r3 | 1);
- c.g2 = false;
- } else {
- c.u.s64.b = regs[r3 | 1];
- c.g2 = true;
- }
-
- tcg_gen_add_i64(regs[r1], regs[r1], regs[r3]);
- c.u.s64.a = regs[r1];
- c.g1 = true;
-
- return help_branch(s, &c, is_imm, imm, o->in2);
-}
-
-static ExitStatus op_cj(DisasContext *s, DisasOps *o)
-{
- int imm, m3 = get_field(s->fields, m3);
- bool is_imm;
- DisasCompare c;
-
- c.cond = ltgt_cond[m3];
- if (s->insn->data) {
- c.cond = tcg_unsigned_cond(c.cond);
- }
- c.is_64 = c.g1 = c.g2 = true;
- c.u.s64.a = o->in1;
- c.u.s64.b = o->in2;
-
- is_imm = have_field(s->fields, i4);
- if (is_imm) {
- imm = get_field(s->fields, i4);
- } else {
- imm = 0;
- o->out = get_address(s, 0, get_field(s->fields, b4),
- get_field(s->fields, d4));
- }
-
- return help_branch(s, &c, is_imm, imm, o->out);
-}
-
-static ExitStatus op_ceb(DisasContext *s, DisasOps *o)
-{
- gen_helper_ceb(cc_op, cpu_env, o->in1, o->in2);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_cdb(DisasContext *s, DisasOps *o)
-{
- gen_helper_cdb(cc_op, cpu_env, o->in1, o->in2);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_cxb(DisasContext *s, DisasOps *o)
-{
- gen_helper_cxb(cc_op, cpu_env, o->out, o->out2, o->in1, o->in2);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_cfeb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cfeb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
- gen_set_cc_nz_f32(s, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_cfdb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cfdb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
- gen_set_cc_nz_f64(s, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_cfxb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cfxb(o->out, cpu_env, o->in1, o->in2, m3);
- tcg_temp_free_i32(m3);
- gen_set_cc_nz_f128(s, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_cgeb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cgeb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
- gen_set_cc_nz_f32(s, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_cgdb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cgdb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
- gen_set_cc_nz_f64(s, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_cgxb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cgxb(o->out, cpu_env, o->in1, o->in2, m3);
- tcg_temp_free_i32(m3);
- gen_set_cc_nz_f128(s, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_clfeb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clfeb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
- gen_set_cc_nz_f32(s, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_clfdb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clfdb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
- gen_set_cc_nz_f64(s, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_clfxb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clfxb(o->out, cpu_env, o->in1, o->in2, m3);
- tcg_temp_free_i32(m3);
- gen_set_cc_nz_f128(s, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_clgeb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clgeb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
- gen_set_cc_nz_f32(s, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_clgdb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clgdb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
- gen_set_cc_nz_f64(s, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_clgxb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_clgxb(o->out, cpu_env, o->in1, o->in2, m3);
- tcg_temp_free_i32(m3);
- gen_set_cc_nz_f128(s, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_cegb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cegb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
- return NO_EXIT;
-}
-
-static ExitStatus op_cdgb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cdgb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
- return NO_EXIT;
-}
-
-static ExitStatus op_cxgb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cxgb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
- return_low128(o->out2);
- return NO_EXIT;
-}
-
-static ExitStatus op_celgb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_celgb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
- return NO_EXIT;
-}
-
-static ExitStatus op_cdlgb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cdlgb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
- return NO_EXIT;
-}
-
-static ExitStatus op_cxlgb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_cxlgb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
- return_low128(o->out2);
- return NO_EXIT;
-}
-
-static ExitStatus op_cksm(DisasContext *s, DisasOps *o)
-{
- int r2 = get_field(s->fields, r2);
- TCGv_i64 len = tcg_temp_new_i64();
-
- potential_page_fault(s);
- gen_helper_cksm(len, cpu_env, o->in1, o->in2, regs[r2 + 1]);
- set_cc_static(s);
- return_low128(o->out);
-
- tcg_gen_add_i64(regs[r2], regs[r2], len);
- tcg_gen_sub_i64(regs[r2 + 1], regs[r2 + 1], len);
- tcg_temp_free_i64(len);
-
- return NO_EXIT;
-}
-
-static ExitStatus op_clc(DisasContext *s, DisasOps *o)
-{
- int l = get_field(s->fields, l1);
- TCGv_i32 vl;
-
- switch (l + 1) {
- case 1:
- tcg_gen_qemu_ld8u(cc_src, o->addr1, get_mem_index(s));
- tcg_gen_qemu_ld8u(cc_dst, o->in2, get_mem_index(s));
- break;
- case 2:
- tcg_gen_qemu_ld16u(cc_src, o->addr1, get_mem_index(s));
- tcg_gen_qemu_ld16u(cc_dst, o->in2, get_mem_index(s));
- break;
- case 4:
- tcg_gen_qemu_ld32u(cc_src, o->addr1, get_mem_index(s));
- tcg_gen_qemu_ld32u(cc_dst, o->in2, get_mem_index(s));
- break;
- case 8:
- tcg_gen_qemu_ld64(cc_src, o->addr1, get_mem_index(s));
- tcg_gen_qemu_ld64(cc_dst, o->in2, get_mem_index(s));
- break;
- default:
- potential_page_fault(s);
- vl = tcg_const_i32(l);
- gen_helper_clc(cc_op, cpu_env, vl, o->addr1, o->in2);
- tcg_temp_free_i32(vl);
- set_cc_static(s);
- return NO_EXIT;
- }
- gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, cc_src, cc_dst);
- return NO_EXIT;
-}
-
-static ExitStatus op_clcle(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));
- potential_page_fault(s);
- gen_helper_clcle(cc_op, cpu_env, r1, o->in2, r3);
- tcg_temp_free_i32(r1);
- tcg_temp_free_i32(r3);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_clm(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- TCGv_i32 t1 = tcg_temp_new_i32();
- tcg_gen_extrl_i64_i32(t1, o->in1);
- potential_page_fault(s);
- gen_helper_clm(cc_op, cpu_env, t1, m3, o->in2);
- set_cc_static(s);
- tcg_temp_free_i32(t1);
- tcg_temp_free_i32(m3);
- return NO_EXIT;
-}
-
-static ExitStatus op_clst(DisasContext *s, DisasOps *o)
-{
- potential_page_fault(s);
- gen_helper_clst(o->in1, cpu_env, regs[0], o->in1, o->in2);
- set_cc_static(s);
- return_low128(o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_cps(DisasContext *s, DisasOps *o)
-{
- TCGv_i64 t = tcg_temp_new_i64();
- tcg_gen_andi_i64(t, o->in1, 0x8000000000000000ull);
- tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffffffffffull);
- tcg_gen_or_i64(o->out, o->out, t);
- tcg_temp_free_i64(t);
- return NO_EXIT;
-}
-
-static ExitStatus op_cs(DisasContext *s, DisasOps *o)
-{
- /* FIXME: needs an atomic solution for CONFIG_USER_ONLY. */
- int d2 = get_field(s->fields, d2);
- int b2 = get_field(s->fields, b2);
- int is_64 = s->insn->data;
- TCGv_i64 addr, mem, cc, z;
-
- /* Note that in1 = R3 (new value) and
- in2 = (zero-extended) R1 (expected value). */
-
- /* Load the memory into the (temporary) output. While the PoO only talks
- about moving the memory to R1 on inequality, if we include equality it
- means that R1 is equal to the memory in all conditions. */
- addr = get_address(s, 0, b2, d2);
- if (is_64) {
- tcg_gen_qemu_ld64(o->out, addr, get_mem_index(s));
- } else {
- tcg_gen_qemu_ld32u(o->out, addr, get_mem_index(s));
- }
-
- /* Are the memory and expected values (un)equal? Note that this setcond
- produces the output CC value, thus the NE sense of the test. */
- cc = tcg_temp_new_i64();
- tcg_gen_setcond_i64(TCG_COND_NE, cc, o->in2, o->out);
-
- /* If the memory and expected values are equal (CC==0), copy R3 to MEM.
- Recall that we are allowed to unconditionally issue the store (and
- thus any possible write trap), so (re-)store the original contents
- of MEM in case of inequality. */
- z = tcg_const_i64(0);
- mem = tcg_temp_new_i64();
- tcg_gen_movcond_i64(TCG_COND_EQ, mem, cc, z, o->in1, o->out);
- if (is_64) {
- tcg_gen_qemu_st64(mem, addr, get_mem_index(s));
- } else {
- tcg_gen_qemu_st32(mem, addr, get_mem_index(s));
- }
- tcg_temp_free_i64(z);
- tcg_temp_free_i64(mem);
- tcg_temp_free_i64(addr);
-
- /* Store CC back to cc_op. Wait until after the store so that any
- exception gets the old cc_op value. */
- tcg_gen_extrl_i64_i32(cc_op, cc);
- tcg_temp_free_i64(cc);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_cdsg(DisasContext *s, DisasOps *o)
-{
- /* FIXME: needs an atomic solution for CONFIG_USER_ONLY. */
- int r1 = get_field(s->fields, r1);
- int r3 = get_field(s->fields, r3);
- int d2 = get_field(s->fields, d2);
- int b2 = get_field(s->fields, b2);
- TCGv_i64 addrh, addrl, memh, meml, outh, outl, cc, z;
-
- /* Note that R1:R1+1 = expected value and R3:R3+1 = new value. */
-
- addrh = get_address(s, 0, b2, d2);
- addrl = get_address(s, 0, b2, d2 + 8);
- outh = tcg_temp_new_i64();
- outl = tcg_temp_new_i64();
-
- tcg_gen_qemu_ld64(outh, addrh, get_mem_index(s));
- tcg_gen_qemu_ld64(outl, addrl, get_mem_index(s));
-
- /* Fold the double-word compare with arithmetic. */
- cc = tcg_temp_new_i64();
- z = tcg_temp_new_i64();
- tcg_gen_xor_i64(cc, outh, regs[r1]);
- tcg_gen_xor_i64(z, outl, regs[r1 + 1]);
- tcg_gen_or_i64(cc, cc, z);
- tcg_gen_movi_i64(z, 0);
- tcg_gen_setcond_i64(TCG_COND_NE, cc, cc, z);
-
- memh = tcg_temp_new_i64();
- meml = tcg_temp_new_i64();
- tcg_gen_movcond_i64(TCG_COND_EQ, memh, cc, z, regs[r3], outh);
- tcg_gen_movcond_i64(TCG_COND_EQ, meml, cc, z, regs[r3 + 1], outl);
- tcg_temp_free_i64(z);
-
- tcg_gen_qemu_st64(memh, addrh, get_mem_index(s));
- tcg_gen_qemu_st64(meml, addrl, get_mem_index(s));
- tcg_temp_free_i64(memh);
- tcg_temp_free_i64(meml);
- tcg_temp_free_i64(addrh);
- tcg_temp_free_i64(addrl);
-
- /* Save back state now that we've passed all exceptions. */
- tcg_gen_mov_i64(regs[r1], outh);
- tcg_gen_mov_i64(regs[r1 + 1], outl);
- tcg_gen_extrl_i64_i32(cc_op, cc);
- tcg_temp_free_i64(outh);
- tcg_temp_free_i64(outl);
- tcg_temp_free_i64(cc);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-#ifndef CONFIG_USER_ONLY
-static ExitStatus op_csp(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
- check_privileged(s);
- gen_helper_csp(cc_op, cpu_env, r1, o->in2);
- tcg_temp_free_i32(r1);
- set_cc_static(s);
- return NO_EXIT;
-}
-#endif
-
-static ExitStatus op_cvd(DisasContext *s, DisasOps *o)
-{
- TCGv_i64 t1 = tcg_temp_new_i64();
- TCGv_i32 t2 = tcg_temp_new_i32();
- tcg_gen_extrl_i64_i32(t2, o->in1);
- gen_helper_cvd(t1, t2);
- tcg_temp_free_i32(t2);
- tcg_gen_qemu_st64(t1, o->in2, get_mem_index(s));
- tcg_temp_free_i64(t1);
- return NO_EXIT;
-}
-
-static ExitStatus op_ct(DisasContext *s, DisasOps *o)
-{
- int m3 = get_field(s->fields, m3);
- TCGLabel *lab = gen_new_label();
- TCGCond c;
-
- c = tcg_invert_cond(ltgt_cond[m3]);
- if (s->insn->data) {
- c = tcg_unsigned_cond(c);
- }
- tcg_gen_brcond_i64(c, o->in1, o->in2, lab);
-
- /* Trap. */
- gen_trap(s);
-
- gen_set_label(lab);
- return NO_EXIT;
-}
-
-#ifndef CONFIG_USER_ONLY
-static ExitStatus op_diag(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));
- TCGv_i32 func_code = tcg_const_i32(get_field(s->fields, i2));
-
- check_privileged(s);
- update_psw_addr(s);
- gen_op_calc_cc(s);
-
- gen_helper_diag(cpu_env, r1, r3, func_code);
-
- tcg_temp_free_i32(func_code);
- tcg_temp_free_i32(r3);
- tcg_temp_free_i32(r1);
- return NO_EXIT;
-}
-#endif
-
-static ExitStatus op_divs32(DisasContext *s, DisasOps *o)
-{
- gen_helper_divs32(o->out2, cpu_env, o->in1, o->in2);
- return_low128(o->out);
- return NO_EXIT;
-}
-
-static ExitStatus op_divu32(DisasContext *s, DisasOps *o)
-{
- gen_helper_divu32(o->out2, cpu_env, o->in1, o->in2);
- return_low128(o->out);
- return NO_EXIT;
-}
-
-static ExitStatus op_divs64(DisasContext *s, DisasOps *o)
-{
- gen_helper_divs64(o->out2, cpu_env, o->in1, o->in2);
- return_low128(o->out);
- return NO_EXIT;
-}
-
-static ExitStatus op_divu64(DisasContext *s, DisasOps *o)
-{
- gen_helper_divu64(o->out2, cpu_env, o->out, o->out2, o->in2);
- return_low128(o->out);
- return NO_EXIT;
-}
-
-static ExitStatus op_deb(DisasContext *s, DisasOps *o)
-{
- gen_helper_deb(o->out, cpu_env, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_ddb(DisasContext *s, DisasOps *o)
-{
- gen_helper_ddb(o->out, cpu_env, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_dxb(DisasContext *s, DisasOps *o)
-{
- gen_helper_dxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
- return_low128(o->out2);
- return NO_EXIT;
-}
-
-static ExitStatus op_ear(DisasContext *s, DisasOps *o)
-{
- int r2 = get_field(s->fields, r2);
- tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, aregs[r2]));
- return NO_EXIT;
-}
-
-static ExitStatus op_ecag(DisasContext *s, DisasOps *o)
-{
- /* No cache information provided. */
- tcg_gen_movi_i64(o->out, -1);
- return NO_EXIT;
-}
-
-static ExitStatus op_efpc(DisasContext *s, DisasOps *o)
-{
- tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, fpc));
- return NO_EXIT;
-}
-
-static ExitStatus op_epsw(DisasContext *s, DisasOps *o)
-{
- int r1 = get_field(s->fields, r1);
- int r2 = get_field(s->fields, r2);
- TCGv_i64 t = tcg_temp_new_i64();
-
- /* Note the "subsequently" in the PoO, which implies a defined result
- if r1 == r2. Thus we cannot defer these writes to an output hook. */
- tcg_gen_shri_i64(t, psw_mask, 32);
- store_reg32_i64(r1, t);
- if (r2 != 0) {
- store_reg32_i64(r2, psw_mask);
- }
-
- tcg_temp_free_i64(t);
- return NO_EXIT;
-}
-
-static ExitStatus op_ex(DisasContext *s, DisasOps *o)
-{
- /* ??? Perhaps a better way to implement EXECUTE is to set a bit in
- tb->flags, (ab)use the tb->cs_base field as the address of
- the template in memory, and grab 8 bits of tb->flags/cflags for
- the contents of the register. We would then recognize all this
- in gen_intermediate_code_internal, generating code for exactly
- one instruction. This new TB then gets executed normally.
-
- On the other hand, this seems to be mostly used for modifying
- MVC inside of memcpy, which needs a helper call anyway. So
- perhaps this doesn't bear thinking about any further. */
-
- TCGv_i64 tmp;
-
- update_psw_addr(s);
- gen_op_calc_cc(s);
-
- tmp = tcg_const_i64(s->next_pc);
- gen_helper_ex(cc_op, cpu_env, cc_op, o->in1, o->in2, tmp);
- tcg_temp_free_i64(tmp);
-
- return NO_EXIT;
-}
-
-static ExitStatus op_fieb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_fieb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
- return NO_EXIT;
-}
-
-static ExitStatus op_fidb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_fidb(o->out, cpu_env, o->in2, m3);
- tcg_temp_free_i32(m3);
- return NO_EXIT;
-}
-
-static ExitStatus op_fixb(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
- gen_helper_fixb(o->out, cpu_env, o->in1, o->in2, m3);
- return_low128(o->out2);
- tcg_temp_free_i32(m3);
- return NO_EXIT;
-}
-
-static ExitStatus op_flogr(DisasContext *s, DisasOps *o)
-{
- /* We'll use the original input for cc computation, since we get to
- compare that against 0, which ought to be better than comparing
- the real output against 64. It also lets cc_dst be a convenient
- temporary during our computation. */
- gen_op_update1_cc_i64(s, CC_OP_FLOGR, o->in2);
-
- /* R1 = IN ? CLZ(IN) : 64. */
- gen_helper_clz(o->out, o->in2);
-
- /* R1+1 = IN & ~(found bit). Note that we may attempt to shift this
- value by 64, which is undefined. But since the shift is 64 iff the
- input is zero, we still get the correct result after and'ing. */
- tcg_gen_movi_i64(o->out2, 0x8000000000000000ull);
- tcg_gen_shr_i64(o->out2, o->out2, o->out);
- tcg_gen_andc_i64(o->out2, cc_dst, o->out2);
- return NO_EXIT;
-}
-
-static ExitStatus op_icm(DisasContext *s, DisasOps *o)
-{
- int m3 = get_field(s->fields, m3);
- int pos, len, base = s->insn->data;
- TCGv_i64 tmp = tcg_temp_new_i64();
- uint64_t ccm;
-
- switch (m3) {
- case 0xf:
- /* Effectively a 32-bit load. */
- tcg_gen_qemu_ld32u(tmp, o->in2, get_mem_index(s));
- len = 32;
- goto one_insert;
-
- case 0xc:
- case 0x6:
- case 0x3:
- /* Effectively a 16-bit load. */
- tcg_gen_qemu_ld16u(tmp, o->in2, get_mem_index(s));
- len = 16;
- goto one_insert;
-
- case 0x8:
- case 0x4:
- case 0x2:
- case 0x1:
- /* Effectively an 8-bit load. */
- tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s));
- len = 8;
- goto one_insert;
-
- one_insert:
- pos = base + ctz32(m3) * 8;
- tcg_gen_deposit_i64(o->out, o->out, tmp, pos, len);
- ccm = ((1ull << len) - 1) << pos;
- break;
-
- default:
- /* This is going to be a sequence of loads and inserts. */
- pos = base + 32 - 8;
- ccm = 0;
- while (m3) {
- if (m3 & 0x8) {
- tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s));
- tcg_gen_addi_i64(o->in2, o->in2, 1);
- tcg_gen_deposit_i64(o->out, o->out, tmp, pos, 8);
- ccm |= 0xff << pos;
- }
- m3 = (m3 << 1) & 0xf;
- pos -= 8;
- }
- break;
- }
-
- tcg_gen_movi_i64(tmp, ccm);
- gen_op_update2_cc_i64(s, CC_OP_ICM, tmp, o->out);
- tcg_temp_free_i64(tmp);
- return NO_EXIT;
-}
-
-static ExitStatus op_insi(DisasContext *s, DisasOps *o)
-{
- int shift = s->insn->data & 0xff;
- int size = s->insn->data >> 8;
- tcg_gen_deposit_i64(o->out, o->in1, o->in2, shift, size);
- return NO_EXIT;
-}
-
-static ExitStatus op_ipm(DisasContext *s, DisasOps *o)
-{
- TCGv_i64 t1;
-
- gen_op_calc_cc(s);
- tcg_gen_andi_i64(o->out, o->out, ~0xff000000ull);
-
- t1 = tcg_temp_new_i64();
- tcg_gen_shli_i64(t1, psw_mask, 20);
- tcg_gen_shri_i64(t1, t1, 36);
- tcg_gen_or_i64(o->out, o->out, t1);
-
- tcg_gen_extu_i32_i64(t1, cc_op);
- tcg_gen_shli_i64(t1, t1, 28);
- tcg_gen_or_i64(o->out, o->out, t1);
- tcg_temp_free_i64(t1);
- return NO_EXIT;
-}
-
-#ifndef CONFIG_USER_ONLY
-static ExitStatus op_ipte(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- gen_helper_ipte(cpu_env, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_iske(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- gen_helper_iske(o->out, cpu_env, o->in2);
- return NO_EXIT;
-}
-#endif
-
-static ExitStatus op_ldeb(DisasContext *s, DisasOps *o)
-{
- gen_helper_ldeb(o->out, cpu_env, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_ledb(DisasContext *s, DisasOps *o)
-{
- gen_helper_ledb(o->out, cpu_env, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_ldxb(DisasContext *s, DisasOps *o)
-{
- gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_lexb(DisasContext *s, DisasOps *o)
-{
- gen_helper_lexb(o->out, cpu_env, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_lxdb(DisasContext *s, DisasOps *o)
-{
- gen_helper_lxdb(o->out, cpu_env, o->in2);
- return_low128(o->out2);
- return NO_EXIT;
-}
-
-static ExitStatus op_lxeb(DisasContext *s, DisasOps *o)
-{
- gen_helper_lxeb(o->out, cpu_env, o->in2);
- return_low128(o->out2);
- return NO_EXIT;
-}
-
-static ExitStatus op_llgt(DisasContext *s, DisasOps *o)
-{
- tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff);
- return NO_EXIT;
-}
-
-static ExitStatus op_ld8s(DisasContext *s, DisasOps *o)
-{
- tcg_gen_qemu_ld8s(o->out, o->in2, get_mem_index(s));
- return NO_EXIT;
-}
-
-static ExitStatus op_ld8u(DisasContext *s, DisasOps *o)
-{
- tcg_gen_qemu_ld8u(o->out, o->in2, get_mem_index(s));
- return NO_EXIT;
-}
-
-static ExitStatus op_ld16s(DisasContext *s, DisasOps *o)
-{
- tcg_gen_qemu_ld16s(o->out, o->in2, get_mem_index(s));
- return NO_EXIT;
-}
-
-static ExitStatus op_ld16u(DisasContext *s, DisasOps *o)
-{
- tcg_gen_qemu_ld16u(o->out, o->in2, get_mem_index(s));
- return NO_EXIT;
-}
-
-static ExitStatus op_ld32s(DisasContext *s, DisasOps *o)
-{
- tcg_gen_qemu_ld32s(o->out, o->in2, get_mem_index(s));
- return NO_EXIT;
-}
-
-static ExitStatus op_ld32u(DisasContext *s, DisasOps *o)
-{
- tcg_gen_qemu_ld32u(o->out, o->in2, get_mem_index(s));
- return NO_EXIT;
-}
-
-static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
-{
- tcg_gen_qemu_ld64(o->out, o->in2, get_mem_index(s));
- return NO_EXIT;
-}
-
-static ExitStatus op_lat(DisasContext *s, DisasOps *o)
-{
- TCGLabel *lab = gen_new_label();
- store_reg32_i64(get_field(s->fields, r1), o->in2);
- /* The value is stored even in case of trap. */
- tcg_gen_brcondi_i64(TCG_COND_NE, o->in2, 0, lab);
- gen_trap(s);
- gen_set_label(lab);
- return NO_EXIT;
-}
-
-static ExitStatus op_lgat(DisasContext *s, DisasOps *o)
-{
- TCGLabel *lab = gen_new_label();
- tcg_gen_qemu_ld64(o->out, o->in2, get_mem_index(s));
- /* The value is stored even in case of trap. */
- tcg_gen_brcondi_i64(TCG_COND_NE, o->out, 0, lab);
- gen_trap(s);
- gen_set_label(lab);
- return NO_EXIT;
-}
-
-static ExitStatus op_lfhat(DisasContext *s, DisasOps *o)
-{
- TCGLabel *lab = gen_new_label();
- store_reg32h_i64(get_field(s->fields, r1), o->in2);
- /* The value is stored even in case of trap. */
- tcg_gen_brcondi_i64(TCG_COND_NE, o->in2, 0, lab);
- gen_trap(s);
- gen_set_label(lab);
- return NO_EXIT;
-}
-
-static ExitStatus op_llgfat(DisasContext *s, DisasOps *o)
-{
- TCGLabel *lab = gen_new_label();
- tcg_gen_qemu_ld32u(o->out, o->in2, get_mem_index(s));
- /* The value is stored even in case of trap. */
- tcg_gen_brcondi_i64(TCG_COND_NE, o->out, 0, lab);
- gen_trap(s);
- gen_set_label(lab);
- return NO_EXIT;
-}
-
-static ExitStatus op_llgtat(DisasContext *s, DisasOps *o)
-{
- TCGLabel *lab = gen_new_label();
- tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff);
- /* The value is stored even in case of trap. */
- tcg_gen_brcondi_i64(TCG_COND_NE, o->out, 0, lab);
- gen_trap(s);
- gen_set_label(lab);
- return NO_EXIT;
-}
-
-static ExitStatus op_loc(DisasContext *s, DisasOps *o)
-{
- DisasCompare c;
-
- disas_jcc(s, &c, get_field(s->fields, m3));
-
- if (c.is_64) {
- tcg_gen_movcond_i64(c.cond, o->out, c.u.s64.a, c.u.s64.b,
- o->in2, o->in1);
- free_compare(&c);
- } else {
- TCGv_i32 t32 = tcg_temp_new_i32();
- TCGv_i64 t, z;
-
- tcg_gen_setcond_i32(c.cond, t32, c.u.s32.a, c.u.s32.b);
- free_compare(&c);
-
- t = tcg_temp_new_i64();
- tcg_gen_extu_i32_i64(t, t32);
- tcg_temp_free_i32(t32);
-
- z = tcg_const_i64(0);
- tcg_gen_movcond_i64(TCG_COND_NE, o->out, t, z, o->in2, o->in1);
- tcg_temp_free_i64(t);
- tcg_temp_free_i64(z);
- }
-
- return NO_EXIT;
-}
-
-#ifndef CONFIG_USER_ONLY
-static ExitStatus 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);
- potential_page_fault(s);
- gen_helper_lctl(cpu_env, r1, o->in2, r3);
- tcg_temp_free_i32(r1);
- tcg_temp_free_i32(r3);
- return NO_EXIT;
-}
-
-static ExitStatus 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);
- potential_page_fault(s);
- gen_helper_lctlg(cpu_env, r1, o->in2, r3);
- tcg_temp_free_i32(r1);
- tcg_temp_free_i32(r3);
- return NO_EXIT;
-}
-static ExitStatus op_lra(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_lra(o->out, cpu_env, o->in2);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus 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_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. */
- tcg_gen_shli_i64(t1, t1, 32);
- gen_helper_load_psw(cpu_env, t1, t2);
- tcg_temp_free_i64(t1);
- tcg_temp_free_i64(t2);
- return EXIT_NORETURN;
-}
-
-static ExitStatus 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_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);
- tcg_temp_free_i64(t1);
- tcg_temp_free_i64(t2);
- return EXIT_NORETURN;
-}
-#endif
-
-static ExitStatus op_lam(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));
- potential_page_fault(s);
- gen_helper_lam(cpu_env, r1, o->in2, r3);
- tcg_temp_free_i32(r1);
- tcg_temp_free_i32(r3);
- return NO_EXIT;
-}
-
-static ExitStatus op_lm32(DisasContext *s, DisasOps *o)
-{
- int r1 = get_field(s->fields, r1);
- int r3 = get_field(s->fields, r3);
- TCGv_i64 t1, t2;
-
- /* Only one register to read. */
- t1 = tcg_temp_new_i64();
- if (unlikely(r1 == r3)) {
- tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
- store_reg32_i64(r1, t1);
- tcg_temp_free(t1);
- return NO_EXIT;
- }
-
- /* First load the values of the first and last registers to trigger
- possible page faults. */
- t2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
- tcg_gen_addi_i64(t2, o->in2, 4 * ((r3 - r1) & 15));
- tcg_gen_qemu_ld32u(t2, t2, get_mem_index(s));
- store_reg32_i64(r1, t1);
- store_reg32_i64(r3, t2);
-
- /* Only two registers to read. */
- if (((r1 + 1) & 15) == r3) {
- tcg_temp_free(t2);
- tcg_temp_free(t1);
- return NO_EXIT;
- }
-
- /* Then load the remaining registers. Page fault can't occur. */
- r3 = (r3 - 1) & 15;
- tcg_gen_movi_i64(t2, 4);
- while (r1 != r3) {
- r1 = (r1 + 1) & 15;
- tcg_gen_add_i64(o->in2, o->in2, t2);
- tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
- store_reg32_i64(r1, t1);
- }
- tcg_temp_free(t2);
- tcg_temp_free(t1);
-
- return NO_EXIT;
-}
-
-static ExitStatus op_lmh(DisasContext *s, DisasOps *o)
-{
- int r1 = get_field(s->fields, r1);
- int r3 = get_field(s->fields, r3);
- TCGv_i64 t1, t2;
-
- /* Only one register to read. */
- t1 = tcg_temp_new_i64();
- if (unlikely(r1 == r3)) {
- tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
- store_reg32h_i64(r1, t1);
- tcg_temp_free(t1);
- return NO_EXIT;
- }
-
- /* First load the values of the first and last registers to trigger
- possible page faults. */
- t2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
- tcg_gen_addi_i64(t2, o->in2, 4 * ((r3 - r1) & 15));
- tcg_gen_qemu_ld32u(t2, t2, get_mem_index(s));
- store_reg32h_i64(r1, t1);
- store_reg32h_i64(r3, t2);
-
- /* Only two registers to read. */
- if (((r1 + 1) & 15) == r3) {
- tcg_temp_free(t2);
- tcg_temp_free(t1);
- return NO_EXIT;
- }
-
- /* Then load the remaining registers. Page fault can't occur. */
- r3 = (r3 - 1) & 15;
- tcg_gen_movi_i64(t2, 4);
- while (r1 != r3) {
- r1 = (r1 + 1) & 15;
- tcg_gen_add_i64(o->in2, o->in2, t2);
- tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
- store_reg32h_i64(r1, t1);
- }
- tcg_temp_free(t2);
- tcg_temp_free(t1);
-
- return NO_EXIT;
-}
-
-static ExitStatus op_lm64(DisasContext *s, DisasOps *o)
-{
- int r1 = get_field(s->fields, r1);
- int r3 = get_field(s->fields, r3);
- TCGv_i64 t1, t2;
-
- /* Only one register to read. */
- if (unlikely(r1 == r3)) {
- tcg_gen_qemu_ld64(regs[r1], o->in2, get_mem_index(s));
- return NO_EXIT;
- }
-
- /* First load the values of the first and last registers to trigger
- possible page faults. */
- t1 = tcg_temp_new_i64();
- t2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld64(t1, o->in2, get_mem_index(s));
- tcg_gen_addi_i64(t2, o->in2, 8 * ((r3 - r1) & 15));
- tcg_gen_qemu_ld64(regs[r3], t2, get_mem_index(s));
- tcg_gen_mov_i64(regs[r1], t1);
- tcg_temp_free(t2);
-
- /* Only two registers to read. */
- if (((r1 + 1) & 15) == r3) {
- tcg_temp_free(t1);
- return NO_EXIT;
- }
-
- /* Then load the remaining registers. Page fault can't occur. */
- r3 = (r3 - 1) & 15;
- tcg_gen_movi_i64(t1, 8);
- while (r1 != r3) {
- r1 = (r1 + 1) & 15;
- tcg_gen_add_i64(o->in2, o->in2, t1);
- tcg_gen_qemu_ld64(regs[r1], o->in2, get_mem_index(s));
- }
- tcg_temp_free(t1);
-
- return NO_EXIT;
-}
-
-#ifndef CONFIG_USER_ONLY
-static ExitStatus op_lura(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_lura(o->out, cpu_env, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_lurag(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_lurag(o->out, cpu_env, o->in2);
- return NO_EXIT;
-}
-#endif
-
-static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
-{
- o->out = o->in2;
- o->g_out = o->g_in2;
- TCGV_UNUSED_I64(o->in2);
- o->g_in2 = false;
- return NO_EXIT;
-}
-
-static ExitStatus op_mov2e(DisasContext *s, DisasOps *o)
-{
- int b2 = get_field(s->fields, b2);
- TCGv ar1 = tcg_temp_new_i64();
-
- o->out = o->in2;
- o->g_out = o->g_in2;
- TCGV_UNUSED_I64(o->in2);
- o->g_in2 = false;
-
- switch (s->tb->flags & FLAG_MASK_ASC) {
- case PSW_ASC_PRIMARY >> 32:
- tcg_gen_movi_i64(ar1, 0);
- break;
- case PSW_ASC_ACCREG >> 32:
- tcg_gen_movi_i64(ar1, 1);
- break;
- case PSW_ASC_SECONDARY >> 32:
- if (b2) {
- tcg_gen_ld32u_i64(ar1, cpu_env, offsetof(CPUS390XState, aregs[b2]));
- } else {
- tcg_gen_movi_i64(ar1, 0);
- }
- break;
- case PSW_ASC_HOME >> 32:
- tcg_gen_movi_i64(ar1, 2);
- break;
- }
-
- tcg_gen_st32_i64(ar1, cpu_env, offsetof(CPUS390XState, aregs[1]));
- tcg_temp_free_i64(ar1);
-
- return NO_EXIT;
-}
-
-static ExitStatus op_movx(DisasContext *s, DisasOps *o)
-{
- o->out = o->in1;
- o->out2 = o->in2;
- o->g_out = o->g_in1;
- o->g_out2 = o->g_in2;
- TCGV_UNUSED_I64(o->in1);
- TCGV_UNUSED_I64(o->in2);
- o->g_in1 = o->g_in2 = false;
- return NO_EXIT;
-}
-
-static ExitStatus op_mvc(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
- potential_page_fault(s);
- gen_helper_mvc(cpu_env, l, o->addr1, o->in2);
- tcg_temp_free_i32(l);
- return NO_EXIT;
-}
-
-static ExitStatus op_mvcl(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));
- potential_page_fault(s);
- gen_helper_mvcl(cc_op, cpu_env, r1, r2);
- tcg_temp_free_i32(r1);
- tcg_temp_free_i32(r2);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_mvcle(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));
- potential_page_fault(s);
- gen_helper_mvcle(cc_op, cpu_env, r1, o->in2, r3);
- tcg_temp_free_i32(r1);
- tcg_temp_free_i32(r3);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-#ifndef CONFIG_USER_ONLY
-static ExitStatus op_mvcp(DisasContext *s, DisasOps *o)
-{
- int r1 = get_field(s->fields, l1);
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_mvcp(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_mvcs(DisasContext *s, DisasOps *o)
-{
- int r1 = get_field(s->fields, l1);
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_mvcs(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
- set_cc_static(s);
- return NO_EXIT;
-}
-#endif
-
-static ExitStatus op_mvpg(DisasContext *s, DisasOps *o)
-{
- potential_page_fault(s);
- gen_helper_mvpg(cpu_env, regs[0], o->in1, o->in2);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_mvst(DisasContext *s, DisasOps *o)
-{
- potential_page_fault(s);
- gen_helper_mvst(o->in1, cpu_env, regs[0], o->in1, o->in2);
- set_cc_static(s);
- return_low128(o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_mul(DisasContext *s, DisasOps *o)
-{
- tcg_gen_mul_i64(o->out, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_mul128(DisasContext *s, DisasOps *o)
-{
- tcg_gen_mulu2_i64(o->out2, o->out, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_meeb(DisasContext *s, DisasOps *o)
-{
- gen_helper_meeb(o->out, cpu_env, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_mdeb(DisasContext *s, DisasOps *o)
-{
- gen_helper_mdeb(o->out, cpu_env, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_mdb(DisasContext *s, DisasOps *o)
-{
- gen_helper_mdb(o->out, cpu_env, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_mxb(DisasContext *s, DisasOps *o)
-{
- gen_helper_mxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
- return_low128(o->out2);
- return NO_EXIT;
-}
-
-static ExitStatus op_mxdb(DisasContext *s, DisasOps *o)
-{
- gen_helper_mxdb(o->out, cpu_env, o->out, o->out2, o->in2);
- return_low128(o->out2);
- return NO_EXIT;
-}
-
-static ExitStatus op_maeb(DisasContext *s, DisasOps *o)
-{
- TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3));
- gen_helper_maeb(o->out, cpu_env, o->in1, o->in2, r3);
- tcg_temp_free_i64(r3);
- return NO_EXIT;
-}
-
-static ExitStatus op_madb(DisasContext *s, DisasOps *o)
-{
- int r3 = get_field(s->fields, r3);
- gen_helper_madb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
- return NO_EXIT;
-}
-
-static ExitStatus op_mseb(DisasContext *s, DisasOps *o)
-{
- TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3));
- gen_helper_mseb(o->out, cpu_env, o->in1, o->in2, r3);
- tcg_temp_free_i64(r3);
- return NO_EXIT;
-}
-
-static ExitStatus op_msdb(DisasContext *s, DisasOps *o)
-{
- int r3 = get_field(s->fields, r3);
- gen_helper_msdb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
- return NO_EXIT;
-}
-
-static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
-{
- TCGv_i64 z, n;
- z = tcg_const_i64(0);
- n = tcg_temp_new_i64();
- tcg_gen_neg_i64(n, o->in2);
- tcg_gen_movcond_i64(TCG_COND_GE, o->out, o->in2, z, n, o->in2);
- tcg_temp_free_i64(n);
- tcg_temp_free_i64(z);
- return NO_EXIT;
-}
-
-static ExitStatus op_nabsf32(DisasContext *s, DisasOps *o)
-{
- tcg_gen_ori_i64(o->out, o->in2, 0x80000000ull);
- return NO_EXIT;
-}
-
-static ExitStatus op_nabsf64(DisasContext *s, DisasOps *o)
-{
- tcg_gen_ori_i64(o->out, o->in2, 0x8000000000000000ull);
- return NO_EXIT;
-}
-
-static ExitStatus op_nabsf128(DisasContext *s, DisasOps *o)
-{
- tcg_gen_ori_i64(o->out, o->in1, 0x8000000000000000ull);
- tcg_gen_mov_i64(o->out2, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_nc(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
- potential_page_fault(s);
- gen_helper_nc(cc_op, cpu_env, l, o->addr1, o->in2);
- tcg_temp_free_i32(l);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_neg(DisasContext *s, DisasOps *o)
-{
- tcg_gen_neg_i64(o->out, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_negf32(DisasContext *s, DisasOps *o)
-{
- tcg_gen_xori_i64(o->out, o->in2, 0x80000000ull);
- return NO_EXIT;
-}
-
-static ExitStatus op_negf64(DisasContext *s, DisasOps *o)
-{
- tcg_gen_xori_i64(o->out, o->in2, 0x8000000000000000ull);
- return NO_EXIT;
-}
-
-static ExitStatus op_negf128(DisasContext *s, DisasOps *o)
-{
- tcg_gen_xori_i64(o->out, o->in1, 0x8000000000000000ull);
- tcg_gen_mov_i64(o->out2, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_oc(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
- potential_page_fault(s);
- gen_helper_oc(cc_op, cpu_env, l, o->addr1, o->in2);
- tcg_temp_free_i32(l);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_or(DisasContext *s, DisasOps *o)
-{
- tcg_gen_or_i64(o->out, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_ori(DisasContext *s, DisasOps *o)
-{
- int shift = s->insn->data & 0xff;
- int size = s->insn->data >> 8;
- uint64_t mask = ((1ull << size) - 1) << shift;
-
- assert(!o->g_in2);
- tcg_gen_shli_i64(o->in2, o->in2, shift);
- tcg_gen_or_i64(o->out, o->in1, o->in2);
-
- /* Produce the CC from only the bits manipulated. */
- tcg_gen_andi_i64(cc_dst, o->out, mask);
- set_cc_nz_u64(s, cc_dst);
- return NO_EXIT;
-}
-
-static ExitStatus op_popcnt(DisasContext *s, DisasOps *o)
-{
- gen_helper_popcnt(o->out, o->in2);
- return NO_EXIT;
-}
-
-#ifndef CONFIG_USER_ONLY
-static ExitStatus op_ptlb(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- gen_helper_ptlb(cpu_env);
- return NO_EXIT;
-}
-#endif
-
-static ExitStatus op_risbg(DisasContext *s, DisasOps *o)
-{
- int i3 = get_field(s->fields, i3);
- int i4 = get_field(s->fields, i4);
- int i5 = get_field(s->fields, i5);
- int do_zero = i4 & 0x80;
- uint64_t mask, imask, pmask;
- int pos, len, rot;
-
- /* Adjust the arguments for the specific insn. */
- switch (s->fields->op2) {
- case 0x55: /* risbg */
- i3 &= 63;
- i4 &= 63;
- pmask = ~0;
- break;
- case 0x5d: /* risbhg */
- i3 &= 31;
- i4 &= 31;
- pmask = 0xffffffff00000000ull;
- break;
- case 0x51: /* risblg */
- i3 &= 31;
- i4 &= 31;
- pmask = 0x00000000ffffffffull;
- break;
- default:
- abort();
- }
-
- /* MASK is the set of bits to be inserted from R2.
- Take care for I3/I4 wraparound. */
- mask = pmask >> i3;
- if (i3 <= i4) {
- mask ^= pmask >> i4 >> 1;
- } else {
- mask |= ~(pmask >> i4 >> 1);
- }
- mask &= pmask;
-
- /* IMASK is the set of bits to be kept from R1. In the case of the high/low
- insns, we need to keep the other half of the register. */
- imask = ~mask | ~pmask;
- if (do_zero) {
- if (s->fields->op2 == 0x55) {
- imask = 0;
- } else {
- imask = ~pmask;
- }
- }
-
- /* In some cases we can implement this with deposit, which can be more
- efficient on some hosts. */
- if (~mask == imask && i3 <= i4) {
- if (s->fields->op2 == 0x5d) {
- i3 += 32, i4 += 32;
- }
- /* Note that we rotate the bits to be inserted to the lsb, not to
- the position as described in the PoO. */
- len = i4 - i3 + 1;
- pos = 63 - i4;
- rot = (i5 - pos) & 63;
- } else {
- pos = len = -1;
- rot = i5 & 63;
- }
-
- /* Rotate the input as necessary. */
- tcg_gen_rotli_i64(o->in2, o->in2, rot);
-
- /* Insert the selected bits into the output. */
- if (pos >= 0) {
- tcg_gen_deposit_i64(o->out, o->out, o->in2, pos, len);
- } else if (imask == 0) {
- tcg_gen_andi_i64(o->out, o->in2, mask);
- } else {
- tcg_gen_andi_i64(o->in2, o->in2, mask);
- tcg_gen_andi_i64(o->out, o->out, imask);
- tcg_gen_or_i64(o->out, o->out, o->in2);
- }
- return NO_EXIT;
-}
-
-static ExitStatus op_rosbg(DisasContext *s, DisasOps *o)
-{
- int i3 = get_field(s->fields, i3);
- int i4 = get_field(s->fields, i4);
- int i5 = get_field(s->fields, i5);
- uint64_t mask;
-
- /* If this is a test-only form, arrange to discard the result. */
- if (i3 & 0x80) {
- o->out = tcg_temp_new_i64();
- o->g_out = false;
- }
-
- i3 &= 63;
- i4 &= 63;
- i5 &= 63;
-
- /* MASK is the set of bits to be operated on from R2.
- Take care for I3/I4 wraparound. */
- mask = ~0ull >> i3;
- if (i3 <= i4) {
- mask ^= ~0ull >> i4 >> 1;
- } else {
- mask |= ~(~0ull >> i4 >> 1);
- }
-
- /* Rotate the input as necessary. */
- tcg_gen_rotli_i64(o->in2, o->in2, i5);
-
- /* Operate. */
- switch (s->fields->op2) {
- case 0x55: /* AND */
- tcg_gen_ori_i64(o->in2, o->in2, ~mask);
- tcg_gen_and_i64(o->out, o->out, o->in2);
- break;
- case 0x56: /* OR */
- tcg_gen_andi_i64(o->in2, o->in2, mask);
- tcg_gen_or_i64(o->out, o->out, o->in2);
- break;
- case 0x57: /* XOR */
- tcg_gen_andi_i64(o->in2, o->in2, mask);
- tcg_gen_xor_i64(o->out, o->out, o->in2);
- break;
- default:
- abort();
- }
-
- /* Set the CC. */
- tcg_gen_andi_i64(cc_dst, o->out, mask);
- set_cc_nz_u64(s, cc_dst);
- return NO_EXIT;
-}
-
-static ExitStatus op_rev16(DisasContext *s, DisasOps *o)
-{
- tcg_gen_bswap16_i64(o->out, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_rev32(DisasContext *s, DisasOps *o)
-{
- tcg_gen_bswap32_i64(o->out, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_rev64(DisasContext *s, DisasOps *o)
-{
- tcg_gen_bswap64_i64(o->out, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_rll32(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 t1 = tcg_temp_new_i32();
- TCGv_i32 t2 = tcg_temp_new_i32();
- TCGv_i32 to = tcg_temp_new_i32();
- tcg_gen_extrl_i64_i32(t1, o->in1);
- tcg_gen_extrl_i64_i32(t2, o->in2);
- tcg_gen_rotl_i32(to, t1, t2);
- tcg_gen_extu_i32_i64(o->out, to);
- tcg_temp_free_i32(t1);
- tcg_temp_free_i32(t2);
- tcg_temp_free_i32(to);
- return NO_EXIT;
-}
-
-static ExitStatus op_rll64(DisasContext *s, DisasOps *o)
-{
- tcg_gen_rotl_i64(o->out, o->in1, o->in2);
- return NO_EXIT;
-}
-
-#ifndef CONFIG_USER_ONLY
-static ExitStatus op_rrbe(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- gen_helper_rrbe(cc_op, cpu_env, o->in2);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus 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 EXIT_PC_STALE;
-}
-#endif
-
-static ExitStatus op_sam(DisasContext *s, DisasOps *o)
-{
- int sam = s->insn->data;
- TCGv_i64 tsam;
- uint64_t mask;
-
- switch (sam) {
- case 0:
- mask = 0xffffff;
- break;
- case 1:
- mask = 0x7fffffff;
- break;
- default:
- mask = -1;
- break;
- }
-
- /* Bizarre but true, we check the address of the current insn for the
- specification exception, not the next to be executed. Thus the PoO
- documents that Bad Things Happen two bytes before the end. */
- if (s->pc & ~mask) {
- gen_program_exception(s, PGM_SPECIFICATION);
- return EXIT_NORETURN;
- }
- s->next_pc &= mask;
-
- tsam = tcg_const_i64(sam);
- tcg_gen_deposit_i64(psw_mask, psw_mask, tsam, 31, 2);
- tcg_temp_free_i64(tsam);
-
- /* Always exit the TB, since we (may have) changed execution mode. */
- return EXIT_PC_STALE;
-}
-
-static ExitStatus op_sar(DisasContext *s, DisasOps *o)
-{
- int r1 = get_field(s->fields, r1);
- tcg_gen_st32_i64(o->in2, cpu_env, offsetof(CPUS390XState, aregs[r1]));
- return NO_EXIT;
-}
-
-static ExitStatus op_seb(DisasContext *s, DisasOps *o)
-{
- gen_helper_seb(o->out, cpu_env, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_sdb(DisasContext *s, DisasOps *o)
-{
- gen_helper_sdb(o->out, cpu_env, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_sxb(DisasContext *s, DisasOps *o)
-{
- gen_helper_sxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
- return_low128(o->out2);
- return NO_EXIT;
-}
-
-static ExitStatus op_sqeb(DisasContext *s, DisasOps *o)
-{
- gen_helper_sqeb(o->out, cpu_env, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_sqdb(DisasContext *s, DisasOps *o)
-{
- gen_helper_sqdb(o->out, cpu_env, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_sqxb(DisasContext *s, DisasOps *o)
-{
- gen_helper_sqxb(o->out, cpu_env, o->in1, o->in2);
- return_low128(o->out2);
- return NO_EXIT;
-}
-
-#ifndef CONFIG_USER_ONLY
-static ExitStatus op_servc(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_servc(cc_op, cpu_env, o->in2, o->in1);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_sigp(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_sigp(cc_op, cpu_env, o->in2, r1, o->in1);
- tcg_temp_free_i32(r1);
- return NO_EXIT;
-}
-#endif
-
-static ExitStatus op_soc(DisasContext *s, DisasOps *o)
-{
- DisasCompare c;
- TCGv_i64 a;
- TCGLabel *lab;
- int r1;
-
- disas_jcc(s, &c, get_field(s->fields, m3));
-
- /* We want to store when the condition is fulfilled, so branch
- out when it's not */
- c.cond = tcg_invert_cond(c.cond);
-
- lab = gen_new_label();
- if (c.is_64) {
- tcg_gen_brcond_i64(c.cond, c.u.s64.a, c.u.s64.b, lab);
- } else {
- tcg_gen_brcond_i32(c.cond, c.u.s32.a, c.u.s32.b, lab);
- }
- free_compare(&c);
-
- r1 = get_field(s->fields, r1);
- a = get_address(s, 0, get_field(s->fields, b2), get_field(s->fields, d2));
- if (s->insn->data) {
- tcg_gen_qemu_st64(regs[r1], a, get_mem_index(s));
- } else {
- tcg_gen_qemu_st32(regs[r1], a, get_mem_index(s));
- }
- tcg_temp_free_i64(a);
-
- gen_set_label(lab);
- return NO_EXIT;
-}
-
-static ExitStatus op_sla(DisasContext *s, DisasOps *o)
-{
- uint64_t sign = 1ull << s->insn->data;
- enum cc_op cco = s->insn->data == 31 ? CC_OP_SLA_32 : CC_OP_SLA_64;
- gen_op_update2_cc_i64(s, cco, o->in1, o->in2);
- tcg_gen_shl_i64(o->out, o->in1, o->in2);
- /* The arithmetic left shift is curious in that it does not affect
- the sign bit. Copy that over from the source unchanged. */
- tcg_gen_andi_i64(o->out, o->out, ~sign);
- tcg_gen_andi_i64(o->in1, o->in1, sign);
- tcg_gen_or_i64(o->out, o->out, o->in1);
- return NO_EXIT;
-}
-
-static ExitStatus op_sll(DisasContext *s, DisasOps *o)
-{
- tcg_gen_shl_i64(o->out, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_sra(DisasContext *s, DisasOps *o)
-{
- tcg_gen_sar_i64(o->out, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_srl(DisasContext *s, DisasOps *o)
-{
- tcg_gen_shr_i64(o->out, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_sfpc(DisasContext *s, DisasOps *o)
-{
- gen_helper_sfpc(cpu_env, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_sfas(DisasContext *s, DisasOps *o)
-{
- gen_helper_sfas(cpu_env, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_srnm(DisasContext *s, DisasOps *o)
-{
- int b2 = get_field(s->fields, b2);
- int d2 = get_field(s->fields, d2);
- TCGv_i64 t1 = tcg_temp_new_i64();
- TCGv_i64 t2 = tcg_temp_new_i64();
- int mask, pos, len;
-
- switch (s->fields->op2) {
- case 0x99: /* SRNM */
- pos = 0, len = 2;
- break;
- case 0xb8: /* SRNMB */
- pos = 0, len = 3;
- break;
- case 0xb9: /* SRNMT */
- pos = 4, len = 3;
- break;
- default:
- tcg_abort();
- }
- mask = (1 << len) - 1;
-
- /* Insert the value into the appropriate field of the FPC. */
- if (b2 == 0) {
- tcg_gen_movi_i64(t1, d2 & mask);
- } else {
- tcg_gen_addi_i64(t1, regs[b2], d2);
- tcg_gen_andi_i64(t1, t1, mask);
- }
- tcg_gen_ld32u_i64(t2, cpu_env, offsetof(CPUS390XState, fpc));
- tcg_gen_deposit_i64(t2, t2, t1, pos, len);
- tcg_temp_free_i64(t1);
-
- /* Then install the new FPC to set the rounding mode in fpu_status. */
- gen_helper_sfpc(cpu_env, t2);
- tcg_temp_free_i64(t2);
- return NO_EXIT;
-}
-
-#ifndef CONFIG_USER_ONLY
-static ExitStatus 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, 4);
- return NO_EXIT;
-}
-
-static ExitStatus op_sske(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- gen_helper_sske(cpu_env, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8);
- return NO_EXIT;
-}
-
-static ExitStatus op_stap(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- /* ??? Surely cpu address != cpu number. In any case the previous
- version of this stored more than the required half-word, so it
- is unlikely this has ever been tested. */
- tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num));
- return NO_EXIT;
-}
-
-static ExitStatus op_stck(DisasContext *s, DisasOps *o)
-{
- gen_helper_stck(o->out, cpu_env);
- /* ??? We don't implement clock states. */
- gen_op_movi_cc(s, 0);
- return NO_EXIT;
-}
-
-static ExitStatus op_stcke(DisasContext *s, DisasOps *o)
-{
- TCGv_i64 c1 = tcg_temp_new_i64();
- TCGv_i64 c2 = tcg_temp_new_i64();
- gen_helper_stck(c1, cpu_env);
- /* Shift the 64-bit value into its place as a zero-extended
- 104-bit value. Note that "bit positions 64-103 are always
- non-zero so that they compare differently to STCK"; we set
- the least significant bit to 1. */
- tcg_gen_shli_i64(c2, c1, 56);
- tcg_gen_shri_i64(c1, c1, 8);
- tcg_gen_ori_i64(c2, c2, 0x10000);
- tcg_gen_qemu_st64(c1, o->in2, get_mem_index(s));
- tcg_gen_addi_i64(o->in2, o->in2, 8);
- tcg_gen_qemu_st64(c2, o->in2, get_mem_index(s));
- tcg_temp_free_i64(c1);
- tcg_temp_free_i64(c2);
- /* ??? We don't implement clock states. */
- gen_op_movi_cc(s, 0);
- return NO_EXIT;
-}
-
-static ExitStatus op_sckc(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- gen_helper_sckc(cpu_env, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_stckc(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- gen_helper_stckc(o->out, cpu_env);
- return NO_EXIT;
-}
-
-static ExitStatus 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);
- potential_page_fault(s);
- gen_helper_stctg(cpu_env, r1, o->in2, r3);
- tcg_temp_free_i32(r1);
- tcg_temp_free_i32(r3);
- return NO_EXIT;
-}
-
-static ExitStatus 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);
- potential_page_fault(s);
- gen_helper_stctl(cpu_env, r1, o->in2, r3);
- tcg_temp_free_i32(r1);
- tcg_temp_free_i32(r3);
- return NO_EXIT;
-}
-
-static ExitStatus op_stidp(DisasContext *s, DisasOps *o)
-{
- TCGv_i64 t1 = tcg_temp_new_i64();
-
- check_privileged(s);
- tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num));
- tcg_gen_ld32u_i64(t1, cpu_env, offsetof(CPUS390XState, machine_type));
- tcg_gen_deposit_i64(o->out, o->out, t1, 32, 32);
- tcg_temp_free_i64(t1);
-
- return NO_EXIT;
-}
-
-static ExitStatus op_spt(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- gen_helper_spt(cpu_env, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_stfl(DisasContext *s, DisasOps *o)
-{
- TCGv_i64 f, a;
- /* We really ought to have more complete indication of facilities
- that we implement. Address this when STFLE is implemented. */
- check_privileged(s);
- f = tcg_const_i64(0xc0000000);
- a = tcg_const_i64(200);
- tcg_gen_qemu_st32(f, a, get_mem_index(s));
- tcg_temp_free_i64(f);
- tcg_temp_free_i64(a);
- return NO_EXIT;
-}
-
-static ExitStatus op_stpt(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- gen_helper_stpt(o->out, cpu_env);
- return NO_EXIT;
-}
-
-static ExitStatus op_stsi(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_stsi(cc_op, cpu_env, o->in2, regs[0], regs[1]);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_spx(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- gen_helper_spx(cpu_env, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_xsch(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_xsch(cpu_env, regs[1]);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_csch(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_csch(cpu_env, regs[1]);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_hsch(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_hsch(cpu_env, regs[1]);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_msch(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_msch(cpu_env, regs[1], o->in2);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_rchp(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_rchp(cpu_env, regs[1]);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_rsch(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_rsch(cpu_env, regs[1]);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_ssch(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_ssch(cpu_env, regs[1], o->in2);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_stsch(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_stsch(cpu_env, regs[1], o->in2);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_tsch(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_tsch(cpu_env, regs[1], o->in2);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_chsc(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_chsc(cpu_env, o->in2);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus 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 NO_EXIT;
-}
-
-static ExitStatus 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. */
- t = tcg_temp_new_i64();
- tcg_gen_shri_i64(t, psw_mask, 56);
- tcg_gen_qemu_st8(t, o->addr1, get_mem_index(s));
- tcg_temp_free_i64(t);
-
- if (s->fields->op == 0xac) {
- tcg_gen_andi_i64(psw_mask, psw_mask,
- (i2 << 56) | 0x00ffffffffffffffull);
- } else {
- tcg_gen_ori_i64(psw_mask, psw_mask, i2 << 56);
- }
- return NO_EXIT;
-}
-
-static ExitStatus op_stura(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_stura(cpu_env, o->in2, o->in1);
- return NO_EXIT;
-}
-
-static ExitStatus op_sturg(DisasContext *s, DisasOps *o)
-{
- check_privileged(s);
- potential_page_fault(s);
- gen_helper_sturg(cpu_env, o->in2, o->in1);
- return NO_EXIT;
-}
-#endif
-
-static ExitStatus op_st8(DisasContext *s, DisasOps *o)
-{
- tcg_gen_qemu_st8(o->in1, o->in2, get_mem_index(s));
- return NO_EXIT;
-}
-
-static ExitStatus op_st16(DisasContext *s, DisasOps *o)
-{
- tcg_gen_qemu_st16(o->in1, o->in2, get_mem_index(s));
- return NO_EXIT;
-}
-
-static ExitStatus op_st32(DisasContext *s, DisasOps *o)
-{
- tcg_gen_qemu_st32(o->in1, o->in2, get_mem_index(s));
- return NO_EXIT;
-}
-
-static ExitStatus op_st64(DisasContext *s, DisasOps *o)
-{
- tcg_gen_qemu_st64(o->in1, o->in2, get_mem_index(s));
- return NO_EXIT;
-}
-
-static ExitStatus op_stam(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));
- potential_page_fault(s);
- gen_helper_stam(cpu_env, r1, o->in2, r3);
- tcg_temp_free_i32(r1);
- tcg_temp_free_i32(r3);
- return NO_EXIT;
-}
-
-static ExitStatus op_stcm(DisasContext *s, DisasOps *o)
-{
- int m3 = get_field(s->fields, m3);
- int pos, base = s->insn->data;
- TCGv_i64 tmp = tcg_temp_new_i64();
-
- pos = base + ctz32(m3) * 8;
- switch (m3) {
- case 0xf:
- /* Effectively a 32-bit store. */
- tcg_gen_shri_i64(tmp, o->in1, pos);
- tcg_gen_qemu_st32(tmp, o->in2, get_mem_index(s));
- break;
-
- case 0xc:
- case 0x6:
- case 0x3:
- /* Effectively a 16-bit store. */
- tcg_gen_shri_i64(tmp, o->in1, pos);
- tcg_gen_qemu_st16(tmp, o->in2, get_mem_index(s));
- break;
-
- case 0x8:
- case 0x4:
- case 0x2:
- case 0x1:
- /* Effectively an 8-bit store. */
- tcg_gen_shri_i64(tmp, o->in1, pos);
- tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s));
- break;
-
- default:
- /* This is going to be a sequence of shifts and stores. */
- pos = base + 32 - 8;
- while (m3) {
- if (m3 & 0x8) {
- tcg_gen_shri_i64(tmp, o->in1, pos);
- tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s));
- tcg_gen_addi_i64(o->in2, o->in2, 1);
- }
- m3 = (m3 << 1) & 0xf;
- pos -= 8;
- }
- break;
- }
- tcg_temp_free_i64(tmp);
- return NO_EXIT;
-}
-
-static ExitStatus op_stm(DisasContext *s, DisasOps *o)
-{
- int r1 = get_field(s->fields, r1);
- int r3 = get_field(s->fields, r3);
- int size = s->insn->data;
- TCGv_i64 tsize = tcg_const_i64(size);
-
- while (1) {
- if (size == 8) {
- tcg_gen_qemu_st64(regs[r1], o->in2, get_mem_index(s));
- } else {
- tcg_gen_qemu_st32(regs[r1], o->in2, get_mem_index(s));
- }
- if (r1 == r3) {
- break;
- }
- tcg_gen_add_i64(o->in2, o->in2, tsize);
- r1 = (r1 + 1) & 15;
- }
-
- tcg_temp_free_i64(tsize);
- return NO_EXIT;
-}
-
-static ExitStatus op_stmh(DisasContext *s, DisasOps *o)
-{
- int r1 = get_field(s->fields, r1);
- int r3 = get_field(s->fields, r3);
- TCGv_i64 t = tcg_temp_new_i64();
- TCGv_i64 t4 = tcg_const_i64(4);
- TCGv_i64 t32 = tcg_const_i64(32);
-
- while (1) {
- tcg_gen_shl_i64(t, regs[r1], t32);
- tcg_gen_qemu_st32(t, o->in2, get_mem_index(s));
- if (r1 == r3) {
- break;
- }
- tcg_gen_add_i64(o->in2, o->in2, t4);
- r1 = (r1 + 1) & 15;
- }
-
- tcg_temp_free_i64(t);
- tcg_temp_free_i64(t4);
- tcg_temp_free_i64(t32);
- return NO_EXIT;
-}
-
-static ExitStatus op_srst(DisasContext *s, DisasOps *o)
-{
- potential_page_fault(s);
- gen_helper_srst(o->in1, cpu_env, regs[0], o->in1, o->in2);
- set_cc_static(s);
- return_low128(o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_sub(DisasContext *s, DisasOps *o)
-{
- tcg_gen_sub_i64(o->out, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_subb(DisasContext *s, DisasOps *o)
-{
- DisasCompare cmp;
- TCGv_i64 borrow;
-
- tcg_gen_sub_i64(o->out, o->in1, o->in2);
-
- /* The !borrow flag is the msb of CC. Since we want the inverse of
- that, we ask for a comparison of CC=0 | CC=1 -> mask of 8 | 4. */
- disas_jcc(s, &cmp, 8 | 4);
- borrow = tcg_temp_new_i64();
- if (cmp.is_64) {
- tcg_gen_setcond_i64(cmp.cond, borrow, cmp.u.s64.a, cmp.u.s64.b);
- } else {
- TCGv_i32 t = tcg_temp_new_i32();
- tcg_gen_setcond_i32(cmp.cond, t, cmp.u.s32.a, cmp.u.s32.b);
- tcg_gen_extu_i32_i64(borrow, t);
- tcg_temp_free_i32(t);
- }
- free_compare(&cmp);
-
- tcg_gen_sub_i64(o->out, o->out, borrow);
- tcg_temp_free_i64(borrow);
- return NO_EXIT;
-}
-
-static ExitStatus op_svc(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 t;
-
- update_psw_addr(s);
- update_cc_op(s);
-
- t = tcg_const_i32(get_field(s->fields, i1) & 0xff);
- tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_code));
- tcg_temp_free_i32(t);
-
- t = tcg_const_i32(s->next_pc - s->pc);
- tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_ilen));
- tcg_temp_free_i32(t);
-
- gen_exception(EXCP_SVC);
- return EXIT_NORETURN;
-}
-
-static ExitStatus op_tceb(DisasContext *s, DisasOps *o)
-{
- gen_helper_tceb(cc_op, o->in1, o->in2);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_tcdb(DisasContext *s, DisasOps *o)
-{
- gen_helper_tcdb(cc_op, o->in1, o->in2);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_tcxb(DisasContext *s, DisasOps *o)
-{
- gen_helper_tcxb(cc_op, o->out, o->out2, o->in2);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-#ifndef CONFIG_USER_ONLY
-static ExitStatus op_tprot(DisasContext *s, DisasOps *o)
-{
- potential_page_fault(s);
- gen_helper_tprot(cc_op, o->addr1, o->in2);
- set_cc_static(s);
- return NO_EXIT;
-}
-#endif
-
-static ExitStatus op_tr(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
- potential_page_fault(s);
- gen_helper_tr(cpu_env, l, o->addr1, o->in2);
- tcg_temp_free_i32(l);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_tre(DisasContext *s, DisasOps *o)
-{
- potential_page_fault(s);
- gen_helper_tre(o->out, cpu_env, o->out, o->out2, o->in2);
- return_low128(o->out2);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_trt(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
- potential_page_fault(s);
- gen_helper_trt(cc_op, cpu_env, l, o->addr1, o->in2);
- tcg_temp_free_i32(l);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_unpk(DisasContext *s, DisasOps *o)
-{
- TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
- potential_page_fault(s);
- gen_helper_unpk(cpu_env, l, o->addr1, o->in2);
- tcg_temp_free_i32(l);
- return NO_EXIT;
-}
-
-static ExitStatus op_xc(DisasContext *s, DisasOps *o)
-{
- int d1 = get_field(s->fields, d1);
- int d2 = get_field(s->fields, d2);
- int b1 = get_field(s->fields, b1);
- int b2 = get_field(s->fields, b2);
- int l = get_field(s->fields, l1);
- TCGv_i32 t32;
-
- o->addr1 = get_address(s, 0, b1, d1);
-
- /* If the addresses are identical, this is a store/memset of zero. */
- if (b1 == b2 && d1 == d2 && (l + 1) <= 32) {
- o->in2 = tcg_const_i64(0);
-
- l++;
- while (l >= 8) {
- tcg_gen_qemu_st64(o->in2, o->addr1, get_mem_index(s));
- l -= 8;
- if (l > 0) {
- tcg_gen_addi_i64(o->addr1, o->addr1, 8);
- }
- }
- if (l >= 4) {
- tcg_gen_qemu_st32(o->in2, o->addr1, get_mem_index(s));
- l -= 4;
- if (l > 0) {
- tcg_gen_addi_i64(o->addr1, o->addr1, 4);
- }
- }
- if (l >= 2) {
- tcg_gen_qemu_st16(o->in2, o->addr1, get_mem_index(s));
- l -= 2;
- if (l > 0) {
- tcg_gen_addi_i64(o->addr1, o->addr1, 2);
- }
- }
- if (l) {
- tcg_gen_qemu_st8(o->in2, o->addr1, get_mem_index(s));
- }
- gen_op_movi_cc(s, 0);
- return NO_EXIT;
- }
-
- /* But in general we'll defer to a helper. */
- o->in2 = get_address(s, 0, b2, d2);
- t32 = tcg_const_i32(l);
- potential_page_fault(s);
- gen_helper_xc(cc_op, cpu_env, t32, o->addr1, o->in2);
- tcg_temp_free_i32(t32);
- set_cc_static(s);
- return NO_EXIT;
-}
-
-static ExitStatus op_xor(DisasContext *s, DisasOps *o)
-{
- tcg_gen_xor_i64(o->out, o->in1, o->in2);
- return NO_EXIT;
-}
-
-static ExitStatus op_xori(DisasContext *s, DisasOps *o)
-{
- int shift = s->insn->data & 0xff;
- int size = s->insn->data >> 8;
- uint64_t mask = ((1ull << size) - 1) << shift;
-
- assert(!o->g_in2);
- tcg_gen_shli_i64(o->in2, o->in2, shift);
- tcg_gen_xor_i64(o->out, o->in1, o->in2);
-
- /* Produce the CC from only the bits manipulated. */
- tcg_gen_andi_i64(cc_dst, o->out, mask);
- set_cc_nz_u64(s, cc_dst);
- return NO_EXIT;
-}
-
-static ExitStatus op_zero(DisasContext *s, DisasOps *o)
-{
- o->out = tcg_const_i64(0);
- return NO_EXIT;
-}
-
-static ExitStatus op_zero2(DisasContext *s, DisasOps *o)
-{
- o->out = tcg_const_i64(0);
- o->out2 = o->out;
- o->g_out2 = true;
- return NO_EXIT;
-}
-
-/* ====================================================================== */
-/* The "Cc OUTput" generators. Given the generated output (and in some cases
- the original inputs), update the various cc data structures in order to
- be able to compute the new condition code. */
-
-static void cout_abs32(DisasContext *s, DisasOps *o)
-{
- gen_op_update1_cc_i64(s, CC_OP_ABS_32, o->out);
-}
-
-static void cout_abs64(DisasContext *s, DisasOps *o)
-{
- gen_op_update1_cc_i64(s, CC_OP_ABS_64, o->out);
-}
-
-static void cout_adds32(DisasContext *s, DisasOps *o)
-{
- gen_op_update3_cc_i64(s, CC_OP_ADD_32, o->in1, o->in2, o->out);
-}
-
-static void cout_adds64(DisasContext *s, DisasOps *o)
-{
- gen_op_update3_cc_i64(s, CC_OP_ADD_64, o->in1, o->in2, o->out);
-}
-
-static void cout_addu32(DisasContext *s, DisasOps *o)
-{
- gen_op_update3_cc_i64(s, CC_OP_ADDU_32, o->in1, o->in2, o->out);
-}
-
-static void cout_addu64(DisasContext *s, DisasOps *o)
-{
- gen_op_update3_cc_i64(s, CC_OP_ADDU_64, o->in1, o->in2, o->out);
-}
-
-static void cout_addc32(DisasContext *s, DisasOps *o)
-{
- gen_op_update3_cc_i64(s, CC_OP_ADDC_32, o->in1, o->in2, o->out);
-}
-
-static void cout_addc64(DisasContext *s, DisasOps *o)
-{
- gen_op_update3_cc_i64(s, CC_OP_ADDC_64, o->in1, o->in2, o->out);
-}
-
-static void cout_cmps32(DisasContext *s, DisasOps *o)
-{
- gen_op_update2_cc_i64(s, CC_OP_LTGT_32, o->in1, o->in2);
-}
-
-static void cout_cmps64(DisasContext *s, DisasOps *o)
-{
- gen_op_update2_cc_i64(s, CC_OP_LTGT_64, o->in1, o->in2);
-}
-
-static void cout_cmpu32(DisasContext *s, DisasOps *o)
-{
- gen_op_update2_cc_i64(s, CC_OP_LTUGTU_32, o->in1, o->in2);
-}
-
-static void cout_cmpu64(DisasContext *s, DisasOps *o)
-{
- gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, o->in1, o->in2);
-}
-
-static void cout_f32(DisasContext *s, DisasOps *o)
-{
- gen_op_update1_cc_i64(s, CC_OP_NZ_F32, o->out);
-}
-
-static void cout_f64(DisasContext *s, DisasOps *o)
-{
- gen_op_update1_cc_i64(s, CC_OP_NZ_F64, o->out);
-}
-
-static void cout_f128(DisasContext *s, DisasOps *o)
-{
- gen_op_update2_cc_i64(s, CC_OP_NZ_F128, o->out, o->out2);
-}
-
-static void cout_nabs32(DisasContext *s, DisasOps *o)
-{
- gen_op_update1_cc_i64(s, CC_OP_NABS_32, o->out);
-}
-
-static void cout_nabs64(DisasContext *s, DisasOps *o)
-{
- gen_op_update1_cc_i64(s, CC_OP_NABS_64, o->out);
-}
-
-static void cout_neg32(DisasContext *s, DisasOps *o)
-{
- gen_op_update1_cc_i64(s, CC_OP_COMP_32, o->out);
-}
-
-static void cout_neg64(DisasContext *s, DisasOps *o)
-{
- gen_op_update1_cc_i64(s, CC_OP_COMP_64, o->out);
-}
-
-static void cout_nz32(DisasContext *s, DisasOps *o)
-{
- tcg_gen_ext32u_i64(cc_dst, o->out);
- gen_op_update1_cc_i64(s, CC_OP_NZ, cc_dst);
-}
-
-static void cout_nz64(DisasContext *s, DisasOps *o)
-{
- gen_op_update1_cc_i64(s, CC_OP_NZ, o->out);
-}
-
-static void cout_s32(DisasContext *s, DisasOps *o)
-{
- gen_op_update1_cc_i64(s, CC_OP_LTGT0_32, o->out);
-}
-
-static void cout_s64(DisasContext *s, DisasOps *o)
-{
- gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, o->out);
-}
-
-static void cout_subs32(DisasContext *s, DisasOps *o)
-{
- gen_op_update3_cc_i64(s, CC_OP_SUB_32, o->in1, o->in2, o->out);
-}
-
-static void cout_subs64(DisasContext *s, DisasOps *o)
-{
- gen_op_update3_cc_i64(s, CC_OP_SUB_64, o->in1, o->in2, o->out);
-}
-
-static void cout_subu32(DisasContext *s, DisasOps *o)
-{
- gen_op_update3_cc_i64(s, CC_OP_SUBU_32, o->in1, o->in2, o->out);
-}
-
-static void cout_subu64(DisasContext *s, DisasOps *o)
-{
- gen_op_update3_cc_i64(s, CC_OP_SUBU_64, o->in1, o->in2, o->out);
-}
-
-static void cout_subb32(DisasContext *s, DisasOps *o)
-{
- gen_op_update3_cc_i64(s, CC_OP_SUBB_32, o->in1, o->in2, o->out);
-}
-
-static void cout_subb64(DisasContext *s, DisasOps *o)
-{
- gen_op_update3_cc_i64(s, CC_OP_SUBB_64, o->in1, o->in2, o->out);
-}
-
-static void cout_tm32(DisasContext *s, DisasOps *o)
-{
- gen_op_update2_cc_i64(s, CC_OP_TM_32, o->in1, o->in2);
-}
-
-static void cout_tm64(DisasContext *s, DisasOps *o)
-{
- gen_op_update2_cc_i64(s, CC_OP_TM_64, o->in1, o->in2);
-}
-
-/* ====================================================================== */
-/* The "PREParation" generators. These initialize the DisasOps.OUT fields
- with the TCG register to which we will write. Used in combination with
- the "wout" generators, in some cases we need a new temporary, and in
- some cases we can write to a TCG global. */
-
-static void prep_new(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->out = tcg_temp_new_i64();
-}
-#define SPEC_prep_new 0
-
-static void prep_new_P(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->out = tcg_temp_new_i64();
- o->out2 = tcg_temp_new_i64();
-}
-#define SPEC_prep_new_P 0
-
-static void prep_r1(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->out = regs[get_field(f, r1)];
- o->g_out = true;
-}
-#define SPEC_prep_r1 0
-
-static void prep_r1_P(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- int r1 = get_field(f, r1);
- o->out = regs[r1];
- o->out2 = regs[r1 + 1];
- o->g_out = o->g_out2 = true;
-}
-#define SPEC_prep_r1_P SPEC_r1_even
-
-static void prep_f1(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->out = fregs[get_field(f, r1)];
- o->g_out = true;
-}
-#define SPEC_prep_f1 0
-
-static void prep_x1(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- int r1 = get_field(f, r1);
- o->out = fregs[r1];
- o->out2 = fregs[r1 + 2];
- o->g_out = o->g_out2 = true;
-}
-#define SPEC_prep_x1 SPEC_r1_f128
-
-/* ====================================================================== */
-/* The "Write OUTput" generators. These generally perform some non-trivial
- copy of data to TCG globals, or to main memory. The trivial cases are
- generally handled by having a "prep" generator install the TCG global
- as the destination of the operation. */
-
-static void wout_r1(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- store_reg(get_field(f, r1), o->out);
-}
-#define SPEC_wout_r1 0
-
-static void wout_r1_8(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- int r1 = get_field(f, r1);
- tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 8);
-}
-#define SPEC_wout_r1_8 0
-
-static void wout_r1_16(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- int r1 = get_field(f, r1);
- tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 16);
-}
-#define SPEC_wout_r1_16 0
-
-static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- store_reg32_i64(get_field(f, r1), o->out);
-}
-#define SPEC_wout_r1_32 0
-
-static void wout_r1_32h(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- store_reg32h_i64(get_field(f, r1), o->out);
-}
-#define SPEC_wout_r1_32h 0
-
-static void wout_r1_P32(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- int r1 = get_field(f, r1);
- store_reg32_i64(r1, o->out);
- store_reg32_i64(r1 + 1, o->out2);
-}
-#define SPEC_wout_r1_P32 SPEC_r1_even
-
-static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- int r1 = get_field(f, r1);
- store_reg32_i64(r1 + 1, o->out);
- tcg_gen_shri_i64(o->out, o->out, 32);
- store_reg32_i64(r1, o->out);
-}
-#define SPEC_wout_r1_D32 SPEC_r1_even
-
-static void wout_e1(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- store_freg32_i64(get_field(f, r1), o->out);
-}
-#define SPEC_wout_e1 0
-
-static void wout_f1(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- store_freg(get_field(f, r1), o->out);
-}
-#define SPEC_wout_f1 0
-
-static void wout_x1(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- int f1 = get_field(s->fields, r1);
- store_freg(f1, o->out);
- store_freg(f1 + 2, o->out2);
-}
-#define SPEC_wout_x1 SPEC_r1_f128
-
-static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- if (get_field(f, r1) != get_field(f, r2)) {
- store_reg32_i64(get_field(f, r1), o->out);
- }
-}
-#define SPEC_wout_cond_r1r2_32 0
-
-static void wout_cond_e1e2(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- if (get_field(f, r1) != get_field(f, r2)) {
- store_freg32_i64(get_field(f, r1), o->out);
- }
-}
-#define SPEC_wout_cond_e1e2 0
-
-static void wout_m1_8(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- tcg_gen_qemu_st8(o->out, o->addr1, get_mem_index(s));
-}
-#define SPEC_wout_m1_8 0
-
-static void wout_m1_16(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- tcg_gen_qemu_st16(o->out, o->addr1, get_mem_index(s));
-}
-#define SPEC_wout_m1_16 0
-
-static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
-}
-#define SPEC_wout_m1_32 0
-
-static void wout_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s));
-}
-#define SPEC_wout_m1_64 0
-
-static void wout_m2_32(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- tcg_gen_qemu_st32(o->out, o->in2, get_mem_index(s));
-}
-#define SPEC_wout_m2_32 0
-
-static void wout_m2_32_r1_atomic(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- /* XXX release reservation */
- tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
- store_reg32_i64(get_field(f, r1), o->in2);
-}
-#define SPEC_wout_m2_32_r1_atomic 0
-
-static void wout_m2_64_r1_atomic(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- /* XXX release reservation */
- tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s));
- store_reg(get_field(f, r1), o->in2);
-}
-#define SPEC_wout_m2_64_r1_atomic 0
-
-/* ====================================================================== */
-/* The "INput 1" generators. These load the first operand to an insn. */
-
-static void in1_r1(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in1 = load_reg(get_field(f, r1));
-}
-#define SPEC_in1_r1 0
-
-static void in1_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in1 = regs[get_field(f, r1)];
- o->g_in1 = true;
-}
-#define SPEC_in1_r1_o 0
-
-static void in1_r1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in1 = tcg_temp_new_i64();
- tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r1)]);
-}
-#define SPEC_in1_r1_32s 0
-
-static void in1_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in1 = tcg_temp_new_i64();
- tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1)]);
-}
-#define SPEC_in1_r1_32u 0
-
-static void in1_r1_sr32(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in1 = tcg_temp_new_i64();
- tcg_gen_shri_i64(o->in1, regs[get_field(f, r1)], 32);
-}
-#define SPEC_in1_r1_sr32 0
-
-static void in1_r1p1(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in1 = load_reg(get_field(f, r1) + 1);
-}
-#define SPEC_in1_r1p1 SPEC_r1_even
-
-static void in1_r1p1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in1 = tcg_temp_new_i64();
- tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r1) + 1]);
-}
-#define SPEC_in1_r1p1_32s SPEC_r1_even
-
-static void in1_r1p1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in1 = tcg_temp_new_i64();
- tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1) + 1]);
-}
-#define SPEC_in1_r1p1_32u SPEC_r1_even
-
-static void in1_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- int r1 = get_field(f, r1);
- o->in1 = tcg_temp_new_i64();
- tcg_gen_concat32_i64(o->in1, regs[r1 + 1], regs[r1]);
-}
-#define SPEC_in1_r1_D32 SPEC_r1_even
-
-static void in1_r2(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in1 = load_reg(get_field(f, r2));
-}
-#define SPEC_in1_r2 0
-
-static void in1_r2_sr32(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in1 = tcg_temp_new_i64();
- tcg_gen_shri_i64(o->in1, regs[get_field(f, r2)], 32);
-}
-#define SPEC_in1_r2_sr32 0
-
-static void in1_r3(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in1 = load_reg(get_field(f, r3));
-}
-#define SPEC_in1_r3 0
-
-static void in1_r3_o(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in1 = regs[get_field(f, r3)];
- o->g_in1 = true;
-}
-#define SPEC_in1_r3_o 0
-
-static void in1_r3_32s(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in1 = tcg_temp_new_i64();
- tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r3)]);
-}
-#define SPEC_in1_r3_32s 0
-
-static void in1_r3_32u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in1 = tcg_temp_new_i64();
- tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r3)]);
-}
-#define SPEC_in1_r3_32u 0
-
-static void in1_r3_D32(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- int r3 = get_field(f, r3);
- o->in1 = tcg_temp_new_i64();
- tcg_gen_concat32_i64(o->in1, regs[r3 + 1], regs[r3]);
-}
-#define SPEC_in1_r3_D32 SPEC_r3_even
-
-static void in1_e1(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in1 = load_freg32_i64(get_field(f, r1));
-}
-#define SPEC_in1_e1 0
-
-static void in1_f1_o(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in1 = fregs[get_field(f, r1)];
- o->g_in1 = true;
-}
-#define SPEC_in1_f1_o 0
-
-static void in1_x1_o(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- int r1 = get_field(f, r1);
- o->out = fregs[r1];
- o->out2 = fregs[r1 + 2];
- o->g_out = o->g_out2 = true;
-}
-#define SPEC_in1_x1_o SPEC_r1_f128
-
-static void in1_f3_o(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in1 = fregs[get_field(f, r3)];
- o->g_in1 = true;
-}
-#define SPEC_in1_f3_o 0
-
-static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
-}
-#define SPEC_in1_la1 0
-
-static void in1_la2(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
- o->addr1 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
-}
-#define SPEC_in1_la2 0
-
-static void in1_m1_8u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- in1_la1(s, f, o);
- o->in1 = tcg_temp_new_i64();
- tcg_gen_qemu_ld8u(o->in1, o->addr1, get_mem_index(s));
-}
-#define SPEC_in1_m1_8u 0
-
-static void in1_m1_16s(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- in1_la1(s, f, o);
- o->in1 = tcg_temp_new_i64();
- tcg_gen_qemu_ld16s(o->in1, o->addr1, get_mem_index(s));
-}
-#define SPEC_in1_m1_16s 0
-
-static void in1_m1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- in1_la1(s, f, o);
- o->in1 = tcg_temp_new_i64();
- tcg_gen_qemu_ld16u(o->in1, o->addr1, get_mem_index(s));
-}
-#define SPEC_in1_m1_16u 0
-
-static void in1_m1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- in1_la1(s, f, o);
- o->in1 = tcg_temp_new_i64();
- tcg_gen_qemu_ld32s(o->in1, o->addr1, get_mem_index(s));
-}
-#define SPEC_in1_m1_32s 0
-
-static void in1_m1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- in1_la1(s, f, o);
- o->in1 = tcg_temp_new_i64();
- tcg_gen_qemu_ld32u(o->in1, o->addr1, get_mem_index(s));
-}
-#define SPEC_in1_m1_32u 0
-
-static void in1_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- in1_la1(s, f, o);
- o->in1 = tcg_temp_new_i64();
- tcg_gen_qemu_ld64(o->in1, o->addr1, get_mem_index(s));
-}
-#define SPEC_in1_m1_64 0
-
-/* ====================================================================== */
-/* The "INput 2" generators. These load the second operand to an insn. */
-
-static void in2_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = regs[get_field(f, r1)];
- o->g_in2 = true;
-}
-#define SPEC_in2_r1_o 0
-
-static void in2_r1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = tcg_temp_new_i64();
- tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r1)]);
-}
-#define SPEC_in2_r1_16u 0
-
-static void in2_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = tcg_temp_new_i64();
- tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r1)]);
-}
-#define SPEC_in2_r1_32u 0
-
-static void in2_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- int r1 = get_field(f, r1);
- o->in2 = tcg_temp_new_i64();
- tcg_gen_concat32_i64(o->in2, regs[r1 + 1], regs[r1]);
-}
-#define SPEC_in2_r1_D32 SPEC_r1_even
-
-static void in2_r2(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = load_reg(get_field(f, r2));
-}
-#define SPEC_in2_r2 0
-
-static void in2_r2_o(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = regs[get_field(f, r2)];
- o->g_in2 = true;
-}
-#define SPEC_in2_r2_o 0
-
-static void in2_r2_nz(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- int r2 = get_field(f, r2);
- if (r2 != 0) {
- o->in2 = load_reg(r2);
- }
-}
-#define SPEC_in2_r2_nz 0
-
-static void in2_r2_8s(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = tcg_temp_new_i64();
- tcg_gen_ext8s_i64(o->in2, regs[get_field(f, r2)]);
-}
-#define SPEC_in2_r2_8s 0
-
-static void in2_r2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = tcg_temp_new_i64();
- tcg_gen_ext8u_i64(o->in2, regs[get_field(f, r2)]);
-}
-#define SPEC_in2_r2_8u 0
-
-static void in2_r2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = tcg_temp_new_i64();
- tcg_gen_ext16s_i64(o->in2, regs[get_field(f, r2)]);
-}
-#define SPEC_in2_r2_16s 0
-
-static void in2_r2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = tcg_temp_new_i64();
- tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r2)]);
-}
-#define SPEC_in2_r2_16u 0
-
-static void in2_r3(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = load_reg(get_field(f, r3));
-}
-#define SPEC_in2_r3 0
-
-static void in2_r3_sr32(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = tcg_temp_new_i64();
- tcg_gen_shri_i64(o->in2, regs[get_field(f, r3)], 32);
-}
-#define SPEC_in2_r3_sr32 0
-
-static void in2_r2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = tcg_temp_new_i64();
- tcg_gen_ext32s_i64(o->in2, regs[get_field(f, r2)]);
-}
-#define SPEC_in2_r2_32s 0
-
-static void in2_r2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = tcg_temp_new_i64();
- tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r2)]);
-}
-#define SPEC_in2_r2_32u 0
-
-static void in2_r2_sr32(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = tcg_temp_new_i64();
- tcg_gen_shri_i64(o->in2, regs[get_field(f, r2)], 32);
-}
-#define SPEC_in2_r2_sr32 0
-
-static void in2_e2(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = load_freg32_i64(get_field(f, r2));
-}
-#define SPEC_in2_e2 0
-
-static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = fregs[get_field(f, r2)];
- o->g_in2 = true;
-}
-#define SPEC_in2_f2_o 0
-
-static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- int r2 = get_field(f, r2);
- o->in1 = fregs[r2];
- o->in2 = fregs[r2 + 2];
- o->g_in1 = o->g_in2 = true;
-}
-#define SPEC_in2_x2_o SPEC_r2_f128
-
-static void in2_ra2(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = get_address(s, 0, get_field(f, r2), 0);
-}
-#define SPEC_in2_ra2 0
-
-static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
- o->in2 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
-}
-#define SPEC_in2_a2 0
-
-static void in2_ri2(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = tcg_const_i64(s->pc + (int64_t)get_field(f, i2) * 2);
-}
-#define SPEC_in2_ri2 0
-
-static void in2_sh32(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- help_l2_shift(s, f, o, 31);
-}
-#define SPEC_in2_sh32 0
-
-static void in2_sh64(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- help_l2_shift(s, f, o, 63);
-}
-#define SPEC_in2_sh64 0
-
-static void in2_m2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- in2_a2(s, f, o);
- tcg_gen_qemu_ld8u(o->in2, o->in2, get_mem_index(s));
-}
-#define SPEC_in2_m2_8u 0
-
-static void in2_m2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- in2_a2(s, f, o);
- tcg_gen_qemu_ld16s(o->in2, o->in2, get_mem_index(s));
-}
-#define SPEC_in2_m2_16s 0
-
-static void in2_m2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- in2_a2(s, f, o);
- tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
-}
-#define SPEC_in2_m2_16u 0
-
-static void in2_m2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- in2_a2(s, f, o);
- tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
-}
-#define SPEC_in2_m2_32s 0
-
-static void in2_m2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- in2_a2(s, f, o);
- tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
-}
-#define SPEC_in2_m2_32u 0
-
-static void in2_m2_64(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- in2_a2(s, f, o);
- tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
-}
-#define SPEC_in2_m2_64 0
-
-static void in2_mri2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- in2_ri2(s, f, o);
- tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
-}
-#define SPEC_in2_mri2_16u 0
-
-static void in2_mri2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- in2_ri2(s, f, o);
- tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
-}
-#define SPEC_in2_mri2_32s 0
-
-static void in2_mri2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- in2_ri2(s, f, o);
- tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
-}
-#define SPEC_in2_mri2_32u 0
-
-static void in2_mri2_64(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- in2_ri2(s, f, o);
- tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
-}
-#define SPEC_in2_mri2_64 0
-
-static void in2_m2_32s_atomic(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- /* XXX should reserve the address */
- in1_la2(s, f, o);
- o->in2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld32s(o->in2, o->addr1, get_mem_index(s));
-}
-#define SPEC_in2_m2_32s_atomic 0
-
-static void in2_m2_64_atomic(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- /* XXX should reserve the address */
- in1_la2(s, f, o);
- o->in2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld64(o->in2, o->addr1, get_mem_index(s));
-}
-#define SPEC_in2_m2_64_atomic 0
-
-static void in2_i2(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = tcg_const_i64(get_field(f, i2));
-}
-#define SPEC_in2_i2 0
-
-static void in2_i2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = tcg_const_i64((uint8_t)get_field(f, i2));
-}
-#define SPEC_in2_i2_8u 0
-
-static void in2_i2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = tcg_const_i64((uint16_t)get_field(f, i2));
-}
-#define SPEC_in2_i2_16u 0
-
-static void in2_i2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = tcg_const_i64((uint32_t)get_field(f, i2));
-}
-#define SPEC_in2_i2_32u 0
-
-static void in2_i2_16u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- uint64_t i2 = (uint16_t)get_field(f, i2);
- o->in2 = tcg_const_i64(i2 << s->insn->data);
-}
-#define SPEC_in2_i2_16u_shl 0
-
-static void in2_i2_32u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- uint64_t i2 = (uint32_t)get_field(f, i2);
- o->in2 = tcg_const_i64(i2 << s->insn->data);
-}
-#define SPEC_in2_i2_32u_shl 0
-
-#ifndef CONFIG_USER_ONLY
-static void in2_insn(DisasContext *s, DisasFields *f, DisasOps *o)
-{
- o->in2 = tcg_const_i64(s->fields->raw_insn);
-}
-#define SPEC_in2_insn 0
-#endif
-
-/* ====================================================================== */
-
-/* Find opc within the table of insns. This is formulated as a switch
- statement so that (1) we get compile-time notice of cut-paste errors
- for duplicated opcodes, and (2) the compiler generates the binary
- 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)
-
-#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) insn_ ## NM,
-
-enum DisasInsnEnum {
-#include "insn-data.def"
-};
-
-#undef D
-#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) { \
- .opc = OPC, \
- .fmt = FMT_##FT, \
- .fac = FAC_##FC, \
- .spec = SPEC_in1_##I1 | SPEC_in2_##I2 | SPEC_prep_##P | SPEC_wout_##W, \
- .name = #NM, \
- .help_in1 = in1_##I1, \
- .help_in2 = in2_##I2, \
- .help_prep = prep_##P, \
- .help_wout = wout_##W, \
- .help_cout = cout_##CC, \
- .help_op = op_##OP, \
- .data = D \
- },
-
-/* Allow 0 to be used for NULL in the table below. */
-#define in1_0 NULL
-#define in2_0 NULL
-#define prep_0 NULL
-#define wout_0 NULL
-#define cout_0 NULL
-#define op_0 NULL
-
-#define SPEC_in1_0 0
-#define SPEC_in2_0 0
-#define SPEC_prep_0 0
-#define SPEC_wout_0 0
-
-static const DisasInsn insn_info[] = {
-#include "insn-data.def"
-};
-
-#undef D
-#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) \
- case OPC: return &insn_info[insn_ ## NM];
-
-static const DisasInsn *lookup_opc(uint16_t opc)
-{
- switch (opc) {
-#include "insn-data.def"
- default:
- return NULL;
- }
-}
-
-#undef D
-#undef C
-
-/* Extract a field from the insn. The INSN should be left-aligned in
- the uint64_t so that we can more easily utilize the big-bit-endian
- definitions we extract from the Principals of Operation. */
-
-static void extract_field(DisasFields *o, const DisasField *f, uint64_t insn)
-{
- uint32_t r, m;
-
- if (f->size == 0) {
- return;
- }
-
- /* Zero extract the field from the insn. */
- r = (insn << f->beg) >> (64 - f->size);
-
- /* Sign-extend, or un-swap the field as necessary. */
- switch (f->type) {
- case 0: /* unsigned */
- break;
- case 1: /* signed */
- assert(f->size <= 32);
- m = 1u << (f->size - 1);
- r = (r ^ m) - m;
- break;
- case 2: /* dl+dh split, signed 20 bit. */
- r = ((int8_t)r << 12) | (r >> 8);
- break;
- default:
- abort();
- }
-
- /* Validate that the "compressed" encoding we selected above is valid.
- I.e. we havn't make two different original fields overlap. */
- assert(((o->presentC >> f->indexC) & 1) == 0);
- o->presentC |= 1 << f->indexC;
- o->presentO |= 1 << f->indexO;
-
- o->c[f->indexC] = r;
-}
-
-/* Lookup the insn at the current PC, extracting the operands into O and
- returning the info struct for the insn. Returns NULL for invalid insn. */
-
-static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s,
- DisasFields *f)
-{
- uint64_t insn, pc = s->pc;
- int op, op2, ilen;
- const DisasInsn *info;
-
- insn = ld_code2(env, pc);
- op = (insn >> 8) & 0xff;
- ilen = get_ilen(op);
- s->next_pc = s->pc + ilen;
-
- switch (ilen) {
- case 2:
- insn = insn << 48;
- break;
- case 4:
- insn = ld_code4(env, pc) << 32;
- break;
- case 6:
- insn = (insn << 48) | (ld_code4(env, pc + 2) << 16);
- break;
- default:
- abort();
- }
-
- /* We can't actually determine the insn format until we've looked up
- the full insn opcode. Which we can't do without locating the
- secondary opcode. Assume by default that OP2 is at bit 40; for
- those smaller insns that don't actually have a secondary opcode
- this will correctly result in OP2 = 0. */
- switch (op) {
- case 0x01: /* E */
- case 0x80: /* S */
- case 0x82: /* S */
- case 0x93: /* S */
- case 0xb2: /* S, RRF, RRE */
- case 0xb3: /* RRE, RRD, RRF */
- case 0xb9: /* RRE, RRF */
- case 0xe5: /* SSE, SIL */
- op2 = (insn << 8) >> 56;
- break;
- case 0xa5: /* RI */
- case 0xa7: /* RI */
- case 0xc0: /* RIL */
- case 0xc2: /* RIL */
- case 0xc4: /* RIL */
- case 0xc6: /* RIL */
- case 0xc8: /* SSF */
- case 0xcc: /* RIL */
- op2 = (insn << 12) >> 60;
- break;
- case 0xd0 ... 0xdf: /* SS */
- case 0xe1: /* SS */
- case 0xe2: /* SS */
- case 0xe8: /* SS */
- case 0xe9: /* SS */
- case 0xea: /* SS */
- case 0xee ... 0xf3: /* SS */
- case 0xf8 ... 0xfd: /* SS */
- op2 = 0;
- break;
- default:
- op2 = (insn << 40) >> 56;
- break;
- }
-
- memset(f, 0, sizeof(*f));
- f->raw_insn = insn;
- f->op = op;
- f->op2 = op2;
-
- /* Lookup the instruction. */
- info = lookup_opc(op << 8 | op2);
-
- /* If we found it, extract the operands. */
- if (info != NULL) {
- DisasFormat fmt = info->fmt;
- int i;
-
- for (i = 0; i < NUM_C_FIELD; ++i) {
- extract_field(f, &format_info[fmt].op[i], insn);
- }
- }
- return info;
-}
-
-static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
-{
- const DisasInsn *insn;
- ExitStatus ret = NO_EXIT;
- DisasFields f;
- DisasOps o;
-
- /* Search for the insn in the table. */
- insn = extract_insn(env, s, &f);
-
- /* Not found means unimplemented/illegal opcode. */
- if (insn == NULL) {
- qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%02x%02x\n",
- f.op, f.op2);
- gen_illegal_opcode(s);
- return EXIT_NORETURN;
- }
-
-#ifndef CONFIG_USER_ONLY
- if (s->tb->flags & FLAG_MASK_PER) {
- TCGv_i64 addr = tcg_const_i64(s->pc);
- gen_helper_per_ifetch(cpu_env, addr);
- tcg_temp_free_i64(addr);
- }
-#endif
-
- /* 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);
- return EXIT_NORETURN;
- }
- }
-
- /* Set up the strutures we use to communicate with the helpers. */
- s->insn = insn;
- s->fields = &f;
- o.g_out = o.g_out2 = o.g_in1 = o.g_in2 = false;
- TCGV_UNUSED_I64(o.out);
- TCGV_UNUSED_I64(o.out2);
- TCGV_UNUSED_I64(o.in1);
- TCGV_UNUSED_I64(o.in2);
- TCGV_UNUSED_I64(o.addr1);
-
- /* Implement the instruction. */
- if (insn->help_in1) {
- insn->help_in1(s, &f, &o);
- }
- if (insn->help_in2) {
- insn->help_in2(s, &f, &o);
- }
- if (insn->help_prep) {
- insn->help_prep(s, &f, &o);
- }
- if (insn->help_op) {
- ret = insn->help_op(s, &o);
- }
- if (insn->help_wout) {
- insn->help_wout(s, &f, &o);
- }
- if (insn->help_cout) {
- insn->help_cout(s, &o);
- }
-
- /* Free any temporaries created by the helpers. */
- if (!TCGV_IS_UNUSED_I64(o.out) && !o.g_out) {
- tcg_temp_free_i64(o.out);
- }
- if (!TCGV_IS_UNUSED_I64(o.out2) && !o.g_out2) {
- tcg_temp_free_i64(o.out2);
- }
- if (!TCGV_IS_UNUSED_I64(o.in1) && !o.g_in1) {
- tcg_temp_free_i64(o.in1);
- }
- if (!TCGV_IS_UNUSED_I64(o.in2) && !o.g_in2) {
- tcg_temp_free_i64(o.in2);
- }
- if (!TCGV_IS_UNUSED_I64(o.addr1)) {
- tcg_temp_free_i64(o.addr1);
- }
-
-#ifndef CONFIG_USER_ONLY
- if (s->tb->flags & FLAG_MASK_PER) {
- /* An exception might be triggered, save PSW if not already done. */
- if (ret == NO_EXIT || ret == EXIT_PC_STALE) {
- tcg_gen_movi_i64(psw_addr, s->next_pc);
- }
-
- /* Save off cc. */
- update_cc_op(s);
-
- /* Call the helper to check for a possible PER exception. */
- gen_helper_per_check_exception(cpu_env);
- }
-#endif
-
- /* Advance to the next instruction. */
- s->pc = s->next_pc;
- return ret;
-}
-
-void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb)
-{
- S390CPU *cpu = s390_env_get_cpu(env);
- CPUState *cs = CPU(cpu);
- DisasContext dc;
- target_ulong pc_start;
- uint64_t next_page_start;
- int num_insns, max_insns;
- ExitStatus status;
- bool do_debug;
-
- pc_start = tb->pc;
-
- /* 31-bit mode */
- if (!(tb->flags & FLAG_MASK_64)) {
- pc_start &= 0x7fffffff;
- }
-
- dc.tb = tb;
- dc.pc = pc_start;
- dc.cc_op = CC_OP_DYNAMIC;
- do_debug = dc.singlestep_enabled = cs->singlestep_enabled;
-
- next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
-
- num_insns = 0;
- max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0) {
- max_insns = CF_COUNT_MASK;
- }
- if (max_insns > TCG_MAX_INSNS) {
- max_insns = TCG_MAX_INSNS;
- }
-
- gen_tb_start(tb);
-
- do {
- tcg_gen_insn_start(dc.pc, dc.cc_op);
- num_insns++;
-
- if (unlikely(cpu_breakpoint_test(cs, dc.pc, BP_ANY))) {
- status = EXIT_PC_STALE;
- do_debug = true;
- /* The address covered by the breakpoint must be included in
- [tb->pc, tb->pc + tb->size) in order to for it to be
- properly cleared -- thus we increment the PC here so that
- the logic setting tb->size below does the right thing. */
- dc.pc += 2;
- break;
- }
-
- if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
- gen_io_start();
- }
-
- status = NO_EXIT;
- if (status == NO_EXIT) {
- status = translate_one(env, &dc);
- }
-
- /* If we reach a page boundary, are single stepping,
- or exhaust instruction count, stop generation. */
- if (status == NO_EXIT
- && (dc.pc >= next_page_start
- || tcg_op_buf_full()
- || num_insns >= max_insns
- || singlestep
- || cs->singlestep_enabled)) {
- status = EXIT_PC_STALE;
- }
- } while (status == NO_EXIT);
-
- if (tb->cflags & CF_LAST_IO) {
- gen_io_end();
- }
-
- switch (status) {
- case EXIT_GOTO_TB:
- case EXIT_NORETURN:
- break;
- case EXIT_PC_STALE:
- update_psw_addr(&dc);
- /* FALLTHRU */
- case EXIT_PC_UPDATED:
- /* Next TB starts off with CC_OP_DYNAMIC, so make sure the
- cc op type is in env */
- update_cc_op(&dc);
- /* Exit the TB, either by raising a debug exception or by return. */
- if (do_debug) {
- gen_exception(EXCP_DEBUG);
- } else {
- tcg_gen_exit_tb(0);
- }
- break;
- default:
- abort();
- }
-
- gen_tb_end(tb, num_insns);
-
- tb->size = dc.pc - pc_start;
- tb->icount = num_insns;
-
-#if defined(S390X_DEBUG_DISAS)
- if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
- qemu_log("IN: %s\n", lookup_symbol(pc_start));
- log_target_disas(cs, pc_start, dc.pc - pc_start, 1);
- qemu_log("\n");
- }
-#endif
-}
-
-void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb,
- target_ulong *data)
-{
- int cc_op = data[1];
- env->psw.addr = data[0];
- if ((cc_op != CC_OP_DYNAMIC) && (cc_op != CC_OP_STATIC)) {
- env->cc_op = cc_op;
- }
-}