Merge pull request #11677 from AdmiralCurtiss/deglobal-jit

Avoid System::GetInstance() and ppcState global in Jit64 and CachedInterpreter.
This commit is contained in:
Admiral H. Curtiss 2023-03-25 14:52:46 +01:00 committed by GitHub
commit 6b44947488
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 292 additions and 184 deletions

View File

@ -20,6 +20,8 @@ struct CachedInterpreter::Instruction
using CommonCallback = void (*)(UGeckoInstruction); using CommonCallback = void (*)(UGeckoInstruction);
using ConditionalCallback = bool (*)(u32); using ConditionalCallback = bool (*)(u32);
using InterpreterCallback = void (*)(Interpreter&, UGeckoInstruction); using InterpreterCallback = void (*)(Interpreter&, UGeckoInstruction);
using CachedInterpreterCallback = void (*)(CachedInterpreter&, UGeckoInstruction);
using ConditionalCachedInterpreterCallback = bool (*)(CachedInterpreter&, u32);
Instruction() {} Instruction() {}
Instruction(const CommonCallback c, UGeckoInstruction i) Instruction(const CommonCallback c, UGeckoInstruction i)
@ -37,12 +39,25 @@ struct CachedInterpreter::Instruction
{ {
} }
Instruction(const CachedInterpreterCallback c, UGeckoInstruction i)
: cached_interpreter_callback(c), data(i.hex), type(Type::CachedInterpreter)
{
}
Instruction(const ConditionalCachedInterpreterCallback c, u32 d)
: conditional_cached_interpreter_callback(c), data(d),
type(Type::ConditionalCachedInterpreter)
{
}
enum class Type enum class Type
{ {
Abort, Abort,
Common, Common,
Conditional, Conditional,
Interpreter, Interpreter,
CachedInterpreter,
ConditionalCachedInterpreter,
}; };
union union
@ -50,13 +65,17 @@ struct CachedInterpreter::Instruction
const CommonCallback common_callback = nullptr; const CommonCallback common_callback = nullptr;
const ConditionalCallback conditional_callback; const ConditionalCallback conditional_callback;
const InterpreterCallback interpreter_callback; const InterpreterCallback interpreter_callback;
const CachedInterpreterCallback cached_interpreter_callback;
const ConditionalCachedInterpreterCallback conditional_cached_interpreter_callback;
}; };
u32 data = 0; u32 data = 0;
Type type = Type::Abort; Type type = Type::Abort;
}; };
CachedInterpreter::CachedInterpreter() = default; CachedInterpreter::CachedInterpreter(Core::System& system) : JitBase(system)
{
}
CachedInterpreter::~CachedInterpreter() = default; CachedInterpreter::~CachedInterpreter() = default;
@ -89,11 +108,12 @@ void CachedInterpreter::ExecuteOneBlock()
const u8* normal_entry = m_block_cache.Dispatch(); const u8* normal_entry = m_block_cache.Dispatch();
if (!normal_entry) if (!normal_entry)
{ {
Jit(PowerPC::ppcState.pc); Jit(m_ppc_state.pc);
return; return;
} }
const Instruction* code = reinterpret_cast<const Instruction*>(normal_entry); const Instruction* code = reinterpret_cast<const Instruction*>(normal_entry);
auto& interpreter = m_system.GetInterpreter();
for (; code->type != Instruction::Type::Abort; ++code) for (; code->type != Instruction::Type::Abort; ++code)
{ {
@ -109,8 +129,16 @@ void CachedInterpreter::ExecuteOneBlock()
break; break;
case Instruction::Type::Interpreter: case Instruction::Type::Interpreter:
code->interpreter_callback(Core::System::GetInstance().GetInterpreter(), code->interpreter_callback(interpreter, UGeckoInstruction(code->data));
UGeckoInstruction(code->data)); break;
case Instruction::Type::CachedInterpreter:
code->cached_interpreter_callback(*this, UGeckoInstruction(code->data));
break;
case Instruction::Type::ConditionalCachedInterpreter:
if (code->conditional_cached_interpreter_callback(*this, code->data))
return;
break; break;
default: default:
@ -123,9 +151,8 @@ void CachedInterpreter::ExecuteOneBlock()
void CachedInterpreter::Run() void CachedInterpreter::Run()
{ {
auto& system = Core::System::GetInstance(); auto& core_timing = m_system.GetCoreTiming();
auto& core_timing = system.GetCoreTiming(); auto& cpu = m_system.GetCPU();
auto& cpu = system.GetCPU();
const CPU::State* state_ptr = cpu.GetStatePtr(); const CPU::State* state_ptr = cpu.GetStatePtr();
while (cpu.GetState() == CPU::State::Running) while (cpu.GetState() == CPU::State::Running)
@ -137,96 +164,103 @@ void CachedInterpreter::Run()
do do
{ {
ExecuteOneBlock(); ExecuteOneBlock();
} while (PowerPC::ppcState.downcount > 0 && *state_ptr == CPU::State::Running); } while (m_ppc_state.downcount > 0 && *state_ptr == CPU::State::Running);
} }
} }
void CachedInterpreter::SingleStep() void CachedInterpreter::SingleStep()
{ {
// Enter new timing slice // Enter new timing slice
Core::System::GetInstance().GetCoreTiming().Advance(); m_system.GetCoreTiming().Advance();
ExecuteOneBlock(); ExecuteOneBlock();
} }
static void EndBlock(UGeckoInstruction data) void CachedInterpreter::EndBlock(CachedInterpreter& cached_interpreter, UGeckoInstruction data)
{ {
PowerPC::ppcState.pc = PowerPC::ppcState.npc; auto& ppc_state = cached_interpreter.m_ppc_state;
PowerPC::ppcState.downcount -= data.hex; ppc_state.pc = ppc_state.npc;
PowerPC::UpdatePerformanceMonitor(data.hex, 0, 0, PowerPC::ppcState); ppc_state.downcount -= data.hex;
PowerPC::UpdatePerformanceMonitor(data.hex, 0, 0, ppc_state);
} }
static void UpdateNumLoadStoreInstructions(UGeckoInstruction data) void CachedInterpreter::UpdateNumLoadStoreInstructions(CachedInterpreter& cached_interpreter,
UGeckoInstruction data)
{ {
PowerPC::UpdatePerformanceMonitor(0, data.hex, 0, PowerPC::ppcState); PowerPC::UpdatePerformanceMonitor(0, data.hex, 0, cached_interpreter.m_ppc_state);
} }
static void UpdateNumFloatingPointInstructions(UGeckoInstruction data) void CachedInterpreter::UpdateNumFloatingPointInstructions(CachedInterpreter& cached_interpreter,
UGeckoInstruction data)
{ {
PowerPC::UpdatePerformanceMonitor(0, 0, data.hex, PowerPC::ppcState); PowerPC::UpdatePerformanceMonitor(0, 0, data.hex, cached_interpreter.m_ppc_state);
} }
static void WritePC(UGeckoInstruction data) void CachedInterpreter::WritePC(CachedInterpreter& cached_interpreter, UGeckoInstruction data)
{ {
PowerPC::ppcState.pc = data.hex; auto& ppc_state = cached_interpreter.m_ppc_state;
PowerPC::ppcState.npc = data.hex + 4; ppc_state.pc = data.hex;
ppc_state.npc = data.hex + 4;
} }
static void WriteBrokenBlockNPC(UGeckoInstruction data) void CachedInterpreter::WriteBrokenBlockNPC(CachedInterpreter& cached_interpreter,
UGeckoInstruction data)
{ {
PowerPC::ppcState.npc = data.hex; cached_interpreter.m_ppc_state.npc = data.hex;
} }
static bool CheckFPU(u32 data) bool CachedInterpreter::CheckFPU(CachedInterpreter& cached_interpreter, u32 data)
{ {
if (!PowerPC::ppcState.msr.FP) auto& ppc_state = cached_interpreter.m_ppc_state;
if (!ppc_state.msr.FP)
{ {
PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE; ppc_state.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
PowerPC::CheckExceptions(); PowerPC::CheckExceptions();
PowerPC::ppcState.downcount -= data; ppc_state.downcount -= data;
return true; return true;
} }
return false; return false;
} }
static bool CheckDSI(u32 data) bool CachedInterpreter::CheckDSI(CachedInterpreter& cached_interpreter, u32 data)
{ {
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) auto& ppc_state = cached_interpreter.m_ppc_state;
if (ppc_state.Exceptions & EXCEPTION_DSI)
{ {
PowerPC::CheckExceptions(); PowerPC::CheckExceptions();
PowerPC::ppcState.downcount -= data; ppc_state.downcount -= data;
return true; return true;
} }
return false; return false;
} }
static bool CheckProgramException(u32 data) bool CachedInterpreter::CheckProgramException(CachedInterpreter& cached_interpreter, u32 data)
{ {
if (PowerPC::ppcState.Exceptions & EXCEPTION_PROGRAM) auto& ppc_state = cached_interpreter.m_ppc_state;
if (ppc_state.Exceptions & EXCEPTION_PROGRAM)
{ {
PowerPC::CheckExceptions(); PowerPC::CheckExceptions();
PowerPC::ppcState.downcount -= data; ppc_state.downcount -= data;
return true; return true;
} }
return false; return false;
} }
static bool CheckBreakpoint(u32 data) bool CachedInterpreter::CheckBreakpoint(CachedInterpreter& cached_interpreter, u32 data)
{ {
PowerPC::CheckBreakPoints(); PowerPC::CheckBreakPoints();
auto& system = Core::System::GetInstance(); if (cached_interpreter.m_system.GetCPU().GetState() != CPU::State::Running)
if (system.GetCPU().GetState() != CPU::State::Running)
{ {
PowerPC::ppcState.downcount -= data; cached_interpreter.m_ppc_state.downcount -= data;
return true; return true;
} }
return false; return false;
} }
static bool CheckIdle(u32 idle_pc) bool CachedInterpreter::CheckIdle(CachedInterpreter& cached_interpreter, u32 idle_pc)
{ {
if (PowerPC::ppcState.npc == idle_pc) if (cached_interpreter.m_ppc_state.npc == idle_pc)
{ {
Core::System::GetInstance().GetCoreTiming().Idle(); cached_interpreter.m_system.GetCoreTiming().Idle();
} }
return false; return false;
} }
@ -255,20 +289,20 @@ void CachedInterpreter::Jit(u32 address)
} }
const u32 nextPC = const u32 nextPC =
analyzer.Analyze(PowerPC::ppcState.pc, &code_block, &m_code_buffer, m_code_buffer.size()); analyzer.Analyze(m_ppc_state.pc, &code_block, &m_code_buffer, m_code_buffer.size());
if (code_block.m_memory_exception) if (code_block.m_memory_exception)
{ {
// Address of instruction could not be translated // Address of instruction could not be translated
PowerPC::ppcState.npc = nextPC; m_ppc_state.npc = nextPC;
PowerPC::ppcState.Exceptions |= EXCEPTION_ISI; m_ppc_state.Exceptions |= EXCEPTION_ISI;
PowerPC::CheckExceptions(); PowerPC::CheckExceptions();
WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", nextPC); WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", nextPC);
return; return;
} }
JitBlock* b = m_block_cache.AllocateBlock(PowerPC::ppcState.pc); JitBlock* b = m_block_cache.AllocateBlock(m_ppc_state.pc);
js.blockStart = PowerPC::ppcState.pc; js.blockStart = m_ppc_state.pc;
js.firstFPInstructionFound = false; js.firstFPInstructionFound = false;
js.fifoBytesSinceCheck = 0; js.fifoBytesSinceCheck = 0;
js.downcountAmount = 0; js.downcountAmount = 0;

View File

@ -13,7 +13,11 @@
class CachedInterpreter : public JitBase class CachedInterpreter : public JitBase
{ {
public: public:
CachedInterpreter(); explicit CachedInterpreter(Core::System& system);
CachedInterpreter(const CachedInterpreter&) = delete;
CachedInterpreter(CachedInterpreter&&) = delete;
CachedInterpreter& operator=(const CachedInterpreter&) = delete;
CachedInterpreter& operator=(CachedInterpreter&&) = delete;
~CachedInterpreter(); ~CachedInterpreter();
void Init() override; void Init() override;
@ -39,6 +43,19 @@ private:
bool HandleFunctionHooking(u32 address); bool HandleFunctionHooking(u32 address);
static void EndBlock(CachedInterpreter& cached_interpreter, UGeckoInstruction data);
static void UpdateNumLoadStoreInstructions(CachedInterpreter& cached_interpreter,
UGeckoInstruction data);
static void UpdateNumFloatingPointInstructions(CachedInterpreter& cached_interpreter,
UGeckoInstruction data);
static void WritePC(CachedInterpreter& cached_interpreter, UGeckoInstruction data);
static void WriteBrokenBlockNPC(CachedInterpreter& cached_interpreter, UGeckoInstruction data);
static bool CheckFPU(CachedInterpreter& cached_interpreter, u32 data);
static bool CheckDSI(CachedInterpreter& cached_interpreter, u32 data);
static bool CheckProgramException(CachedInterpreter& cached_interpreter, u32 data);
static bool CheckBreakpoint(CachedInterpreter& cached_interpreter, u32 data);
static bool CheckIdle(CachedInterpreter& cached_interpreter, u32 idle_pc);
BlockCache m_block_cache{*this}; BlockCache m_block_cache{*this};
std::vector<Instruction> m_code; std::vector<Instruction> m_code;
}; };

View File

@ -116,7 +116,7 @@ using namespace PowerPC;
and such, but it's currently limited to integer ops only. This can definitely be made better. and such, but it's currently limited to integer ops only. This can definitely be made better.
*/ */
Jit64::Jit64() : QuantizedMemoryRoutines(*this) Jit64::Jit64(Core::System& system) : JitBase(system), QuantizedMemoryRoutines(*this)
{ {
} }
@ -136,12 +136,11 @@ bool Jit64::HandleFault(uintptr_t access_address, SContext* ctx)
// Only instructions that access I/O will get these, and there won't be that // Only instructions that access I/O will get these, and there won't be that
// many of them in a typical program/game. // many of them in a typical program/game.
auto& system = Core::System::GetInstance(); auto& memory = m_system.GetMemory();
auto& memory = system.GetMemory();
if (memory.IsAddressInFastmemArea(reinterpret_cast<u8*>(access_address))) if (memory.IsAddressInFastmemArea(reinterpret_cast<u8*>(access_address)))
{ {
auto& ppc_state = system.GetPPCState(); auto& ppc_state = m_system.GetPPCState();
const uintptr_t memory_base = reinterpret_cast<uintptr_t>( const uintptr_t memory_base = reinterpret_cast<uintptr_t>(
ppc_state.msr.DR ? memory.GetLogicalBase() : memory.GetPhysicalBase()); ppc_state.msr.DR ? memory.GetLogicalBase() : memory.GetPhysicalBase());
@ -253,8 +252,7 @@ void Jit64::Init()
{ {
EnableBlockLink(); EnableBlockLink();
auto& system = Core::System::GetInstance(); auto& memory = m_system.GetMemory();
auto& memory = system.GetMemory();
jo.fastmem_arena = m_fastmem_enabled && memory.InitFastmemArena(); jo.fastmem_arena = m_fastmem_enabled && memory.InitFastmemArena();
jo.optimizeGatherPipe = true; jo.optimizeGatherPipe = true;
@ -322,8 +320,7 @@ void Jit64::Shutdown()
{ {
FreeCodeSpace(); FreeCodeSpace();
auto& system = Core::System::GetInstance(); auto& memory = m_system.GetMemory();
auto& memory = system.GetMemory();
memory.ShutdownFastmemArena(); memory.ShutdownFastmemArena();
blocks.Shutdown(); blocks.Shutdown();
@ -344,7 +341,7 @@ void Jit64::FallBackToInterpreter(UGeckoInstruction inst)
Interpreter::Instruction instr = Interpreter::GetInterpreterOp(inst); Interpreter::Instruction instr = Interpreter::GetInterpreterOp(inst);
ABI_PushRegistersAndAdjustStack({}, 0); ABI_PushRegistersAndAdjustStack({}, 0);
ABI_CallFunctionPC(instr, &Core::System::GetInstance().GetInterpreter(), inst.hex); ABI_CallFunctionPC(instr, &m_system.GetInterpreter(), inst.hex);
ABI_PopRegistersAndAdjustStack({}, 0); ABI_PopRegistersAndAdjustStack({}, 0);
// If the instruction wrote to any registers which were marked as discarded, // If the instruction wrote to any registers which were marked as discarded,
@ -404,29 +401,27 @@ void Jit64::DoNothing(UGeckoInstruction _inst)
// Yup, just don't do anything. // Yup, just don't do anything.
} }
static const bool ImHereDebug = false; void Jit64::ImHere(Jit64& jit)
static const bool ImHereLog = false;
static std::map<u32, int> been_here;
static void ImHere()
{ {
auto& ppc_state = jit.m_ppc_state;
static File::IOFile f; static File::IOFile f;
if (ImHereLog) if (jit.m_im_here_log)
{ {
if (!f) if (!f)
f.Open("log64.txt", "w"); f.Open("log64.txt", "w");
f.WriteString(fmt::format("{0:08x}\n", PowerPC::ppcState.pc)); f.WriteString(fmt::format("{0:08x}\n", ppc_state.pc));
} }
if (been_here.find(PowerPC::ppcState.pc) != been_here.end()) auto& been_here = jit.m_been_here;
auto it = been_here.find(ppc_state.pc);
if (it != been_here.end())
{ {
been_here.find(PowerPC::ppcState.pc)->second++; it->second++;
if ((been_here.find(PowerPC::ppcState.pc)->second) & 1023) if (it->second & 1023)
return; return;
} }
INFO_LOG_FMT(DYNA_REC, "I'm here - PC = {:08x} , LR = {:08x}", PowerPC::ppcState.pc, INFO_LOG_FMT(DYNA_REC, "I'm here - PC = {:08x} , LR = {:08x}", ppc_state.pc, LR(ppc_state));
LR(PowerPC::ppcState)); been_here[ppc_state.pc] = 1;
been_here[PowerPC::ppcState.pc] = 1;
} }
bool Jit64::Cleanup() bool Jit64::Cleanup()
@ -440,18 +435,18 @@ bool Jit64::Cleanup()
CMP(64, R(RSCRATCH), Imm32(GPFifo::GATHER_PIPE_SIZE)); CMP(64, R(RSCRATCH), Imm32(GPFifo::GATHER_PIPE_SIZE));
FixupBranch exit = J_CC(CC_L); FixupBranch exit = J_CC(CC_L);
ABI_PushRegistersAndAdjustStack({}, 0); ABI_PushRegistersAndAdjustStack({}, 0);
ABI_CallFunctionP(GPFifo::UpdateGatherPipe, &Core::System::GetInstance().GetGPFifo()); ABI_CallFunctionP(GPFifo::UpdateGatherPipe, &m_system.GetGPFifo());
ABI_PopRegistersAndAdjustStack({}, 0); ABI_PopRegistersAndAdjustStack({}, 0);
SetJumpTarget(exit); SetJumpTarget(exit);
did_something = true; did_something = true;
} }
// SPEED HACK: MMCR0/MMCR1 should be checked at run-time, not at compile time. // SPEED HACK: MMCR0/MMCR1 should be checked at run-time, not at compile time.
if (MMCR0(PowerPC::ppcState).Hex || MMCR1(PowerPC::ppcState).Hex) if (MMCR0(m_ppc_state).Hex || MMCR1(m_ppc_state).Hex)
{ {
ABI_PushRegistersAndAdjustStack({}, 0); ABI_PushRegistersAndAdjustStack({}, 0);
ABI_CallFunctionCCCP(PowerPC::UpdatePerformanceMonitor, js.downcountAmount, js.numLoadStoreInst, ABI_CallFunctionCCCP(PowerPC::UpdatePerformanceMonitor, js.downcountAmount, js.numLoadStoreInst,
js.numFloatingPointInst, &PowerPC::ppcState); js.numFloatingPointInst, &m_ppc_state);
ABI_PopRegistersAndAdjustStack({}, 0); ABI_PopRegistersAndAdjustStack({}, 0);
did_something = true; did_something = true;
} }
@ -663,25 +658,24 @@ void Jit64::Trace()
std::string fregs; std::string fregs;
#ifdef JIT_LOG_GPR #ifdef JIT_LOG_GPR
for (size_t i = 0; i < std::size(PowerPC::ppcState.gpr); i++) for (size_t i = 0; i < std::size(m_ppc_state.gpr); i++)
{ {
regs += fmt::format("r{:02d}: {:08x} ", i, PowerPC::ppcState.gpr[i]); regs += fmt::format("r{:02d}: {:08x} ", i, m_ppc_state.gpr[i]);
} }
#endif #endif
#ifdef JIT_LOG_FPR #ifdef JIT_LOG_FPR
for (size_t i = 0; i < std::size(PowerPC::ppcState.ps); i++) for (size_t i = 0; i < std::size(m_ppc_state.ps); i++)
{ {
fregs += fmt::format("f{:02d}: {:016x} ", i, PowerPC::ppcState.ps[i].PS0AsU64()); fregs += fmt::format("f{:02d}: {:016x} ", i, m_ppc_state.ps[i].PS0AsU64());
} }
#endif #endif
DEBUG_LOG_FMT(DYNA_REC, DEBUG_LOG_FMT(DYNA_REC,
"JIT64 PC: {:08x} SRR0: {:08x} SRR1: {:08x} FPSCR: {:08x} " "JIT64 PC: {:08x} SRR0: {:08x} SRR1: {:08x} FPSCR: {:08x} "
"MSR: {:08x} LR: {:08x} {} {}", "MSR: {:08x} LR: {:08x} {} {}",
PowerPC::ppcState.pc, SRR0(PowerPC::ppcState), SRR1(PowerPC::ppcState), m_ppc_state.pc, SRR0(m_ppc_state), SRR1(m_ppc_state), m_ppc_state.fpscr.Hex,
PowerPC::ppcState.fpscr.Hex, PowerPC::ppcState.msr.Hex, PowerPC::ppcState.spr[8], m_ppc_state.msr.Hex, m_ppc_state.spr[8], regs, fregs);
regs, fregs);
} }
void Jit64::Jit(u32 em_address) void Jit64::Jit(u32 em_address)
@ -720,7 +714,7 @@ void Jit64::Jit(u32 em_address, bool clear_cache_and_retry_on_failure)
if (!jo.profile_blocks) if (!jo.profile_blocks)
{ {
if (Core::System::GetInstance().GetCPU().IsStepping()) if (m_system.GetCPU().IsStepping())
{ {
block_size = 1; block_size = 1;
@ -744,8 +738,8 @@ void Jit64::Jit(u32 em_address, bool clear_cache_and_retry_on_failure)
if (code_block.m_memory_exception) if (code_block.m_memory_exception)
{ {
// Address of instruction could not be translated // Address of instruction could not be translated
PowerPC::ppcState.npc = nextPC; m_ppc_state.npc = nextPC;
PowerPC::ppcState.Exceptions |= EXCEPTION_ISI; m_ppc_state.Exceptions |= EXCEPTION_ISI;
PowerPC::CheckExceptions(); PowerPC::CheckExceptions();
WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", nextPC); WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", nextPC);
return; return;
@ -822,8 +816,6 @@ bool Jit64::SetEmitterStateToFreeCodeRegion()
bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
{ {
auto& system = Core::System::GetInstance();
js.firstFPInstructionFound = false; js.firstFPInstructionFound = false;
js.isLastInstruction = false; js.isLastInstruction = false;
js.blockStart = em_address; js.blockStart = em_address;
@ -839,10 +831,10 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
b->normalEntry = start; b->normalEntry = start;
// Used to get a trace of the last few blocks before a crash, sometimes VERY useful // Used to get a trace of the last few blocks before a crash, sometimes VERY useful
if (ImHereDebug) if (m_im_here_debug)
{ {
ABI_PushRegistersAndAdjustStack({}, 0); ABI_PushRegistersAndAdjustStack({}, 0);
ABI_CallFunction(ImHere); ABI_CallFunctionP(ImHere, this);
ABI_PopRegistersAndAdjustStack({}, 0); ABI_PopRegistersAndAdjustStack({}, 0);
} }
@ -895,9 +887,9 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
// the start of the block in case our guess turns out wrong. // the start of the block in case our guess turns out wrong.
for (int gqr : gqr_static) for (int gqr : gqr_static)
{ {
u32 value = GQR(PowerPC::ppcState, gqr); u32 value = GQR(m_ppc_state, gqr);
js.constantGqr[gqr] = value; js.constantGqr[gqr] = value;
CMP_or_TEST(32, PPCSTATE(spr[SPR_GQR0 + gqr]), Imm32(value)); CMP_or_TEST(32, PPCSTATE_SPR(SPR_GQR0 + gqr), Imm32(value));
J_CC(CC_NZ, target); J_CC(CC_NZ, target);
} }
js.constantGqrValid = gqr_static; js.constantGqrValid = gqr_static;
@ -944,7 +936,7 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
js.mustCheckFifo = false; js.mustCheckFifo = false;
BitSet32 registersInUse = CallerSavedRegistersInUse(); BitSet32 registersInUse = CallerSavedRegistersInUse();
ABI_PushRegistersAndAdjustStack(registersInUse, 0); ABI_PushRegistersAndAdjustStack(registersInUse, 0);
ABI_CallFunctionP(GPFifo::FastCheckGatherPipe, &system.GetGPFifo()); ABI_CallFunctionP(GPFifo::FastCheckGatherPipe, &m_system.GetGPFifo());
ABI_PopRegistersAndAdjustStack(registersInUse, 0); ABI_PopRegistersAndAdjustStack(registersInUse, 0);
gatherPipeIntCheck = true; gatherPipeIntCheck = true;
} }
@ -961,7 +953,7 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
SetJumpTarget(extException); SetJumpTarget(extException);
TEST(32, PPCSTATE(msr), Imm32(0x0008000)); TEST(32, PPCSTATE(msr), Imm32(0x0008000));
FixupBranch noExtIntEnable = J_CC(CC_Z, true); FixupBranch noExtIntEnable = J_CC(CC_Z, true);
MOV(64, R(RSCRATCH), ImmPtr(&system.GetProcessorInterface().m_interrupt_cause)); MOV(64, R(RSCRATCH), ImmPtr(&m_system.GetProcessorInterface().m_interrupt_cause));
TEST(32, MatR(RSCRATCH), TEST(32, MatR(RSCRATCH),
Imm32(ProcessorInterface::INT_CAUSE_CP | ProcessorInterface::INT_CAUSE_PE_TOKEN | Imm32(ProcessorInterface::INT_CAUSE_CP | ProcessorInterface::INT_CAUSE_PE_TOKEN |
ProcessorInterface::INT_CAUSE_PE_FINISH)); ProcessorInterface::INT_CAUSE_PE_FINISH));
@ -1013,7 +1005,7 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
js.firstFPInstructionFound = true; js.firstFPInstructionFound = true;
} }
auto& cpu = system.GetCPU(); auto& cpu = m_system.GetCPU();
if (m_enable_debugging && breakpoints.IsAddressBreakPoint(op.address) && !cpu.IsStepping()) if (m_enable_debugging && breakpoints.IsAddressBreakPoint(op.address) && !cpu.IsStepping())
{ {
gpr.Flush(); gpr.Flush();
@ -1190,7 +1182,7 @@ void Jit64::IntializeSpeculativeConstants()
const u8* target = nullptr; const u8* target = nullptr;
for (auto i : code_block.m_gpr_inputs) for (auto i : code_block.m_gpr_inputs)
{ {
u32 compileTimeValue = PowerPC::ppcState.gpr[i]; u32 compileTimeValue = m_ppc_state.gpr[i];
if (PowerPC::IsOptimizableGatherPipeWrite(compileTimeValue) || if (PowerPC::IsOptimizableGatherPipeWrite(compileTimeValue) ||
PowerPC::IsOptimizableGatherPipeWrite(compileTimeValue - 0x8000) || PowerPC::IsOptimizableGatherPipeWrite(compileTimeValue - 0x8000) ||
compileTimeValue == 0xCC000000) compileTimeValue == 0xCC000000)
@ -1207,7 +1199,7 @@ void Jit64::IntializeSpeculativeConstants()
JMP(asm_routines.dispatcher_no_check, true); JMP(asm_routines.dispatcher_no_check, true);
SwitchToNearCode(); SwitchToNearCode();
} }
CMP(32, PPCSTATE(gpr[i]), Imm32(compileTimeValue)); CMP(32, PPCSTATE_GPR(i), Imm32(compileTimeValue));
J_CC(CC_NZ, target); J_CC(CC_NZ, target);
gpr.SetImmediate32(i, compileTimeValue, false); gpr.SetImmediate32(i, compileTimeValue, false);
} }

View File

@ -43,7 +43,11 @@ struct CodeOp;
class Jit64 : public JitBase, public QuantizedMemoryRoutines class Jit64 : public JitBase, public QuantizedMemoryRoutines
{ {
public: public:
Jit64(); explicit Jit64(Core::System& system);
Jit64(const Jit64&) = delete;
Jit64(Jit64&&) = delete;
Jit64& operator=(const Jit64&) = delete;
Jit64& operator=(Jit64&&) = delete;
~Jit64() override; ~Jit64() override;
void Init() override; void Init() override;
@ -256,6 +260,8 @@ private:
void ResetFreeMemoryRanges(); void ResetFreeMemoryRanges();
static void ImHere(Jit64& jit);
JitBlockCache blocks{*this}; JitBlockCache blocks{*this};
TrampolineCache trampolines{*this}; TrampolineCache trampolines{*this};
@ -266,6 +272,10 @@ private:
HyoutaUtilities::RangeSizeSet<u8*> m_free_ranges_near; HyoutaUtilities::RangeSizeSet<u8*> m_free_ranges_near;
HyoutaUtilities::RangeSizeSet<u8*> m_free_ranges_far; HyoutaUtilities::RangeSizeSet<u8*> m_free_ranges_far;
const bool m_im_here_debug = false;
const bool m_im_here_log = false;
std::map<u32, int> m_been_here;
}; };
void LogGeneratedX86(size_t size, const PPCAnalyst::CodeBuffer& code_buffer, const u8* normalEntry, void LogGeneratedX86(size_t size, const PPCAnalyst::CodeBuffer& code_buffer, const u8* normalEntry,

View File

@ -20,7 +20,7 @@
using namespace Gen; using namespace Gen;
Jit64AsmRoutineManager::Jit64AsmRoutineManager(Jit64& jit) : CommonAsmRoutines(jit), m_jit{jit} Jit64AsmRoutineManager::Jit64AsmRoutineManager(Jit64& jit) : CommonAsmRoutines(jit)
{ {
} }
@ -45,9 +45,11 @@ void Jit64AsmRoutineManager::Generate()
// waste a bit of space for a second shadow, but whatever. // waste a bit of space for a second shadow, but whatever.
ABI_PushRegistersAndAdjustStack(ABI_ALL_CALLEE_SAVED, 8, /*frame*/ 16); ABI_PushRegistersAndAdjustStack(ABI_ALL_CALLEE_SAVED, 8, /*frame*/ 16);
auto& ppc_state = m_jit.m_ppc_state;
// Two statically allocated registers. // Two statically allocated registers.
// MOV(64, R(RMEM), Imm64((u64)Memory::physical_base)); // MOV(64, R(RMEM), Imm64((u64)Memory::physical_base));
MOV(64, R(RPPCSTATE), Imm64((u64)&PowerPC::ppcState + 0x80)); MOV(64, R(RPPCSTATE), Imm64((u64)&ppc_state + 0x80));
MOV(64, PPCSTATE(stored_stack_pointer), R(RSP)); MOV(64, PPCSTATE(stored_stack_pointer), R(RSP));
@ -81,7 +83,7 @@ void Jit64AsmRoutineManager::Generate()
dispatcher_no_timing_check = GetCodePtr(); dispatcher_no_timing_check = GetCodePtr();
auto& system = Core::System::GetInstance(); auto& system = m_jit.m_system;
FixupBranch dbg_exit; FixupBranch dbg_exit;
if (enable_debugging) if (enable_debugging)

View File

@ -11,8 +11,6 @@ namespace Gen
class X64CodeBlock; class X64CodeBlock;
} }
class JitBase;
// In Dolphin, we don't use inline assembly. Instead, we generate all machine-near // In Dolphin, we don't use inline assembly. Instead, we generate all machine-near
// code at runtime. In the case of fixed code like this, after writing it, we write // code at runtime. In the case of fixed code like this, after writing it, we write
// protect the memory, essentially making it work just like precompiled code. // protect the memory, essentially making it work just like precompiled code.
@ -43,6 +41,4 @@ public:
private: private:
void Generate(); void Generate();
void GenerateCommon(); void GenerateCommon();
JitBase& m_jit;
}; };

View File

@ -780,7 +780,7 @@ void Jit64::FloatCompare(UGeckoInstruction inst, bool upper)
SetJumpTarget(continue3); SetJumpTarget(continue3);
} }
MOV(64, PPCSTATE(cr.fields[crf]), R(RSCRATCH)); MOV(64, PPCSTATE_CR(crf), R(RSCRATCH));
} }
void Jit64::fcmpX(UGeckoInstruction inst) void Jit64::fcmpX(UGeckoInstruction inst)

View File

@ -148,16 +148,16 @@ void Jit64::ComputeRC(preg_t preg, bool needs_test, bool needs_sext)
if (arg.IsImm()) if (arg.IsImm())
{ {
MOV(64, PPCSTATE(cr.fields[0]), Imm32(arg.SImm32())); MOV(64, PPCSTATE_CR(0), Imm32(arg.SImm32()));
} }
else if (needs_sext) else if (needs_sext)
{ {
MOVSX(64, 32, RSCRATCH, arg); MOVSX(64, 32, RSCRATCH, arg);
MOV(64, PPCSTATE(cr.fields[0]), R(RSCRATCH)); MOV(64, PPCSTATE_CR(0), R(RSCRATCH));
} }
else else
{ {
MOV(64, PPCSTATE(cr.fields[0]), arg); MOV(64, PPCSTATE_CR(0), arg);
} }
if (CheckMergedBranch(0)) if (CheckMergedBranch(0))
@ -391,14 +391,14 @@ void Jit64::DoMergedBranch()
if (js.op[1].branchIsIdleLoop) if (js.op[1].branchIsIdleLoop)
{ {
if (next.LK) if (next.LK)
MOV(32, PPCSTATE(spr[SPR_LR]), Imm32(nextPC + 4)); MOV(32, PPCSTATE_SPR(SPR_LR), Imm32(nextPC + 4));
WriteIdleExit(js.op[1].branchTo); WriteIdleExit(js.op[1].branchTo);
} }
else if (next.OPCD == 16) // bcx else if (next.OPCD == 16) // bcx
{ {
if (next.LK) if (next.LK)
MOV(32, PPCSTATE(spr[SPR_LR]), Imm32(nextPC + 4)); MOV(32, PPCSTATE_SPR(SPR_LR), Imm32(nextPC + 4));
u32 destination; u32 destination;
if (next.AA) if (next.AA)
@ -410,18 +410,18 @@ void Jit64::DoMergedBranch()
else if ((next.OPCD == 19) && (next.SUBOP10 == 528)) // bcctrx else if ((next.OPCD == 19) && (next.SUBOP10 == 528)) // bcctrx
{ {
if (next.LK) if (next.LK)
MOV(32, PPCSTATE(spr[SPR_LR]), Imm32(nextPC + 4)); MOV(32, PPCSTATE_SPR(SPR_LR), Imm32(nextPC + 4));
MOV(32, R(RSCRATCH), PPCSTATE(spr[SPR_CTR])); MOV(32, R(RSCRATCH), PPCSTATE_SPR(SPR_CTR));
AND(32, R(RSCRATCH), Imm32(0xFFFFFFFC)); AND(32, R(RSCRATCH), Imm32(0xFFFFFFFC));
WriteExitDestInRSCRATCH(next.LK, nextPC + 4); WriteExitDestInRSCRATCH(next.LK, nextPC + 4);
} }
else if ((next.OPCD == 19) && (next.SUBOP10 == 16)) // bclrx else if ((next.OPCD == 19) && (next.SUBOP10 == 16)) // bclrx
{ {
MOV(32, R(RSCRATCH), PPCSTATE(spr[SPR_LR])); MOV(32, R(RSCRATCH), PPCSTATE_SPR(SPR_LR));
if (!m_enable_blr_optimization) if (!m_enable_blr_optimization)
AND(32, R(RSCRATCH), Imm32(0xFFFFFFFC)); AND(32, R(RSCRATCH), Imm32(0xFFFFFFFC));
if (next.LK) if (next.LK)
MOV(32, PPCSTATE(spr[SPR_LR]), Imm32(nextPC + 4)); MOV(32, PPCSTATE_SPR(SPR_LR), Imm32(nextPC + 4));
WriteBLRExit(); WriteBLRExit();
} }
else else
@ -551,12 +551,12 @@ void Jit64::cmpXX(UGeckoInstruction inst)
(u64)gpr.Imm32(a) - (u64)comparand.Imm32(); (u64)gpr.Imm32(a) - (u64)comparand.Imm32();
if (compareResult == (s32)compareResult) if (compareResult == (s32)compareResult)
{ {
MOV(64, PPCSTATE(cr.fields[crf]), Imm32((u32)compareResult)); MOV(64, PPCSTATE_CR(crf), Imm32((u32)compareResult));
} }
else else
{ {
MOV(64, R(RSCRATCH), Imm64(compareResult)); MOV(64, R(RSCRATCH), Imm64(compareResult));
MOV(64, PPCSTATE(cr.fields[crf]), R(RSCRATCH)); MOV(64, PPCSTATE_CR(crf), R(RSCRATCH));
} }
if (merge_branch) if (merge_branch)
@ -573,7 +573,7 @@ void Jit64::cmpXX(UGeckoInstruction inst)
RCX64Reg Ra = gpr.Bind(a, RCMode::Read); RCX64Reg Ra = gpr.Bind(a, RCMode::Read);
RegCache::Realize(Ra); RegCache::Realize(Ra);
MOV(64, PPCSTATE(cr.fields[crf]), Ra); MOV(64, PPCSTATE_CR(crf), Ra);
if (merge_branch) if (merge_branch)
{ {
TEST(64, Ra, Ra); TEST(64, Ra, Ra);
@ -621,7 +621,7 @@ void Jit64::cmpXX(UGeckoInstruction inst)
if (comparand.IsImm() && comparand.Imm32() == 0) if (comparand.IsImm() && comparand.Imm32() == 0)
{ {
MOV(64, PPCSTATE(cr.fields[crf]), R(input)); MOV(64, PPCSTATE_CR(crf), R(input));
// Place the comparison next to the branch for macro-op fusion // Place the comparison next to the branch for macro-op fusion
if (merge_branch) if (merge_branch)
TEST(64, R(input), R(input)); TEST(64, R(input), R(input));
@ -629,7 +629,7 @@ void Jit64::cmpXX(UGeckoInstruction inst)
else else
{ {
SUB(64, R(input), comparand); SUB(64, R(input), comparand);
MOV(64, PPCSTATE(cr.fields[crf]), R(input)); MOV(64, PPCSTATE_CR(crf), R(input));
} }
if (merge_branch) if (merge_branch)

View File

@ -320,7 +320,7 @@ void Jit64::dcbx(UGeckoInstruction inst)
FixupBranch bat_lookup_failed; FixupBranch bat_lookup_failed;
MOV(32, R(effective_address), R(addr)); MOV(32, R(effective_address), R(addr));
const u8* loop_start = GetCodePtr(); const u8* loop_start = GetCodePtr();
if (PowerPC::ppcState.msr.IR) if (m_ppc_state.msr.IR)
{ {
// Translate effective address to physical address. // Translate effective address to physical address.
bat_lookup_failed = BATAddressLookup(addr, tmp, PowerPC::ibat_table.data()); bat_lookup_failed = BATAddressLookup(addr, tmp, PowerPC::ibat_table.data());
@ -349,7 +349,7 @@ void Jit64::dcbx(UGeckoInstruction inst)
SwitchToFarCode(); SwitchToFarCode();
SetJumpTarget(invalidate_needed); SetJumpTarget(invalidate_needed);
if (PowerPC::ppcState.msr.IR) if (m_ppc_state.msr.IR)
SetJumpTarget(bat_lookup_failed); SetJumpTarget(bat_lookup_failed);
BitSet32 registersInUse = CallerSavedRegistersInUse(); BitSet32 registersInUse = CallerSavedRegistersInUse();
@ -422,7 +422,7 @@ void Jit64::dcbz(UGeckoInstruction inst)
end_dcbz_hack = J_CC(CC_L); end_dcbz_hack = J_CC(CC_L);
} }
bool emit_fast_path = PowerPC::ppcState.msr.DR && m_jit.jo.fastmem_arena; bool emit_fast_path = m_ppc_state.msr.DR && m_jit.jo.fastmem_arena;
if (emit_fast_path) if (emit_fast_path)
{ {

View File

@ -23,7 +23,7 @@ void Jit64::psq_stXX(UGeckoInstruction inst)
JITDISABLE(bJITLoadStorePairedOff); JITDISABLE(bJITLoadStorePairedOff);
// For performance, the AsmCommon routines assume address translation is on. // For performance, the AsmCommon routines assume address translation is on.
FALLBACK_IF(!PowerPC::ppcState.msr.DR); FALLBACK_IF(!m_ppc_state.msr.DR);
s32 offset = inst.SIMM_12; s32 offset = inst.SIMM_12;
bool indexed = inst.OPCD == 4; bool indexed = inst.OPCD == 4;
@ -90,7 +90,7 @@ void Jit64::psq_stXX(UGeckoInstruction inst)
// UU[SCALE]UUUUU[TYPE] where SCALE is 6 bits and TYPE is 3 bits, so we have to AND with // UU[SCALE]UUUUU[TYPE] where SCALE is 6 bits and TYPE is 3 bits, so we have to AND with
// 0b0011111100000111, or 0x3F07. // 0b0011111100000111, or 0x3F07.
MOV(32, R(RSCRATCH2), Imm32(0x3F07)); MOV(32, R(RSCRATCH2), Imm32(0x3F07));
AND(32, R(RSCRATCH2), PPCSTATE(spr[SPR_GQR0 + i])); AND(32, R(RSCRATCH2), PPCSTATE_SPR(SPR_GQR0 + i));
LEA(64, RSCRATCH, LEA(64, RSCRATCH,
M(w ? asm_routines.single_store_quantized : asm_routines.paired_store_quantized)); M(w ? asm_routines.single_store_quantized : asm_routines.paired_store_quantized));
// 8-bit operations do not zero upper 32-bits of 64-bit registers. // 8-bit operations do not zero upper 32-bits of 64-bit registers.
@ -112,7 +112,7 @@ void Jit64::psq_lXX(UGeckoInstruction inst)
JITDISABLE(bJITLoadStorePairedOff); JITDISABLE(bJITLoadStorePairedOff);
// For performance, the AsmCommon routines assume address translation is on. // For performance, the AsmCommon routines assume address translation is on.
FALLBACK_IF(!PowerPC::ppcState.msr.DR); FALLBACK_IF(!m_ppc_state.msr.DR);
s32 offset = inst.SIMM_12; s32 offset = inst.SIMM_12;
bool indexed = inst.OPCD == 4; bool indexed = inst.OPCD == 4;
@ -147,7 +147,7 @@ void Jit64::psq_lXX(UGeckoInstruction inst)
// Stash PC in case asm_routine causes exception // Stash PC in case asm_routine causes exception
MOV(32, PPCSTATE(pc), Imm32(js.compilerPC)); MOV(32, PPCSTATE(pc), Imm32(js.compilerPC));
// Get the high part of the GQR register // Get the high part of the GQR register
OpArg gqr = PPCSTATE(spr[SPR_GQR0 + i]); OpArg gqr = PPCSTATE_SPR(SPR_GQR0 + i);
gqr.AddMemOffset(2); gqr.AddMemOffset(2);
MOV(32, R(RSCRATCH2), Imm32(0x3F07)); MOV(32, R(RSCRATCH2), Imm32(0x3F07));
AND(32, R(RSCRATCH2), gqr); AND(32, R(RSCRATCH2), gqr);

View File

@ -20,7 +20,7 @@ using namespace Gen;
static OpArg CROffset(int field) static OpArg CROffset(int field)
{ {
return PPCSTATE(cr.fields[field]); return PPCSTATE_CR(field);
} }
void Jit64::GetCRFieldBit(int field, int bit, X64Reg out, bool negate) void Jit64::GetCRFieldBit(int field, int bit, X64Reg out, bool negate)
@ -216,9 +216,9 @@ void Jit64::UpdateFPExceptionSummary(X64Reg fpscr, X64Reg tmp1, X64Reg tmp2)
OR(32, R(fpscr), R(tmp1)); OR(32, R(fpscr), R(tmp1));
} }
static void DoICacheReset() static void DoICacheReset(PowerPC::PowerPCState& ppc_state)
{ {
PowerPC::ppcState.iCache.Reset(); ppc_state.iCache.Reset();
} }
void Jit64::mtspr(UGeckoInstruction inst) void Jit64::mtspr(UGeckoInstruction inst)
@ -282,11 +282,11 @@ void Jit64::mtspr(UGeckoInstruction inst)
MOV(32, R(RSCRATCH), Rd); MOV(32, R(RSCRATCH), Rd);
BTR(32, R(RSCRATCH), Imm8(31 - 20)); // ICFI BTR(32, R(RSCRATCH), Imm8(31 - 20)); // ICFI
MOV(32, PPCSTATE(spr[iIndex]), R(RSCRATCH)); MOV(32, PPCSTATE_SPR(iIndex), R(RSCRATCH));
FixupBranch dont_reset_icache = J_CC(CC_NC); FixupBranch dont_reset_icache = J_CC(CC_NC);
BitSet32 regs = CallerSavedRegistersInUse(); BitSet32 regs = CallerSavedRegistersInUse();
ABI_PushRegistersAndAdjustStack(regs, 0); ABI_PushRegistersAndAdjustStack(regs, 0);
ABI_CallFunction(DoICacheReset); ABI_CallFunctionP(DoICacheReset, &m_ppc_state);
ABI_PopRegistersAndAdjustStack(regs, 0); ABI_PopRegistersAndAdjustStack(regs, 0);
SetJumpTarget(dont_reset_icache); SetJumpTarget(dont_reset_icache);
return; return;
@ -299,7 +299,7 @@ void Jit64::mtspr(UGeckoInstruction inst)
// OK, this is easy. // OK, this is easy.
RCOpArg Rd = gpr.BindOrImm(d, RCMode::Read); RCOpArg Rd = gpr.BindOrImm(d, RCMode::Read);
RegCache::Realize(Rd); RegCache::Realize(Rd);
MOV(32, PPCSTATE(spr[iIndex]), Rd); MOV(32, PPCSTATE_SPR(iIndex), Rd);
} }
void Jit64::mfspr(UGeckoInstruction inst) void Jit64::mfspr(UGeckoInstruction inst)
@ -323,7 +323,7 @@ void Jit64::mfspr(UGeckoInstruction inst)
RCX64Reg rax = gpr.Scratch(RAX); RCX64Reg rax = gpr.Scratch(RAX);
RCX64Reg rcx = gpr.Scratch(RCX); RCX64Reg rcx = gpr.Scratch(RCX);
auto& core_timing_globals = Core::System::GetInstance().GetCoreTiming().GetGlobals(); auto& core_timing_globals = m_system.GetCoreTiming().GetGlobals();
MOV(64, rcx, ImmPtr(&core_timing_globals)); MOV(64, rcx, ImmPtr(&core_timing_globals));
// An inline implementation of CoreTiming::GetFakeTimeBase, since in timer-heavy games the // An inline implementation of CoreTiming::GetFakeTimeBase, since in timer-heavy games the
@ -355,7 +355,7 @@ void Jit64::mfspr(UGeckoInstruction inst)
MOV(64, rax, MDisp(rcx, offsetof(CoreTiming::Globals, fake_TB_start_value))); MOV(64, rax, MDisp(rcx, offsetof(CoreTiming::Globals, fake_TB_start_value)));
SHR(64, rdx, Imm8(3)); SHR(64, rdx, Imm8(3));
ADD(64, rax, rdx); ADD(64, rax, rdx);
MOV(64, PPCSTATE(spr[SPR_TL]), rax); MOV(64, PPCSTATE_SPR(SPR_TL), rax);
if (CanMergeNextInstructions(1)) if (CanMergeNextInstructions(1))
{ {
@ -422,7 +422,7 @@ void Jit64::mfspr(UGeckoInstruction inst)
{ {
RCX64Reg Rd = gpr.Bind(d, RCMode::Write); RCX64Reg Rd = gpr.Bind(d, RCMode::Write);
RegCache::Realize(Rd); RegCache::Realize(Rd);
MOV(32, Rd, PPCSTATE(spr[iIndex])); MOV(32, Rd, PPCSTATE_SPR(iIndex));
break; break;
} }
} }
@ -457,8 +457,7 @@ void Jit64::mtmsr(UGeckoInstruction inst)
FixupBranch noExceptionsPending = J_CC(CC_Z, true); FixupBranch noExceptionsPending = J_CC(CC_Z, true);
// Check if a CP interrupt is waiting and keep the GPU emulation in sync (issue 4336) // Check if a CP interrupt is waiting and keep the GPU emulation in sync (issue 4336)
auto& system = Core::System::GetInstance(); MOV(64, R(RSCRATCH), ImmPtr(&m_system.GetProcessorInterface().m_interrupt_cause));
MOV(64, R(RSCRATCH), ImmPtr(&system.GetProcessorInterface().m_interrupt_cause));
TEST(32, MatR(RSCRATCH), Imm32(ProcessorInterface::INT_CAUSE_CP)); TEST(32, MatR(RSCRATCH), Imm32(ProcessorInterface::INT_CAUSE_CP));
FixupBranch cpInt = J_CC(CC_NZ, true); FixupBranch cpInt = J_CC(CC_NZ, true);

View File

@ -35,7 +35,7 @@ const X64Reg* FPURegCache::GetAllocationOrder(size_t* count) const
OpArg FPURegCache::GetDefaultLocation(preg_t preg) const OpArg FPURegCache::GetDefaultLocation(preg_t preg) const
{ {
return PPCSTATE(ps[preg].ps0); return PPCSTATE_PS0(preg);
} }
BitSet32 FPURegCache::GetRegUtilization() const BitSet32 FPURegCache::GetRegUtilization() const

View File

@ -27,7 +27,7 @@ void GPRRegCache::LoadRegister(preg_t preg, X64Reg new_loc)
OpArg GPRRegCache::GetDefaultLocation(preg_t preg) const OpArg GPRRegCache::GetDefaultLocation(preg_t preg) const
{ {
return PPCSTATE(gpr[preg]); return PPCSTATE_GPR(preg);
} }
const X64Reg* GPRRegCache::GetAllocationOrder(size_t* count) const const X64Reg* GPRRegCache::GetAllocationOrder(size_t* count) const

View File

@ -209,10 +209,10 @@ template <typename T>
class MMIOReadCodeGenerator : public MMIO::ReadHandlingMethodVisitor<T> class MMIOReadCodeGenerator : public MMIO::ReadHandlingMethodVisitor<T>
{ {
public: public:
MMIOReadCodeGenerator(Gen::X64CodeBlock* code, BitSet32 registers_in_use, Gen::X64Reg dst_reg, MMIOReadCodeGenerator(Core::System* system, Gen::X64CodeBlock* code, BitSet32 registers_in_use,
u32 address, bool sign_extend) Gen::X64Reg dst_reg, u32 address, bool sign_extend)
: m_code(code), m_registers_in_use(registers_in_use), m_dst_reg(dst_reg), m_address(address), : m_system(system), m_code(code), m_registers_in_use(registers_in_use), m_dst_reg(dst_reg),
m_sign_extend(sign_extend) m_address(address), m_sign_extend(sign_extend)
{ {
} }
@ -273,11 +273,12 @@ private:
void CallLambda(int sbits, const std::function<T(Core::System&, u32)>* lambda) void CallLambda(int sbits, const std::function<T(Core::System&, u32)>* lambda)
{ {
m_code->ABI_PushRegistersAndAdjustStack(m_registers_in_use, 0); m_code->ABI_PushRegistersAndAdjustStack(m_registers_in_use, 0);
m_code->ABI_CallLambdaPC(lambda, &Core::System::GetInstance(), m_address); m_code->ABI_CallLambdaPC(lambda, m_system, m_address);
m_code->ABI_PopRegistersAndAdjustStack(m_registers_in_use, 0); m_code->ABI_PopRegistersAndAdjustStack(m_registers_in_use, 0);
MoveOpArgToReg(sbits, R(ABI_RETURN)); MoveOpArgToReg(sbits, R(ABI_RETURN));
} }
Core::System* m_system;
Gen::X64CodeBlock* m_code; Gen::X64CodeBlock* m_code;
BitSet32 m_registers_in_use; BitSet32 m_registers_in_use;
Gen::X64Reg m_dst_reg; Gen::X64Reg m_dst_reg;
@ -293,19 +294,22 @@ void EmuCodeBlock::MMIOLoadToReg(MMIO::Mapping* mmio, Gen::X64Reg reg_value,
{ {
case 8: case 8:
{ {
MMIOReadCodeGenerator<u8> gen(this, registers_in_use, reg_value, address, sign_extend); MMIOReadCodeGenerator<u8> gen(&m_jit.m_system, this, registers_in_use, reg_value, address,
sign_extend);
mmio->GetHandlerForRead<u8>(address).Visit(gen); mmio->GetHandlerForRead<u8>(address).Visit(gen);
break; break;
} }
case 16: case 16:
{ {
MMIOReadCodeGenerator<u16> gen(this, registers_in_use, reg_value, address, sign_extend); MMIOReadCodeGenerator<u16> gen(&m_jit.m_system, this, registers_in_use, reg_value, address,
sign_extend);
mmio->GetHandlerForRead<u16>(address).Visit(gen); mmio->GetHandlerForRead<u16>(address).Visit(gen);
break; break;
} }
case 32: case 32:
{ {
MMIOReadCodeGenerator<u32> gen(this, registers_in_use, reg_value, address, sign_extend); MMIOReadCodeGenerator<u32> gen(&m_jit.m_system, this, registers_in_use, reg_value, address,
sign_extend);
mmio->GetHandlerForRead<u32>(address).Visit(gen); mmio->GetHandlerForRead<u32>(address).Visit(gen);
break; break;
} }
@ -367,7 +371,7 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress,
} }
FixupBranch exit; FixupBranch exit;
const bool dr_set = (flags & SAFE_LOADSTORE_DR_ON) || PowerPC::ppcState.msr.DR; const bool dr_set = (flags & SAFE_LOADSTORE_DR_ON) || m_jit.m_ppc_state.msr.DR;
const bool fast_check_address = !slowmem && dr_set && m_jit.jo.fastmem_arena; const bool fast_check_address = !slowmem && dr_set && m_jit.jo.fastmem_arena;
if (fast_check_address) if (fast_check_address)
{ {
@ -442,8 +446,7 @@ void EmuCodeBlock::SafeLoadToRegImmediate(X64Reg reg_value, u32 address, int acc
u32 mmioAddress = PowerPC::IsOptimizableMMIOAccess(address, accessSize); u32 mmioAddress = PowerPC::IsOptimizableMMIOAccess(address, accessSize);
if (accessSize != 64 && mmioAddress) if (accessSize != 64 && mmioAddress)
{ {
auto& system = Core::System::GetInstance(); auto& memory = m_jit.m_system.GetMemory();
auto& memory = system.GetMemory();
MMIOLoadToReg(memory.GetMMIOMapping(), reg_value, registersInUse, mmioAddress, accessSize, MMIOLoadToReg(memory.GetMMIOMapping(), reg_value, registersInUse, mmioAddress, accessSize,
signExtend); signExtend);
return; return;
@ -537,7 +540,7 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces
} }
FixupBranch exit; FixupBranch exit;
const bool dr_set = (flags & SAFE_LOADSTORE_DR_ON) || PowerPC::ppcState.msr.DR; const bool dr_set = (flags & SAFE_LOADSTORE_DR_ON) || m_jit.m_ppc_state.msr.DR;
const bool fast_check_address = !slowmem && dr_set && m_jit.jo.fastmem_arena; const bool fast_check_address = !slowmem && dr_set && m_jit.jo.fastmem_arena;
if (fast_check_address) if (fast_check_address)
{ {

View File

@ -305,7 +305,7 @@ void CommonAsmRoutines::GenMfcr()
if (i != 0) if (i != 0)
SHL(32, R(dst), Imm8(4)); SHL(32, R(dst), Imm8(4));
MOV(64, R(cr_val), PPCSTATE(cr.fields[i])); MOV(64, R(cr_val), PPCSTATE_CR(i));
// EQ: Bits 31-0 == 0; set flag bit 1 // EQ: Bits 31-0 == 0; set flag bit 1
TEST(32, R(cr_val), R(cr_val)); TEST(32, R(cr_val), R(cr_val));

View File

@ -9,6 +9,8 @@
enum EQuantizeType : u32; enum EQuantizeType : u32;
class Jit64;
class QuantizedMemoryRoutines : public EmuCodeBlock class QuantizedMemoryRoutines : public EmuCodeBlock
{ {
public: public:
@ -24,7 +26,7 @@ private:
class CommonAsmRoutines : public CommonAsmRoutinesBase, public QuantizedMemoryRoutines class CommonAsmRoutines : public CommonAsmRoutinesBase, public QuantizedMemoryRoutines
{ {
public: public:
explicit CommonAsmRoutines(Jit64& jit) : QuantizedMemoryRoutines(jit) {} explicit CommonAsmRoutines(Jit64& jit) : QuantizedMemoryRoutines(jit), m_jit(jit) {}
void GenFrsqrte(); void GenFrsqrte();
void GenFres(); void GenFres();
void GenMfcr(); void GenMfcr();
@ -37,4 +39,6 @@ protected:
void GenQuantizedSingleLoads(); void GenQuantizedSingleLoads();
void GenQuantizedStores(); void GenQuantizedStores();
void GenQuantizedSingleStores(); void GenQuantizedSingleStores();
Jit64& m_jit;
}; };

View File

@ -3,17 +3,38 @@
#pragma once #pragma once
#include <type_traits>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Core/PowerPC/Jit64Common/Jit64Constants.h" #include "Core/PowerPC/Jit64Common/Jit64Constants.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
// We offset by 0x80 because the range of one byte memory offsets is // We offset by 0x80 because the range of one byte memory offsets is
// -0x80..0x7f. // -0x80..0x7f.
#define PPCSTATE(x) \ #define PPCSTATE_OFF(i) (static_cast<int>(offsetof(PowerPC::PowerPCState, i)) - 0x80)
MDisp(RPPCSTATE, (int)((char*)&PowerPC::ppcState.x - (char*)&PowerPC::ppcState) - 0x80) #define PPCSTATE_OFF_ARRAY(elem, i) \
// In case you want to disable the ppcstate register: (static_cast<int>(offsetof(PowerPC::PowerPCState, elem[0]) + \
// #define PPCSTATE(x) M(&PowerPC::ppcState.x) sizeof(PowerPC::PowerPCState::elem[0]) * (i)) - \
#define PPCSTATE_LR PPCSTATE(spr[SPR_LR]) 0x80)
#define PPCSTATE_CTR PPCSTATE(spr[SPR_CTR])
#define PPCSTATE_SRR0 PPCSTATE(spr[SPR_SRR0]) #define PPCSTATE_OFF_GPR(i) PPCSTATE_OFF_ARRAY(gpr, i)
#define PPCSTATE_SRR1 PPCSTATE(spr[SPR_SRR1]) #define PPCSTATE_OFF_CR(i) PPCSTATE_OFF_ARRAY(cr.fields, i)
#define PPCSTATE_OFF_SR(i) PPCSTATE_OFF_ARRAY(sr, i)
#define PPCSTATE_OFF_SPR(i) PPCSTATE_OFF_ARRAY(spr, i)
static_assert(std::is_same_v<decltype(PowerPC::PowerPCState::ps[0]), PowerPC::PairedSingle&>);
#define PPCSTATE_OFF_PS0(i) (PPCSTATE_OFF_ARRAY(ps, i) + offsetof(PowerPC::PairedSingle, ps0))
#define PPCSTATE_OFF_PS1(i) (PPCSTATE_OFF_ARRAY(ps, i) + offsetof(PowerPC::PairedSingle, ps1))
#define PPCSTATE(i) MDisp(RPPCSTATE, PPCSTATE_OFF(i))
#define PPCSTATE_GPR(i) MDisp(RPPCSTATE, PPCSTATE_OFF_ARRAY(gpr, i))
#define PPCSTATE_CR(i) MDisp(RPPCSTATE, PPCSTATE_OFF_ARRAY(cr.fields, i))
#define PPCSTATE_SR(i) MDisp(RPPCSTATE, PPCSTATE_OFF_ARRAY(sr, i))
#define PPCSTATE_SPR(i) MDisp(RPPCSTATE, PPCSTATE_OFF_ARRAY(spr, i))
#define PPCSTATE_PS0(i) MDisp(RPPCSTATE, PPCSTATE_OFF_PS0(i))
#define PPCSTATE_PS1(i) MDisp(RPPCSTATE, PPCSTATE_OFF_PS1(i))
#define PPCSTATE_LR PPCSTATE_SPR(SPR_LR)
#define PPCSTATE_CTR PPCSTATE_SPR(SPR_CTR)
#define PPCSTATE_SRR0 PPCSTATE_SPR(SPR_SRR0)
#define PPCSTATE_SRR1 PPCSTATE_SPR(SPR_SRR1)

View File

@ -38,7 +38,7 @@ constexpr size_t CODE_SIZE = 1024 * 1024 * 32;
constexpr size_t FARCODE_SIZE = 1024 * 1024 * 64; constexpr size_t FARCODE_SIZE = 1024 * 1024 * 64;
constexpr size_t FARCODE_SIZE_MMU = 1024 * 1024 * 64; constexpr size_t FARCODE_SIZE_MMU = 1024 * 1024 * 64;
JitArm64::JitArm64() : m_float_emit(this) JitArm64::JitArm64(Core::System& system) : JitBase(system), m_float_emit(this)
{ {
} }

View File

@ -22,7 +22,11 @@
class JitArm64 : public JitBase, public Arm64Gen::ARM64CodeBlock, public CommonAsmRoutinesBase class JitArm64 : public JitBase, public Arm64Gen::ARM64CodeBlock, public CommonAsmRoutinesBase
{ {
public: public:
JitArm64(); explicit JitArm64(Core::System& system);
JitArm64(const JitArm64&) = delete;
JitArm64(JitArm64&&) = delete;
JitArm64& operator=(const JitArm64&) = delete;
JitArm64& operator=(JitArm64&&) = delete;
~JitArm64() override; ~JitArm64() override;
void Init() override; void Init() override;

View File

@ -60,7 +60,8 @@ void JitTrampoline(JitBase& jit, u32 em_address)
jit.Jit(em_address); jit.Jit(em_address);
} }
JitBase::JitBase() : m_code_buffer(code_buffer_size) JitBase::JitBase(Core::System& system)
: m_code_buffer(code_buffer_size), m_system(system), m_ppc_state(system.GetPPCState())
{ {
m_registered_config_callback_id = Config::AddConfigChangedCallback( m_registered_config_callback_id = Config::AddConfigChangedCallback(
[this] { Core::RunAsCPUThread([this] { RefreshConfig(); }); }); [this] { Core::RunAsCPUThread([this] { RefreshConfig(); }); });
@ -94,8 +95,8 @@ void JitBase::RefreshConfig()
m_fprf = Config::Get(Config::MAIN_FPRF); m_fprf = Config::Get(Config::MAIN_FPRF);
m_accurate_nans = Config::Get(Config::MAIN_ACCURATE_NANS); m_accurate_nans = Config::Get(Config::MAIN_ACCURATE_NANS);
m_fastmem_enabled = Config::Get(Config::MAIN_FASTMEM); m_fastmem_enabled = Config::Get(Config::MAIN_FASTMEM);
m_mmu_enabled = Core::System::GetInstance().IsMMUMode(); m_mmu_enabled = m_system.IsMMUMode();
m_pause_on_panic_enabled = Core::System::GetInstance().IsPauseOnPanicMode(); m_pause_on_panic_enabled = m_system.IsPauseOnPanicMode();
m_accurate_cpu_cache_enabled = Config::Get(Config::MAIN_ACCURATE_CPU_CACHE); m_accurate_cpu_cache_enabled = Config::Get(Config::MAIN_ACCURATE_CPU_CACHE);
if (m_accurate_cpu_cache_enabled) if (m_accurate_cpu_cache_enabled)
{ {
@ -192,7 +193,7 @@ bool JitBase::HandleStackFault()
// to reset the guard page. // to reset the guard page.
// Yeah, it's kind of gross. // Yeah, it's kind of gross.
GetBlockCache()->InvalidateICache(0, 0xffffffff, true); GetBlockCache()->InvalidateICache(0, 0xffffffff, true);
Core::System::GetInstance().GetCoreTiming().ForceExceptionCheck(0); m_system.GetCoreTiming().ForceExceptionCheck(0);
m_cleanup_after_stackfault = true; m_cleanup_after_stackfault = true;
return true; return true;
@ -213,8 +214,7 @@ void JitBase::CleanUpAfterStackFault()
bool JitBase::CanMergeNextInstructions(int count) const bool JitBase::CanMergeNextInstructions(int count) const
{ {
auto& system = Core::System::GetInstance(); if (m_system.GetCPU().IsStepping() || js.instructionsLeft < count)
if (system.GetCPU().IsStepping() || js.instructionsLeft < count)
return false; return false;
// Be careful: a breakpoint kills flags in between instructions // Be careful: a breakpoint kills flags in between instructions
for (int i = 1; i <= count; i++) for (int i = 1; i <= count; i++)
@ -230,8 +230,7 @@ bool JitBase::CanMergeNextInstructions(int count) const
void JitBase::UpdateMemoryAndExceptionOptions() void JitBase::UpdateMemoryAndExceptionOptions()
{ {
bool any_watchpoints = PowerPC::memchecks.HasAny(); bool any_watchpoints = PowerPC::memchecks.HasAny();
jo.fastmem = jo.fastmem = m_fastmem_enabled && jo.fastmem_arena && (m_ppc_state.msr.DR || !any_watchpoints);
m_fastmem_enabled && jo.fastmem_arena && (PowerPC::ppcState.msr.DR || !any_watchpoints);
jo.memcheck = m_mmu_enabled || m_pause_on_panic_enabled || any_watchpoints; jo.memcheck = m_mmu_enabled || m_pause_on_panic_enabled || any_watchpoints;
jo.fp_exceptions = m_enable_float_exceptions; jo.fp_exceptions = m_enable_float_exceptions;
jo.div_by_zero_exceptions = m_enable_div_by_zero_exceptions; jo.div_by_zero_exceptions = m_enable_div_by_zero_exceptions;

View File

@ -17,6 +17,15 @@
#include "Core/PowerPC/JitCommon/JitCache.h" #include "Core/PowerPC/JitCommon/JitCache.h"
#include "Core/PowerPC/PPCAnalyst.h" #include "Core/PowerPC/PPCAnalyst.h"
namespace Core
{
class System;
}
namespace PowerPC
{
struct PowerPCState;
}
//#define JIT_LOG_GENERATED_CODE // Enables logging of generated code //#define JIT_LOG_GENERATED_CODE // Enables logging of generated code
//#define JIT_LOG_GPR // Enables logging of the PPC general purpose regs //#define JIT_LOG_GPR // Enables logging of the PPC general purpose regs
//#define JIT_LOG_FPR // Enables logging of the PPC floating point regs //#define JIT_LOG_FPR // Enables logging of the PPC floating point regs
@ -162,7 +171,11 @@ protected:
bool ShouldHandleFPExceptionForInstruction(const PPCAnalyst::CodeOp* op); bool ShouldHandleFPExceptionForInstruction(const PPCAnalyst::CodeOp* op);
public: public:
JitBase(); explicit JitBase(Core::System& system);
JitBase(const JitBase&) = delete;
JitBase(JitBase&&) = delete;
JitBase& operator=(const JitBase&) = delete;
JitBase& operator=(JitBase&&) = delete;
~JitBase() override; ~JitBase() override;
bool IsDebuggingEnabled() const { return m_enable_debugging; } bool IsDebuggingEnabled() const { return m_enable_debugging; }
@ -182,6 +195,9 @@ public:
// This should probably be removed from public: // This should probably be removed from public:
JitOptions jo{}; JitOptions jo{};
JitState js{}; JitState js{};
Core::System& m_system;
PowerPC::PowerPCState& m_ppc_state;
}; };
void JitTrampoline(JitBase& jit, u32 em_address); void JitTrampoline(JitBase& jit, u32 em_address);

View File

@ -54,20 +54,22 @@ void DoState(PointerWrap& p)
} }
CPUCoreBase* InitJitCore(PowerPC::CPUCore core) CPUCoreBase* InitJitCore(PowerPC::CPUCore core)
{ {
auto& system = Core::System::GetInstance();
switch (core) switch (core)
{ {
#if _M_X86 #if _M_X86
case PowerPC::CPUCore::JIT64: case PowerPC::CPUCore::JIT64:
g_jit = new Jit64(); g_jit = new Jit64(system);
break; break;
#endif #endif
#if _M_ARM_64 #if _M_ARM_64
case PowerPC::CPUCore::JITARM64: case PowerPC::CPUCore::JITARM64:
g_jit = new JitArm64(); g_jit = new JitArm64(system);
break; break;
#endif #endif
case PowerPC::CPUCore::CachedInterpreter: case PowerPC::CPUCore::CachedInterpreter:
g_jit = new CachedInterpreter(); g_jit = new CachedInterpreter(system);
break; break;
default: default:

View File

@ -9,6 +9,7 @@
#include "Core/MemTools.h" #include "Core/MemTools.h"
#include "Core/PowerPC/JitCommon/JitBase.h" #include "Core/PowerPC/JitCommon/JitBase.h"
#include "Core/PowerPC/JitInterface.h" #include "Core/PowerPC/JitInterface.h"
#include "Core/System.h"
// include order is important // include order is important
#include <gtest/gtest.h> // NOLINT #include <gtest/gtest.h> // NOLINT
@ -25,6 +26,8 @@ enum
class PageFaultFakeJit : public JitBase class PageFaultFakeJit : public JitBase
{ {
public: public:
explicit PageFaultFakeJit(Core::System& system) : JitBase(system) {}
// CPUCoreBase methods // CPUCoreBase methods
void Init() override {} void Init() override {}
void Shutdown() override {} void Shutdown() override {}
@ -72,7 +75,7 @@ TEST(PageFault, PageFault)
EXPECT_NE(data, nullptr); EXPECT_NE(data, nullptr);
Common::WriteProtectMemory(data, PAGE_GRAN, false); Common::WriteProtectMemory(data, PAGE_GRAN, false);
PageFaultFakeJit pfjit; PageFaultFakeJit pfjit(Core::System::GetInstance());
JitInterface::SetJit(&pfjit); JitInterface::SetJit(&pfjit);
pfjit.m_data = data; pfjit.m_data = data;

View File

@ -11,6 +11,7 @@
#include "Core/PowerPC/Jit64/Jit.h" #include "Core/PowerPC/Jit64/Jit.h"
#include "Core/PowerPC/Jit64Common/Jit64AsmCommon.h" #include "Core/PowerPC/Jit64Common/Jit64AsmCommon.h"
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h" #include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
#include "Core/System.h"
#include "../TestValues.h" #include "../TestValues.h"
@ -22,7 +23,7 @@ namespace
class TestCommonAsmRoutines : public CommonAsmRoutines class TestCommonAsmRoutines : public CommonAsmRoutines
{ {
public: public:
TestCommonAsmRoutines() : CommonAsmRoutines(jit) explicit TestCommonAsmRoutines(Core::System& system) : CommonAsmRoutines(jit), jit(system)
{ {
using namespace Gen; using namespace Gen;
@ -51,7 +52,7 @@ public:
TEST(Jit64, ConvertDoubleToSingle) TEST(Jit64, ConvertDoubleToSingle)
{ {
TestCommonAsmRoutines routines; TestCommonAsmRoutines routines(Core::System::GetInstance());
for (const u64 input : double_test_values) for (const u64 input : double_test_values)
{ {

View File

@ -11,6 +11,7 @@
#include "Core/PowerPC/Jit64/Jit.h" #include "Core/PowerPC/Jit64/Jit.h"
#include "Core/PowerPC/Jit64Common/Jit64AsmCommon.h" #include "Core/PowerPC/Jit64Common/Jit64AsmCommon.h"
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h" #include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
#include "Core/System.h"
#include "../TestValues.h" #include "../TestValues.h"
@ -22,7 +23,7 @@ namespace
class TestCommonAsmRoutines : public CommonAsmRoutines class TestCommonAsmRoutines : public CommonAsmRoutines
{ {
public: public:
TestCommonAsmRoutines() : CommonAsmRoutines(jit) explicit TestCommonAsmRoutines(Core::System& system) : CommonAsmRoutines(jit), jit(system)
{ {
using namespace Gen; using namespace Gen;
@ -58,7 +59,7 @@ public:
TEST(Jit64, Frsqrte) TEST(Jit64, Frsqrte)
{ {
TestCommonAsmRoutines routines; TestCommonAsmRoutines routines(Core::System::GetInstance());
UReg_FPSCR fpscr; UReg_FPSCR fpscr;

View File

@ -9,6 +9,7 @@
#include "Common/FPURoundMode.h" #include "Common/FPURoundMode.h"
#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h" #include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h"
#include "Core/PowerPC/JitArm64/Jit.h" #include "Core/PowerPC/JitArm64/Jit.h"
#include "Core/System.h"
#include "../TestValues.h" #include "../TestValues.h"
@ -30,7 +31,7 @@ struct Pair
class TestConversion : private JitArm64 class TestConversion : private JitArm64
{ {
public: public:
TestConversion() explicit TestConversion(Core::System& system) : JitArm64(system)
{ {
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes; const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
@ -119,7 +120,7 @@ private:
TEST(JitArm64, ConvertDoubleToSingle) TEST(JitArm64, ConvertDoubleToSingle)
{ {
TestConversion test; TestConversion test(Core::System::GetInstance());
for (const u64 input : double_test_values) for (const u64 input : double_test_values)
{ {
@ -154,7 +155,7 @@ TEST(JitArm64, ConvertDoubleToSingle)
TEST(JitArm64, ConvertSingleToDouble) TEST(JitArm64, ConvertSingleToDouble)
{ {
TestConversion test; TestConversion test(Core::System::GetInstance());
for (const u32 input : single_test_values) for (const u32 input : single_test_values)
{ {

View File

@ -10,6 +10,7 @@
#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h" #include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h"
#include "Core/PowerPC/JitArm64/Jit.h" #include "Core/PowerPC/JitArm64/Jit.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
#include "../TestValues.h" #include "../TestValues.h"
@ -22,7 +23,7 @@ using namespace Arm64Gen;
class TestFPRF : public JitArm64 class TestFPRF : public JitArm64
{ {
public: public:
TestFPRF() explicit TestFPRF(Core::System& system) : JitArm64(system)
{ {
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes; const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
@ -67,7 +68,7 @@ static u32 RunUpdateFPRF(const std::function<void()>& f)
TEST(JitArm64, FPRF) TEST(JitArm64, FPRF)
{ {
TestFPRF test; TestFPRF test(Core::System::GetInstance());
for (const u64 double_input : double_test_values) for (const u64 double_input : double_test_values)
{ {

View File

@ -9,6 +9,7 @@
#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h" #include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h"
#include "Core/PowerPC/JitArm64/Jit.h" #include "Core/PowerPC/JitArm64/Jit.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
#include "../TestValues.h" #include "../TestValues.h"
@ -21,7 +22,7 @@ using namespace Arm64Gen;
class TestFres : public JitArm64 class TestFres : public JitArm64
{ {
public: public:
TestFres() explicit TestFres(Core::System& system) : JitArm64(system)
{ {
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes; const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
@ -50,7 +51,7 @@ public:
TEST(JitArm64, Fres) TEST(JitArm64, Fres)
{ {
TestFres test; TestFres test(Core::System::GetInstance());
for (const u64 ivalue : double_test_values) for (const u64 ivalue : double_test_values)
{ {

View File

@ -9,6 +9,7 @@
#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h" #include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h"
#include "Core/PowerPC/JitArm64/Jit.h" #include "Core/PowerPC/JitArm64/Jit.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
#include "../TestValues.h" #include "../TestValues.h"
@ -21,7 +22,7 @@ using namespace Arm64Gen;
class TestFrsqrte : public JitArm64 class TestFrsqrte : public JitArm64
{ {
public: public:
TestFrsqrte() explicit TestFrsqrte(Core::System& system) : JitArm64(system)
{ {
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes; const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
@ -50,7 +51,7 @@ public:
TEST(JitArm64, Frsqrte) TEST(JitArm64, Frsqrte)
{ {
TestFrsqrte test; TestFrsqrte test(Core::System::GetInstance());
for (const u64 ivalue : double_test_values) for (const u64 ivalue : double_test_values)
{ {