From d1bbc1d3c0cefd869a26713d0359bcf6ccafda93 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 7 Jul 2015 01:12:42 +0200 Subject: [PATCH] More regcache fixes. ML_IMM works now although there is another stability issue somewhere. --- Core/HLE/ReplaceTables.cpp | 2 ++ Core/MIPS/ARM64/Arm64Asm.cpp | 2 +- Core/MIPS/ARM64/Arm64CompVFPU.cpp | 2 ++ Core/MIPS/ARM64/Arm64RegCache.cpp | 44 ++++++++++++++++++++++++------- Core/MIPS/ARM64/Arm64RegCache.h | 1 + 5 files changed, 41 insertions(+), 10 deletions(-) diff --git a/Core/HLE/ReplaceTables.cpp b/Core/HLE/ReplaceTables.cpp index 4f8e18f968..f06e02c728 100644 --- a/Core/HLE/ReplaceTables.cpp +++ b/Core/HLE/ReplaceTables.cpp @@ -1207,6 +1207,8 @@ void RestoreReplacedInstruction(u32 address) { } void RestoreReplacedInstructions(u32 startAddr, u32 endAddr) { + if (endAddr == startAddr) + return; // Need to be in order, or we'll hang. if (endAddr < startAddr) std::swap(endAddr, startAddr); diff --git a/Core/MIPS/ARM64/Arm64Asm.cpp b/Core/MIPS/ARM64/Arm64Asm.cpp index af8be217c2..61bdbb4efa 100644 --- a/Core/MIPS/ARM64/Arm64Asm.cpp +++ b/Core/MIPS/ARM64/Arm64Asm.cpp @@ -185,7 +185,7 @@ void Arm64Jit::GenerateFixedCode(const JitOptions &jo) { BR(SCRATCH1_64); SetJumpTarget(skipJump); - // No block found, let's jit + // No block found, let's jit. I don't think we actually need to save static regs that are in callee-save regs here but whatever. SaveStaticRegisters(); RestoreRoundingMode(true); QuickCallFunction(SCRATCH1_64, (void *)&MIPSComp::JitAt); diff --git a/Core/MIPS/ARM64/Arm64CompVFPU.cpp b/Core/MIPS/ARM64/Arm64CompVFPU.cpp index 7ec8b631ee..4242fa4397 100644 --- a/Core/MIPS/ARM64/Arm64CompVFPU.cpp +++ b/Core/MIPS/ARM64/Arm64CompVFPU.cpp @@ -1841,6 +1841,8 @@ namespace MIPSComp { gpr.FlushBeforeCall(); fpr.FlushAll(); + // Don't need to SaveStaticRegs here as long as they are all in callee-save regs - this callee won't read them. + bool negSin1 = (imm & 0x10) ? true : false; fpr.MapRegV(sreg); diff --git a/Core/MIPS/ARM64/Arm64RegCache.cpp b/Core/MIPS/ARM64/Arm64RegCache.cpp index 946b473638..0844b3c854 100644 --- a/Core/MIPS/ARM64/Arm64RegCache.cpp +++ b/Core/MIPS/ARM64/Arm64RegCache.cpp @@ -70,7 +70,7 @@ const ARM64Reg *Arm64RegCache::GetMIPSAllocationOrder(int &count) { W19, W20, W21, W22, W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, }; static const ARM64Reg allocationOrderStaticAlloc[] = { - W21, W22, W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, + W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, }; if (jo_->useStaticAlloc) { @@ -88,6 +88,8 @@ const Arm64RegCache::StaticAllocation *Arm64RegCache::GetStaticAllocations(int & static const StaticAllocation allocs[] = { {MIPS_REG_V0, W19}, {MIPS_REG_SP, W20, true}, + {MIPS_REG_A0, W21}, + {MIPS_REG_V1, W22}, }; if (jo_->useStaticAlloc) { @@ -137,8 +139,12 @@ bool Arm64RegCache::IsMapped(MIPSGPReg mipsReg) { } bool Arm64RegCache::IsMappedAsPointer(MIPSGPReg mipsReg) { - if (IsMapped(mipsReg)) { + if (mr[mipsReg].loc == ML_ARMREG) { return ar[mr[mipsReg].reg].pointerified; + } else if (mr[mipsReg].loc == ML_ARMREG_IMM) { + if (ar[mr[mipsReg].reg].pointerified) { + ELOG("Really shouldn't be pointerified here"); + } } return false; } @@ -154,6 +160,7 @@ void Arm64RegCache::SetRegImm(ARM64Reg reg, u64 imm) { } // On ARM64, at least Cortex A57, good old MOVT/MOVW (MOVK in 64-bit) is really fast. emit_->MOVI2R(reg, imm); + // ar[reg].pointerified = false; } void Arm64RegCache::MapRegTo(ARM64Reg reg, MIPSGPReg mipsReg, int mapFlags) { @@ -259,17 +266,20 @@ ARM64Reg Arm64RegCache::MapReg(MIPSGPReg mipsReg, int mapFlags) { if (mr[mipsReg].isStatic) { if (mr[mipsReg].loc == ML_IMM) { + // Back into the register, with or without the imm value. if ((mapFlags & MAP_NOINIT) == MAP_NOINIT) { mr[mipsReg].loc = ML_ARMREG; } else { SetRegImm(armReg, mr[mipsReg].imm); mr[mipsReg].loc = ML_ARMREG_IMM; + ar[armReg].pointerified = false; } } + // Erasing the imm on dirty (necessary since otherwise we will still think it's ML_ARMREG_IMM and return // true for IsImm and calculate crazily wrong things). /unknown if (mapFlags & MAP_DIRTY) { - mr[mipsReg].loc = ML_ARMREG; + mr[mipsReg].loc = ML_ARMREG; // As we are dirty, can't keep ARMREG_IMM, we will quickly drift out of sync ar[armReg].pointerified = false; ar[armReg].isDirty = true; // Not that it matters } @@ -336,18 +346,22 @@ allocate: Arm64Gen::ARM64Reg Arm64RegCache::MapRegAsPointer(MIPSGPReg reg) { ARM64Reg retval = INVALID_REG; - if (mr[reg].loc != ML_ARMREG) { + if (mr[reg].loc != ML_ARMREG && mr[reg].loc != ML_ARMREG_IMM) { retval = MapReg(reg); + } else { + retval = mr[reg].reg; } - if (mr[reg].loc == ML_ARMREG) { + if (mr[reg].loc == ML_ARMREG || mr[reg].loc == ML_ARMREG_IMM) { + // If there was an imm attached, discard it. + mr[reg].loc = ML_ARMREG; int a = DecodeReg(mr[reg].reg); if (!ar[a].pointerified) { emit_->MOVK(ARM64Reg(X0 + a), ((uint64_t)Memory::base) >> 32, SHIFT_32); ar[a].pointerified = true; } } else { - ERROR_LOG(JIT, "MapRegAsPointer : MapReg failed to allocate a register?"); + ELOG("MapRegAsPointer : MapReg failed to allocate a register?"); } return retval; } @@ -442,6 +456,7 @@ void Arm64RegCache::DiscardR(MIPSGPReg mipsReg) { if (mr[mipsReg].loc == ML_ARMREG_IMM || mr[mipsReg].loc == ML_IMM) { // Ignore the imm value, restore sanity mr[mipsReg].loc = ML_ARMREG; + ar[mr[mipsReg].reg].pointerified = false; } return; } @@ -570,6 +585,7 @@ void Arm64RegCache::FlushAll() { // Flush it first so we don't get it confused. FlushR(MIPS_REG_LO); + // Try to flush in pairs when possible. // 1 because MIPS_REG_ZERO isn't flushable anyway. // 31 because 30 and 31 are the last possible pair - MIPS_REG_FPCOND, etc. are too far away. for (int i = 1; i < 31; i++) { @@ -579,10 +595,10 @@ void Arm64RegCache::FlushAll() { ARM64Reg areg2 = ARM64RegForFlush(mreg2); // If either one doesn't have a reg yet, try flushing imms to scratch regs. - if (areg1 == INVALID_REG && IsImm(mreg1)) { + if (areg1 == INVALID_REG && IsPureImm(mreg1) && !mr[i].isStatic) { areg1 = SCRATCH1; } - if (areg2 == INVALID_REG && IsImm(mreg2)) { + if (areg2 == INVALID_REG && IsPureImm(mreg2) && !mr[i].isStatic) { areg2 = SCRATCH2; } @@ -611,6 +627,7 @@ void Arm64RegCache::FlushAll() { if (mr[i].isStatic) { if (mr[i].loc == ML_IMM) { SetRegImm(mr[i].reg, mr[i].imm); + ar[mr[mipsReg].reg].pointerified = false; } if (i != MIPS_REG_ZERO && mr[i].reg == INVALID_REG) { ELOG("ARM reg of static %i is invalid", i); @@ -649,13 +666,15 @@ void Arm64RegCache::SetImm(MIPSGPReg r, u64 immVal) { } if (mr[r].isStatic) { - if (true) { // Set to false to use ML_IMM + if (false) { // Set to false to use ML_IMM mr[r].loc = ML_ARMREG_IMM; mr[r].imm = immVal; SetRegImm(mr[r].reg, immVal); + ar[mr[r].reg].pointerified = false; } else { mr[r].loc = ML_IMM; mr[r].imm = immVal; + ar[mr[r].reg].pointerified = false; } // We do not change reg to INVALID_REG for obvious reasons.. } else { @@ -677,6 +696,13 @@ bool Arm64RegCache::IsImm(MIPSGPReg r) const { return mr[r].loc == ML_IMM || mr[r].loc == ML_ARMREG_IMM; } +bool Arm64RegCache::IsPureImm(MIPSGPReg r) const { + if (r == MIPS_REG_ZERO) + return true; + else + return mr[r].loc == ML_IMM; +} + u64 Arm64RegCache::GetImm(MIPSGPReg r) const { if (r == MIPS_REG_ZERO) return 0; diff --git a/Core/MIPS/ARM64/Arm64RegCache.h b/Core/MIPS/ARM64/Arm64RegCache.h index 56c0eec18c..ff3efe20de 100644 --- a/Core/MIPS/ARM64/Arm64RegCache.h +++ b/Core/MIPS/ARM64/Arm64RegCache.h @@ -98,6 +98,7 @@ public: void SetImm(MIPSGPReg reg, u64 immVal); bool IsImm(MIPSGPReg reg) const; + bool IsPureImm(MIPSGPReg reg) const; u64 GetImm(MIPSGPReg reg) const; // Optimally set a register to an imm value (possibly using another register.) void SetRegImm(Arm64Gen::ARM64Reg reg, u64 imm);