Merge pull request #5445 from JosJuice/remove-jitil

Remove JITIL
This commit is contained in:
Mat M
2017-05-19 21:33:38 -04:00
committed by GitHub
26 changed files with 9 additions and 7913 deletions
-12
View File
@@ -219,22 +219,10 @@ set(SRCS
PowerPC/JitCommon/JitAsmCommon.cpp
PowerPC/JitCommon/JitBase.cpp
PowerPC/JitCommon/JitCache.cpp
PowerPC/JitILCommon/IR.cpp
PowerPC/JitILCommon/JitILBase_Branch.cpp
PowerPC/JitILCommon/JitILBase_LoadStore.cpp
PowerPC/JitILCommon/JitILBase_SystemRegisters.cpp
PowerPC/JitILCommon/JitILBase_LoadStoreFloating.cpp
PowerPC/JitILCommon/JitILBase_LoadStorePaired.cpp
PowerPC/JitILCommon/JitILBase_Paired.cpp
PowerPC/JitILCommon/JitILBase_FloatingPoint.cpp
PowerPC/JitILCommon/JitILBase_Integer.cpp
)
if(_M_X86)
set(SRCS ${SRCS}
PowerPC/Jit64IL/IR_X86.cpp
PowerPC/Jit64IL/JitIL.cpp
PowerPC/Jit64IL/JitIL_Tables.cpp
PowerPC/Jit64/FPURegCache.cpp
PowerPC/Jit64/GPRRegCache.cpp
PowerPC/Jit64/Jit64_Tables.cpp
-2
View File
@@ -581,8 +581,6 @@ void SConfig::LoadCoreSettings(IniFile& ini)
core->Get("SlotB", (int*)&m_EXIDevice[1], ExpansionInterface::EXIDEVICE_NONE);
core->Get("SerialPort1", (int*)&m_EXIDevice[2], ExpansionInterface::EXIDEVICE_NONE);
core->Get("BBA_MAC", &m_bba_mac);
core->Get("TimeProfiling", &bJITILTimeProfiling, false);
core->Get("OutputIR", &bJITILOutputIR, false);
for (int i = 0; i < SerialInterface::MAX_SI_CHANNELS; ++i)
{
core->Get(StringFromFormat("SIDevice%i", i), (u32*)&m_SIDevice[i],
+1 -4
View File
@@ -74,9 +74,8 @@ struct SConfig : NonCopyable
bool bAutomaticStart = false;
bool bBootToPause = false;
int iCPUCore;
int iCPUCore; // Uses the values of PowerPC::CPUCore
// JIT (shared between JIT and JITIL)
bool bJITNoBlockCache = false;
bool bJITNoBlockLinking = false;
bool bJITOff = false;
@@ -91,8 +90,6 @@ struct SConfig : NonCopyable
bool bJITPairedOff = false;
bool bJITSystemRegistersOff = false;
bool bJITBranchOff = false;
bool bJITILTimeProfiling = false;
bool bJITILOutputIR = false;
bool bFastmem;
bool bFPRF = false;
-15
View File
@@ -249,18 +249,6 @@
<ClCompile Include="PowerPC\Interpreter\Interpreter_SystemRegisters.cpp" />
<ClCompile Include="PowerPC\Interpreter\Interpreter_Tables.cpp" />
<ClCompile Include="PowerPC\Jit64Common\ConstantPool.cpp" />
<ClCompile Include="PowerPC\JitILCommon\IR.cpp" />
<ClCompile Include="PowerPC\JitILCommon\JitILBase_Branch.cpp" />
<ClCompile Include="PowerPC\JitILCommon\JitILBase_FloatingPoint.cpp" />
<ClCompile Include="PowerPC\JitILCommon\JitILBase_Integer.cpp" />
<ClCompile Include="PowerPC\JitILCommon\JitILBase_LoadStore.cpp" />
<ClCompile Include="PowerPC\JitILCommon\JitILBase_LoadStoreFloating.cpp" />
<ClCompile Include="PowerPC\JitILCommon\JitILBase_LoadStorePaired.cpp" />
<ClCompile Include="PowerPC\JitILCommon\JitILBase_Paired.cpp" />
<ClCompile Include="PowerPC\JitILCommon\JitILBase_SystemRegisters.cpp" />
<ClCompile Include="PowerPC\Jit64IL\IR_X86.cpp" />
<ClCompile Include="PowerPC\Jit64IL\JitIL.cpp" />
<ClCompile Include="PowerPC\Jit64IL\JitIL_Tables.cpp" />
<ClCompile Include="PowerPC\Jit64\FPURegCache.cpp" />
<ClCompile Include="PowerPC\Jit64\GPRRegCache.cpp" />
<ClCompile Include="PowerPC\Jit64\Jit.cpp" />
@@ -496,14 +484,11 @@
<ClInclude Include="PowerPC\Interpreter\Interpreter.h" />
<ClInclude Include="PowerPC\Interpreter\Interpreter_FPUtils.h" />
<ClInclude Include="PowerPC\Jit64Common\ConstantPool.h" />
<ClInclude Include="PowerPC\Jit64IL\JitIL.h" />
<ClInclude Include="PowerPC\Jit64\FPURegCache.h" />
<ClInclude Include="PowerPC\Jit64\GPRRegCache.h" />
<ClInclude Include="PowerPC\Jit64\Jit.h" />
<ClInclude Include="PowerPC\Jit64\JitAsm.h" />
<ClInclude Include="PowerPC\Jit64\JitRegCache.h" />
<ClInclude Include="PowerPC\JitILCommon\IR.h" />
<ClInclude Include="PowerPC\JitILCommon\JitILBase.h" />
<ClInclude Include="PowerPC\Jit64Common\BlockCache.h" />
<ClInclude Include="PowerPC\Jit64Common\EmuCodeBlock.h" />
<ClInclude Include="PowerPC\Jit64Common\FarCodeCache.h" />
-51
View File
@@ -43,9 +43,6 @@
<Filter Include="PowerPC\JitCommon">
<UniqueIdentifier>{c88ec388-371f-4401-851c-a32dcdc0b88b}</UniqueIdentifier>
</Filter>
<Filter Include="PowerPC\JitIL">
<UniqueIdentifier>{f26d3866-92d1-4623-9445-caf9a065ed74}</UniqueIdentifier>
</Filter>
<Filter Include="DSPCore\Interpreter">
<UniqueIdentifier>{6204f663-bbd0-4eb5-bc15-e3778d8b6091}</UniqueIdentifier>
</Filter>
@@ -112,9 +109,6 @@
<Filter Include="HW %28Flipper/Hollywood%29\Wii IPC">
<UniqueIdentifier>{2b41ab45-ba8c-45dc-92cc-9107c1fa3e36}</UniqueIdentifier>
</Filter>
<Filter Include="PowerPC\JitILCommon">
<UniqueIdentifier>{827afa93-1a80-4835-93ae-b5516d95867f}</UniqueIdentifier>
</Filter>
<Filter Include="PowerPC\Jit64Common">
<UniqueIdentifier>{81956f71-d9fe-454f-96a6-855195d611c4}</UniqueIdentifier>
</Filter>
@@ -631,15 +625,6 @@
<ClCompile Include="PowerPC\JitCommon\JitCache.cpp">
<Filter>PowerPC\JitCommon</Filter>
</ClCompile>
<ClCompile Include="PowerPC\Jit64IL\IR_X86.cpp">
<Filter>PowerPC\JitIL</Filter>
</ClCompile>
<ClCompile Include="PowerPC\Jit64IL\JitIL.cpp">
<Filter>PowerPC\JitIL</Filter>
</ClCompile>
<ClCompile Include="PowerPC\Jit64IL\JitIL_Tables.cpp">
<Filter>PowerPC\JitIL</Filter>
</ClCompile>
<ClCompile Include="PowerPC\Jit64\FPURegCache.cpp">
<Filter>PowerPC\Jit64</Filter>
</ClCompile>
@@ -676,33 +661,6 @@
<ClCompile Include="PowerPC\Jit64\JitRegCache.cpp">
<Filter>PowerPC\Jit64</Filter>
</ClCompile>
<ClCompile Include="PowerPC\JitILCommon\JitILBase_Branch.cpp">
<Filter>PowerPC\JitILCommon</Filter>
</ClCompile>
<ClCompile Include="PowerPC\JitILCommon\JitILBase_FloatingPoint.cpp">
<Filter>PowerPC\JitILCommon</Filter>
</ClCompile>
<ClCompile Include="PowerPC\JitILCommon\JitILBase_Integer.cpp">
<Filter>PowerPC\JitILCommon</Filter>
</ClCompile>
<ClCompile Include="PowerPC\JitILCommon\JitILBase_LoadStore.cpp">
<Filter>PowerPC\JitILCommon</Filter>
</ClCompile>
<ClCompile Include="PowerPC\JitILCommon\JitILBase_LoadStoreFloating.cpp">
<Filter>PowerPC\JitILCommon</Filter>
</ClCompile>
<ClCompile Include="PowerPC\JitILCommon\JitILBase_LoadStorePaired.cpp">
<Filter>PowerPC\JitILCommon</Filter>
</ClCompile>
<ClCompile Include="PowerPC\JitILCommon\JitILBase_Paired.cpp">
<Filter>PowerPC\JitILCommon</Filter>
</ClCompile>
<ClCompile Include="PowerPC\JitILCommon\JitILBase_SystemRegisters.cpp">
<Filter>PowerPC\JitILCommon</Filter>
</ClCompile>
<ClCompile Include="PowerPC\JitILCommon\IR.cpp">
<Filter>PowerPC\JitILCommon</Filter>
</ClCompile>
<ClCompile Include="HW\GCKeyboardEmu.cpp">
<Filter>HW %28Flipper/Hollywood%29\GCKeyboard</Filter>
</ClCompile>
@@ -1328,9 +1286,6 @@
<ClInclude Include="PowerPC\JitCommon\JitCache.h">
<Filter>PowerPC\JitCommon</Filter>
</ClInclude>
<ClInclude Include="PowerPC\Jit64IL\JitIL.h">
<Filter>PowerPC\JitIL</Filter>
</ClInclude>
<ClInclude Include="PowerPC\Jit64\FPURegCache.h">
<Filter>PowerPC\Jit64</Filter>
</ClInclude>
@@ -1343,12 +1298,6 @@
<ClInclude Include="PowerPC\Jit64\JitAsm.h">
<Filter>PowerPC\Jit64</Filter>
</ClInclude>
<ClInclude Include="PowerPC\JitILCommon\JitILBase.h">
<Filter>PowerPC\JitILCommon</Filter>
</ClInclude>
<ClInclude Include="PowerPC\JitILCommon\IR.h">
<Filter>PowerPC\JitILCommon</Filter>
</ClInclude>
<ClInclude Include="MachineContext.h" />
<ClInclude Include="HW\GCKeyboardEmu.h">
<Filter>HW %28Flipper/Hollywood%29\GCKeyboard</Filter>
+1 -1
View File
@@ -81,7 +81,7 @@ struct DTMHeader
bool bProgressive;
bool bDSPHLE;
bool bFastDiscSpeed;
u8 CPUCore; // 0 = interpreter, 1 = JIT, 2 = JITIL
u8 CPUCore; // Uses the values of PowerPC::CPUCore
bool bEFBAccessEnable;
bool bEFBCopyEnable;
bool bSkipEFBCopyToRam;
@@ -19,7 +19,6 @@ namespace PPCAnalyst
class CodeBuffer;
}
// The following register assignments are common to Jit64 and Jit64IL:
// RSCRATCH and RSCRATCH2 are always scratch registers and can be used without
// limitation.
constexpr Gen::X64Reg RSCRATCH = Gen::RAX;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-83
View File
@@ -1,83 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
// ========================
// See comments in Jit.cpp.
// ========================
// Mystery: Capcom vs SNK 800aa278
// CR flags approach:
// * Store that "N+Z flag contains CR0" or "S+Z flag contains CR3".
// * All flag altering instructions flush this
// * A flush simply does a conditional write to the appropriate CRx.
// * If flag available, branch code can become absolutely trivial.
#pragma once
#include "Common/CommonTypes.h"
#include "Common/x64ABI.h"
#include "Common/x64Emitter.h"
#include "Core/PowerPC/Gekko.h"
#include "Core/PowerPC/Jit64/JitAsm.h"
#include "Core/PowerPC/JitCommon/JitCache.h"
#include "Core/PowerPC/JitILCommon/JitILBase.h"
#include "Core/PowerPC/PPCAnalyst.h"
class JitIL : public JitILBase
{
public:
Jit64AsmRoutineManager asm_routines;
JitIL() {}
~JitIL() {}
// Initialization, etc
void Init() override;
void Shutdown() override;
void EnableBlockLink();
// Jit!
void Jit(u32 em_address) override;
const u8* DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBlock* b, u32 nextPC);
void Trace();
JitBlockCache* GetBlockCache() override { return &blocks; }
void ClearCache() override;
const CommonAsmRoutines* GetAsmRoutines() override { return &asm_routines; }
const char* GetName() override { return "JIT64IL"; }
// Run!
void Run() override;
void SingleStep() override;
// Utilities for use by opcodes
void WriteExit(u32 destination);
void WriteExitDestInOpArg(const Gen::OpArg& arg);
void WriteExceptionExit();
void WriteRfiExitDestInOpArg(const Gen::OpArg& arg);
void Cleanup();
void WriteCode(u32 exitAddress);
// OPCODES
using Instruction = void (JitIL::*)(UGeckoInstruction instCode);
void FallBackToInterpreter(UGeckoInstruction _inst) override;
void DoNothing(UGeckoInstruction _inst) override;
void HLEFunction(UGeckoInstruction _inst) override;
void DynaRunTable4(UGeckoInstruction _inst) override;
void DynaRunTable19(UGeckoInstruction _inst) override;
void DynaRunTable31(UGeckoInstruction _inst) override;
void DynaRunTable59(UGeckoInstruction _inst) override;
void DynaRunTable63(UGeckoInstruction _inst) override;
private:
static void InitializeInstructionTables();
void CompileInstruction(PPCAnalyst::CodeOp& op);
};
@@ -1,493 +0,0 @@
// Copyright 2010 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/PowerPC/Jit64IL/JitIL.h"
#include "Core/PowerPC/Gekko.h"
#include "Core/PowerPC/PPCTables.h"
static JitIL::Instruction dynaOpTable[64];
static JitIL::Instruction dynaOpTable4[1024];
static JitIL::Instruction dynaOpTable19[1024];
static JitIL::Instruction dynaOpTable31[1024];
static JitIL::Instruction dynaOpTable59[32];
static JitIL::Instruction dynaOpTable63[1024];
void JitIL::DynaRunTable4(UGeckoInstruction _inst)
{
(this->*dynaOpTable4[_inst.SUBOP10])(_inst);
}
void JitIL::DynaRunTable19(UGeckoInstruction _inst)
{
(this->*dynaOpTable19[_inst.SUBOP10])(_inst);
}
void JitIL::DynaRunTable31(UGeckoInstruction _inst)
{
(this->*dynaOpTable31[_inst.SUBOP10])(_inst);
}
void JitIL::DynaRunTable59(UGeckoInstruction _inst)
{
(this->*dynaOpTable59[_inst.SUBOP5])(_inst);
}
void JitIL::DynaRunTable63(UGeckoInstruction _inst)
{
(this->*dynaOpTable63[_inst.SUBOP10])(_inst);
}
struct GekkoOPTemplate
{
int opcode;
JitIL::Instruction Inst;
};
const GekkoOPTemplate primarytable[] = {
{4, &JitIL::DynaRunTable4}, //"RunTable4", OPTYPE_SUBTABLE | (4<<24), 0}},
{19, &JitIL::DynaRunTable19}, //"RunTable19", OPTYPE_SUBTABLE | (19<<24), 0}},
{31, &JitIL::DynaRunTable31}, //"RunTable31", OPTYPE_SUBTABLE | (31<<24), 0}},
{59, &JitIL::DynaRunTable59}, //"RunTable59", OPTYPE_SUBTABLE | (59<<24), 0}},
{63, &JitIL::DynaRunTable63}, //"RunTable63", OPTYPE_SUBTABLE | (63<<24), 0}},
{16, &JitIL::bcx}, //"bcx", OPTYPE_SYSTEM, FL_ENDBLOCK}},
{18, &JitIL::bx}, //"bx", OPTYPE_SYSTEM, FL_ENDBLOCK}},
{3, &JitIL::FallBackToInterpreter}, //"twi", OPTYPE_SYSTEM, 0}},
{17, &JitIL::sc}, //"sc", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}},
{7, &JitIL::mulli}, //"mulli", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_RC_BIT, 2}},
{8, &JitIL::subfic}, //"subfic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}},
{10, &JitIL::cmpXX}, //"cmpli", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}},
{11, &JitIL::cmpXX}, //"cmpi", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}},
{12, &JitIL::reg_imm}, //"addic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}},
{13, &JitIL::reg_imm}, //"addic_rc", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CR0}},
{14, &JitIL::reg_imm}, //"addi", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}},
{15, &JitIL::reg_imm}, //"addis", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}},
{20,
&JitIL::rlwimix}, //"rlwimix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_A | FL_IN_S | FL_RC_BIT}},
{21, &JitIL::rlwinmx}, //"rlwinmx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{23, &JitIL::rlwnmx}, //"rlwnmx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_IN_B | FL_RC_BIT}},
{24, &JitIL::reg_imm}, //"ori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{25, &JitIL::reg_imm}, //"oris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{26, &JitIL::reg_imm}, //"xori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{27, &JitIL::reg_imm}, //"xoris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{28, &JitIL::reg_imm}, //"andi_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
{29, &JitIL::reg_imm}, //"andis_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
{32, &JitIL::lXz}, //"lwz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{33, &JitIL::lXz}, //"lwzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
{34, &JitIL::lXz}, //"lbz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{35, &JitIL::lbzu}, //"lbzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
{40, &JitIL::lXz}, //"lhz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{41, &JitIL::lXz}, //"lhzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
{42, &JitIL::lha}, //"lha", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{43, &JitIL::lhau}, //"lhau", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
{44, &JitIL::stX}, //"sth", OPTYPE_STORE, FL_IN_A | FL_IN_S}},
{45, &JitIL::stX}, //"sthu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}},
{36, &JitIL::stX}, //"stw", OPTYPE_STORE, FL_IN_A | FL_IN_S}},
{37, &JitIL::stX}, //"stwu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}},
{38, &JitIL::stX}, //"stb", OPTYPE_STORE, FL_IN_A | FL_IN_S}},
{39, &JitIL::stX}, //"stbu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}},
{46, &JitIL::lmw}, //"lmw", OPTYPE_SYSTEM, FL_EVIL, 10}},
{47, &JitIL::stmw}, //"stmw", OPTYPE_SYSTEM, FL_EVIL, 10}},
{48, &JitIL::lfs}, //"lfs", OPTYPE_LOADFP, FL_IN_A}},
{49, &JitIL::lfsu}, //"lfsu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A}},
{50, &JitIL::lfd}, //"lfd", OPTYPE_LOADFP, FL_IN_A}},
{51, &JitIL::lfdu}, //"lfdu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A}},
{52, &JitIL::stfs}, //"stfs", OPTYPE_STOREFP, FL_IN_A}},
{53, &JitIL::stfs}, //"stfsu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}},
{54, &JitIL::stfd}, //"stfd", OPTYPE_STOREFP, FL_IN_A}},
{55, &JitIL::stfd}, //"stfdu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}},
{56, &JitIL::psq_l}, //"psq_l", OPTYPE_PS, FL_IN_A}},
{57, &JitIL::psq_l}, //"psq_lu", OPTYPE_PS, FL_OUT_A | FL_IN_A}},
{60, &JitIL::psq_st}, //"psq_st", OPTYPE_PS, FL_IN_A}},
{61, &JitIL::psq_st}, //"psq_stu", OPTYPE_PS, FL_OUT_A | FL_IN_A}},
// missing: 0, 1, 2, 5, 6, 9, 22, 30, 62, 58
};
const GekkoOPTemplate table4[] = {
// SUBOP10
{0, &JitIL::FallBackToInterpreter}, //"ps_cmpu0", OPTYPE_PS, FL_SET_CRn}},
{32, &JitIL::FallBackToInterpreter}, //"ps_cmpo0", OPTYPE_PS, FL_SET_CRn}},
{40, &JitIL::FallBackToInterpreter}, //"ps_neg", OPTYPE_PS, FL_RC_BIT}},
{136, &JitIL::FallBackToInterpreter}, //"ps_nabs", OPTYPE_PS, FL_RC_BIT}},
{264, &JitIL::FallBackToInterpreter}, //"ps_abs", OPTYPE_PS, FL_RC_BIT}},
{64, &JitIL::FallBackToInterpreter}, //"ps_cmpu1", OPTYPE_PS, FL_RC_BIT}},
{72, &JitIL::FallBackToInterpreter}, //"ps_mr", OPTYPE_PS, FL_RC_BIT}},
{96, &JitIL::FallBackToInterpreter}, //"ps_cmpo1", OPTYPE_PS, FL_RC_BIT}},
{528, &JitIL::ps_mergeXX}, //"ps_merge00", OPTYPE_PS, FL_RC_BIT}},
{560, &JitIL::ps_mergeXX}, //"ps_merge01", OPTYPE_PS, FL_RC_BIT}},
{592, &JitIL::ps_mergeXX}, //"ps_merge10", OPTYPE_PS, FL_RC_BIT}},
{624, &JitIL::ps_mergeXX}, //"ps_merge11", OPTYPE_PS, FL_RC_BIT}},
{1014, &JitIL::FallBackToInterpreter}, //"dcbz_l", OPTYPE_SYSTEM, 0}},
};
const GekkoOPTemplate table4_2[] = {
{10, &JitIL::ps_sum}, //"ps_sum0", OPTYPE_PS, 0}},
{11, &JitIL::ps_sum}, //"ps_sum1", OPTYPE_PS, 0}},
{12, &JitIL::ps_muls}, //"ps_muls0", OPTYPE_PS, 0}},
{13, &JitIL::ps_muls}, //"ps_muls1", OPTYPE_PS, 0}},
{14, &JitIL::ps_maddXX}, //"ps_madds0", OPTYPE_PS, 0}},
{15, &JitIL::ps_maddXX}, //"ps_madds1", OPTYPE_PS, 0}},
{18, &JitIL::ps_arith}, //"ps_div", OPTYPE_PS, 0, 16}},
{20, &JitIL::ps_arith}, //"ps_sub", OPTYPE_PS, 0}},
{21, &JitIL::ps_arith}, //"ps_add", OPTYPE_PS, 0}},
{23, &JitIL::FallBackToInterpreter}, //"ps_sel", OPTYPE_PS, 0}},
{24, &JitIL::FallBackToInterpreter}, //"ps_res", OPTYPE_PS, 0}},
{25, &JitIL::ps_arith}, //"ps_mul", OPTYPE_PS, 0}},
{26, &JitIL::FallBackToInterpreter}, //"ps_rsqrte", OPTYPE_PS, 0, 1}},
{28, &JitIL::ps_maddXX}, //"ps_msub", OPTYPE_PS, 0}},
{29, &JitIL::ps_maddXX}, //"ps_madd", OPTYPE_PS, 0}},
{30, &JitIL::ps_maddXX}, //"ps_nmsub", OPTYPE_PS, 0}},
{31, &JitIL::ps_maddXX}, //"ps_nmadd", OPTYPE_PS, 0}},
};
const GekkoOPTemplate table4_3[] = {
{6, &JitIL::FallBackToInterpreter}, //"psq_lx", OPTYPE_PS, 0}},
{7, &JitIL::FallBackToInterpreter}, //"psq_stx", OPTYPE_PS, 0}},
{38, &JitIL::FallBackToInterpreter}, //"psq_lux", OPTYPE_PS, 0}},
{39, &JitIL::FallBackToInterpreter}, //"psq_stux", OPTYPE_PS, 0}},
};
const GekkoOPTemplate table19[] = {
{528, &JitIL::bcctrx}, //"bcctrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
{16, &JitIL::bclrx}, //"bclrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
{257, &JitIL::crXX}, //"crand", OPTYPE_CR, FL_EVIL}},
{129, &JitIL::crXX}, //"crandc", OPTYPE_CR, FL_EVIL}},
{289, &JitIL::crXX}, //"creqv", OPTYPE_CR, FL_EVIL}},
{225, &JitIL::crXX}, //"crnand", OPTYPE_CR, FL_EVIL}},
{33, &JitIL::crXX}, //"crnor", OPTYPE_CR, FL_EVIL}},
{449, &JitIL::crXX}, //"cror", OPTYPE_CR, FL_EVIL}},
{417, &JitIL::crXX}, //"crorc", OPTYPE_CR, FL_EVIL}},
{193, &JitIL::crXX}, //"crxor", OPTYPE_CR, FL_EVIL}},
{150, &JitIL::DoNothing}, //"isync", OPTYPE_ICACHE, FL_EVIL}},
{0, &JitIL::mcrf}, //"mcrf", OPTYPE_SYSTEM, FL_EVIL}},
{50, &JitIL::rfi}, //"rfi", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS, 1}},
};
const GekkoOPTemplate table31[] = {
{266, &JitIL::addx}, //"addx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{778, &JitIL::addx}, //"addox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{10, &JitIL::FallBackToInterpreter}, //"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB |
// FL_SET_CA | FL_RC_BIT}},
{522, &JitIL::FallBackToInterpreter}, //"addcox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB |
// FL_SET_CA | FL_RC_BIT}},
{138, &JitIL::addex}, //"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA
//| FL_RC_BIT}},
{650, &JitIL::addex}, //"addeox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA
//| FL_RC_BIT}},
{234, &JitIL::FallBackToInterpreter}, //"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB |
// FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{746, &JitIL::FallBackToInterpreter}, //"addmeox"
{202, &JitIL::addzex}, //"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA |
// FL_SET_CA | FL_RC_BIT}},
{714, &JitIL::addzex}, //"addzeox"
{491, &JitIL::FallBackToInterpreter}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB |
// FL_RC_BIT, 39}},
{1003, &JitIL::FallBackToInterpreter}, //"divwox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB |
// FL_RC_BIT, 39}},
{459, &JitIL::divwux}, //"divwux", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
{971, &JitIL::divwux}, //"divwuox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
{75, &JitIL::FallBackToInterpreter}, //"mulhwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB |
// FL_RC_BIT, 4}},
{11, &JitIL::mulhwux}, //"mulhwux", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
{235, &JitIL::mullwx}, //"mullwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
{747, &JitIL::mullwx}, //"mullwox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
{104, &JitIL::negx}, //"negx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{616, &JitIL::negx}, //"negox"
{40, &JitIL::subfx}, //"subfx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{552, &JitIL::subfx}, //"subfox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{8,
&JitIL::subfcx}, //"subfcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
{520,
&JitIL::subfcx}, //"subfcox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
{136, &JitIL::subfex}, //"subfex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA |
// FL_SET_CA | FL_RC_BIT}},
{648, &JitIL::subfex}, //"subfeox"
{232, &JitIL::FallBackToInterpreter}, //"subfmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB |
// FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{744, &JitIL::FallBackToInterpreter}, //"subfmeox"
{200, &JitIL::FallBackToInterpreter}, //"subfzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB |
// FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{712, &JitIL::FallBackToInterpreter}, //"subfzeox"
{28, &JitIL::boolX}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{60, &JitIL::boolX}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{444, &JitIL::boolX}, //"orx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{124, &JitIL::boolX}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{316, &JitIL::boolX}, //"xorx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{412, &JitIL::boolX}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{476, &JitIL::boolX}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{284, &JitIL::boolX}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{0, &JitIL::cmpXX}, //"cmp", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
{32, &JitIL::cmpXX}, //"cmpl", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
{26, &JitIL::cntlzwx}, //"cntlzwx",OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{922, &JitIL::extshx}, //"extshx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{954, &JitIL::extsbx}, //"extsbx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{536, &JitIL::srwx}, //"srwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{792, &JitIL::srawx}, //"srawx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{824, &JitIL::srawix}, //"srawix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{24, &JitIL::slwx}, //"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{54, &JitIL::dcbst}, //"dcbst", OPTYPE_DCACHE, 0, 4}},
{86, &JitIL::FallBackToInterpreter}, //"dcbf", OPTYPE_DCACHE, 0, 4}},
{246, &JitIL::DoNothing}, //"dcbtst", OPTYPE_DCACHE, 0, 1}},
{278, &JitIL::DoNothing}, //"dcbt", OPTYPE_DCACHE, 0, 1}},
{470, &JitIL::FallBackToInterpreter}, //"dcbi", OPTYPE_DCACHE, 0, 4}},
{758, &JitIL::DoNothing}, //"dcba", OPTYPE_DCACHE, 0, 4}},
{1014, &JitIL::dcbz}, //"dcbz", OPTYPE_DCACHE, 0, 4}},
// load word
{23, &JitIL::lXzx}, //"lwzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{55, &JitIL::lXzx}, //"lwzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
// load halfword
{279, &JitIL::lXzx}, //"lhzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{311, &JitIL::lXzx}, //"lhzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
// load halfword signextend
{343, &JitIL::lhax}, //"lhax", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{375, &JitIL::lhaux}, //"lhaux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
// load byte
{87, &JitIL::lXzx}, //"lbzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{119, &JitIL::lXzx}, //"lbzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
// load byte reverse
{534, &JitIL::FallBackToInterpreter}, //"lwbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{790, &JitIL::FallBackToInterpreter}, //"lhbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
// Conditional load/store (Wii SMP)
{150, &JitIL::FallBackToInterpreter}, //"stwcxd", OPTYPE_STORE, FL_EVIL | FL_SET_CR0}},
{20, &JitIL::FallBackToInterpreter}, //"lwarx", OPTYPE_LOAD, FL_EVIL | FL_OUT_D | FL_IN_A0B |
// FL_SET_CR0}},
// load string (interpret these)
{533, &JitIL::FallBackToInterpreter}, //"lswx", OPTYPE_LOAD, FL_EVIL | FL_IN_A | FL_OUT_D}},
{597, &JitIL::FallBackToInterpreter}, //"lswi", OPTYPE_LOAD, FL_EVIL | FL_IN_AB | FL_OUT_D}},
// store word
{151, &JitIL::stXx}, //"stwx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
{183, &JitIL::stXx}, //"stwux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}},
// store halfword
{407, &JitIL::stXx}, //"sthx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
{439, &JitIL::stXx}, //"sthux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}},
// store byte
{215, &JitIL::stXx}, //"stbx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
{247, &JitIL::stXx}, //"stbux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}},
// store bytereverse
{662, &JitIL::FallBackToInterpreter}, //"stwbrx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
{918, &JitIL::FallBackToInterpreter}, //"sthbrx", OPTYPE_STORE, FL_IN_A | FL_IN_B}},
{661, &JitIL::FallBackToInterpreter}, //"stswx", OPTYPE_STORE, FL_EVIL}},
{725, &JitIL::FallBackToInterpreter}, //"stswi", OPTYPE_STORE, FL_EVIL}},
// fp load/store
{535, &JitIL::lfsx}, //"lfsx", OPTYPE_LOADFP, FL_IN_A0 | FL_IN_B}},
{567, &JitIL::FallBackToInterpreter}, //"lfsux", OPTYPE_LOADFP, FL_IN_A | FL_IN_B}},
{599, &JitIL::FallBackToInterpreter}, //"lfdx", OPTYPE_LOADFP, FL_IN_A0 | FL_IN_B}},
{631, &JitIL::FallBackToInterpreter}, //"lfdux", OPTYPE_LOADFP, FL_IN_A | FL_IN_B}},
{663, &JitIL::stfsx}, //"stfsx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}},
{695, &JitIL::FallBackToInterpreter}, //"stfsux", OPTYPE_STOREFP, FL_IN_A | FL_IN_B}},
{727, &JitIL::FallBackToInterpreter}, //"stfdx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}},
{759, &JitIL::FallBackToInterpreter}, //"stfdux", OPTYPE_STOREFP, FL_IN_A | FL_IN_B}},
{983, &JitIL::FallBackToInterpreter}, //"stfiwx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}},
{19, &JitIL::mfcr}, //"mfcr", OPTYPE_SYSTEM, FL_OUT_D}},
{83, &JitIL::mfmsr}, //"mfmsr", OPTYPE_SYSTEM, FL_OUT_D}},
{144, &JitIL::mtcrf}, //"mtcrf", OPTYPE_SYSTEM, 0}},
{146, &JitIL::mtmsr}, //"mtmsr", OPTYPE_SYSTEM, FL_ENDBLOCK}},
{210, &JitIL::FallBackToInterpreter}, //"mtsr", OPTYPE_SYSTEM, 0}},
{242, &JitIL::FallBackToInterpreter}, //"mtsrin", OPTYPE_SYSTEM, 0}},
{339, &JitIL::mfspr}, //"mfspr", OPTYPE_SPR, FL_OUT_D}},
{467, &JitIL::mtspr}, //"mtspr", OPTYPE_SPR, 0, 2}},
{371, &JitIL::mftb}, //"mftb", OPTYPE_SYSTEM, FL_OUT_D | FL_TIMER}},
{512, &JitIL::FallBackToInterpreter}, //"mcrxr", OPTYPE_SYSTEM, 0}},
{595, &JitIL::FallBackToInterpreter}, //"mfsr", OPTYPE_SYSTEM, FL_OUT_D, 2}},
{659, &JitIL::FallBackToInterpreter}, //"mfsrin", OPTYPE_SYSTEM, FL_OUT_D, 2}},
{4, &JitIL::FallBackToInterpreter}, //"tw", OPTYPE_SYSTEM, 0, 1}},
{598, &JitIL::DoNothing}, //"sync", OPTYPE_SYSTEM, 0, 2}},
{982, &JitIL::icbi}, //"icbi", OPTYPE_SYSTEM, FL_ENDBLOCK, 3}},
// Unused instructions on GC
{310, &JitIL::FallBackToInterpreter}, //"eciwx", OPTYPE_INTEGER, FL_RC_BIT}},
{438, &JitIL::FallBackToInterpreter}, //"ecowx", OPTYPE_INTEGER, FL_RC_BIT}},
{854, &JitIL::DoNothing}, //"eieio", OPTYPE_INTEGER, FL_RC_BIT}},
{306, &JitIL::FallBackToInterpreter}, //"tlbie", OPTYPE_SYSTEM, 0}},
{566, &JitIL::DoNothing}, //"tlbsync", OPTYPE_SYSTEM, 0}},
};
const GekkoOPTemplate table59[] = {
{18, &JitIL::FallBackToInterpreter}, //{"fdivsx", OPTYPE_FPU, FL_RC_BIT_F, 16}},
{20, &JitIL::fp_arith_s}, //"fsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
{21, &JitIL::fp_arith_s}, //"faddsx", OPTYPE_FPU, FL_RC_BIT_F}},
{24, &JitIL::FallBackToInterpreter}, //"fresx", OPTYPE_FPU, FL_RC_BIT_F}},
{25, &JitIL::fp_arith_s}, //"fmulsx", OPTYPE_FPU, FL_RC_BIT_F}},
{28, &JitIL::fmaddXX}, //"fmsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
{29, &JitIL::fmaddXX}, //"fmaddsx", OPTYPE_FPU, FL_RC_BIT_F}},
{30, &JitIL::fmaddXX}, //"fnmsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
{31, &JitIL::fmaddXX}, //"fnmaddsx", OPTYPE_FPU, FL_RC_BIT_F}},
};
const GekkoOPTemplate table63[] = {
{264, &JitIL::fsign}, //"fabsx", OPTYPE_FPU, FL_RC_BIT_F}},
{32, &JitIL::fcmpX}, //"fcmpo", OPTYPE_FPU, FL_RC_BIT_F}},
{0, &JitIL::fcmpX}, //"fcmpu", OPTYPE_FPU, FL_RC_BIT_F}},
{14, &JitIL::FallBackToInterpreter}, //"fctiwx", OPTYPE_FPU, FL_RC_BIT_F}},
{15, &JitIL::FallBackToInterpreter}, //"fctiwzx", OPTYPE_FPU, FL_RC_BIT_F}},
{72, &JitIL::fmrx}, //"fmrx", OPTYPE_FPU, FL_RC_BIT_F}},
{136, &JitIL::fsign}, //"fnabsx", OPTYPE_FPU, FL_RC_BIT_F}},
{40, &JitIL::fsign}, //"fnegx", OPTYPE_FPU, FL_RC_BIT_F}},
{12, &JitIL::FallBackToInterpreter}, //"frspx", OPTYPE_FPU, FL_RC_BIT_F}},
{64, &JitIL::FallBackToInterpreter}, //"mcrfs", OPTYPE_SYSTEMFP, 0}},
{583, &JitIL::FallBackToInterpreter}, //"mffsx", OPTYPE_SYSTEMFP, 0}},
{70, &JitIL::FallBackToInterpreter}, //"mtfsb0x", OPTYPE_SYSTEMFP, 0, 2}},
{38, &JitIL::FallBackToInterpreter}, //"mtfsb1x", OPTYPE_SYSTEMFP, 0, 2}},
{134, &JitIL::FallBackToInterpreter}, //"mtfsfix", OPTYPE_SYSTEMFP, 0, 2}},
{711, &JitIL::FallBackToInterpreter}, //"mtfsfx", OPTYPE_SYSTEMFP, 0, 2}},
};
const GekkoOPTemplate table63_2[] = {
{18, &JitIL::FallBackToInterpreter}, //"fdivx", OPTYPE_FPU, FL_RC_BIT_F, 30}},
{20, &JitIL::FallBackToInterpreter}, //"fsubx", OPTYPE_FPU, FL_RC_BIT_F}},
{21, &JitIL::FallBackToInterpreter}, //"faddx", OPTYPE_FPU, FL_RC_BIT_F}},
{23, &JitIL::FallBackToInterpreter}, //"fselx", OPTYPE_FPU, FL_RC_BIT_F}},
{25, &JitIL::fp_arith_s}, //"fmulx", OPTYPE_FPU, FL_RC_BIT_F}},
{26, &JitIL::FallBackToInterpreter}, //"frsqrtex", OPTYPE_FPU, FL_RC_BIT_F}},
{28, &JitIL::fmaddXX}, //"fmsubx", OPTYPE_FPU, FL_RC_BIT_F}},
{29, &JitIL::fmaddXX}, //"fmaddx", OPTYPE_FPU, FL_RC_BIT_F}},
{30, &JitIL::fmaddXX}, //"fnmsubx", OPTYPE_FPU, FL_RC_BIT_F}},
{31, &JitIL::fmaddXX}, //"fnmaddx", OPTYPE_FPU, FL_RC_BIT_F}},
};
void JitIL::CompileInstruction(PPCAnalyst::CodeOp& op)
{
(this->*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(js.compilerPC);
}
#endif
info->compileCount++;
info->lastUse = js.compilerPC;
}
else
{
PanicAlert("Tried to compile illegal (or unknown) instruction %08x, at %08x", op.inst.hex,
js.compilerPC);
}
}
void JitIL::InitializeInstructionTables()
{
// once initialized, tables are read-only
static bool initialized = false;
if (initialized)
return;
// clear
for (auto& tpl : dynaOpTable)
{
tpl = &JitIL::FallBackToInterpreter;
}
for (auto& tpl : dynaOpTable59)
{
tpl = &JitIL::FallBackToInterpreter;
}
for (int i = 0; i < 1024; i++)
{
dynaOpTable4[i] = &JitIL::FallBackToInterpreter;
dynaOpTable19[i] = &JitIL::FallBackToInterpreter;
dynaOpTable31[i] = &JitIL::FallBackToInterpreter;
dynaOpTable63[i] = &JitIL::FallBackToInterpreter;
}
for (const auto& tpl : primarytable)
{
dynaOpTable[tpl.opcode] = tpl.Inst;
}
for (int i = 0; i < 32; i++)
{
int fill = i << 5;
for (const auto& tpl : table4_2)
{
int op = fill + tpl.opcode;
dynaOpTable4[op] = tpl.Inst;
}
}
for (int i = 0; i < 16; i++)
{
int fill = i << 6;
for (const auto& tpl : table4_3)
{
int op = fill + tpl.opcode;
dynaOpTable4[op] = tpl.Inst;
}
}
for (const auto& tpl : table4)
{
int op = tpl.opcode;
dynaOpTable4[op] = tpl.Inst;
}
for (const auto& tpl : table31)
{
int op = tpl.opcode;
dynaOpTable31[op] = tpl.Inst;
}
for (const auto& tpl : table19)
{
int op = tpl.opcode;
dynaOpTable19[op] = tpl.Inst;
}
for (const auto& tpl : table59)
{
int op = tpl.opcode;
dynaOpTable59[op] = tpl.Inst;
}
for (const auto& tpl : table63)
{
int op = tpl.opcode;
dynaOpTable63[op] = tpl.Inst;
}
for (int i = 0; i < 32; i++)
{
int fill = i << 5;
for (const auto& tpl : table63_2)
{
int op = fill + tpl.opcode;
dynaOpTable63[op] = tpl.Inst;
}
}
initialized = true;
}
File diff suppressed because it is too large Load Diff
-443
View File
@@ -1,443 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <array>
#include <cstddef>
#include <vector>
#include "Common/CommonTypes.h"
#include "Common/NonCopyable.h"
namespace IREmitter
{
enum Opcode
{
Nop = 0,
// "Zero-operand" operators
// Register load operators
LoadGReg,
LoadLink,
LoadCR,
LoadCarry,
LoadCTR,
LoadMSR,
LoadGQR,
// Unary operators
// Integer unary operators
SExt8,
SExt16,
BSwap32,
BSwap16,
Cntlzw, // Count leading zeros
Not,
Load8, // These loads zext
Load16,
Load32,
// CR conversions
ConvertFromFastCR,
ConvertToFastCR,
// Branches
BranchUncond,
// Register store operators
StoreGReg,
StoreCR,
StoreLink,
StoreCarry,
StoreCTR,
StoreMSR,
StoreFPRF,
StoreGQR,
StoreSRR,
// Branch conditions
FastCRSOSet,
FastCREQSet,
FastCRGTSet,
FastCRLTSet,
// Arbitrary interpreter instruction
FallBackToInterpreter,
// Binary operators
// Commutative integer operators
Add,
Mul,
And,
Or,
Xor,
// Non-commutative integer operators
MulHighUnsigned,
Sub,
Shl, // Note that shifts ignore bits above the bottom 5
Shrl,
Sarl,
Rol,
ICmpCRSigned, // CR for signed int compare
ICmpCRUnsigned, // CR for unsigned int compare
ICmpEq, // One if equal, zero otherwise
ICmpNe,
ICmpUgt, // One if op1 > op2, zero otherwise
ICmpUlt,
ICmpUge,
ICmpUle,
ICmpSgt, // One if op1 > op2, zero otherwise
ICmpSlt,
ICmpSge,
ICmpSle, // Opposite of sgt
// Memory store operators
Store8,
Store16,
Store32,
BranchCond,
// Floating-point
// There are three floating-point formats: single, double,
// and packed. For any operation where the format of the
// operand isn't known, the ForceTo* operations are used;
// these are folded into the appropriate conversion
// (or no conversion) depending on the type of the operand.
// The "mreg" format is a pair of doubles; this is the
// most general possible represenation which is used
// in the register state.
// This might seem like overkill, but the semantics require
// having the different formats.
// FIXME: Check the accuracy of the mapping:
// 1. Is paired arithmetic always rounded to single-precision
// first, or does it do double-to-single like the
// single-precision instructions?
// 2. The implementation of madd is slightly off, and
// the implementation of fmuls is very slightly off;
// likely nothing cares, though.
FResult_Start,
LoadSingle,
LoadDouble,
LoadPaired, // This handles quantizers itself
DoubleToSingle,
DupSingleToMReg,
DupSingleToPacked,
InsertDoubleInMReg,
ExpandPackedToMReg,
CompactMRegToPacked,
LoadFReg,
LoadFRegDENToZero,
FSMul,
FSAdd,
FSSub,
FSNeg,
FPAdd,
FPMul,
FPSub,
FPNeg,
FDMul,
FDAdd,
FDSub,
FDNeg,
FPMerge00,
FPMerge01,
FPMerge10,
FPMerge11,
FPDup0,
FPDup1,
FResult_End,
StorePaired,
StoreSingle,
StoreDouble,
StoreFReg,
FDCmpCR,
// "Trinary" operators
// FIXME: Need to change representation!
// Select, // Equivalent to C "Op1 ? Op2 : Op3"
// Integer constants
CInt16,
CInt32,
// Funny PPC "branches"
SystemCall,
RFIExit,
InterpreterBranch,
IdleBranch, // branch operation belonging to idle loop
ShortIdleLoop, // Idle loop seen in homebrew like Wii mahjong,
// just a branch
// used for exception checking, at least until someone
// has a better idea of integrating it
FPExceptionCheck,
DSIExceptionCheck,
ExtExceptionCheck,
BreakPointCheck,
// "Opcode" representing a register too far away to
// reference directly; this is a size optimization
Tramp,
// "Opcode"s representing the start and end
BlockStart,
BlockEnd,
// used for debugging
Int3
};
using Inst = u32;
using InstLoc = Inst*;
constexpr u32 getOpcode(Inst i)
{
return i & 255;
}
constexpr bool isImm(Inst i)
{
return getOpcode(i) >= CInt16 && getOpcode(i) <= CInt32;
}
constexpr bool isICmp(Inst i)
{
return getOpcode(i) >= ICmpEq && getOpcode(i) <= ICmpSle;
}
constexpr bool isFResult(Inst i)
{
return getOpcode(i) > FResult_Start && getOpcode(i) < FResult_End;
}
InstLoc inline getOp1(InstLoc i)
{
i = i - 1 - ((*i >> 8) & 255);
if (getOpcode(*i) == Tramp)
{
i = i - 1 - (*i >> 8);
}
return i;
}
InstLoc inline getOp2(InstLoc i)
{
i = i - 1 - ((*i >> 16) & 255);
if (getOpcode(*i) == Tramp)
{
i = i - 1 - (*i >> 8);
}
return i;
}
class IRBuilder final : private NonCopyable
{
public:
IRBuilder();
void Reset();
InstLoc EmitIntConst(unsigned value) { return EmitIntConst64(value); }
InstLoc EmitIntConst64(u64 value);
InstLoc EmitStoreLink(InstLoc val) { return FoldUOp(StoreLink, val); }
InstLoc EmitBranchUncond(InstLoc val) { return FoldUOp(BranchUncond, val); }
InstLoc EmitBranchCond(InstLoc check, InstLoc dest) { return FoldBiOp(BranchCond, check, dest); }
InstLoc EmitIdleBranch(InstLoc check, InstLoc dest) { return FoldBiOp(IdleBranch, check, dest); }
InstLoc EmitLoadCR(unsigned crreg) { return FoldZeroOp(LoadCR, crreg); }
InstLoc EmitStoreCR(InstLoc value, unsigned crreg) { return FoldUOp(StoreCR, value, crreg); }
InstLoc EmitLoadLink() { return FoldZeroOp(LoadLink, 0); }
InstLoc EmitLoadMSR() { return FoldZeroOp(LoadMSR, 0); }
InstLoc EmitStoreMSR(InstLoc val, InstLoc pc) { return FoldBiOp(StoreMSR, val, pc); }
InstLoc EmitStoreFPRF(InstLoc value) { return FoldUOp(StoreFPRF, value); }
InstLoc EmitLoadGReg(unsigned reg) { return FoldZeroOp(LoadGReg, reg); }
InstLoc EmitStoreGReg(InstLoc value, unsigned reg) { return FoldUOp(StoreGReg, value, reg); }
InstLoc EmitNot(InstLoc op1) { return FoldUOp(Not, op1); }
InstLoc EmitAnd(InstLoc op1, InstLoc op2) { return FoldBiOp(And, op1, op2); }
InstLoc EmitXor(InstLoc op1, InstLoc op2) { return FoldBiOp(Xor, op1, op2); }
InstLoc EmitSub(InstLoc op1, InstLoc op2) { return FoldBiOp(Sub, op1, op2); }
InstLoc EmitOr(InstLoc op1, InstLoc op2) { return FoldBiOp(Or, op1, op2); }
InstLoc EmitAdd(InstLoc op1, InstLoc op2) { return FoldBiOp(Add, op1, op2); }
InstLoc EmitMul(InstLoc op1, InstLoc op2) { return FoldBiOp(Mul, op1, op2); }
InstLoc EmitMulHighUnsigned(InstLoc op1, InstLoc op2)
{
return FoldBiOp(MulHighUnsigned, op1, op2);
}
InstLoc EmitRol(InstLoc op1, InstLoc op2) { return FoldBiOp(Rol, op1, op2); }
InstLoc EmitShl(InstLoc op1, InstLoc op2) { return FoldBiOp(Shl, op1, op2); }
InstLoc EmitShrl(InstLoc op1, InstLoc op2) { return FoldBiOp(Shrl, op1, op2); }
InstLoc EmitSarl(InstLoc op1, InstLoc op2) { return FoldBiOp(Sarl, op1, op2); }
InstLoc EmitLoadCTR() { return FoldZeroOp(LoadCTR, 0); }
InstLoc EmitStoreCTR(InstLoc op1) { return FoldUOp(StoreCTR, op1); }
InstLoc EmitICmpEq(InstLoc op1, InstLoc op2) { return FoldBiOp(ICmpEq, op1, op2); }
InstLoc EmitICmpNe(InstLoc op1, InstLoc op2) { return FoldBiOp(ICmpNe, op1, op2); }
InstLoc EmitICmpUgt(InstLoc op1, InstLoc op2) { return FoldBiOp(ICmpUgt, op1, op2); }
InstLoc EmitICmpUlt(InstLoc op1, InstLoc op2) { return FoldBiOp(ICmpUlt, op1, op2); }
InstLoc EmitICmpSgt(InstLoc op1, InstLoc op2) { return FoldBiOp(ICmpSgt, op1, op2); }
InstLoc EmitICmpSlt(InstLoc op1, InstLoc op2) { return FoldBiOp(ICmpSlt, op1, op2); }
InstLoc EmitICmpSge(InstLoc op1, InstLoc op2) { return FoldBiOp(ICmpSge, op1, op2); }
InstLoc EmitICmpSle(InstLoc op1, InstLoc op2) { return FoldBiOp(ICmpSle, op1, op2); }
InstLoc EmitLoad8(InstLoc op1) { return FoldUOp(Load8, op1); }
InstLoc EmitLoad16(InstLoc op1) { return FoldUOp(Load16, op1); }
InstLoc EmitLoad32(InstLoc op1) { return FoldUOp(Load32, op1); }
InstLoc EmitStore8(InstLoc op1, InstLoc op2) { return FoldBiOp(Store8, op1, op2); }
InstLoc EmitStore16(InstLoc op1, InstLoc op2) { return FoldBiOp(Store16, op1, op2); }
InstLoc EmitStore32(InstLoc op1, InstLoc op2) { return FoldBiOp(Store32, op1, op2); }
InstLoc EmitSExt16(InstLoc op1) { return FoldUOp(SExt16, op1); }
InstLoc EmitSExt8(InstLoc op1) { return FoldUOp(SExt8, op1); }
InstLoc EmitCntlzw(InstLoc op1) { return FoldUOp(Cntlzw, op1); }
InstLoc EmitICmpCRSigned(InstLoc op1, InstLoc op2) { return FoldBiOp(ICmpCRSigned, op1, op2); }
InstLoc EmitICmpCRUnsigned(InstLoc op1, InstLoc op2)
{
return FoldBiOp(ICmpCRUnsigned, op1, op2);
}
InstLoc EmitConvertFromFastCR(InstLoc op1) { return FoldUOp(ConvertFromFastCR, op1); }
InstLoc EmitConvertToFastCR(InstLoc op1) { return FoldUOp(ConvertToFastCR, op1); }
InstLoc EmitFastCRSOSet(InstLoc op1) { return FoldUOp(FastCRSOSet, op1); }
InstLoc EmitFastCREQSet(InstLoc op1) { return FoldUOp(FastCREQSet, op1); }
InstLoc EmitFastCRLTSet(InstLoc op1) { return FoldUOp(FastCRLTSet, op1); }
InstLoc EmitFastCRGTSet(InstLoc op1) { return FoldUOp(FastCRGTSet, op1); }
InstLoc EmitFallBackToInterpreter(InstLoc op1, InstLoc op2)
{
return FoldBiOp(FallBackToInterpreter, op1, op2);
}
InstLoc EmitInterpreterBranch() { return FoldZeroOp(InterpreterBranch, 0); }
InstLoc EmitLoadCarry() { return FoldZeroOp(LoadCarry, 0); }
InstLoc EmitStoreCarry(InstLoc op1) { return FoldUOp(StoreCarry, op1); }
InstLoc EmitSystemCall(InstLoc pc) { return FoldUOp(SystemCall, pc); }
InstLoc EmitFPExceptionCheck(InstLoc pc) { return EmitUOp(FPExceptionCheck, pc); }
InstLoc EmitDSIExceptionCheck(InstLoc pc) { return EmitUOp(DSIExceptionCheck, pc); }
InstLoc EmitExtExceptionCheck(InstLoc pc) { return EmitUOp(ExtExceptionCheck, pc); }
InstLoc EmitBreakPointCheck(InstLoc pc) { return EmitUOp(BreakPointCheck, pc); }
InstLoc EmitRFIExit() { return FoldZeroOp(RFIExit, 0); }
InstLoc EmitShortIdleLoop(InstLoc pc) { return FoldUOp(ShortIdleLoop, pc); }
InstLoc EmitLoadSingle(InstLoc addr) { return FoldUOp(LoadSingle, addr); }
InstLoc EmitLoadDouble(InstLoc addr) { return FoldUOp(LoadDouble, addr); }
InstLoc EmitLoadPaired(InstLoc addr, unsigned quantReg)
{
return FoldUOp(LoadPaired, addr, quantReg);
}
InstLoc EmitStoreSingle(InstLoc value, InstLoc addr)
{
return FoldBiOp(StoreSingle, value, addr);
}
InstLoc EmitStoreDouble(InstLoc value, InstLoc addr)
{
return FoldBiOp(StoreDouble, value, addr);
}
InstLoc EmitStorePaired(InstLoc value, InstLoc addr, unsigned quantReg)
{
return FoldBiOp(StorePaired, value, addr, quantReg);
}
InstLoc EmitLoadFReg(unsigned freg) { return FoldZeroOp(LoadFReg, freg); }
InstLoc EmitLoadFRegDENToZero(unsigned freg) { return FoldZeroOp(LoadFRegDENToZero, freg); }
InstLoc EmitStoreFReg(InstLoc val, unsigned freg) { return FoldUOp(StoreFReg, val, freg); }
InstLoc EmitDupSingleToMReg(InstLoc val) { return FoldUOp(DupSingleToMReg, val); }
InstLoc EmitDupSingleToPacked(InstLoc val) { return FoldUOp(DupSingleToPacked, val); }
InstLoc EmitInsertDoubleInMReg(InstLoc val, InstLoc reg)
{
return FoldBiOp(InsertDoubleInMReg, val, reg);
}
InstLoc EmitExpandPackedToMReg(InstLoc val) { return FoldUOp(ExpandPackedToMReg, val); }
InstLoc EmitCompactMRegToPacked(InstLoc val) { return FoldUOp(CompactMRegToPacked, val); }
InstLoc EmitFSMul(InstLoc op1, InstLoc op2) { return FoldBiOp(FSMul, op1, op2); }
InstLoc EmitFSAdd(InstLoc op1, InstLoc op2) { return FoldBiOp(FSAdd, op1, op2); }
InstLoc EmitFSSub(InstLoc op1, InstLoc op2) { return FoldBiOp(FSSub, op1, op2); }
InstLoc EmitFSNeg(InstLoc op1) { return FoldUOp(FSNeg, op1); }
InstLoc EmitFDMul(InstLoc op1, InstLoc op2) { return FoldBiOp(FDMul, op1, op2); }
InstLoc EmitFDAdd(InstLoc op1, InstLoc op2) { return FoldBiOp(FDAdd, op1, op2); }
InstLoc EmitFDSub(InstLoc op1, InstLoc op2) { return FoldBiOp(FDSub, op1, op2); }
InstLoc EmitFDNeg(InstLoc op1) { return FoldUOp(FDNeg, op1); }
InstLoc EmitFPAdd(InstLoc op1, InstLoc op2) { return FoldBiOp(FPAdd, op1, op2); }
InstLoc EmitFPMul(InstLoc op1, InstLoc op2) { return FoldBiOp(FPMul, op1, op2); }
InstLoc EmitFPSub(InstLoc op1, InstLoc op2) { return FoldBiOp(FPSub, op1, op2); }
InstLoc EmitFPMerge00(InstLoc op1, InstLoc op2) { return FoldBiOp(FPMerge00, op1, op2); }
InstLoc EmitFPMerge01(InstLoc op1, InstLoc op2) { return FoldBiOp(FPMerge01, op1, op2); }
InstLoc EmitFPMerge10(InstLoc op1, InstLoc op2) { return FoldBiOp(FPMerge10, op1, op2); }
InstLoc EmitFPMerge11(InstLoc op1, InstLoc op2) { return FoldBiOp(FPMerge11, op1, op2); }
InstLoc EmitFPDup0(InstLoc op1) { return FoldUOp(FPDup0, op1); }
InstLoc EmitFPDup1(InstLoc op1) { return FoldUOp(FPDup1, op1); }
InstLoc EmitFPNeg(InstLoc op1) { return FoldUOp(FPNeg, op1); }
InstLoc EmitDoubleToSingle(InstLoc op1) { return FoldUOp(DoubleToSingle, op1); }
InstLoc EmitFDCmpCR(InstLoc op1, InstLoc op2, int ordered)
{
return FoldBiOp(FDCmpCR, op1, op2, ordered);
}
InstLoc EmitLoadGQR(unsigned gqr) { return FoldZeroOp(LoadGQR, gqr); }
InstLoc EmitStoreGQR(InstLoc op1, unsigned gqr) { return FoldUOp(StoreGQR, op1, gqr); }
InstLoc EmitStoreSRR(InstLoc op1, unsigned srr) { return FoldUOp(StoreSRR, op1, srr); }
InstLoc EmitINT3() { return FoldZeroOp(Int3, 0); }
void StartBackPass() { curReadPtr = InstList.data() + InstList.size(); }
void StartForwardPass() { curReadPtr = InstList.data(); }
InstLoc ReadForward() { return curReadPtr++; }
InstLoc ReadBackward() { return --curReadPtr; }
InstLoc getFirstInst() { return InstList.data(); }
size_t getNumInsts() const { return InstList.size(); }
unsigned int GetImmValue(InstLoc I) const { return (u32)GetImmValue64(I); }
u64 GetImmValue64(InstLoc I) const;
void SetMarkUsed(InstLoc I);
bool IsMarkUsed(InstLoc I) const;
void WriteToFile(u64 codeHash);
private:
void InvalidateCaches();
InstLoc EmitZeroOp(unsigned Opcode, unsigned extra);
InstLoc EmitUOp(unsigned OpCode, InstLoc Op1, unsigned extra = 0);
InstLoc EmitBiOp(unsigned OpCode, InstLoc Op1, InstLoc Op2, unsigned extra = 0);
InstLoc FoldAdd(InstLoc Op1, InstLoc Op2);
InstLoc FoldSub(InstLoc Op1, InstLoc Op2);
InstLoc FoldMul(InstLoc Op1, InstLoc Op2);
InstLoc FoldMulHighUnsigned(InstLoc Op1, InstLoc Op2);
InstLoc FoldAnd(InstLoc Op1, InstLoc Op2);
InstLoc FoldOr(InstLoc Op1, InstLoc Op2);
InstLoc FoldRol(InstLoc Op1, InstLoc Op2);
InstLoc FoldShl(InstLoc Op1, InstLoc Op2);
InstLoc FoldShrl(InstLoc Op1, InstLoc Op2);
InstLoc FoldXor(InstLoc Op1, InstLoc Op2);
InstLoc FoldBranchCond(InstLoc Op1, InstLoc Op2);
InstLoc FoldICmp(unsigned Opcode, InstLoc Op1, InstLoc Op2);
InstLoc FoldICmpCRSigned(InstLoc Op1, InstLoc Op2);
InstLoc FoldICmpCRUnsigned(InstLoc Op1, InstLoc Op2);
InstLoc FoldDoubleBiOp(unsigned Opcode, InstLoc Op1, InstLoc Op2);
InstLoc FoldFallBackToInterpreter(InstLoc Op1, InstLoc Op2);
InstLoc FoldZeroOp(unsigned Opcode, unsigned extra);
InstLoc FoldUOp(unsigned OpCode, InstLoc Op1, unsigned extra = 0);
InstLoc FoldBiOp(unsigned OpCode, InstLoc Op1, InstLoc Op2, unsigned extra = 0);
unsigned ComputeKnownZeroBits(InstLoc I) const;
bool isSameValue(InstLoc Op1, InstLoc Op2) const;
unsigned getComplexity(InstLoc I) const;
unsigned getNumberOfOperands(InstLoc I) const;
void simplifyCommutative(unsigned Opcode, InstLoc& Op1, InstLoc& Op2);
bool maskedValueIsZero(InstLoc Op1, InstLoc Op2) const;
InstLoc isNeg(InstLoc I) const;
std::vector<Inst> InstList; // FIXME: We must ensure this is continuous!
std::vector<bool> MarkUsed; // Used for IRWriter
std::vector<u64> ConstList;
InstLoc curReadPtr;
std::array<InstLoc, 32> GRegCache;
std::array<InstLoc, 32> GRegCacheStore;
std::array<InstLoc, 32> FRegCache;
std::array<InstLoc, 32> FRegCacheStore;
InstLoc CarryCache;
InstLoc CarryCacheStore;
InstLoc CTRCache;
InstLoc CTRCacheStore;
std::array<InstLoc, 8> CRCache;
std::array<InstLoc, 8> CRCacheStore;
};
} // namespace IREmitter
@@ -1,130 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include "Common/CommonTypes.h"
#include "Core/PowerPC/Gekko.h"
#include "Core/PowerPC/Jit64Common/Jit64Base.h"
#include "Core/PowerPC/JitILCommon/IR.h"
#include "Core/PowerPC/PPCAnalyst.h"
class JitILBase : public Jitx86Base
{
public:
JitILBase() : code_buffer(32000) {}
~JitILBase() {}
virtual void Jit(u32 em_address) = 0;
virtual const CommonAsmRoutinesBase* GetAsmRoutines() = 0;
// OPCODES
virtual void FallBackToInterpreter(UGeckoInstruction inst) = 0;
virtual void DoNothing(UGeckoInstruction inst) = 0;
virtual void HLEFunction(UGeckoInstruction inst) = 0;
virtual void DynaRunTable4(UGeckoInstruction _inst) = 0;
virtual void DynaRunTable19(UGeckoInstruction _inst) = 0;
virtual void DynaRunTable31(UGeckoInstruction _inst) = 0;
virtual void DynaRunTable59(UGeckoInstruction _inst) = 0;
virtual void DynaRunTable63(UGeckoInstruction _inst) = 0;
// Branches
void sc(UGeckoInstruction inst);
void rfi(UGeckoInstruction inst);
void bx(UGeckoInstruction inst);
void bcx(UGeckoInstruction inst);
void bcctrx(UGeckoInstruction inst);
void bclrx(UGeckoInstruction inst);
// LoadStore
void lXzx(UGeckoInstruction inst);
void lhax(UGeckoInstruction inst);
void lhaux(UGeckoInstruction inst);
void stXx(UGeckoInstruction inst);
void lmw(UGeckoInstruction inst);
void stmw(UGeckoInstruction inst);
void stX(UGeckoInstruction inst); // stw sth stb
void lXz(UGeckoInstruction inst);
void lbzu(UGeckoInstruction inst);
void lha(UGeckoInstruction inst);
void lhau(UGeckoInstruction inst);
// System Registers
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 dcbst(UGeckoInstruction inst);
void dcbz(UGeckoInstruction inst);
void icbi(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 reg_imm(UGeckoInstruction inst);
void ps_arith(UGeckoInstruction inst); // aggregate
void ps_mergeXX(UGeckoInstruction inst);
void ps_maddXX(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 lfsu(UGeckoInstruction inst);
void lfd(UGeckoInstruction inst);
void lfdu(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 rlwinmx(UGeckoInstruction inst);
void rlwimix(UGeckoInstruction inst);
void rlwnmx(UGeckoInstruction inst);
void negx(UGeckoInstruction inst);
void slwx(UGeckoInstruction inst);
void srwx(UGeckoInstruction inst);
void lfsx(UGeckoInstruction inst);
void subfic(UGeckoInstruction inst);
void subfcx(UGeckoInstruction inst);
void subfx(UGeckoInstruction inst);
void subfex(UGeckoInstruction inst);
protected:
// The default code buffer. We keep it around to not have to alloc/dealloc a
// large chunk of memory for each recompiled block.
PPCAnalyst::CodeBuffer code_buffer;
IREmitter::IRBuilder ibuild;
};
@@ -1,217 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/PowerPC/JitILCommon/JitILBase.h"
#include "Common/CommonTypes.h"
#include "Core/ConfigManager.h"
#include "Core/PowerPC/Gekko.h"
#include "Core/PowerPC/PowerPC.h"
// The branches are known good, or at least reasonably good.
// No need for a disable-mechanism.
// 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 FallBackToInterpreter(inst); ibuild.EmitInterpreterBranch(); return;
#define NORMALBRANCH_START
void JitILBase::sc(UGeckoInstruction inst)
{
ibuild.EmitSystemCall(ibuild.EmitIntConst(js.compilerPC));
}
void JitILBase::rfi(UGeckoInstruction inst)
{
ibuild.EmitRFIExit();
}
void JitILBase::bx(UGeckoInstruction inst)
{
NORMALBRANCH_START
INSTRUCTION_START;
// We must always process the following sentence
// even if the blocks are merged by PPCAnalyst::Flatten().
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
// If this is not the last instruction of a block,
// we will skip the rest process.
// Because PPCAnalyst::Flatten() merged the blocks.
if (!js.isLastInstruction)
{
return;
}
u32 destination;
if (inst.AA)
destination = SignExt26(inst.LI << 2);
else
destination = js.compilerPC + SignExt26(inst.LI << 2);
if (destination == js.compilerPC)
{
ibuild.EmitShortIdleLoop(ibuild.EmitIntConst(js.compilerPC));
return;
}
ibuild.EmitBranchUncond(ibuild.EmitIntConst(destination));
}
static IREmitter::InstLoc EmitCRTest(IREmitter::IRBuilder& ibuild, UGeckoInstruction inst)
{
IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2);
IREmitter::InstLoc CRTest = nullptr;
switch (3 - (inst.BI & 3))
{
case CR_SO_BIT:
CRTest = ibuild.EmitFastCRSOSet(CRReg);
break;
case CR_EQ_BIT:
CRTest = ibuild.EmitFastCREQSet(CRReg);
break;
case CR_GT_BIT:
CRTest = ibuild.EmitFastCRGTSet(CRReg);
break;
case CR_LT_BIT:
CRTest = ibuild.EmitFastCRLTSet(CRReg);
break;
}
if (!(inst.BO & 8))
CRTest = ibuild.EmitXor(CRTest, ibuild.EmitIntConst(1));
return CRTest;
}
static IREmitter::InstLoc TestBranch(IREmitter::IRBuilder& ibuild, UGeckoInstruction inst)
{
IREmitter::InstLoc CRTest = nullptr, CTRTest = nullptr;
if ((inst.BO & 16) == 0) // Test a CR bit
{
CRTest = EmitCRTest(ibuild, inst);
}
if ((inst.BO & 4) == 0)
{
IREmitter::InstLoc c = ibuild.EmitLoadCTR();
c = ibuild.EmitSub(c, ibuild.EmitIntConst(1));
ibuild.EmitStoreCTR(c);
if (inst.BO & 2)
CTRTest = ibuild.EmitICmpEq(c, ibuild.EmitIntConst(0));
else
CTRTest = c;
}
IREmitter::InstLoc Test = CRTest;
if (CTRTest)
{
if (Test)
Test = ibuild.EmitAnd(Test, CTRTest);
else
Test = CTRTest;
}
if (!Test)
{
Test = ibuild.EmitIntConst(1);
}
return Test;
}
void JitILBase::bcx(UGeckoInstruction inst)
{
NORMALBRANCH_START
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
IREmitter::InstLoc Test = TestBranch(ibuild, inst);
u32 destination;
if (inst.AA)
destination = SignExt16(inst.BD << 2);
else
destination = js.compilerPC + SignExt16(inst.BD << 2);
// Idle skipping:
// The main Idle skipping is done in the LoadStore code, but there is an optimization here.
// If idle skipping is enabled, then this branch will only be reached when the branch is not
// taken.
// TODO: We shouldn't use debug reads here.
if (inst.hex == 0x4182fff8 &&
(PowerPC::HostRead_U32(js.compilerPC - 8) & 0xFFFF0000) == 0x800D0000 &&
(PowerPC::HostRead_U32(js.compilerPC - 4) == 0x28000000 ||
(SConfig::GetInstance().bWii && PowerPC::HostRead_U32(js.compilerPC - 4) == 0x2C000000)))
{
// Uh, Do nothing.
}
else
{
ibuild.EmitBranchCond(Test, ibuild.EmitIntConst(destination));
}
ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4));
}
void JitILBase::bcctrx(UGeckoInstruction inst)
{
NORMALBRANCH_START
if ((inst.BO & 4) == 0)
{
IREmitter::InstLoc c = ibuild.EmitLoadCTR();
c = ibuild.EmitSub(c, ibuild.EmitIntConst(1));
ibuild.EmitStoreCTR(c);
}
IREmitter::InstLoc test;
if ((inst.BO & 16) == 0) // Test a CR bit
{
test = EmitCRTest(ibuild, inst);
}
else
{
test = ibuild.EmitIntConst(1);
}
test = ibuild.EmitICmpEq(test, ibuild.EmitIntConst(0));
ibuild.EmitBranchCond(test, ibuild.EmitIntConst(js.compilerPC + 4));
IREmitter::InstLoc destination = ibuild.EmitLoadCTR();
destination = ibuild.EmitAnd(destination, ibuild.EmitIntConst(-4));
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
ibuild.EmitBranchUncond(destination);
}
void JitILBase::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);
}
@@ -1,125 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/PowerPC/JitILCommon/JitILBase.h"
#include "Common/Assert.h"
#include "Common/CommonTypes.h"
#include "Common/MsgHandler.h"
#include "Core/ConfigManager.h"
void JitILBase::fp_arith_s(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITFloatingPointOff);
FALLBACK_IF(inst.Rc || (inst.SUBOP5 != 25 && inst.SUBOP5 != 20 && inst.SUBOP5 != 21));
// Only the interpreter has "proper" support for (some) FP flags
FALLBACK_IF(inst.SUBOP5 == 25 && SConfig::GetInstance().bFPRF);
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA);
switch (inst.SUBOP5)
{
case 20: // sub
val = ibuild.EmitFDSub(val, ibuild.EmitLoadFReg(inst.FB));
break;
case 21: // add
val = ibuild.EmitFDAdd(val, ibuild.EmitLoadFReg(inst.FB));
break;
case 25: // mul
val = ibuild.EmitFDMul(val, ibuild.EmitLoadFReg(inst.FC));
break;
default:
_assert_msg_(DYNA_REC, 0, "fp_arith_s WTF!!!");
}
if (inst.OPCD == 59)
{
val = ibuild.EmitDoubleToSingle(val);
val = ibuild.EmitDupSingleToMReg(val);
}
else
{
val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD));
}
ibuild.EmitStoreFReg(val, inst.FD);
}
void JitILBase::fmaddXX(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITFloatingPointOff);
FALLBACK_IF(inst.Rc);
// Only the interpreter has "proper" support for (some) FP flags
FALLBACK_IF(inst.SUBOP5 == 29 && SConfig::GetInstance().bFPRF);
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA);
val = ibuild.EmitFDMul(val, ibuild.EmitLoadFReg(inst.FC));
if (inst.SUBOP5 & 1)
val = ibuild.EmitFDAdd(val, ibuild.EmitLoadFReg(inst.FB));
else
val = ibuild.EmitFDSub(val, ibuild.EmitLoadFReg(inst.FB));
if (inst.SUBOP5 & 2)
val = ibuild.EmitFDNeg(val);
if (inst.OPCD == 59)
{
val = ibuild.EmitDoubleToSingle(val);
val = ibuild.EmitDupSingleToMReg(val);
}
else
{
val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD));
}
ibuild.EmitStoreFReg(val, inst.FD);
}
void JitILBase::fmrx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITFloatingPointOff);
FALLBACK_IF(inst.Rc);
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FB);
val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD));
ibuild.EmitStoreFReg(val, inst.FD);
}
void JitILBase::fcmpX(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITFloatingPointOff);
IREmitter::InstLoc lhs, rhs, res;
lhs = ibuild.EmitLoadFReg(inst.FA);
rhs = ibuild.EmitLoadFReg(inst.FB);
int ordered = (inst.SUBOP10 == 32) ? 1 : 0;
res = ibuild.EmitFDCmpCR(lhs, rhs, ordered);
ibuild.EmitStoreFPRF(res);
ibuild.EmitStoreCR(ibuild.EmitConvertToFastCR(res), inst.CRFD);
}
void JitILBase::fsign(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITFloatingPointOff);
FALLBACK_IF(true);
// TODO
switch (inst.SUBOP10)
{
case 40: // fnegx
break;
case 264: // fabsx
break;
case 136: // fnabs
break;
default:
PanicAlert("fsign bleh");
break;
}
}
File diff suppressed because it is too large Load Diff
@@ -1,310 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/PowerPC/JitILCommon/JitILBase.h"
#include "Common/Assert.h"
#include "Common/CommonTypes.h"
#include "Core/ConfigManager.h"
#include "Core/HW/CPU.h"
#include "Core/PowerPC/PowerPC.h"
void JitILBase::lhax(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
IREmitter::InstLoc val = ibuild.EmitLoad16(addr);
val = ibuild.EmitSExt16(val);
ibuild.EmitStoreGReg(val, inst.RD);
}
void JitILBase::lhaux(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB);
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
IREmitter::InstLoc val = ibuild.EmitLoad16(addr);
val = ibuild.EmitSExt16(val);
ibuild.EmitStoreGReg(val, inst.RD);
ibuild.EmitStoreGReg(addr, inst.RA);
}
void JitILBase::lXz(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
if (inst.OPCD & 1)
ibuild.EmitStoreGReg(addr, inst.RA);
IREmitter::InstLoc val;
// Idle Skipping.
// TODO: This really should be done somewhere else. Either lower in the IR
// or higher in PPCAnalyst
// TODO: We shouldn't use debug reads here.
if (!CPU::IsStepping() && inst.OPCD == 32 && // Lwx
(inst.hex & 0xFFFF0000) == 0x800D0000 &&
(PowerPC::HostRead_U32(js.compilerPC + 4) == 0x28000000 ||
(SConfig::GetInstance().bWii && PowerPC::HostRead_U32(js.compilerPC + 4) == 0x2C000000)) &&
PowerPC::HostRead_U32(js.compilerPC + 8) == 0x4182fff8)
{
val = ibuild.EmitLoad32(addr);
ibuild.EmitIdleBranch(val, ibuild.EmitIntConst(js.compilerPC));
ibuild.EmitStoreGReg(val, inst.RD);
return;
}
switch (inst.OPCD & ~0x1)
{
case 32: // lwz
val = ibuild.EmitLoad32(addr);
break;
case 40: // lhz
val = ibuild.EmitLoad16(addr);
break;
case 34: // lbz
val = ibuild.EmitLoad8(addr);
break;
default:
PanicAlert("lXz: invalid access size");
val = nullptr;
break;
}
ibuild.EmitStoreGReg(val, inst.RD);
}
void JitILBase::lbzu(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff);
const IREmitter::InstLoc uAddress =
ibuild.EmitAdd(ibuild.EmitLoadGReg(inst.RA), ibuild.EmitIntConst((int)inst.SIMM_16));
const IREmitter::InstLoc temp = ibuild.EmitLoad8(uAddress);
ibuild.EmitStoreGReg(temp, inst.RD);
ibuild.EmitStoreGReg(uAddress, inst.RA);
}
void JitILBase::lha(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitIntConst((s32)(s16)inst.SIMM_16);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
IREmitter::InstLoc val = ibuild.EmitLoad16(addr);
val = ibuild.EmitSExt16(val);
ibuild.EmitStoreGReg(val, inst.RD);
}
void JitILBase::lhau(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitIntConst((s32)inst.SIMM_16);
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
IREmitter::InstLoc val = ibuild.EmitLoad16(addr);
val = ibuild.EmitSExt16(val);
ibuild.EmitStoreGReg(val, inst.RD);
ibuild.EmitStoreGReg(addr, inst.RA);
}
void JitILBase::lXzx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB);
if (inst.RA)
{
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
if (inst.SUBOP10 & 32)
ibuild.EmitStoreGReg(addr, inst.RA);
}
IREmitter::InstLoc val;
switch (inst.SUBOP10 & ~32)
{
default:
PanicAlert("lXzx: invalid access size");
case 23: // lwzx
val = ibuild.EmitLoad32(addr);
break;
case 279: // lhzx
val = ibuild.EmitLoad16(addr);
break;
case 87: // lbzx
val = ibuild.EmitLoad8(addr);
break;
}
ibuild.EmitStoreGReg(val, inst.RD);
}
void JitILBase::dcbst(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff);
// If the dcbst instruction is preceded by dcbt, it is flushing a prefetched
// memory location. Do not invalidate the JIT cache in this case as the memory
// will be the same.
// dcbt = 0x7c00022c
// TODO: We shouldn't use a debug read here; it should be possible to get the
// previous instruction from the JIT state.
FALLBACK_IF((PowerPC::HostRead_U32(js.compilerPC - 4) & 0x7c00022c) != 0x7c00022c);
}
// Zero cache line.
void JitILBase::dcbz(UGeckoInstruction inst)
{
FALLBACK_IF(true);
// TODO!
#if 0
if (SConfig::GetInstance().bJITOff || SConfig::GetInstance().bJITLoadStoreOff)
{
Default(inst);
return;
}
INSTRUCTION_START;
MOV(32, R(RSCRATCH), gpr.R(inst.RB));
if (inst.RA)
ADD(32, R(RSCRATCH), gpr.R(inst.RA));
AND(32, R(RSCRATCH), Imm32(~31));
PXOR(XMM0, R(XMM0));
MOVAPS(MComplex(RMEM, RSCRATCH, SCALE_1, 0), XMM0);
MOVAPS(MComplex(RMEM, RSCRATCH, SCALE_1, 16), XMM0);
#endif
}
void JitILBase::stX(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
IREmitter::InstLoc value = ibuild.EmitLoadGReg(inst.RS);
if (inst.RA)
addr = ibuild.EmitAdd(ibuild.EmitLoadGReg(inst.RA), addr);
if (inst.OPCD & 1)
ibuild.EmitStoreGReg(addr, inst.RA);
switch (inst.OPCD & ~1)
{
case 36: // stw
ibuild.EmitStore32(value, addr);
break;
case 44: // sth
ibuild.EmitStore16(value, addr);
break;
case 38: // stb
ibuild.EmitStore8(value, addr);
break;
default:
_assert_msg_(DYNA_REC, 0, "stX: Invalid access size.");
return;
}
}
void JitILBase::stXx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB);
IREmitter::InstLoc value = ibuild.EmitLoadGReg(inst.RS);
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
if (inst.SUBOP10 & 32)
ibuild.EmitStoreGReg(addr, inst.RA);
switch (inst.SUBOP10 & ~32)
{
case 151: // stw
ibuild.EmitStore32(value, addr);
break;
case 407: // sth
ibuild.EmitStore16(value, addr);
break;
case 215: // stb
ibuild.EmitStore8(value, addr);
break;
default:
_assert_msg_(DYNA_REC, 0, "stXx: Invalid store size.");
return;
}
}
// A few games use these heavily in video codecs. (GFZP01 @ 0x80020E18)
void JitILBase::lmw(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
for (int i = inst.RD; i < 32; i++)
{
IREmitter::InstLoc val = ibuild.EmitLoad32(addr);
ibuild.EmitStoreGReg(val, i);
addr = ibuild.EmitAdd(addr, ibuild.EmitIntConst(4));
}
}
void JitILBase::stmw(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
for (int i = inst.RD; i < 32; i++)
{
IREmitter::InstLoc val = ibuild.EmitLoadGReg(i);
ibuild.EmitStore32(val, addr);
addr = ibuild.EmitAdd(addr, ibuild.EmitIntConst(4));
}
}
void JitILBase::icbi(UGeckoInstruction inst)
{
FallBackToInterpreter(inst);
ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4));
}
@@ -1,139 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/PowerPC/JitILCommon/JitILBase.h"
#include "Common/CommonTypes.h"
// TODO: Add peephole optimizations for multiple consecutive lfd/lfs/stfd/stfs since they are so
// common,
// and pshufb could help a lot.
// Also add hacks for things like lfs/stfs the same reg consecutively, that is, simple memory moves.
void JitILBase::lfs(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreFloatingOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
IREmitter::InstLoc val = ibuild.EmitDupSingleToMReg(ibuild.EmitLoadSingle(addr));
ibuild.EmitStoreFReg(val, inst.FD);
}
void JitILBase::lfsu(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreFloatingOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
IREmitter::InstLoc val = ibuild.EmitDupSingleToMReg(ibuild.EmitLoadSingle(addr));
ibuild.EmitStoreFReg(val, inst.FD);
ibuild.EmitStoreGReg(addr, inst.RA);
}
void JitILBase::lfd(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreFloatingOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.RD);
val = ibuild.EmitInsertDoubleInMReg(ibuild.EmitLoadDouble(addr), val);
ibuild.EmitStoreFReg(val, inst.RD);
}
void JitILBase::lfdu(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreFloatingOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FD);
val = ibuild.EmitInsertDoubleInMReg(ibuild.EmitLoadDouble(addr), val);
ibuild.EmitStoreFReg(val, inst.FD);
ibuild.EmitStoreGReg(addr, inst.RA);
}
void JitILBase::stfd(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreFloatingOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.RS);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
if (inst.OPCD & 1)
ibuild.EmitStoreGReg(addr, inst.RA);
ibuild.EmitStoreDouble(val, addr);
}
void JitILBase::stfs(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreFloatingOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.RS);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
if (inst.OPCD & 1)
ibuild.EmitStoreGReg(addr, inst.RA);
val = ibuild.EmitDoubleToSingle(val);
ibuild.EmitStoreSingle(val, addr);
}
void JitILBase::stfsx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreFloatingOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB);
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.RS);
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
val = ibuild.EmitDoubleToSingle(val);
ibuild.EmitStoreSingle(val, addr);
}
void JitILBase::lfsx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStoreFloatingOff);
FALLBACK_IF(jo.memcheck);
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB), val;
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
val = ibuild.EmitDupSingleToMReg(ibuild.EmitLoadSingle(addr));
ibuild.EmitStoreFReg(val, inst.RD);
}
@@ -1,56 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/PowerPC/JitILCommon/JitILBase.h"
#include "Common/CommonTypes.h"
#include "Core/PowerPC/PowerPC.h"
void JitILBase::psq_st(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStorePairedOff);
FALLBACK_IF(jo.memcheck || inst.W);
// For performance, the AsmCommon routines assume address translation is on.
FALLBACK_IF(!UReg_MSR(MSR).DR);
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_12);
IREmitter::InstLoc val;
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
if (inst.OPCD == 61)
ibuild.EmitStoreGReg(addr, inst.RA);
val = ibuild.EmitLoadFReg(inst.RS);
val = ibuild.EmitCompactMRegToPacked(val);
ibuild.EmitStorePaired(val, addr, inst.I);
}
void JitILBase::psq_l(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITLoadStorePairedOff);
FALLBACK_IF(jo.memcheck || inst.W);
// For performance, the AsmCommon routines assume address translation is on.
FALLBACK_IF(!UReg_MSR(MSR).DR);
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_12);
IREmitter::InstLoc val;
if (inst.RA)
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
if (inst.OPCD == 57)
ibuild.EmitStoreGReg(addr, inst.RA);
val = ibuild.EmitLoadPaired(
addr,
inst.I | (inst.W << 3)); // The lower 3 bits is for GQR index. The next 1 bit is for inst.W
val = ibuild.EmitExpandPackedToMReg(val);
ibuild.EmitStoreFReg(val, inst.RD);
}

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