From baba7f54dc73c2c73ce9b7e3324f93dd02c882af Mon Sep 17 00:00:00 2001 From: nodchip Date: Mon, 30 Aug 2010 01:24:14 +0000 Subject: [PATCH] JitIL: Fixed the Issue 3114. The bug was introduced because the usage of MOVSD/MOVSS was wrong. MOVSD/MOVSS don't clear the upper bits when they are used to transfer between registers. But they clear the upper bits when they are used to transfer between a register and memory. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6151 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp index 11e2f7143f..629d844d33 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp @@ -1362,9 +1362,17 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak // TODO: Optimize the case that the register of op1 can be // recycled. (SHUFPD may not be so fast.) X64Reg reg = fregBinRHSRegWithMov(RI, I); - // TODO: Check whether the following code works - // when the op1 is in the FSlotSet - Jit->MOVSD(reg, fregLocForInst(RI, getOp1(I))); + OpArg loc1 = fregLocForInst(RI, getOp1(I)); + if (loc1.IsSimpleReg()) { + Jit->MOVSD(reg, loc1); + } else { + // If op1 is in FSlotSet, we have to mov loc1 to XMM0 + // before MOVSD/MOVSS. + // Because register<->memory transfer with MOVSD/MOVSS + // clears upper 64/96-bits of the destination register. + Jit->MOVAPD(XMM0, loc1); + Jit->MOVSD(reg, R(XMM0)); + } RI.fregs[reg] = I; fregNormalRegClear(RI, I); break; @@ -1569,9 +1577,13 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak // TODO: Optimize the case that the register of only op1 can be // recycled. X64Reg reg = fregBinRHSRegWithMov(RI, I); - // TODO: Check whether the following code works - // when the op1 is in the FSlotSet - Jit->MOVSS(reg, fregLocForInst(RI, getOp1(I))); + OpArg loc1 = fregLocForInst(RI, getOp1(I)); + if (loc1.IsSimpleReg()) { + Jit->MOVSS(reg, loc1); + } else { + Jit->MOVAPD(XMM0, loc1); + Jit->MOVSS(reg, R(XMM0)); + } RI.fregs[reg] = I; fregNormalRegClear(RI, I); break; @@ -1582,9 +1594,13 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak // TODO: Optimize the case that the register of only op2 can be // recycled. X64Reg reg = fregBinLHSRegWithMov(RI, I); - // TODO: Check whether the following code works - // when the op1 is in the FSlotSet - Jit->MOVSS(reg, fregLocForInst(RI, getOp2(I))); + OpArg loc2 = fregLocForInst(RI, getOp2(I)); + if (loc2.IsSimpleReg()) { + Jit->MOVSS(reg, loc2); + } else { + Jit->MOVAPD(XMM0, loc2); + Jit->MOVSS(reg, R(XMM0)); + } Jit->SHUFPS(reg, R(reg), 0xF1); RI.fregs[reg] = I; fregNormalRegClear(RI, I);