load register only if needed
- do thumb bl long merge in the first step - preparations for better branch jitting
This commit is contained in:
parent
2ef776883f
commit
5338c28f40
|
@ -159,6 +159,7 @@ CompiledBlock CompileBlock(ARM* cpu)
|
||||||
u32 r15 = cpu->R[15];
|
u32 r15 = cpu->R[15];
|
||||||
cpu->FillPipeline();
|
cpu->FillPipeline();
|
||||||
u32 nextInstr[2] = {cpu->NextInstr[0], cpu->NextInstr[1]};
|
u32 nextInstr[2] = {cpu->NextInstr[0], cpu->NextInstr[1]};
|
||||||
|
u32 nextInstrAddr[2] = {blockAddr, r15};
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
r15 += thumb ? 2 : 4;
|
r15 += thumb ? 2 : 4;
|
||||||
|
@ -167,6 +168,10 @@ CompiledBlock CompileBlock(ARM* cpu)
|
||||||
instrs[i].Instr = nextInstr[0];
|
instrs[i].Instr = nextInstr[0];
|
||||||
instrs[i].NextInstr[0] = nextInstr[0] = nextInstr[1];
|
instrs[i].NextInstr[0] = nextInstr[0] = nextInstr[1];
|
||||||
|
|
||||||
|
instrs[i].Addr = nextInstrAddr[0];
|
||||||
|
nextInstrAddr[0] = nextInstrAddr[1];
|
||||||
|
nextInstrAddr[1] = r15;
|
||||||
|
|
||||||
if (cpu->Num == 0)
|
if (cpu->Num == 0)
|
||||||
{
|
{
|
||||||
ARMv5* cpuv5 = (ARMv5*)cpu;
|
ARMv5* cpuv5 = (ARMv5*)cpu;
|
||||||
|
@ -193,8 +198,19 @@ CompiledBlock CompileBlock(ARM* cpu)
|
||||||
instrs[i].NextInstr[1] = nextInstr[1];
|
instrs[i].NextInstr[1] = nextInstr[1];
|
||||||
instrs[i].Info = ARMInstrInfo::Decode(thumb, cpu->Num, instrs[i].Instr);
|
instrs[i].Info = ARMInstrInfo::Decode(thumb, cpu->Num, instrs[i].Instr);
|
||||||
|
|
||||||
|
if (thumb && instrs[i].Info.Kind == ARMInstrInfo::tk_BL_LONG_2 && i > 0
|
||||||
|
&& instrs[i - 1].Info.Kind == ARMInstrInfo::tk_BL_LONG_1)
|
||||||
|
{
|
||||||
|
instrs[i - 1].Info.Kind = ARMInstrInfo::tk_BL_LONG;
|
||||||
|
instrs[i - 1].Instr = (instrs[i - 1].Instr & 0xFFFF) | (instrs[i].Instr << 16);
|
||||||
|
instrs[i - 1].Info.DstRegs = 0xC000;
|
||||||
|
instrs[i - 1].Info.SrcRegs = 0;
|
||||||
|
instrs[i - 1].Info.EndBlock = true;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
|
|
||||||
bool canCompile = compiler->CanCompile(thumb, instrs[i - 1].Info.Kind);
|
bool canCompile = compiler->CanCompile(thumb, instrs[i - 1].Info.Kind);
|
||||||
if (instrs[i - 1].Info.ReadFlags != 0 || !canCompile)
|
if (instrs[i - 1].Info.ReadFlags != 0 || !canCompile)
|
||||||
floodFillSetFlags(instrs, i - 2, canCompile ? instrs[i - 1].Info.ReadFlags : 0xF);
|
floodFillSetFlags(instrs, i - 2, canCompile ? instrs[i - 1].Info.ReadFlags : 0xF);
|
||||||
|
|
|
@ -31,6 +31,7 @@ struct FetchedInstr
|
||||||
u8 SetFlags;
|
u8 SetFlags;
|
||||||
u32 Instr;
|
u32 Instr;
|
||||||
u32 NextInstr[2];
|
u32 NextInstr[2];
|
||||||
|
u32 Addr;
|
||||||
|
|
||||||
u8 CodeCycles;
|
u8 CodeCycles;
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
Mapping[reg] = (Reg)-1;
|
Mapping[reg] = (Reg)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadRegister(int reg)
|
void LoadRegister(int reg, bool loadValue)
|
||||||
{
|
{
|
||||||
assert(Mapping[reg] == -1);
|
assert(Mapping[reg] == -1);
|
||||||
for (int i = 0; i < NativeRegsAvailable; i++)
|
for (int i = 0; i < NativeRegsAvailable; i++)
|
||||||
|
@ -50,7 +50,8 @@ public:
|
||||||
NativeRegsUsed |= 1 << (int)nativeReg;
|
NativeRegsUsed |= 1 << (int)nativeReg;
|
||||||
LoadedRegs |= 1 << reg;
|
LoadedRegs |= 1 << reg;
|
||||||
|
|
||||||
Compiler->LoadReg(reg, nativeReg);
|
if (loadValue)
|
||||||
|
Compiler->LoadReg(reg, nativeReg);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +67,7 @@ public:
|
||||||
UnloadRegister(reg);
|
UnloadRegister(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Prepare(int i)
|
void Prepare(bool thumb, int i)
|
||||||
{
|
{
|
||||||
u16 futureNeeded = 0;
|
u16 futureNeeded = 0;
|
||||||
int ranking[16];
|
int ranking[16];
|
||||||
|
@ -111,8 +112,11 @@ public:
|
||||||
loadedSet.m_val = LoadedRegs;
|
loadedSet.m_val = LoadedRegs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BitSet16 needValueLoaded(needToBeLoaded);
|
||||||
|
if (thumb || Instr.Cond() >= 0xE)
|
||||||
|
needValueLoaded = BitSet16(Instr.Info.SrcRegs);
|
||||||
for (int reg : needToBeLoaded)
|
for (int reg : needToBeLoaded)
|
||||||
LoadRegister(reg);
|
LoadRegister(reg, needValueLoaded[reg]);
|
||||||
}
|
}
|
||||||
DirtyRegs |= Instr.Info.DstRegs & ~(1 << 15);
|
DirtyRegs |= Instr.Info.DstRegs & ~(1 << 15);
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,15 +271,17 @@ void Compiler::T_Comp_BL_LONG_2()
|
||||||
Comp_JumpTo(RSCRATCH);
|
Comp_JumpTo(RSCRATCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::T_Comp_BL_Merged(FetchedInstr part1)
|
void Compiler::T_Comp_BL_Merged()
|
||||||
{
|
{
|
||||||
assert(part1.Info.Kind == ARMInstrInfo::tk_BL_LONG_1);
|
|
||||||
Comp_AddCycles_C();
|
Comp_AddCycles_C();
|
||||||
|
|
||||||
u32 target = (R15 - 2) + ((s32)((part1.Instr & 0x7FF) << 21) >> 9);
|
R15 += 2;
|
||||||
target += (CurInstr.Instr & 0x7FF) << 1;
|
|
||||||
|
|
||||||
if (Num == 1 || CurInstr.Instr & (1 << 12))
|
u32 upperPart = CurInstr.Instr >> 16;
|
||||||
|
u32 target = (R15 - 2) + ((s32)((CurInstr.Instr & 0x7FF) << 21) >> 9);
|
||||||
|
target += (upperPart & 0x7FF) << 1;
|
||||||
|
|
||||||
|
if (Num == 1 || upperPart & (1 << 12))
|
||||||
target |= 1;
|
target |= 1;
|
||||||
|
|
||||||
MOV(32, MapReg(14), Imm32((R15 - 2) | 1));
|
MOV(32, MapReg(14), Imm32((R15 - 2) | 1));
|
||||||
|
|
|
@ -338,7 +338,8 @@ const Compiler::CompileFunc T_Comp[ARMInstrInfo::tk_Count] = {
|
||||||
// Branch
|
// Branch
|
||||||
F(T_Comp_BCOND), F(T_Comp_BranchXchangeReg), F(T_Comp_BranchXchangeReg), F(T_Comp_B), F(T_Comp_BL_LONG_1), F(T_Comp_BL_LONG_2),
|
F(T_Comp_BCOND), F(T_Comp_BranchXchangeReg), F(T_Comp_BranchXchangeReg), F(T_Comp_B), F(T_Comp_BL_LONG_1), F(T_Comp_BL_LONG_2),
|
||||||
// Unk, SVC
|
// Unk, SVC
|
||||||
NULL, NULL
|
NULL, NULL,
|
||||||
|
F(T_Comp_BL_Merged)
|
||||||
};
|
};
|
||||||
#undef F
|
#undef F
|
||||||
|
|
||||||
|
@ -361,21 +362,18 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
|
||||||
ConstantCycles = 0;
|
ConstantCycles = 0;
|
||||||
Thumb = cpu->CPSR & 0x20;
|
Thumb = cpu->CPSR & 0x20;
|
||||||
Num = cpu->Num;
|
Num = cpu->Num;
|
||||||
R15 = cpu->R[15];
|
|
||||||
CodeRegion = cpu->CodeRegion;
|
CodeRegion = cpu->CodeRegion;
|
||||||
CurCPU = cpu;
|
CurCPU = cpu;
|
||||||
|
|
||||||
CompiledBlock res = (CompiledBlock)GetWritableCodePtr();
|
CompiledBlock res = (CompiledBlock)GetWritableCodePtr();
|
||||||
|
|
||||||
if (!(Num == 0
|
if (!(Num == 0
|
||||||
? IsMapped<0>(R15 - (Thumb ? 2 : 4))
|
? IsMapped<0>(instrs[0].Addr - (Thumb ? 2 : 4))
|
||||||
: IsMapped<1>(R15 - (Thumb ? 2 : 4))))
|
: IsMapped<1>(instrs[0].Addr - (Thumb ? 2 : 4))))
|
||||||
{
|
{
|
||||||
printf("Trying to compile a block in unmapped memory\n");
|
printf("Trying to compile a block in unmapped memory\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mergedThumbBL = false;
|
|
||||||
|
|
||||||
ABI_PushRegistersAndAdjustStack(BitSet32(ABI_ALL_CALLEE_SAVED & ABI_ALL_GPRS & ~BitSet32({RSP})), 8);
|
ABI_PushRegistersAndAdjustStack(BitSet32(ABI_ALL_CALLEE_SAVED & ABI_ALL_GPRS & ~BitSet32({RSP})), 8);
|
||||||
|
|
||||||
MOV(64, R(RCPU), ImmPtr(cpu));
|
MOV(64, R(RCPU), ImmPtr(cpu));
|
||||||
|
@ -387,8 +385,8 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
|
||||||
|
|
||||||
for (int i = 0; i < instrsCount; i++)
|
for (int i = 0; i < instrsCount; i++)
|
||||||
{
|
{
|
||||||
R15 += Thumb ? 2 : 4;
|
|
||||||
CurInstr = instrs[i];
|
CurInstr = instrs[i];
|
||||||
|
R15 = CurInstr.Addr + (Thumb ? 4 : 8);
|
||||||
|
|
||||||
CompileFunc comp = Thumb
|
CompileFunc comp = Thumb
|
||||||
? T_Comp[CurInstr.Info.Kind]
|
? T_Comp[CurInstr.Info.Kind]
|
||||||
|
@ -406,29 +404,21 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp != NULL)
|
if (comp != NULL)
|
||||||
RegCache.Prepare(i);
|
RegCache.Prepare(Thumb, i);
|
||||||
else
|
else
|
||||||
RegCache.Flush();
|
RegCache.Flush();
|
||||||
|
|
||||||
if (Thumb)
|
if (Thumb)
|
||||||
{
|
{
|
||||||
if (i < instrsCount - 1 && CurInstr.Info.Kind == ARMInstrInfo::tk_BL_LONG_1
|
u32 icode = (CurInstr.Instr >> 6) & 0x3FF;
|
||||||
&& instrs[i + 1].Info.Kind == ARMInstrInfo::tk_BL_LONG_2)
|
if (comp == NULL)
|
||||||
mergedThumbBL = true;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
u32 icode = (CurInstr.Instr >> 6) & 0x3FF;
|
MOV(64, R(ABI_PARAM1), R(RCPU));
|
||||||
if (comp == NULL)
|
|
||||||
{
|
|
||||||
MOV(64, R(ABI_PARAM1), R(RCPU));
|
|
||||||
|
|
||||||
ABI_CallFunction(ARMInterpreter::THUMBInstrTable[icode]);
|
ABI_CallFunction(ARMInterpreter::THUMBInstrTable[icode]);
|
||||||
}
|
|
||||||
else if (mergedThumbBL)
|
|
||||||
T_Comp_BL_Merged(instrs[i - 1]);
|
|
||||||
else
|
|
||||||
(this->*comp)();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
(this->*comp)();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -90,7 +90,7 @@ public:
|
||||||
void T_Comp_BranchXchangeReg();
|
void T_Comp_BranchXchangeReg();
|
||||||
void T_Comp_BL_LONG_1();
|
void T_Comp_BL_LONG_1();
|
||||||
void T_Comp_BL_LONG_2();
|
void T_Comp_BL_LONG_2();
|
||||||
void T_Comp_BL_Merged(FetchedInstr prefix);
|
void T_Comp_BL_Merged();
|
||||||
|
|
||||||
void Comp_MemAccess(Gen::OpArg rd, bool signExtend, bool store, int size);
|
void Comp_MemAccess(Gen::OpArg rd, bool signExtend, bool store, int size);
|
||||||
s32 Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc, bool decrement, bool usermode);
|
s32 Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc, bool decrement, bool usermode);
|
||||||
|
|
|
@ -212,6 +212,9 @@ enum
|
||||||
tk_UNK,
|
tk_UNK,
|
||||||
tk_SVC,
|
tk_SVC,
|
||||||
|
|
||||||
|
// not a real instruction
|
||||||
|
tk_BL_LONG,
|
||||||
|
|
||||||
tk_Count
|
tk_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue