mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Remove JITIL
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -582,8 +582,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],
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
@@ -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
@@ -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
Reference in New Issue
Block a user