diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2023-03-20 18:09:59 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-20 11:09:59 +0100 |
| commit | 61a6af1de7ea81b845115d22459247c90366cb05 (patch) | |
| tree | bfa74b29fedd71c3d8a4c40a869ea38c22f3fa1d /src | |
| parent | 77f8bea61510eb5e3906042c6567ca6bb192893e (diff) | |
| download | box64-61a6af1de7ea81b845115d22459247c90366cb05.tar.gz box64-61a6af1de7ea81b845115d22459247c90366cb05.zip | |
[RV64_DYNAREC] Added 80 /3 SBB opcode (#597)
* [RV64_DYNAREC] Simplify SET_DFNONE * [RV64_DYNARC] Fixed 80 /3 AND opcode * [RV64_DYNAREC] Added 80 /3 SBB opcode
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00.c | 25 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_logic.c | 16 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_math.c | 59 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_shift.c | 8 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_tests.c | 14 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 8 |
6 files changed, 94 insertions, 36 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c index 4db2ce60..44aaa4bb 100644 --- a/src/dynarec/rv64/dynarec_rv64_00.c +++ b/src/dynarec/rv64/dynarec_rv64_00.c @@ -300,13 +300,22 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0x80: nextop = F8; switch((nextop>>3)&7) { + case 3: // SBB + INST_NAME("SBB Eb, Ib"); + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + GETEB(x1, 1); + u8 = F8; + emit_sbb8c(dyn, ninst, x1, u8, x3, x4, x5, x6); + EBBACK(x3); + break; case 4: // AND INST_NAME("AND Eb, Ib"); SETFLAGS(X_ALL, SF_SET_PENDING); GETEB(x1, 1); u8 = F8; - emit_and8c(dyn, ninst, x1, u8, x2, x4); - EBBACK(x2); + emit_and8c(dyn, ninst, x1, u8, x3, x4); + EBBACK(x3); break; case 7: // CMP INST_NAME("CMP Eb, Ib"); @@ -1026,7 +1035,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("DIV Ed"); SETFLAGS(X_ALL, SF_SET); if(!rex.w) { - SET_DFNONE(x2); + SET_DFNONE(); GETED(0); SLLI(x3, xRDX, 32); AND(x2, xRAX, xMASK); @@ -1044,7 +1053,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni && dyn->insts[ninst-1].x64.addr && *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x31 && *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0xD2) { - SET_DFNONE(x2); + SET_DFNONE(); GETED(0); DIVU(x2, xRAX, ed); REMU(xRDX, xRAX, ed); @@ -1059,7 +1068,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni DIVU(x2, xRAX, ed); REMU(xRDX, xRAX, ed); MV(xRAX, x2); - SET_DFNONE(x2); + SET_DFNONE(); } } break; @@ -1067,7 +1076,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INST_NAME("IDIV Ed"); SETFLAGS(X_ALL, SF_SET); if(!rex.w) { - SET_DFNONE(x2) + SET_DFNONE() GETSED(0); SLLI(x3, xRDX, 32); AND(x2, xRAX, xMASK); @@ -1081,7 +1090,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni && dyn->insts[ninst-1].x64.addr && *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x48 && *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0x99) { - SET_DFNONE(x2) + SET_DFNONE() GETED(0); DIV(x2, xRAX, ed); REM(xRDX, xRAX, ed); @@ -1104,7 +1113,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni DIV(x2, xRAX, ed); REM(xRDX, xRAX, ed); MV(xRAX, x2); - SET_DFNONE(x2) + SET_DFNONE() } } break; diff --git a/src/dynarec/rv64/dynarec_rv64_emit_logic.c b/src/dynarec/rv64/dynarec_rv64_emit_logic.c index 1baf214c..f1e92b83 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_logic.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_logic.c @@ -30,7 +30,7 @@ void emit_xor32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX(X_PEND) { SET_DF(s4, rex.w?d_xor64:d_xor32); } else IFX(X_ALL) { - SET_DFNONE(s4); + SET_DFNONE(); } XOR(s1, s1, s2); @@ -64,7 +64,7 @@ void emit_xor32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i IFX(X_PEND) { SET_DF(s4, rex.w?d_xor64:d_xor32); } else IFX(X_ALL) { - SET_DFNONE(s4); + SET_DFNONE(); } if(c>=-2048 && c<=2047) { @@ -102,7 +102,7 @@ void emit_or16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4) { IFX(X_PEND) { SET_DF(s3, d_or16); } else IFX(X_ALL) { - SET_DFNONE(s3); + SET_DFNONE(); } OR(s1, s1, s2); @@ -134,7 +134,7 @@ void emit_or32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 IFX(X_PEND) { SET_DF(s4, rex.w?d_or64:d_or32); } else IFX(X_ALL) { - SET_DFNONE(s4); + SET_DFNONE(); } OR(s1, s1, s2); @@ -168,7 +168,7 @@ void emit_or32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in IFX(X_PEND) { SET_DF(s4, rex.w?d_or64:d_or32); } else IFX(X_ALL) { - SET_DFNONE(s4); + SET_DFNONE(); } if(c>=-2048 && c<=2047) { @@ -207,7 +207,7 @@ void emit_and8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s IFX(X_PEND) { SET_DF(s3, d_and8); } else IFX(X_ALL) { - SET_DFNONE(s3); + SET_DFNONE(); } ANDI(s1, s1, c&0xff); @@ -236,7 +236,7 @@ void emit_and32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s IFX(X_PEND) { SET_DF(s3, rex.w?d_tst64:d_tst32); } else IFX(X_ALL) { - SET_DFNONE(s4); + SET_DFNONE(); } AND(s1, s1, s2); // res = s1 & s2 @@ -266,7 +266,7 @@ void emit_and32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i IFX(X_PEND) { SET_DF(s3, rex.w?d_tst64:d_tst32); } else IFX(X_ALL) { - SET_DFNONE(s4); + SET_DFNONE(); } if(c>=-2048 && c<=2047) { diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c index 8b735f32..ed213f55 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_math.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c @@ -32,7 +32,7 @@ void emit_add32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s SDxw(s2, xEmu, offsetof(x64emu_t, op2)); SET_DF(s3, rex.w?d_add64:d_add32b); } else IFX(X_ALL) { - SET_DFNONE(s3); + SET_DFNONE(); } IFX(X_CF) { if (rex.w) { @@ -121,7 +121,7 @@ void emit_add32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i SDxw(s2, xEmu, offsetof(x64emu_t, op2)); SET_DF(s3, rex.w?d_add64:d_add32b); } else IFX(X_ALL) { - SET_DFNONE(s3); + SET_DFNONE(); } IFX(X_CF) { if (rex.w) { @@ -202,7 +202,7 @@ void emit_sub32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s SDxw(s2, xEmu, offsetof(x64emu_t, op2)); SET_DF(s3, rex.w?d_sub64:d_sub32); } else IFX(X_ALL) { - SET_DFNONE(s3); + SET_DFNONE(); } IFX(X_AF | X_CF | X_OF) { @@ -254,7 +254,7 @@ void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i SDxw(s2, xEmu, offsetof(x64emu_t, op2)); SET_DF(s3, rex.w?d_sub64:d_sub32); } else IFX(X_ALL) { - SET_DFNONE(s3); + SET_DFNONE(); } IFX(X_AF | X_CF | X_OF) { @@ -305,7 +305,7 @@ void emit_inc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s SDxw(s1, xEmu, offsetof(x64emu_t, op1)); SET_DF(s3, rex.w?d_inc64:d_inc32); } else IFX(X_ALL) { - SET_DFNONE(s3); + SET_DFNONE(); } IFX(X_AF | X_OF) { ORI(s3, s1, 1); // s3 = op1 | op2 @@ -350,3 +350,52 @@ void emit_inc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s ORI(xFlags, xFlags, 1 << F_ZF); } } + +// emit SBB8 instruction, from s1, s2, store result in s1 using s3, s4 and s5 as scratch +void emit_sbb8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5) +{ + IFX(X_PEND) { + SB(s1, xEmu, offsetof(x64emu_t, op1)); + SB(s2, xEmu, offsetof(x64emu_t, op2)); + SET_DF(s3, d_sbb8); + } else IFX(X_ALL) { + SET_DFNONE(); + } + + IFX(X_AF | X_CF | X_OF) { + // for later flag calculation + NOT(s5, s1); + } + + SUBW(s1, s1, s2); + ANDI(s1, s1, 0xff); + ANDI(s3, xFlags, 1 << F_CF); + BEQZ(s3, 12); + ADDIW(s1, s1, -1); + ANDI(s1, s1, 0xff); + + IFX(X_PEND) { + SB(s1, xEmu, offsetof(x64emu_t, res)); + } + + CALC_SUB_FLAGS(s5, s2, s1, s3, s4, 8); + IFX(X_SF) { + SRLI(s3, s1, 7); + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + IFX(X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} + +// emit SBB8 instruction, from s1, constant c, store result in s1 using s3, s4, s5 and s6 as scratch +void emit_sbb8c(dynarec_rv64_t* dyn, int ninst, int s1, int c, int s3, int s4, int s5, int s6) +{ + MOV32w(s6, c&0xff); + emit_sbb8(dyn, ninst, s1, s6, s3, s4, s5); +} diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c index 015ea2f5..a9e3a2b9 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c @@ -33,7 +33,7 @@ void emit_shl32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s SDxw(s2, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, rex.w?d_shl64:d_shl32); } else IFX(X_ALL) { - SET_DFNONE(s4); + SET_DFNONE(); } IFX(X_CF) { @@ -83,7 +83,7 @@ void emit_shl32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, SDxw(s1, xEmu, offsetof(x64emu_t, op1)); SET_DF(s4, rex.w?d_shl64:d_shl32); } else IFX(X_ALL) { - SET_DFNONE(s4); + SET_DFNONE(); } if(!c) { @@ -143,7 +143,7 @@ void emit_shr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, SDxw(s1, xEmu, offsetof(x64emu_t, op1)); SET_DF(s4, rex.w?d_shr64:d_shr32); } else IFX(X_ALL) { - SET_DFNONE(s4); + SET_DFNONE(); } if(!c) { IFX(X_PEND) { @@ -208,7 +208,7 @@ void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, SDxw(s1, xEmu, offsetof(x64emu_t, op1)); SET_DF(s4, rex.w?d_sar64:d_sar32); } else IFX(X_ALL) { - SET_DFNONE(s4); + SET_DFNONE(); } if(!c) { IFX(X_PEND) { diff --git a/src/dynarec/rv64/dynarec_rv64_emit_tests.c b/src/dynarec/rv64/dynarec_rv64_emit_tests.c index 4aa41f5b..7ce0ae58 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_tests.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_tests.c @@ -32,7 +32,7 @@ void emit_cmp8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i SB(s2, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, d_cmp8); } else { - SET_DFNONE(s4); + SET_DFNONE(); } IFX(X_AF | X_CF | X_OF) { @@ -71,7 +71,7 @@ void emit_cmp8_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4) SB(s1, xEmu, offsetof(x64emu_t, res)); SET_DF(s3, d_cmp8); } else { - SET_DFNONE(s4); + SET_DFNONE(); } IFX(X_SF) { @@ -97,7 +97,7 @@ void emit_cmp32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s SDxw(s2, xEmu, offsetof(x64emu_t, op2)); SET_DF(s4, rex.w?d_cmp64:d_cmp32); } else { - SET_DFNONE(s4); + SET_DFNONE(); } IFX(X_AF | X_CF | X_OF) { @@ -137,7 +137,7 @@ void emit_cmp32_0(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s3, int SD(s1, xEmu, offsetof(x64emu_t, res)); SET_DF(s4, rex.w?d_cmp64:d_cmp32); } else { - SET_DFNONE(s4); + SET_DFNONE(); } IFX(X_SF) { if (rex.w) { @@ -163,7 +163,7 @@ void emit_test8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, IFX_PENDOR0 { SET_DF(s3, d_tst8); } else { - SET_DFNONE(s4); + SET_DFNONE(); } AND(s3, s1, s2); // res = s1 & s2 @@ -192,7 +192,7 @@ void emit_test32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int IFX_PENDOR0 { SET_DF(s3, rex.w?d_tst64:d_tst32); } else { - SET_DFNONE(s4); + SET_DFNONE(); } AND(s3, s1, s2); // res = s1 & s2 @@ -222,7 +222,7 @@ void emit_test32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, IFX_PENDOR0 { SET_DF(s3, rex.w?d_tst64:d_tst32); } else { - SET_DFNONE(s4); + SET_DFNONE(); } if(c>=-2048 && c<=2047) diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 9532b9f2..fc526327 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -310,8 +310,8 @@ LOAD_REG(R11); \ -#define SET_DFNONE(S) if(!dyn->f.dfnone) {SW(xZR, xEmu, offsetof(x64emu_t, df)); dyn->f.dfnone=1;} -#define SET_DF(S, N) if((N)!=d_none) {MOV_U12(S, (N)); SW(S, xEmu, offsetof(x64emu_t, df)); dyn->f.dfnone=0;} else SET_DFNONE(S) +#define SET_DFNONE() if(!dyn->f.dfnone) {SW(xZR, xEmu, offsetof(x64emu_t, df)); dyn->f.dfnone=1;} +#define SET_DF(S, N) if((N)!=d_none) {MOV_U12(S, (N)); SW(S, xEmu, offsetof(x64emu_t, df)); dyn->f.dfnone=0;} else SET_DFNONE() #define SET_NODF() dyn->f.dfnone = 0 #define SET_DFOK() dyn->f.dfnone = 1 @@ -703,8 +703,8 @@ void emit_inc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s //void emit_adc16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); //void emit_sbb32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); //void emit_sbb32c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); -//void emit_sbb8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); -//void emit_sbb8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4, int s5); +void emit_sbb8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); +void emit_sbb8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4, int s5, int s6); //void emit_sbb16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); //void emit_sbb16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); //void emit_neg32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4); |