diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_660f.c | 135 |
1 files changed, 131 insertions, 4 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c index 4afeed13..260ea32b 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f.c +++ b/src/dynarec/rv64/dynarec_rv64_660f.c @@ -377,6 +377,20 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int DEFAULT; } break; + case 0x50: + INST_NAME("PMOVMSKD Gd, Ex"); + nextop = F8; + GETGD; + GETEX(x1, 0); + MV(gd, xZR); + for(int i=0; i<2; ++i) { + // GD->dword[0] |= ((EX->q[i]>>63)&1)<<i; + LD(x2, wback, fixedaddress+8*i); + SRLI(x2, x2, 63); + if (i) SLLI(x2, x2, 1); + OR(gd, gd, x2); + } + break; case 0x51: INST_NAME("SQRTPD Gx, Ex"); nextop = F8; @@ -431,10 +445,22 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x58: INST_NAME("ADDPD Gx, Ex"); nextop = F8; - //TODO: fastnan handling GETEX(x1, 0); GETGX(x2); - SSE_LOOP_FQ(x3, x4, FADDD(v0, v0, v1)); + SSE_LOOP_FQ(x3, x4, { + if(!box64_dynarec_fastnan) { + FEQD(x3, v0, v0); + FEQD(x4, v1, v1); + } + FADDD(v0, v0, v1); + if(!box64_dynarec_fastnan) { + AND(x3, x3, x4); + BEQZ(x3, 16); + FEQD(x3, v0, v0); + BNEZ(x3, 8); + FNEGD(v0, v0); + } + }); break; case 0x59: INST_NAME("MULPD Gx, Ex"); @@ -473,13 +499,43 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int // GX->q[1] = 0; SD(xZR, gback, 8); break; + case 0x5B: + INST_NAME("CVTPS2DQ 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<4; ++i) { + FLW(d0, wback, fixedaddress+4*i); + FCVTLS(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); + break; case 0x5C: INST_NAME("SUBPD Gx, Ex"); nextop = F8; - //TODO: fastnan handling GETEX(x1, 0); GETGX(x2); - SSE_LOOP_FQ(x3, x4, FSUBD(v0, v0, v1)); + SSE_LOOP_FQ(x3, x4, { + if(!box64_dynarec_fastnan) { + FEQD(x3, v0, v0); + FEQD(x4, v1, v1); + } + FSUBD(v0, v0, v1); + if(!box64_dynarec_fastnan) { + AND(x3, x3, x4); + BEQZ(x3, 16); + FEQD(x3, v0, v0); + BNEZ(x3, 8); + FNEGD(v0, v0); + } + }); break; case 0x5D: INST_NAME("MINPD Gx, Ex"); @@ -500,6 +556,26 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int FSD(d1, gback, 8*i); } break; + case 0x5E: + INST_NAME("DIVPD Gx, Ex"); + nextop = F8; + GETEX(x1, 0); + GETGX(x2); + SSE_LOOP_FQ(x3, x4, { + if(!box64_dynarec_fastnan) { + FEQD(x3, v0, v0); + FEQD(x4, v1, v1); + } + FDIVD(v0, v0, v1); + if(!box64_dynarec_fastnan) { + AND(x3, x3, x4); + BEQZ(x3, 16); + FEQD(x3, v0, v0); + BNEZ(x3, 8); + FNEGD(v0, v0); + } + }); + break; case 0x5F: INST_NAME("MAXPD Gx, Ex"); nextop = F8; @@ -1121,6 +1197,57 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int AND(x1, x1, x5); OR(gd, gd, x1); break; + case 0xC2: + INST_NAME("CMPPD Gx, Ex, Ib"); + nextop = F8; + GETGX(x1); + GETEX(x2, 1); + u8 = F8; + d0 = fpu_get_scratch(dyn); + d1 = fpu_get_scratch(dyn); + for(int i=0; i<2; ++i) { + FLD(d0, gback, 8*i); + FLD(d1, wback, fixedaddress+8*i); + if ((u8&7) == 0) { // Equal + FEQD(x3, d0, d1); + } else if ((u8&7) == 4) { // Not Equal or unordered + FEQD(x3, d0, d1); + XORI(x3, x3, 1); + } else { + // x4 = !(isnan(d0) || isnan(d1)) + FEQD(x4, d0, d0); + FEQD(x3, d1, d1); + AND(x3, x3, x4); + + switch(u8&7) { + case 1: BEQ_MARK(x3, xZR); FLTD(x3, d0, d1); break; // Less than + case 2: BEQ_MARK(x3, xZR); FLED(x3, d0, d1); break; // Less or equal + case 3: XORI(x3, x3, 1); break; // NaN + case 5: { // Greater or equal or unordered + BEQ(x3, xZR, 12); // MARK2 + FLED(x3, d1, d0); + J(8); // MARK; + break; + } + case 6: { // Greater or unordered + BEQ(x3, xZR, 12); // MARK2 + FLTD(x3, d1, d0); + J(8); // MARK; + break; + } + case 7: break; // Not NaN + } + + // MARK2; + if ((u8&7) == 5 || (u8&7) == 6) { + MOV32w(x3, 1); + } + // MARK; + } + NEG(x3, x3); + SD(x3, gback, 8*i); + } + break; case 0xC4: INST_NAME("PINSRW Gx,Ed,Ib"); nextop = F8; |