mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-09-01 02:05:21 +02:00
All ~82 MIPSInt::Int_* functions (Interpreter.cpp/.h, InterpreterVFPU.cpp/.h) now take an explicit MIPSState *mips instead of reaching for the global currentMIPS internally, along with their file-local helpers (DelayBranchTo, SkipLikely, ApplySwizzleS/T, ApplyPrefixD/ST, RetainInvalidSwizzleST, EatPrefixes). MIPSInterpretFunc, Interpret(), ExecInstruction()/InterpreterDispatch.cpp (regenerated), and RunUntilFast() all thread mips through accordingly. Deliberately left on currentMIPS for now: MIPSVFPUUtils.cpp's ReadVector/WriteVector/ReadMatrix/WriteMatrix/VFPURewritePrefix - these are shared with every JIT backend's compile-time VFPU code, so parameterizing them would balloon this into a JIT-wide refactor. This is a partial refactor; that's the next boundary to push on. Several JIT backends (x86 Jit.cpp, ARM/ArmJit.cpp, ARM64/Arm64Jit.cpp, x86/X64IRJit.cpp, RiscV/RiscVJit.cpp, LoongArch64/LoongArch64Jit.cpp, ARM64/Arm64IRJit.cpp) bake the raw interpreter function pointer directly into JIT-generated machine code as their "fall back to the interpreter for this one op" mechanism, with only a single argument register set up for the call. Rather than hand-editing register allocation across four architectures that can't be build-tested here, added MIPSInterpretTrampoline(MIPSOpcode op) - a 1-arg wrapper around MIPSInterpret(currentMIPS, op) - and pointed all 7 such call sites at it instead, leaving that codegen untouched. Two other call sites (JitLogMiss, JitBranchLog) were plain C++ calls and just got the extra argument directly. Verified (Windows x64): PPSSPPWindows/PPSSPPHeadless/UnitTest all build clean, 49/49 unit tests pass. `test.py -g --graphics=software`: interpreter 312/314 (cpu/fpu/fpu is the pre-existing, unrelated interpreter-vs-JIT denormal difference; gpu/rendertarget/copy passes standalone, so was cross-test state bleed in the batch run, not a regression), default JIT 314/314, jit-ir 313/314 (gpu/vertices/morph is an expected difference from the vertex decoder taking a different mode with this core change, not a bug). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019SKhm9wKEQzRUsx9mTrrtQ
91 lines
3.0 KiB
Python
91 lines
3.0 KiB
Python
#!/usr/bin/env python
|
|
|
|
# Regenerates Core/MIPS/InterpreterDispatch.cpp (the ExecInstruction switch-tree
|
|
# interpreter dispatcher) from the tables in Core/MIPS/MIPSTables.cpp.
|
|
#
|
|
# Run this after changing anything that affects those tables - new instructions,
|
|
# retimed cycle counts, encoding changes, etc. The generated file is checked into
|
|
# git like any other source file, not built on the fly, so it needs to be
|
|
# regenerated and the diff committed whenever the tables change.
|
|
#
|
|
# This script only needs an already-built PPSSPPHeadless binary (see
|
|
# docs/pspautotests.md for how to build one); it doesn't build anything itself.
|
|
# After it finishes, just build normally - Core/MIPS/InterpreterDispatch.cpp is
|
|
# already wired into every build system, so no further steps are needed.
|
|
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
# Same search list test.py uses to find a headless build.
|
|
CANDIDATES = [
|
|
"Windows/x64/Debug/PPSSPPHeadless.exe",
|
|
"Windows/x64/Release/PPSSPPHeadless.exe",
|
|
"Windows/Debug/PPSSPPHeadless.exe",
|
|
"Windows/Release/PPSSPPHeadless.exe",
|
|
"build/Debug/PPSSPPHeadless",
|
|
"build/Release/PPSSPPHeadless",
|
|
"build/RelWithDebInfo/PPSSPPHeadless",
|
|
"build/MinSizeRel/PPSSPPHeadless",
|
|
"build/PPSSPPHeadless",
|
|
"./PPSSPPHeadless",
|
|
"./PPSSPPHeadless.exe",
|
|
]
|
|
|
|
OUT_PATH = os.path.join("Core", "MIPS", "InterpreterDispatch.cpp")
|
|
|
|
|
|
def find_headless():
|
|
for candidate in CANDIDATES:
|
|
if os.path.isfile(candidate):
|
|
return candidate
|
|
return None
|
|
|
|
|
|
def main():
|
|
repo_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
os.chdir(repo_root)
|
|
|
|
headless = find_headless()
|
|
if headless is None:
|
|
sys.stderr.write("error: couldn't find a built PPSSPPHeadless binary. Checked:\n")
|
|
for candidate in CANDIDATES:
|
|
sys.stderr.write(" %s\n" % candidate)
|
|
sys.stderr.write("Build PPSSPPHeadless first (see docs/pspautotests.md), then re-run this script.\n")
|
|
return 1
|
|
|
|
print("Using %s" % headless)
|
|
|
|
# subprocess/CreateProcess on Windows can fail to resolve a relative,
|
|
# forward-slash path as the executable itself - use an absolute, normalized path.
|
|
headless_abs = os.path.normpath(os.path.abspath(headless))
|
|
|
|
try:
|
|
result = subprocess.run([headless_abs, "--generate-interpreter-dispatch"], capture_output=True)
|
|
except OSError as e:
|
|
sys.stderr.write("error: couldn't run %s: %s\n" % (headless, e))
|
|
return 1
|
|
|
|
if result.returncode != 0:
|
|
sys.stderr.buffer.write(result.stderr)
|
|
sys.stderr.write("error: %s exited with code %d\n" % (headless, result.returncode))
|
|
return 1
|
|
|
|
generated = result.stdout
|
|
|
|
# Sanity check before clobbering the tracked file - a stale/broken binary should
|
|
# fail loudly here rather than silently truncating InterpreterDispatch.cpp.
|
|
if b"int ExecInstruction(MIPSState *mips, MIPSOpcode op)" not in generated:
|
|
sys.stderr.write("error: generated output doesn't look right (missing ExecInstruction) - not overwriting %s\n" % OUT_PATH)
|
|
return 1
|
|
|
|
with open(OUT_PATH, "wb") as f:
|
|
f.write(generated)
|
|
|
|
print("Regenerated %s" % OUT_PATH)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|