about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/arm64_emitter.h18
-rwxr-xr-xsrc/dynarec/arm64_printer.c9
-rwxr-xr-xsrc/dynarec/dynarec_arm64_00.c30
-rwxr-xr-xsrc/dynarec/dynarec_arm64_helper.h8
4 files changed, 62 insertions, 3 deletions
diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h
index a2ad2561..e59a9cbf 100755
--- a/src/dynarec/arm64_emitter.h
+++ b/src/dynarec/arm64_emitter.h
@@ -283,7 +283,20 @@
 #define POP1(reg)       LDRx_S9_postindex(reg, xRSP, 8)
 #define PUSH1(reg)      STRx_S9_preindex(reg, xRSP, -8)
 
-// BR and branchs
+// LOAD/STORE Exclusive
+#define MEMX_gen(size, L, Rs, Rn, Rt)       ((size)<<30 | 0b001000<<24 | (L)<<22 | (Rs)<<16 | 1<<15 | 0b11111<<10 | (Rn)<<5 | (Rt))
+#define LDAXRB(Rt, Rn)                  EMIT(MEMX_gen(0b00, 1, 31, Rn, Rt))
+#define STLXRB(Rs, Rt, Rn)              EMIT(MEMX_gen(0b00, 0, Rs, Rn, Rt))
+#define LDAXRH(Rt, Rn)                  EMIT(MEMX_gen(0b01, 1, 31, Rn, Rt))
+#define STLXRH(Rs, Rt, Rn)              EMIT(MEMX_gen(0b01, 0, Rs, Rn, Rt))
+#define LDAXRw(Rt, Rn)                  EMIT(MEMX_gen(0b10, 1, 31, Rn, Rt))
+#define STLXRw(Rs, Rt, Rn)              EMIT(MEMX_gen(0b10, 0, Rs, Rn, Rt))
+#define LDAXRx(Rt, Rn)                  EMIT(MEMX_gen(0b11, 1, 31, Rn, Rt))
+#define STLXRx(Rs, Rt, Rn)              EMIT(MEMX_gen(0b11, 0, Rs, Rn, Rt))
+#define LDAXRxw(Rt, Rn)                 EMIT(MEMX_gen(2+rex.w, 1, 31, Rn, Rt))
+#define STLXRxw(Rs, Rt, Rn)             EMIT(MEMX_gen(2+rex.w, 0, Rs, Rn, Rt))
+
+// BR and Branches
 #define BR_gen(Z, op, A, M, Rn, Rm)       (0b1101011<<25 | (Z)<<24 | (op)<<21 | 0b11111<<16 | (A)<<11 | (M)<<10 | (Rn)<<5 | (Rm))
 #define BR(Rn)                            EMIT(BR_gen(0, 0b00, 0, 0, Rn, 0))
 #define BLR(Rn)                           EMIT(BR_gen(0, 0b01, 0, 0, Rn, 0))
@@ -326,9 +339,8 @@
 #define ORRw_mask(Rd, Rn, immr, imms)       EMIT(LOGIC_gen(0, 0b01, 0, immr, imms, Rn, Rd))
 #define EORx_mask(Rd, Rn, N, immr, imms)    EMIT(LOGIC_gen(1, 0b10, N, immr, imms, Rn, Rd))
 #define EORw_mask(Rd, Rn, immr, imms)       EMIT(LOGIC_gen(0, 0b10, 0, immr, imms, Rn, Rd))
-#define TSTx_mask(Rn, immr, imms)           ANDSx_mask(xZR, Rn, immr, imms)
+#define TSTx_mask(Rn, N, immr, imms)        ANDSx_mask(xZR, Rn, N, immr, imms)
 #define TSTw_mask(Rn, immr, imms)           ANDSw_mask(wZR, Rn, immr, imms)
-#define TSTxw_mask(Rn, immr, imms)          ANDSxw_mask(xZR, Rn, immr, imms)
 
 #define LOGIC_REG_gen(sf, opc, shift, N, Rm, imm6, Rn, Rd)    ((sf)<<31 | (opc)<<29 | 0b01010<<24 | (shift)<<22 | (N)<<21 | (Rm)<<16 | (imm6)<<10 | (Rn)<<5 | (Rd))
 #define ANDx_REG(Rd, Rn, Rm)            EMIT(LOGIC_REG_gen(1, 0b00, 0b00, 0, Rm, 0, Rn, Rd))
diff --git a/src/dynarec/arm64_printer.c b/src/dynarec/arm64_printer.c
index b068b9d8..103e6aff 100755
--- a/src/dynarec/arm64_printer.c
+++ b/src/dynarec/arm64_printer.c
@@ -106,6 +106,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
     #define Rm a.m

     #define Rd a.d

     #define Ra a.a

+    #define Rs a.s

     #define sf a.f

     #define imm a.i

     #define option a.o

@@ -275,6 +276,14 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
         return buff;

     }

 

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

+        if(a.L)

+            snprintf(buff, sizeof(buff), "LDAXR%s %s, [%s]", (sf==0)?"B":((sf==1)?"H":""), (sf==2)?Wt[Rt]:Xt[Rt], XtSp[Rn]);

+        else

+            snprintf(buff, sizeof(buff), "STLXR%s %s, %s, [%s]", (sf==0)?"B":((sf==1)?"H":""), (sf==2)?Wt[Rs]:Xt[Rs], (sf==2)?Wt[Rt]:Xt[Rt], XtSp[Rn]);

+        return buff;

+    }

+

     // --- MOV (REGS: see Logic MOV==ORR, MVN==ORN)

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

         if(!hw)

diff --git a/src/dynarec/dynarec_arm64_00.c b/src/dynarec/dynarec_arm64_00.c
index 3bf36e57..bb51582a 100755
--- a/src/dynarec/dynarec_arm64_00.c
+++ b/src/dynarec/dynarec_arm64_00.c
@@ -830,6 +830,36 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             emit_test32(dyn, ninst, rex, ed, gd, x3, x5);
             break;
 
+        case 0x87:
+            INST_NAME("(LOCK)XCHG Ed, Gd");
+            nextop = F8;
+            if(MODREG) {
+                GETGD;
+                GETED(0);
+                MOVxw_REG(x1, gd);
+                MOVxw_REG(gd, ed);
+                MOVxw_REG(ed, x1);
+            } else {
+                GETGD;
+                addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
+                if(rex.w) {
+                    TSTx_mask(ed, 1, 0, 2);    // mask=7
+                } else {
+                    TSTw_mask(ed, 0, 1);    // mask=3
+                }
+                B_MARK(cNE);
+                MARKLOCK;
+                LDAXRxw(x1, ed);
+                STLXRxw(x3, gd, ed);
+                CBZx_MARKLOCK(x3);
+                B_MARK2_nocond;
+                MARK;
+                LDRxw_U12(x1, ed, 0);
+                STRxw_U12(gd, ed, 0);
+                MARK2;
+                MOVxw_REG(gd, x1);
+            }
+            break;
         case 0x88:
             INST_NAME("MOV Eb, Gb");
             nextop = F8;
diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h
index ed8fd357..91bc4f83 100755
--- a/src/dynarec/dynarec_arm64_helper.h
+++ b/src/dynarec/dynarec_arm64_helper.h
@@ -261,6 +261,10 @@
 #define B_MARK2(cond)    \
     j32 = GETMARK2-(dyn->arm_size);   \
     Bcond(cond, j32)
+// Branch to MARK2 unconditionnal (use j32)
+#define B_MARK2_nocond    \
+    j32 = GETMARK2-(dyn->arm_size);   \
+    B(j32)
 // Branch to MARK3 if cond (use j32)
 #define B_MARK3(cond)    \
     j32 = GETMARK3-(dyn->arm_size);   \
@@ -289,6 +293,10 @@
 #define B_MARKLOCK(cond)    \
     j32 = GETMARKLOCK-(dyn->arm_size);   \
     Bcond(cond, j32)
+// Branch to MARKLOCK if reg is not 0 (use j32)
+#define CBZx_MARKLOCK(reg)    \
+    j32 = GETMARKLOCK-(dyn->arm_size);   \
+    CBNZx(reg, j32)
 
 #define IFX(A)  if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(A)))
 #define IFXX(A) if(dyn->insts && (dyn->insts[ninst].x64.need_flags==(A)))