about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-04-16 15:46:03 +0200
committerptitSeb <sebastien.chev@gmail.com>2021-04-16 15:46:03 +0200
commit7a95dcd6b6bf51cde91d0cc2a17107b49d17a376 (patch)
treef0689a01a5897f6a851e07cc9f148ff21746a488 /src
parent47d0c04b30fe953db0d7dd77b6c46a5f62f4464b (diff)
downloadbox64-7a95dcd6b6bf51cde91d0cc2a17107b49d17a376.tar.gz
box64-7a95dcd6b6bf51cde91d0cc2a17107b49d17a376.zip
Added E0..E3 opcodes ([DYNAREC] too)
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/dynarec_arm64_00.c43
-rwxr-xr-xsrc/dynarec/dynarec_arm64_helper.h8
-rwxr-xr-xsrc/emu/x64run.c29
3 files changed, 80 insertions, 0 deletions
diff --git a/src/dynarec/dynarec_arm64_00.c b/src/dynarec/dynarec_arm64_00.c
index 2f89297e..98ccde9f 100755
--- a/src/dynarec/dynarec_arm64_00.c
+++ b/src/dynarec/dynarec_arm64_00.c
@@ -1871,6 +1871,49 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0xDF:
             addr = dynarec64_DF(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
             break;
+        #define GO(Z)                                                   \
+            BARRIER(2);                                                 \
+            JUMP(addr+i8);                                              \
+            if(dyn->insts) {                                            \
+                if(dyn->insts[ninst].x64.jmp_insts==-1) {               \
+                    /* out of the block */                              \
+                    i32 = dyn->insts[ninst+1].address-(dyn->arm_size);  \
+                    if(Z) {CBNZx(xRCX, i32);} else {CBZx(xRCX, i32);};  \
+                    jump_to_next(dyn, addr+i8, 0, ninst);               \
+                } else {                                                \
+                    /* inside the block */                              \
+                    i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size);    \
+                    if(Z) {CBZx(xRCX, i32);} else {CBNZx(xRCX, i32);};  \
+                }   \
+            }
+        case 0xE0:
+            INST_NAME("LOOPNZ");
+            READFLAGS(X_ZF);
+            i8 = F8S;
+            SUBx_U12(xRCX, xRCX, 1);
+            TBNZ_NEXT(xFlags, 1<<F_ZF);
+            GO(0);
+            break;
+        case 0xE1:
+            INST_NAME("LOOPZ");
+            READFLAGS(X_ZF);
+            i8 = F8S;
+            SUBx_U12(xRCX, xRCX, 1);
+            TBZ_NEXT(xFlags, 1<<F_ZF);
+            GO(0);
+            break;
+        case 0xE2:
+            INST_NAME("LOOP");
+            i8 = F8S;
+            SUBx_U12(xRCX, xRCX, 1);
+            GO(0);
+            break;
+        case 0xE3:
+            INST_NAME("JECXZ");
+            i8 = F8S;
+            GO(1);
+            break;
+        #undef GO
 
         case 0xE8:
             INST_NAME("CALL Id");
diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h
index 854a6457..dfa6f4ce 100755
--- a/src/dynarec/dynarec_arm64_helper.h
+++ b/src/dynarec/dynarec_arm64_helper.h
@@ -328,10 +328,18 @@
 #define CBZx_NEXT(reg)    \
     j64 =  (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
     CBZx(reg, j64)
+// Branch to next instruction if reg is not 0 (use j64)
+#define CBNZx_NEXT(reg)   \
+    j64 =  (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
+    CBNZx(reg, j64)
 // Test bit N of A and branch to next instruction if not set
 #define TBZ_NEXT(A, N)              \
     j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
     TBZ(A, N, j64)
+// Test bit N of A and branch to next instruction if set
+#define TBNZ_NEXT(A, N)             \
+    j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
+    TBNZ(A, N, j64)
 // Branch to MARKSEG if cond (use j64)
 #define B_MARKSEG(cond)    \
     j64 = GETMARKSEG-(dyn->arm_size);   \
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
index c08c1ac0..1fcc6d2f 100755
--- a/src/emu/x64run.c
+++ b/src/emu/x64run.c
@@ -1146,6 +1146,35 @@ x64emurun:
             if(emu->quit)
                 goto fini;
             break;
+        case 0xE0:                      /* LOOPNZ */
+            CHECK_FLAGS(emu);
+            tmp8s = F8S;
+            --R_RCX; // don't update flags
+            if(R_RCX && !ACCESS_FLAG(F_ZF))
+                R_RIP += tmp8s;
+            STEP
+            break;
+        case 0xE1:                      /* LOOPZ */
+            CHECK_FLAGS(emu);
+            tmp8s = F8S;
+            --R_RCX; // don't update flags
+            if(R_RCX && ACCESS_FLAG(F_ZF))
+                R_RIP += tmp8s;
+            STEP
+            break;
+        case 0xE2:                      /* LOOP */
+            tmp8s = F8S;
+            --R_RCX; // don't update flags
+            if(R_RCX)
+                R_RIP += tmp8s;
+            STEP
+            break;
+        case 0xE3:                      /* JECXZ */
+            tmp8s = F8S;
+            if(!R_RCX)
+                R_RIP += tmp8s;
+            STEP
+            break;
 
         case 0xE8:                      /* CALL Id */
             tmp32s = F32S; // call is relative