diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_66.c | 29 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_66.c | 32 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_66.c | 32 | ||||
| -rw-r--r-- | src/emu/x64run66.c | 15 |
4 files changed, 105 insertions, 3 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c index 15ce091b..3dc765df 100644 --- a/src/dynarec/arm64/dynarec_arm64_66.c +++ b/src/dynarec/arm64/dynarec_arm64_66.c @@ -758,7 +758,34 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin STRH_U12(xRAX, x1, 0); SMWRITELOCK(lock); break; - + case 0xA4: + SMREAD(); + if(rep) { + INST_NAME("REP MOVSB"); + CBZx_NEXT(xRCX); + TBNZ_MARK2(xFlags, F_DF); + MARK; // Part with DF==0 + LDRB_S9_postindex(x1, xRSI, 1); + STRB_S9_postindex(x1, xRDI, 1); + SUBx_U12(xRCX, xRCX, 1); + CBNZx_MARK(xRCX); + B_NEXT_nocond; + MARK2; // Part with DF==1 + LDRB_S9_postindex(x1, xRSI, -1); + STRB_S9_postindex(x1, xRDI, -1); + SUBx_U12(xRCX, xRCX, 1); + CBNZx_MARK2(xRCX); + // done + } else { + INST_NAME("MOVSB"); + GETDIR(x3, 1); + LDRB_U12(x1, xRSI, 0); + STRB_U12(x1, xRDI, 0); + ADDx_REG(xRSI, xRSI, x3); + ADDx_REG(xRDI, xRDI, x3); + } + SMWRITE(); + break; case 0xA5: SMREAD(); if(rep) { diff --git a/src/dynarec/la64/dynarec_la64_66.c b/src/dynarec/la64/dynarec_la64_66.c index 5130a3b0..3c32462d 100644 --- a/src/dynarec/la64/dynarec_la64_66.c +++ b/src/dynarec/la64/dynarec_la64_66.c @@ -413,6 +413,38 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni BSTRINS_D(gd, x2, 15, 0); } break; + + case 0xA4: + if (rep) { + INST_NAME("REP MOVSB"); + CBZ_NEXT(xRCX); + ANDI(x1, xFlags, 1 << F_DF); + BNEZ_MARK2(x1); + MARK; // Part with DF==0 + LD_BU(x1, xRSI, 0); + ST_B(x1, xRDI, 0); + ADDI_D(xRSI, xRSI, 1); + ADDI_D(xRDI, xRDI, 1); + ADDI_D(xRCX, xRCX, -1); + BNEZ_MARK(xRCX); + B_NEXT_nocond; + MARK2; // Part with DF==1 + LD_BU(x1, xRSI, 0); + ST_B(x1, xRDI, 0); + ADDI_D(xRSI, xRSI, -1); + ADDI_D(xRDI, xRDI, -1); + ADDI_D(xRCX, xRCX, -1); + BNEZ_MARK2(xRCX); + // done + } else { + INST_NAME("MOVSB"); + GETDIR(x3, x1, 1); + LD_BU(x1, xRSI, 0); + ST_B(x1, xRDI, 0); + ADD_D(xRSI, xRSI, x3); + ADD_D(xRDI, xRDI, x3); + } + break; case 0xA5: if (rep) { INST_NAME("REP MOVSW"); diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index ba57b57d..0f0f31d0 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -717,7 +717,37 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SH(xRAX, x1, 0); SMWRITELOCK(lock); break; - + case 0xA4: + if(rep) { + INST_NAME("REP MOVSB"); + CBZ_NEXT(xRCX); + ANDI(x1, xFlags, 1<<F_DF); + BNEZ_MARK2(x1); + MARK; // Part with DF==0 + LBU(x1, xRSI, 0); + SB(x1, xRDI, 0); + ADDI(xRSI, xRSI, 1); + ADDI(xRDI, xRDI, 1); + SUBI(xRCX, xRCX, 1); + BNEZ_MARK(xRCX); + B_NEXT_nocond; + MARK2; // Part with DF==1 + LBU(x1, xRSI, 0); + SB(x1, xRDI, 0); + SUBI(xRSI, xRSI, 1); + SUBI(xRDI, xRDI, 1); + SUBI(xRCX, xRCX, 1); + BNEZ_MARK2(xRCX); + // done + } else { + INST_NAME("MOVSB"); + GETDIR(x3, x1, 1); + LBU(x1, xRSI, 0); + SB(x1, xRDI, 0); + ADD(xRSI, xRSI, x3); + ADD(xRDI, xRDI, x3); + } + break; case 0xA5: if(rep) { INST_NAME("REP MOVSW"); diff --git a/src/emu/x64run66.c b/src/emu/x64run66.c index 536583bc..17199c71 100644 --- a/src/emu/x64run66.c +++ b/src/emu/x64run66.c @@ -477,7 +477,20 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr) *(uint16_t*)F64 = R_AX; } break; - + case 0xA4: /* (REP) MOVSB */ + tmp8s = ACCESS_FLAG(F_DF)?-1:+1; + tmp64u = (rep)?R_RCX:1L; + while(tmp64u) { + #ifndef TEST_INTERPRETER + *(uint8_t*)R_RDI = *(uint8_t*)R_RSI; + #endif + R_RDI += tmp8s; + R_RSI += tmp8s; + --tmp64u; + } + if(rep) + R_RCX = tmp64u; + break; case 0xA5: /* (REP) MOVSW */ tmp8s = ACCESS_FLAG(F_DF)?-1:+1; tmp64u = (rep)?R_RCX:1L; |