mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
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:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+31
-58
@@ -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;
|
||||
|
||||
-2
@@ -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
Reference in New Issue
Block a user