From dc2f6a30fbf4718674882aa2d505deeb4f2b3865 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 11 Jul 2015 16:25:22 +0200 Subject: [PATCH] ARM64: Fix joining of lwl/lwr and swl/swr. "implement" the cache instruction. --- Core/MIPS/ARM/ArmCompLoadStore.cpp | 33 ++++++++++++- Core/MIPS/ARM64/Arm64CompLoadStore.cpp | 65 ++++++++++++++++++++++---- 2 files changed, 89 insertions(+), 9 deletions(-) diff --git a/Core/MIPS/ARM/ArmCompLoadStore.cpp b/Core/MIPS/ARM/ArmCompLoadStore.cpp index 5a370d36a2..f9d8c0bca4 100644 --- a/Core/MIPS/ARM/ArmCompLoadStore.cpp +++ b/Core/MIPS/ARM/ArmCompLoadStore.cpp @@ -393,6 +393,37 @@ namespace MIPSComp } void ArmJit::Comp_Cache(MIPSOpcode op) { - DISABLE; + // int imm = (s16)(op & 0xFFFF); + // int rs = _RS; + // int addr = R(rs) + imm; + int func = (op >> 16) & 0x1F; + + // It appears that a cache line is 0x40 (64) bytes, loops in games + // issue the cache instruction at that interval. + + // These codes might be PSP-specific, they don't match regular MIPS cache codes very well + switch (func) { + // Icache + case 8: + // Invalidate the instruction cache at this address + DISABLE; + break; + // Dcache + case 24: + // "Create Dirty Exclusive" - for avoiding a cacheline fill before writing to it. + // Will cause garbage on the real machine so we just ignore it, the app will overwrite the cacheline. + break; + case 25: // Hit Invalidate - zaps the line if present in cache. Should not writeback???? scary. + // No need to do anything. + break; + case 27: // D-cube. Hit Writeback Invalidate. Tony Hawk Underground 2 + break; + case 30: // GTA LCS, a lot. Fill (prefetch). Tony Hawk Underground 2 + break; + + default: + DISABLE; + break; + } } } diff --git a/Core/MIPS/ARM64/Arm64CompLoadStore.cpp b/Core/MIPS/ARM64/Arm64CompLoadStore.cpp index ec28bcf463..64a7092087 100644 --- a/Core/MIPS/ARM64/Arm64CompLoadStore.cpp +++ b/Core/MIPS/ARM64/Arm64CompLoadStore.cpp @@ -132,15 +132,12 @@ namespace MIPSComp { MIPSGPReg rs = _RS; int o = op >> 26; - DISABLE; - // TODO: For some reason I can't get this to work on ARM64. - if (!js.inDelaySlot && false) { + if (!js.inDelaySlot) { // Optimisation: Combine to single unaligned load/store bool isLeft = (o == 34 || o == 42); MIPSOpcode nextOp = GetOffsetInstruction(1); // Find a matching shift in opposite direction with opposite offset. - if (nextOp == (isLeft ? (op.encoding + (4 << 26) - 3) - : (op.encoding - (4 << 26) + 3))) { + 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); @@ -148,6 +145,8 @@ namespace MIPSComp { } } + DISABLE; + u32 iaddr = gpr.IsImm(rs) ? offset + gpr.GetImm(rs) : 0xFFFFFFFF; std::vector skips; @@ -313,6 +312,25 @@ namespace MIPSComp { std::vector skips; ARM64Reg addrReg = SCRATCH1; + int dataSize = 4; + switch (o) { + case 37: + case 33: + dataSize = 2; + break; + case 36: + case 32: + dataSize = 1; + break; + // Store + case 41: + dataSize = 2; + break; + case 40: + dataSize = 1; + break; + } + switch (o) { case 32: //lb case 33: //lh @@ -328,8 +346,8 @@ namespace MIPSComp { int offsetRange = 0x3ff; if (o == 41 || o == 33 || o == 37 || o == 32) offsetRange = 0xff; // 8 bit offset only - - if (!gpr.IsImm(rs) && rs != rt && (offset <= offsetRange) && offset >= 0) { + if (!gpr.IsImm(rs) && rs != rt && (offset <= offsetRange) && offset >= 0 && + (dataSize == 1 || (offset & (dataSize - 1)) == 0)) { // Check that the offset is aligned to the access size as that's required for INDEX_UNSIGNED encodings. we can get here through fallback from lwl/lwr gpr.SpillLock(rs, rt); gpr.MapRegAsPointer(rs); gpr.MapReg(rt, load ? MAP_NOINIT : 0); @@ -408,6 +426,37 @@ namespace MIPSComp { } void Arm64Jit::Comp_Cache(MIPSOpcode op) { - DISABLE; +// int imm = (s16)(op & 0xFFFF); +// int rs = _RS; +// int addr = R(rs) + imm; + int func = (op >> 16) & 0x1F; + + // It appears that a cache line is 0x40 (64) bytes, loops in games + // issue the cache instruction at that interval. + + // These codes might be PSP-specific, they don't match regular MIPS cache codes very well + switch (func) { + // Icache + case 8: + // Invalidate the instruction cache at this address + DISABLE; + break; + // Dcache + case 24: + // "Create Dirty Exclusive" - for avoiding a cacheline fill before writing to it. + // Will cause garbage on the real machine so we just ignore it, the app will overwrite the cacheline. + break; + case 25: // Hit Invalidate - zaps the line if present in cache. Should not writeback???? scary. + // No need to do anything. + break; + case 27: // D-cube. Hit Writeback Invalidate. Tony Hawk Underground 2 + break; + case 30: // GTA LCS, a lot. Fill (prefetch). Tony Hawk Underground 2 + break; + + default: + DISABLE; + break; + } } }