allow allocating caller saved registers
currently system-v only
This commit is contained in:
parent
0f53a34551
commit
5a0b568647
|
@ -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
|
||||||
|
|
|
@ -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]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue