mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-12-11 23:53:55 +00:00
Re-enable lwl/lwr/swl/swr on the x86 jit.
Now correctly handling ECX on x64.
This commit is contained in:
parent
662ae77214
commit
2d15eb2acd
@ -104,25 +104,28 @@ namespace MIPSComp
|
||||
|
||||
void Jit::CompITypeMemUnpairedLR(u32 op, bool isStore)
|
||||
{
|
||||
// TODO: ECX getting overwritten? Why?
|
||||
DISABLE;
|
||||
|
||||
CONDITIONAL_DISABLE;
|
||||
int o = op>>26;
|
||||
int offset = (signed short)(op&0xFFFF);
|
||||
int rt = _RT;
|
||||
int rs = _RS;
|
||||
|
||||
X64Reg shiftReg = ECX;
|
||||
gpr.FlushLockX(ECX, EDX);
|
||||
#ifdef _M_X64
|
||||
// On x64, we need ECX for CL, but it's also the first arg and gets lost. Annoying.
|
||||
gpr.FlushLockX(R9);
|
||||
shiftReg = R9;
|
||||
#endif
|
||||
|
||||
gpr.Lock(rt);
|
||||
gpr.BindToRegister(rt, true, !isStore);
|
||||
|
||||
// Grab the offset from alignment for shifting (<< 3 for bytes -> bits.)
|
||||
MOV(32, R(ECX), gpr.R(rs));
|
||||
ADD(32, R(ECX), Imm32(offset));
|
||||
AND(32, R(ECX), Imm32(3));
|
||||
SHL(32, R(ECX), Imm8(3));
|
||||
MOV(32, R(shiftReg), gpr.R(rs));
|
||||
ADD(32, R(shiftReg), Imm32(offset));
|
||||
AND(32, R(shiftReg), Imm32(3));
|
||||
SHL(32, R(shiftReg), Imm8(3));
|
||||
|
||||
{
|
||||
JitSafeMem safe(this, rs, offset, ~3);
|
||||
@ -133,10 +136,10 @@ namespace MIPSComp
|
||||
if (!src.IsSimpleReg(EAX))
|
||||
MOV(32, R(EAX), src);
|
||||
|
||||
CompITypeMemUnpairedLRInner(op);
|
||||
CompITypeMemUnpairedLRInner(op, shiftReg);
|
||||
}
|
||||
if (safe.PrepareSlowRead((void *) &Memory::Read_U32))
|
||||
CompITypeMemUnpairedLRInner(op);
|
||||
CompITypeMemUnpairedLRInner(op, shiftReg);
|
||||
safe.Finish();
|
||||
}
|
||||
|
||||
@ -156,37 +159,69 @@ namespace MIPSComp
|
||||
gpr.UnlockAllX();
|
||||
}
|
||||
|
||||
void Jit::CompITypeMemUnpairedLRInner(u32 op)
|
||||
void Jit::CompITypeMemUnpairedLRInner(u32 op, X64Reg shiftReg)
|
||||
{
|
||||
CONDITIONAL_DISABLE;
|
||||
int o = op>>26;
|
||||
int rt = _RT;
|
||||
|
||||
// Make sure we have the shift for the target in ECX.
|
||||
if (shiftReg != ECX)
|
||||
MOV(32, R(ECX), R(shiftReg));
|
||||
|
||||
// Now use that shift (left on target, right on source.)
|
||||
switch (o)
|
||||
{
|
||||
case 34: //lwl
|
||||
// First clear the target bits.
|
||||
MOV(32, R(EDX), Imm32(0x00ffffff));
|
||||
SHR(32, R(EDX), R(CL));
|
||||
AND(32, gpr.R(rt), R(EDX));
|
||||
break;
|
||||
|
||||
// Adjust the shift to the bits we want.
|
||||
case 38: //lwr
|
||||
SHR(32, R(EAX), R(CL));
|
||||
break;
|
||||
|
||||
case 42: //swl
|
||||
MOV(32, R(EDX), Imm32(0xffffff00));
|
||||
SHL(32, R(EDX), R(CL));
|
||||
AND(32, R(EAX), R(EDX));
|
||||
break;
|
||||
|
||||
case 46: //swr
|
||||
MOV(32, R(EDX), gpr.R(rt));
|
||||
SHL(32, R(EDX), R(CL));
|
||||
// EDX is already the target value to write, but may be overwritten below. Save it.
|
||||
PUSH(EDX);
|
||||
break;
|
||||
|
||||
default:
|
||||
_dbg_assert_msg_(JIT, 0, "Unsupported left/right load/store instruction.");
|
||||
}
|
||||
|
||||
// Flip ECX around from 3 bytes / 24 bits.
|
||||
if (shiftReg == ECX)
|
||||
{
|
||||
MOV(32, R(EDX), Imm32(24));
|
||||
SUB(32, R(EDX), R(ECX));
|
||||
MOV(32, R(ECX), R(EDX));
|
||||
}
|
||||
else
|
||||
{
|
||||
MOV(32, R(ECX), Imm32(24));
|
||||
SUB(32, R(ECX), R(shiftReg));
|
||||
}
|
||||
|
||||
// Use the flipped shift (left on source, right on target) and write target.
|
||||
switch (o)
|
||||
{
|
||||
case 34: //lwl
|
||||
SHL(32, R(EAX), R(CL));
|
||||
|
||||
OR(32, gpr.R(rt), R(EAX));
|
||||
break;
|
||||
|
||||
case 38: //lwr
|
||||
// Adjust the shift to the bits we want.
|
||||
SHR(32, R(EAX), R(CL));
|
||||
|
||||
// Clear the target bits we're replacing.
|
||||
MOV(32, R(EDX), Imm32(24));
|
||||
SUB(32, R(EDX), R(ECX));
|
||||
MOV(32, R(ECX), R(EDX));
|
||||
MOV(32, R(EDX), Imm32(0xffffff00));
|
||||
SHL(32, R(EDX), R(CL));
|
||||
AND(32, gpr.R(rt), R(EDX));
|
||||
@ -195,15 +230,6 @@ namespace MIPSComp
|
||||
break;
|
||||
|
||||
case 42: //swl
|
||||
// First clear the target memory bits.
|
||||
MOV(32, R(EDX), Imm32(0xffffff00));
|
||||
SHL(32, R(EDX), R(CL));
|
||||
AND(32, R(EAX), R(EDX));
|
||||
|
||||
// Flip the shift, and adjust the shift in a temporary.
|
||||
MOV(32, R(EDX), Imm32(24));
|
||||
SUB(32, R(EDX), R(ECX));
|
||||
MOV(32, R(ECX), R(EDX));
|
||||
MOV(32, R(EDX), gpr.R(rt));
|
||||
SHR(32, R(EDX), R(CL));
|
||||
|
||||
@ -211,19 +237,11 @@ namespace MIPSComp
|
||||
break;
|
||||
|
||||
case 46: //swr
|
||||
// Adjust the shift to the bits we want.
|
||||
MOV(32, R(EDX), gpr.R(rt));
|
||||
SHL(32, R(EDX), R(CL));
|
||||
PUSH(EDX);
|
||||
|
||||
// Clear the target bits we're replacing.
|
||||
MOV(32, R(EDX), Imm32(24));
|
||||
SUB(32, R(EDX), R(ECX));
|
||||
MOV(32, R(ECX), R(EDX));
|
||||
MOV(32, R(EDX), Imm32(0x00ffffff));
|
||||
SHR(32, R(EDX), R(CL));
|
||||
AND(32, R(EAX), R(EDX));
|
||||
|
||||
// This is the target value we saved earlier.
|
||||
POP(EDX);
|
||||
OR(32, R(EDX), R(EAX));
|
||||
break;
|
||||
|
@ -275,7 +275,7 @@ private:
|
||||
void CompITypeMemRead(u32 op, u32 bits, void (XEmitter::*mov)(int, int, X64Reg, OpArg), void *safeFunc);
|
||||
void CompITypeMemWrite(u32 op, u32 bits, void *safeFunc);
|
||||
void CompITypeMemUnpairedLR(u32 op, bool isStore);
|
||||
void CompITypeMemUnpairedLRInner(u32 op);
|
||||
void CompITypeMemUnpairedLRInner(u32 op, X64Reg shiftReg);
|
||||
|
||||
void CompFPTriArith(u32 op, void (XEmitter::*arith)(X64Reg reg, OpArg), bool orderMatters);
|
||||
void CompFPComp(int lhs, int rhs, u8 compare, bool allowNaN = false);
|
||||
|
@ -26,15 +26,16 @@ using namespace Gen;
|
||||
|
||||
static const int allocationOrder[] =
|
||||
{
|
||||
// R12, when used as base register, for example in a LEA, can generate bad code! Need to look into this.
|
||||
// R12, when used as base register, for example in a LEA, can generate bad code! Need to look into this.
|
||||
// On x64, RCX and RDX are the first args. CallProtectedFunction() assumes they're not regcached.
|
||||
#ifdef _M_X64
|
||||
#ifdef _WIN32
|
||||
RSI, RDI, R13, R14, R8, R9, R10, R11, R12, //, RCX
|
||||
RSI, RDI, R13, R14, R8, R9, R10, R11, R12,
|
||||
#else
|
||||
RBP, R13, R14, R8, R9, R10, R11, R12, //, RCX
|
||||
RBP, R13, R14, R8, R9, R10, R11, R12,
|
||||
#endif
|
||||
#elif _M_IX86
|
||||
ESI, EDI, EBP, EDX, ECX, // Let's try to free up EBX as well.
|
||||
ESI, EDI, EBP, EDX, ECX, // Let's try to free up EBX as well.
|
||||
#endif
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user