diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h index 7e830714ac..d143b3ad4b 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h @@ -145,6 +145,7 @@ enum Opcode { StoreDouble, StoreFReg, FDCmpCR, + CFloatOne, // Store 1.0f into the specified floating register // "Trinary" operators // FIXME: Need to change representation! @@ -513,6 +514,9 @@ public: InstLoc EmitFDCmpCR(InstLoc op1, InstLoc op2) { return FoldBiOp(FDCmpCR, op1, op2); } + InstLoc EmitCFloatOne() { + return FoldZeroOp(CFloatOne, 0); + } InstLoc EmitLoadGQR(unsigned gqr) { return FoldZeroOp(LoadGQR, gqr); } diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp index 56fa5bdf83..aa9dee3cd8 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp @@ -725,6 +725,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak case LoadDouble: case LoadSingle: case LoadPaired: + case CFloatOne: if (thisUsed) regMarkUse(RI, I, getOp1(I), 1); break; @@ -1169,6 +1170,16 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak regNormalRegClear(RI, I); break; } + case CFloatOne: { + if (!thisUsed) break; + X64Reg reg = fregFindFreeReg(RI); + static const float one = 1.0f; + Jit->MOV(32, R(ECX), Imm32(*(u32*)&one)); + Jit->MOVD_xmm(reg, R(ECX)); + RI.fregs[reg] = I; + regNormalRegClear(RI, I); + break; + } case LoadDouble: { if (!thisUsed) break; X64Reg reg = fregFindFreeReg(RI); diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp index 769bf71c2c..8fca0bf194 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp @@ -38,7 +38,6 @@ void JitIL::psq_st(UGeckoInstruction inst) INSTRUCTION_START JITDISABLE(LoadStorePaired) if (js.memcheck) { Default(inst); return; } - if (inst.W) {Default(inst); return;} IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_12), val; if (inst.RA) addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA)); @@ -46,7 +45,14 @@ void JitIL::psq_st(UGeckoInstruction inst) ibuild.EmitStoreGReg(addr, inst.RA); val = ibuild.EmitLoadFReg(inst.RS); val = ibuild.EmitCompactMRegToPacked(val); - ibuild.EmitStorePaired(val, addr, inst.I); + if (inst.W == 0) { + ibuild.EmitStorePaired(val, addr, inst.I); + } else { + IREmitter::InstLoc addr4 = ibuild.EmitAdd(addr, ibuild.EmitIntConst(4)); + IREmitter::InstLoc backup = ibuild.EmitLoad32(addr4); + ibuild.EmitStorePaired(val, addr, inst.I); + ibuild.EmitStore32(backup, addr4); + } } void JitIL::psq_l(UGeckoInstruction inst) @@ -54,13 +60,15 @@ void JitIL::psq_l(UGeckoInstruction inst) INSTRUCTION_START JITDISABLE(LoadStorePaired) if (js.memcheck) { Default(inst); return; } - if (inst.W) {Default(inst); return;} IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_12), val; if (inst.RA) addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA)); if (inst.OPCD == 57) ibuild.EmitStoreGReg(addr, inst.RA); val = ibuild.EmitLoadPaired(addr, inst.I); + if (inst.W) { + val = ibuild.EmitFPMerge00(val, ibuild.EmitCFloatOne()); + } val = ibuild.EmitExpandPackedToMReg(val); ibuild.EmitStoreFReg(val, inst.RD); }