Merge branch 'JitArmIL'

This implements a partial JITIL based off of the JIT64IL. It's enough to run most games, albiet at a slow speed.
Implementing instructions for this IL is really simple since it basically is just enabling based on what is already in JIT64IL, and then enabling each individual IL instruction.
This commit is contained in:
Ryan Houdek
2013-10-09 23:16:07 +00:00
32 changed files with 2387 additions and 314 deletions
+3 -1
View File
@@ -19,10 +19,12 @@
<string-array name="emuCoreEntriesARM" translatable="false">
<item>@string/interpreter</item>
<item>@string/jit_arm_recompiler</item>
<item>@string/jitil_arm_recompiler</item>
</string-array>
<string-array name="emuCoreValuesARM" translatable="false">
<item>0</item>
<item>3</item>
<item>4</item>
</string-array>
<!-- CPU core selection - Other -->
@@ -137,4 +139,4 @@
<item>4</item>
</string-array>
</resources>
</resources>
+1
View File
@@ -69,6 +69,7 @@
<string name="jit64_recompiler">JIT64 Recompiler</string>
<string name="jitil_recompiler">JITIL Recompiler</string>
<string name="jit_arm_recompiler">JIT ARM Recompiler</string>
<string name="jitil_arm_recompiler">JITIL ARM Recompiler</string>
<string name="cpu_core">CPU Core</string>
<string name="cpu_settings">CPU</string>
<string name="emu_core_to_use">Emulation core to use</string>
+4 -11
View File
@@ -491,11 +491,10 @@ void ARMXEmitter::POP(const int num, ...)
void ARMXEmitter::WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, Operand2 op2)
{
Write32(condition | (13 << 21) | (SetFlags << 20) | (dest << 12) | op2.Imm5() | (op << 4) | src);
}
void ARMXEmitter::WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, ARMReg op2)
{
Write32(condition | (13 << 21) | (SetFlags << 20) | (dest << 12) | (op2 << 8) | (op << 4) | src);
if (op2.GetType() == TYPE_REG)
Write32(condition | (13 << 21) | (SetFlags << 20) | (dest << 12) | (op2.GetData() << 8) | ((op + 1) << 4) | src);
else
Write32(condition | (13 << 21) | (SetFlags << 20) | (dest << 12) | op2.Imm5() | (op << 4) | src);
}
// IMM, REG, IMMSREG, RSR
@@ -610,16 +609,10 @@ void ARMXEmitter::SDIV(ARMReg dest, ARMReg dividend, ARMReg divisor)
}
void ARMXEmitter::LSL (ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(0, false, dest, src, op2);}
void ARMXEmitter::LSLS(ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(0, true, dest, src, op2);}
void ARMXEmitter::LSL (ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(1, false, dest, src, op2);}
void ARMXEmitter::LSLS(ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(1, true, dest, src, op2);}
void ARMXEmitter::LSR (ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(2, false, dest, src, op2);}
void ARMXEmitter::LSRS(ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(2, true, dest, src, op2);}
void ARMXEmitter::LSR (ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(3, false, dest, src, op2);}
void ARMXEmitter::LSRS(ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(3, true, dest, src, op2);}
void ARMXEmitter::ASR (ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(4, false, dest, src, op2);}
void ARMXEmitter::ASRS(ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(4, true, dest, src, op2);}
void ARMXEmitter::ASR (ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(5, false, dest, src, op2);}
void ARMXEmitter::ASRS(ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(5, true, dest, src, op2);}
void ARMXEmitter::MUL (ARMReg dest, ARMReg src, ARMReg op2)
{
-7
View File
@@ -357,7 +357,6 @@ private:
void WriteStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 op2, bool RegAdd);
void WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList);
void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, ARMReg op2);
void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, Operand2 op2);
void WriteSignedMultiply(u32 Op, u32 Op2, u32 Op3, ARMReg dest, ARMReg r1, ARMReg r2);
@@ -448,17 +447,11 @@ public:
void ADC (ARMReg dest, ARMReg src, Operand2 op2);
void ADCS(ARMReg dest, ARMReg src, Operand2 op2);
void LSL (ARMReg dest, ARMReg src, Operand2 op2);
void LSL (ARMReg dest, ARMReg src, ARMReg op2);
void LSLS(ARMReg dest, ARMReg src, Operand2 op2);
void LSLS(ARMReg dest, ARMReg src, ARMReg op2);
void LSR (ARMReg dest, ARMReg src, Operand2 op2);
void LSRS(ARMReg dest, ARMReg src, Operand2 op2);
void LSR (ARMReg dest, ARMReg src, ARMReg op2);
void LSRS(ARMReg dest, ARMReg src, ARMReg op2);
void ASR (ARMReg dest, ARMReg src, Operand2 op2);
void ASRS(ARMReg dest, ARMReg src, Operand2 op2);
void ASR (ARMReg dest, ARMReg src, ARMReg op2);
void ASRS(ARMReg dest, ARMReg src, ARMReg op2);
void SBC (ARMReg dest, ARMReg src, Operand2 op2);
void SBCS(ARMReg dest, ARMReg src, Operand2 op2);
void RBIT(ARMReg dest, ARMReg src);
+19 -11
View File
@@ -166,23 +166,24 @@ set(SRCS Src/ActionReplay.cpp
Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp
Src/PowerPC/Interpreter/Interpreter_Tables.cpp
Src/PowerPC/JitCommon/JitBase.cpp
Src/PowerPC/JitCommon/JitCache.cpp)
Src/PowerPC/JitCommon/JitCache.cpp
Src/PowerPC/JitILCommon/IR.cpp
Src/PowerPC/JitILCommon/JitILBase_Branch.cpp
Src/PowerPC/JitILCommon/JitILBase_LoadStore.cpp
Src/PowerPC/JitILCommon/JitILBase_SystemRegisters.cpp
Src/PowerPC/JitILCommon/JitILBase_LoadStoreFloating.cpp
Src/PowerPC/JitILCommon/JitILBase_LoadStorePaired.cpp
Src/PowerPC/JitILCommon/JitILBase_Paired.cpp
Src/PowerPC/JitILCommon/JitILBase_FloatingPoint.cpp
Src/PowerPC/JitILCommon/JitILBase_Integer.cpp
)
if(NOT _M_GENERIC)
set(SRCS ${SRCS}
Src/x64MemTools.cpp
Src/PowerPC/Jit64IL/IR.cpp
Src/PowerPC/Jit64IL/IR_X86.cpp
Src/PowerPC/Jit64IL/JitILAsm.cpp
Src/PowerPC/Jit64IL/JitIL_Branch.cpp
Src/PowerPC/Jit64IL/JitIL.cpp
Src/PowerPC/Jit64IL/JitIL_FloatingPoint.cpp
Src/PowerPC/Jit64IL/JitIL_Integer.cpp
Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp
Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp
Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp
Src/PowerPC/Jit64IL/JitIL_Paired.cpp
Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp
Src/PowerPC/Jit64IL/JitIL_Tables.cpp
Src/PowerPC/Jit64/Jit64_Tables.cpp
Src/PowerPC/Jit64/JitAsm.cpp
@@ -217,7 +218,14 @@ if(_M_ARM)
Src/PowerPC/JitArm32/JitArm_Paired.cpp
Src/PowerPC/JitArm32/JitArm_LoadStorePaired.cpp
Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp
Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp)
Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp
#JitArmIL
Src/PowerPC/JitArmIL/JitIL.cpp
Src/PowerPC/JitArmIL/JitILAsm.cpp
Src/PowerPC/JitArmIL/JitIL_Tables.cpp
Src/PowerPC/JitArmIL/JitIL_Branch.cpp
Src/PowerPC/JitArmIL/IR_Arm.cpp
)
endif()
set(LIBS bdisasm inputcommon videosoftware sfml-network)
+12 -11
View File
@@ -352,18 +352,18 @@
<ClCompile Include="Src\PowerPC\Interpreter\Interpreter_Paired.cpp" />
<ClCompile Include="Src\PowerPC\Interpreter\Interpreter_SystemRegisters.cpp" />
<ClCompile Include="Src\PowerPC\Interpreter\Interpreter_Tables.cpp" />
<ClCompile Include="Src\PowerPC\Jit64IL\IR.cpp" />
<ClCompile Include="Src\PowerPC\JitILCommon\IR.cpp" />
<ClCompile Include="Src\PowerPC\JitILCommon\JitILBase_Branch.cpp" />
<ClCompile Include="Src\PowerPC\JitILCommon\JitILBase_FloatingPoint.cpp" />
<ClCompile Include="Src\PowerPC\JitILCommon\JitILBase_Integer.cpp" />
<ClCompile Include="Src\PowerPC\JitILCommon\JitILBase_LoadStore.cpp" />
<ClCompile Include="Src\PowerPC\JitILCommon\JitILBase_LoadStoreFloating.cpp" />
<ClCompile Include="Src\PowerPC\JitILCommon\JitILBase_LoadStorePaired.cpp" />
<ClCompile Include="Src\PowerPC\JitILCommon\JitILBase_Paired.cpp" />
<ClCompile Include="Src\PowerPC\JitILCommon\JitILBase_SystemRegisters.cpp" />
<ClCompile Include="Src\PowerPC\Jit64IL\IR_X86.cpp" />
<ClCompile Include="Src\PowerPC\Jit64IL\JitIL.cpp" />
<ClCompile Include="Src\PowerPC\Jit64IL\JitILAsm.cpp" />
<ClCompile Include="Src\PowerPC\Jit64IL\JitIL_Branch.cpp" />
<ClCompile Include="Src\PowerPC\Jit64IL\JitIL_FloatingPoint.cpp" />
<ClCompile Include="Src\PowerPC\Jit64IL\JitIL_Integer.cpp" />
<ClCompile Include="Src\PowerPC\Jit64IL\JitIL_LoadStore.cpp" />
<ClCompile Include="Src\PowerPC\Jit64IL\JitIL_LoadStoreFloating.cpp" />
<ClCompile Include="Src\PowerPC\Jit64IL\JitIL_LoadStorePaired.cpp" />
<ClCompile Include="Src\PowerPC\Jit64IL\JitIL_Paired.cpp" />
<ClCompile Include="Src\PowerPC\Jit64IL\JitIL_SystemRegisters.cpp" />
<ClCompile Include="Src\PowerPC\Jit64IL\JitIL_Tables.cpp" />
<ClCompile Include="Src\PowerPC\Jit64\Jit.cpp" />
<ClCompile Include="Src\PowerPC\Jit64\Jit64_Tables.cpp" />
@@ -560,7 +560,6 @@
<ClInclude Include="Src\PowerPC\Interpreter\Interpreter.h" />
<ClInclude Include="Src\PowerPC\Interpreter\Interpreter_FPUtils.h" />
<ClInclude Include="Src\PowerPC\Interpreter\Interpreter_Tables.h" />
<ClInclude Include="Src\PowerPC\Jit64IL\IR.h" />
<ClInclude Include="Src\PowerPC\Jit64IL\JitIL.h" />
<ClInclude Include="Src\PowerPC\Jit64IL\JitILAsm.h" />
<ClInclude Include="Src\PowerPC\Jit64IL\JitIL_Tables.h" />
@@ -568,6 +567,8 @@
<ClInclude Include="Src\PowerPC\Jit64\Jit64_Tables.h" />
<ClInclude Include="Src\PowerPC\Jit64\JitAsm.h" />
<ClInclude Include="Src\PowerPC\Jit64\JitRegCache.h" />
<ClInclude Include="Src\PowerPC\JitILCommon\IR.h" />
<ClInclude Include="Src\PowerPC\JitILCommon\JitILBase.h" />
<ClInclude Include="Src\PowerPC\JitCommon\JitAsmCommon.h" />
<ClInclude Include="Src\PowerPC\JitCommon\JitBackpatch.h" />
<ClInclude Include="Src\PowerPC\JitCommon\JitBase.h" />
@@ -611,4 +612,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
@@ -24,7 +24,7 @@ The register allocation is linear scan allocation.
#pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned
#endif
#include "IR.h"
#include "../JitILCommon/IR.h"
#include "../PPCTables.h"
#include "../../CoreTiming.h"
#include "../../HW/Memmap.h"
+11 -95
View File
@@ -24,7 +24,8 @@
#include "../JitCommon/Jit_Util.h"
#include "x64Emitter.h"
#include "x64Analyzer.h"
#include "IR.h"
#include "../JitILCommon/JitILBase.h"
#include "../JitILCommon/IR.h"
#include "../JitCommon/JitBase.h"
#include "JitILAsm.h"
@@ -44,10 +45,11 @@
#define DISABLE64
#endif
class JitIL : public Jitx86Base
class JitIL : public JitILBase, public EmuCodeBlock
{
private:
JitBlockCache blocks;
TrampolineCache trampolines;
// The default code buffer. We keep it around to not have to alloc/dealloc a
// large chunk of memory for each recompiled block.
@@ -73,6 +75,12 @@ public:
void Trace();
JitBlockCache *GetBlockCache() { return &blocks; }
const u8 *BackPatch(u8 *codePtr, u32 em_address, void *ctx) { return NULL; };
bool IsInCodeSpace(u8 *ptr) { return IsInSpace(ptr); }
void ClearCache();
const u8 *GetDispatcher() {
return asm_routines.dispatcher; // asm_routines.dispatcher
@@ -125,98 +133,6 @@ public:
void DynaRunTable31(UGeckoInstruction _inst);
void DynaRunTable59(UGeckoInstruction _inst);
void DynaRunTable63(UGeckoInstruction _inst);
void addx(UGeckoInstruction inst);
void boolX(UGeckoInstruction inst);
void mulli(UGeckoInstruction inst);
void mulhwux(UGeckoInstruction inst);
void mullwx(UGeckoInstruction inst);
void divwux(UGeckoInstruction inst);
void srawix(UGeckoInstruction inst);
void srawx(UGeckoInstruction inst);
void addex(UGeckoInstruction inst);
void addzex(UGeckoInstruction inst);
void extsbx(UGeckoInstruction inst);
void extshx(UGeckoInstruction inst);
void sc(UGeckoInstruction _inst);
void rfi(UGeckoInstruction _inst);
void bx(UGeckoInstruction inst);
void bclrx(UGeckoInstruction _inst);
void bcctrx(UGeckoInstruction _inst);
void bcx(UGeckoInstruction inst);
void mtspr(UGeckoInstruction inst);
void mfspr(UGeckoInstruction inst);
void mtmsr(UGeckoInstruction inst);
void mfmsr(UGeckoInstruction inst);
void mftb(UGeckoInstruction inst);
void mtcrf(UGeckoInstruction inst);
void mfcr(UGeckoInstruction inst);
void mcrf(UGeckoInstruction inst);
void crXX(UGeckoInstruction inst);
void reg_imm(UGeckoInstruction inst);
void ps_sel(UGeckoInstruction inst);
void ps_mr(UGeckoInstruction inst);
void ps_sign(UGeckoInstruction inst); //aggregate
void ps_arith(UGeckoInstruction inst); //aggregate
void ps_mergeXX(UGeckoInstruction inst);
void ps_maddXX(UGeckoInstruction inst);
void ps_rsqrte(UGeckoInstruction inst);
void ps_sum(UGeckoInstruction inst);
void ps_muls(UGeckoInstruction inst);
void fp_arith_s(UGeckoInstruction inst);
void fcmpx(UGeckoInstruction inst);
void fmrx(UGeckoInstruction inst);
void cmpXX(UGeckoInstruction inst);
void cntlzwx(UGeckoInstruction inst);
void lfs(UGeckoInstruction inst);
void lfd(UGeckoInstruction inst);
void stfd(UGeckoInstruction inst);
void stfs(UGeckoInstruction inst);
void stfsx(UGeckoInstruction inst);
void psq_l(UGeckoInstruction inst);
void psq_st(UGeckoInstruction inst);
void fmaddXX(UGeckoInstruction inst);
void fsign(UGeckoInstruction inst);
void stX(UGeckoInstruction inst); //stw sth stb
void lXz(UGeckoInstruction inst);
void lbzu(UGeckoInstruction inst);
void lha(UGeckoInstruction inst);
void rlwinmx(UGeckoInstruction inst);
void rlwimix(UGeckoInstruction inst);
void rlwnmx(UGeckoInstruction inst);
void negx(UGeckoInstruction inst);
void slwx(UGeckoInstruction inst);
void srwx(UGeckoInstruction inst);
void dcbst(UGeckoInstruction inst);
void dcbz(UGeckoInstruction inst);
void lfsx(UGeckoInstruction inst);
void subfic(UGeckoInstruction inst);
void subfcx(UGeckoInstruction inst);
void subfx(UGeckoInstruction inst);
void subfex(UGeckoInstruction inst);
void lXzx(UGeckoInstruction inst);
void lhax(UGeckoInstruction inst);
void stXx(UGeckoInstruction inst);
void lmw(UGeckoInstruction inst);
void stmw(UGeckoInstruction inst);
void icbi(UGeckoInstruction inst);
};
void Jit(u32 em_address);
File diff suppressed because it is too large Load Diff
@@ -0,0 +1 @@
@@ -0,0 +1,365 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include <map>
#include "Common.h"
#include "../../HLE/HLE.h"
#include "../../Core.h"
#include "../../PatchEngine.h"
#include "../../CoreTiming.h"
#include "../../ConfigManager.h"
#include "../PowerPC.h"
#include "../Profiler.h"
#include "../PPCTables.h"
#include "../PPCAnalyst.h"
#include "../../HW/Memmap.h"
#include "../../HW/GPFifo.h"
#include "JitIL.h"
#include "JitIL_Tables.h"
#include "ArmEmitter.h"
#include "../JitInterface.h"
using namespace ArmGen;
using namespace PowerPC;
static int CODE_SIZE = 1024*1024*32;
namespace CPUCompare
{
extern u32 m_BlockStart;
}
void JitArmIL::Init()
{
AllocCodeSpace(CODE_SIZE);
blocks.Init();
asm_routines.Init();
}
void JitArmIL::ClearCache()
{
ClearCodeSpace();
blocks.Clear();
}
void JitArmIL::Shutdown()
{
FreeCodeSpace();
blocks.Shutdown();
asm_routines.Shutdown();
}
void JitArmIL::unknown_instruction(UGeckoInstruction inst)
{
// CCPU::Break();
PanicAlert("unknown_instruction %08x - Fix me ;)", inst.hex);
}
void JitArmIL::Default(UGeckoInstruction _inst)
{
ibuild.EmitInterpreterFallback(
ibuild.EmitIntConst(_inst.hex),
ibuild.EmitIntConst(js.compilerPC));
}
void JitArmIL::HLEFunction(UGeckoInstruction _inst)
{
// XXX
}
void JitArmIL::DoNothing(UGeckoInstruction _inst)
{
// Yup, just don't do anything.
}
void JitArmIL::Break(UGeckoInstruction _inst)
{
ibuild.EmitINT3();
}
void JitArmIL::DoDownCount()
{
ARMReg rA = R14;
ARMReg rB = R12;
MOVI2R(rA, (u32)&CoreTiming::downcount);
LDR(rB, rA);
if(js.downcountAmount < 255) // We can enlarge this if we used rotations
{
SUBS(rB, rB, js.downcountAmount);
STR(rB, rA);
}
else
{
ARMReg rC = R11;
MOVI2R(rC, js.downcountAmount);
SUBS(rB, rB, rC);
STR(rB, rA);
}
}
void JitArmIL::WriteExitDestInReg(ARMReg Reg)
{
STR(Reg, R9, PPCSTATE_OFF(pc));
DoDownCount();
MOVI2R(Reg, (u32)asm_routines.dispatcher);
B(Reg);
}
void JitArmIL::WriteRfiExitDestInR(ARMReg Reg)
{
STR(Reg, R9, PPCSTATE_OFF(pc));
DoDownCount();
MOVI2R(Reg, (u32)asm_routines.testExceptions);
B(Reg);
}
void JitArmIL::WriteExceptionExit()
{
DoDownCount();
MOVI2R(R14, (u32)asm_routines.testExceptions);
B(R14);
}
void JitArmIL::WriteExit(u32 destination, int exit_num)
{
DoDownCount();
//If nobody has taken care of this yet (this can be removed when all branches are done)
JitBlock *b = js.curBlock;
b->exitAddress[exit_num] = destination;
b->exitPtrs[exit_num] = GetWritableCodePtr();
// Link opportunity!
int block = blocks.GetBlockNumberFromStartAddress(destination);
if (block >= 0 && jo.enableBlocklink)
{
// It exists! Joy of joy!
B(blocks.GetBlock(block)->checkedEntry);
b->linkStatus[exit_num] = true;
}
else
{
MOVI2R(R14, destination);
STR(R14, R9, PPCSTATE_OFF(pc));
MOVI2R(R14, (u32)asm_routines.dispatcher);
B(R14);
}
}
void JitArmIL::PrintDebug(UGeckoInstruction inst, u32 level)
{
if (level > 0)
printf("Start: %08x OP '%s' Info\n", (u32)GetCodePtr(), PPCTables::GetInstructionName(inst));
if (level > 1)
{
GekkoOPInfo* Info = GetOpInfo(inst.hex);
printf("\tOuts\n");
if (Info->flags & FL_OUT_A)
printf("\t-OUT_A: %x\n", inst.RA);
if(Info->flags & FL_OUT_D)
printf("\t-OUT_D: %x\n", inst.RD);
printf("\tIns\n");
// A, AO, B, C, S
if(Info->flags & FL_IN_A)
printf("\t-IN_A: %x\n", inst.RA);
if(Info->flags & FL_IN_A0)
printf("\t-IN_A0: %x\n", inst.RA);
if(Info->flags & FL_IN_B)
printf("\t-IN_B: %x\n", inst.RB);
if(Info->flags & FL_IN_C)
printf("\t-IN_C: %x\n", inst.RC);
if(Info->flags & FL_IN_S)
printf("\t-IN_S: %x\n", inst.RS);
}
}
void STACKALIGN JitArmIL::Run()
{
CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode;
pExecAddr();
}
void JitArmIL::SingleStep()
{
CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode;
pExecAddr();
}
void STACKALIGN JitArmIL::Jit(u32 em_address)
{
if (GetSpaceLeft() < 0x10000 || blocks.IsFull() || Core::g_CoreStartupParameter.bJITNoBlockCache)
{
ClearCache();
}
int block_num = blocks.AllocateBlock(PowerPC::ppcState.pc);
JitBlock *b = blocks.GetBlock(block_num);
const u8* BlockPtr = DoJit(PowerPC::ppcState.pc, &code_buffer, b);
blocks.FinalizeBlock(block_num, jo.enableBlocklink, BlockPtr);
}
const u8* JitArmIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b)
{
int blockSize = code_buf->GetSize();
// Memory exception on instruction fetch
bool memory_exception = false;
// A broken block is a block that does not end in a branch
bool broken_block = false;
if (Core::g_CoreStartupParameter.bEnableDebugging)
{
// Comment out the following to disable breakpoints (speed-up)
blockSize = 1;
broken_block = true;
}
if (em_address == 0)
{
Core::SetState(Core::CORE_PAUSE);
PanicAlert("ERROR: Compiling at 0. LR=%08x CTR=%08x", LR, CTR);
}
if (Core::g_CoreStartupParameter.bMMU && (em_address & JIT_ICACHE_VMEM_BIT))
{
if (!Memory::TranslateAddress(em_address, Memory::FLAG_OPCODE))
{
// Memory exception occurred during instruction fetch
memory_exception = true;
}
}
int size = 0;
js.isLastInstruction = false;
js.blockStart = em_address;
js.fifoBytesThisBlock = 0;
js.curBlock = b;
js.block_flags = 0;
js.cancel = false;
// Analyze the block, collect all instructions it is made of (including inlining,
// if that is enabled), reorder instructions for optimal performance, and join joinable instructions.
u32 nextPC = em_address;
u32 merged_addresses[32];
const int capacity_of_merged_addresses = sizeof(merged_addresses) / sizeof(merged_addresses[0]);
int size_of_merged_addresses = 0;
if (!memory_exception)
{
// If there is a memory exception inside a block (broken_block==true), compile up to that instruction.
nextPC = PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, broken_block, code_buf, blockSize, merged_addresses, capacity_of_merged_addresses, size_of_merged_addresses);
}
PPCAnalyst::CodeOp *ops = code_buf->codebuffer;
const u8 *start = GetCodePtr();
b->checkedEntry = start;
b->runCount = 0;
// Downcount flag check, Only valid for linked blocks
{
// XXX
}
const u8 *normalEntry = GetCodePtr();
b->normalEntry = normalEntry;
if (js.fpa.any)
{
// XXX
// This block uses FPU - needs to add FP exception bailout
}
js.rewriteStart = (u8*)GetCodePtr();
u64 codeHash = -1;
{
// For profiling and IR Writer
for (int i = 0; i < (int)size; i++)
{
const u64 inst = ops[i].inst.hex;
// Ported from boost::hash
codeHash ^= inst + (codeHash << 6) + (codeHash >> 2);
}
}
// Conditionally add profiling code.
if (Profiler::g_ProfileBlocks) {
// XXX
}
// Start up IR builder (structure that collects the
// instruction processed by the JIT routines)
ibuild.Reset();
js.downcountAmount = 0;
if (!Core::g_CoreStartupParameter.bEnableDebugging)
{
for (int i = 0; i < size_of_merged_addresses; ++i)
{
const u32 address = merged_addresses[i];
js.downcountAmount += PatchEngine::GetSpeedhackCycles(address);
}
}
js.skipnext = false;
js.blockSize = size;
js.compilerPC = nextPC;
// Translate instructions
for (int i = 0; i < (int)size; i++)
{
js.compilerPC = ops[i].address;
js.op = &ops[i];
js.instructionNumber = i;
const GekkoOPInfo *opinfo = ops[i].opinfo;
js.downcountAmount += (opinfo->numCyclesMinusOne + 1);
if (i == (int)size - 1)
{
// WARNING - cmp->branch merging will screw this up.
js.isLastInstruction = true;
js.next_inst = 0;
if (Profiler::g_ProfileBlocks) {
// CAUTION!!! push on stack regs you use, do your stuff, then pop
PROFILER_VPUSH;
// get end tic
PROFILER_QUERY_PERFORMANCE_COUNTER(&b->ticStop);
// tic counter += (end tic - start tic)
PROFILER_ADD_DIFF_LARGE_INTEGER(&b->ticCounter, &b->ticStop, &b->ticStart);
PROFILER_VPOP;
}
}
else
{
// help peephole optimizations
js.next_inst = ops[i + 1].inst;
js.next_compilerPC = ops[i + 1].address;
}
if (!ops[i].skip)
{
PrintDebug(ops[i].inst, 0);
if (js.memcheck && (opinfo->flags & FL_USE_FPU))
{
// Don't do this yet
BKPT(0x7777);
}
JitArmILTables::CompileInstruction(ops[i]);
if (js.memcheck && (opinfo->flags & FL_LOADSTORE))
{
// Don't do this yet
BKPT(0x666);
}
}
}
if (memory_exception)
BKPT(0x500);
if (broken_block)
{
printf("Broken Block going to 0x%08x\n", nextPC);
WriteExit(nextPC, 0);
}
// Perform actual code generation
WriteCode();
b->flags = js.block_flags;
b->codeSize = (u32)(GetCodePtr() - normalEntry);
b->originalSize = size;
{
}
FlushIcache();
return start;
}
@@ -0,0 +1,99 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#ifndef _JITARMIL_H
#define _JITARMIL_H
#include "../PPCAnalyst.h"
#include "ArmEmitter.h"
#include "../JitArm32/JitArmCache.h"
#include "../JitILCommon/JitILBase.h"
#include "../JitILCommon/IR.h"
#include "../JitCommon/JitBase.h"
#include "JitILAsm.h"
#define JITDISABLE(setting) \
if (Core::g_CoreStartupParameter.bJITOff || \
Core::g_CoreStartupParameter.setting) \
{Default(inst); return;}
#define PPCSTATE_OFF(elem) ((s32)STRUCT_OFF(PowerPC::ppcState, elem) - (s32)STRUCT_OFF(PowerPC::ppcState, spr[0]))
class JitArmIL : public JitILBase, public ArmGen::ARMXCodeBlock
{
private:
JitArmBlockCache blocks;
JitArmILAsmRoutineManager asm_routines;
void PrintDebug(UGeckoInstruction inst, u32 level);
void DoDownCount();
public:
// Initialization, etc
JitArmIL() {}
~JitArmIL() {}
void Init();
void Shutdown();
// Jit!
void Jit(u32 em_address);
const u8* DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buffer, JitBlock *b);
JitBaseBlockCache *GetBlockCache() { return &blocks; }
const u8 *BackPatch(u8 *codePtr, u32 em_address, void *ctx) { return NULL; }
bool IsInCodeSpace(u8 *ptr) { return IsInSpace(ptr); }
void ClearCache();
const u8 *GetDispatcher() {
return asm_routines.dispatcher; // asm_routines.dispatcher
}
const CommonAsmRoutinesBase *GetAsmRoutines() {
return &asm_routines;
}
const char *GetName() {
return "JITARMIL";
}
// Run!
void Run();
void SingleStep();
//
void WriteCode();
void WriteExit(u32 destination, int exit_num);
void WriteExitDestInReg(ARMReg Reg);
void WriteRfiExitDestInR(ARMReg Reg);
void WriteExceptionExit();
// OPCODES
void unknown_instruction(UGeckoInstruction inst);
void Default(UGeckoInstruction inst);
void DoNothing(UGeckoInstruction inst);
void HLEFunction(UGeckoInstruction inst);
void Break(UGeckoInstruction inst);
void DynaRunTable4(UGeckoInstruction inst);
void DynaRunTable19(UGeckoInstruction inst);
void DynaRunTable31(UGeckoInstruction inst);
void DynaRunTable59(UGeckoInstruction inst);
void DynaRunTable63(UGeckoInstruction inst);
// Binary ops
void BIN_AND(ARMReg reg, Operand2 op2);
void BIN_XOR(ARMReg reg, Operand2 op2);
void BIN_OR(ARMReg reg, Operand2 op2);
void BIN_ADD(ARMReg reg, Operand2 op2);
// Branches
void bx(UGeckoInstruction inst);
void bcx(UGeckoInstruction inst);
void bclrx(UGeckoInstruction inst);
void bcctrx(UGeckoInstruction inst);
};
#endif
@@ -0,0 +1,121 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include "../../HW/Memmap.h"
#include "../PowerPC.h"
#include "../../CoreTiming.h"
#include "MemoryUtil.h"
#include "JitIL.h"
#include "../JitCommon/JitCache.h"
#include "../../HW/GPFifo.h"
#include "../../Core.h"
#include "JitILAsm.h"
#include "ArmEmitter.h"
JitArmILAsmRoutineManager armil_asm_routines;
void JitArmILAsmRoutineManager::Generate()
{
enterCode = GetCodePtr();
PUSH(9, R4, R5, R6, R7, R8, R9, R10, R11, _LR);
// Take care to 8-byte align stack for function calls.
// We are misaligned here because of an odd number of args for PUSH.
// It's not like x86 where you need to account for an extra 4 bytes
// consumed by CALL.
SUB(_SP, _SP, 4);
MOVI2R(R0, (u32)&CoreTiming::downcount);
MOVI2R(R9, (u32)&PowerPC::ppcState.spr[0]);
FixupBranch skipToRealDispatcher = B();
dispatcher = GetCodePtr();
printf("ILDispatcher is %p\n", dispatcher);
// Downcount Check
// The result of slice decrementation should be in flags if somebody jumped here
// IMPORTANT - We jump on negative, not carry!!!
FixupBranch bail = B_CC(CC_MI);
SetJumpTarget(skipToRealDispatcher);
dispatcherNoCheck = GetCodePtr();
// This block of code gets the address of the compiled block of code
// It runs though to the compiling portion if it isn't found
LDR(R12, R9, PPCSTATE_OFF(pc));// Load the current PC into R12
Operand2 iCacheMask = Operand2(0xE, 2); // JIT_ICACHE_MASK
BIC(R12, R12, iCacheMask); // R12 contains PC & JIT_ICACHE_MASK here.
MOVI2R(R14, (u32)jit->GetBlockCache()->GetICache());
LDR(R12, R14, R12); // R12 contains iCache[PC & JIT_ICACHE_MASK] here
// R12 Confirmed this is the correct iCache Location loaded.
TST(R12, 0xFC); // Test to see if it is a JIT block.
SetCC(CC_EQ);
// Success, it is our Jitblock.
MOVI2R(R14, (u32)jit->GetBlockCache()->GetCodePointers());
// LDR R14 right here to get CodePointers()[0] pointer.
REV(R12, R12); // Reversing this gives us our JITblock.
LSL(R12, R12, 2); // Multiply by four because address locations are u32 in size
LDR(R14, R14, R12); // Load the block address in to R14
B(R14);
// No need to jump anywhere after here, the block will go back to dispatcher start
SetCC();
// If we get to this point, that means that we don't have the block cached to execute
// So call ArmJit to compile the block and then execute it.
MOVI2R(R14, (u32)&Jit);
BL(R14);
B(dispatcherNoCheck);
// fpException()
// Floating Point Exception Check, Jumped to if false
fpException = GetCodePtr();
LDR(R0, R9, PPCSTATE_OFF(Exceptions));
ORR(R0, R0, EXCEPTION_FPU_UNAVAILABLE);
STR(R0, R9, PPCSTATE_OFF(Exceptions));
QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions);
LDR(R0, R9, PPCSTATE_OFF(npc));
STR(R0, R9, PPCSTATE_OFF(pc));
B(dispatcher);
SetJumpTarget(bail);
doTiming = GetCodePtr();
// XXX: In JIT64, Advance() gets called /after/ the exception checking
// once it jumps back to the start of outerLoop
QuickCallFunction(R14, (void*)&CoreTiming::Advance);
// Does exception checking
testExceptions = GetCodePtr();
LDR(R0, R9, PPCSTATE_OFF(pc));
STR(R0, R9, PPCSTATE_OFF(npc));
QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions);
LDR(R0, R9, PPCSTATE_OFF(npc));
STR(R0, R9, PPCSTATE_OFF(pc));
// Check the state pointer to see if we are exiting
// Gets checked on every exception check
MOVI2R(R0, (u32)PowerPC::GetStatePtr());
MVN(R1, 0);
LDR(R0, R0);
TST(R0, R1);
FixupBranch Exit = B_CC(CC_NEQ);
B(dispatcher);
SetJumpTarget(Exit);
ADD(_SP, _SP, 4);
POP(9, R4, R5, R6, R7, R8, R9, R10, R11, _PC); // Returns
GenerateCommon();
FlushIcache();
}
@@ -0,0 +1,32 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#ifndef _JITARMILASM_H
#define _JITARMILASM_H
#include "ArmEmitter.h"
#include "../JitCommon/JitAsmCommon.h"
using namespace ArmGen;
class JitArmILAsmRoutineManager : public CommonAsmRoutinesBase, public ARMXCodeBlock
{
private:
void Generate();
void GenerateCommon() {}
public:
void Init() {
AllocCodeSpace(8192);
Generate();
WriteProtect();
}
void Shutdown() {
FreeCodeSpace();
}
};
extern JitArmILAsmRoutineManager armil_asm_routines;
#endif
@@ -6,44 +6,18 @@
#include "../../ConfigManager.h"
#include "../PowerPC.h"
#include "../../CoreTiming.h"
#include "../PPCTables.h"
#include "x64Emitter.h"
#include "JitIL.h"
#include "JitILAsm.h"
#include "../../HW/Memmap.h"
// The branches are known good, or at least reasonably good.
// No need for a disable-mechanism.
#define NORMALBRANCH_START Default(inst); ibuild.EmitInterpreterBranch(); return;
//#define NORMALBRANCH_START
// If defined, clears CR0 at blr and bl-s. If the assumption that
// flags never carry over between functions holds, then the task for
// an optimizer becomes much easier.
// #define ACID_TEST
// Zelda and many more games seem to pass the Acid Test.
//#define NORMALBRANCH_START Default(inst); ibuild.EmitInterpreterBranch(); return;
#define NORMALBRANCH_START
using namespace Gen;
void JitIL::sc(UGeckoInstruction inst)
void JitArmIL::bx(UGeckoInstruction inst)
{
ibuild.EmitSystemCall(ibuild.EmitIntConst(js.compilerPC));
}
void JitIL::rfi(UGeckoInstruction inst)
{
ibuild.EmitRFIExit();
}
void JitIL::bx(UGeckoInstruction inst)
{
NORMALBRANCH_START
//NORMALBRANCH_START
INSTRUCTION_START;
// We must always process the following sentence
@@ -71,7 +45,6 @@ void JitIL::bx(UGeckoInstruction inst)
ibuild.EmitBranchUncond(ibuild.EmitIntConst(destination));
}
static IREmitter::InstLoc TestBranch(IREmitter::IRBuilder& ibuild, UGeckoInstruction inst) {
IREmitter::InstLoc CRTest = 0, CTRTest = 0;
if ((inst.BO & 16) == 0) // Test a CR bit
@@ -109,7 +82,32 @@ static IREmitter::InstLoc TestBranch(IREmitter::IRBuilder& ibuild, UGeckoInstruc
return Test;
}
void JitIL::bcx(UGeckoInstruction inst)
void JitArmIL::bclrx(UGeckoInstruction inst)
{
NORMALBRANCH_START
if (!js.isLastInstruction &&
(inst.BO & (1 << 4)) && (inst.BO & (1 << 2))) {
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
return;
}
if (inst.hex == 0x4e800020) {
ibuild.EmitBranchUncond(ibuild.EmitLoadLink());
return;
}
IREmitter::InstLoc test = TestBranch(ibuild, inst);
test = ibuild.EmitICmpEq(test, ibuild.EmitIntConst(0));
ibuild.EmitBranchCond(test, ibuild.EmitIntConst(js.compilerPC + 4));
IREmitter::InstLoc destination = ibuild.EmitLoadLink();
destination = ibuild.EmitAnd(destination, ibuild.EmitIntConst(-4));
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
ibuild.EmitBranchUncond(destination);
}
void JitArmIL::bcx(UGeckoInstruction inst)
{
NORMALBRANCH_START
if (inst.LK)
@@ -140,7 +138,7 @@ void JitIL::bcx(UGeckoInstruction inst)
ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4));
}
void JitIL::bcctrx(UGeckoInstruction inst)
void JitArmIL::bcctrx(UGeckoInstruction inst)
{
NORMALBRANCH_START
if ((inst.BO & 4) == 0) {
@@ -169,28 +167,3 @@ void JitIL::bcctrx(UGeckoInstruction inst)
ibuild.EmitBranchUncond(destination);
}
void JitIL::bclrx(UGeckoInstruction inst)
{
NORMALBRANCH_START
if (!js.isLastInstruction &&
(inst.BO & (1 << 4)) && (inst.BO & (1 << 2))) {
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
return;
}
if (inst.hex == 0x4e800020) {
ibuild.EmitBranchUncond(ibuild.EmitLoadLink());
return;
}
IREmitter::InstLoc test = TestBranch(ibuild, inst);
test = ibuild.EmitICmpEq(test, ibuild.EmitIntConst(0));
ibuild.EmitBranchCond(test, ibuild.EmitIntConst(js.compilerPC + 4));
IREmitter::InstLoc destination = ibuild.EmitLoadLink();
destination = ibuild.EmitAnd(destination, ibuild.EmitIntConst(-4));
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
ibuild.EmitBranchUncond(destination);
}
@@ -0,0 +1,489 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include "JitIL.h"
#include "../JitInterface.h"
#include "JitIL_Tables.h"
// Should be moved in to the Jit class
typedef void (JitArmIL::*_Instruction) (UGeckoInstruction instCode);
static _Instruction dynaOpTable[64];
static _Instruction dynaOpTable4[1024];
static _Instruction dynaOpTable19[1024];
static _Instruction dynaOpTable31[1024];
static _Instruction dynaOpTable59[32];
static _Instruction dynaOpTable63[1024];
void JitArmIL::DynaRunTable4(UGeckoInstruction _inst) {(this->*dynaOpTable4 [_inst.SUBOP10])(_inst);}
void JitArmIL::DynaRunTable19(UGeckoInstruction _inst) {(this->*dynaOpTable19[_inst.SUBOP10])(_inst);}
void JitArmIL::DynaRunTable31(UGeckoInstruction _inst) {(this->*dynaOpTable31[_inst.SUBOP10])(_inst);}
void JitArmIL::DynaRunTable59(UGeckoInstruction _inst) {(this->*dynaOpTable59[_inst.SUBOP5 ])(_inst);}
void JitArmIL::DynaRunTable63(UGeckoInstruction _inst) {(this->*dynaOpTable63[_inst.SUBOP10])(_inst);}
struct GekkoOPTemplate
{
int opcode;
_Instruction Inst;
//GekkoOPInfo opinfo; // Doesn't need opinfo, Interpreter fills it out
};
static GekkoOPTemplate primarytable[] =
{
{4, &JitArmIL::DynaRunTable4}, //"RunTable4", OPTYPE_SUBTABLE | (4<<24), 0}},
{19, &JitArmIL::DynaRunTable19}, //"RunTable19", OPTYPE_SUBTABLE | (19<<24), 0}},
{31, &JitArmIL::DynaRunTable31}, //"RunTable31", OPTYPE_SUBTABLE | (31<<24), 0}},
{59, &JitArmIL::DynaRunTable59}, //"RunTable59", OPTYPE_SUBTABLE | (59<<24), 0}},
{63, &JitArmIL::DynaRunTable63}, //"RunTable63", OPTYPE_SUBTABLE | (63<<24), 0}},
{16, &JitArmIL::bcx}, //"bcx", OPTYPE_SYSTEM, FL_ENDBLOCK}},
{18, &JitArmIL::bx}, //"bx", OPTYPE_SYSTEM, FL_ENDBLOCK}},
{1, &JitArmIL::HLEFunction}, //"HLEFunction", OPTYPE_SYSTEM, FL_ENDBLOCK}},
{2, &JitArmIL::Default}, //"DynaBlock", OPTYPE_SYSTEM, 0}},
{3, &JitArmIL::Break}, //"twi", OPTYPE_SYSTEM, FL_ENDBLOCK}},
{17, &JitArmIL::sc}, //"sc", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}},
{7, &JitArmIL::Default}, //"mulli", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_RC_BIT, 2}},
{8, &JitArmIL::Default}, //"subfic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}},
{10, &JitArmIL::cmpXX}, //"cmpli", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}},
{11, &JitArmIL::cmpXX}, //"cmpi", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}},
{12, &JitArmIL::Default}, //"addic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}},
{13, &JitArmIL::Default}, //"addic_rc", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CR0}},
{14, &JitArmIL::reg_imm}, //"addi", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}},
{15, &JitArmIL::reg_imm}, //"addis", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}},
{20, &JitArmIL::Default}, //"rlwimix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_A | FL_IN_S | FL_RC_BIT}},
{21, &JitArmIL::Default}, //"rlwinmx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{23, &JitArmIL::Default}, //"rlwnmx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_IN_B | FL_RC_BIT}},
{24, &JitArmIL::reg_imm}, //"ori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{25, &JitArmIL::reg_imm}, //"oris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{26, &JitArmIL::reg_imm}, //"xori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{27, &JitArmIL::reg_imm}, //"xoris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{28, &JitArmIL::reg_imm}, //"andi_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
{29, &JitArmIL::reg_imm}, //"andis_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
{32, &JitArmIL::Default}, //"lwz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{33, &JitArmIL::Default}, //"lwzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
{34, &JitArmIL::Default}, //"lbz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{35, &JitArmIL::Default}, //"lbzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
{40, &JitArmIL::Default}, //"lhz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{41, &JitArmIL::Default}, //"lhzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
{42, &JitArmIL::Default}, //"lha", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{43, &JitArmIL::Default}, //"lhau", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
{44, &JitArmIL::Default}, //"sth", OPTYPE_STORE, FL_IN_A | FL_IN_S}},
{45, &JitArmIL::Default}, //"sthu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}},
{36, &JitArmIL::Default}, //"stw", OPTYPE_STORE, FL_IN_A | FL_IN_S}},
{37, &JitArmIL::Default}, //"stwu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}},
{38, &JitArmIL::Default}, //"stb", OPTYPE_STORE, FL_IN_A | FL_IN_S}},
{39, &JitArmIL::Default}, //"stbu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}},
{46, &JitArmIL::Default}, //"lmw", OPTYPE_SYSTEM, FL_EVIL, 10}},
{47, &JitArmIL::Default}, //"stmw", OPTYPE_SYSTEM, FL_EVIL, 10}},
{48, &JitArmIL::Default}, //"lfs", OPTYPE_LOADFP, FL_IN_A}},
{49, &JitArmIL::Default}, //"lfsu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A}},
{50, &JitArmIL::Default}, //"lfd", OPTYPE_LOADFP, FL_IN_A}},
{51, &JitArmIL::Default}, //"lfdu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A}},
{52, &JitArmIL::Default}, //"stfs", OPTYPE_STOREFP, FL_IN_A}},
{53, &JitArmIL::Default}, //"stfsu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}},
{54, &JitArmIL::Default}, //"stfd", OPTYPE_STOREFP, FL_IN_A}},
{55, &JitArmIL::Default}, //"stfdu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}},
{56, &JitArmIL::Default}, //"psq_l", OPTYPE_PS, FL_IN_A}},
{57, &JitArmIL::Default}, //"psq_lu", OPTYPE_PS, FL_OUT_A | FL_IN_A}},
{60, &JitArmIL::Default}, //"psq_st", OPTYPE_PS, FL_IN_A}},
{61, &JitArmIL::Default}, //"psq_stu", OPTYPE_PS, FL_OUT_A | FL_IN_A}},
//missing: 0, 5, 6, 9, 22, 30, 62, 58
{0, &JitArmIL::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
{5, &JitArmIL::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
{6, &JitArmIL::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
{9, &JitArmIL::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
{22, &JitArmIL::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
{30, &JitArmIL::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
{62, &JitArmIL::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
{58, &JitArmIL::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
};
static GekkoOPTemplate table4[] =
{ //SUBOP10
{0, &JitArmIL::Default}, //"ps_cmpu0", OPTYPE_PS, FL_SET_CRn}},
{32, &JitArmIL::Default}, //"ps_cmpo0", OPTYPE_PS, FL_SET_CRn}},
{40, &JitArmIL::Default}, //"ps_neg", OPTYPE_PS, FL_RC_BIT}},
{136, &JitArmIL::Default}, //"ps_nabs", OPTYPE_PS, FL_RC_BIT}},
{264, &JitArmIL::Default}, //"ps_abs", OPTYPE_PS, FL_RC_BIT}},
{64, &JitArmIL::Default}, //"ps_cmpu1", OPTYPE_PS, FL_RC_BIT}},
{72, &JitArmIL::Default}, //"ps_mr", OPTYPE_PS, FL_RC_BIT}},
{96, &JitArmIL::Default}, //"ps_cmpo1", OPTYPE_PS, FL_RC_BIT}},
{528, &JitArmIL::Default}, //"ps_merge00", OPTYPE_PS, FL_RC_BIT}},
{560, &JitArmIL::Default}, //"ps_merge01", OPTYPE_PS, FL_RC_BIT}},
{592, &JitArmIL::Default}, //"ps_merge10", OPTYPE_PS, FL_RC_BIT}},
{624, &JitArmIL::Default}, //"ps_merge11", OPTYPE_PS, FL_RC_BIT}},
{1014, &JitArmIL::Default}, //"dcbz_l", OPTYPE_SYSTEM, 0}},
};
static GekkoOPTemplate table4_2[] =
{
{10, &JitArmIL::Default}, //"ps_sum0", OPTYPE_PS, 0}},
{11, &JitArmIL::Default}, //"ps_sum1", OPTYPE_PS, 0}},
{12, &JitArmIL::Default}, //"ps_muls0", OPTYPE_PS, 0}},
{13, &JitArmIL::Default}, //"ps_muls1", OPTYPE_PS, 0}},
{14, &JitArmIL::Default}, //"ps_madds0", OPTYPE_PS, 0}},
{15, &JitArmIL::Default}, //"ps_madds1", OPTYPE_PS, 0}},
{18, &JitArmIL::Default}, //"ps_div", OPTYPE_PS, 0, 16}},
{20, &JitArmIL::Default}, //"ps_sub", OPTYPE_PS, 0}},
{21, &JitArmIL::Default}, //"ps_add", OPTYPE_PS, 0}},
{23, &JitArmIL::Default}, //"ps_sel", OPTYPE_PS, 0}},
{24, &JitArmIL::Default}, //"ps_res", OPTYPE_PS, 0}},
{25, &JitArmIL::Default}, //"ps_mul", OPTYPE_PS, 0}},
{26, &JitArmIL::Default}, //"ps_rsqrte", OPTYPE_PS, 0, 1}},
{28, &JitArmIL::Default}, //"ps_msub", OPTYPE_PS, 0}},
{29, &JitArmIL::Default}, //"ps_madd", OPTYPE_PS, 0}},
{30, &JitArmIL::Default}, //"ps_nmsub", OPTYPE_PS, 0}},
{31, &JitArmIL::Default}, //"ps_nmadd", OPTYPE_PS, 0}},
};
static GekkoOPTemplate table4_3[] =
{
{6, &JitArmIL::Default}, //"psq_lx", OPTYPE_PS, 0}},
{7, &JitArmIL::Default}, //"psq_stx", OPTYPE_PS, 0}},
{38, &JitArmIL::Default}, //"psq_lux", OPTYPE_PS, 0}},
{39, &JitArmIL::Default}, //"psq_stux", OPTYPE_PS, 0}},
};
static GekkoOPTemplate table19[] =
{
{528, &JitArmIL::bcctrx}, //"bcctrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
{16, &JitArmIL::bclrx}, //"bclrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
{257, &JitArmIL::crXX}, //"crand", OPTYPE_CR, FL_EVIL}},
{129, &JitArmIL::crXX}, //"crandc", OPTYPE_CR, FL_EVIL}},
{289, &JitArmIL::crXX}, //"creqv", OPTYPE_CR, FL_EVIL}},
{225, &JitArmIL::crXX}, //"crnand", OPTYPE_CR, FL_EVIL}},
{33, &JitArmIL::crXX}, //"crnor", OPTYPE_CR, FL_EVIL}},
{449, &JitArmIL::crXX}, //"cror", OPTYPE_CR, FL_EVIL}},
{417, &JitArmIL::crXX}, //"crorc", OPTYPE_CR, FL_EVIL}},
{193, &JitArmIL::crXX}, //"crxor", OPTYPE_CR, FL_EVIL}},
{150, &JitArmIL::Default}, //"isync", OPTYPE_ICACHE, FL_EVIL}},
{0, &JitArmIL::Default}, //"mcrf", OPTYPE_SYSTEM, FL_EVIL}},
{50, &JitArmIL::rfi}, //"rfi", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS, 1}},
{18, &JitArmIL::Break}, //"rfid", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS}}
};
static GekkoOPTemplate table31[] =
{
{28, &JitArmIL::boolX}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{60, &JitArmIL::boolX}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{444, &JitArmIL::boolX}, //"orx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{124, &JitArmIL::boolX}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{316, &JitArmIL::boolX}, //"xorx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{412, &JitArmIL::boolX}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{476, &JitArmIL::boolX}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{284, &JitArmIL::boolX}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{0, &JitArmIL::cmpXX}, //"cmp", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
{32, &JitArmIL::cmpXX}, //"cmpl", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
{26, &JitArmIL::Default}, //"cntlzwx",OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{922, &JitArmIL::Default}, //"extshx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{954, &JitArmIL::Default}, //"extsbx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{536, &JitArmIL::Default}, //"srwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{792, &JitArmIL::Default}, //"srawx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{824, &JitArmIL::Default}, //"srawix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{24, &JitArmIL::Default}, //"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{54, &JitArmIL::Default}, //"dcbst", OPTYPE_DCACHE, 0, 4}},
{86, &JitArmIL::Default}, //"dcbf", OPTYPE_DCACHE, 0, 4}},
{246, &JitArmIL::Default}, //"dcbtst", OPTYPE_DCACHE, 0, 1}},
{278, &JitArmIL::Default}, //"dcbt", OPTYPE_DCACHE, 0, 1}},
{470, &JitArmIL::Default}, //"dcbi", OPTYPE_DCACHE, 0, 4}},
{758, &JitArmIL::Default}, //"dcba", OPTYPE_DCACHE, 0, 4}},
{1014, &JitArmIL::Default}, //"dcbz", OPTYPE_DCACHE, 0, 4}},
//load word
{23, &JitArmIL::Default}, //"lwzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{55, &JitArmIL::Default}, //"lwzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
//load halfword
{279, &JitArmIL::Default}, //"lhzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{311, &JitArmIL::Default}, //"lhzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
//load halfword signextend
{343, &JitArmIL::Default}, //"lhax", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{375, &JitArmIL::Default}, //"lhaux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
//load byte
{87, &JitArmIL::Default}, //"lbzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{119, &JitArmIL::Default}, //"lbzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
//load byte reverse
{534, &JitArmIL::Default}, //"lwbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{790, &JitArmIL::Default}, //"lhbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
// Conditional load/store (Wii SMP)
{150, &JitArmIL::Default}, //"stwcxd", OPTYPE_STORE, FL_EVIL | FL_SET_CR0}},
{20, &JitArmIL::Default}, //"lwarx", OPTYPE_LOAD, FL_EVIL | FL_OUT_D | FL_IN_A0B | FL_SET_CR0}},
//load string (interpret these)
{533, &JitArmIL::Default}, //"lswx", OPTYPE_LOAD, FL_EVIL | FL_IN_A | FL_OUT_D}},
{597, &JitArmIL::Default}, //"lswi", OPTYPE_LOAD, FL_EVIL | FL_IN_AB | FL_OUT_D}},
//store word
{151, &JitArmIL::Default}, //"stwx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
{183, &JitArmIL::Default}, //"stwux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}},
//store halfword
{407, &JitArmIL::Default}, //"sthx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
{439, &JitArmIL::Default}, //"sthux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}},
//store byte
{215, &JitArmIL::Default}, //"stbx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
{247, &JitArmIL::Default}, //"stbux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}},
//store bytereverse
{662, &JitArmIL::Default}, //"stwbrx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
{918, &JitArmIL::Default}, //"sthbrx", OPTYPE_STORE, FL_IN_A | FL_IN_B}},
{661, &JitArmIL::Default}, //"stswx", OPTYPE_STORE, FL_EVIL}},
{725, &JitArmIL::Default}, //"stswi", OPTYPE_STORE, FL_EVIL}},
// fp load/store
{535, &JitArmIL::Default}, //"lfsx", OPTYPE_LOADFP, FL_IN_A0 | FL_IN_B}},
{567, &JitArmIL::Default}, //"lfsux", OPTYPE_LOADFP, FL_IN_A | FL_IN_B}},
{599, &JitArmIL::Default}, //"lfdx", OPTYPE_LOADFP, FL_IN_A0 | FL_IN_B}},
{631, &JitArmIL::Default}, //"lfdux", OPTYPE_LOADFP, FL_IN_A | FL_IN_B}},
{663, &JitArmIL::Default}, //"stfsx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}},
{695, &JitArmIL::Default}, //"stfsux", OPTYPE_STOREFP, FL_IN_A | FL_IN_B}},
{727, &JitArmIL::Default}, //"stfdx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}},
{759, &JitArmIL::Default}, //"stfdux", OPTYPE_STOREFP, FL_IN_A | FL_IN_B}},
{983, &JitArmIL::Default}, //"stfiwx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}},
{19, &JitArmIL::Default}, //"mfcr", OPTYPE_SYSTEM, FL_OUT_D}},
{83, &JitArmIL::Default}, //"mfmsr", OPTYPE_SYSTEM, FL_OUT_D}},
{144, &JitArmIL::Default}, //"mtcrf", OPTYPE_SYSTEM, 0}},
{146, &JitArmIL::mtmsr}, //"mtmsr", OPTYPE_SYSTEM, FL_ENDBLOCK}},
{210, &JitArmIL::Default}, //"mtsr", OPTYPE_SYSTEM, 0}},
{242, &JitArmIL::Default}, //"mtsrin", OPTYPE_SYSTEM, 0}},
{339, &JitArmIL::Default}, //"mfspr", OPTYPE_SPR, FL_OUT_D}},
{467, &JitArmIL::Default}, //"mtspr", OPTYPE_SPR, 0, 2}},
{371, &JitArmIL::Default}, //"mftb", OPTYPE_SYSTEM, FL_OUT_D | FL_TIMER}},
{512, &JitArmIL::Default}, //"mcrxr", OPTYPE_SYSTEM, 0}},
{595, &JitArmIL::Default}, //"mfsr", OPTYPE_SYSTEM, FL_OUT_D, 2}},
{659, &JitArmIL::Default}, //"mfsrin", OPTYPE_SYSTEM, FL_OUT_D, 2}},
{4, &JitArmIL::Break}, //"tw", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}},
{598, &JitArmIL::Default}, //"sync", OPTYPE_SYSTEM, 0, 2}},
{982, &JitArmIL::icbi}, //"icbi", OPTYPE_SYSTEM, FL_ENDBLOCK, 3}},
// Unused instructions on GC
{310, &JitArmIL::Default}, //"eciwx", OPTYPE_INTEGER, FL_RC_BIT}},
{438, &JitArmIL::Default}, //"ecowx", OPTYPE_INTEGER, FL_RC_BIT}},
{854, &JitArmIL::Default}, //"eieio", OPTYPE_INTEGER, FL_RC_BIT}},
{306, &JitArmIL::Default}, //"tlbie", OPTYPE_SYSTEM, 0}},
{370, &JitArmIL::Default}, //"tlbia", OPTYPE_SYSTEM, 0}},
{566, &JitArmIL::Default}, //"tlbsync", OPTYPE_SYSTEM, 0}},
};
static GekkoOPTemplate table31_2[] =
{
{266, &JitArmIL::Default}, //"addx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{778, &JitArmIL::Default}, //"addx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{10, &JitArmIL::Default}, //"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
{138, &JitArmIL::Default}, //"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{234, &JitArmIL::Default}, //"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{202, &JitArmIL::Default}, //"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{491, &JitArmIL::Default}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
{1003, &JitArmIL::Default}, //"divwox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
{459, &JitArmIL::Default}, //"divwux", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
{971, &JitArmIL::Default}, //"divwuox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
{75, &JitArmIL::Default}, //"mulhwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
{11, &JitArmIL::Default}, //"mulhwux", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
{235, &JitArmIL::Default}, //"mullwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
{747, &JitArmIL::Default}, //"mullwox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
{104, &JitArmIL::Default}, //"negx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{40, &JitArmIL::Default}, //"subfx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{552, &JitArmIL::Default}, //"subox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{8, &JitArmIL::Default}, //"subfcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
{136, &JitArmIL::Default}, //"subfex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{232, &JitArmIL::Default}, //"subfmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{200, &JitArmIL::Default}, //"subfzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
};
static GekkoOPTemplate table59[] =
{
{18, &JitArmIL::Default}, //{"fdivsx", OPTYPE_FPU, FL_RC_BIT_F, 16}},
{20, &JitArmIL::Default}, //"fsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
{21, &JitArmIL::Default}, //"faddsx", OPTYPE_FPU, FL_RC_BIT_F}},
// {22, &JitArmIL::Default}, //"fsqrtsx", OPTYPE_FPU, FL_RC_BIT_F}},
{24, &JitArmIL::Default}, //"fresx", OPTYPE_FPU, FL_RC_BIT_F}},
{25, &JitArmIL::Default}, //"fmulsx", OPTYPE_FPU, FL_RC_BIT_F}},
{28, &JitArmIL::Default}, //"fmsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
{29, &JitArmIL::Default}, //"fmaddsx", OPTYPE_FPU, FL_RC_BIT_F}},
{30, &JitArmIL::Default}, //"fnmsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
{31, &JitArmIL::Default}, //"fnmaddsx", OPTYPE_FPU, FL_RC_BIT_F}},
};
static GekkoOPTemplate table63[] =
{
{264, &JitArmIL::Default}, //"fabsx", OPTYPE_FPU, FL_RC_BIT_F}},
{32, &JitArmIL::Default}, //"fcmpo", OPTYPE_FPU, FL_RC_BIT_F}},
{0, &JitArmIL::Default}, //"fcmpu", OPTYPE_FPU, FL_RC_BIT_F}},
{14, &JitArmIL::Default}, //"fctiwx", OPTYPE_FPU, FL_RC_BIT_F}},
{15, &JitArmIL::Default}, //"fctiwzx", OPTYPE_FPU, FL_RC_BIT_F}},
{72, &JitArmIL::Default}, //"fmrx", OPTYPE_FPU, FL_RC_BIT_F}},
{136, &JitArmIL::Default}, //"fnabsx", OPTYPE_FPU, FL_RC_BIT_F}},
{40, &JitArmIL::Default}, //"fnegx", OPTYPE_FPU, FL_RC_BIT_F}},
{12, &JitArmIL::Default}, //"frspx", OPTYPE_FPU, FL_RC_BIT_F}},
{64, &JitArmIL::Default}, //"mcrfs", OPTYPE_SYSTEMFP, 0}},
{583, &JitArmIL::Default}, //"mffsx", OPTYPE_SYSTEMFP, 0}},
{70, &JitArmIL::Default}, //"mtfsb0x", OPTYPE_SYSTEMFP, 0, 2}},
{38, &JitArmIL::Default}, //"mtfsb1x", OPTYPE_SYSTEMFP, 0, 2}},
{134, &JitArmIL::Default}, //"mtfsfix", OPTYPE_SYSTEMFP, 0, 2}},
{711, &JitArmIL::Default}, //"mtfsfx", OPTYPE_SYSTEMFP, 0, 2}},
};
static GekkoOPTemplate table63_2[] =
{
{18, &JitArmIL::Default}, //"fdivx", OPTYPE_FPU, FL_RC_BIT_F, 30}},
{20, &JitArmIL::Default}, //"fsubx", OPTYPE_FPU, FL_RC_BIT_F}},
{21, &JitArmIL::Default}, //"faddx", OPTYPE_FPU, FL_RC_BIT_F}},
{22, &JitArmIL::Default}, //"fsqrtx", OPTYPE_FPU, FL_RC_BIT_F}},
{23, &JitArmIL::Default}, //"fselx", OPTYPE_FPU, FL_RC_BIT_F}},
{25, &JitArmIL::Default}, //"fmulx", OPTYPE_FPU, FL_RC_BIT_F}},
{26, &JitArmIL::Default}, //"frsqrtex", OPTYPE_FPU, FL_RC_BIT_F}},
{28, &JitArmIL::Default}, //"fmsubx", OPTYPE_FPU, FL_RC_BIT_F}},
{29, &JitArmIL::Default}, //"fmaddx", OPTYPE_FPU, FL_RC_BIT_F}},
{30, &JitArmIL::Default}, //"fnmsubx", OPTYPE_FPU, FL_RC_BIT_F}},
{31, &JitArmIL::Default}, //"fnmaddx", OPTYPE_FPU, FL_RC_BIT_F}},
};
namespace JitArmILTables
{
void CompileInstruction(PPCAnalyst::CodeOp & op)
{
JitArmIL *jitarm = (JitArmIL *)jit;
(jitarm->*dynaOpTable[op.inst.OPCD])(op.inst);
GekkoOPInfo *info = op.opinfo;
if (info) {
#ifdef OPLOG
if (!strcmp(info->opname, OP_TO_LOG)){ ///"mcrfs"
rsplocations.push_back(jit.js.compilerPC);
}
#endif
info->compileCount++;
info->lastUse = jit->js.compilerPC;
}
}
void InitTables()
{
// once initialized, tables are read-only
static bool initialized = false;
if (initialized)
return;
//clear
for (int i = 0; i < 32; i++)
{
dynaOpTable59[i] = &JitArmIL::unknown_instruction;
}
for (int i = 0; i < 1024; i++)
{
dynaOpTable4 [i] = &JitArmIL::unknown_instruction;
dynaOpTable19[i] = &JitArmIL::unknown_instruction;
dynaOpTable31[i] = &JitArmIL::unknown_instruction;
dynaOpTable63[i] = &JitArmIL::unknown_instruction;
}
for (int i = 0; i < (int)(sizeof(primarytable) / sizeof(GekkoOPTemplate)); i++)
{
dynaOpTable[primarytable[i].opcode] = primarytable[i].Inst;
}
for (int i = 0; i < 32; i++)
{
int fill = i << 5;
for (int j = 0; j < (int)(sizeof(table4_2) / sizeof(GekkoOPTemplate)); j++)
{
int op = fill+table4_2[j].opcode;
dynaOpTable4[op] = table4_2[j].Inst;
}
}
for (int i = 0; i < 16; i++)
{
int fill = i << 6;
for (int j = 0; j < (int)(sizeof(table4_3) / sizeof(GekkoOPTemplate)); j++)
{
int op = fill+table4_3[j].opcode;
dynaOpTable4[op] = table4_3[j].Inst;
}
}
for (int i = 0; i < (int)(sizeof(table4) / sizeof(GekkoOPTemplate)); i++)
{
int op = table4[i].opcode;
dynaOpTable4[op] = table4[i].Inst;
}
for (int i = 0; i < (int)(sizeof(table31) / sizeof(GekkoOPTemplate)); i++)
{
int op = table31[i].opcode;
dynaOpTable31[op] = table31[i].Inst;
}
for (int i = 0; i < 1; i++)
{
int fill = i << 9;
for (int j = 0; j < (int)(sizeof(table31_2) / sizeof(GekkoOPTemplate)); j++)
{
int op = fill + table31_2[j].opcode;
dynaOpTable31[op] = table31_2[j].Inst;
}
}
for (int i = 0; i < (int)(sizeof(table19) / sizeof(GekkoOPTemplate)); i++)
{
int op = table19[i].opcode;
dynaOpTable19[op] = table19[i].Inst;
}
for (int i = 0; i < (int)(sizeof(table59) / sizeof(GekkoOPTemplate)); i++)
{
int op = table59[i].opcode;
dynaOpTable59[op] = table59[i].Inst;
}
for (int i = 0; i < (int)(sizeof(table63) / sizeof(GekkoOPTemplate)); i++)
{
int op = table63[i].opcode;
dynaOpTable63[op] = table63[i].Inst;
}
for (int i = 0; i < 32; i++)
{
int fill = i << 5;
for (int j = 0; j < (int)(sizeof(table63_2) / sizeof(GekkoOPTemplate)); j++)
{
int op = fill + table63_2[j].opcode;
dynaOpTable63[op] = table63_2[j].Inst;
}
}
initialized = true;
}
} // namespace
@@ -0,0 +1,16 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#ifndef JITARMIL_TABLES_H
#define JITARMIL_TABLES_H
#include "../Gekko.h"
#include "../PPCTables.h"
namespace JitArmILTables
{
void CompileInstruction(PPCAnalyst::CodeOp & op);
void InitTables();
}
#endif
@@ -107,6 +107,19 @@
#define CTX_R15 gregs[REG_R15]
#define CTX_RIP gregs[REG_RIP]
#elif defined(_M_IX86)
#ifdef ANDROID
#include <asm/sigcontext.h>
typedef sigcontext SContext;
#define CTX_EAX eax
#define CTX_EBX ebx
#define CTX_ECX ecx
#define CTX_EDX edx
#define CTX_EDI edi
#define CTX_ESI esi
#define CTX_EBP ebp
#define CTX_ESP esp
#define CTX_EIP eip
#else
#include <ucontext.h>
typedef mcontext_t SContext;
#define CTX_EAX gregs[REG_EAX]
@@ -118,6 +131,7 @@
#define CTX_EBP gregs[REG_EBP]
#define CTX_ESP gregs[REG_ESP]
#define CTX_EIP gregs[REG_EIP]
#endif
#elif defined(_M_ARM)
// Add others if required.
typedef struct sigcontext SContext;
@@ -124,8 +124,6 @@ Fix profiled loads/stores to work safely. On 32-bit, one solution is to
#include "../PPCTables.h"
#include "../../CoreTiming.h"
#include "../../HW/Memmap.h"
#include "JitILAsm.h"
#include "JitIL.h"
#include "../../HW/GPFifo.h"
#include "../../Core.h"
using namespace Gen;

Some files were not shown because too many files have changed in this diff Show More