diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2023-04-23 23:31:06 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-23 17:31:06 +0200 |
| commit | 29e7497adcf4d7c53d6138e92c2e8d9a18a56c08 (patch) | |
| tree | a4f256d0ae61df53610d24e7b29d5dd508ccb3c6 /src | |
| parent | 8ecf28de9bc3d562396b5f81c931e2671319a9e4 (diff) | |
| download | box64-29e7497adcf4d7c53d6138e92c2e8d9a18a56c08.tar.gz box64-29e7497adcf4d7c53d6138e92c2e8d9a18a56c08.zip | |
[RV64_DYNAREC] Added more opcodes (#733)
* Added 66 1B SBB opcode * Added 66 0F E4 PMULHUW opcode * Added 66 0F E8 PSUBSB opcode * Added 1A SBB opcode * Added F2 0F E6 CVTPD2DQ opcode * Added 66 F7 /2 NOT opcode * Small optimization
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_0.c | 10 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_66.c | 16 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_660f.c | 37 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_math.c | 44 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_f20f.c | 19 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 2 |
6 files changed, 126 insertions, 2 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_0.c b/src/dynarec/rv64/dynarec_rv64_00_0.c index 6cf6a342..0320107d 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_0.c +++ b/src/dynarec/rv64/dynarec_rv64_00_0.c @@ -202,6 +202,16 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int emit_sbb32(dyn, ninst, rex, ed, gd, x3, x4, x5); WBACK; break; + case 0x1A: + INST_NAME("SBB Gb, Eb"); + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETEB(x2, 0); + GETGB(x1); + emit_sbb8(dyn, ninst, x1, x2, x3, x4, x5); + GBBACK(x5); + break; case 0x1B: INST_NAME("SBB Gd, Ed"); READFLAGS(X_CF); diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index 320f58a0..acafe265 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -124,6 +124,16 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0x0F: addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog); break; + case 0x1B: + INST_NAME("SBB Gw, Ew"); + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGW(x1); + GETEW(x2, 0); + emit_sbb16(dyn, ninst, x1, x2, x3, x4, x5); + GWBACK; + break; case 0x21: INST_NAME("AND Ew, Gw"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -708,6 +718,12 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni MOV32w(x2, u16); emit_test16(dyn, ninst, x1, x2, x3, x4, x5); break; + case 2: + INST_NAME("NOT Ew"); + GETEW(x1, 0); + NOT(ed, ed); // No flags affected + EWBACK; + break; case 3: INST_NAME("NEG Ew"); SETFLAGS(X_ALL, SF_SET_PENDING); diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c index 91283c6f..b71af6d0 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f.c +++ b/src/dynarec/rv64/dynarec_rv64_660f.c @@ -1216,6 +1216,43 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETEX(x2, 0); SSE_LOOP_Q(x3, x4, NOT(x3, x3); AND(x3, x3, x4)); break; + case 0xE4: + INST_NAME("PMULHUW Gx,Ex"); + nextop = F8; + GETGX(x1); + GETEX(x2, 0); + for(int i=0; i<8; ++i) { + LHU(x3, gback, 2*i); + LHU(x4, wback, fixedaddress+2*i); + MULW(x3, x3, x4); + SRLIW(x3, x3, 16); + SH(x3, gback, 2*i); + } + break; + case 0xE8: + INST_NAME("PSUBSB Gx,Ex"); + nextop = F8; + GETGX(x1); + GETEX(x2, 0); + for(int i=0; i<16; ++i) { + // tmp16s = (int16_t)GX->sb[i] - EX->sb[i]; + // GX->sb[i] = (tmp16s<-128)?-128:((tmp16s>127)?127:tmp16s); + LB(x3, gback, i); + LB(x4, wback, fixedaddress+i); + SUBW(x3, x3, x4); + SLLIW(x3, x3, 16); + SRAIW(x3, x3, 16); + ADDI(x4, xZR, 0x7f); + BLT(x3, x4, 12); // tmp16s>127? + SB(x4, gback, i); + J(24); // continue + ADDI(x4, xZR, 0xf80); + BLT(x4, x3, 12); // tmp16s<-128? + SB(x4, gback, i); + J(8); // continue + SB(x3, gback, i); + } + break; case 0xEB: INST_NAME("POR Gx,Ex"); nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c index 90031672..d468e972 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_math.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c @@ -880,7 +880,49 @@ void emit_sbb8c(dynarec_rv64_t* dyn, int ninst, int s1, int c, int s3, int s4, i emit_sbb8(dyn, ninst, s1, s6, s3, s4, s5); } -// emit SBB32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch +// emit SBB16 instruction, from s1, s2, store result in s1 using s3, s4 and s5 as scratch +void emit_sbb16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5) +{ + IFX(X_PEND) { + SH(s1, xEmu, offsetof(x64emu_t, op1)); + SH(s2, xEmu, offsetof(x64emu_t, op2)); + SET_DF(s3, d_sbb16); + } 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(s3, xFlags, 1 << F_CF); + SUBW(s1, s1, s3); + + IFX(X_SF) { + BGE(s1, xZR, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + + SLLI(s1, s1, 48); + SRLI(s1, s1, 48); + + IFX(X_PEND) { + SH(s1, xEmu, offsetof(x64emu_t, res)); + } + + CALC_SUB_FLAGS(s5, s2, s1, s3, s4, 16); + IFX(X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} + +// emit SBB32 instruction, from s1, s2, store result in s1 using s3, s4 and s5 as scratch void emit_sbb32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5) { IFX(X_PEND) { diff --git a/src/dynarec/rv64/dynarec_rv64_f20f.c b/src/dynarec/rv64/dynarec_rv64_f20f.c index 13e89083..95f526f0 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f.c @@ -344,6 +344,25 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int NEG(x2, x2); FMVDX(d0, x2); break; + case 0xE6: + INST_NAME("CVTPD2DQ Gx, Ex"); + nextop = F8; + GETGX(x1); + GETEX(x2, 0); + d0 = fpu_get_scratch(dyn); + u8 = sse_setround(dyn, ninst, x6, x4); + for (int i=0; i<2 ; ++i) { + FLD(d0, wback, fixedaddress+8*i); + FCVTLD(x3, d0, RD_DYN); + SEXT_W(x5, x3); + SUB(x5, x5, x3); + BEQZ(x5, 8); + LUI(x3, 0x80000); // INT32_MIN + SW(x3, gback, 4*i); + } + x87_restoreround(dyn, ninst, u8); + SD(xZR, gback, 8); + break; default: DEFAULT; } diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index b3675745..7fb1cdc9 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -960,7 +960,7 @@ void emit_sbb32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s //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, 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_sbb16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); //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 s2, int s3); void emit_neg16(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); |