diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2023-04-12 14:52:12 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-12 08:52:12 +0200 |
| commit | 90bf55e64523edc605d3a5a9274af96a8ffb08ae (patch) | |
| tree | b2998fa82a033fcefee4acf79ac49d6a044cfd0d /src | |
| parent | e066e920d0bab799c5a1f8f88e1400aa8c2806d5 (diff) | |
| download | box64-90bf55e64523edc605d3a5a9274af96a8ffb08ae.tar.gz box64-90bf55e64523edc605d3a5a9274af96a8ffb08ae.zip | |
[RV64_DYNAREC] Add more opcodes for SV (#688)
* [RV64_DYNAREC] Added F2 0F 5F MAXSD opcode * [RV64_DYNAREC] Added 0F A4 SHLD opcode * [RV64_DYNAREC] Added F0 21 LOCK AND opcode * [RV64_DYNAREC] Added 66 0F 71 opcodes
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_0f.c | 10 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_660f.c | 56 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_shift.c | 60 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_f0.c | 21 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_f20f.c | 15 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 2 |
6 files changed, 163 insertions, 1 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index 40a15310..55c15191 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -444,6 +444,16 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni ANDI(xFlags, xFlags, ~1); //F_CF is 1 OR(xFlags, xFlags, x4); break; + case 0xA4: + nextop = F8; + INST_NAME("SHLD Ed, Gd, Ib"); + SETFLAGS(X_ALL, SF_SET_PENDING); + GETED(1); + GETGD; + u8 = F8; + emit_shld32c(dyn, ninst, rex, ed, gd, u8, x3, x4, x5); + WBACK; + break; case 0xAB: INST_NAME("BTS Ed, Gd"); SETFLAGS(X_CF, SF_SUBSET); diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c index 85ad9b38..4ae1eaa7 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f.c +++ b/src/dynarec/rv64/dynarec_rv64_660f.c @@ -474,6 +474,62 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SW(x5, gback, 2*4); SW(x6, gback, 3*4); break; + case 0x71: + nextop = F8; + switch((nextop>>3)&7) { + case 2: + INST_NAME("PSRLW Ex, Ib"); + GETEX(x1, 1); + u8 = F8; + if (u8>15) { + // just zero dest + SD(xZR, x1, fixedaddress+0); + SD(xZR, x1, fixedaddress+8); + } else if(u8) { + for (int i=0; i<8; ++i) { + // EX->uw[i] >>= u8; + LHU(x3, wback, fixedaddress+i*2); + SRLI(x3, x3, u8); + SH(x3, wback, fixedaddress+i*2); + } + } + break; + case 4: + INST_NAME("PSRAW Ex, Ib"); + GETEX(x1, 1); + u8 = F8; + if(u8>15) u8=15; + if(u8) { + for (int i=0; i<8; ++i) { + // EX->sw[i] >>= u8; + LH(x3, wback, fixedaddress+i*2); + SRAI(x3, x3, u8); + SH(x3, wback, fixedaddress+i*2); + } + } + break; + case 6: + INST_NAME("PSLLW Ex, Ib"); + GETEX(x1, 1); + u8 = F8; + if (u8>15) { + // just zero dest + SD(xZR, x1, fixedaddress+0); + SD(xZR, x1, fixedaddress+8); + } else if(u8) { + for (int i=0; i<8; ++i) { + // EX->uw[i] <<= u8; + LHU(x3, wback, fixedaddress+i*2); + SLLI(x3, x3, u8); + SH(x3, wback, fixedaddress+i*2); + } + } + break; + default: + *ok = 0; + DEFAULT; + } + break; case 0x72: nextop = F8; switch((nextop>>3)&7) { diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c index ae7e6ebe..baf3f7b3 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c @@ -418,3 +418,63 @@ void emit_shrd32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin emit_pf(dyn, ninst, s1, s3, s4); } } + +void emit_shld32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4, int s5) { + CLEAR_FLAGS(); + IFX(X_PEND) { + if (c) { + MOV64x(s3, c); + SDxw(s3, xEmu, offsetof(x64emu_t, op2)); + } else SDxw(xZR, xEmu, offsetof(x64emu_t, op2)); + SDxw(s1, xEmu, offsetof(x64emu_t, op1)); + SET_DF(s4, rex.w?d_shl64:d_shl32); + } else IFX(X_ALL) { + SET_DFNONE(); + } + + if(!c) { + IFX(X_PEND) { + SDxw(s1, xEmu, offsetof(x64emu_t, res)); + } + return; + } + IFX(X_CF|X_OF) { + if (c > 0) { + SRLI(s3, s1, (rex.w?64:32)-c); + ANDI(s5, s3, 1); // F_CF + IFX(X_CF) { + OR(xFlags, xFlags, s5); + } + } else { + IFX(X_OF) MOV64x(s5, 0); + } + } + + SLLIxw(s3, s1, c); + SRLIxw(s1, s2, (rex.w?64:32)-c); + OR(s1, s1, s3); + + IFX(X_SF) { + BGE(s1, xZR, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + if (!rex.w) { + ZEROUP(s1); + } + IFX(X_PEND) { + SDxw(s1, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX(X_OF) { + SRLIxw(s3, s1, rex.w?63:31); + XOR(s3, s3, s5); + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_OF2); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} diff --git a/src/dynarec/rv64/dynarec_rv64_f0.c b/src/dynarec/rv64/dynarec_rv64_f0.c index e78756e5..781990ac 100644 --- a/src/dynarec/rv64/dynarec_rv64_f0.c +++ b/src/dynarec/rv64/dynarec_rv64_f0.c @@ -157,6 +157,27 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni DEFAULT; } break; + case 0x21: + INST_NAME("LOCK AND Ed, Gd"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGD; + SMDMB(); + if(MODREG) { + ed = xRAX+(nextop&7)+(rex.b<<3); + emit_and32(dyn, ninst, rex, ed, gd, x3, x4); + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0); + MARKLOCK; + LRxw(x1, wback, 1, 1); + AND(x4, x1, gd); + SCxw(x3, x4, wback, 1, 1); + BNEZ_MARKLOCK(x3); + IFX(X_ALL|X_PEND) + emit_and32(dyn, ninst, rex, x1, gd, x3, x4); + } + SMDMB(); + break; case 0x81: case 0x83: nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_f20f.c b/src/dynarec/rv64/dynarec_rv64_f20f.c index ec8912fa..711927ef 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f.c @@ -190,6 +190,21 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FNEGD(v0, v0); } break; + case 0x5F: + INST_NAME("MAXSD Gx, Ex"); + nextop = F8; + GETGXSD(v0); + GETEXSD(v1, 0); + FEQD(x2, v0, v0); + FEQD(x3, v1, v1); + AND(x2, x2, x3); + BEQ_MARK(x2, xZR); + FLED(x2, v0, v1); + BEQ_MARK2(x2, xZR); + MARK; + FMVD(v0, v1); + MARK2; + break; case 0x70: // TODO: Optimize this! INST_NAME("PSHUFLW Gx, Ex, Ib"); nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index a1bfbc8a..a9e1a9a1 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -957,7 +957,7 @@ void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4); //void emit_ror32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4); void emit_shrd32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4); -//void emit_shld32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4); +void emit_shld32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4, int s5); void emit_pf(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); |