about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/dynarec/arm64/dynarec_arm64_67_32.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_67_32.c b/src/dynarec/arm64/dynarec_arm64_67_32.c
index c4315996..691c470c 100644
--- a/src/dynarec/arm64/dynarec_arm64_67_32.c
+++ b/src/dynarec/arm64/dynarec_arm64_67_32.c
@@ -65,6 +65,66 @@ uintptr_t dynarec64_67_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
             addr = dynarec64_6764_32(dyn, addr, ip, ninst, rex, rep, _FS, ok, need_epilog);
             break;
 
+        #define GO(NO, YES)                                             \
+            BARRIER(BARRIER_MAYBE);                                     \
+            JUMP(addr+i8, 1);                                           \
+            if(dyn->insts[ninst].x64.jmp_insts==-1 ||                   \
+                CHECK_CACHE()) {                                        \
+                /* out of the block */                                  \
+                i32 = dyn->insts[ninst].epilog-(dyn->native_size);      \
+                Bcond(NO, i32);                                         \
+                if(dyn->insts[ninst].x64.jmp_insts==-1) {               \
+                    if(!(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT))  \
+                        fpu_purgecache(dyn, ninst, 1, x1, x2, x3);      \
+                    jump_to_next(dyn, addr+i8, 0, ninst, rex.is32bits); \
+                } else {                                                \
+                    CacheTransform(dyn, ninst, cacheupd, x1, x2, x3);   \
+                    i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size);\
+                    B(i32);                                             \
+                }                                                       \
+            } else {    \
+                /* inside the block */  \
+                i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size);    \
+                Bcond(YES, i32);    \
+            }
+        case 0xE0:
+            INST_NAME("LOOPNZ (16bits)");
+            READFLAGS(X_ZF);
+            i8 = F8S;
+            UXTHw(x1, xRCX);
+            SUBSw_U12(x1, x1, 1);
+            BFIx(xRCX, x1, 0, 16);
+            B_NEXT(cEQ);    // ECX is 0, no LOOP
+            TSTw_mask(xFlags, 0b011010, 0); //mask=0x40
+            GO(cNE, cEQ);
+            break;
+        case 0xE1:
+            INST_NAME("LOOPZ (16bits)");
+            READFLAGS(X_ZF);
+            i8 = F8S;
+            UXTHw(x1, xRCX);
+            SUBSw_U12(x1, x1, 1);
+            BFIx(xRCX, x1, 0, 16);
+            B_NEXT(cEQ);    // ECX is 0, no LOOP
+            TSTw_mask(xFlags, 0b011010, 0); //mask=0x40
+            GO(cEQ, cNE);
+            break;
+        case 0xE2:
+            INST_NAME("LOOP (16bits)");
+            i8 = F8S;
+            UXTHw(x1, xRCX);
+            SUBSw_U12(x1, x1, 1);
+            BFIx(xRCX, x1, 0, 16);
+            GO(cEQ, cNE);
+            break;
+        case 0xE3:
+            INST_NAME("JCXZ");
+            i8 = F8S;
+            TSTw_mask(xRCX, 0, 15); //mask=0xffff
+            GO(cNE, cEQ);
+            break;
+        #undef GO
+        
         default:
             DEFAULT;
     }