diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c index 3e084330..bac50efc 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f.c +++ b/src/dynarec/rv64/dynarec_rv64_660f.c @@ -161,6 +161,22 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SD(x3, gback, 0); SD(x4, gback, 8); break; + case 0x70: // TODO: Optimize this! + INST_NAME("PSHUFD Gx,Ex,Ib"); + nextop = F8; + GETGX(x1); + GETEX(x2, 1); + u8 = F8; + i32 = -1; + for (int i=0; i<4; ++i) { + int32_t idx = (u8>>(i*2))&3; + if (idx!=i32) { + LWU(x4, wback, fixedaddress+idx*4); + i32 = idx; + } + SW(x4, gback, i*4); + } + break; case 0x72: nextop = F8; switch((nextop>>3)&7) { diff --git a/src/dynarec/rv64/dynarec_rv64_db.c b/src/dynarec/rv64/dynarec_rv64_db.c index 1bc42f1e..95e350c0 100644 --- a/src/dynarec/rv64/dynarec_rv64_db.c +++ b/src/dynarec/rv64/dynarec_rv64_db.c @@ -179,7 +179,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); LW(x1, ed, fixedaddress); - FCVTDW(v1, x1); // i32 -> double + FCVTDW(v1, x1, RD_RNE); // i32 -> double break; case 1: INST_NAME("FISTTP Ed, ST0"); diff --git a/src/dynarec/rv64/dynarec_rv64_f20f.c b/src/dynarec/rv64/dynarec_rv64_f20f.c index 27e77a87..ef181e97 100644 --- a/src/dynarec/rv64/dynarec_rv64_f20f.c +++ b/src/dynarec/rv64/dynarec_rv64_f20f.c @@ -79,7 +79,17 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SMWRITE2(); } break; - + case 0x2A: + INST_NAME("CVTSI2SD Gx, Ed"); + nextop = F8; + GETGXSD(v0); + GETED(0); + if(rex.w) { + FCVTDL(v0, ed, RD_RNE); + } else { + FCVTDW(v0, ed, RD_RNE); + } + break; case 0x38: // these are some more SSSE4.2+ opcodes opcode = F8; switch(opcode) { @@ -124,7 +134,24 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int GETEXSD(v1, 0); FSUBD(v0, v0, v1); break; - + case 0x5E: + INST_NAME("DIVSD Gx, Ex"); + nextop = F8; + GETGXSD(v0); + GETEXSD(v1, 0); + if(!box64_dynarec_fastnan) { + FEQD(x3, v0, v0); + FEQD(x4, v1, v1); + } + FDIVD(v0, v0, v1); + if(!box64_dynarec_fastnan) { + AND(x3, x3, x4); + CBZ_NEXT(x3); + FEQD(x3, v0, v0); + CBNZ_NEXT(x3); + FNEGD(v0, v0); + } + break; case 0xC2: INST_NAME("CMPSD Gx, Ex, Ib"); nextop = F8; diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h index 3e2bcbd6..73955b1c 100644 --- a/src/dynarec/rv64/rv64_emitter.h +++ b/src/dynarec/rv64/rv64_emitter.h @@ -469,7 +469,7 @@ f28–31 ft8–11 FP temporaries Caller // |rs1| => rd #define FABSD(rd, rs1) FSGNJXD(rd, rs1, rs1) // Convert from signed 32bits to Double -#define FCVTDW(frd, rs1) EMIT(R_type(0b1101001, 0b00000, rs1, 0b000, frd, 0b1010011)) +#define FCVTDW(frd, rs1, rm) EMIT(R_type(0b1101001, 0b00000, rs1, rm, frd, 0b1010011)) #define FEQD(rd, frs1, frs2) EMIT(R_type(0b1010001, frs2, frs1, 0b010, rd, 0b1010011)) #define FLTD(rd, frs1, frs2) EMIT(R_type(0b1010001, frs2, frs1, 0b001, rd, 0b1010011))