Loading target/arm/helper-a64.c +134 −127 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include "exec/exec-all.h" #include "exec/cpu_ldst.h" #include "qemu/int128.h" #include "qemu/atomic128.h" #include "tcg.h" #include "fpu/softfloat.h" #include <zlib.h> /* For crc32 */ Loading Loading @@ -509,28 +510,15 @@ uint64_t HELPER(crc32c_64)(uint64_t acc, uint64_t val, uint32_t bytes) return crc32c(acc, buf, bytes) ^ 0xffffffff; } /* Returns 0 on success; 1 otherwise. */ static uint64_t do_paired_cmpxchg64_le(CPUARMState *env, uint64_t addr, uint64_t new_lo, uint64_t new_hi, bool parallel, uintptr_t ra) uint64_t HELPER(paired_cmpxchg64_le)(CPUARMState *env, uint64_t addr, uint64_t new_lo, uint64_t new_hi) { Int128 oldv, cmpv, newv; bool success; cmpv = int128_make128(env->exclusive_val, env->exclusive_high); newv = int128_make128(new_lo, new_hi); if (parallel) { #ifndef CONFIG_ATOMIC128 cpu_loop_exit_atomic(ENV_GET_CPU(env), ra); #else int mem_idx = cpu_mmu_index(env, false); TCGMemOpIdx oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx); oldv = helper_atomic_cmpxchgo_le_mmu(env, addr, cmpv, newv, oi, ra); success = int128_eq(oldv, cmpv); #endif } else { Int128 cmpv = int128_make128(env->exclusive_val, env->exclusive_high); Int128 newv = int128_make128(new_lo, new_hi); Int128 oldv; uintptr_t ra = GETPC(); uint64_t o0, o1; bool success; #ifdef CONFIG_USER_ONLY /* ??? Enforce alignment. */ Loading Loading @@ -562,47 +550,47 @@ static uint64_t do_paired_cmpxchg64_le(CPUARMState *env, uint64_t addr, helper_le_stq_mmu(env, addr + 8, int128_gethi(newv), oi1, ra); } #endif } return !success; } uint64_t HELPER(paired_cmpxchg64_le)(CPUARMState *env, uint64_t addr, uint64_t HELPER(paired_cmpxchg64_le_parallel)(CPUARMState *env, uint64_t addr, uint64_t new_lo, uint64_t new_hi) { return do_paired_cmpxchg64_le(env, addr, new_lo, new_hi, false, GETPC()); Int128 oldv, cmpv, newv; uintptr_t ra = GETPC(); bool success; int mem_idx; TCGMemOpIdx oi; if (!HAVE_CMPXCHG128) { cpu_loop_exit_atomic(ENV_GET_CPU(env), ra); } uint64_t HELPER(paired_cmpxchg64_le_parallel)(CPUARMState *env, uint64_t addr, uint64_t new_lo, uint64_t new_hi) { return do_paired_cmpxchg64_le(env, addr, new_lo, new_hi, true, GETPC()); mem_idx = cpu_mmu_index(env, false); oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx); cmpv = int128_make128(env->exclusive_val, env->exclusive_high); newv = int128_make128(new_lo, new_hi); oldv = helper_atomic_cmpxchgo_le_mmu(env, addr, cmpv, newv, oi, ra); success = int128_eq(oldv, cmpv); return !success; } static uint64_t do_paired_cmpxchg64_be(CPUARMState *env, uint64_t addr, uint64_t new_lo, uint64_t new_hi, bool parallel, uintptr_t ra) uint64_t HELPER(paired_cmpxchg64_be)(CPUARMState *env, uint64_t addr, uint64_t new_lo, uint64_t new_hi) { Int128 oldv, cmpv, newv; bool success; /* high and low need to be switched here because this is not actually a /* * High and low need to be switched here because this is not actually a * 128bit store but two doublewords stored consecutively */ cmpv = int128_make128(env->exclusive_high, env->exclusive_val); newv = int128_make128(new_hi, new_lo); if (parallel) { #ifndef CONFIG_ATOMIC128 cpu_loop_exit_atomic(ENV_GET_CPU(env), ra); #else int mem_idx = cpu_mmu_index(env, false); TCGMemOpIdx oi = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx); oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra); success = int128_eq(oldv, cmpv); #endif } else { Int128 cmpv = int128_make128(env->exclusive_val, env->exclusive_high); Int128 newv = int128_make128(new_lo, new_hi); Int128 oldv; uintptr_t ra = GETPC(); uint64_t o0, o1; bool success; #ifdef CONFIG_USER_ONLY /* ??? Enforce alignment. */ Loading Loading @@ -634,64 +622,83 @@ static uint64_t do_paired_cmpxchg64_be(CPUARMState *env, uint64_t addr, helper_be_stq_mmu(env, addr + 8, int128_getlo(newv), oi1, ra); } #endif } return !success; } uint64_t HELPER(paired_cmpxchg64_be)(CPUARMState *env, uint64_t addr, uint64_t HELPER(paired_cmpxchg64_be_parallel)(CPUARMState *env, uint64_t addr, uint64_t new_lo, uint64_t new_hi) { return do_paired_cmpxchg64_be(env, addr, new_lo, new_hi, false, GETPC()); Int128 oldv, cmpv, newv; uintptr_t ra = GETPC(); bool success; int mem_idx; TCGMemOpIdx oi; if (!HAVE_CMPXCHG128) { cpu_loop_exit_atomic(ENV_GET_CPU(env), ra); } uint64_t HELPER(paired_cmpxchg64_be_parallel)(CPUARMState *env, uint64_t addr, uint64_t new_lo, uint64_t new_hi) { return do_paired_cmpxchg64_be(env, addr, new_lo, new_hi, true, GETPC()); mem_idx = cpu_mmu_index(env, false); oi = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx); /* * High and low need to be switched here because this is not actually a * 128bit store but two doublewords stored consecutively */ cmpv = int128_make128(env->exclusive_high, env->exclusive_val); newv = int128_make128(new_hi, new_lo); oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra); success = int128_eq(oldv, cmpv); return !success; } /* Writes back the old data into Rs. */ void HELPER(casp_le_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr, uint64_t new_lo, uint64_t new_hi) { Int128 oldv, cmpv, newv; uintptr_t ra = GETPC(); #ifndef CONFIG_ATOMIC128 int mem_idx; TCGMemOpIdx oi; if (!HAVE_CMPXCHG128) { cpu_loop_exit_atomic(ENV_GET_CPU(env), ra); #else Int128 oldv, cmpv, newv; } mem_idx = cpu_mmu_index(env, false); oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx); cmpv = int128_make128(env->xregs[rs], env->xregs[rs + 1]); newv = int128_make128(new_lo, new_hi); int mem_idx = cpu_mmu_index(env, false); TCGMemOpIdx oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx); oldv = helper_atomic_cmpxchgo_le_mmu(env, addr, cmpv, newv, oi, ra); env->xregs[rs] = int128_getlo(oldv); env->xregs[rs + 1] = int128_gethi(oldv); #endif } void HELPER(casp_be_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr, uint64_t new_hi, uint64_t new_lo) { Int128 oldv, cmpv, newv; uintptr_t ra = GETPC(); #ifndef CONFIG_ATOMIC128 int mem_idx; TCGMemOpIdx oi; if (!HAVE_CMPXCHG128) { cpu_loop_exit_atomic(ENV_GET_CPU(env), ra); #else Int128 oldv, cmpv, newv; } mem_idx = cpu_mmu_index(env, false); oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx); cmpv = int128_make128(env->xregs[rs + 1], env->xregs[rs]); newv = int128_make128(new_lo, new_hi); int mem_idx = cpu_mmu_index(env, false); TCGMemOpIdx oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx); oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra); env->xregs[rs + 1] = int128_getlo(oldv); env->xregs[rs] = int128_gethi(oldv); #endif } /* Loading Loading
target/arm/helper-a64.c +134 −127 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include "exec/exec-all.h" #include "exec/cpu_ldst.h" #include "qemu/int128.h" #include "qemu/atomic128.h" #include "tcg.h" #include "fpu/softfloat.h" #include <zlib.h> /* For crc32 */ Loading Loading @@ -509,28 +510,15 @@ uint64_t HELPER(crc32c_64)(uint64_t acc, uint64_t val, uint32_t bytes) return crc32c(acc, buf, bytes) ^ 0xffffffff; } /* Returns 0 on success; 1 otherwise. */ static uint64_t do_paired_cmpxchg64_le(CPUARMState *env, uint64_t addr, uint64_t new_lo, uint64_t new_hi, bool parallel, uintptr_t ra) uint64_t HELPER(paired_cmpxchg64_le)(CPUARMState *env, uint64_t addr, uint64_t new_lo, uint64_t new_hi) { Int128 oldv, cmpv, newv; bool success; cmpv = int128_make128(env->exclusive_val, env->exclusive_high); newv = int128_make128(new_lo, new_hi); if (parallel) { #ifndef CONFIG_ATOMIC128 cpu_loop_exit_atomic(ENV_GET_CPU(env), ra); #else int mem_idx = cpu_mmu_index(env, false); TCGMemOpIdx oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx); oldv = helper_atomic_cmpxchgo_le_mmu(env, addr, cmpv, newv, oi, ra); success = int128_eq(oldv, cmpv); #endif } else { Int128 cmpv = int128_make128(env->exclusive_val, env->exclusive_high); Int128 newv = int128_make128(new_lo, new_hi); Int128 oldv; uintptr_t ra = GETPC(); uint64_t o0, o1; bool success; #ifdef CONFIG_USER_ONLY /* ??? Enforce alignment. */ Loading Loading @@ -562,47 +550,47 @@ static uint64_t do_paired_cmpxchg64_le(CPUARMState *env, uint64_t addr, helper_le_stq_mmu(env, addr + 8, int128_gethi(newv), oi1, ra); } #endif } return !success; } uint64_t HELPER(paired_cmpxchg64_le)(CPUARMState *env, uint64_t addr, uint64_t HELPER(paired_cmpxchg64_le_parallel)(CPUARMState *env, uint64_t addr, uint64_t new_lo, uint64_t new_hi) { return do_paired_cmpxchg64_le(env, addr, new_lo, new_hi, false, GETPC()); Int128 oldv, cmpv, newv; uintptr_t ra = GETPC(); bool success; int mem_idx; TCGMemOpIdx oi; if (!HAVE_CMPXCHG128) { cpu_loop_exit_atomic(ENV_GET_CPU(env), ra); } uint64_t HELPER(paired_cmpxchg64_le_parallel)(CPUARMState *env, uint64_t addr, uint64_t new_lo, uint64_t new_hi) { return do_paired_cmpxchg64_le(env, addr, new_lo, new_hi, true, GETPC()); mem_idx = cpu_mmu_index(env, false); oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx); cmpv = int128_make128(env->exclusive_val, env->exclusive_high); newv = int128_make128(new_lo, new_hi); oldv = helper_atomic_cmpxchgo_le_mmu(env, addr, cmpv, newv, oi, ra); success = int128_eq(oldv, cmpv); return !success; } static uint64_t do_paired_cmpxchg64_be(CPUARMState *env, uint64_t addr, uint64_t new_lo, uint64_t new_hi, bool parallel, uintptr_t ra) uint64_t HELPER(paired_cmpxchg64_be)(CPUARMState *env, uint64_t addr, uint64_t new_lo, uint64_t new_hi) { Int128 oldv, cmpv, newv; bool success; /* high and low need to be switched here because this is not actually a /* * High and low need to be switched here because this is not actually a * 128bit store but two doublewords stored consecutively */ cmpv = int128_make128(env->exclusive_high, env->exclusive_val); newv = int128_make128(new_hi, new_lo); if (parallel) { #ifndef CONFIG_ATOMIC128 cpu_loop_exit_atomic(ENV_GET_CPU(env), ra); #else int mem_idx = cpu_mmu_index(env, false); TCGMemOpIdx oi = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx); oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra); success = int128_eq(oldv, cmpv); #endif } else { Int128 cmpv = int128_make128(env->exclusive_val, env->exclusive_high); Int128 newv = int128_make128(new_lo, new_hi); Int128 oldv; uintptr_t ra = GETPC(); uint64_t o0, o1; bool success; #ifdef CONFIG_USER_ONLY /* ??? Enforce alignment. */ Loading Loading @@ -634,64 +622,83 @@ static uint64_t do_paired_cmpxchg64_be(CPUARMState *env, uint64_t addr, helper_be_stq_mmu(env, addr + 8, int128_getlo(newv), oi1, ra); } #endif } return !success; } uint64_t HELPER(paired_cmpxchg64_be)(CPUARMState *env, uint64_t addr, uint64_t HELPER(paired_cmpxchg64_be_parallel)(CPUARMState *env, uint64_t addr, uint64_t new_lo, uint64_t new_hi) { return do_paired_cmpxchg64_be(env, addr, new_lo, new_hi, false, GETPC()); Int128 oldv, cmpv, newv; uintptr_t ra = GETPC(); bool success; int mem_idx; TCGMemOpIdx oi; if (!HAVE_CMPXCHG128) { cpu_loop_exit_atomic(ENV_GET_CPU(env), ra); } uint64_t HELPER(paired_cmpxchg64_be_parallel)(CPUARMState *env, uint64_t addr, uint64_t new_lo, uint64_t new_hi) { return do_paired_cmpxchg64_be(env, addr, new_lo, new_hi, true, GETPC()); mem_idx = cpu_mmu_index(env, false); oi = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx); /* * High and low need to be switched here because this is not actually a * 128bit store but two doublewords stored consecutively */ cmpv = int128_make128(env->exclusive_high, env->exclusive_val); newv = int128_make128(new_hi, new_lo); oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra); success = int128_eq(oldv, cmpv); return !success; } /* Writes back the old data into Rs. */ void HELPER(casp_le_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr, uint64_t new_lo, uint64_t new_hi) { Int128 oldv, cmpv, newv; uintptr_t ra = GETPC(); #ifndef CONFIG_ATOMIC128 int mem_idx; TCGMemOpIdx oi; if (!HAVE_CMPXCHG128) { cpu_loop_exit_atomic(ENV_GET_CPU(env), ra); #else Int128 oldv, cmpv, newv; } mem_idx = cpu_mmu_index(env, false); oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx); cmpv = int128_make128(env->xregs[rs], env->xregs[rs + 1]); newv = int128_make128(new_lo, new_hi); int mem_idx = cpu_mmu_index(env, false); TCGMemOpIdx oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx); oldv = helper_atomic_cmpxchgo_le_mmu(env, addr, cmpv, newv, oi, ra); env->xregs[rs] = int128_getlo(oldv); env->xregs[rs + 1] = int128_gethi(oldv); #endif } void HELPER(casp_be_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr, uint64_t new_hi, uint64_t new_lo) { Int128 oldv, cmpv, newv; uintptr_t ra = GETPC(); #ifndef CONFIG_ATOMIC128 int mem_idx; TCGMemOpIdx oi; if (!HAVE_CMPXCHG128) { cpu_loop_exit_atomic(ENV_GET_CPU(env), ra); #else Int128 oldv, cmpv, newv; } mem_idx = cpu_mmu_index(env, false); oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx); cmpv = int128_make128(env->xregs[rs + 1], env->xregs[rs]); newv = int128_make128(new_lo, new_hi); int mem_idx = cpu_mmu_index(env, false); TCGMemOpIdx oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx); oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra); env->xregs[rs + 1] = int128_getlo(oldv); env->xregs[rs] = int128_gethi(oldv); #endif } /* Loading