For consistency, rename the existing cmpxchg8b/16b helpers by appending _unlocked to them, to stress that they are not atomic.
Signed-off-by: Emilio G. Cota <c...@braap.org> --- target-i386/helper.h | 2 ++ target-i386/mem_helper.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++-- target-i386/translate.c | 12 +++++++++-- 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/target-i386/helper.h b/target-i386/helper.h index af84836..2bb0d1f 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -78,9 +78,11 @@ DEF_HELPER_4(cmpxchgb, tl, env, tl, tl, tl) DEF_HELPER_4(cmpxchgw, tl, env, tl, tl, tl) DEF_HELPER_4(cmpxchgl, tl, env, tl, tl, tl) DEF_HELPER_2(cmpxchg8b, void, env, tl) +DEF_HELPER_2(cmpxchg8b_unlocked, void, env, tl) #ifdef TARGET_X86_64 DEF_HELPER_4(cmpxchgq, tl, env, tl, tl, tl) DEF_HELPER_2(cmpxchg16b, void, env, tl) +DEF_HELPER_2(cmpxchg16b_unlocked, void, env, tl) #endif DEF_HELPER_1(single_step, void, env) DEF_HELPER_1(cpuid, void, env) diff --git a/target-i386/mem_helper.c b/target-i386/mem_helper.c index 3b17326..b002aba 100644 --- a/target-i386/mem_helper.c +++ b/target-i386/mem_helper.c @@ -71,7 +71,7 @@ GEN_CMPXCHG_HELPER(cmpxchgq) #endif #undef GEN_CMPXCHG_HELPER -void helper_cmpxchg8b(CPUX86State *env, target_ulong a0) +void helper_cmpxchg8b_unlocked(CPUX86State *env, target_ulong a0) { uint64_t d; int eflags; @@ -92,8 +92,36 @@ void helper_cmpxchg8b(CPUX86State *env, target_ulong a0) CC_SRC = eflags; } +void helper_cmpxchg8b(CPUX86State *env, target_ulong a0) +{ + uint64_t d; + uint64_t old; + uint64_t new; + int eflags; + + old = env->regs[R_EDX]; + old <<= 32; + old |= env->regs[R_EAX]; + + new = env->regs[R_ECX]; + new <<= 32; + new |= env->regs[R_EBX]; + + eflags = cpu_cc_compute_all(env, CC_OP); + + d = cpu_cmpxchgq_data_ra(env, a0, old, new, GETPC()); + if (d == old) { + eflags |= CC_Z; + } else { + env->regs[R_EDX] = (uint32_t)(d >> 32); + env->regs[R_EAX] = (uint32_t)d; + eflags &= ~CC_Z; + } + CC_SRC = eflags; +} + #ifdef TARGET_X86_64 -void helper_cmpxchg16b(CPUX86State *env, target_ulong a0) +void helper_cmpxchg16b_unlocked(CPUX86State *env, target_ulong a0) { uint64_t d0, d1; int eflags; @@ -118,6 +146,28 @@ void helper_cmpxchg16b(CPUX86State *env, target_ulong a0) } CC_SRC = eflags; } + +void helper_cmpxchg16b(CPUX86State *env, target_ulong a0) +{ + uint64_t d0 = env->regs[R_EAX]; + uint64_t d1 = env->regs[R_EDX]; + int eflags; + + if ((a0 & 0xf) != 0) { + raise_exception_ra(env, EXCP0D_GPF, GETPC()); + } + eflags = cpu_cc_compute_all(env, CC_OP); + + if (cpu_cmpxchgo_data_ra(env, a0, &d0, &d1, env->regs[R_EBX], + env->regs[R_ECX], GETPC())) { + eflags |= CC_Z; + } else { + env->regs[R_EDX] = d1; + env->regs[R_EAX] = d0; + eflags &= ~CC_Z; + } + CC_SRC = eflags; +} #endif void helper_boundw(CPUX86State *env, target_ulong a0, int v) diff --git a/target-i386/translate.c b/target-i386/translate.c index fba90e7..9abd82f 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -5166,14 +5166,22 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, if (!(s->cpuid_ext_features & CPUID_EXT_CX16)) goto illegal_op; gen_lea_modrm(env, s, modrm); - gen_helper_cmpxchg16b(cpu_env, cpu_A0); + if (s->prefix & PREFIX_LOCK) { + gen_helper_cmpxchg16b(cpu_env, cpu_A0); + } else { + gen_helper_cmpxchg16b_unlocked(cpu_env, cpu_A0); + } } else #endif { if (!(s->cpuid_features & CPUID_CX8)) goto illegal_op; gen_lea_modrm(env, s, modrm); - gen_helper_cmpxchg8b(cpu_env, cpu_A0); + if (s->prefix & PREFIX_LOCK) { + gen_helper_cmpxchg8b(cpu_env, cpu_A0); + } else { + gen_helper_cmpxchg8b_unlocked(cpu_env, cpu_A0); + } } set_cc_op(s, CC_OP_EFLAGS); break; -- 2.5.0