mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
armjit: Handle lwl/lwr (not pretty, though.)
This commit is contained in:
parent
e90f7f360d
commit
4026944b02
2 changed files with 114 additions and 64 deletions
|
@ -91,7 +91,7 @@ namespace MIPSComp
|
|||
}
|
||||
}
|
||||
|
||||
void Jit::SetCCAndR0ForSafeAddress(MIPSGPReg rs, s16 offset, ARMReg tempReg) {
|
||||
void Jit::SetCCAndR0ForSafeAddress(MIPSGPReg rs, s16 offset, ARMReg tempReg, bool reverse) {
|
||||
SetR0ToEffectiveAddress(rs, offset);
|
||||
|
||||
// There are three valid ranges. Each one gets a bit.
|
||||
|
@ -123,7 +123,116 @@ namespace MIPSComp
|
|||
// If we left any bit set, the address is OK.
|
||||
SetCC(CC_AL);
|
||||
CMP(tempReg, 0);
|
||||
SetCC(CC_GT);
|
||||
SetCC(reverse ? CC_EQ : CC_GT);
|
||||
}
|
||||
|
||||
void Jit::Comp_ITypeMemLR(MIPSOpcode op, bool load) {
|
||||
CONDITIONAL_DISABLE;
|
||||
int offset = (signed short)(op & 0xFFFF);
|
||||
MIPSGPReg rt = _RT;
|
||||
MIPSGPReg rs = _RS;
|
||||
int o = op >> 26;
|
||||
|
||||
if (!js.inDelaySlot) {
|
||||
// Optimisation: Combine to single unaligned load/store
|
||||
bool isLeft = (o == 34 || o == 42);
|
||||
MIPSOpcode nextOp = Memory::Read_Instruction(js.compilerPC + 4);
|
||||
// Find a matching shift in opposite direction with opposite offset.
|
||||
if (nextOp == (isLeft ? (op.encoding + (4<<26) - 3)
|
||||
: (op.encoding - (4<<26) + 3)))
|
||||
{
|
||||
EatInstruction(nextOp);
|
||||
nextOp = MIPSOpcode(((load ? 35 : 43) << 26) | ((isLeft ? nextOp : op) & 0x03FFFFFF)); //lw, sw
|
||||
Comp_ITypeMem(nextOp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
u32 iaddr = gpr.IsImm(rs) ? offset + gpr.GetImm(rs) : 0xFFFFFFFF;
|
||||
bool doCheck = false;
|
||||
FixupBranch skip;
|
||||
|
||||
if (gpr.IsImm(rs) && Memory::IsValidAddress(iaddr)) {
|
||||
u32 addr = iaddr & 0x3FFFFFFF;
|
||||
// Must be OK even if rs == rt since we have the value from imm already.
|
||||
gpr.MapReg(rt, load ? MAP_NOINIT | MAP_DIRTY : 0);
|
||||
MOVI2R(R0, addr);
|
||||
} else {
|
||||
_dbg_assert_msg_(JIT, !gpr.IsImm(rs), "Invalid immediate address? CPU bug?");
|
||||
load ? gpr.MapDirtyIn(rt, rs, false) : gpr.MapInIn(rt, rs);
|
||||
|
||||
if (!g_Config.bFastMemory && rs != MIPS_REG_SP) {
|
||||
SetCCAndR0ForSafeAddress(rs, offset, R1, true);
|
||||
doCheck = true;
|
||||
} else {
|
||||
SetR0ToEffectiveAddress(rs, offset);
|
||||
}
|
||||
}
|
||||
if (doCheck) {
|
||||
skip = B();
|
||||
}
|
||||
|
||||
// Need temp regs. TODO: Get from the regcache?
|
||||
if (load) {
|
||||
PUSH(1, R10);
|
||||
} else {
|
||||
PUSH(2, R9, R10);
|
||||
}
|
||||
|
||||
// Here's our shift amount.
|
||||
AND(R1, R0, 3);
|
||||
LSL(R1, R1, 3);
|
||||
|
||||
// Now align the address for the actual read.
|
||||
BIC(R0, R0, 3);
|
||||
|
||||
switch (o) {
|
||||
case 34: // lwl
|
||||
MOVI2R(R10, 0x00ffffff);
|
||||
LDR(R0, R11, R0);
|
||||
AND(gpr.R(rt), gpr.R(rt), Operand2(R10, ST_LSR, R1));
|
||||
RSB(R1, R1, 24);
|
||||
ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, R1));
|
||||
break;
|
||||
|
||||
case 38: // lwr
|
||||
MOVI2R(R10, 0xffffff00);
|
||||
LDR(R0, R11, R0);
|
||||
LSR(R0, R0, R1);
|
||||
RSB(R1, R1, 24);
|
||||
AND(gpr.R(rt), gpr.R(rt), Operand2(R10, ST_LSL, R1));
|
||||
ORR(gpr.R(rt), gpr.R(rt), R0);
|
||||
break;
|
||||
|
||||
case 42: // swl
|
||||
MOVI2R(R10, 0xffffff00);
|
||||
LDR(R9, R11, R0);
|
||||
AND(R9, R9, Operand2(R10, ST_LSL, R1));
|
||||
RSB(R1, R1, 24);
|
||||
ORR(R9, R9, Operand2(gpr.R(rt), ST_LSR, R1));
|
||||
STR(R9, R11, R0);
|
||||
break;
|
||||
|
||||
case 46: // swr
|
||||
MOVI2R(R10, 0x00ffffff);
|
||||
LDR(R9, R11, R0);
|
||||
RSB(R1, R1, 24);
|
||||
AND(R9, R9, Operand2(R10, ST_LSR, R1));
|
||||
RSB(R1, R1, 24);
|
||||
ORR(R9, R9, Operand2(gpr.R(rt), ST_LSL, R1));
|
||||
STR(R9, R11, R0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (load) {
|
||||
POP(1, R10);
|
||||
} else {
|
||||
POP(2, R9, R10);
|
||||
}
|
||||
|
||||
if (doCheck) {
|
||||
SetJumpTarget(skip);
|
||||
}
|
||||
}
|
||||
|
||||
void Jit::Comp_ITypeMem(MIPSOpcode op)
|
||||
|
@ -225,67 +334,7 @@ namespace MIPSComp
|
|||
load = true;
|
||||
case 42: //swl
|
||||
case 46: //swr
|
||||
if (!js.inDelaySlot) {
|
||||
// Optimisation: Combine to single unaligned load/store
|
||||
bool isLeft = (o == 34 || o == 42);
|
||||
MIPSOpcode nextOp = Memory::Read_Instruction(js.compilerPC + 4);
|
||||
// Find a matching shift in opposite direction with opposite offset.
|
||||
if (nextOp == (isLeft ? (op.encoding + (4<<26) - 3)
|
||||
: (op.encoding - (4<<26) + 3)))
|
||||
{
|
||||
EatInstruction(nextOp);
|
||||
nextOp = MIPSOpcode(((load ? 35 : 43) << 26) | ((isLeft ? nextOp : op) & 0x03FFFFFF)); //lw, sw
|
||||
Comp_ITypeMem(nextOp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DISABLE; // Disabled until crashes are resolved.
|
||||
if (g_Config.bFastMemory) {
|
||||
int shift;
|
||||
if (gpr.IsImm(rs)) {
|
||||
u32 addr = (offset + gpr.GetImm(rs)) & 0x3FFFFFFF;
|
||||
shift = (addr & 3) << 3;
|
||||
addr &= 0xfffffffc;
|
||||
load ? gpr.MapReg(rt, MAP_DIRTY) : gpr.MapReg(rt, 0);
|
||||
MOVI2R(R0, addr);
|
||||
} else {
|
||||
load ? gpr.MapDirtyIn(rt, rs, false) : gpr.MapInIn(rt, rs);
|
||||
shift = (offset & 3) << 3; // Should be addr. Difficult as we don't know it yet.
|
||||
offset &= 0xfffffffc;
|
||||
SetR0ToEffectiveAddress(rs, offset);
|
||||
}
|
||||
switch (o)
|
||||
{
|
||||
// Load
|
||||
case 34:
|
||||
AND(gpr.R(rt), gpr.R(rt), 0x00ffffff >> shift);
|
||||
LDR(R0, R11, R0);
|
||||
ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, 24 - shift));
|
||||
break;
|
||||
case 38:
|
||||
AND(gpr.R(rt), gpr.R(rt), 0xffffff00 << (24 - shift));
|
||||
LDR(R0, R11, R0);
|
||||
ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSR, shift));
|
||||
break;
|
||||
// Store
|
||||
case 42:
|
||||
LDR(R1, R11, R0);
|
||||
AND(R1, R1, 0xffffff00 << shift);
|
||||
ORR(R1, R1, Operand2(gpr.R(rt), ST_LSR, 24 - shift));
|
||||
STR(R1, R11, R0);
|
||||
break;
|
||||
case 46:
|
||||
LDR(R1, R11, R0);
|
||||
AND(R1, R1, 0x00ffffff >> (24 - shift));
|
||||
ORR(R1, R1, Operand2(gpr.R(rt), ST_LSL, shift));
|
||||
STR(R1, R11, R0);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
Comp_Generic(op);
|
||||
return;
|
||||
}
|
||||
Comp_ITypeMemLR(op, load);
|
||||
break;
|
||||
default:
|
||||
Comp_Generic(op);
|
||||
|
|
|
@ -182,7 +182,8 @@ private:
|
|||
|
||||
// Utils
|
||||
void SetR0ToEffectiveAddress(MIPSGPReg rs, s16 offset);
|
||||
void SetCCAndR0ForSafeAddress(MIPSGPReg rs, s16 offset, ARMReg tempReg);
|
||||
void SetCCAndR0ForSafeAddress(MIPSGPReg rs, s16 offset, ARMReg tempReg, bool reverse = false);
|
||||
void Comp_ITypeMemLR(MIPSOpcode op, bool load);
|
||||
|
||||
JitBlockCache blocks;
|
||||
ArmJitOptions jo;
|
||||
|
|
Loading…
Add table
Reference in a new issue