More regcache fixes. ML_IMM works now although there is another stability issue somewhere.

This commit is contained in:
Henrik Rydgard 2015-07-07 01:12:42 +02:00
parent 568e2abb2b
commit d1bbc1d3c0
5 changed files with 41 additions and 10 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);