Files
Xenia-Canary/RUST_PORT_CODEMAP.md
2026-04-12 18:25:46 +02:00

6.3 KiB

Xenia Xbox 360 Emulator: JIT vs Interpreter Architecture Analysis

Analysis of Xenia's architecture comparing JIT vs interpreter approaches for Rust porting. Key findings: JIT pipeline [1a-1d] uses Xbyak with no Rust equivalent, MMIO relies on hardware exceptions [2a-2d], while interpreter approach uses explicit MMIO checking [3a-3d]. The PPC context [4a-4d] and opcode infrastructure [5a-5d] support both approaches. Memory system [6a-6c] requires unsafe Rust regardless. Kernel HLE [7a-7c] and GPU shader translation [8a-8c] present additional challenges.

1. JIT Code Generation Pipeline

The current PPC-to-x64 JIT compilation pipeline using HIR and Xbyak

1a. JIT Pipeline Initialization (ppc_translator.cc:44)

Sets up scanner, HIR builder, compiler, and Xbyak assembler

PPCTranslator::PPCTranslator(PPCFrontend* frontend) : frontend_(frontend) {

1b. HIR Optimization Passes (ppc_translator.cc:57)

Adds multiple optimization passes to the compiler pipeline

compiler_->AddPass(std::make_unique<passes::ControlFlowAnalysisPass>());

1c. Xbyak-based Code Emitter (x64_emitter.h:208)

X64Emitter inherits from Xbyak for runtime x64 code generation

class X64Emitter : public Xbyak::CodeGenerator {

1d. Host-to-Guest Thunk (x64_backend.cc:656)

Raw x64 assembly emitted for host↔guest ABI transitions

mov(rdi, ptr[rsi + offsetof(ppc::PPCContext, virtual_membase)]);  // membase

2. MMIO Exception Handling

Hardware exception-based MMIO interception used by the JIT

2a. Exception Handler Entry (mmio_handler.cc:402)

Catches access violations to handle MMIO operations

bool MMIOHandler::ExceptionCallback(Exception* ex) {

2b. Filter Access Violations (mmio_handler.cc:403)

Only processes memory access violations

if (ex->code() != Exception::Code::kAccessViolation) {

2c. Address Translation (mmio_handler.cc:427)

Translates host fault address back to guest virtual address

fault_guest_virtual_address = host_to_guest_virtual_(

2d. Instruction Decoding (mmio_handler.cc:449)

Decodes the faulting x64 instruction to determine the operation

if (!TryDecodeLoadStore(p, decoded_load_store)) {

3. Interpreter Alternative Approach

Explicit MMIO checking pattern that enables interpreter implementation

3a. Explicit MMIO Check Function (x64_seq_memory.cc:1216)

Pattern for checking MMIO ranges without exceptions

static T MMIOAwareLoad(void* _ctx, unsigned int guestaddr) {

3b. Range Lookup (x64_seq_memory.cc:1225)

Explicitly checks if address is in mapped MMIO range

auto gaddr = ctx->processor->memory()->LookupVirtualMappedRange(guestaddr);

3c. MMIO Callback Invocation (x64_seq_memory.cc:1236)

Calls MMIO read callback instead of accessing memory directly

value = gaddr->read(nullptr, gaddr->callback_context, guestaddr);

3d. MMIO Handler Interface (mmio_handler.h:73)

Public API for explicit MMIO checking in interpreter mode

bool CheckLoad(uint32_t virtual_address, uint32_t* out_value);

4. PPC Context and State Management

Register file and thread state structures that would need Rust porting

4a. PPC Register File (ppc_context.h:378)

32 GPRs, CTR, LR, MSR in the context structure

uint64_t r[32];  // 0x20 General purpose registers

4b. Floating-Point and Vector Registers (ppc_context.h:384)

32 FPRs and 128 VMX128 vector registers

double f[32];     // 0x120 Floating-point registers

4c. Thread State Context (thread_state.h:49)

Each guest thread owns a PPCContext pointer

ppc::PPCContext* context_;

4d. Big-Endian Wrapper (byte_order.h:134)

Type that handles big-endian conversion for guest structures

template <typename T>
using be = endian_store<T, std::endian::big>;

5. Opcode Dispatch Infrastructure

PPC opcode enumeration and lookup that enables interpreter implementation

5a. PPC Opcode Enumeration (ppc_opcode.h:14)

Complete enum of all PPC opcodes including VMX128 extensions

enum class PPCOpcode : uint32_t {

5b. Opcode Dispatch Table (ppc_opcode_lookup_gen.cc:262)

Fast lookup table for opcode decoding

case 0b000101: PPC_DECODER_HIT(vrlw128);

5c. VMX128 Instruction Encoding (ppc_emit_altivec.cc:37)

Macros for decoding Xbox 360-specific VMX128 instructions

#define VX128(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x3d0))

5d. Basic Block Discovery (ppc_scanner.h:36)

Finds basic block boundaries for potential interpreter caching

std::vector<BlockInfo> FindBlocks(GuestFunction* function);

6. Memory System Architecture

4GB virtual address space management required for both approaches

6a. Virtual Memory Allocation (memory.cc:142)

Creates 4GB+ file-backed mapping for guest address space

mapping_ = xe::memory::CreateFileMappingHandle(

6b. Virtual Memory Base (memory.cc:167)

Sets up virtual and physical memory base addresses

virtual_membase_ = mapping_base_;

6c. Guest Address Translation (ppc_context.h:433)

Fast inline function for translating guest to host addresses

inline T TranslateVirtual(uint32_t guest_address) const {

7. Kernel HLE System

Massive kernel export table that would need Rust porting

7a. Kernel Export Table (xboxkrnl_table.inc:15)

96KB+ table of all xboxkrnl exports

XE_EXPORT(xboxkrnl, 0x00000001, DbgBreakPoint,                                              kFunction),

7b. Guest Thread Structure (xthread.h:256)

Packed big-endian X_KTHREAD structure living in guest memory

xe::be<uint32_t> stack_base;       // 0x5C

7c. Kernel State Management (emulator.h:349)

Central kernel object tracking all guest kernel state

std::unique_ptr<kernel::KernelState> kernel_state_;

8. GPU Shader Translation

Complex shader translation pipeline that poses challenges for Rust porting

8a. SPIR-V Builder Initialization (spirv_shader_translator.cc:155)

Uses glslang C++ API for SPIR-V generation

builder_ = std::make_unique<SpirvBuilder>(

8b. Shader Interpreter (shader_interpreter.h:51)

Existing interpreter for simple shaders without texture fetches

static bool CanInterpretShader(const Shader& shader) {

8c. C++ Dependency (premake5.lua:31)

glslang dependency with no direct Rust equivalent

"glslang-spirv",