aboutsummaryrefslogtreecommitdiff
path: root/target/ppc/mem_helper.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2018-06-26 09:19:12 -0700
committerDavid Gibson <david@gibson.dropbear.id.au>2018-07-03 09:56:52 +1000
commit4a9b3c5dd30cfd548d447521d4ef1fdba6f0fcf2 (patch)
tree27a61359435eb949c9aa4b0e155b421028b53c29 /target/ppc/mem_helper.c
parentf89ced5f556a06986d362dd41a99dfc4dc960fc1 (diff)
downloadqemu-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.c38
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
/*****************************************************************************/