JIT: implemented most ALU instructions
This commit is contained in:
parent
c692287eba
commit
2f6b46fd4f
18
src/ARM.cpp
18
src/ARM.cpp
|
@ -560,10 +560,10 @@ void ARMv5::Execute()
|
||||||
AddCycles_C();
|
AddCycles_C();
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
if (!ARMJIT::IsMapped(Num, R[15] - ((CPSR&0x20)?2:4)))
|
/*if (!ARMJIT::IsMapped(0, R[15] - ((CPSR&0x20)?2:4)))
|
||||||
printf("aaarg ungempappter raum %x\n", R[15]);
|
printf("aaarg ungempappter raum %x\n", R[15]);*/
|
||||||
|
|
||||||
ARMJIT::CompiledBlock block = ARMJIT::LookUpBlock(Num, R[15] - ((CPSR&0x20)?2:4));
|
ARMJIT::CompiledBlock block = ARMJIT::LookUpBlock(0, R[15] - ((CPSR&0x20)?2:4));
|
||||||
if (block == NULL)
|
if (block == NULL)
|
||||||
block = ARMJIT::CompileBlock(this);
|
block = ARMJIT::CompileBlock(this);
|
||||||
Cycles += block();
|
Cycles += block();
|
||||||
|
@ -615,7 +615,7 @@ void ARMv4::Execute()
|
||||||
|
|
||||||
while (NDS::ARM7Timestamp < NDS::ARM7Target)
|
while (NDS::ARM7Timestamp < NDS::ARM7Target)
|
||||||
{
|
{
|
||||||
if (CPSR & 0x20) // THUMB
|
/*if (CPSR & 0x20) // THUMB
|
||||||
{
|
{
|
||||||
// prefetch
|
// prefetch
|
||||||
R[15] += 2;
|
R[15] += 2;
|
||||||
|
@ -643,7 +643,15 @@ void ARMv4::Execute()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
AddCycles_C();
|
AddCycles_C();
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
/*if (!ARMJIT::IsMapped(1, R[15] - ((CPSR&0x20)?2:4)))
|
||||||
|
printf("aaarg ungempappter raum %x\n", R[15]);*/
|
||||||
|
|
||||||
|
ARMJIT::CompiledBlock block = ARMJIT::LookUpBlock(1, R[15] - ((CPSR&0x20)?2:4));
|
||||||
|
if (block == NULL)
|
||||||
|
block = ARMJIT::CompileBlock(this);
|
||||||
|
Cycles += block();
|
||||||
|
|
||||||
// TODO optimize this shit!!!
|
// TODO optimize this shit!!!
|
||||||
if (Halted)
|
if (Halted)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "ARMJIT.h"
|
#include "ARMJIT.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "ARMJIT_x64/ARMJIT_Compiler.h"
|
#include "ARMJIT_x64/ARMJIT_Compiler.h"
|
||||||
|
|
||||||
namespace ARMJIT
|
namespace ARMJIT
|
||||||
|
@ -8,7 +10,6 @@ namespace ARMJIT
|
||||||
Compiler* compiler;
|
Compiler* compiler;
|
||||||
BlockCache cache;
|
BlockCache cache;
|
||||||
|
|
||||||
|
|
||||||
#define DUP2(x) x, x
|
#define DUP2(x) x, x
|
||||||
|
|
||||||
static ptrdiff_t JIT_MEM[2][32] = {
|
static ptrdiff_t JIT_MEM[2][32] = {
|
||||||
|
@ -174,4 +175,17 @@ CompiledBlock CompileBlock(ARM* cpu)
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ResetBlocks()
|
||||||
|
{
|
||||||
|
memset(cache.MainRAM, 0, sizeof(cache.MainRAM));
|
||||||
|
memset(cache.SWRAM, 0, sizeof(cache.SWRAM));
|
||||||
|
memset(cache.ARM9_BIOS, 0, sizeof(cache.ARM9_BIOS));
|
||||||
|
memset(cache.ARM9_ITCM, 0, sizeof(cache.ARM9_ITCM));
|
||||||
|
memset(cache.ARM9_LCDC, 0, sizeof(cache.ARM9_LCDC));
|
||||||
|
memset(cache.ARM7_BIOS, 0, sizeof(cache.ARM7_BIOS));
|
||||||
|
memset(cache.ARM7_WIRAM, 0, sizeof(cache.ARM7_WIRAM));
|
||||||
|
memset(cache.ARM7_WRAM, 0, sizeof(cache.ARM7_WRAM));
|
||||||
|
memset(cache.ARM7_WVRAM, 0, sizeof(cache.ARM7_WVRAM));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
25
src/ARMJIT.h
25
src/ARMJIT.h
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "ARM.h"
|
#include "ARM.h"
|
||||||
#include "ARM_InstrInfo.h"
|
#include "ARM_InstrInfo.h"
|
||||||
|
|
||||||
|
@ -13,14 +11,6 @@ namespace ARMJIT
|
||||||
|
|
||||||
typedef u32 (*CompiledBlock)();
|
typedef u32 (*CompiledBlock)();
|
||||||
|
|
||||||
class RegCache
|
|
||||||
{
|
|
||||||
|
|
||||||
static const int NativeRegAllocOrder[];
|
|
||||||
static const int NativeRegsCount;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FetchedInstr
|
struct FetchedInstr
|
||||||
{
|
{
|
||||||
u32 A_Reg(int pos) const
|
u32 A_Reg(int pos) const
|
||||||
|
@ -117,24 +107,13 @@ inline void InsertBlock(u32 num, u32 addr, CompiledBlock func)
|
||||||
cache.AddrMapping[num][(addr & 0xFFFFFFF) >> 14][(addr & 0x3FFF) >> 1] = func;
|
cache.AddrMapping[num][(addr & 0xFFFFFFF) >> 14][(addr & 0x3FFF) >> 1] = func;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void ResetBlocks()
|
|
||||||
{
|
|
||||||
memset(cache.MainRAM, 0, sizeof(cache.MainRAM));
|
|
||||||
memset(cache.SWRAM, 0, sizeof(cache.SWRAM));
|
|
||||||
memset(cache.ARM9_BIOS, 0, sizeof(cache.ARM9_BIOS));
|
|
||||||
memset(cache.ARM9_ITCM, 0, sizeof(cache.ARM9_ITCM));
|
|
||||||
memset(cache.ARM9_LCDC, 0, sizeof(cache.ARM9_LCDC));
|
|
||||||
memset(cache.ARM7_BIOS, 0, sizeof(cache.ARM7_BIOS));
|
|
||||||
memset(cache.ARM7_WIRAM, 0, sizeof(cache.ARM7_WIRAM));
|
|
||||||
memset(cache.ARM7_WRAM, 0, sizeof(cache.ARM7_WRAM));
|
|
||||||
memset(cache.ARM7_WVRAM, 0, sizeof(cache.ARM7_WVRAM));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void DeInit();
|
void DeInit();
|
||||||
|
|
||||||
CompiledBlock CompileBlock(ARM* cpu);
|
CompiledBlock CompileBlock(ARM* cpu);
|
||||||
|
|
||||||
|
void ResetBlocks();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -0,0 +1,136 @@
|
||||||
|
#ifndef ARMJIT_REGCACHE_H
|
||||||
|
#define ARMJIT_REGCACHE_H
|
||||||
|
|
||||||
|
#include "ARMJIT.h"
|
||||||
|
|
||||||
|
// TODO: replace this in the future
|
||||||
|
#include "dolphin/BitSet.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
namespace ARMJIT
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T, typename Reg>
|
||||||
|
class RegCache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RegCache()
|
||||||
|
{}
|
||||||
|
|
||||||
|
RegCache(T* compiler, FetchedInstr instrs[], int instrsCount)
|
||||||
|
: Compiler(compiler), Instrs(instrs), InstrsCount(instrsCount)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
Mapping[i] = (Reg)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnloadRegister(int reg)
|
||||||
|
{
|
||||||
|
assert(Mapping[reg] != -1);
|
||||||
|
|
||||||
|
if (DirtyRegs & (1 << reg))
|
||||||
|
Compiler->UnloadReg(reg, Mapping[reg]);
|
||||||
|
|
||||||
|
DirtyRegs &= ~(1 << reg);
|
||||||
|
LoadedRegs &= ~(1 << reg);
|
||||||
|
NativeRegsUsed &= ~(1 << (int)Mapping[reg]);
|
||||||
|
Mapping[reg] = (Reg)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadRegister(int reg)
|
||||||
|
{
|
||||||
|
assert(Mapping[reg] == -1);
|
||||||
|
for (int i = 0; i < NativeRegsAvailable; i++)
|
||||||
|
{
|
||||||
|
Reg nativeReg = NativeRegAllocOrder[i];
|
||||||
|
if (!(NativeRegsUsed & (1 << nativeReg)))
|
||||||
|
{
|
||||||
|
Mapping[reg] = nativeReg;
|
||||||
|
NativeRegsUsed |= 1 << (int)nativeReg;
|
||||||
|
LoadedRegs |= 1 << reg;
|
||||||
|
|
||||||
|
Compiler->LoadReg(reg, nativeReg);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert("Welp!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Flush()
|
||||||
|
{
|
||||||
|
BitSet16 loadedSet(LoadedRegs);
|
||||||
|
for (int reg : loadedSet)
|
||||||
|
UnloadRegister(reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Prepare(int i)
|
||||||
|
{
|
||||||
|
u16 futureNeeded = 0;
|
||||||
|
int ranking[16];
|
||||||
|
for (int j = 0; j < 16; j++)
|
||||||
|
ranking[j] = 0;
|
||||||
|
for (int j = i; j < InstrsCount; j++)
|
||||||
|
{
|
||||||
|
BitSet16 regsNeeded((Instrs[j].Info.SrcRegs & ~(1 << 15)) | Instrs[j].Info.DstRegs);
|
||||||
|
futureNeeded |= regsNeeded.m_val;
|
||||||
|
for (int reg : regsNeeded)
|
||||||
|
ranking[reg]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we'll unload all registers which are never used again
|
||||||
|
BitSet16 neverNeededAgain(LoadedRegs & ~futureNeeded);
|
||||||
|
for (int reg : neverNeededAgain)
|
||||||
|
UnloadRegister(reg);
|
||||||
|
|
||||||
|
FetchedInstr Instr = Instrs[i];
|
||||||
|
u16 necessaryRegs = (Instr.Info.SrcRegs & ~(1 << 15)) | Instr.Info.DstRegs;
|
||||||
|
BitSet16 needToBeLoaded(necessaryRegs & ~LoadedRegs);
|
||||||
|
if (needToBeLoaded != BitSet16(0))
|
||||||
|
{
|
||||||
|
int neededCount = needToBeLoaded.Count();
|
||||||
|
BitSet16 loadedSet(LoadedRegs);
|
||||||
|
while (loadedSet.Count() + neededCount > NativeRegsAvailable)
|
||||||
|
{
|
||||||
|
int leastReg = -1;
|
||||||
|
int rank = 1000;
|
||||||
|
for (int reg : loadedSet)
|
||||||
|
{
|
||||||
|
if (!((1 << reg) & necessaryRegs) && ranking[reg] < rank)
|
||||||
|
{
|
||||||
|
leastReg = reg;
|
||||||
|
rank = ranking[reg];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(leastReg != -1);
|
||||||
|
UnloadRegister(leastReg);
|
||||||
|
|
||||||
|
loadedSet.m_val = LoadedRegs;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int reg : needToBeLoaded)
|
||||||
|
LoadRegister(reg);
|
||||||
|
}
|
||||||
|
DirtyRegs |= Instr.Info.DstRegs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Reg NativeRegAllocOrder[];
|
||||||
|
static const int NativeRegsAvailable;
|
||||||
|
|
||||||
|
Reg Mapping[16];
|
||||||
|
u32 NativeRegsUsed = 0;
|
||||||
|
u16 LoadedRegs = 0;
|
||||||
|
u16 DirtyRegs = 0;
|
||||||
|
|
||||||
|
T* Compiler;
|
||||||
|
|
||||||
|
FetchedInstr* Instrs;
|
||||||
|
int InstrsCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,546 @@
|
||||||
|
#include "ARMJIT_Compiler.h"
|
||||||
|
|
||||||
|
using namespace Gen;
|
||||||
|
|
||||||
|
namespace ARMJIT
|
||||||
|
{
|
||||||
|
|
||||||
|
// uses RSCRATCH3
|
||||||
|
void Compiler::Comp_ArithTriOp(void (Compiler::*op)(int, const OpArg&, const OpArg&),
|
||||||
|
OpArg rd, OpArg rn, OpArg op2, bool carryUsed, int opFlags)
|
||||||
|
{
|
||||||
|
if (opFlags & opSyncCarry)
|
||||||
|
{
|
||||||
|
BT(32, R(RCPSR), Imm8(29));
|
||||||
|
if (opFlags & opInvertCarry)
|
||||||
|
CMC();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rd == rn && !(opFlags & opInvertOp2))
|
||||||
|
(this->*op)(32, rd, op2);
|
||||||
|
else if (opFlags & opSymmetric && op2 == R(RSCRATCH))
|
||||||
|
{
|
||||||
|
if (opFlags & opInvertOp2)
|
||||||
|
NOT(32, op2);
|
||||||
|
(this->*op)(32, op2, rn);
|
||||||
|
MOV(32, rd, op2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (opFlags & opInvertOp2)
|
||||||
|
{
|
||||||
|
if (op2 != R(RSCRATCH))
|
||||||
|
{
|
||||||
|
MOV(32, R(RSCRATCH), op2);
|
||||||
|
op2 = R(RSCRATCH);
|
||||||
|
}
|
||||||
|
NOT(32, op2);
|
||||||
|
}
|
||||||
|
MOV(32, R(RSCRATCH3), rn);
|
||||||
|
(this->*op)(32, R(RSCRATCH3), op2);
|
||||||
|
MOV(32, rd, R(RSCRATCH3));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opFlags & opSetsFlags)
|
||||||
|
Comp_RetriveFlags(opFlags & opInvertCarry, opFlags & opRetriveCV, carryUsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Compiler::Comp_ArithTriOpReverse(void (Compiler::*op)(int, const Gen::OpArg&, const Gen::OpArg&),
|
||||||
|
Gen::OpArg rd, Gen::OpArg rn, Gen::OpArg op2, bool carryUsed, int opFlags)
|
||||||
|
{
|
||||||
|
if (opFlags & opSyncCarry)
|
||||||
|
{
|
||||||
|
BT(32, R(RCPSR), Imm8(29));
|
||||||
|
if (opFlags & opInvertCarry)
|
||||||
|
CMC();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op2 != R(RSCRATCH))
|
||||||
|
{
|
||||||
|
MOV(32, R(RSCRATCH), op2);
|
||||||
|
op2 = R(RSCRATCH);
|
||||||
|
}
|
||||||
|
(this->*op)(32, op2, rn);
|
||||||
|
MOV(32, rd, op2);
|
||||||
|
|
||||||
|
if (opFlags & opSetsFlags)
|
||||||
|
Comp_RetriveFlags(opFlags & opInvertCarry, opFlags & opRetriveCV, carryUsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Compiler::Comp_CmpOp(int op, Gen::OpArg rn, Gen::OpArg op2, bool carryUsed)
|
||||||
|
{
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case 0: // TST
|
||||||
|
if (rn.IsImm())
|
||||||
|
{
|
||||||
|
MOV(32, R(RSCRATCH3), rn);
|
||||||
|
rn = R(RSCRATCH3);
|
||||||
|
}
|
||||||
|
TEST(32, rn, op2);
|
||||||
|
break;
|
||||||
|
case 1: // TEQ
|
||||||
|
MOV(32, R(RSCRATCH3), rn);
|
||||||
|
XOR(32, R(RSCRATCH3), op2);
|
||||||
|
break;
|
||||||
|
case 2: // CMP
|
||||||
|
if (rn.IsImm())
|
||||||
|
{
|
||||||
|
MOV(32, R(RSCRATCH3), rn);
|
||||||
|
rn = R(RSCRATCH3);
|
||||||
|
}
|
||||||
|
CMP(32, rn, op2);
|
||||||
|
break;
|
||||||
|
case 3: // CMN
|
||||||
|
MOV(32, R(RSCRATCH3), rn);
|
||||||
|
ADD(32, R(RSCRATCH3), op2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Comp_RetriveFlags(op == 2, op >= 2, carryUsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// also calculates cycles
|
||||||
|
OpArg Compiler::A_Comp_GetALUOp2(bool S, bool& carryUsed)
|
||||||
|
{
|
||||||
|
if (CurrentInstr.Instr & (1 << 25))
|
||||||
|
{
|
||||||
|
Comp_AddCycles_C();
|
||||||
|
carryUsed = false;
|
||||||
|
return Imm32(ROR(CurrentInstr.Instr & 0xFF, (CurrentInstr.Instr >> 7) & 0x1E));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int op = (CurrentInstr.Instr >> 5) & 0x3;
|
||||||
|
if (CurrentInstr.Instr & (1 << 4))
|
||||||
|
{
|
||||||
|
Comp_AddCycles_CI(1);
|
||||||
|
OpArg rm = MapReg(CurrentInstr.A_Reg(0));
|
||||||
|
if (rm.IsImm() && CurrentInstr.A_Reg(0) == 15)
|
||||||
|
rm = Imm32(rm.Imm32() + 4);
|
||||||
|
return Comp_RegShiftReg(op, MapReg(CurrentInstr.A_Reg(8)), rm, S, carryUsed);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Comp_AddCycles_C();
|
||||||
|
return Comp_RegShiftImm(op, (CurrentInstr.Instr >> 7) & 0x1F,
|
||||||
|
MapReg(CurrentInstr.A_Reg(0)), S, carryUsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Compiler::A_Comp_CmpOp()
|
||||||
|
{
|
||||||
|
u32 op = (CurrentInstr.Instr >> 21) & 0xF;
|
||||||
|
|
||||||
|
bool carryUsed;
|
||||||
|
OpArg rn = MapReg(CurrentInstr.A_Reg(16));
|
||||||
|
OpArg op2 = A_Comp_GetALUOp2((1 << op) & 0xF303, carryUsed);
|
||||||
|
|
||||||
|
Comp_CmpOp(op - 0x8, rn, op2, carryUsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Compiler::A_Comp_Arith()
|
||||||
|
{
|
||||||
|
bool S = CurrentInstr.Instr & (1 << 20);
|
||||||
|
u32 op = (CurrentInstr.Instr >> 21) & 0xF;
|
||||||
|
|
||||||
|
bool carryUsed;
|
||||||
|
OpArg rn = MapReg(CurrentInstr.A_Reg(16));
|
||||||
|
OpArg rd = MapReg(CurrentInstr.A_Reg(12));
|
||||||
|
OpArg op2 = A_Comp_GetALUOp2(S && (1 << op) & 0xF303, carryUsed);
|
||||||
|
|
||||||
|
u32 sFlag = S ? opSetsFlags : 0;
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case 0x0: // AND
|
||||||
|
Comp_ArithTriOp(AND, rd, rn, op2, carryUsed, opSymmetric|sFlag);
|
||||||
|
return;
|
||||||
|
case 0x1: // EOR
|
||||||
|
Comp_ArithTriOp(XOR, rd, rn, op2, carryUsed, opSymmetric|sFlag);
|
||||||
|
return;
|
||||||
|
case 0x2: // SUB
|
||||||
|
Comp_ArithTriOp(SUB, rd, rn, op2, carryUsed, sFlag|opRetriveCV|opInvertCarry);
|
||||||
|
return;
|
||||||
|
case 0x3: // RSB
|
||||||
|
if (op2.IsZero())
|
||||||
|
{
|
||||||
|
if (rd != rn)
|
||||||
|
MOV(32, rd, rn);
|
||||||
|
NEG(32, rd);
|
||||||
|
if (S)
|
||||||
|
Comp_RetriveFlags(true, true, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Comp_ArithTriOpReverse(SUB, rd, rn, op2, carryUsed, sFlag|opRetriveCV|opInvertCarry);
|
||||||
|
return;
|
||||||
|
case 0x4: // ADD
|
||||||
|
Comp_ArithTriOp(ADD, rd, rn, op2, carryUsed, opSymmetric|sFlag|opRetriveCV);
|
||||||
|
return;
|
||||||
|
case 0x5: // ADC
|
||||||
|
Comp_ArithTriOp(ADC, rd, rn, op2, carryUsed, opSymmetric|sFlag|opRetriveCV|opSyncCarry);
|
||||||
|
return;
|
||||||
|
case 0x6: // SBC
|
||||||
|
Comp_ArithTriOp(SBB, rd, rn, op2, carryUsed, opSymmetric|sFlag|opRetriveCV|opSyncCarry|opInvertCarry);
|
||||||
|
return;
|
||||||
|
case 0x7: // RSC
|
||||||
|
Comp_ArithTriOpReverse(SBB, rd, rn, op2, carryUsed, sFlag|opRetriveCV|opInvertCarry|opSyncCarry);
|
||||||
|
return;
|
||||||
|
case 0xC: // ORR
|
||||||
|
Comp_ArithTriOp(OR, rd, rn, op2, carryUsed, opSymmetric|sFlag);
|
||||||
|
return;
|
||||||
|
case 0xE: // BIC
|
||||||
|
Comp_ArithTriOp(AND, rd, rn, op2, carryUsed, sFlag|opSymmetric|opInvertOp2);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
assert("unimplemented");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Compiler::A_Comp_MovOp()
|
||||||
|
{
|
||||||
|
bool carryUsed;
|
||||||
|
bool S = CurrentInstr.Instr & (1 << 20);
|
||||||
|
OpArg op2 = A_Comp_GetALUOp2(S, carryUsed);
|
||||||
|
OpArg rd = MapReg(CurrentInstr.A_Reg(12));
|
||||||
|
|
||||||
|
if (rd != op2)
|
||||||
|
MOV(32, rd, op2);
|
||||||
|
|
||||||
|
if (((CurrentInstr.Instr >> 21) & 0xF) == 0xF)
|
||||||
|
NOT(32, rd);
|
||||||
|
|
||||||
|
if (S)
|
||||||
|
{
|
||||||
|
TEST(32, rd, rd);
|
||||||
|
Comp_RetriveFlags(false, false, carryUsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Compiler::Comp_RetriveFlags(bool sign, bool retriveCV, bool carryUsed)
|
||||||
|
{
|
||||||
|
CPSRDirty = true;
|
||||||
|
|
||||||
|
bool carryOnly = !retriveCV && carryUsed;
|
||||||
|
if (retriveCV)
|
||||||
|
{
|
||||||
|
SETcc(CC_O, R(RSCRATCH));
|
||||||
|
SETcc(sign ? CC_NC : CC_C, R(RSCRATCH3));
|
||||||
|
LEA(32, RSCRATCH2, MComplex(RSCRATCH, RSCRATCH3, SCALE_2, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (carryUsed == 983298)
|
||||||
|
printf("etwas ist faul im lande daenemark %x\n", CurrentInstr.Instr);
|
||||||
|
|
||||||
|
SETcc(CC_S, R(RSCRATCH));
|
||||||
|
SETcc(CC_Z, R(RSCRATCH3));
|
||||||
|
LEA(32, RSCRATCH, MComplex(RSCRATCH3, RSCRATCH, SCALE_2, 0));
|
||||||
|
int shiftAmount = 30;
|
||||||
|
if (retriveCV || carryUsed)
|
||||||
|
{
|
||||||
|
LEA(32, RSCRATCH, MComplex(RSCRATCH2, RSCRATCH, carryOnly ? SCALE_2 : SCALE_4, 0));
|
||||||
|
shiftAmount = carryOnly ? 29 : 28;
|
||||||
|
}
|
||||||
|
SHL(32, R(RSCRATCH), Imm8(shiftAmount));
|
||||||
|
|
||||||
|
AND(32, R(RCPSR), Imm32(0x3FFFFFFF & ~(carryUsed << 29) & ~((retriveCV ? 3 : 0) << 28)));
|
||||||
|
OR(32, R(RCPSR), R(RSCRATCH));
|
||||||
|
}
|
||||||
|
|
||||||
|
// always uses RSCRATCH, RSCRATCH2 only if S == true
|
||||||
|
OpArg Compiler::Comp_RegShiftReg(int op, Gen::OpArg rs, Gen::OpArg rm, bool S, bool& carryUsed)
|
||||||
|
{
|
||||||
|
carryUsed = S;
|
||||||
|
|
||||||
|
if (S)
|
||||||
|
{
|
||||||
|
XOR(32, R(RSCRATCH2), R(RSCRATCH2));
|
||||||
|
BT(32, R(RCPSR), Imm8(29));
|
||||||
|
SETcc(CC_C, R(RSCRATCH2));
|
||||||
|
}
|
||||||
|
|
||||||
|
MOV(32, R(RSCRATCH), rm);
|
||||||
|
static_assert(RSCRATCH3 == ECX);
|
||||||
|
MOV(32, R(ECX), rs);
|
||||||
|
AND(32, R(ECX), Imm32(0xFF));
|
||||||
|
|
||||||
|
FixupBranch zero = J_CC(CC_Z);
|
||||||
|
if (op < 3)
|
||||||
|
{
|
||||||
|
void (Compiler::*shiftOp)(int, const OpArg&, const OpArg&) = NULL;
|
||||||
|
if (op == 0)
|
||||||
|
shiftOp = SHL;
|
||||||
|
else if (op == 1)
|
||||||
|
shiftOp = SHR;
|
||||||
|
else if (op == 2)
|
||||||
|
shiftOp = SAR;
|
||||||
|
|
||||||
|
CMP(32, R(ECX), Imm8(32));
|
||||||
|
FixupBranch lt32 = J_CC(CC_L);
|
||||||
|
FixupBranch done1;
|
||||||
|
if (op < 2)
|
||||||
|
{
|
||||||
|
FixupBranch eq32 = J_CC(CC_E);
|
||||||
|
XOR(32, R(RSCRATCH), R(RSCRATCH));
|
||||||
|
if (S)
|
||||||
|
XOR(32, R(RSCRATCH2), R(RSCRATCH2));
|
||||||
|
done1 = J();
|
||||||
|
SetJumpTarget(eq32);
|
||||||
|
}
|
||||||
|
(this->*shiftOp)(32, R(RSCRATCH), Imm8(31));
|
||||||
|
(this->*shiftOp)(32, R(RSCRATCH), Imm8(1));
|
||||||
|
if (S)
|
||||||
|
SETcc(CC_C, R(RSCRATCH2));
|
||||||
|
|
||||||
|
FixupBranch done2 = J();
|
||||||
|
|
||||||
|
SetJumpTarget(lt32);
|
||||||
|
(this->*shiftOp)(32, R(RSCRATCH), R(ECX));
|
||||||
|
if (S)
|
||||||
|
SETcc(CC_C, R(RSCRATCH2));
|
||||||
|
|
||||||
|
if (op < 2)
|
||||||
|
SetJumpTarget(done1);
|
||||||
|
SetJumpTarget(done2);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (op == 3)
|
||||||
|
{
|
||||||
|
if (S)
|
||||||
|
BT(32, R(RSCRATCH), Imm8(31));
|
||||||
|
ROR_(32, R(RSCRATCH), R(ECX));
|
||||||
|
if (S)
|
||||||
|
SETcc(CC_C, R(RSCRATCH2));
|
||||||
|
}
|
||||||
|
SetJumpTarget(zero);
|
||||||
|
|
||||||
|
return R(RSCRATCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
// may uses RSCRATCH for op2 and RSCRATCH2 for the carryValue
|
||||||
|
OpArg Compiler::Comp_RegShiftImm(int op, int amount, OpArg rm, bool S, bool& carryUsed)
|
||||||
|
{
|
||||||
|
carryUsed = true;
|
||||||
|
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case 0: // LSL
|
||||||
|
if (amount > 0)
|
||||||
|
{
|
||||||
|
MOV(32, R(RSCRATCH), rm);
|
||||||
|
SHL(32, R(RSCRATCH), Imm8(amount));
|
||||||
|
if (S)
|
||||||
|
SETcc(CC_C, R(RSCRATCH2));
|
||||||
|
|
||||||
|
return R(RSCRATCH);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
carryUsed = false;
|
||||||
|
return rm;
|
||||||
|
}
|
||||||
|
case 1: // LSR
|
||||||
|
if (amount > 0)
|
||||||
|
{
|
||||||
|
MOV(32, R(RSCRATCH), rm);
|
||||||
|
SHR(32, R(RSCRATCH), Imm8(amount));
|
||||||
|
if (S)
|
||||||
|
SETcc(CC_C, R(RSCRATCH2));
|
||||||
|
return R(RSCRATCH);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (S)
|
||||||
|
{
|
||||||
|
MOV(32, R(RSCRATCH2), rm);
|
||||||
|
SHR(32, R(RSCRATCH2), Imm8(31));
|
||||||
|
}
|
||||||
|
return Imm32(0);
|
||||||
|
}
|
||||||
|
case 2: // ASR
|
||||||
|
MOV(32, R(RSCRATCH), rm);
|
||||||
|
SAR(32, R(RSCRATCH), Imm8(amount ? amount : 31));
|
||||||
|
if (S)
|
||||||
|
{
|
||||||
|
if (amount == 0)
|
||||||
|
BT(32, rm, Imm8(31));
|
||||||
|
SETcc(CC_C, R(RSCRATCH2));
|
||||||
|
}
|
||||||
|
return R(RSCRATCH);
|
||||||
|
case 3: // ROR
|
||||||
|
MOV(32, R(RSCRATCH), rm);
|
||||||
|
if (amount > 0)
|
||||||
|
ROR_(32, R(RSCRATCH), Imm8(amount));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BT(32, R(RCPSR), Imm8(29));
|
||||||
|
RCR(32, R(RSCRATCH), Imm8(1));
|
||||||
|
}
|
||||||
|
if (S)
|
||||||
|
SETcc(CC_C, R(RSCRATCH2));
|
||||||
|
return R(RSCRATCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Compiler::T_Comp_ShiftImm()
|
||||||
|
{
|
||||||
|
OpArg rd = MapReg(CurrentInstr.T_Reg(0));
|
||||||
|
OpArg rs = MapReg(CurrentInstr.T_Reg(3));
|
||||||
|
|
||||||
|
int op = (CurrentInstr.Instr >> 11) & 0x3;
|
||||||
|
int amount = (CurrentInstr.Instr >> 6) & 0x1F;
|
||||||
|
|
||||||
|
Comp_AddCycles_C();
|
||||||
|
|
||||||
|
bool carryUsed;
|
||||||
|
OpArg shifted = Comp_RegShiftImm(op, amount, rs, true, carryUsed);
|
||||||
|
|
||||||
|
if (shifted != rd)
|
||||||
|
MOV(32, rd, shifted);
|
||||||
|
|
||||||
|
TEST(32, rd, rd);
|
||||||
|
Comp_RetriveFlags(false, false, carryUsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Compiler::T_Comp_AddSub_()
|
||||||
|
{
|
||||||
|
OpArg rd = MapReg(CurrentInstr.T_Reg(0));
|
||||||
|
OpArg rs = MapReg(CurrentInstr.T_Reg(3));
|
||||||
|
|
||||||
|
int op = (CurrentInstr.Instr >> 9) & 0x3;
|
||||||
|
|
||||||
|
OpArg rn = op >= 2 ? Imm32((CurrentInstr.Instr >> 6) & 0x7) : MapReg(CurrentInstr.T_Reg(6));
|
||||||
|
|
||||||
|
Comp_AddCycles_C();
|
||||||
|
|
||||||
|
if (op & 1)
|
||||||
|
Comp_ArithTriOp(SUB, rd, rs, rn, false, opSetsFlags|opInvertCarry|opRetriveCV);
|
||||||
|
else
|
||||||
|
Comp_ArithTriOp(ADD, rd, rs, rn, false, opSetsFlags|opSymmetric|opRetriveCV);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Compiler::T_Comp_ALU_Imm8()
|
||||||
|
{
|
||||||
|
OpArg rd = MapReg(CurrentInstr.T_Reg(8));
|
||||||
|
|
||||||
|
u32 op = (CurrentInstr.Instr >> 11) & 0x3;
|
||||||
|
OpArg imm = Imm32(CurrentInstr.Instr & 0xFF);
|
||||||
|
|
||||||
|
Comp_AddCycles_C();
|
||||||
|
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case 0x0:
|
||||||
|
MOV(32, rd, imm);
|
||||||
|
TEST(32, rd, rd);
|
||||||
|
Comp_RetriveFlags(false, false, false);
|
||||||
|
return;
|
||||||
|
case 0x1:
|
||||||
|
Comp_CmpOp(2, rd, imm, false);
|
||||||
|
return;
|
||||||
|
case 0x2:
|
||||||
|
Comp_ArithTriOp(ADD, rd, rd, imm, false, opSetsFlags|opSymmetric|opRetriveCV);
|
||||||
|
return;
|
||||||
|
case 0x3:
|
||||||
|
Comp_ArithTriOp(SUB, rd, rd, imm, false, opSetsFlags|opInvertCarry|opRetriveCV);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Compiler::T_Comp_ALU()
|
||||||
|
{
|
||||||
|
OpArg rd = MapReg(CurrentInstr.T_Reg(0));
|
||||||
|
OpArg rs = MapReg(CurrentInstr.T_Reg(3));
|
||||||
|
|
||||||
|
u32 op = (CurrentInstr.Instr >> 6) & 0xF;
|
||||||
|
|
||||||
|
Comp_AddCycles_C();
|
||||||
|
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case 0x0: // AND
|
||||||
|
Comp_ArithTriOp(AND, rd, rd, rs, false, opSetsFlags|opSymmetric);
|
||||||
|
return;
|
||||||
|
case 0x1: // EOR
|
||||||
|
Comp_ArithTriOp(XOR, rd, rd, rs, false, opSetsFlags|opSymmetric);
|
||||||
|
return;
|
||||||
|
case 0x2:
|
||||||
|
case 0x3:
|
||||||
|
case 0x4:
|
||||||
|
case 0x7:
|
||||||
|
{
|
||||||
|
int shiftOp = op == 7 ? 3 : op - 0x2;
|
||||||
|
bool carryUsed;
|
||||||
|
OpArg shifted = Comp_RegShiftReg(shiftOp, rs, rd, true, carryUsed);
|
||||||
|
TEST(32, shifted, shifted);
|
||||||
|
MOV(32, rd, shifted);
|
||||||
|
Comp_RetriveFlags(false, false, true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case 0x5: // ADC
|
||||||
|
Comp_ArithTriOp(ADC, rd, rd, rs, false, opSetsFlags|opSymmetric|opSyncCarry|opRetriveCV);
|
||||||
|
return;
|
||||||
|
case 0x6: // SBC
|
||||||
|
Comp_ArithTriOp(SBB, rd, rd, rs, false, opSetsFlags|opSyncCarry|opInvertCarry|opRetriveCV);
|
||||||
|
return;
|
||||||
|
case 0x8: // TST
|
||||||
|
Comp_CmpOp(0, rd, rs, false);
|
||||||
|
return;
|
||||||
|
case 0x9: // NEG
|
||||||
|
if (rd != rs)
|
||||||
|
MOV(32, rd, rs);
|
||||||
|
NEG(32, rd);
|
||||||
|
Comp_RetriveFlags(true, true, false);
|
||||||
|
return;
|
||||||
|
case 0xA: // CMP
|
||||||
|
Comp_CmpOp(2, rd, rs, false);
|
||||||
|
return;
|
||||||
|
case 0xB: // CMN
|
||||||
|
Comp_CmpOp(3, rd, rs, false);
|
||||||
|
return;
|
||||||
|
case 0xC: // ORR
|
||||||
|
Comp_ArithTriOp(OR, rd, rd, rs, false, opSetsFlags|opSymmetric);
|
||||||
|
return;
|
||||||
|
case 0xE: // BIC
|
||||||
|
Comp_ArithTriOp(AND, rd, rd, rs, false, opSetsFlags|opSymmetric|opInvertOp2);
|
||||||
|
return;
|
||||||
|
case 0xF: // MVN
|
||||||
|
if (rd != rs)
|
||||||
|
MOV(32, rd, rs);
|
||||||
|
NOT(32, rd);
|
||||||
|
Comp_RetriveFlags(false, false, false);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Compiler::T_Comp_ALU_HiReg()
|
||||||
|
{
|
||||||
|
OpArg rd = MapReg(((CurrentInstr.Instr & 0x7) | ((CurrentInstr.Instr >> 4) & 0x8)));
|
||||||
|
OpArg rs = MapReg((CurrentInstr.Instr >> 3) & 0xF);
|
||||||
|
|
||||||
|
u32 op = (CurrentInstr.Instr >> 8) & 0x3;
|
||||||
|
|
||||||
|
Comp_AddCycles_C();
|
||||||
|
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case 0x0: // ADD
|
||||||
|
Comp_ArithTriOp(ADD, rd, rd, rs, false, opSymmetric|opRetriveCV);
|
||||||
|
return;
|
||||||
|
case 0x1: // CMP
|
||||||
|
Comp_CmpOp(2, rd, rs, false);
|
||||||
|
return;
|
||||||
|
case 0x2: // MOV
|
||||||
|
if (rd != rs)
|
||||||
|
MOV(32, rd, rs);
|
||||||
|
TEST(32, rd, rd);
|
||||||
|
Comp_RetriveFlags(false, false, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -8,18 +8,16 @@ using namespace Gen;
|
||||||
|
|
||||||
namespace ARMJIT
|
namespace ARMJIT
|
||||||
{
|
{
|
||||||
|
template <>
|
||||||
const int RegCache::NativeRegAllocOrder[] = {(int)RBX, (int)RSI, (int)RDI, (int)R12, (int)R13};
|
const X64Reg RegCache<Compiler, X64Reg>::NativeRegAllocOrder[] = {RBX, RSI, RDI, R12, R13};
|
||||||
const int RegCache::NativeRegsCount = 5;
|
template <>
|
||||||
|
const int RegCache<Compiler, X64Reg>::NativeRegsAvailable = 5;
|
||||||
|
|
||||||
Compiler::Compiler()
|
Compiler::Compiler()
|
||||||
{
|
{
|
||||||
AllocCodeSpace(1024 * 1024 * 4);
|
AllocCodeSpace(1024 * 1024 * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void (Compiler::*CompileFunc)();
|
|
||||||
typedef void (*InterpretFunc)(ARM*);
|
|
||||||
|
|
||||||
void Compiler::LoadCPSR()
|
void Compiler::LoadCPSR()
|
||||||
{
|
{
|
||||||
assert(!CPSRDirty);
|
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)
|
CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrsCount)
|
||||||
{
|
{
|
||||||
if (IsAlmostFull())
|
if (IsAlmostFull())
|
||||||
|
@ -58,12 +69,18 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
|
||||||
|
|
||||||
LoadCPSR();
|
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++)
|
for (int i = 0; i < instrsCount; i++)
|
||||||
{
|
{
|
||||||
R15 += Thumb ? 2 : 4;
|
R15 += Thumb ? 2 : 4;
|
||||||
CurrentInstr = instrs[i];
|
CurrentInstr = instrs[i];
|
||||||
|
|
||||||
CompileFunc comp = NULL;
|
CompileFunc comp = GetCompFunc(CurrentInstr.Info.Kind);
|
||||||
|
|
||||||
|
if (CurrentInstr.Info.Branches())
|
||||||
|
comp = NULL;
|
||||||
|
|
||||||
if (comp == NULL || i == instrsCount - 1)
|
if (comp == NULL || i == instrsCount - 1)
|
||||||
{
|
{
|
||||||
|
@ -79,6 +96,11 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
|
||||||
SaveCPSR();
|
SaveCPSR();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (comp != NULL)
|
||||||
|
RegCache.Prepare(i);
|
||||||
|
else
|
||||||
|
RegCache.Flush();
|
||||||
|
|
||||||
if (Thumb)
|
if (Thumb)
|
||||||
{
|
{
|
||||||
if (comp == NULL)
|
if (comp == NULL)
|
||||||
|
@ -89,8 +111,7 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
|
||||||
ABI_CallFunction(ARMInterpreter::THUMBInstrTable[icode]);
|
ABI_CallFunction(ARMInterpreter::THUMBInstrTable[icode]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
(this->*comp)();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -101,7 +122,7 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
|
||||||
ABI_CallFunction(ARMInterpreter::A_BLX_IMM);
|
ABI_CallFunction(ARMInterpreter::A_BLX_IMM);
|
||||||
}
|
}
|
||||||
else if (cond == 0xF)
|
else if (cond == 0xF)
|
||||||
AddCycles_C();
|
Comp_AddCycles_C();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FixupBranch skipExecute;
|
FixupBranch skipExecute;
|
||||||
|
@ -115,17 +136,17 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
|
||||||
MOV(32, R(RSCRATCH), Imm32(1));
|
MOV(32, R(RSCRATCH), Imm32(1));
|
||||||
SHL(32, R(RSCRATCH), R(RSCRATCH3));
|
SHL(32, R(RSCRATCH), R(RSCRATCH3));
|
||||||
TEST(32, R(RSCRATCH), Imm32(ARM::ConditionTable[cond]));
|
TEST(32, R(RSCRATCH), Imm32(ARM::ConditionTable[cond]));
|
||||||
|
|
||||||
skipExecute = J_CC(CC_Z);
|
skipExecute = J_CC(CC_Z);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// could have used a LUT, but then where would be the fun?
|
// 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))));
|
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);
|
skipExecute = J_CC(cond & 1 ? CC_C : CC_NC);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp == NULL)
|
if (comp == NULL)
|
||||||
|
@ -136,8 +157,7 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
|
||||||
ABI_CallFunction(ARMInterpreter::ARMInstrTable[icode]);
|
ABI_CallFunction(ARMInterpreter::ARMInstrTable[icode]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
(this->*comp)();
|
||||||
}
|
|
||||||
|
|
||||||
FixupBranch skipFailed;
|
FixupBranch skipFailed;
|
||||||
if (CurrentInstr.Cond() < 0xE)
|
if (CurrentInstr.Cond() < 0xE)
|
||||||
|
@ -145,7 +165,7 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
|
||||||
skipFailed = J();
|
skipFailed = J();
|
||||||
SetJumpTarget(skipExecute);
|
SetJumpTarget(skipExecute);
|
||||||
|
|
||||||
AddCycles_C();
|
Comp_AddCycles_C();
|
||||||
|
|
||||||
SetJumpTarget(skipFailed);
|
SetJumpTarget(skipFailed);
|
||||||
}
|
}
|
||||||
|
@ -155,13 +175,14 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
|
||||||
/*
|
/*
|
||||||
we don't need to collect the interpreted cycles,
|
we don't need to collect the interpreted cycles,
|
||||||
since all functions only add to it, the dispatcher
|
since all functions only add to it, the dispatcher
|
||||||
can take care of it.
|
takes care of it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (comp == NULL && i != instrsCount - 1)
|
if (comp == NULL && i != instrsCount - 1)
|
||||||
LoadCPSR();
|
LoadCPSR();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RegCache.Flush();
|
||||||
SaveCPSR();
|
SaveCPSR();
|
||||||
|
|
||||||
LEA(32, RAX, MDisp(RCycles, ConstantCycles));
|
LEA(32, RAX, MDisp(RCycles, ConstantCycles));
|
||||||
|
@ -172,42 +193,57 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
|
||||||
return res;
|
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] =
|
const CompileFunc A_Comp[ARMInstrInfo::ak_Count] =
|
||||||
{
|
{
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
// AND
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
// EOR
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
// SUB
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
// RSB
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
// ADD
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
// ADC
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
// SBC
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
// RSC
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
// ORR
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
// MOV
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
// BIC
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
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,
|
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] = {
|
const CompileFunc T_Comp[ARMInstrInfo::tk_Count] = {
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
// Shift imm
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
T_Comp_ShiftImm, T_Comp_ShiftImm, T_Comp_ShiftImm,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
// Three operand ADD/SUB
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
T_Comp_AddSub_, T_Comp_AddSub_, T_Comp_AddSub_, T_Comp_AddSub_,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
// 8 bit imm
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
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, NULL, NULL, 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 ?
|
s32 cycles = Num ?
|
||||||
NDS::ARM7MemTimings[CurrentInstr.CodeCycles][Thumb ? 1 : 3]
|
NDS::ARM7MemTimings[CurrentInstr.CodeCycles][Thumb ? 1 : 3]
|
||||||
|
@ -253,80 +302,16 @@ void Compiler::AddCycles_C()
|
||||||
ConstantCycles += cycles;
|
ConstantCycles += cycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
// may uses RSCRATCH for op2 and RSCRATCH2 for the carryValue
|
void Compiler::Comp_AddCycles_CI(u32 i)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
#include "../dolphin/x64Emitter.h"
|
#include "../dolphin/x64Emitter.h"
|
||||||
|
|
||||||
#include "../ARMJIT.h"
|
#include "../ARMJIT.h"
|
||||||
|
#include "../ARMJIT_RegCache.h"
|
||||||
|
|
||||||
namespace ARMJIT
|
namespace ARMJIT
|
||||||
{
|
{
|
||||||
|
@ -17,6 +17,10 @@ const Gen::X64Reg RSCRATCH = Gen::EAX;
|
||||||
const Gen::X64Reg RSCRATCH2 = Gen::EDX;
|
const Gen::X64Reg RSCRATCH2 = Gen::EDX;
|
||||||
const Gen::X64Reg RSCRATCH3 = Gen::ECX;
|
const Gen::X64Reg RSCRATCH3 = Gen::ECX;
|
||||||
|
|
||||||
|
class Compiler;
|
||||||
|
|
||||||
|
typedef void (Compiler::*CompileFunc)();
|
||||||
|
|
||||||
class Compiler : public Gen::X64CodeBlock
|
class Compiler : public Gen::X64CodeBlock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -24,24 +28,66 @@ public:
|
||||||
|
|
||||||
CompiledBlock CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrsCount);
|
CompiledBlock CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrsCount);
|
||||||
|
|
||||||
void StartBlock(ARM* cpu);
|
void LoadReg(int reg, Gen::X64Reg nativeReg);
|
||||||
CompiledBlock FinaliseBlock();
|
void UnloadReg(int reg, Gen::X64Reg nativeReg);
|
||||||
|
|
||||||
void Compile(RegCache& regs, const FetchedInstr& instr);
|
|
||||||
private:
|
private:
|
||||||
void AddCycles_C();
|
CompileFunc GetCompFunc(int kind);
|
||||||
|
|
||||||
Gen::OpArg Comp_ShiftRegImm(int op, int amount, Gen::X64Reg rm, bool S, bool& carryUsed);
|
void Comp_AddCycles_C();
|
||||||
|
void Comp_AddCycles_CI(u32 i);
|
||||||
|
|
||||||
void A_Comp_ALU(const FetchedInstr& instr);
|
enum
|
||||||
|
{
|
||||||
|
opSetsFlags = 1 << 0,
|
||||||
|
opSymmetric = 1 << 1,
|
||||||
|
opRetriveCV = 1 << 2,
|
||||||
|
opInvertCarry = 1 << 3,
|
||||||
|
opSyncCarry = 1 << 4,
|
||||||
|
opInvertOp2 = 1 << 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
void A_Comp_Arith();
|
||||||
|
void A_Comp_MovOp();
|
||||||
|
void A_Comp_CmpOp();
|
||||||
|
|
||||||
|
void T_Comp_ShiftImm();
|
||||||
|
void T_Comp_AddSub_();
|
||||||
|
void T_Comp_ALU_Imm8();
|
||||||
|
void T_Comp_ALU();
|
||||||
|
void T_Comp_ALU_HiReg();
|
||||||
|
|
||||||
|
void Comp_ArithTriOp(void (Compiler::*op)(int, const Gen::OpArg&, const Gen::OpArg&),
|
||||||
|
Gen::OpArg rd, Gen::OpArg rn, Gen::OpArg op2, bool carryUsed, int opFlags);
|
||||||
|
void Comp_ArithTriOpReverse(void (Compiler::*op)(int, const Gen::OpArg&, const Gen::OpArg&),
|
||||||
|
Gen::OpArg rd, Gen::OpArg rn, Gen::OpArg op2, bool carryUsed, int opFlags);
|
||||||
|
void Comp_CmpOp(int op, Gen::OpArg rn, Gen::OpArg op2, bool carryUsed);
|
||||||
|
|
||||||
|
void Comp_RetriveFlags(bool sign, bool retriveCV, bool carryUsed);
|
||||||
|
|
||||||
|
Gen::OpArg Comp_RegShiftImm(int op, int amount, Gen::OpArg rm, bool S, bool& carryUsed);
|
||||||
|
Gen::OpArg Comp_RegShiftReg(int op, Gen::OpArg rs, Gen::OpArg rm, bool S, bool& carryUsed);
|
||||||
|
|
||||||
|
Gen::OpArg A_Comp_GetALUOp2(bool S, bool& carryUsed);
|
||||||
|
|
||||||
void LoadCPSR();
|
void LoadCPSR();
|
||||||
void SaveCPSR();
|
void SaveCPSR();
|
||||||
|
|
||||||
|
Gen::OpArg MapReg(int reg)
|
||||||
|
{
|
||||||
|
if (reg == 15 && RegCache.Mapping[reg] == Gen::INVALID_REG)
|
||||||
|
return Gen::Imm32(R15);
|
||||||
|
|
||||||
|
assert(RegCache.Mapping[reg] != Gen::INVALID_REG);
|
||||||
|
return Gen::R(RegCache.Mapping[reg]);
|
||||||
|
}
|
||||||
|
|
||||||
bool CPSRDirty = false;
|
bool CPSRDirty = false;
|
||||||
|
|
||||||
FetchedInstr CurrentInstr;
|
FetchedInstr CurrentInstr;
|
||||||
|
|
||||||
|
RegCache<Compiler, Gen::X64Reg> RegCache;
|
||||||
|
|
||||||
bool Thumb;
|
bool Thumb;
|
||||||
u32 Num;
|
u32 Num;
|
||||||
u32 R15;
|
u32 R15;
|
||||||
|
|
|
@ -52,6 +52,7 @@ add_library(core STATIC
|
||||||
|
|
||||||
ARMJIT.cpp
|
ARMJIT.cpp
|
||||||
ARMJIT_x64/ARMJIT_Compiler.cpp
|
ARMJIT_x64/ARMJIT_Compiler.cpp
|
||||||
|
ARMJIT_x64/ARMJIT_ALU.cpp
|
||||||
|
|
||||||
dolphin/CommonFuncs.cpp
|
dolphin/CommonFuncs.cpp
|
||||||
dolphin/x64ABI.cpp
|
dolphin/x64ABI.cpp
|
||||||
|
|
Loading…
Reference in New Issue