diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-04-16 15:46:03 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-04-16 15:46:03 +0200 |
| commit | 7a95dcd6b6bf51cde91d0cc2a17107b49d17a376 (patch) | |
| tree | f0689a01a5897f6a851e07cc9f148ff21746a488 /src | |
| parent | 47d0c04b30fe953db0d7dd77b6c46a5f62f4464b (diff) | |
| download | box64-7a95dcd6b6bf51cde91d0cc2a17107b49d17a376.tar.gz box64-7a95dcd6b6bf51cde91d0cc2a17107b49d17a376.zip | |
Added E0..E3 opcodes ([DYNAREC] too)
Diffstat (limited to 'src')
| -rwxr-xr-x | src/dynarec/dynarec_arm64_00.c | 43 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_helper.h | 8 | ||||
| -rwxr-xr-x | src/emu/x64run.c | 29 |
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 |