Files
ppsspp/Core/MIPS/IR/IRInterpreter.h
T
Henrik RydgårdandClaude Opus 5.5 6e475258da ME: Run the Media Engine on the ARM64 and x64 JITs
The native dispatcher generated for the ME leaves when its downcount
runs out instead of calling CoreTiming::Advance, and IRNativeJit gets
RunDowncount. Pointerify is decided from the CPU's own memory base. ARM32,
RISC-V and LoongArch64 still give the ME the IR interpreter.

LoadKernel/StoreKernel are now compiled on ARM64 and x64 rather than
going through the IR interpreter one op at a time: memory directly, or a
call to fixed code (which saves the caller-saved registers guest values
live in) for 0xBC000000-0xBFFFFFFF. ARM64's block size estimate counts
them as such. The 16-bit ones stay generic while the software renderer's
depth mirrors are active, as Load16/Store16 do. That matters for the main
CPU's kernel code too, and for all code while the ME is emulated, which
runs in kernel mode everywhere. mcidclan's me-soft-interrupt went from
476 billion to 6.4 billion host instructions for 3 emulated seconds,
ending with the same ME counter as the IR interpreter.

The ME unit tests run on the native JIT too.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 10:28:50 +02:00

37 lines
1.1 KiB
C++

#pragma once
#include "Common/CommonTypes.h"
#include "Core/Core.h"
#include "Core/MemMap.h"
class MIPSState;
struct IRInst;
u32 IRRunBreakpoint(u32 pc);
u32 IRRunMemCheck(u32 pc, u32 addr);
// A LoadKernel*/StoreKernel* (op) to an address the native JITs don't access directly: a hardware
// register, or not memory at all.
u32 IRRunKernelLoad(MIPSState *mips, u32 addr, u32 op);
void IRRunKernelStore(MIPSState *mips, u32 addr, u32 value, u32 op);
template <uint32_t alignment>
u32 RunValidateAddress(u32 pc, u32 addr, u32 isWrite) {
static_assert(alignment <= 16);
const auto toss = [&](MemoryExceptionType t) {
Core_MemoryException(addr, alignment, pc, t);
return coreState != CORE_RUNNING_CPU ? 1 : 0;
};
if (!Memory::IsValidNAlignedAddress<alignment>(addr)) {
MemoryExceptionType t = isWrite == 1 ? MemoryExceptionType::WRITE_WORD : MemoryExceptionType::READ_WORD;
if constexpr (alignment > 4)
t = isWrite ? MemoryExceptionType::WRITE_BLOCK : MemoryExceptionType::READ_BLOCK;
return toss(t);
}
if constexpr (alignment > 1)
if ((addr & (alignment - 1)) != 0)
return toss(MemoryExceptionType::ALIGNMENT);
return 0;
}