Patch queue for s390 - 2015-06-05
This time there are a lot of s390x TCG emulation bug fixes - almost all of them from Aurelien, who returned from nirvana :). -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.9 (GNU/Linux) iQIcBAABAgAGBQJVcOGvAAoJECszeR4D/txgPK8QAJ8SplsjchnbXXfcskQKZZy9 U+UhwwPrR5qGyTyj/h6yhIuMHTMtyb91MUH2gkp0s/yR1US9aibx8kQCtEerX4C0 8isL61eIBa6/Cg3dmuRyM9nNNjgslnEG+G5l7ueVG+imXlhFOGnB0P1w6rhh9DCy eLhT2YgE7Scr0oK38VzoA8rXyowbfolFtJfbVR8BiSHZuBQKVjvcjTiefKiZG6xV KiizRGrys4QjK8yL61555+Vc559CGgBm10BmrdxBDqvAP8tKDVivhgT5XcsDLjKT d79s6ou2D2xpYk8v6BKviK0SazK5TCD2Sp9NCYTmCjabb4/JCG0riQyKnzl7+xeM iwxPcpUudO/TYRTKQAhRB8OxxV89DFc5b41Z1aZC8gd84wOBAQwuEFteeOU+wiM4 KH8604s80ImVg3W3euHTh8XBl1ULadCAl5mVW6nBZEPh443FknS55EHvGj4K6Mnv eQnYtqckMzDpkCzz/B0xOuv5V56CX2pAh0QZfzABG/tpB4JANo+2fLocTk1FN09H UyxpespIbsjQda+xxlKcvlGVM3P+vx/7fdhkcNn4FckmWzmqZvpOO18V5SJarysy kylvjXinkf1Zawh2KkgtAoD80uI2A3g7r6M9kJPPFvi3qFrzbTVw3e7ERWgu8wkc FCSCtIbYBbiVZ8D2mgAQ =60Dx -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/agraf/tags/signed-s390-for-upstream' into staging Patch queue for s390 - 2015-06-05 This time there are a lot of s390x TCG emulation bug fixes - almost all of them from Aurelien, who returned from nirvana :). # gpg: Signature made Fri Jun 5 00:39:27 2015 BST using RSA key ID 03FEDC60 # gpg: Good signature from "Alexander Graf <agraf@suse.de>" # gpg: aka "Alexander Graf <alex@csgraf.de>" * remotes/agraf/tags/signed-s390-for-upstream: (34 commits) target-s390x: Only access allocated storage keys target-s390x: fix MVC instruction when areas overlap target-s390x: use softmmu functions for mvcp/mvcs target-s390x: support non current ASC in s390_cpu_handle_mmu_fault target-s390x: add a cpu_mmu_idx_to_asc function target-s390x: implement high-word facility target-s390x: implement load-and-trap facility target-s390x: implement miscellaneous-instruction-extensions facility target-s390x: implement LPDFR and LNDFR instructions target-s390x: implement TRANSLATE EXTENDED instruction target-s390x: implement TRANSLATE AND TEST instruction target-s390x: implement LOAD FP INTEGER instructions target-s390x: move SET DFP ROUNDING MODE to the correct facility target-s390x: move STORE CLOCK FAST to the correct facility target-s390x: change CHRL and CGHRL format to RIL-b target-s390x: fix CLGIT instruction target-s390x: fix exception for invalid operation code target-s390x: implement LAY and LAEY instructions target-s390x: move a few instructions to the correct facility target-s390x: detect tininess before rounding for FP operations ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
00967f4e0b
@ -113,7 +113,7 @@ const float16 float16_default_nan = const_float16(0xFE00);
|
||||
#if defined(TARGET_SPARC)
|
||||
const float32 float32_default_nan = const_float32(0x7FFFFFFF);
|
||||
#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
|
||||
defined(TARGET_XTENSA)
|
||||
defined(TARGET_XTENSA) || defined(TARGET_S390X)
|
||||
const float32 float32_default_nan = const_float32(0x7FC00000);
|
||||
#elif SNAN_BIT_IS_ONE
|
||||
const float32 float32_default_nan = const_float32(0x7FBFFFFF);
|
||||
@ -126,7 +126,8 @@ const float32 float32_default_nan = const_float32(0xFFC00000);
|
||||
*----------------------------------------------------------------------------*/
|
||||
#if defined(TARGET_SPARC)
|
||||
const float64 float64_default_nan = const_float64(LIT64( 0x7FFFFFFFFFFFFFFF ));
|
||||
#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
|
||||
#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
|
||||
defined(TARGET_S390X)
|
||||
const float64 float64_default_nan = const_float64(LIT64( 0x7FF8000000000000 ));
|
||||
#elif SNAN_BIT_IS_ONE
|
||||
const float64 float64_default_nan = const_float64(LIT64(0x7FF7FFFFFFFFFFFF));
|
||||
@ -155,6 +156,9 @@ const floatx80 floatx80_default_nan
|
||||
#if SNAN_BIT_IS_ONE
|
||||
#define float128_default_nan_high LIT64(0x7FFF7FFFFFFFFFFF)
|
||||
#define float128_default_nan_low LIT64(0xFFFFFFFFFFFFFFFF)
|
||||
#elif defined(TARGET_S390X)
|
||||
#define float128_default_nan_high LIT64( 0x7FFF800000000000 )
|
||||
#define float128_default_nan_low LIT64( 0x0000000000000000 )
|
||||
#else
|
||||
#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
|
||||
#define float128_default_nan_low LIT64( 0x0000000000000000 )
|
||||
|
@ -195,7 +195,7 @@ static uint32_t cc_calc_abs_64(int64_t dst)
|
||||
if ((uint64_t)dst == 0x8000000000000000ULL) {
|
||||
return 3;
|
||||
} else if (dst) {
|
||||
return 1;
|
||||
return 2;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@ -296,7 +296,7 @@ static uint32_t cc_calc_abs_32(int32_t dst)
|
||||
if ((uint32_t)dst == 0x80000000UL) {
|
||||
return 3;
|
||||
} else if (dst) {
|
||||
return 1;
|
||||
return 2;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -118,6 +118,10 @@ static void s390_cpu_initial_reset(CPUState *s)
|
||||
|
||||
env->pfault_token = -1UL;
|
||||
|
||||
/* 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);
|
||||
@ -143,6 +147,10 @@ static void s390_cpu_full_reset(CPUState *s)
|
||||
|
||||
env->pfault_token = -1UL;
|
||||
|
||||
/* 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);
|
||||
|
@ -48,7 +48,7 @@
|
||||
#define MMU_MODE1_SUFFIX _secondary
|
||||
#define MMU_MODE2_SUFFIX _home
|
||||
|
||||
#define MMU_USER_IDX 1
|
||||
#define MMU_USER_IDX 0
|
||||
|
||||
#define MAX_EXT_QUEUE 16
|
||||
#define MAX_IO_QUEUE 16
|
||||
@ -302,13 +302,39 @@ static inline CPU_DoubleU *get_freg(CPUS390XState *cs, int nr)
|
||||
#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)
|
||||
{
|
||||
if (env->psw.mask & PSW_MASK_PSTATE) {
|
||||
return 1;
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
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,
|
||||
@ -995,6 +1021,11 @@ 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)
|
||||
{
|
||||
|
@ -265,7 +265,7 @@ uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
|
||||
{
|
||||
float64 ret = float32_to_float64(f2, &env->fpu_status);
|
||||
handle_exceptions(env, GETPC());
|
||||
return ret;
|
||||
return float64_maybe_silence_nan(ret);
|
||||
}
|
||||
|
||||
/* convert 128-bit float to 64-bit float */
|
||||
@ -273,7 +273,7 @@ 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 ret;
|
||||
return float64_maybe_silence_nan(ret);
|
||||
}
|
||||
|
||||
/* convert 64-bit float to 128-bit float */
|
||||
@ -281,7 +281,7 @@ uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
|
||||
{
|
||||
float128 ret = float64_to_float128(f2, &env->fpu_status);
|
||||
handle_exceptions(env, GETPC());
|
||||
return RET128(ret);
|
||||
return RET128(float128_maybe_silence_nan(ret));
|
||||
}
|
||||
|
||||
/* convert 32-bit float to 128-bit float */
|
||||
@ -289,7 +289,7 @@ uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
|
||||
{
|
||||
float128 ret = float32_to_float128(f2, &env->fpu_status);
|
||||
handle_exceptions(env, GETPC());
|
||||
return RET128(ret);
|
||||
return RET128(float128_maybe_silence_nan(ret));
|
||||
}
|
||||
|
||||
/* convert 64-bit float to 32-bit float */
|
||||
@ -297,7 +297,7 @@ uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
|
||||
{
|
||||
float32 ret = float64_to_float32(f2, &env->fpu_status);
|
||||
handle_exceptions(env, GETPC());
|
||||
return ret;
|
||||
return float32_maybe_silence_nan(ret);
|
||||
}
|
||||
|
||||
/* convert 128-bit float to 32-bit float */
|
||||
@ -305,7 +305,7 @@ 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 ret;
|
||||
return float32_maybe_silence_nan(ret);
|
||||
}
|
||||
|
||||
/* 32-bit FP compare */
|
||||
@ -552,6 +552,37 @@ uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
|
||||
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)
|
||||
|
@ -112,7 +112,7 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr,
|
||||
{
|
||||
S390CPU *cpu = S390_CPU(cs);
|
||||
CPUS390XState *env = &cpu->env;
|
||||
uint64_t asc = env->psw.mask & PSW_MASK_ASC;
|
||||
uint64_t asc = cpu_mmu_idx_to_asc(mmu_idx);
|
||||
target_ulong vaddr, raddr;
|
||||
int prot;
|
||||
|
||||
|
@ -15,10 +15,6 @@ 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_1(abs_i32, TCG_CALL_NO_RWG_SE, i32, s32)
|
||||
DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_NO_RWG_SE, s32, s32)
|
||||
DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_NO_RWG_SE, i64, s64)
|
||||
DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_NO_RWG_SE, s64, s64)
|
||||
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)
|
||||
@ -64,6 +60,9 @@ 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)
|
||||
@ -78,6 +77,8 @@ 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)
|
||||
|
@ -34,6 +34,9 @@
|
||||
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)
|
||||
@ -41,6 +44,8 @@
|
||||
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)
|
||||
@ -58,6 +63,9 @@
|
||||
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)
|
||||
@ -66,6 +74,9 @@
|
||||
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)
|
||||
@ -111,6 +122,8 @@
|
||||
/* 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)
|
||||
@ -159,8 +172,14 @@
|
||||
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_a, GIE, r1_o, mri2_32s, 0, 0, 0, cmps32)
|
||||
C(0xc604, CGHRL, RIL_a, GIE, r1_o, mri2_64, 0, 0, 0, cmps64)
|
||||
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)
|
||||
@ -171,6 +190,10 @@
|
||||
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)
|
||||
@ -179,6 +202,8 @@
|
||||
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)
|
||||
@ -230,8 +255,10 @@
|
||||
/* 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, 0)
|
||||
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)
|
||||
@ -336,7 +363,7 @@
|
||||
/* 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, 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)
|
||||
@ -357,6 +384,9 @@
|
||||
/* 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 */
|
||||
@ -384,11 +414,16 @@
|
||||
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)
|
||||
@ -403,15 +438,23 @@
|
||||
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 */
|
||||
@ -419,11 +462,15 @@
|
||||
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)
|
||||
@ -437,6 +484,9 @@
|
||||
/* 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 */
|
||||
@ -448,6 +498,7 @@
|
||||
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)
|
||||
@ -461,6 +512,7 @@
|
||||
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)
|
||||
@ -476,6 +528,10 @@
|
||||
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)
|
||||
@ -595,8 +651,9 @@
|
||||
|
||||
/* ROTATE THEN INSERT SELECTED BITS */
|
||||
C(0xec55, RISBG, RIE_f, GIE, 0, r2, r1, 0, risbg, s64)
|
||||
C(0xec5d, RISBHG, RIE_f, GIE, 0, r2, r1, 0, risbg, 0)
|
||||
C(0xec51, RISBLG, RIE_f, GIE, 0, r2, r1, 0, risbg, 0)
|
||||
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)
|
||||
@ -619,7 +676,7 @@
|
||||
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, DFP, 0, 0, 0, 0, srnm, 0)
|
||||
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)
|
||||
@ -667,15 +724,21 @@
|
||||
/* 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, LD, r1_o, a2, 0, 0, stcm, 0, 32)
|
||||
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)
|
||||
@ -715,6 +778,9 @@
|
||||
/* 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)
|
||||
@ -725,6 +791,9 @@
|
||||
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)
|
||||
@ -752,6 +821,10 @@
|
||||
|
||||
/* 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
|
||||
@ -812,7 +885,7 @@
|
||||
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, 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 */
|
||||
|
@ -115,48 +115,6 @@ uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* absolute value 32-bit */
|
||||
uint32_t HELPER(abs_i32)(int32_t val)
|
||||
{
|
||||
if (val < 0) {
|
||||
return -val;
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/* negative absolute value 32-bit */
|
||||
int32_t HELPER(nabs_i32)(int32_t val)
|
||||
{
|
||||
if (val < 0) {
|
||||
return val;
|
||||
} else {
|
||||
return -val;
|
||||
}
|
||||
}
|
||||
|
||||
/* absolute value 64-bit */
|
||||
uint64_t HELPER(abs_i64)(int64_t val)
|
||||
{
|
||||
HELPER_LOG("%s: val 0x%" PRIx64 "\n", __func__, val);
|
||||
|
||||
if (val < 0) {
|
||||
return -val;
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/* negative absolute value 64-bit */
|
||||
int64_t HELPER(nabs_i64)(int64_t val)
|
||||
{
|
||||
if (val < 0) {
|
||||
return val;
|
||||
} else {
|
||||
return -val;
|
||||
}
|
||||
}
|
||||
|
||||
/* count leading zeros, for find leftmost one */
|
||||
uint64_t HELPER(clz)(uint64_t v)
|
||||
{
|
||||
|
@ -213,21 +213,22 @@ void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
|
||||
if (dest == (src + 1)) {
|
||||
memset(g2h(dest), cpu_ldub_data(env, src), l + 1);
|
||||
return;
|
||||
} else {
|
||||
/* mvc and memmove do not behave the same when areas overlap! */
|
||||
} else if ((dest < src) || (src + l < dest)) {
|
||||
memmove(g2h(dest), g2h(src), l + 1);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* handle the parts that fit into 8-byte loads/stores */
|
||||
if (dest != (src + 1)) {
|
||||
if ((dest + 8 <= src) || (src + 8 <= dest)) {
|
||||
for (i = 0; i < l_64; i++) {
|
||||
cpu_stq_data(env, dest + x, cpu_ldq_data(env, src + x));
|
||||
x += 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* slow version crossing pages with byte accesses */
|
||||
/* slow version with byte accesses which always work */
|
||||
for (i = x; i <= l; i++) {
|
||||
cpu_stb_data(env, dest + i, cpu_ldub_data(env, src + i));
|
||||
}
|
||||
@ -509,6 +510,9 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1,
|
||||
case 0xc00:
|
||||
helper_tr(env, l, get_address(env, 0, b1, d1),
|
||||
get_address(env, 0, b2, d2));
|
||||
case 0xd00:
|
||||
cc = helper_trt(env, l, get_address(env, 0, b1, d1),
|
||||
get_address(env, 0, b2, d2));
|
||||
break;
|
||||
default:
|
||||
goto abort;
|
||||
@ -801,6 +805,66 @@ void HELPER(tr)(CPUS390XState *env, uint32_t len, uint64_t array,
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -952,59 +1016,46 @@ uint32_t HELPER(csp)(CPUS390XState *env, uint32_t r1, uint64_t r2)
|
||||
return cc;
|
||||
}
|
||||
|
||||
static uint32_t mvc_asc(CPUS390XState *env, int64_t l, uint64_t a1,
|
||||
uint64_t mode1, uint64_t a2, uint64_t mode2)
|
||||
uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2)
|
||||
{
|
||||
CPUState *cs = CPU(s390_env_get_cpu(env));
|
||||
target_ulong src, dest;
|
||||
int flags, cc = 0, i;
|
||||
int cc = 0, i;
|
||||
|
||||
if (!l) {
|
||||
return 0;
|
||||
} else if (l > 256) {
|
||||
HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
|
||||
__func__, l, a1, a2);
|
||||
|
||||
if (l > 256) {
|
||||
/* max 256 */
|
||||
l = 256;
|
||||
cc = 3;
|
||||
}
|
||||
|
||||
if (mmu_translate(env, a1, 1, mode1, &dest, &flags, true)) {
|
||||
cpu_loop_exit(CPU(s390_env_get_cpu(env)));
|
||||
}
|
||||
dest |= a1 & ~TARGET_PAGE_MASK;
|
||||
|
||||
if (mmu_translate(env, a2, 0, mode2, &src, &flags, true)) {
|
||||
cpu_loop_exit(CPU(s390_env_get_cpu(env)));
|
||||
}
|
||||
src |= a2 & ~TARGET_PAGE_MASK;
|
||||
|
||||
/* XXX replace w/ memcpy */
|
||||
for (i = 0; i < l; i++) {
|
||||
/* XXX be more clever */
|
||||
if ((((dest + i) & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) ||
|
||||
(((src + i) & TARGET_PAGE_MASK) != (src & TARGET_PAGE_MASK))) {
|
||||
mvc_asc(env, l - i, a1 + i, mode1, a2 + i, mode2);
|
||||
break;
|
||||
}
|
||||
stb_phys(cs->as, dest + i, ldub_phys(cs->as, src + i));
|
||||
cpu_stb_secondary(env, a1 + i, cpu_ldub_primary(env, a2 + i));
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2)
|
||||
{
|
||||
HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
|
||||
__func__, l, a1, a2);
|
||||
|
||||
return mvc_asc(env, l, a1, PSW_ASC_SECONDARY, a2, PSW_ASC_PRIMARY);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return mvc_asc(env, l, a1, PSW_ASC_PRIMARY, a2, PSW_ASC_SECONDARY);
|
||||
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 */
|
||||
|
@ -61,7 +61,7 @@ void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
|
||||
/* Advance past the insn. */
|
||||
t = cpu_ldub_code(env, env->psw.addr);
|
||||
env->int_pgm_ilen = t = get_ilen(t);
|
||||
env->psw.addr += 2 * t;
|
||||
env->psw.addr += t;
|
||||
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
@ -268,7 +268,8 @@ void HELPER(spx)(CPUS390XState *env, uint64_t a1)
|
||||
tlb_flush_page(cs, TARGET_PAGE_SIZE);
|
||||
}
|
||||
|
||||
static inline uint64_t clock_value(CPUS390XState *env)
|
||||
/* Store Clock */
|
||||
uint64_t HELPER(stck)(CPUS390XState *env)
|
||||
{
|
||||
uint64_t time;
|
||||
|
||||
@ -278,12 +279,6 @@ static inline uint64_t clock_value(CPUS390XState *env)
|
||||
return time;
|
||||
}
|
||||
|
||||
/* Store Clock */
|
||||
uint64_t HELPER(stck)(CPUS390XState *env)
|
||||
{
|
||||
return clock_value(env);
|
||||
}
|
||||
|
||||
/* Set Clock Comparator */
|
||||
void HELPER(sckc)(CPUS390XState *env, uint64_t time)
|
||||
{
|
||||
@ -291,19 +286,21 @@ void HELPER(sckc)(CPUS390XState *env, uint64_t time)
|
||||
return;
|
||||
}
|
||||
|
||||
/* difference between now and then */
|
||||
time -= clock_value(env);
|
||||
/* nanoseconds */
|
||||
time = (time * 125) >> 9;
|
||||
env->ckc = time;
|
||||
|
||||
timer_mod(env->tod_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 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)
|
||||
{
|
||||
/* XXX implement */
|
||||
return 0;
|
||||
return env->ckc;
|
||||
}
|
||||
|
||||
/* Set CPU Timer */
|
||||
@ -314,16 +311,17 @@ void HELPER(spt)(CPUS390XState *env, uint64_t time)
|
||||
}
|
||||
|
||||
/* nanoseconds */
|
||||
time = (time * 125) >> 9;
|
||||
time = tod2time(time);
|
||||
|
||||
timer_mod(env->cpu_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 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)
|
||||
{
|
||||
/* XXX implement */
|
||||
return 0;
|
||||
return time2tod(env->cputm - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
|
||||
}
|
||||
|
||||
/* Store System Information */
|
||||
|
@ -358,7 +358,7 @@ int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
|
||||
/* Convert real address -> absolute address */
|
||||
*raddr = mmu_real2abs(env, *raddr);
|
||||
|
||||
if (*raddr <= ram_size) {
|
||||
if (*raddr < ram_size) {
|
||||
sk = &env->storage_keys[*raddr / TARGET_PAGE_SIZE];
|
||||
if (*flags & PAGE_READ) {
|
||||
*sk |= SK_R;
|
||||
|
@ -320,7 +320,21 @@ static void gen_program_exception(DisasContext *s, int code)
|
||||
|
||||
static inline void gen_illegal_opcode(DisasContext *s)
|
||||
{
|
||||
gen_program_exception(s, PGM_SPECIFICATION);
|
||||
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
|
||||
@ -1119,6 +1133,8 @@ typedef enum DisasFacility {
|
||||
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 */
|
||||
@ -1310,7 +1326,13 @@ static ExitStatus help_branch(DisasContext *s, DisasCompare *c,
|
||||
|
||||
static ExitStatus op_abs(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
gen_helper_abs_i64(o->out, o->in2);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1460,6 +1482,30 @@ static ExitStatus op_bct32(DisasContext *s, DisasOps *o)
|
||||
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_trunc_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);
|
||||
@ -1961,7 +2007,6 @@ static ExitStatus op_ct(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int m3 = get_field(s->fields, m3);
|
||||
TCGLabel *lab = gen_new_label();
|
||||
TCGv_i32 t;
|
||||
TCGCond c;
|
||||
|
||||
c = tcg_invert_cond(ltgt_cond[m3]);
|
||||
@ -1970,15 +2015,8 @@ static ExitStatus op_ct(DisasContext *s, DisasOps *o)
|
||||
}
|
||||
tcg_gen_brcond_i64(c, o->in1, o->in2, lab);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Trap. */
|
||||
gen_program_exception(s, PGM_DATA);
|
||||
gen_trap(s);
|
||||
|
||||
gen_set_label(lab);
|
||||
return NO_EXIT;
|
||||
@ -2101,13 +2139,37 @@ static ExitStatus op_ex(DisasContext *s, DisasOps *o)
|
||||
TCGv_i64 tmp;
|
||||
|
||||
update_psw_addr(s);
|
||||
update_cc_op(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);
|
||||
|
||||
set_cc_static(s);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -2320,6 +2382,61 @@ static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
|
||||
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;
|
||||
@ -2435,21 +2552,45 @@ static ExitStatus op_lm32(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 t1, t2;
|
||||
|
||||
while (1) {
|
||||
tcg_gen_qemu_ld32u(t, o->in2, get_mem_index(s));
|
||||
store_reg32_i64(r1, t);
|
||||
if (r1 == r3) {
|
||||
break;
|
||||
}
|
||||
tcg_gen_add_i64(o->in2, o->in2, t4);
|
||||
r1 = (r1 + 1) & 15;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
tcg_temp_free_i64(t);
|
||||
tcg_temp_free_i64(t4);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -2457,21 +2598,45 @@ static ExitStatus op_lmh(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 t1, t2;
|
||||
|
||||
while (1) {
|
||||
tcg_gen_qemu_ld32u(t, o->in2, get_mem_index(s));
|
||||
store_reg32h_i64(r1, t);
|
||||
if (r1 == r3) {
|
||||
break;
|
||||
}
|
||||
tcg_gen_add_i64(o->in2, o->in2, t4);
|
||||
r1 = (r1 + 1) & 15;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
tcg_temp_free_i64(t);
|
||||
tcg_temp_free_i64(t4);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -2479,18 +2644,40 @@ static ExitStatus op_lm64(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int r1 = get_field(s->fields, r1);
|
||||
int r3 = get_field(s->fields, r3);
|
||||
TCGv_i64 t8 = tcg_const_i64(8);
|
||||
TCGv_i64 t1, t2;
|
||||
|
||||
while (1) {
|
||||
/* Only one register to read. */
|
||||
if (unlikely(r1 == r3)) {
|
||||
tcg_gen_qemu_ld64(regs[r1], o->in2, get_mem_index(s));
|
||||
if (r1 == r3) {
|
||||
break;
|
||||
}
|
||||
tcg_gen_add_i64(o->in2, o->in2, t8);
|
||||
r1 = (r1 + 1) & 15;
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
tcg_temp_free_i64(t8);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -2521,6 +2708,41 @@ static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
|
||||
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;
|
||||
@ -2681,7 +2903,13 @@ static ExitStatus op_msdb(DisasContext *s, DisasOps *o)
|
||||
|
||||
static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
gen_helper_nabs_i64(o->out, o->in2);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -3646,6 +3874,25 @@ static ExitStatus op_tr(DisasContext *s, DisasOps *o)
|
||||
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));
|
||||
@ -3989,6 +4236,12 @@ static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
|
||||
}
|
||||
#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);
|
||||
@ -4159,6 +4412,13 @@ static void in1_r2(DisasContext *s, DisasFields *f, DisasOps *o)
|
||||
}
|
||||
#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));
|
||||
@ -4372,6 +4632,13 @@ static void in2_r3(DisasContext *s, DisasFields *f, DisasOps *o)
|
||||
}
|
||||
#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();
|
||||
@ -4386,6 +4653,13 @@ static void in2_r2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
|
||||
}
|
||||
#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));
|
||||
|
Loading…
Reference in New Issue
Block a user