allow allocating caller saved registers

currently system-v only
This commit is contained in:
RSDuck 2020-05-09 14:34:52 +02:00
parent 0f53a34551
commit 5a0b568647
4 changed files with 65 additions and 34 deletions

View File

@ -138,18 +138,7 @@ void Compiler::Comp_JumpTo(Gen::X64Reg addr, bool restoreCPSR)
bool cpsrDirty = CPSRDirty; bool cpsrDirty = CPSRDirty;
SaveCPSR(); SaveCPSR();
if (restoreCPSR) PushRegs(restoreCPSR);
{
if (Thumb || CurInstr.Cond() >= 0xE)
RegCache.Flush();
else
{
// the ugly way...
// we only save them, to load and save them again
for (int reg : hiRegsLoaded)
SaveReg(reg, RegCache.Mapping[reg]);
}
}
MOV(64, R(ABI_PARAM1), R(RCPU)); MOV(64, R(ABI_PARAM1), R(RCPU));
MOV(32, R(ABI_PARAM2), R(addr)); MOV(32, R(ABI_PARAM2), R(addr));
@ -162,11 +151,7 @@ void Compiler::Comp_JumpTo(Gen::X64Reg addr, bool restoreCPSR)
else else
CALL((void*)&ARMv4::JumpTo); CALL((void*)&ARMv4::JumpTo);
if (!Thumb && restoreCPSR && CurInstr.Cond() < 0xE) PopRegs(restoreCPSR);
{
for (int reg : hiRegsLoaded)
LoadReg(reg, RegCache.Mapping[reg]);
}
LoadCPSR(); LoadCPSR();
// in case this instruction is skipped // in case this instruction is skipped

View File

@ -26,7 +26,8 @@ const X64Reg RegisterCache<Compiler, X64Reg>::NativeRegAllocOrder[] =
#ifdef _WIN32 #ifdef _WIN32
RBX, RSI, RDI, R12, R13, R14 RBX, RSI, RDI, R12, R13, R14
#else #else
RBX, R12, R13, R14 // this is sad RBX, R12, R13, R14, // callee saved, this is sad
R9, R10, R11, // caller saved
#endif #endif
}; };
template <> template <>
@ -34,10 +35,46 @@ const int RegisterCache<Compiler, X64Reg>::NativeRegsAvailable =
#ifdef _WIN32 #ifdef _WIN32
6 6
#else #else
4 7
#endif #endif
; ;
void Compiler::PushRegs(bool saveHiRegs)
{
BitSet32 loadedRegs(RegCache.LoadedRegs);
if (saveHiRegs)
{
BitSet32 hiRegsLoaded(RegCache.LoadedRegs & 0x7F00);
for (int reg : hiRegsLoaded)
{
if (Thumb || CurInstr.Cond() == 0xE)
RegCache.UnloadRegister(reg);
else
SaveReg(reg, RegCache.Mapping[reg]);
// prevent saving the register twice
loadedRegs[reg] = false;
}
}
for (int reg : loadedRegs)
if (BitSet32(1 << RegCache.Mapping[reg]) & ABI_ALL_CALLER_SAVED)
SaveReg(reg, RegCache.Mapping[reg]);
}
void Compiler::PopRegs(bool saveHiRegs)
{
BitSet32 loadedRegs(RegCache.LoadedRegs);
for (int reg : loadedRegs)
{
if ((saveHiRegs && reg >= 8 && reg < 15)
|| BitSet32(1 << RegCache.Mapping[reg]) & ABI_ALL_CALLER_SAVED)
{
LoadReg(reg, RegCache.Mapping[reg]);
}
}
}
void Compiler::A_Comp_MRS() void Compiler::A_Comp_MRS()
{ {
Comp_AddCycles_C(); Comp_AddCycles_C();
@ -136,27 +173,14 @@ void Compiler::A_Comp_MSR()
AND(32, R(RSCRATCH2), val); AND(32, R(RSCRATCH2), val);
OR(32, R(RCPSR), R(RSCRATCH2)); OR(32, R(RCPSR), R(RSCRATCH2));
BitSet16 hiRegsLoaded(RegCache.LoadedRegs & 0x7F00); PushRegs(true);
if (Thumb || CurInstr.Cond() >= 0xE)
RegCache.Flush();
else
{
// the ugly way...
// we only save them, to load and save them again
for (int reg : hiRegsLoaded)
SaveReg(reg, RegCache.Mapping[reg]);
}
MOV(32, R(ABI_PARAM3), R(RCPSR)); MOV(32, R(ABI_PARAM3), R(RCPSR));
MOV(32, R(ABI_PARAM2), R(RSCRATCH3)); MOV(32, R(ABI_PARAM2), R(RSCRATCH3));
MOV(64, R(ABI_PARAM1), R(RCPU)); MOV(64, R(ABI_PARAM1), R(RCPU));
CALL((void*)&ARM::UpdateMode); CALL((void*)&ARM::UpdateMode);
if (!Thumb && CurInstr.Cond() < 0xE) PopRegs(true);
{
for (int reg : hiRegsLoaded)
LoadReg(reg, RegCache.Mapping[reg]);
}
} }
} }
} }

View File

@ -168,6 +168,9 @@ public:
Gen::FixupBranch CheckCondition(u32 cond); Gen::FixupBranch CheckCondition(u32 cond);
void PushRegs(bool saveHiRegs);
void PopRegs(bool saveHiRegs);
Gen::OpArg MapReg(int reg) Gen::OpArg MapReg(int reg)
{ {
if (reg == 15 && RegCache.Mapping[reg] == Gen::INVALID_REG) if (reg == 15 && RegCache.Mapping[reg] == Gen::INVALID_REG)

View File

@ -283,6 +283,8 @@ void Compiler::Comp_MemAccess(int rd, int rn, const ComplexOperand& op2, int siz
} }
else else
{ {
PushRegs(false);
u32 maskedDataRegion; u32 maskedDataRegion;
if (addrIsStatic) if (addrIsStatic)
@ -310,6 +312,8 @@ void Compiler::Comp_MemAccess(int rd, int rn, const ComplexOperand& op2, int siz
MOV(32, R(ABI_PARAM2), rdMapped); MOV(32, R(ABI_PARAM2), rdMapped);
ABI_CallFunction((void(*)())func); ABI_CallFunction((void(*)())func);
PopRegs(false);
} }
else else
{ {
@ -318,6 +322,8 @@ void Compiler::Comp_MemAccess(int rd, int rn, const ComplexOperand& op2, int siz
ABI_CallFunction((void(*)())func); ABI_CallFunction((void(*)())func);
PopRegs(false);
if (!addrIsStatic) if (!addrIsStatic)
MOV(32, R(RSCRATCH3), rdMapped); MOV(32, R(RSCRATCH3), rdMapped);
@ -352,6 +358,8 @@ void Compiler::Comp_MemAccess(int rd, int rn, const ComplexOperand& op2, int siz
if (compileSlowPath) if (compileSlowPath)
{ {
PushRegs(false);
if (Num == 0) if (Num == 0)
{ {
MOV(32, R(ABI_PARAM2), R(RSCRATCH3)); MOV(32, R(ABI_PARAM2), R(RSCRATCH3));
@ -402,6 +410,9 @@ void Compiler::Comp_MemAccess(int rd, int rn, const ComplexOperand& op2, int siz
} }
} }
} }
PopRegs(false);
if (!(flags & memop_Store)) if (!(flags & memop_Store))
{ {
if (flags & memop_SignExtend) if (flags & memop_SignExtend)
@ -561,6 +572,8 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
if (!store) if (!store)
{ {
PushRegs(false);
MOV(32, R(ABI_PARAM1), R(RSCRATCH4)); MOV(32, R(ABI_PARAM1), R(RSCRATCH4));
MOV(32, R(ABI_PARAM3), Imm32(regsCount)); MOV(32, R(ABI_PARAM3), Imm32(regsCount));
SUB(64, R(RSP), stackAlloc <= INT8_MAX ? Imm8(stackAlloc) : Imm32(stackAlloc)); SUB(64, R(RSP), stackAlloc <= INT8_MAX ? Imm8(stackAlloc) : Imm32(stackAlloc));
@ -580,6 +593,8 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
case 3: CALL((void*)&SlowBlockTransfer7<true, false>); break; case 3: CALL((void*)&SlowBlockTransfer7<true, false>); break;
} }
PopRegs(false);
if (allocOffset) if (allocOffset)
ADD(64, R(RSP), Imm8(allocOffset)); ADD(64, R(RSP), Imm8(allocOffset));
@ -655,6 +670,8 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
if (allocOffset) if (allocOffset)
SUB(64, R(RSP), Imm8(allocOffset)); SUB(64, R(RSP), Imm8(allocOffset));
PushRegs(false);
MOV(32, R(ABI_PARAM1), R(RSCRATCH4)); MOV(32, R(ABI_PARAM1), R(RSCRATCH4));
if (allocOffset) if (allocOffset)
LEA(64, ABI_PARAM2, MDisp(RSP, allocOffset)); LEA(64, ABI_PARAM2, MDisp(RSP, allocOffset));
@ -674,6 +691,8 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
} }
ADD(64, R(RSP), stackAlloc <= INT8_MAX ? Imm8(stackAlloc) : Imm32(stackAlloc)); ADD(64, R(RSP), stackAlloc <= INT8_MAX ? Imm8(stackAlloc) : Imm32(stackAlloc));
PopRegs(false);
} }
if (compileFastPath) if (compileFastPath)