load register only if needed

- do thumb bl long merge in the first step
- preparations for better branch jitting
This commit is contained in:
RSDuck 2019-09-08 14:48:20 +02:00
parent 85680d6fe5
commit 0e26aa4ede
7 changed files with 48 additions and 32 deletions

View File

@ -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;
@ -166,6 +167,10 @@ CompiledBlock CompileBlock(ARM* cpu)
instrs[i].SetFlags = 0; instrs[i].SetFlags = 0;
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)
{ {
@ -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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -212,6 +212,9 @@ enum
tk_UNK, tk_UNK,
tk_SVC, tk_SVC,
// not a real instruction
tk_BL_LONG,
tk_Count tk_Count
}; };