about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/arm64_emitter.h12
-rw-r--r--src/dynarec/arm64/arm64_printer.c10
-rw-r--r--src/dynarec/arm64/dynarec_arm64_66.c42
-rw-r--r--src/dynarec/arm64/dynarec_arm64_f0.c11
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.c2
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.h4
6 files changed, 59 insertions, 22 deletions
diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h
index 178c5b20..cbfa8371 100644
--- a/src/dynarec/arm64/arm64_emitter.h
+++ b/src/dynarec/arm64/arm64_emitter.h
@@ -200,6 +200,12 @@
 #define SBCSw_REG(Rd, Rn, Rm)       EMIT(ADDSUBC_gen(0, 1, 1, Rm, Rn, Rd))
 #define SBCSxw_REG(Rd, Rn, Rm)      EMIT(ADDSUBC_gen(rex.w, 1, 1, Rm, Rn, Rd))
 
+// CCMP compare if cond is true, set nzcv if false
+#define CCMP_reg(sf, Rm, cond, Rn, nzcv)    ((sf)<<31 | 1<<30 | 1<<29 | 0b11010010<<21 | (Rm)<<16 | (cond)<<12 | (Rn)<<5 | (nzcv))
+#define CCMPw(Wn, Wm, nzcv, cond)   EMIT(CCMP_reg(0, Wm, cond, Wn, nzcv))
+#define CCMPx(Xn, Xm, nzcv, cond)   EMIT(CCMP_reg(1, Xm, cond, Xn, nzcv))
+#define CCMPxw(Xn, Xm, nzcv, cond)  EMIT(CCMP_reg(rex.w, Xm, cond, Xn, nzcv))
+
 // ADR
 #define ADR_gen(immlo, immhi, Rd)   ((immlo)<<29 | 0b10000<<24 | (immhi)<<5 | (Rd))
 #define ADR_S20(Rd, imm)            EMIT(ADR_gen((imm)&3, ((imm)>>2)&0x7ffff, (Rd)))
@@ -430,6 +436,12 @@
 #define DMB_ISH()                       EMIT(DMB_gen(0b1011))
 #define DMB_SY()                        EMIT(DMB_gen(0b1111))
 
+// Data Synchronization Barrier
+#define DSB_gen(CRm)                    (0b1101010100<<22 | 0b011<<16 | 0b0011<<12 | (CRm)<<8 | 1<<7 | 0b00<<5 | 0b11111)
+#define DSB_ISH()                       EMIT(DSB_gen(0b1011))
+#define DSB_ISHST()                     EMIT(DSB_gen(0b1010))
+#define DSB_SY()                        EMIT(DSB_gen(0b1111))
+
 // Break
 #define BRK_gen(imm16)                  (0b11010100<<24 | 0b001<<21 | (((imm16)&0xffff)<<5))
 #define BRK(imm16)                      EMIT(BRK_gen(imm16))
diff --git a/src/dynarec/arm64/arm64_printer.c b/src/dynarec/arm64/arm64_printer.c
index eca8c632..572d645f 100644
--- a/src/dynarec/arm64/arm64_printer.c
+++ b/src/dynarec/arm64/arm64_printer.c
@@ -797,6 +797,11 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
         snprintf(buff, sizeof(buff), "CSEL %s, %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], conds[cond]);    

         return buff;

     }

+    if(isMask(opcode, "f1111010010mmmmmcccc00nnnnn0iiii", &a)) {

+        snprintf(buff, sizeof(buff), "CCMP %s, %s, %s 0x%x", sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], conds[cond], imm);

+        return buff;

+    }

+

     // MISC Bits

     if(isMask(opcode, "f10110101100000000010onnnnnddddd", &a)) {

         snprintf(buff, sizeof(buff), "CL%c %s, %s", option?'S':'Z', sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn]);

@@ -1621,6 +1626,11 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
         snprintf(buff, sizeof(buff), "DMB %s", (Rn==0b1011)?"ISH":"???");

         return buff;

     }

+    // DSB ISH/ISHST

+    if(isMask(opcode, "11010101000000110011nnnn10011111", &a)) {

+        snprintf(buff, sizeof(buff), "DSB %s", (Rn==0b1011)?"ISH":((Rn==0b1010)?"ISHST":"???"));

+        return buff;

+    }

 

     // CASxw

     if(isMask(opcode, "1f0010001L1ssssso11111nnnnnttttt", &a)) {

diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c
index bb4a757e..e8540776 100644
--- a/src/dynarec/arm64/dynarec_arm64_66.c
+++ b/src/dynarec/arm64/dynarec_arm64_66.c
@@ -591,18 +591,36 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             } else {

                 GETGD;

                 addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);

-                TSTx_mask(ed, 1, 0, 0);    // mask=1

-                B_MARK(cNE);

-                MARKLOCK;

-                LDAXRH(x1, ed);

-                STLXRH(x3, gd, ed);

-                CBNZx_MARKLOCK(x3);

-                B_MARK2_nocond;

-                MARK;

-                LDRH_U12(x1, ed, 0);

-                STRH_U12(gd, ed, 0);

-                MARK2;

-                SMDMB();

+                if(!ALIGNED_ATOMICH) {

+                    TSTx_mask(ed, 1, 0, 0);    // mask=1

+                    B_MARK(cNE);

+                }

+                if(arm64_atomics) {

+                    SWPALH(gd, x1, ed);

+                    SMDMB();

+                    if(!ALIGNED_ATOMICH) {

+                        B_MARK2_nocond;

+                    }

+                } else {

+                    MARKLOCK;

+                    LDAXRH(x1, ed);

+                    STLXRH(x3, gd, ed);

+                    CBNZx_MARKLOCK(x3);

+                    SMDMB();

+                    if(!ALIGNED_ATOMICH) {

+                        B_MARK2_nocond;

+                    }

+                }

+                if(!ALIGNED_ATOMICH) {

+                    MARK;

+                    LDRH_U12(x1, ed, 0);

+                    LDAXRB(x3, ed);

+                    STLXRB(x3, gd, ed);

+                    CBNZx_MARK(x3);

+                    STRH_U12(gd, ed, 0);

+                    SMDMB();

+                    MARK2;

+                }

                 BFIx(gd, x1, 0, 16);

             }

             break;

diff --git a/src/dynarec/arm64/dynarec_arm64_f0.c b/src/dynarec/arm64/dynarec_arm64_f0.c
index 033b1f81..09d053cb 100644
--- a/src/dynarec/arm64/dynarec_arm64_f0.c
+++ b/src/dynarec/arm64/dynarec_arm64_f0.c
@@ -612,10 +612,8 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                                 CASPALxw(x2, x4, wback);
                                 UFLAG_IF {
                                     CMPSxw_REG(x2, xRAX);
-                                    CSETw(x4, cEQ);
-                                    CMPSxw_REG(x3, xRDX);
-                                    CSETw(x5, cEQ);
-                                    ANDw_REG(x1, x4, x5);
+                                    CCMPxw(x3, xRDX, 0, cEQ);
+                                    CSETw(x1, cEQ);
                                 }
                                 MOVx_REG(xRAX, x2);
                                 MOVx_REG(xRDX, x3);
@@ -623,9 +621,8 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                                 MARKLOCK;
                                 LDAXPxw(x2, x3, wback);
                                 CMPSxw_REG(xRAX, x2);
-                                B_MARK(cNE);    // EAX != Ed[0]
-                                CMPSxw_REG(xRDX, x3);
-                                B_MARK(cNE);    // EDX != Ed[1]
+                                CCMPxw(xRDX, x3, 0, cEQ);
+                                B_MARK(cNE);    // EAX!=ED[0] || EDX!=Ed[1]
                                 STLXPxw(x4, xRBX, xRCX, wback);
                                 CBNZx_MARKLOCK(x4);
                                 UFLAG_IF {
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c
index d404c6f3..ab49bc1e 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.c
+++ b/src/dynarec/arm64/dynarec_arm64_helper.c
@@ -32,7 +32,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
 {
     MAYUSE(dyn); MAYUSE(ninst); MAYUSE(delta);
 
-    if(l==LOCK_LOCK) { SMDMB(); }
+    if(l==LOCK_LOCK) { /*SMDMB();*/DMB_ISH(); }
 
     if(rex.is32bits)
         return geted_32(dyn, addr, ninst, nextop, ed, hint, fixaddress, unscaled, absmax, mask, l, s);
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index b511457d..664ccaaf 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -55,9 +55,9 @@
 // Start of sequence
 #define SMSTART()   SMEND()
 // End of sequence
-#define SMEND()     if(dyn->smwrite && box64_dynarec_strongmem) {DMB_ISH();} dyn->smwrite=0; dyn->smread=0;
+#define SMEND()     if(dyn->smwrite && box64_dynarec_strongmem) {if(box64_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();}} dyn->smwrite=0; dyn->smread=0;
 // Force a Data memory barrier (for LOCK: prefix)
-#define SMDMB()     DMB_ISH(); dyn->smwrite=0; dyn->smread=1; dyn->smlastdmb = ninst
+#define SMDMB()     if(box64_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();} dyn->smwrite=0; dyn->smread=1; dyn->smlastdmb = ninst
 
 //LOCK_* define
 #define LOCK_LOCK   (int*)1