mirror of https://github.com/xqemu/xqemu.git
target/s390x: Split do_cdsg, do_lpq, do_stpq
Reviewed-by: David Hildenbrand <david@redhat.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
5e95612e2e
commit
0c9fa16805
|
@ -1380,57 +1380,58 @@ uint32_t HELPER(trXX)(CPUS390XState *env, uint32_t r1, uint32_t r2,
|
||||||
return cc;
|
return cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_cdsg(CPUS390XState *env, uint64_t addr,
|
void HELPER(cdsg)(CPUS390XState *env, uint64_t addr,
|
||||||
uint32_t r1, uint32_t r3, bool parallel)
|
uint32_t r1, uint32_t r3)
|
||||||
{
|
{
|
||||||
uintptr_t ra = GETPC();
|
uintptr_t ra = GETPC();
|
||||||
Int128 cmpv = int128_make128(env->regs[r1 + 1], env->regs[r1]);
|
Int128 cmpv = int128_make128(env->regs[r1 + 1], env->regs[r1]);
|
||||||
Int128 newv = int128_make128(env->regs[r3 + 1], env->regs[r3]);
|
Int128 newv = int128_make128(env->regs[r3 + 1], env->regs[r3]);
|
||||||
Int128 oldv;
|
Int128 oldv;
|
||||||
|
uint64_t oldh, oldl;
|
||||||
bool fail;
|
bool fail;
|
||||||
|
|
||||||
if (parallel) {
|
check_alignment(env, addr, 16, ra);
|
||||||
#if !HAVE_CMPXCHG128
|
|
||||||
cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
|
|
||||||
#else
|
|
||||||
int mem_idx = cpu_mmu_index(env, false);
|
|
||||||
TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
|
|
||||||
oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra);
|
|
||||||
fail = !int128_eq(oldv, cmpv);
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
uint64_t oldh, oldl;
|
|
||||||
|
|
||||||
check_alignment(env, addr, 16, ra);
|
oldh = cpu_ldq_data_ra(env, addr + 0, ra);
|
||||||
|
oldl = cpu_ldq_data_ra(env, addr + 8, ra);
|
||||||
|
|
||||||
oldh = cpu_ldq_data_ra(env, addr + 0, ra);
|
oldv = int128_make128(oldl, oldh);
|
||||||
oldl = cpu_ldq_data_ra(env, addr + 8, ra);
|
fail = !int128_eq(oldv, cmpv);
|
||||||
|
if (fail) {
|
||||||
oldv = int128_make128(oldl, oldh);
|
newv = oldv;
|
||||||
fail = !int128_eq(oldv, cmpv);
|
|
||||||
if (fail) {
|
|
||||||
newv = oldv;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu_stq_data_ra(env, addr + 0, int128_gethi(newv), ra);
|
|
||||||
cpu_stq_data_ra(env, addr + 8, int128_getlo(newv), ra);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cpu_stq_data_ra(env, addr + 0, int128_gethi(newv), ra);
|
||||||
|
cpu_stq_data_ra(env, addr + 8, int128_getlo(newv), ra);
|
||||||
|
|
||||||
env->cc_op = fail;
|
env->cc_op = fail;
|
||||||
env->regs[r1] = int128_gethi(oldv);
|
env->regs[r1] = int128_gethi(oldv);
|
||||||
env->regs[r1 + 1] = int128_getlo(oldv);
|
env->regs[r1 + 1] = int128_getlo(oldv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HELPER(cdsg)(CPUS390XState *env, uint64_t addr,
|
|
||||||
uint32_t r1, uint32_t r3)
|
|
||||||
{
|
|
||||||
do_cdsg(env, addr, r1, r3, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HELPER(cdsg_parallel)(CPUS390XState *env, uint64_t addr,
|
void HELPER(cdsg_parallel)(CPUS390XState *env, uint64_t addr,
|
||||||
uint32_t r1, uint32_t r3)
|
uint32_t r1, uint32_t r3)
|
||||||
{
|
{
|
||||||
do_cdsg(env, addr, r1, r3, true);
|
uintptr_t ra = GETPC();
|
||||||
|
Int128 cmpv = int128_make128(env->regs[r1 + 1], env->regs[r1]);
|
||||||
|
Int128 newv = int128_make128(env->regs[r3 + 1], env->regs[r3]);
|
||||||
|
int mem_idx;
|
||||||
|
TCGMemOpIdx oi;
|
||||||
|
Int128 oldv;
|
||||||
|
bool fail;
|
||||||
|
|
||||||
|
if (!HAVE_CMPXCHG128) {
|
||||||
|
cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
|
||||||
|
}
|
||||||
|
|
||||||
|
mem_idx = cpu_mmu_index(env, false);
|
||||||
|
oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
|
||||||
|
oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra);
|
||||||
|
fail = !int128_eq(oldv, cmpv);
|
||||||
|
|
||||||
|
env->cc_op = fail;
|
||||||
|
env->regs[r1] = int128_gethi(oldv);
|
||||||
|
env->regs[r1 + 1] = int128_getlo(oldv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
|
static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
|
||||||
|
@ -2097,16 +2098,25 @@ uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* load pair from quadword */
|
/* load pair from quadword */
|
||||||
static uint64_t do_lpq(CPUS390XState *env, uint64_t addr, bool parallel)
|
uint64_t HELPER(lpq)(CPUS390XState *env, uint64_t addr)
|
||||||
{
|
{
|
||||||
uintptr_t ra = GETPC();
|
uintptr_t ra = GETPC();
|
||||||
uint64_t hi, lo;
|
uint64_t hi, lo;
|
||||||
|
|
||||||
if (!parallel) {
|
check_alignment(env, addr, 16, ra);
|
||||||
check_alignment(env, addr, 16, ra);
|
hi = cpu_ldq_data_ra(env, addr + 0, ra);
|
||||||
hi = cpu_ldq_data_ra(env, addr + 0, ra);
|
lo = cpu_ldq_data_ra(env, addr + 8, ra);
|
||||||
lo = cpu_ldq_data_ra(env, addr + 8, ra);
|
|
||||||
} else if (HAVE_ATOMIC128) {
|
env->retxl = lo;
|
||||||
|
return hi;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t HELPER(lpq_parallel)(CPUS390XState *env, uint64_t addr)
|
||||||
|
{
|
||||||
|
uintptr_t ra = GETPC();
|
||||||
|
uint64_t hi, lo;
|
||||||
|
|
||||||
|
if (HAVE_ATOMIC128) {
|
||||||
int mem_idx = cpu_mmu_index(env, false);
|
int mem_idx = cpu_mmu_index(env, false);
|
||||||
TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
|
TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
|
||||||
Int128 v = helper_atomic_ldo_be_mmu(env, addr, oi, ra);
|
Int128 v = helper_atomic_ldo_be_mmu(env, addr, oi, ra);
|
||||||
|
@ -2120,27 +2130,23 @@ static uint64_t do_lpq(CPUS390XState *env, uint64_t addr, bool parallel)
|
||||||
return hi;
|
return hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t HELPER(lpq)(CPUS390XState *env, uint64_t addr)
|
|
||||||
{
|
|
||||||
return do_lpq(env, addr, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t HELPER(lpq_parallel)(CPUS390XState *env, uint64_t addr)
|
|
||||||
{
|
|
||||||
return do_lpq(env, addr, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* store pair to quadword */
|
/* store pair to quadword */
|
||||||
static void do_stpq(CPUS390XState *env, uint64_t addr,
|
void HELPER(stpq)(CPUS390XState *env, uint64_t addr,
|
||||||
uint64_t low, uint64_t high, bool parallel)
|
uint64_t low, uint64_t high)
|
||||||
{
|
{
|
||||||
uintptr_t ra = GETPC();
|
uintptr_t ra = GETPC();
|
||||||
|
|
||||||
if (!parallel) {
|
check_alignment(env, addr, 16, ra);
|
||||||
check_alignment(env, addr, 16, ra);
|
cpu_stq_data_ra(env, addr + 0, high, ra);
|
||||||
cpu_stq_data_ra(env, addr + 0, high, ra);
|
cpu_stq_data_ra(env, addr + 8, low, ra);
|
||||||
cpu_stq_data_ra(env, addr + 8, low, ra);
|
}
|
||||||
} else if (HAVE_ATOMIC128) {
|
|
||||||
|
void HELPER(stpq_parallel)(CPUS390XState *env, uint64_t addr,
|
||||||
|
uint64_t low, uint64_t high)
|
||||||
|
{
|
||||||
|
uintptr_t ra = GETPC();
|
||||||
|
|
||||||
|
if (HAVE_ATOMIC128) {
|
||||||
int mem_idx = cpu_mmu_index(env, false);
|
int mem_idx = cpu_mmu_index(env, false);
|
||||||
TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
|
TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
|
||||||
Int128 v = int128_make128(low, high);
|
Int128 v = int128_make128(low, high);
|
||||||
|
@ -2150,18 +2156,6 @@ static void do_stpq(CPUS390XState *env, uint64_t addr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HELPER(stpq)(CPUS390XState *env, uint64_t addr,
|
|
||||||
uint64_t low, uint64_t high)
|
|
||||||
{
|
|
||||||
do_stpq(env, addr, low, high, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HELPER(stpq_parallel)(CPUS390XState *env, uint64_t addr,
|
|
||||||
uint64_t low, uint64_t high)
|
|
||||||
{
|
|
||||||
do_stpq(env, addr, low, high, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Execute instruction. This instruction executes an insn modified with
|
/* Execute instruction. This instruction executes an insn modified with
|
||||||
the contents of r1. It does not change the executed instruction in memory;
|
the contents of r1. It does not change the executed instruction in memory;
|
||||||
it does not change the program counter.
|
it does not change the program counter.
|
||||||
|
|
Loading…
Reference in New Issue