diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2018-06-26 09:19:12 -0700 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2018-07-03 09:56:52 +1000 |
commit | 4a9b3c5dd30cfd548d447521d4ef1fdba6f0fcf2 (patch) | |
tree | 27a61359435eb949c9aa4b0e155b421028b53c29 /target/ppc/mem_helper.c | |
parent | f89ced5f556a06986d362dd41a99dfc4dc960fc1 (diff) | |
download | qemu-4a9b3c5dd30cfd548d447521d4ef1fdba6f0fcf2.zip qemu-4a9b3c5dd30cfd548d447521d4ef1fdba6f0fcf2.tar.gz qemu-4a9b3c5dd30cfd548d447521d4ef1fdba6f0fcf2.tar.bz2 |
target/ppc: Use atomic cmpxchg for STQCX
When running in a parallel context, we must use a helper in order
to perform the 128-bit atomic operation. When running in a serial
context, do the compare before the store.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'target/ppc/mem_helper.c')
-rw-r--r-- | target/ppc/mem_helper.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c index 57e301e..8f0d86d 100644 --- a/target/ppc/mem_helper.c +++ b/target/ppc/mem_helper.c @@ -245,6 +245,44 @@ void helper_stq_be_parallel(CPUPPCState *env, target_ulong addr, Int128 val = int128_make128(lo, hi); helper_atomic_sto_be_mmu(env, addr, val, opidx, GETPC()); } + +uint32_t helper_stqcx_le_parallel(CPUPPCState *env, target_ulong addr, + uint64_t new_lo, uint64_t new_hi, + uint32_t opidx) +{ + bool success = false; + + if (likely(addr == env->reserve_addr)) { + Int128 oldv, cmpv, newv; + + cmpv = int128_make128(env->reserve_val2, env->reserve_val); + newv = int128_make128(new_lo, new_hi); + oldv = helper_atomic_cmpxchgo_le_mmu(env, addr, cmpv, newv, + opidx, GETPC()); + success = int128_eq(oldv, cmpv); + } + env->reserve_addr = -1; + return env->so + success * CRF_EQ_BIT; +} + +uint32_t helper_stqcx_be_parallel(CPUPPCState *env, target_ulong addr, + uint64_t new_lo, uint64_t new_hi, + uint32_t opidx) +{ + bool success = false; + + if (likely(addr == env->reserve_addr)) { + Int128 oldv, cmpv, newv; + + cmpv = int128_make128(env->reserve_val2, env->reserve_val); + newv = int128_make128(new_lo, new_hi); + oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, + opidx, GETPC()); + success = int128_eq(oldv, cmpv); + } + env->reserve_addr = -1; + return env->so + success * CRF_EQ_BIT; +} #endif /*****************************************************************************/ |