mirror of https://gitee.com/openkylin/qemu.git
Queued s390 patches
-----BEGIN PGP SIGNATURE----- iQEcBAABAgAGBQJZN0ZVAAoJEK0ScMxN0CebytMIAIwTia8mBPc7Oa42F4OBvv5y jX8vTnI63Xg7TfLQVlufk69xvJw6z+xagPlHVJcpINtxXQhg7ER3Gc4Ny0U9cmAj Sw7Es4ErxYizs11mZotAxcXU71paLoJ+kDa/l7HGni//6GQ7qIlFyvBjS26FQD9/ V6ZiQxEprgpGVjNbTwRFrJpVu8tSi/bHXkPJWW6PZ6qfFJBS85mT0xsS7pCHCQAL rxGtoS2cPU5sqP7jrNNJkc95Hkzp+ffYdF5JtBOcH7Nf8G8UkLzopdlE3Z6YqvV7 ABawNcRSBDEs7O2CIRnB6AlISWV19TUjCjW3gKiSaS+p08flAdHHrGJ/w5hHAY0= =3bqT -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/rth/tags/pull-s390-20170606' into staging Queued s390 patches # gpg: Signature made Wed 07 Jun 2017 01:18:29 BST # gpg: using RSA key 0xAD1270CC4DD0279B # gpg: Good signature from "Richard Henderson <rth7680@gmail.com>" # gpg: aka "Richard Henderson <rth@redhat.com>" # gpg: aka "Richard Henderson <rth@twiddle.net>" # Primary key fingerprint: 9CB1 8DDA F8E8 49AD 2AFC 16A4 AD12 70CC 4DD0 279B * remotes/rth/tags/pull-s390-20170606: (70 commits) target/s390x: addressing exceptions are suppressing target/s390x: mark ETF2 and ETF2-ENH facilities as available target/s390x: check alignment in CDSG in the !CONFIG_ATOMIC128 case target/s390x: implement STORE PAIR TO QUADWORD target/s390x: implement LOAD PAIR FROM QUADWORD target/s390x: implement TRANSLATE ONE/TWO TO ONE/TWO target/s390x: implement TEST DECIMAL target/s390x: implement UNPACK UNICODE target/s390x: implement UNPACK ASCII target/s390x: implement PACK UNICODE target/s390x: implement PACK ASCII target/s390x: implement MOVE LONG UNICODE target/s390x: implement COMPARE LOGICAL LONG UNICODE target/s390x: improve MOVE LONG and MOVE LONG EXTENDED target/s390x: fix adj_len_to_page target/s390x: implement COMPARE LOGICAL LONG target/s390x: fix COMPARE LOGICAL LONG EXTENDED target/s390x: improve 24-bit and 31-bit lengths read/write target/s390x: improve 24-bit and 31-bit addresses write target/s390x: improve 24-bit and 31-bit addresses read ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
8b3e9ca74c
|
@ -107,6 +107,8 @@ typedef struct CPUS390XState {
|
|||
uint64_t cc_dst;
|
||||
uint64_t cc_vr;
|
||||
|
||||
uint64_t ex_value;
|
||||
|
||||
uint64_t __excp_addr;
|
||||
uint64_t psa;
|
||||
|
||||
|
@ -393,7 +395,7 @@ static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc,
|
|||
target_ulong *cs_base, uint32_t *flags)
|
||||
{
|
||||
*pc = env->psw.addr;
|
||||
*cs_base = 0;
|
||||
*cs_base = env->ex_value;
|
||||
*flags = ((env->psw.mask >> 32) & ~FLAG_MASK_CC) |
|
||||
((env->psw.mask & PSW_MASK_32) ? FLAG_MASK_32 : 0);
|
||||
}
|
||||
|
@ -1033,6 +1035,8 @@ struct sysib_322 {
|
|||
#define _SEGMENT_ENTRY_RO 0x200 /* page protection bit */
|
||||
#define _SEGMENT_ENTRY_INV 0x20 /* invalid segment table entry */
|
||||
|
||||
#define VADDR_PX 0xff000 /* page index bits */
|
||||
|
||||
#define _PAGE_RO 0x200 /* HW read-only bit */
|
||||
#define _PAGE_INVALID 0x400 /* HW invalid bit */
|
||||
#define _PAGE_RES0 0x800 /* bit must be zero */
|
||||
|
@ -1084,6 +1088,7 @@ struct sysib_322 {
|
|||
#define SIGP_ORDER_MASK 0x000000ff
|
||||
|
||||
void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr);
|
||||
target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr);
|
||||
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);
|
||||
|
|
|
@ -658,6 +658,32 @@ static void check_compatibility(const S390CPUModel *max_model,
|
|||
"available in the configuration: ");
|
||||
}
|
||||
|
||||
/**
|
||||
* The base TCG CPU model "qemu" is based on the z900. However, we already
|
||||
* can also emulate some additional features of later CPU generations, so
|
||||
* we add these additional feature bits here.
|
||||
*/
|
||||
static void add_qemu_cpu_model_features(S390FeatBitmap fbm)
|
||||
{
|
||||
static const int feats[] = {
|
||||
S390_FEAT_STFLE,
|
||||
S390_FEAT_EXTENDED_IMMEDIATE,
|
||||
S390_FEAT_EXTENDED_TRANSLATION_2,
|
||||
S390_FEAT_LONG_DISPLACEMENT,
|
||||
S390_FEAT_LONG_DISPLACEMENT_FAST,
|
||||
S390_FEAT_ETF2_ENH,
|
||||
S390_FEAT_STORE_CLOCK_FAST,
|
||||
S390_FEAT_GENERAL_INSTRUCTIONS_EXT,
|
||||
S390_FEAT_EXECUTE_EXT,
|
||||
S390_FEAT_STFLE_45,
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(feats); i++) {
|
||||
set_bit(feats[i], fbm);
|
||||
}
|
||||
}
|
||||
|
||||
static S390CPUModel *get_max_cpu_model(Error **errp)
|
||||
{
|
||||
static S390CPUModel max_model;
|
||||
|
@ -670,10 +696,11 @@ static S390CPUModel *get_max_cpu_model(Error **errp)
|
|||
if (kvm_enabled()) {
|
||||
kvm_s390_get_host_cpu_model(&max_model, errp);
|
||||
} else {
|
||||
/* TCG emulates a z900 */
|
||||
/* TCG emulates a z900 (with some optional additional features) */
|
||||
max_model.def = &s390_cpu_defs[0];
|
||||
bitmap_copy(max_model.features, max_model.def->default_feat,
|
||||
S390_FEAT_MAX);
|
||||
add_qemu_cpu_model_features(max_model.features);
|
||||
}
|
||||
if (!*errp) {
|
||||
cached = true;
|
||||
|
@ -925,11 +952,14 @@ static void s390_host_cpu_model_initfn(Object *obj)
|
|||
|
||||
static void s390_qemu_cpu_model_initfn(Object *obj)
|
||||
{
|
||||
static S390CPUDef s390_qemu_cpu_defs;
|
||||
S390CPU *cpu = S390_CPU(obj);
|
||||
|
||||
cpu->model = g_malloc0(sizeof(*cpu->model));
|
||||
/* TCG emulates a z900 */
|
||||
cpu->model->def = &s390_cpu_defs[0];
|
||||
/* TCG emulates a z900 (with some optional additional features) */
|
||||
memcpy(&s390_qemu_cpu_defs, &s390_cpu_defs[0], sizeof(s390_qemu_cpu_defs));
|
||||
add_qemu_cpu_model_features(s390_qemu_cpu_defs.full_feat);
|
||||
cpu->model->def = &s390_qemu_cpu_defs;
|
||||
bitmap_copy(cpu->model->features, cpu->model->def->default_feat,
|
||||
S390_FEAT_MAX);
|
||||
}
|
||||
|
|
|
@ -585,6 +585,33 @@ uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
|
|||
return RET128(ret);
|
||||
}
|
||||
|
||||
/* 32-bit FP compare and signal */
|
||||
uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
|
||||
{
|
||||
int cmp = float32_compare(f1, f2, &env->fpu_status);
|
||||
handle_exceptions(env, GETPC());
|
||||
return float_comp_to_cc(env, cmp);
|
||||
}
|
||||
|
||||
/* 64-bit FP compare and signal */
|
||||
uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
|
||||
{
|
||||
int cmp = float64_compare(f1, f2, &env->fpu_status);
|
||||
handle_exceptions(env, GETPC());
|
||||
return float_comp_to_cc(env, cmp);
|
||||
}
|
||||
|
||||
/* 128-bit FP compare and signal */
|
||||
uint32_t HELPER(kxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
|
||||
uint64_t bh, uint64_t bl)
|
||||
{
|
||||
int cmp = float128_compare(make_float128(ah, al),
|
||||
make_float128(bh, bl),
|
||||
&env->fpu_status);
|
||||
handle_exceptions(env, GETPC());
|
||||
return float_comp_to_cc(env, cmp);
|
||||
}
|
||||
|
||||
/* 32-bit FP multiply and add */
|
||||
uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
|
||||
uint64_t f2, uint64_t f3)
|
||||
|
|
|
@ -204,7 +204,7 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr,
|
|||
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);
|
||||
trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_LATER_INC);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -642,6 +642,11 @@ bool s390_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
|||
S390CPU *cpu = S390_CPU(cs);
|
||||
CPUS390XState *env = &cpu->env;
|
||||
|
||||
if (env->ex_value) {
|
||||
/* Execution of the target insn is indivisible from
|
||||
the parent EXECUTE insn. */
|
||||
return false;
|
||||
}
|
||||
if (env->psw.mask & PSW_MASK_EXT) {
|
||||
s390_cpu_do_interrupt(cs);
|
||||
return true;
|
||||
|
|
|
@ -3,8 +3,10 @@ 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(mvcin, 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_3(clcl, 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)
|
||||
|
@ -12,13 +14,18 @@ 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_FLAGS_4(mvn, TCG_CALL_NO_WG, void, env, i32, i64, i64)
|
||||
DEF_HELPER_FLAGS_4(mvo, TCG_CALL_NO_WG, void, env, i32, i64, i64)
|
||||
DEF_HELPER_FLAGS_4(mvpg, TCG_CALL_NO_WG, i32, env, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_4(mvz, TCG_CALL_NO_WG, void, env, i32, i64, i64)
|
||||
DEF_HELPER_4(mvst, i64, env, i64, i64, i64)
|
||||
DEF_HELPER_5(ex, i32, env, i32, i64, i64, i64)
|
||||
DEF_HELPER_4(ex, void, env, i32, 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(mvclu, i32, env, i32, i64, i32)
|
||||
DEF_HELPER_4(clcle, i32, env, i32, i64, i32)
|
||||
DEF_HELPER_4(clclu, 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)
|
||||
|
@ -49,6 +56,9 @@ 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(keb, TCG_CALL_NO_WG, i32, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(kdb, TCG_CALL_NO_WG, i32, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_5(kxb, TCG_CALL_NO_WG, 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)
|
||||
|
@ -75,10 +85,17 @@ 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(pack, TCG_CALL_NO_WG, void, env, i32, i64, i64)
|
||||
DEF_HELPER_FLAGS_4(pka, TCG_CALL_NO_WG, void, env, i64, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(pku, TCG_CALL_NO_WG, void, env, i64, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(unpk, TCG_CALL_NO_WG, void, env, i32, i64, i64)
|
||||
DEF_HELPER_FLAGS_4(unpka, TCG_CALL_NO_WG, i32, env, i64, i32, i64)
|
||||
DEF_HELPER_FLAGS_4(unpku, TCG_CALL_NO_WG, i32, env, i64, i32, i64)
|
||||
DEF_HELPER_FLAGS_3(tp, TCG_CALL_NO_WG, i32, env, i64, i32)
|
||||
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_5(trXX, i32, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64)
|
||||
|
@ -86,6 +103,8 @@ DEF_HELPER_FLAGS_2(sfas, TCG_CALL_NO_WG, void, env, i64)
|
|||
DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_NO_RWG_SE, i64, i64)
|
||||
DEF_HELPER_FLAGS_1(stfl, TCG_CALL_NO_RWG, void, env)
|
||||
DEF_HELPER_2(stfle, i32, env, i64)
|
||||
DEF_HELPER_FLAGS_2(lpq, TCG_CALL_NO_WG, i64, env, i64)
|
||||
DEF_HELPER_FLAGS_4(stpq, TCG_CALL_NO_WG, void, env, i64, i64, i64)
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
DEF_HELPER_3(servc, i32, env, i64, i64)
|
||||
|
@ -102,17 +121,18 @@ 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(testblock, TCG_CALL_NO_WG, i32, env, i64)
|
||||
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_4(ipte, TCG_CALL_NO_RWG, void, env, i64, i64, i32)
|
||||
DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_NO_RWG, void, env)
|
||||
DEF_HELPER_FLAGS_1(purge, 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)
|
||||
|
|
|
@ -154,6 +154,12 @@
|
|||
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 AND SIGNAL */
|
||||
C(0xb308, KEBR, RRE, Z, e1, e2, 0, 0, keb, 0)
|
||||
C(0xb318, KDBR, RRE, Z, f1_o, f2_o, 0, 0, kdb, 0)
|
||||
C(0xb348, KXBR, RRE, Z, x1_o, x2_o, 0, 0, kxb, 0)
|
||||
C(0xed08, KEB, RXE, Z, e1, m2_32u, 0, 0, keb, 0)
|
||||
C(0xed18, KDB, RXE, Z, f1_o, m2_64, 0, 0, kdb, 0)
|
||||
/* 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)
|
||||
|
@ -210,8 +216,12 @@
|
|||
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 */
|
||||
C(0x0f00, CLCL, RR_a, Z, 0, 0, 0, 0, clcl, 0)
|
||||
/* COMPARE LOGICAL LONG EXTENDED */
|
||||
C(0xa900, CLCLE, RS_a, Z, 0, a2, 0, 0, clcle, 0)
|
||||
/* COMPARE LOGICAL LONG UNICODE */
|
||||
C(0xeb8f, CLCLU, RSY_a, E2, 0, a2, 0, 0, clclu, 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)
|
||||
|
@ -327,9 +337,9 @@
|
|||
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)
|
||||
C(0x4400, EX, RX_a, Z, 0, a2, 0, 0, ex, 0)
|
||||
/* EXECUTE RELATIVE LONG */
|
||||
C(0xc600, EXRL, RIL_b, EE, r1_o, ri2, 0, 0, ex, 0)
|
||||
C(0xc600, EXRL, RIL_b, EE, 0, ri2, 0, 0, ex, 0)
|
||||
|
||||
/* EXTRACT ACCESS */
|
||||
C(0xb24f, EAR, RRE, Z, 0, 0, new, r1_32, ear, 0)
|
||||
|
@ -507,6 +517,8 @@
|
|||
/* LOAD PAIR DISJOINT */
|
||||
D(0xc804, LPD, SSF, ILA, 0, 0, new_P, r3_P32, lpd, 0, MO_TEUL)
|
||||
D(0xc805, LPDG, SSF, ILA, 0, 0, new_P, r3_P64, lpd, 0, MO_TEQ)
|
||||
/* LOAD PAIR FROM QUADWORD */
|
||||
C(0xe38f, LPQ, RXY_a, Z, 0, a2, r1_P, 0, lpq, 0)
|
||||
/* 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)
|
||||
|
@ -564,14 +576,26 @@
|
|||
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 INVERSE */
|
||||
C(0xe800, MVCIN, SS_a, Z, la1, a2, 0, 0, mvcin, 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 LONG UNICODE */
|
||||
C(0xeb8e, MVCLU, RSY_a, E2, 0, a2, 0, 0, mvclu, 0)
|
||||
/* MOVE NUMERICS */
|
||||
C(0xd100, MVN, SS_a, Z, la1, a2, 0, 0, mvn, 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)
|
||||
/* MOVE WITH OFFSET */
|
||||
/* 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(0xf100, MVO, SS_a, Z, la1, a2, 0, 0, mvo, 0)
|
||||
/* MOVE ZONES */
|
||||
C(0xd300, MVZ, SS_a, Z, la1, a2, 0, 0, mvz, 0)
|
||||
|
||||
/* MULTIPLY */
|
||||
C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0)
|
||||
|
@ -639,6 +663,15 @@
|
|||
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)
|
||||
|
||||
/* PACK */
|
||||
/* 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(0xf200, PACK, SS_a, Z, la1, a2, 0, 0, pack, 0)
|
||||
/* PACK ASCII */
|
||||
C(0xe900, PKA, SS_f, E2, la1, a2, 0, 0, pka, 0)
|
||||
/* PACK UNICODE */
|
||||
C(0xe100, PKU, SS_f, E2, la1, a2, 0, 0, pku, 0)
|
||||
|
||||
/* PREFETCH */
|
||||
/* Implemented as nops of course. */
|
||||
C(0xe336, PFD, RXY_b, GIE, 0, 0, 0, 0, 0, 0)
|
||||
|
@ -763,6 +796,8 @@
|
|||
/* 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)
|
||||
/* STORE PAIR TO QUADWORD */
|
||||
C(0xe38e, STPQ, RXY_a, Z, 0, a2, r1_P, 0, stpq, 0)
|
||||
|
||||
/* SUBTRACT */
|
||||
C(0x1b00, SR, RR_a, Z, r1, r2, new, r1_32, sub, subs32)
|
||||
|
@ -810,11 +845,20 @@
|
|||
/* SUPERVISOR CALL */
|
||||
C(0x0a00, SVC, I, Z, 0, 0, 0, 0, svc, 0)
|
||||
|
||||
/* TEST ADDRESSING MODE */
|
||||
C(0x010b, TAM, E, Z, 0, 0, 0, 0, tam, 0)
|
||||
|
||||
/* TEST AND SET */
|
||||
C(0x9300, TS, S, Z, 0, a2, 0, 0, ts, 0)
|
||||
|
||||
/* TEST DATA CLASS */
|
||||
C(0xed10, TCEB, RXE, Z, e1, a2, 0, 0, tceb, 0)
|
||||
C(0xed11, TCDB, RXE, Z, f1_o, a2, 0, 0, tcdb, 0)
|
||||
C(0xed12, TCXB, RXE, Z, x1_o, a2, 0, 0, tcxb, 0)
|
||||
|
||||
/* TEST DECIMAL */
|
||||
C(0xebc0, TP, RSL, E2, la1, 0, 0, 0, tp, 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)
|
||||
|
@ -830,14 +874,28 @@
|
|||
/* TRANSLATE EXTENDED */
|
||||
C(0xb2a5, TRE, RRE, Z, 0, r2, r1_P, 0, tre, 0)
|
||||
|
||||
/* TRANSLATE ONE TO ONE */
|
||||
C(0xb993, TROO, RRF_c, E2, 0, 0, 0, 0, trXX, 0)
|
||||
/* TRANSLATE ONE TO TWO */
|
||||
C(0xb992, TROT, RRF_c, E2, 0, 0, 0, 0, trXX, 0)
|
||||
/* TRANSLATE TWO TO ONE */
|
||||
C(0xb991, TRTO, RRF_c, E2, 0, 0, 0, 0, trXX, 0)
|
||||
/* TRANSLATE TWO TO TWO */
|
||||
C(0xb990, TRTT, RRF_c, E2, 0, 0, 0, 0, trXX, 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)
|
||||
/* UNPACK ASCII */
|
||||
C(0xea00, UNPKA, SS_a, E2, la1, a2, 0, 0, unpka, 0)
|
||||
/* UNPACK UNICODE */
|
||||
C(0xe200, UNPKU, SS_a, E2, la1, a2, 0, 0, unpku, 0)
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* COMPARE AND SWAP AND PURGE */
|
||||
C(0xb250, CSP, RRE, Z, 0, ra2, 0, 0, csp, 0)
|
||||
D(0xb250, CSP, RRE, Z, r1_32u, ra2, r1_P, 0, csp, 0, MO_TEUL)
|
||||
D(0xb98a, CSPG, RRE, DAT_ENH, r1_o, ra2, r1_P, 0, csp, 0, MO_TEQ)
|
||||
/* DIAGNOSE (KVM hypercall) */
|
||||
C(0x8300, DIAG, RSI, Z, 0, 0, 0, 0, diag, 0)
|
||||
/* INSERT STORAGE KEY EXTENDED */
|
||||
|
@ -918,6 +976,8 @@
|
|||
/* 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 BLOCK */
|
||||
C(0xb22c, TB, RRE, Z, 0, r2_o, 0, 0, testblock, 0)
|
||||
/* TEST PROTECTION */
|
||||
C(0xe501, TPROT, SSE, Z, la1, a2, 0, 0, tprot, 0)
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ static int cpu_post_load(void *opaque, int version_id)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cpu_pre_save(void *opaque)
|
||||
{
|
||||
S390CPU *cpu = opaque;
|
||||
|
@ -156,6 +157,23 @@ const VMStateDescription vmstate_riccb = {
|
|||
}
|
||||
};
|
||||
|
||||
static bool exval_needed(void *opaque)
|
||||
{
|
||||
S390CPU *cpu = opaque;
|
||||
return cpu->env.ex_value != 0;
|
||||
}
|
||||
|
||||
const VMStateDescription vmstate_exval = {
|
||||
.name = "cpu/exval",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = exval_needed,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT64(env.ex_value, S390CPU),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
const VMStateDescription vmstate_s390_cpu = {
|
||||
.name = "cpu",
|
||||
.post_load = cpu_post_load,
|
||||
|
@ -188,6 +206,7 @@ const VMStateDescription vmstate_s390_cpu = {
|
|||
&vmstate_fpu,
|
||||
&vmstate_vregs,
|
||||
&vmstate_riccb,
|
||||
&vmstate_exval,
|
||||
NULL
|
||||
},
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -80,8 +80,6 @@ void HELPER(exception)(CPUS390XState *env, uint32_t 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);
|
||||
|
@ -108,6 +106,8 @@ void program_interrupt(CPUS390XState *env, uint32_t code, int ilen)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
/* SCLP service call */
|
||||
uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2)
|
||||
{
|
||||
|
|
|
@ -108,7 +108,7 @@ static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
|
|||
* Translate real address to absolute (= physical)
|
||||
* address by taking care of the prefix mapping.
|
||||
*/
|
||||
static target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr)
|
||||
target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr)
|
||||
{
|
||||
if (raddr < 0x2000) {
|
||||
return raddr + env->psa; /* Map the lowcore. */
|
||||
|
@ -143,8 +143,6 @@ static int mmu_translate_pte(CPUS390XState *env, target_ulong vaddr,
|
|||
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,
|
||||
|
|
|
@ -57,7 +57,9 @@ struct DisasContext {
|
|||
struct TranslationBlock *tb;
|
||||
const DisasInsn *insn;
|
||||
DisasFields *fields;
|
||||
uint64_t ex_value;
|
||||
uint64_t pc, next_pc;
|
||||
uint32_t ilen;
|
||||
enum cc_op cc_op;
|
||||
bool singlestep_enabled;
|
||||
};
|
||||
|
@ -349,7 +351,7 @@ static void gen_program_exception(DisasContext *s, int 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);
|
||||
tmp = tcg_const_i32(s->ilen);
|
||||
tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilen));
|
||||
tcg_temp_free_i32(tmp);
|
||||
|
||||
|
@ -1167,6 +1169,8 @@ typedef enum {
|
|||
the PC (for whatever reason), so there's no need to do it again on
|
||||
exiting the TB. */
|
||||
EXIT_PC_UPDATED,
|
||||
/* We have updated the PC and CC values. */
|
||||
EXIT_PC_CC_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,
|
||||
|
@ -1200,6 +1204,8 @@ typedef enum DisasFacility {
|
|||
FAC_SFLE, /* store facility list extended */
|
||||
FAC_ILA, /* interlocked access facility 1 */
|
||||
FAC_LPP, /* load-program-parameter */
|
||||
FAC_DAT_ENH, /* DAT-enhancement */
|
||||
FAC_E2, /* extended-translation facility 2 */
|
||||
} DisasFacility;
|
||||
|
||||
struct DisasInsn {
|
||||
|
@ -1871,7 +1877,6 @@ 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);
|
||||
|
@ -1906,7 +1911,6 @@ static ExitStatus op_clc(DisasContext *s, DisasOps *o)
|
|||
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);
|
||||
|
@ -1917,14 +1921,65 @@ static ExitStatus op_clc(DisasContext *s, DisasOps *o)
|
|||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_clcl(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int r1 = get_field(s->fields, r1);
|
||||
int r2 = get_field(s->fields, r2);
|
||||
TCGv_i32 t1, t2;
|
||||
|
||||
/* r1 and r2 must be even. */
|
||||
if (r1 & 1 || r2 & 1) {
|
||||
gen_program_exception(s, PGM_SPECIFICATION);
|
||||
return EXIT_NORETURN;
|
||||
}
|
||||
|
||||
t1 = tcg_const_i32(r1);
|
||||
t2 = tcg_const_i32(r2);
|
||||
gen_helper_clcl(cc_op, cpu_env, t1, t2);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t2);
|
||||
set_cc_static(s);
|
||||
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);
|
||||
int r1 = get_field(s->fields, r1);
|
||||
int r3 = get_field(s->fields, r3);
|
||||
TCGv_i32 t1, t3;
|
||||
|
||||
/* r1 and r3 must be even. */
|
||||
if (r1 & 1 || r3 & 1) {
|
||||
gen_program_exception(s, PGM_SPECIFICATION);
|
||||
return EXIT_NORETURN;
|
||||
}
|
||||
|
||||
t1 = tcg_const_i32(r1);
|
||||
t3 = tcg_const_i32(r3);
|
||||
gen_helper_clcle(cc_op, cpu_env, t1, o->in2, t3);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t3);
|
||||
set_cc_static(s);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_clclu(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int r1 = get_field(s->fields, r1);
|
||||
int r3 = get_field(s->fields, r3);
|
||||
TCGv_i32 t1, t3;
|
||||
|
||||
/* r1 and r3 must be even. */
|
||||
if (r1 & 1 || r3 & 1) {
|
||||
gen_program_exception(s, PGM_SPECIFICATION);
|
||||
return EXIT_NORETURN;
|
||||
}
|
||||
|
||||
t1 = tcg_const_i32(r1);
|
||||
t3 = tcg_const_i32(r3);
|
||||
gen_helper_clclu(cc_op, cpu_env, t1, o->in2, t3);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t3);
|
||||
set_cc_static(s);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
@ -1934,7 +1989,6 @@ 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);
|
||||
|
@ -1944,7 +1998,6 @@ static ExitStatus op_clm(DisasContext *s, DisasOps *o)
|
|||
|
||||
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);
|
||||
|
@ -2011,11 +2064,45 @@ static ExitStatus op_cdsg(DisasContext *s, DisasOps *o)
|
|||
#ifndef CONFIG_USER_ONLY
|
||||
static ExitStatus op_csp(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
|
||||
TCGMemOp mop = s->insn->data;
|
||||
TCGv_i64 addr, old, cc;
|
||||
TCGLabel *lab = gen_new_label();
|
||||
|
||||
/* Note that in1 = R1 (zero-extended expected value),
|
||||
out = R1 (original reg), out2 = R1+1 (new value). */
|
||||
|
||||
check_privileged(s);
|
||||
gen_helper_csp(cc_op, cpu_env, r1, o->in2);
|
||||
tcg_temp_free_i32(r1);
|
||||
set_cc_static(s);
|
||||
addr = tcg_temp_new_i64();
|
||||
old = tcg_temp_new_i64();
|
||||
tcg_gen_andi_i64(addr, o->in2, -1ULL << (mop & MO_SIZE));
|
||||
tcg_gen_atomic_cmpxchg_i64(old, addr, o->in1, o->out2,
|
||||
get_mem_index(s), mop | MO_ALIGN);
|
||||
tcg_temp_free_i64(addr);
|
||||
|
||||
/* Are the memory and expected values (un)equal? */
|
||||
cc = tcg_temp_new_i64();
|
||||
tcg_gen_setcond_i64(TCG_COND_NE, cc, o->in1, old);
|
||||
tcg_gen_extrl_i64_i32(cc_op, cc);
|
||||
|
||||
/* Write back the output now, so that it happens before the
|
||||
following branch, so that we don't need local temps. */
|
||||
if ((mop & MO_SIZE) == MO_32) {
|
||||
tcg_gen_deposit_i64(o->out, o->out, old, 0, 32);
|
||||
} else {
|
||||
tcg_gen_mov_i64(o->out, old);
|
||||
}
|
||||
tcg_temp_free_i64(old);
|
||||
|
||||
/* If the comparison was equal, and the LSB of R2 was set,
|
||||
then we need to flush the TLB (for all cpus). */
|
||||
tcg_gen_xori_i64(cc, cc, 1);
|
||||
tcg_gen_and_i64(cc, cc, o->in2);
|
||||
tcg_gen_brcondi_i64(TCG_COND_EQ, cc, 0, lab);
|
||||
tcg_temp_free_i64(cc);
|
||||
|
||||
gen_helper_purge(cpu_env);
|
||||
gen_set_label(lab);
|
||||
|
||||
return NO_EXIT;
|
||||
}
|
||||
#endif
|
||||
|
@ -2158,27 +2245,34 @@ static ExitStatus op_epsw(DisasContext *s, DisasOps *o)
|
|||
|
||||
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.
|
||||
int r1 = get_field(s->fields, r1);
|
||||
TCGv_i32 ilen;
|
||||
TCGv_i64 v1;
|
||||
|
||||
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;
|
||||
/* Nested EXECUTE is not allowed. */
|
||||
if (unlikely(s->ex_value)) {
|
||||
gen_program_exception(s, PGM_EXECUTE);
|
||||
return EXIT_NORETURN;
|
||||
}
|
||||
|
||||
update_psw_addr(s);
|
||||
gen_op_calc_cc(s);
|
||||
update_cc_op(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);
|
||||
if (r1 == 0) {
|
||||
v1 = tcg_const_i64(0);
|
||||
} else {
|
||||
v1 = regs[r1];
|
||||
}
|
||||
|
||||
return NO_EXIT;
|
||||
ilen = tcg_const_i32(s->ilen);
|
||||
gen_helper_ex(cpu_env, ilen, v1, o->in2);
|
||||
tcg_temp_free_i32(ilen);
|
||||
|
||||
if (r1 == 0) {
|
||||
tcg_temp_free_i64(v1);
|
||||
}
|
||||
|
||||
return EXIT_PC_CC_UPDATED;
|
||||
}
|
||||
|
||||
static ExitStatus op_fieb(DisasContext *s, DisasOps *o)
|
||||
|
@ -2316,8 +2410,12 @@ static ExitStatus op_ipm(DisasContext *s, DisasOps *o)
|
|||
#ifndef CONFIG_USER_ONLY
|
||||
static ExitStatus op_ipte(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
TCGv_i32 m4;
|
||||
|
||||
check_privileged(s);
|
||||
gen_helper_ipte(cpu_env, o->in1, o->in2);
|
||||
m4 = tcg_const_i32(get_field(s->fields, m4));
|
||||
gen_helper_ipte(cpu_env, o->in1, o->in2, m4);
|
||||
tcg_temp_free_i32(m4);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
|
@ -2329,6 +2427,27 @@ static ExitStatus op_iske(DisasContext *s, DisasOps *o)
|
|||
}
|
||||
#endif
|
||||
|
||||
static ExitStatus op_keb(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
gen_helper_keb(cc_op, cpu_env, o->in1, o->in2);
|
||||
set_cc_static(s);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_kdb(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
gen_helper_kdb(cc_op, cpu_env, o->in1, o->in2);
|
||||
set_cc_static(s);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_kxb(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
gen_helper_kxb(cc_op, cpu_env, o->out, o->out2, o->in1, o->in2);
|
||||
set_cc_static(s);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_laa(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
/* The real output is indeed the original value in memory;
|
||||
|
@ -2550,7 +2669,6 @@ 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);
|
||||
|
@ -2562,7 +2680,6 @@ 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);
|
||||
|
@ -2572,7 +2689,6 @@ static ExitStatus op_lctlg(DisasContext *s, DisasOps *o)
|
|||
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;
|
||||
|
@ -2629,7 +2745,6 @@ 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);
|
||||
|
@ -2794,6 +2909,13 @@ static ExitStatus op_lpd(DisasContext *s, DisasOps *o)
|
|||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_lpq(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
gen_helper_lpq(o->out, cpu_env, o->in2);
|
||||
return_low128(o->out2);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static ExitStatus op_lura(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
|
@ -2871,32 +2993,78 @@ static ExitStatus op_movx(DisasContext *s, DisasOps *o)
|
|||
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_mvcin(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
|
||||
gen_helper_mvcin(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);
|
||||
int r1 = get_field(s->fields, r1);
|
||||
int r2 = get_field(s->fields, r2);
|
||||
TCGv_i32 t1, t2;
|
||||
|
||||
/* r1 and r2 must be even. */
|
||||
if (r1 & 1 || r2 & 1) {
|
||||
gen_program_exception(s, PGM_SPECIFICATION);
|
||||
return EXIT_NORETURN;
|
||||
}
|
||||
|
||||
t1 = tcg_const_i32(r1);
|
||||
t2 = tcg_const_i32(r2);
|
||||
gen_helper_mvcl(cc_op, cpu_env, t1, t2);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t2);
|
||||
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);
|
||||
int r1 = get_field(s->fields, r1);
|
||||
int r3 = get_field(s->fields, r3);
|
||||
TCGv_i32 t1, t3;
|
||||
|
||||
/* r1 and r3 must be even. */
|
||||
if (r1 & 1 || r3 & 1) {
|
||||
gen_program_exception(s, PGM_SPECIFICATION);
|
||||
return EXIT_NORETURN;
|
||||
}
|
||||
|
||||
t1 = tcg_const_i32(r1);
|
||||
t3 = tcg_const_i32(r3);
|
||||
gen_helper_mvcle(cc_op, cpu_env, t1, o->in2, t3);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t3);
|
||||
set_cc_static(s);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_mvclu(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int r1 = get_field(s->fields, r1);
|
||||
int r3 = get_field(s->fields, r3);
|
||||
TCGv_i32 t1, t3;
|
||||
|
||||
/* r1 and r3 must be even. */
|
||||
if (r1 & 1 || r3 & 1) {
|
||||
gen_program_exception(s, PGM_SPECIFICATION);
|
||||
return EXIT_NORETURN;
|
||||
}
|
||||
|
||||
t1 = tcg_const_i32(r1);
|
||||
t3 = tcg_const_i32(r3);
|
||||
gen_helper_mvclu(cc_op, cpu_env, t1, o->in2, t3);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t3);
|
||||
set_cc_static(s);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
@ -2906,7 +3074,6 @@ 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;
|
||||
|
@ -2916,30 +3083,51 @@ 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_mvn(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
|
||||
gen_helper_mvn(cpu_env, l, o->addr1, o->in2);
|
||||
tcg_temp_free_i32(l);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_mvo(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
|
||||
gen_helper_mvo(cpu_env, l, o->addr1, o->in2);
|
||||
tcg_temp_free_i32(l);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_mvpg(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
potential_page_fault(s);
|
||||
gen_helper_mvpg(cpu_env, regs[0], o->in1, o->in2);
|
||||
gen_helper_mvpg(cc_op, 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_mvz(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
|
||||
gen_helper_mvz(cpu_env, l, o->addr1, o->in2);
|
||||
tcg_temp_free_i32(l);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_mul(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
tcg_gen_mul_i64(o->out, o->in1, o->in2);
|
||||
|
@ -3048,7 +3236,6 @@ static ExitStatus op_nabsf128(DisasContext *s, DisasOps *o)
|
|||
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);
|
||||
|
@ -3083,7 +3270,6 @@ static ExitStatus op_negf128(DisasContext *s, DisasOps *o)
|
|||
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);
|
||||
|
@ -3112,6 +3298,46 @@ static ExitStatus op_ori(DisasContext *s, DisasOps *o)
|
|||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_pack(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
|
||||
gen_helper_pack(cpu_env, l, o->addr1, o->in2);
|
||||
tcg_temp_free_i32(l);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_pka(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int l2 = get_field(s->fields, l2) + 1;
|
||||
TCGv_i32 l;
|
||||
|
||||
/* The length must not exceed 32 bytes. */
|
||||
if (l2 > 32) {
|
||||
gen_program_exception(s, PGM_SPECIFICATION);
|
||||
return EXIT_NORETURN;
|
||||
}
|
||||
l = tcg_const_i32(l2);
|
||||
gen_helper_pka(cpu_env, o->addr1, o->in2, l);
|
||||
tcg_temp_free_i32(l);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_pku(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int l2 = get_field(s->fields, l2) + 1;
|
||||
TCGv_i32 l;
|
||||
|
||||
/* The length must be even and should not exceed 64 bytes. */
|
||||
if ((l2 & 1) || (l2 > 64)) {
|
||||
gen_program_exception(s, PGM_SPECIFICATION);
|
||||
return EXIT_NORETURN;
|
||||
}
|
||||
l = tcg_const_i32(l2);
|
||||
gen_helper_pku(cpu_env, o->addr1, o->in2, l);
|
||||
tcg_temp_free_i32(l);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_popcnt(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
gen_helper_popcnt(o->out, o->in2);
|
||||
|
@ -3632,7 +3858,6 @@ 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);
|
||||
|
@ -3644,7 +3869,6 @@ 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);
|
||||
|
@ -3876,7 +4100,6 @@ 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);
|
||||
|
@ -3980,9 +4203,14 @@ static ExitStatus op_stmh(DisasContext *s, DisasOps *o)
|
|||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_stpq(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
gen_helper_stpq(cpu_env, o->in2, o->out2, o->out);
|
||||
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);
|
||||
|
@ -4032,7 +4260,7 @@ static ExitStatus op_svc(DisasContext *s, DisasOps *o)
|
|||
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);
|
||||
t = tcg_const_i32(s->ilen);
|
||||
tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_ilen));
|
||||
tcg_temp_free_i32(t);
|
||||
|
||||
|
@ -4040,6 +4268,16 @@ static ExitStatus op_svc(DisasContext *s, DisasOps *o)
|
|||
return EXIT_NORETURN;
|
||||
}
|
||||
|
||||
static ExitStatus op_tam(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int cc = 0;
|
||||
|
||||
cc |= (s->tb->flags & FLAG_MASK_64) ? 2 : 0;
|
||||
cc |= (s->tb->flags & FLAG_MASK_32) ? 1 : 0;
|
||||
gen_op_movi_cc(s, cc);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_tceb(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
gen_helper_tceb(cc_op, cpu_env, o->in1, o->in2);
|
||||
|
@ -4062,19 +4300,36 @@ static ExitStatus op_tcxb(DisasContext *s, DisasOps *o)
|
|||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
static ExitStatus op_testblock(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
check_privileged(s);
|
||||
gen_helper_testblock(cc_op, cpu_env, o->in2);
|
||||
set_cc_static(s);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
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_tp(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
TCGv_i32 l1 = tcg_const_i32(get_field(s->fields, l1) + 1);
|
||||
gen_helper_tp(cc_op, cpu_env, o->addr1, l1);
|
||||
tcg_temp_free_i32(l1);
|
||||
set_cc_static(s);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -4083,7 +4338,6 @@ static ExitStatus op_tr(DisasContext *s, DisasOps *o)
|
|||
|
||||
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);
|
||||
|
@ -4093,22 +4347,95 @@ static ExitStatus op_tre(DisasContext *s, DisasOps *o)
|
|||
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_trXX(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));
|
||||
TCGv_i32 sizes = tcg_const_i32(s->insn->opc & 3);
|
||||
TCGv_i32 tst = tcg_temp_new_i32();
|
||||
int m3 = get_field(s->fields, m3);
|
||||
|
||||
/* XXX: the C bit in M3 should be considered as 0 when the
|
||||
ETF2-enhancement facility is not installed. */
|
||||
if (m3 & 1) {
|
||||
tcg_gen_movi_i32(tst, -1);
|
||||
} else {
|
||||
tcg_gen_extrl_i64_i32(tst, regs[0]);
|
||||
if (s->insn->opc & 3) {
|
||||
tcg_gen_ext8u_i32(tst, tst);
|
||||
} else {
|
||||
tcg_gen_ext16u_i32(tst, tst);
|
||||
}
|
||||
}
|
||||
gen_helper_trXX(cc_op, cpu_env, r1, r2, tst, sizes);
|
||||
|
||||
tcg_temp_free_i32(r1);
|
||||
tcg_temp_free_i32(r2);
|
||||
tcg_temp_free_i32(sizes);
|
||||
tcg_temp_free_i32(tst);
|
||||
set_cc_static(s);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_ts(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
TCGv_i32 t1 = tcg_const_i32(0xff);
|
||||
tcg_gen_atomic_xchg_i32(t1, o->in2, t1, get_mem_index(s), MO_UB);
|
||||
tcg_gen_extract_i32(cc_op, t1, 7, 1);
|
||||
tcg_temp_free_i32(t1);
|
||||
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_unpka(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int l1 = get_field(s->fields, l1) + 1;
|
||||
TCGv_i32 l;
|
||||
|
||||
/* The length must not exceed 32 bytes. */
|
||||
if (l1 > 32) {
|
||||
gen_program_exception(s, PGM_SPECIFICATION);
|
||||
return EXIT_NORETURN;
|
||||
}
|
||||
l = tcg_const_i32(l1);
|
||||
gen_helper_unpka(cc_op, cpu_env, o->addr1, l, o->in2);
|
||||
tcg_temp_free_i32(l);
|
||||
set_cc_static(s);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_unpku(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int l1 = get_field(s->fields, l1) + 1;
|
||||
TCGv_i32 l;
|
||||
|
||||
/* The length must be even and should not exceed 64 bytes. */
|
||||
if ((l1 & 1) || (l1 > 64)) {
|
||||
gen_program_exception(s, PGM_SPECIFICATION);
|
||||
return EXIT_NORETURN;
|
||||
}
|
||||
l = tcg_const_i32(l1);
|
||||
gen_helper_unpku(cc_op, cpu_env, o->addr1, l, o->in2);
|
||||
tcg_temp_free_i32(l);
|
||||
set_cc_static(s);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static ExitStatus op_xc(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int d1 = get_field(s->fields, d1);
|
||||
|
@ -4156,7 +4483,6 @@ static ExitStatus op_xc(DisasContext *s, DisasOps *o)
|
|||
/* 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);
|
||||
|
@ -5163,24 +5489,36 @@ static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s,
|
|||
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;
|
||||
if (unlikely(s->ex_value)) {
|
||||
/* Drop the EX data now, so that it's clear on exception paths. */
|
||||
TCGv_i64 zero = tcg_const_i64(0);
|
||||
tcg_gen_st_i64(zero, cpu_env, offsetof(CPUS390XState, ex_value));
|
||||
tcg_temp_free_i64(zero);
|
||||
|
||||
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();
|
||||
/* Extract the values saved by EXECUTE. */
|
||||
insn = s->ex_value & 0xffffffffffff0000ull;
|
||||
ilen = s->ex_value & 0xf;
|
||||
op = insn >> 56;
|
||||
} else {
|
||||
insn = ld_code2(env, pc);
|
||||
op = (insn >> 8) & 0xff;
|
||||
ilen = get_ilen(op);
|
||||
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:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
s->next_pc = s->pc + ilen;
|
||||
s->ilen = ilen;
|
||||
|
||||
/* 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
|
||||
|
@ -5397,6 +5735,7 @@ void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb)
|
|||
dc.tb = tb;
|
||||
dc.pc = pc_start;
|
||||
dc.cc_op = CC_OP_DYNAMIC;
|
||||
dc.ex_value = tb->cs_base;
|
||||
do_debug = dc.singlestep_enabled = cs->singlestep_enabled;
|
||||
|
||||
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
|
||||
|
@ -5431,10 +5770,7 @@ void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb)
|
|||
gen_io_start();
|
||||
}
|
||||
|
||||
status = NO_EXIT;
|
||||
if (status == NO_EXIT) {
|
||||
status = translate_one(env, &dc);
|
||||
}
|
||||
status = translate_one(env, &dc);
|
||||
|
||||
/* If we reach a page boundary, are single stepping,
|
||||
or exhaust instruction count, stop generation. */
|
||||
|
@ -5443,7 +5779,8 @@ void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb)
|
|||
|| tcg_op_buf_full()
|
||||
|| num_insns >= max_insns
|
||||
|| singlestep
|
||||
|| cs->singlestep_enabled)) {
|
||||
|| cs->singlestep_enabled
|
||||
|| dc.ex_value)) {
|
||||
status = EXIT_PC_STALE;
|
||||
}
|
||||
} while (status == NO_EXIT);
|
||||
|
@ -5463,6 +5800,8 @@ void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb)
|
|||
/* Next TB starts off with CC_OP_DYNAMIC, so make sure the
|
||||
cc op type is in env */
|
||||
update_cc_op(&dc);
|
||||
/* FALLTHRU */
|
||||
case EXIT_PC_CC_UPDATED:
|
||||
/* Exit the TB, either by raising a debug exception or by return. */
|
||||
if (do_debug) {
|
||||
gen_exception(EXCP_DEBUG);
|
||||
|
@ -5485,9 +5824,14 @@ void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb)
|
|||
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
|
||||
&& qemu_log_in_addr_range(pc_start)) {
|
||||
qemu_log_lock();
|
||||
qemu_log("IN: %s\n", lookup_symbol(pc_start));
|
||||
log_target_disas(cs, pc_start, dc.pc - pc_start, 1);
|
||||
qemu_log("\n");
|
||||
if (unlikely(dc.ex_value)) {
|
||||
/* ??? Unfortunately log_target_disas can't use host memory. */
|
||||
qemu_log("IN: EXECUTE %016" PRIx64 "\n", dc.ex_value);
|
||||
} else {
|
||||
qemu_log("IN: %s\n", lookup_symbol(pc_start));
|
||||
log_target_disas(cs, pc_start, dc.pc - pc_start, 1);
|
||||
qemu_log("\n");
|
||||
}
|
||||
qemu_log_unlock();
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue