Merge pull request #736 from FioraAeterna/fixdirt
JIT: Don't assume the reserved bits in GQRs are zero
This commit is contained in:
commit
b7d4481081
|
@ -38,7 +38,12 @@ void Jit64::psq_st(UGeckoInstruction inst)
|
||||||
ADD(32, R(ECX), Imm32((u32)offset));
|
ADD(32, R(ECX), Imm32((u32)offset));
|
||||||
if (update && offset)
|
if (update && offset)
|
||||||
MOV(32, gpr.R(a), R(ECX));
|
MOV(32, gpr.R(a), R(ECX));
|
||||||
MOVZX(32, 16, EAX, M(&PowerPC::ppcState.spr[SPR_GQR0 + inst.I]));
|
// Some games (e.g. Dirt 2) incorrectly set the unused bits which breaks the lookup table code.
|
||||||
|
// Hence, we need to mask out the unused bits. The layout of the GQR register is
|
||||||
|
// UU[SCALE]UUUUU[TYPE] where SCALE is 6 bits and TYPE is 3 bits, so we have to AND with
|
||||||
|
// 0b0011111100000111, or 0x3F07.
|
||||||
|
MOV(32, R(EAX), Imm32(0x3F07));
|
||||||
|
AND(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_GQR0 + inst.I]));
|
||||||
MOVZX(32, 8, EDX, R(AL));
|
MOVZX(32, 8, EDX, R(AL));
|
||||||
|
|
||||||
// FIXME: Fix ModR/M encoding to allow [EDX*4+disp32] without a base register!
|
// FIXME: Fix ModR/M encoding to allow [EDX*4+disp32] without a base register!
|
||||||
|
@ -75,7 +80,8 @@ void Jit64::psq_l(UGeckoInstruction inst)
|
||||||
MOV(32, R(ECX), gpr.R(inst.RA));
|
MOV(32, R(ECX), gpr.R(inst.RA));
|
||||||
if (update && offset)
|
if (update && offset)
|
||||||
MOV(32, gpr.R(inst.RA), R(ECX));
|
MOV(32, gpr.R(inst.RA), R(ECX));
|
||||||
MOVZX(32, 16, EAX, M(((char *)&GQR(inst.I)) + 2));
|
MOV(32, R(EAX), Imm32(0x3F07));
|
||||||
|
AND(32, R(EAX), M(((char *)&GQR(inst.I)) + 2));
|
||||||
MOVZX(32, 8, EDX, R(AL));
|
MOVZX(32, 8, EDX, R(AL));
|
||||||
if (inst.W)
|
if (inst.W)
|
||||||
OR(32, R(EDX), Imm8(8));
|
OR(32, R(EDX), Imm8(8));
|
||||||
|
|
|
@ -1270,7 +1270,12 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) {
|
||||||
// The lower 3 bits is for GQR index. The next 1 bit is for inst.W
|
// The lower 3 bits is for GQR index. The next 1 bit is for inst.W
|
||||||
unsigned int quantreg = (*I >> 16) & 0x7;
|
unsigned int quantreg = (*I >> 16) & 0x7;
|
||||||
unsigned int w = *I >> 19;
|
unsigned int w = *I >> 19;
|
||||||
Jit->MOVZX(32, 16, EAX, M(((char *)&GQR(quantreg)) + 2));
|
// Some games (e.g. Dirt 2) incorrectly set the unused bits which breaks the lookup table code.
|
||||||
|
// Hence, we need to mask out the unused bits. The layout of the GQR register is
|
||||||
|
// UU[SCALE]UUUUU[TYPE] where SCALE is 6 bits and TYPE is 3 bits, so we have to AND with
|
||||||
|
// 0b0011111100000111, or 0x3F07.
|
||||||
|
Jit->MOV(32, R(EAX), Imm32(0x3F07));
|
||||||
|
Jit->AND(32, R(EAX), M(((char *)&GQR(quantreg)) + 2));
|
||||||
Jit->MOVZX(32, 8, EDX, R(AL));
|
Jit->MOVZX(32, 8, EDX, R(AL));
|
||||||
Jit->OR(32, R(EDX), Imm8(w << 3));
|
Jit->OR(32, R(EDX), Imm8(w << 3));
|
||||||
|
|
||||||
|
@ -1317,7 +1322,8 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) {
|
||||||
regSpill(RI, EAX);
|
regSpill(RI, EAX);
|
||||||
regSpill(RI, EDX);
|
regSpill(RI, EDX);
|
||||||
u32 quantreg = *I >> 24;
|
u32 quantreg = *I >> 24;
|
||||||
Jit->MOVZX(32, 16, EAX, M(&PowerPC::ppcState.spr[SPR_GQR0 + quantreg]));
|
Jit->MOV(32, R(EAX), Imm32(0x3F07));
|
||||||
|
Jit->AND(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_GQR0 + quantreg]));
|
||||||
Jit->MOVZX(32, 8, EDX, R(AL));
|
Jit->MOVZX(32, 8, EDX, R(AL));
|
||||||
|
|
||||||
Jit->MOV(32, R(ECX), regLocForInst(RI, getOp2(I)));
|
Jit->MOV(32, R(ECX), regLocForInst(RI, getOp2(I)));
|
||||||
|
|
Loading…
Reference in New Issue