mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-25 23:29:55 -06:00
JIT: implemented most ALU instructions
This commit is contained in:
@ -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;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user