> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/dolphin-emu/dolphin/llms.txt
> Use this file to discover all available pages before exploring further.

# CPU emulation

> PowerPC CPU emulation with JIT compilation and multiple execution backends

Dolphin emulates the PowerPC 750CL (GameCube) and Broadway (Wii) processors using multiple execution backends optimized for different scenarios.

## PowerPC Architecture

The emulated CPUs are 32-bit RISC processors:

| Feature        | GameCube (Gekko)  | Wii (Broadway)      |
| -------------- | ----------------- | ------------------- |
| Clock Speed    | 486 MHz           | 729 MHz             |
| Architecture   | PowerPC 750CL     | PowerPC 750CL-based |
| L1 Cache       | 32 KB I + 32 KB D | 32 KB I + 32 KB D   |
| L2 Cache       | 256 KB            | 512 KB              |
| Paired Singles | Yes               | Yes                 |
| SIMD           | Limited           | Limited             |

**Location**: `Source/Core/Core/PowerPC/`

## Execution Backends

Dolphin offers multiple CPU emulation modes in `PowerPC/`:

<Tabs>
  <Tab title="JIT (x86-64)">
    **Location**: `PowerPC/Jit64/`

    **Default on x86-64 platforms**. Compiles PowerPC code to native x86-64:

    * Block-level compilation with register allocation
    * Fastmem for direct memory access (when MMU allows)
    * Paired-single optimization using SSE/AVX
    * Fastest execution (5-10x interpreter speed)

    ```cpp theme={null}
    // Enable in config
    [Core]
    CPUCore = 1  // JIT
    ```

    The JIT handles:

    * Branch folding and block linking
    * Constant propagation
    * Register caching across instructions
    * Special handling for common idioms
  </Tab>

  <Tab title="JIT (ARM64)">
    **Location**: `PowerPC/JitArm64/`

    **Default on ARM64 platforms** (Android, Apple Silicon):

    * PowerPC to ARM64 translation
    * NEON for paired-single operations
    * Optimized for mobile/embedded
    * Performance similar to x86-64 JIT

    ```cpp theme={null}
    [Core]
    CPUCore = 4  // JitArm64
    ```
  </Tab>

  <Tab title="Cached Interpreter">
    **Location**: `PowerPC/CachedInterpreter/`

    Hybrid approach:

    * Decode blocks once, cache decoded ops
    * Execute through interpreter loop
    * Slower than JIT but more compatible
    * Useful for debugging

    ```cpp theme={null}
    [Core]
    CPUCore = 2  // Cached Interpreter
    ```
  </Tab>

  <Tab title="Interpreter">
    **Location**: `PowerPC/Interpreter/`

    Pure interpretation:

    * Decode and execute each instruction
    * Slowest but simplest
    * Perfect accuracy reference
    * Mainly for debugging

    ```cpp theme={null}
    [Core]
    CPUCore = 0  // Interpreter  
    ```
  </Tab>
</Tabs>

## JIT Compilation Process

The JIT operates on blocks of PowerPC code:

<Steps>
  <Step title="Block Discovery">
    Identify a basic block starting at PC

    * Follow instructions until branch/return
    * Respect block size limits
    * Check for compiled block in cache
  </Step>

  <Step title="Analysis">
    Analyze PowerPC instructions

    **File**: `PowerPC/PPCAnalyst.cpp`

    * Detect register usage
    * Find memory access patterns
    * Identify idle loops (for skip-idle optimization)
    * Determine instruction dependencies
  </Step>

  <Step title="Compilation">
    Generate native code

    * Allocate registers for PowerPC GPRs/FPRs
    * Emit x86-64/ARM64 instructions
    * Insert memory access trampolines
    * Add exception handling
  </Step>

  <Step title="Linking">
    Connect blocks together

    * Link direct branches between compiled blocks
    * Fast dispatch without dispatcher overhead
    * Invalidate on SMC (self-modifying code)
  </Step>
</Steps>

## Register Mapping

PowerPC has extensive register state:

```cpp theme={null}
// From PowerPC/PowerPC.h
struct PowerPCState {
  u32 gpr[32];        // General purpose registers
  double fpr[32];     // Floating point (also used for paired singles)
  u32 spr[1024];      // Special purpose registers
  u32 cr;             // Condition register (8 x 4-bit fields)
  u32 pc;             // Program counter
  u32 npc;            // Next PC
  // ... more state
};
```

The JIT maps frequently-used registers:

* `r1` (stack pointer) → native register when possible
* `r13` (small data area) → cached
* `f0`-`f31` → x87/SSE registers or stack

## Memory Management Unit

**Location**: `PowerPC/MMU.cpp`

Translates virtual addresses to physical:

<Accordion title="Address Translation">
  PowerPC uses segmented memory model:

  1. **Segment lookup**: Translate EA (effective address) to VA (virtual address)
  2. **Page table lookup**: Translate VA to PA (physical address)
  3. **TLB caching**: Translation Lookaside Buffer speeds up lookups

  ```cpp theme={null}
  u32 TranslateAddress(u32 address, XCheckTLBFlag flag);
  ```
</Accordion>

<Accordion title="Fastmem">
  On x86-64/ARM64 with MMU disabled or known-safe access:

  * Direct pointer to emulated RAM
  * No translation overhead
  * Trap SIGSEGV/EXCEPTION\_ACCESS\_VIOLATION for bounds checking
  * 10x faster than full MMU emulation

  Enabled automatically when safe.
</Accordion>

<Accordion title="BAT Registers">
  Block Address Translation for large mappings:

  * 4 instruction BATs (IBAT0-3)
  * 4 data BATs (DBAT0-3)
  * Map large regions (128 KB - 256 MB)
  * Used by games for main RAM, I/O
</Accordion>

## Paired Singles

GameCube/Wii extension for SIMD floating-point:

```cpp theme={null}
// Each FPR can hold two 32-bit floats
struct PS {
  float ps0;
  float ps1;  
};
```

Common instructions:

* `ps_add`, `ps_sub`, `ps_mul` - Paired arithmetic
* `psq_l`, `psq_st` - Quantized loads/stores
* `ps_merge00`, `ps_merge01` - Shuffle operations

The JIT optimizes paired-singles using:

* **x86-64**: SSE instructions (2x floats per XMM register)
* **ARM64**: NEON instructions (2x floats per vector)

## Gekko/Broadway Differences

Wii (Broadway) is mostly identical to GameCube (Gekko):

| Feature    | Gekko          | Broadway       |
| ---------- | -------------- | -------------- |
| Base ISA   | PowerPC 750CL  | PowerPC 750CL  |
| Extensions | Paired singles | Paired singles |
| Clock      | 486 MHz        | 729 MHz (1.5x) |
| Cache      | 256 KB L2      | 512 KB L2 (2x) |

<Note>
  The main difference is clock speed and cache size. No new instructions were added.
</Note>

## Performance Optimization

### Idle Skipping

Detect idle loops waiting for interrupts:

```cpp theme={null}
// Typical idle loop pattern
0x80001234: lwz r3, 0x800030E0  // Load interrupt flag
0x80001238: cmpwi r3, 0         // Compare to zero  
0x8000123C: beq 0x80001234      // Branch if zero (spin)
```

When detected:

* Skip ahead to next event
* Save thousands of CPU cycles
* Enabled with `SkipIdle = True`

### Branch Following

Compile through unconditional branches:

```cpp theme={null}
// Instead of two blocks:
block1: ...
        b block2
        
block2: ...  

// Compile as one block:
block1: ...
        (inline block2)
```

### Register Allocation

Keep PowerPC registers in native registers:

* Avoid memory loads/stores
* Track liveness across block
* Spill least-used registers

## Debugging CPU Emulation

Tools for CPU debugging:

```bash theme={null}
# Run with interpreter for accuracy
dolphin-emu --exec=game.iso --config=Core.CPUCore=0

# Enable code breakpoints
dolphin-emu --debugger --exec=game.iso
```

In debugger:

* Set breakpoints on PowerPC addresses
* Step through PowerPC instructions
* Inspect GPR/FPR register values
* View disassembly

**Location**: `Source/Core/Core/Debugger/`

## See Also

* [Core Emulation](/architecture/core-emulation)
* [JIT Architecture Overview](/architecture/overview)
* [Debugging Guide](/contributing/debugging)
