diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-03-20 10:20:51 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-03-20 10:20:51 +0100 |
| commit | a68be9117b1d8cc78e9e6ceea5f8236f074983c9 (patch) | |
| tree | 551bf8753513ced2f153ed5de0e143eaef38d63b /src | |
| parent | f4fceb53bc3def59d34baec0453d313382c2a58d (diff) | |
| download | box64-a68be9117b1d8cc78e9e6ceea5f8236f074983c9.tar.gz box64-a68be9117b1d8cc78e9e6ceea5f8236f074983c9.zip | |
[DYNAREC] Added D3 opcodes, and fixed sl32/shl32c/shr32/shr32c emitter
Diffstat (limited to 'src')
| -rwxr-xr-x | src/dynarec/dynarec_arm64_00.c | 132 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_emit_math.c | 2 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_emit_shift.c | 36 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_helper.h | 8 | ||||
| -rwxr-xr-x | src/include/regs.h | 18 |
5 files changed, 164 insertions, 32 deletions
diff --git a/src/dynarec/dynarec_arm64_00.c b/src/dynarec/dynarec_arm64_00.c index 0e6613a9..d0bb204c 100755 --- a/src/dynarec/dynarec_arm64_00.c +++ b/src/dynarec/dynarec_arm64_00.c @@ -766,6 +766,138 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; } break; + case 0xD3: + nextop = F8; + switch((nextop>>3)&7) { + case 0: + INST_NAME("ROL Ed, CL"); + SETFLAGS(X_OF|X_CF, SF_SUBSET); + if(rex.w) { + ANDSx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f + } else { + ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f + } + MOV64xw(x4, (rex.w?64:32)); + SUBx_REG(x3, x4, x3); + GETEDW(x4, x2, 0); + if(!rex.w && MODREG) {MOVw_REG(ed, ed);} + B_NEXT(cEQ); + RORxw_REG(ed, ed, x3); + WBACK; + UFLAG_IF { // calculate flags directly + CMPSw_U12(x3, rex.w?63:31); + B_MARK(cNE); + LSRxw(x1, ed, rex.w?63:31); + ADDxw_REG(x1, x1, ed); + BFIw(xFlags, x1, F_OF, 1); + MARK; + BFIw(xFlags, ed, F_CF, 1); + UFLAG_DF(x2, d_none); + } + break; + case 1: + INST_NAME("ROR Ed, CL"); + SETFLAGS(X_OF|X_CF, SF_SUBSET); + if(rex.w) { + ANDSx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f + } else { + ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f + } + GETEDW(x4, x2, 0); + if(!rex.w && MODREG) {MOVw_REG(ed, ed);} + B_NEXT(cEQ); + RORxw_REG(ed, ed, x3); + WBACK; + UFLAG_IF { // calculate flags directly + CMPSw_U12(x3, 1); + B_MARK(cNE); + LSRxw(x2, ed, rex.w?62:30); // x2 = d>>30 + EORw_REG_LSR(x2, x2, x2, 1); // x2 = ((d>>30) ^ ((d>>30)>>1)) + BFIw(xFlags, x2, F_OF, 1); + MARK; + LSRxw(x2, ed, rex.w?63:31); + BFIw(xFlags, x2, F_CF, 1); + UFLAG_DF(x2, d_none); + } + break; + case 2: + INST_NAME("RCL Ed, CL"); + READFLAGS(X_CF); + SETFLAGS(X_OF|X_CF, SF_SUBSET); + if(rex.w) { + ANDSx_mask(x2, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f + } else { + ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f + } + GETEDW(x4, x1, 0); + if(!rex.w && MODREG) {MOVw_REG(ed, ed);} + B_NEXT(cEQ); + CALL_(rex.w?((void*)rcl64):((void*)rcl32), ed, x4); + WBACK; + break; + case 3: + INST_NAME("RCR Ed, CL"); + READFLAGS(X_CF); + SETFLAGS(X_OF|X_CF, SF_SUBSET); + if(rex.w) { + ANDSx_mask(x2, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f + } else { + ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f + } + GETEDW(x4, x1, 0); + if(!rex.w && MODREG) {MOVw_REG(ed, ed);} + B_NEXT(cEQ); + CALL_(rex.w?((void*)rcr64):((void*)rcr32), ed, x4); + WBACK; + break; + case 4: + case 6: + INST_NAME("SHL Ed, CL"); + SETFLAGS(X_ALL, SF_SET); // some flags are left undefined + if(rex.w) { + ANDSx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f + } else { + ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f + } + GETED(0); + if(!rex.w && MODREG) {MOVw_REG(ed, ed);} + B_NEXT(cEQ); + emit_shl32(dyn, ninst, rex, ed, x3, x5, x4); + WBACK; + break; + case 5: + INST_NAME("SHR Ed, CL"); + SETFLAGS(X_ALL, SF_SET); // some flags are left undefined + if(rex.w) { + ANDSx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f + } else { + ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f + } + GETED(0); + if(!rex.w && MODREG) {MOVw_REG(ed, ed);} + B_NEXT(cEQ); + emit_shr32(dyn, ninst, rex, ed, x3, x5, x4); + WBACK; + break; + case 7: + INST_NAME("SAR Ed, CL"); + SETFLAGS(X_ALL, SF_PENDING); + if(rex.w) { + ANDSx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f + } else { + ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f + } + GETED(0); + if(!rex.w && MODREG) {MOVw_REG(ed, ed);} + B_NEXT(cEQ); + UFLAG_OP12(ed, x3); + ASRxw_REG(ed, ed, x3); + WBACK; + UFLAG_RES(ed); + UFLAG_DF(x3, rex.w?d_sar64:d_sar32); + break; + } + break; case 0xE8: INST_NAME("CALL Id"); diff --git a/src/dynarec/dynarec_arm64_emit_math.c b/src/dynarec/dynarec_arm64_emit_math.c index 34232aba..d3931ccc 100755 --- a/src/dynarec/dynarec_arm64_emit_math.c +++ b/src/dynarec/dynarec_arm64_emit_math.c @@ -1567,7 +1567,7 @@ void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, in } EORw_mask(s4, xFlags, 0, 0); // invert CC because it's reverted for SUB on ARM MRS_nzvc(s3); - BFIx(s3, s4, 0, 1); // set C + BFIx(s3, s4, 29, 1); // set C, bit 29 MSR_nzvc(s3); // load CC into ARM CF IFX(X_AF|X_OF|X_CF) { MVNw_REG(s4, s1); diff --git a/src/dynarec/dynarec_arm64_emit_shift.c b/src/dynarec/dynarec_arm64_emit_shift.c index fef4b4e5..98ed81f5 100755 --- a/src/dynarec/dynarec_arm64_emit_shift.c +++ b/src/dynarec/dynarec_arm64_emit_shift.c @@ -59,7 +59,7 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); } IFX(X_ZF) { - TSTw_REG(s1, s1); + TSTxw_REG(s1, s1); BFCx(xFlags, F_ZF, 1); Bcond(cNE, +8); ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40 @@ -69,10 +69,10 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 BFIx(xFlags, s4, F_SF, 1); } IFX(X_OF) { - CMPSxw_U12(s2, 1); // if s3==1 + CMPSxw_U12(s2, 1); // if s2==1 IFX(X_SF) {} else {LSRxw(s4, s1, (rex.w)?63:31);} + Bcond(cNE, 4+3*4); BFCw(xFlags, F_OF, 1); - Bcond(cNE, +12); EORxw_REG(s4, s4, xFlags); // CF is set if OF is asked BFIw(xFlags, s4, F_OF, 1); } @@ -111,7 +111,7 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); } IFX(X_ZF) { - TSTw_REG(s1, s1); + TSTxw_REG(s1, s1); BFCx(xFlags, F_ZF, 1); Bcond(cNE, +8); ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40 @@ -156,34 +156,34 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 } B_NEXT(cEQ); } + IFX(X_CF) { + SUBxw_U12(s3, s2, 1); + LSRxw_REG(s3, s1, s3); + BFIw(xFlags, s3, 0, 1); + } LSRxw_REG(s1, s1, s2); IFX(X_PEND) { STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); } IFX(X_ZF) { - TSTw_REG(s1, s1); + TSTxw_REG(s1, s1); BFCx(xFlags, F_ZF, 1); Bcond(cNE, +8); ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40 } - IFX(X_CF) { - SUBxw_U12(s3, s2, 1); - LSRxw_REG(s3, s1, s3); - BFIw(xFlags, s3, 0, 1); - } IFX(X_SF) { LSRxw(s4, s1, (rex.w)?63:31); BFIx(xFlags, s4, F_SF, 1); } IFX(X_OF) { - CMPSxw_U12(s2, 1); // if s3==1 + CMPSxw_U12(s2, 1); // if s2==1 Bcond(cNE, 4+3*4); if(rex.w) { LSRx(s4, s1, 62); } else { LSRw(s4, s1, 30); } - EORw_mask(s4, s4, 0, 0); // CF is set if OF is asked + EORw_REG_LSR(s4, s4, s4, 1); BFIw(xFlags, s4, F_OF, 1); } IFX(X_PF) { @@ -208,20 +208,20 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in } return; } + IFX(X_CF) { + LSRxw_REG(s3, s1, c-1); + BFIw(xFlags, s3, 0, 1); + } LSRxw(s1, s1, c); IFX(X_PEND) { STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); } IFX(X_ZF) { - TSTw_REG(s1, s1); + TSTxw_REG(s1, s1); BFCx(xFlags, F_ZF, 1); Bcond(cNE, +8); ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40 } - IFX(X_CF) { - LSRxw_REG(s3, s1, c-1); - BFIw(xFlags, s3, 0, 1); - } IFX(X_SF) { LSRxw(s4, s1, (rex.w)?63:31); BFIx(xFlags, s4, F_SF, 1); @@ -229,7 +229,7 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in IFX(X_OF) { if(c==1) { LSRxw(s4, s1, rex.w?62:30); - EORw_mask(s4, s4, 0, 0); + EORw_REG_LSR(s4, s4, s4, 1); BFIw(xFlags, s4, F_OF, 1); } } diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h index 2da9e799..0c08e5c4 100755 --- a/src/dynarec/dynarec_arm64_helper.h +++ b/src/dynarec/dynarec_arm64_helper.h @@ -430,10 +430,10 @@ #ifndef BARRIER_NEXT #define BARRIER_NEXT(A) #endif -#define UFLAG_OP1(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STR_IMM9(A, xEmu, offsetof(x64emu_t, op1));} -#define UFLAG_OP2(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STR_IMM9(A, xEmu, offsetof(x64emu_t, op2));} -#define UFLAG_OP12(A1, A2) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STR_IMM9(A1, xEmu, offsetof(x64emu_t, op1));STR_IMM9(A2, 0, offsetof(x64emu_t, op2));} -#define UFLAG_RES(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STR_IMM9(A, xEmu, offsetof(x64emu_t, res));} +#define UFLAG_OP1(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op1));} +#define UFLAG_OP2(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op2));} +#define UFLAG_OP12(A1, A2) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A1, xEmu, offsetof(x64emu_t, op1));STRxw_U12(A2, 0, offsetof(x64emu_t, op2));} +#define UFLAG_RES(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, res));} #define UFLAG_DF(r, A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {SET_DF(r, A)} #define UFLAG_IF if(dyn->insts && dyn->insts[ninst].x64.need_flags) #ifndef DEFAULT diff --git a/src/include/regs.h b/src/include/regs.h index 008b61bc..44cc21b8 100755 --- a/src/include/regs.h +++ b/src/include/regs.h @@ -159,18 +159,18 @@ typedef struct { typedef union { struct __attribute__ ((__packed__)) { - unsigned int _F_CF:1; + unsigned int _F_CF:1; //0x0001 unsigned int _F_res1:1; - unsigned int _F_PF:1; + unsigned int _F_PF:1; //0x0004 unsigned int _F_res2:1; - unsigned int _F_AF:1; + unsigned int _F_AF:1; //0x0010 unsigned int _F_res3:1; - unsigned int _F_ZF:1; - unsigned int _F_SF:1; - unsigned int _F_TF:1; - unsigned int _F_IF:1; - unsigned int _F_DF:1; - unsigned int _F_OF:1; + unsigned int _F_ZF:1; //0x0040 + unsigned int _F_SF:1; //0x0080 + unsigned int _F_TF:1; //0x0100 + unsigned int _F_IF:1; //0x0200 + unsigned int _F_DF:1; //0x0400 + unsigned int _F_OF:1; //0x0800 unsigned int _F_IOPL:2; unsigned int _F_NT:1; unsigned int _F_dummy:1; |