diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2023-03-31 16:00:15 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-31 10:00:15 +0200 |
| commit | 4c86c8c2647fc9d88e2c7b847d62fb30f765b597 (patch) | |
| tree | 5a9958495a7617b28d7d72b69cb33ff13333b9a6 /src | |
| parent | 275550a9c387a69a6d5b2e5824577d3e2e25df57 (diff) | |
| download | box64-4c86c8c2647fc9d88e2c7b847d62fb30f765b597.tar.gz box64-4c86c8c2647fc9d88e2c7b847d62fb30f765b597.zip | |
[RV64_DYNAREC] Added more opcodes (#655)
* [RV64_DYNAREC] Added 66 0F 28 MOVAPD opcode * [RV64_DYNAREC] Added 66 0F 2E,2F COMISD opcode * [RV64_DYNAREC] Added F2 0F C2 CMPSD opcode * [RV64_DYNAREC] Added 0F AE /3 STMXCSR opcode * [RV64_DYNAREC] Added 0F AE /2 LDMXCSR opcode
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_0f.c | 14 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_660f.c | 42 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_f20f.c | 44 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 9 |
4 files changed, 109 insertions, 0 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index 8198682b..176e37c2 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -401,6 +401,20 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SMDMB(); } else { switch((nextop>>3)&7) { + case 2: + INST_NAME("LDMXCSR Md"); + GETED(0); + SW(ed, xEmu, offsetof(x64emu_t, mxcsr)); + if(box64_sse_flushto0) { + // TODO: applyFlushTo0 also needs to add RISC-V support. + } + break; + case 3: + INST_NAME("STMXCSR Md"); + addr = geted(dyn, addr, ninst, nextop, &wback, x1, x2, &fixedaddress, rex, NULL, 0, 0); + LWU(x4, xEmu, offsetof(x64emu_t, mxcsr)); + SW(x4, wback, fixedaddress); + break; case 7: INST_NAME("CLFLUSH Ed"); MESSAGE(LOG_DUMP, "Need Optimization?\n"); diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c index bea17833..44da6083 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f.c +++ b/src/dynarec/rv64/dynarec_rv64_660f.c @@ -79,6 +79,48 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GOCOND(0x40, "CMOV", "Gw, Ew"); #undef GO + case 0x28: + INST_NAME("MOVAPD Gx,Ex"); + nextop = F8; + GETEX(x1, 0); + GETGX(x2); + SSE_LOOP_MV_Q(x3); + break; + case 0x2E: + // no special check... + case 0x2F: + if(opcode==0x2F) {INST_NAME("COMISD Gx, Ex");} else {INST_NAME("UCOMISD Gx, Ex");} + SETFLAGS(X_ALL, SF_SET); + nextop = F8; + GETGXSD(d0); + GETEXSD(v0, 0); + CLEAR_FLAGS(); + // if isnan(d0) || isnan(v0) + IFX(X_ZF | X_PF | X_CF) { + FEQD(x3, d0, d0); + FEQD(x2, v0, v0); + AND(x2, x2, x3); + XORI(x2, x2, 1); + BEQ_MARK(x2, xZR); + ORI(xFlags, xFlags, (1<<F_ZF) | (1<<F_PF) | (1<<F_CF)); + B_NEXT_nocond; + } + MARK; + // else if isless(d0, v0) + IFX(X_CF) { + FLTD(x2, d0, v0); + BEQ_MARK2(x2, xZR); + ORI(xFlags, xFlags, 1<<F_CF); + B_NEXT_nocond; + } + MARK2; + // else if d0 == v0 + IFX(X_ZF) { + FEQD(x2, d0, v0); + CBZ_NEXT(x2); + ORI(xFlags, xFlags, 1<<F_ZF); + } + break; case 0x6C: INST_NAME("PUNPCKLQDQ Gx,Ex"); nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_f20f.c b/src/dynarec/rv64/dynarec_rv64_f20f.c index 4eba1c3b..27e77a87 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f.c @@ -125,7 +125,51 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FSUBD(v0, v0, v1); break; + case 0xC2: + INST_NAME("CMPSD Gx, Ex, Ib"); + nextop = F8; + GETGXSD(d0); + GETEXSD(d1, 1); + u8 = F8; + if ((u8&7) == 0) { // Equal + FEQD(x2, d0, d1); + } else if ((u8&7) == 4) { // Not Equal or unordered + FEQD(x2, d0, d1); + XORI(x2, x2, 1); + } else { + // x2 = !(isnan(d0) || isnan(d1)) + FEQD(x3, d0, d0); + FEQD(x2, d1, d1); + AND(x2, x2, x3); + switch(u8&7) { + case 1: BEQ_MARK(x2, xZR); FLTD(x2, d0, d1); break; // Less than + case 2: BEQ_MARK(x2, xZR); FLED(x2, d0, d1); break; // Less or equal + case 3: XORI(x2, x2, 1); break; // NaN + case 5: { // Greater or equal or unordered + BEQ_MARK2(x2, xZR); + FLED(x2, d1, d0); + B_MARK_nocond; + break; + } + case 6: { // Greater or unordered, test inverted, N!=V so unordered or less than (inverted) + BEQ_MARK2(x2, xZR); + FLTD(x2, d1, d0); + B_MARK_nocond; + break; + } + case 7: break; // Not NaN + } + + MARK2; + if ((u8&7) == 5 || (u8&7) == 6) { + MOV32w(x2, 1); + } + MARK; + } + NEG(x2, x2); + FMVDX(d0, x2); + break; default: DEFAULT; } diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index cd795aa6..f7fb7a35 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -365,6 +365,15 @@ SSE_LOOP_Q_ITEM(GX1, EX1, F, 0) \ SSE_LOOP_Q_ITEM(GX1, EX1, F, 1) +#define SSE_LOOP_MV_Q_ITEM(s, i) \ + LD(s, wback, fixedaddress+i*8); \ + SD(s, gback, i*8); + +// Loop for SSE opcode that moves 64bits value from wback to gback, use s as scratch. +#define SSE_LOOP_MV_Q(s) \ + SSE_LOOP_MV_Q_ITEM(s, 0) \ + SSE_LOOP_MV_Q_ITEM(s, 1) + // CALL will use x6 for the call address. Return value can be put in ret (unless ret is -1) // R0 will not be pushed/popd if ret is -2 #define CALL(F, ret) call_c(dyn, ninst, F, x6, ret, 1, 0) |