about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorYang Liu <numbksco@gmail.com>2024-06-01 23:14:23 +0800
committerGitHub <noreply@github.com>2024-06-01 17:14:23 +0200
commit9dbd7fc7e0615f48c9287305610bf9aed1cc24f3 (patch)
tree0a9cd649a22b32cf99a59810f77cba6c557f4075
parenta79eff3b0da5056e2226b7830aa5089e68c91451 (diff)
downloadbox64-9dbd7fc7e0615f48c9287305610bf9aed1cc24f3.tar.gz
box64-9dbd7fc7e0615f48c9287305610bf9aed1cc24f3.zip
[INTERP] Rework on the 16b emulation for LA64 (#1547)
* [INTERP] Rework on the 16b emulation for LA64

* fix compiler issue
-rw-r--r--src/dynarec/la64/la64_lock.S3
-rw-r--r--src/dynarec/native_lock.h9
-rw-r--r--src/dynarec/rv64/rv64_lock.S11
-rw-r--r--src/emu/x64runf0.c43
4 files changed, 34 insertions, 32 deletions
diff --git a/src/dynarec/la64/la64_lock.S b/src/dynarec/la64/la64_lock.S
index 48f21595..18736afd 100644
--- a/src/dynarec/la64/la64_lock.S
+++ b/src/dynarec/la64/la64_lock.S
@@ -191,9 +191,8 @@ la64_lock_cas_dd:
 la64_lock_cas_dq:
     ll.d $a4, $a0, 0
     bne  $a4, $a2, 1f
-    sc.d $a1, $a0, 0
+    .word 0x38571c85 // sc.q $a1, $a3, $a0
     beqz $a1, 1f
-    st.d $a3, $a0, 8
     xori $a0, $a1, 1
     ret
 1:
diff --git a/src/dynarec/native_lock.h b/src/dynarec/native_lock.h
index 33626a63..1ed26e8f 100644
--- a/src/dynarec/native_lock.h
+++ b/src/dynarec/native_lock.h
@@ -66,13 +66,8 @@
 #define native_lock_write_d(A, B)           rv64_lock_cas_d(A, tmpcas, B)

 #define native_lock_read_dd(A)              tmpcas=*(uint64_t*)(A)

 #define native_lock_write_dd(A, B)          rv64_lock_cas_dd(A, tmpcas, B)

-// there is no atomic move on 16bytes, so faking it

-#define native_lock_read_dq(A, B, C)       \

-    do {                                   \

-        *A = tmpcas = ((uint64_t*)(C))[0]; \

-        *B = ((uint64_t*)(C))[1];          \

-    } while (0)

-#define native_lock_write_dq(A, B, C)       rv64_lock_cas_dq(C, A, tmpcas, B);

+#define native_lock_read_dq(A, B, C)        // never used

+#define native_lock_write_dq(A, B, C)       // never used

 #define native_lock_get_b(A)                rv64_lock_get_b(A)

 #define native_lock_get_d(A)                rv64_lock_get_d(A)

 #define native_lock_get_dd(A)               rv64_lock_get_dd(A)

diff --git a/src/dynarec/rv64/rv64_lock.S b/src/dynarec/rv64/rv64_lock.S
index 2b48163b..a525c999 100644
--- a/src/dynarec/rv64/rv64_lock.S
+++ b/src/dynarec/rv64/rv64_lock.S
@@ -229,17 +229,6 @@ rv64_lock_cas_dd:
     li a0, 1
     ret
 
-rv64_lock_cas_dq:
-    mv a4, a0
-    lr.d t0, (a0)
-    bne t0, a1, 1f
-    sc.d a0, a2, (a0)
-    sd a3,(a4)
-    ret
-1:
-    li a0, 1
-    ret
-
 rv64_lock_get_b:
     fence   rw, rw
     lb      a0, 0(a0)
diff --git a/src/emu/x64runf0.c b/src/emu/x64runf0.c
index ce7145fc..c44100c5 100644
--- a/src/emu/x64runf0.c
+++ b/src/emu/x64runf0.c
@@ -746,19 +746,38 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
 #if defined(DYNAREC) && !defined(TEST_INTERPRETER)

                             if (rex.w) {

 #if defined(__riscv) || defined(__loongarch64)

-                                while (native_lock_xchg_d(&emu->context->mutex_16b, 1)); // lock

-                                tmp64u = ((uint64_t*)ED)[0];

-                                tmp64u2 = ((uint64_t*)ED)[1];

-                                if(R_RAX == tmp64u && R_RDX == tmp64u2) {

-                                    SET_FLAG(F_ZF);

-                                    ((uint64_t*)ED)[0] = R_RBX;

-                                    ((uint64_t*)ED)[1] = R_RCX;

-                                } else {

-                                    CLEAR_FLAG(F_ZF);

-                                    R_RAX = tmp64u;

-                                    R_RDX = tmp64u2;

+#if defined(__loongarch64)

+                                if (la64_scq) {

+                                    do {

+                                        native_lock_read_dq(&tmp64u, &tmp64u2, ED);

+                                        if (R_RAX == tmp64u && R_RDX == tmp64u2) {

+                                            SET_FLAG(F_ZF);

+                                            tmp32s = native_lock_write_dq(R_RBX, R_RCX, ED);

+                                        } else {

+                                            CLEAR_FLAG(F_ZF);

+                                            R_RAX = tmp64u;

+                                            R_RDX = tmp64u2;

+                                            tmp32s = 0;

+                                        }

+                                    } while (tmp32s);

+                                } else

+#endif

+                                {

+                                    while (native_lock_xchg_d(&emu->context->mutex_16b, 1))

+                                        ; // lock

+                                    tmp64u = ((uint64_t*)ED)[0];

+                                    tmp64u2 = ((uint64_t*)ED)[1];

+                                    if (R_RAX == tmp64u && R_RDX == tmp64u2) {

+                                        SET_FLAG(F_ZF);

+                                        ((uint64_t*)ED)[0] = R_RBX;

+                                        ((uint64_t*)ED)[1] = R_RCX;

+                                    } else {

+                                        CLEAR_FLAG(F_ZF);

+                                        R_RAX = tmp64u;

+                                        R_RDX = tmp64u2;

+                                    }

+                                    native_lock_xchg_d(&emu->context->mutex_16b, 0); // unlock

                                 }

-                                native_lock_xchg_d(&emu->context->mutex_16b, 0); // unlock

 #else

                                 if(((uintptr_t)ED)&0xf) {

                                     do {