about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-22 18:27:03 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-22 18:27:03 +0100
commitb14be7f6142676daddc66749b42758c858c6fed4 (patch)
treebc2c2ac718c769370012493528ece3d0084af4b1 /src
parent35f8500acdcb84568579db604f47d5cfdd532012 (diff)
downloadbox64-b14be7f6142676daddc66749b42758c858c6fed4.tar.gz
box64-b14be7f6142676daddc66749b42758c858c6fed4.zip
[DYNAREC] Added (F2/F3) A6 opcode
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/arm64_emitter.h4
-rwxr-xr-xsrc/dynarec/arm64_printer.c15
-rwxr-xr-xsrc/dynarec/dynarec_arm64_00.c46
-rwxr-xr-xsrc/dynarec/dynarec_arm64_helper.h4
4 files changed, 67 insertions, 2 deletions
diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h
index ecf35d50..e4fb4572 100755
--- a/src/dynarec/arm64_emitter.h
+++ b/src/dynarec/arm64_emitter.h
@@ -323,6 +323,10 @@
 #define CBZw(Rt, imm19)                 EMIT(CB_gen(0, 0, ((imm19)>>2)&0x7FFFF, Rt))
 #define CBZxw(Rt, imm19)                EMIT(CB_gen(rex.w, 0, ((imm19)>>2)&0x7FFFF, Rt))
 
+#define TB_gen(b5, op, b40, imm14, Rt)  ((b5)<<31 | 0b011011<<25 | (op)<<24  | (b40)<<19 | (imm14)<<5 | (Rt))
+#define TBZ(Rt, bit, imm16)             EMIT(TB_gen(((bit)>>5)&1, 0, (bit)&0x1f, ((imm19)>>2)&0x3FFF, Rt))
+#define TBNZ(Rt, bit, imm16)            EMIT(TB_gen(((bit)>>5)&1, 1, (bit)&0x1f, ((imm19)>>2)&0x3FFF, Rt))
+
 #define Bcond_gen(imm19, cond)          (0b0101010<<25 | (imm19)<<5 | (cond))
 #define Bcond(cond, imm19)              EMIT(Bcond_gen(((imm19)>>2)&0x7FFFF, cond))
 
diff --git a/src/dynarec/arm64_printer.c b/src/dynarec/arm64_printer.c
index c5c09e62..0f894ea7 100755
--- a/src/dynarec/arm64_printer.c
+++ b/src/dynarec/arm64_printer.c
@@ -665,8 +665,19 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
         snprintf(buff, sizeof(buff), "CBNZ %s, #%+di\t; %p", Xt[Rt], offset>>2, (void*)(addr + offset));

         return buff;

     }

-    if(isMask(opcode, "f0011010100mmmmmcccc00nnnnnddddd", &a)) {

-        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]);

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

+        int offset = signExtend(imm, 19)<<2;

+        snprintf(buff, sizeof(buff), "CBZ %s, #%+di\t; %p", Xt[Rt], offset>>2, (void*)(addr + offset));

+        return buff;

+    }

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

+        int offset = signExtend(imm, 14)<<2;

+        snprintf(buff, sizeof(buff), "TBZ %s, 0x%x, #%+di\t; %p", (imms<31)?Xt[Rt]:Wt[Rt], imms, offset>>2, (void*)(addr + offset));

+        return buff;

+    }

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

+        int offset = signExtend(imm, 14)<<2;

+        snprintf(buff, sizeof(buff), "TBNZ %s, 0x%x, #%+di\t; %p", (imms<31)?Xt[Rt]:Wt[Rt], imms, offset>>2, (void*)(addr + offset));

         return buff;

     }

 

diff --git a/src/dynarec/dynarec_arm64_00.c b/src/dynarec/dynarec_arm64_00.c
index 99a2cab6..a4351282 100755
--- a/src/dynarec/dynarec_arm64_00.c
+++ b/src/dynarec/dynarec_arm64_00.c
@@ -989,6 +989,52 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 ADDx_REG(xRDI, xRDI, x3);
             }
             break;
+        case 0xA6:
+            switch(rep) {
+            case 1:
+                INST_NAME("REPZ CMPSB");
+                SETFLAGS(X_ALL, SF_SET);
+                GETDIR(x3, 1);
+                CBZx_NEXT(xRCX);
+                MARK;
+                LDRB_U12(x1, xRSI, 0);
+                LDRB_U12(x2, xRDI, 0);
+                ADDx_REG(xRSI, xRSI, x3);
+                ADDx_REG(xRDI, xRDI, x3);
+                SUBx_U12(xRCX, xRCX, 1);
+                CMPSw_REG(x1, x2);
+                Bcond(cEQ, 4+4);
+                CBNZx_MARK(xRCX);
+                emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5);
+                break;
+            case 2:
+                INST_NAME("REPNZ CMPSB");
+                SETFLAGS(X_ALL, SF_SET);
+                GETDIR(x3, 1);
+                CBZx_NEXT(xRCX);
+                MARK;
+                LDRB_U12(x1, xRSI, 0);
+                LDRB_U12(x2, xRDI, 0);
+                ADDx_REG(xRSI, xRSI, x3);
+                ADDx_REG(xRDI, xRDI, x3);
+                SUBx_U12(xRCX, xRCX, 1);
+                CMPSw_REG(x1, x2);
+                Bcond(cNE, 4+4);
+                CBNZx_MARK(xRCX);
+                emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5);
+                break;
+            default:
+                INST_NAME("CMPSB");
+                SETFLAGS(X_ALL, SF_SET);
+                GETDIR(x3, 1);
+                LDRB_U12(x1, xRSI, 0);
+                LDRB_U12(x2, xRDI, 0);
+                ADDx_REG(xRSI, xRSI, x3);
+                ADDx_REG(xRDI, xRDI, x3);
+                emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5);
+                break;
+            }
+            break;
 
         case 0xA8:
             INST_NAME("TEST AL, Ib");
diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h
index d4920dec..94cdd652 100755
--- a/src/dynarec/dynarec_arm64_helper.h
+++ b/src/dynarec/dynarec_arm64_helper.h
@@ -297,6 +297,10 @@
 #define CBZw_NEXT(reg)    \
     j32 =  (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
     CBZw(reg, j32)
+// Branch to next instruction if reg is 0 (use j32)
+#define CBZx_NEXT(reg)    \
+    j32 =  (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
+    CBZx(reg, j32)
 // Branch to MARKSEG if cond (use j32)
 #define B_MARKSEG(cond)    \
     j32 = GETMARKSEG-(dyn->arm_size);   \