Overview
ReXGlue uses static ahead-of-time (AOT) recompilation to translate Xbox 360 PowerPC machine code into native C++ source code at build time. Unlike traditional emulators that use dynamic recompilation (JIT) at runtime, ReXGlue produces compilable C++ files that can be optimized by modern compilers.Static recompilation happens once during build, not at runtime. The output is standard C++ code that compiles to native machine code for maximum performance.
The Recompilation Pipeline
The recompilation process consists of several stages:Stage 1: Binary Analysis
TheBinaryView examines the XEX executable to extract:
- Code sections and data sections
- Entry points and export tables
.pdata(exception handling metadata) for function boundaries- Relocation information
Stage 2: Function Discovery
TheFunctionScanner (source:include/rex/codegen/recompiled_function.h:84) discovers function boundaries using multiple heuristics:
Function Boundary Detection
- Linear sweep from known entry points
- Branch target tracking to find furthest reachable instruction
- Prologue/epilogue patterns (
mflr,stw r0,blrsequences) - pdata information when available
- Jump table detection for
bctrswitch statements
DiscoveredBlock structure in source:include/rex/codegen/recompiled_function.h:47):
Stage 3: Code Generation
TheRecompiler (source:include/rex/codegen/recompiler.h:67) translates each PowerPC instruction to C++ code:
Instruction-by-Instruction Translation:
RecompilerLocalVariables structure (source:include/rex/codegen/recompiler.h:36) tracks which registers need to be declared as local variables:
PPC_MM_LOAD_U32/PPC_MM_STORE_U32 macros.
Stage 4: Output Generation
Generated C++ functions follow this signature:Function Dispatch
Indirect calls (via CTR register) use a function table stored in guest memory:The function table is indexed by
(guest_addr - CODE_BASE) * 2, allowing 8-byte pointers for each 4-byte-aligned instruction. This is initialized by Memory::InitializeFunctionTable() (source:include/rex/system/xmemory.h:473).Control Flow Handling
Direct Branches
Unconditional branches compile to direct C++ function calls:Conditional Branches
Conditional branches become C++ if statements:Jump Tables
Switch statements viabctr are detected and converted to C++ switch:
Validation and Optimization
Deferred Writes: Generated code is buffered until validation passes (source:include/rex/codegen/recompiler.h:78):FlushPendingWrites() method writes all files to disk only after successful validation.
Force Mode:
The recompile(bool force) method can bypass validation errors:
Performance Characteristics
| Metric | Static Recompilation | Dynamic Recompilation (JIT) |
|---|---|---|
| Translation time | Build time (one-time) | Runtime overhead |
| Code quality | Full compiler optimizations | Limited optimization window |
| Startup time | Instant | Must compile before execution |
| Memory usage | Zero runtime overhead | JIT cache in memory |
| Debugging | Source-level with native tools | Requires special JIT debugger |
Static recompilation trades build time for runtime performance. Once compiled, there is zero translation overhead at runtime.
Code Example
Original PowerPC assembly:See Also
- PowerPC Emulation - Instruction translation details
- Memory Model - Address translation and memory layout
- Kernel Emulation - System call handling