aboutsummaryrefslogtreecommitdiff
path: root/src/ARMJIT_x64/ARMJIT_Compiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ARMJIT_x64/ARMJIT_Compiler.cpp')
-rw-r--r--src/ARMJIT_x64/ARMJIT_Compiler.cpp245
1 files changed, 115 insertions, 130 deletions
diff --git a/src/ARMJIT_x64/ARMJIT_Compiler.cpp b/src/ARMJIT_x64/ARMJIT_Compiler.cpp
index fb2fda8..f51d4d9 100644
--- a/src/ARMJIT_x64/ARMJIT_Compiler.cpp
+++ b/src/ARMJIT_x64/ARMJIT_Compiler.cpp
@@ -8,18 +8,16 @@ using namespace Gen;
namespace ARMJIT
{
-
-const int RegCache::NativeRegAllocOrder[] = {(int)RBX, (int)RSI, (int)RDI, (int)R12, (int)R13};
-const int RegCache::NativeRegsCount = 5;
+template <>
+const X64Reg RegCache<Compiler, X64Reg>::NativeRegAllocOrder[] = {RBX, RSI, RDI, R12, R13};
+template <>
+const int RegCache<Compiler, X64Reg>::NativeRegsAvailable = 5;
Compiler::Compiler()
{
AllocCodeSpace(1024 * 1024 * 4);
}
-typedef void (Compiler::*CompileFunc)();
-typedef void (*InterpretFunc)(ARM*);
-
void Compiler::LoadCPSR()
{
assert(!CPSRDirty);
@@ -36,6 +34,19 @@ void Compiler::SaveCPSR()
}
}
+void Compiler::LoadReg(int reg, X64Reg nativeReg)
+{
+ if (reg != 15)
+ MOV(32, R(nativeReg), MDisp(RCPU, offsetof(ARM, R[reg])));
+ else
+ MOV(32, R(nativeReg), Imm32(R15));
+}
+
+void Compiler::UnloadReg(int reg, X64Reg nativeReg)
+{
+ MOV(32, MDisp(RCPU, offsetof(ARM, R[reg])), R(nativeReg));
+}
+
CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrsCount)
{
if (IsAlmostFull())
@@ -58,12 +69,18 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
LoadCPSR();
+ // TODO: this is ugly as a whole, do better
+ RegCache = ARMJIT::RegCache<Compiler, X64Reg>(this, instrs, instrsCount);
+
for (int i = 0; i < instrsCount; i++)
{
R15 += Thumb ? 2 : 4;
CurrentInstr = instrs[i];
- CompileFunc comp = NULL;
+ CompileFunc comp = GetCompFunc(CurrentInstr.Info.Kind);
+
+ if (CurrentInstr.Info.Branches())
+ comp = NULL;
if (comp == NULL || i == instrsCount - 1)
{
@@ -79,6 +96,11 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
SaveCPSR();
}
+ if (comp != NULL)
+ RegCache.Prepare(i);
+ else
+ RegCache.Flush();
+
if (Thumb)
{
if (comp == NULL)
@@ -89,8 +111,7 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
ABI_CallFunction(ARMInterpreter::THUMBInstrTable[icode]);
}
else
- {
- }
+ (this->*comp)();
}
else
{
@@ -101,7 +122,7 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
ABI_CallFunction(ARMInterpreter::A_BLX_IMM);
}
else if (cond == 0xF)
- AddCycles_C();
+ Comp_AddCycles_C();
else
{
FixupBranch skipExecute;
@@ -115,17 +136,17 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
MOV(32, R(RSCRATCH), Imm32(1));
SHL(32, R(RSCRATCH), R(RSCRATCH3));
TEST(32, R(RSCRATCH), Imm32(ARM::ConditionTable[cond]));
-
+
skipExecute = J_CC(CC_Z);
}
else
{
// could have used a LUT, but then where would be the fun?
BT(32, R(RCPSR), Imm8(28 + ((~(cond >> 1) & 1) << 1 | (cond >> 2 & 1) ^ (cond >> 1 & 1))));
-
+
skipExecute = J_CC(cond & 1 ? CC_C : CC_NC);
}
-
+
}
if (comp == NULL)
@@ -136,8 +157,7 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
ABI_CallFunction(ARMInterpreter::ARMInstrTable[icode]);
}
else
- {
- }
+ (this->*comp)();
FixupBranch skipFailed;
if (CurrentInstr.Cond() < 0xE)
@@ -145,7 +165,7 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
skipFailed = J();
SetJumpTarget(skipExecute);
- AddCycles_C();
+ Comp_AddCycles_C();
SetJumpTarget(skipFailed);
}
@@ -155,13 +175,14 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
/*
we don't need to collect the interpreted cycles,
since all functions only add to it, the dispatcher
- can take care of it.
+ takes care of it.
*/
if (comp == NULL && i != instrsCount - 1)
LoadCPSR();
}
+ RegCache.Flush();
SaveCPSR();
LEA(32, RAX, MDisp(RCycles, ConstantCycles));
@@ -172,42 +193,57 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
return res;
}
-void Compiler::Compile(RegCache& regs, const FetchedInstr& instr)
+CompileFunc Compiler::GetCompFunc(int kind)
{
+ // this might look like waste of space, so many repeatitions, but it's invaluable for debugging.
+ // see ARMInstrInfo.h for the order
const CompileFunc A_Comp[ARMInstrInfo::ak_Count] =
{
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ // AND
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ // EOR
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ // SUB
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ // RSB
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ // ADD
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ // ADC
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ // SBC
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ // RSC
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ // ORR
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ // MOV
+ A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp,
+ A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp,
+ // BIC
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith, A_Comp_Arith,
+ // MVN
+ A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp,
+ A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp, A_Comp_MovOp,
+ // TST
+ A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp,
+ // TEQ
+ A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp,
+ // CMP
+ A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp,
+ // CMN
+ A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp, A_Comp_CmpOp,
+ NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -227,21 +263,34 @@ void Compiler::Compile(RegCache& regs, const FetchedInstr& instr)
};
const CompileFunc T_Comp[ARMInstrInfo::tk_Count] = {
- NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
+ // Shift imm
+ T_Comp_ShiftImm, T_Comp_ShiftImm, T_Comp_ShiftImm,
+ // Three operand ADD/SUB
+ T_Comp_AddSub_, T_Comp_AddSub_, T_Comp_AddSub_, T_Comp_AddSub_,
+ // 8 bit imm
+ T_Comp_ALU_Imm8, T_Comp_ALU_Imm8, T_Comp_ALU_Imm8, T_Comp_ALU_Imm8,
+ // general ALU
+ T_Comp_ALU, T_Comp_ALU, T_Comp_ALU, T_Comp_ALU,
+ T_Comp_ALU, T_Comp_ALU, T_Comp_ALU, T_Comp_ALU,
+ T_Comp_ALU, T_Comp_ALU, T_Comp_ALU, T_Comp_ALU,
+ T_Comp_ALU, NULL, T_Comp_ALU, T_Comp_ALU,
+ // hi reg
+ T_Comp_ALU_HiReg, T_Comp_ALU_HiReg, T_Comp_ALU_HiReg,
+ // pc/sp relative
+ NULL, NULL, NULL,
+ // mem...
+ NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL
};
+
+ return Thumb ? T_Comp[kind] : A_Comp[kind];
}
-void Compiler::AddCycles_C()
+void Compiler::Comp_AddCycles_C()
{
s32 cycles = Num ?
NDS::ARM7MemTimings[CurrentInstr.CodeCycles][Thumb ? 1 : 3]
@@ -253,80 +302,16 @@ void Compiler::AddCycles_C()
ConstantCycles += cycles;
}
-// may uses RSCRATCH for op2 and RSCRATCH2 for the carryValue
-OpArg Compiler::Comp_ShiftRegImm(int op, int amount, Gen::X64Reg rm, bool S, bool& carryUsed)
-{
- carryUsed = true;
-
- switch (op)
- {
- case 0: // LSL
- if (amount > 0)
- {
- MOV(32, R(RSCRATCH), R(rm));
- SHL(32, R(RSCRATCH), Imm8(amount));
- if (S)
- SETcc(CC_C, R(RSCRATCH2));
-
- return R(RSCRATCH);
- }
- else
- {
- carryUsed = false;
- return R(rm);
- }
- case 1: // LSR
- if (amount > 0)
- {
- MOV(32, R(RSCRATCH), R(rm));
- SHR(32, R(RSCRATCH), Imm8(amount));
- if (S)
- SETcc(CC_C, R(RSCRATCH2));
- return R(RSCRATCH);
- }
- else
- {
- if (S)
- {
- MOV(32, R(RSCRATCH2), R(rm));
- SHR(32, R(RSCRATCH2), Imm8(31));
- }
- return Imm32(0);
- }
- case 2: // ASR
- MOV(32, R(RSCRATCH), R(rm));
- SAR(32, R(RSCRATCH), Imm8(amount ? amount : 31));
- if (S)
- {
- if (amount == 0)
- {
- MOV(32, R(RSCRATCH2), R(rm));
- SHR(32, R(RSCRATCH2), Imm8(31));
- }
- else
- SETcc(CC_C, R(RSCRATCH2));
- }
- return R(RSCRATCH);
- case 3: // ROR
- if (amount > 0)
- {
- MOV(32, R(RSCRATCH), R(rm));
- ROR_(32, R(RSCRATCH), Imm8(amount));
- }
- else
- {
- BT(32, R(RCPSR), Imm8(29));
- MOV(32, R(RSCRATCH), R(rm));
- RCR(32, R(RSCRATCH), Imm8(1));
- }
- if (S)
- SETcc(CC_C, R(RSCRATCH2));
- return R(RSCRATCH);
- }
-}
-
-void Compiler::A_Comp_ALU(const FetchedInstr& instr)
+void Compiler::Comp_AddCycles_CI(u32 i)
{
+ s32 cycles = (Num ?
+ NDS::ARM7MemTimings[CurrentInstr.CodeCycles][Thumb ? 0 : 2]
+ : ((R15 & 0x2) ? 0 : CurrentInstr.CodeCycles)) + i;
+
+ if (CurrentInstr.Cond() < 0xE)
+ ADD(32, R(RCycles), Imm8(cycles));
+ else
+ ConstantCycles += cycles;
}
} \ No newline at end of file