qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC 06/30] target-i386: emulate LOCK'ed cmpxchg8b/16b usin


From: Emilio G. Cota
Subject: [Qemu-devel] [RFC 06/30] target-i386: emulate LOCK'ed cmpxchg8b/16b using cmpxchg helpers
Date: Mon, 27 Jun 2016 15:01:52 -0400

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 <address@hidden>
---
 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]