aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRSDuck <rsduck@users.noreply.github.com>2019-09-08 14:48:20 +0200
committerRSDuck <rsduck@users.noreply.github.com>2020-06-16 11:56:02 +0200
commit0e26aa4edeafa0dab57d6e5a1b77e1a80c6ae3c4 (patch)
tree55f9d6d3d9b74149127f827bdfb5a44896c79521
parent85680d6fe56a701d85f7312766764615fab2f012 (diff)
load register only if needed
- do thumb bl long merge in the first step - preparations for better branch jitting
-rw-r--r--src/ARMJIT.cpp16
-rw-r--r--src/ARMJIT.h1
-rw-r--r--src/ARMJIT_RegisterCache.h12
-rw-r--r--src/ARMJIT_x64/ARMJIT_Branch.cpp12
-rw-r--r--src/ARMJIT_x64/ARMJIT_Compiler.cpp34
-rw-r--r--src/ARMJIT_x64/ARMJIT_Compiler.h2
-rw-r--r--src/ARM_InstrInfo.h3
7 files changed, 48 insertions, 32 deletions
diff --git a/src/ARMJIT.cpp b/src/ARMJIT.cpp
index 5d92e47..85cadf3 100644
--- a/src/ARMJIT.cpp
+++ b/src/ARMJIT.cpp
@@ -159,6 +159,7 @@ CompiledBlock CompileBlock(ARM* cpu)
u32 r15 = cpu->R[15];
cpu->FillPipeline();
u32 nextInstr[2] = {cpu->NextInstr[0], cpu->NextInstr[1]};
+ u32 nextInstrAddr[2] = {blockAddr, r15};
do
{
r15 += thumb ? 2 : 4;
@@ -166,6 +167,10 @@ CompiledBlock CompileBlock(ARM* cpu)
instrs[i].SetFlags = 0;
instrs[i].Instr = nextInstr[0];
instrs[i].NextInstr[0] = nextInstr[0] = nextInstr[1];
+
+ instrs[i].Addr = nextInstrAddr[0];
+ nextInstrAddr[0] = nextInstrAddr[1];
+ nextInstrAddr[1] = r15;
if (cpu->Num == 0)
{
@@ -193,8 +198,19 @@ CompiledBlock CompileBlock(ARM* cpu)
instrs[i].NextInstr[1] = nextInstr[1];
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++;
+
bool canCompile = compiler->CanCompile(thumb, instrs[i - 1].Info.Kind);
if (instrs[i - 1].Info.ReadFlags != 0 || !canCompile)
floodFillSetFlags(instrs, i - 2, canCompile ? instrs[i - 1].Info.ReadFlags : 0xF);
diff --git a/src/ARMJIT.h b/src/ARMJIT.h
index 6197695..7e448ef 100644
--- a/src/ARMJIT.h
+++ b/src/ARMJIT.h
@@ -31,6 +31,7 @@ struct FetchedInstr
u8 SetFlags;
u32 Instr;
u32 NextInstr[2];
+ u32 Addr;
u8 CodeCycles;
diff --git a/src/ARMJIT_RegisterCache.h b/src/ARMJIT_RegisterCache.h
index 04c1eda..fe2f203 100644
--- a/src/ARMJIT_RegisterCache.h
+++ b/src/ARMJIT_RegisterCache.h
@@ -38,7 +38,7 @@ public:
Mapping[reg] = (Reg)-1;
}
- void LoadRegister(int reg)
+ void LoadRegister(int reg, bool loadValue)
{
assert(Mapping[reg] == -1);
for (int i = 0; i < NativeRegsAvailable; i++)
@@ -50,7 +50,8 @@ public:
NativeRegsUsed |= 1 << (int)nativeReg;
LoadedRegs |= 1 << reg;
- Compiler->LoadReg(reg, nativeReg);
+ if (loadValue)
+ Compiler->LoadReg(reg, nativeReg);
return;
}
@@ -66,7 +67,7 @@ public:
UnloadRegister(reg);
}
- void Prepare(int i)
+ void Prepare(bool thumb, int i)
{
u16 futureNeeded = 0;
int ranking[16];
@@ -111,8 +112,11 @@ public:
loadedSet.m_val = LoadedRegs;
}
+ BitSet16 needValueLoaded(needToBeLoaded);
+ if (thumb || Instr.Cond() >= 0xE)
+ needValueLoaded = BitSet16(Instr.Info.SrcRegs);
for (int reg : needToBeLoaded)
- LoadRegister(reg);
+ LoadRegister(reg, needValueLoaded[reg]);
}
DirtyRegs |= Instr.Info.DstRegs & ~(1 << 15);
}
diff --git a/src/ARMJIT_x64/ARMJIT_Branch.cpp b/src/ARMJIT_x64/ARMJIT_Branch.cpp
index c0a8f1f..cc7a3c4 100644
--- a/src/ARMJIT_x64/ARMJIT_Branch.cpp
+++ b/src/ARMJIT_x64/ARMJIT_Branch.cpp
@@ -271,15 +271,17 @@ void Compiler::T_Comp_BL_LONG_2()
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();
- u32 target = (R15 - 2) + ((s32)((part1.Instr & 0x7FF) << 21) >> 9);
- target += (CurInstr.Instr & 0x7FF) << 1;
+ R15 += 2;
- 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;
MOV(32, MapReg(14), Imm32((R15 - 2) | 1));
diff --git a/src/ARMJIT_x64/ARMJIT_Compiler.cpp b/src/ARMJIT_x64/ARMJIT_Compiler.cpp
index d585f39..d8ce1aa 100644
--- a/src/ARMJIT_x64/ARMJIT_Compiler.cpp
+++ b/src/ARMJIT_x64/ARMJIT_Compiler.cpp
@@ -338,7 +338,8 @@ const Compiler::CompileFunc T_Comp[ARMInstrInfo::tk_Count] = {
// 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),
// Unk, SVC
- NULL, NULL
+ NULL, NULL,
+ F(T_Comp_BL_Merged)
};
#undef F
@@ -361,21 +362,18 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
ConstantCycles = 0;
Thumb = cpu->CPSR & 0x20;
Num = cpu->Num;
- R15 = cpu->R[15];
CodeRegion = cpu->CodeRegion;
CurCPU = cpu;
CompiledBlock res = (CompiledBlock)GetWritableCodePtr();
if (!(Num == 0
- ? IsMapped<0>(R15 - (Thumb ? 2 : 4))
- : IsMapped<1>(R15 - (Thumb ? 2 : 4))))
+ ? IsMapped<0>(instrs[0].Addr - (Thumb ? 2 : 4))
+ : IsMapped<1>(instrs[0].Addr - (Thumb ? 2 : 4))))
{
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);
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++)
{
- R15 += Thumb ? 2 : 4;
CurInstr = instrs[i];
+ R15 = CurInstr.Addr + (Thumb ? 4 : 8);
CompileFunc comp = Thumb
? T_Comp[CurInstr.Info.Kind]
@@ -406,29 +404,21 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
}
if (comp != NULL)
- RegCache.Prepare(i);
+ RegCache.Prepare(Thumb, i);
else
RegCache.Flush();
if (Thumb)
{
- if (i < instrsCount - 1 && CurInstr.Info.Kind == ARMInstrInfo::tk_BL_LONG_1
- && instrs[i + 1].Info.Kind == ARMInstrInfo::tk_BL_LONG_2)
- mergedThumbBL = true;
- else
+ u32 icode = (CurInstr.Instr >> 6) & 0x3FF;
+ if (comp == NULL)
{
- u32 icode = (CurInstr.Instr >> 6) & 0x3FF;
- if (comp == NULL)
- {
- MOV(64, R(ABI_PARAM1), R(RCPU));
+ MOV(64, R(ABI_PARAM1), R(RCPU));
- ABI_CallFunction(ARMInterpreter::THUMBInstrTable[icode]);
- }
- else if (mergedThumbBL)
- T_Comp_BL_Merged(instrs[i - 1]);
- else
- (this->*comp)();
+ ABI_CallFunction(ARMInterpreter::THUMBInstrTable[icode]);
}
+ else
+ (this->*comp)();
}
else
{
diff --git a/src/ARMJIT_x64/ARMJIT_Compiler.h b/src/ARMJIT_x64/ARMJIT_Compiler.h
index a62f043..fcb2380 100644
--- a/src/ARMJIT_x64/ARMJIT_Compiler.h
+++ b/src/ARMJIT_x64/ARMJIT_Compiler.h
@@ -90,7 +90,7 @@ public:
void T_Comp_BranchXchangeReg();
void T_Comp_BL_LONG_1();
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);
s32 Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc, bool decrement, bool usermode);
diff --git a/src/ARM_InstrInfo.h b/src/ARM_InstrInfo.h
index 5336837..d01c600 100644
--- a/src/ARM_InstrInfo.h
+++ b/src/ARM_InstrInfo.h
@@ -212,6 +212,9 @@ enum
tk_UNK,
tk_SVC,
+ // not a real instruction
+ tk_BL_LONG,
+
tk_Count
};