Skip to content

DSP HLE Fix Examples and Testing

OpenAI Codex edited this page Nov 3, 2026 · 90 revisions

DSP HLE fixes: examples and testing

Experimental development work, not a complete DSP replacement. The running xemu HLE mode still uses the DSP JIT for unsupported work. Some files below are uncommitted worktree-only changes, unavailable at public source links. A match against xemu's JIT is not Xbox-hardware, Dolby, 5.1 or full game-audio proof.

Operation and DSP-PC inventory · Current results and complete measurement tables

Fix examples

These short excerpts are from the local source snapshot on 2026-11-03. DSP PCs identify instructions in an identified emulated program; they are not guest audio API command IDs.

Fix Location Purpose and limit
Program and filter guard gp-filter-hle.c, gp_filter_hle_try_run Admit a known program and selected filter positions; otherwise keep the DSP route.
Saturated 24-bit gain gp-gain-hle.h, gp_gain_hle (worktree-only) Compute 16 output samples in native code, staging output until input validation succeeds.
Native EP program validation ep-native-engine.h, ep_native_engine_validate_program (worktree-only) Clear prior approval before checking current program memory; changes revoke verification.
Transactional EP FIFO ep-native-engine.h, ep_native_engine_process_fifo (worktree-only) Stage engine state and PCM; commit the staged state only after the all-or-nothing FIFO callback succeeds.
DMA side effects dsp-replay.c, dsp_replay_native_dma_start (worktree-only changes) Invoke the existing peripheral and re-read state before restoring it, so DMA changes are preserved.
GP frame entry gp-frame-entry-project.h, gp_frame_entry_project (worktree-only) Project one guarded start-frame acknowledgement in offline replay. Strict replay next reaches an unhandled PC.
GP frame counter gp-frame-entry-project.h, gp_frame_counter_project (worktree-only) Read the existing emulated counter at 0xffffb3 and project the guarded write to X:0x7f.
GP frame DMA setup gp-frame-entry-project.h, gp_frame_setup_project (worktree-only) Project setup from 0x31 to 0x10a before native DMA stop/freeze.
GP DMA handoff gp-frame-entry-project.h, gp_frame_dma_prepare_project (worktree-only) Prepare DMA next-block from 0x112 to 0x118; strict replay executes the native sequence.
GP DMA completion gp-frame-entry-project.h, gp_frame_dma_complete_project (worktree-only) Project guarded end-of-list acknowledgement and return from 0x120 to 0x12c.
GP frame return gp-frame-entry-project.h, gp_frame_return_project (worktree-only) Project the zero X:4 branch from 0x12c to 0x33, or the nonzero branch to 0x66.
GP filter-entry handoff gp-frame-entry-project.h, gp_frame_filter_entry_project (worktree-only) Project 0x33 to 0x185 for odd X:0x84; even values are rejected.
GP first-filter bridge gp-filter-hle.c, gp_filter_hle_start_verified, gp_filter_hle_tail_verified (worktree-only changes) Bridge the first filter's entry and tail to existing native slices in offline strict replay.
GP eight-channel filter gp-filter-hle.c and gp-frame-entry-project.h, gp_filter_transition_project (worktree-only changes) Generalize first/tail handling across eight channels and project seven active-channel transitions. Inactive channels remain unqualified.
GP meter entry gp-frame-entry-project.h, gp_frame_meter_entry_project (worktree-only) Project post-filter setup for odd and even control paths before the meter.
GP meter transition gp-frame-entry-project.h, gp_meter_transition_project (worktree-only) Store the completed meter and prepare the next channel.
GP final meter exit gp-frame-entry-project.h, gp_meter_final_project (worktree-only) Write the last meter and restore loop/stack state when LC = 1.
GP post-meter dispatch gp-frame-entry-project.h, gp_post_meter_dispatch_project (worktree-only) Guard the X:0x1df = 3 route and project stack setup to 0x8d1; other control routes remain unsupported.
GP post-meter DMA return gp-frame-entry-project.h, gp_dma_return_project (worktree-only) Project 0x8d9 to 0x8df; replay writes the verified DMA next-block through the existing peripheral before the native sequence.
GP DMA return to gain gp-frame-entry-project.h, gp_dma_to_gain_project (worktree-only) Set six address-modulo registers and load the gain buffer pointer before the native gain entry at 0x493.
GP first gain return gp-frame-entry-project.h, gp_gain_next_project (worktree-only) Project the first 0x498 return back to 0x493.
GP gain to feedback gp-frame-entry-project.h, gp_gain_to_feedback_project (worktree-only) Project the second 0x498 return to native feedback entry 0x788.
GP first feedback return gp-frame-entry-project.h, gp_feedback_next_project (worktree-only) Project the first 0x792 return back to 0x788.
GP feedback-to-copy and stride copy gp-frame-entry-project.h, gp_feedback_to_copy_project, gp_stride_copy_project (worktree-only) Project the second feedback return and preserve ordered in-place copy behavior; guarded to the tested alias-buffer range and state.
GP copy acknowledgement and mix setup gp-frame-entry-project.h, gp_copy_ack_project, gp_ack_to_mix_project (worktree-only) Acknowledge DMA EOL through the existing peripheral, then prepare the tested mixing loop.
GP interpolation/mix loop gp-frame-entry-project.h, gp_mix_loop_project (worktree-only) Project six fixed-point values and accumulator/flags; reject overlap or unqualified clipping/delta.
GP mix-end dispatch gp-frame-entry-project.h, gp_mix_end_control_project (worktree-only) Follow two guarded control branches after the mixing loop.
GP control to ramp gp-frame-entry-project.h, gp_control_to_ramp_project, gp_ramp_loop_project (worktree-only) Prepare and execute the tested 16-sample gain ramp, including signed clipping.
GP special controls gp-frame-entry-project.h, gp_control_100_project, gp_control_zero_project (worktree-only) Handle a tested control-0x100 effect transition and zero-control ramp reset.
GP ramp to add gp-frame-entry-project.h, gp_ramp_to_add_project (worktree-only) Write completed gain/control, restore loop stack and set up the existing native add.
GP add continuation and MAC setup gp-frame-entry-project.h, gp_add_next_project, gp_add_final_to_mac_project (worktree-only) Continue the guarded add loop and set up the tested multiply-accumulate route.
GP MAC continuation and exit gp-frame-entry-project.h, gp_mac_next_project, gp_mac_final_project (worktree-only) Return to the next MAC or restore loop stack and flags on the guarded final exit.
GP second MAC setup gp-frame-entry-project.h, gp_mac_second_setup_project (worktree-only) Prepare tested buffer pointer, gain, nested loop and stack for the next native MAC.
GP nested MAC continuation gp-frame-entry-project.h, gp_mac_nested_next_project (worktree-only) Load the next gain and restore destination pointer and nested stack on the guarded return.
GP outer MAC continuation gp-frame-entry-project.h, gp_mac_outer_next_project (worktree-only) Exit the inner loop, advance source/destination pointers and set the next gain and stack.
GP outer MAC final exit gp-frame-entry-project.h, gp_mac_outer_final_project (worktree-only) Finish the guarded nested loops, read XRAM, advance pointer and restore stack and LF/FV flags.
GP three-pointer mix gp-frame-entry-project.h, gp_mix3_setup_project, gp_mix3_loop_project (worktree-only) Set up three pointers and sum 16 signed input pairs; reject clipping and output/input overlap.
GP mix return handoffs gp-frame-entry-project.h, gp_mix3_next_project, gp_mix3_to_add_project (worktree-only) Select by return address, reload buffers and enter the existing mixer or add.
GP post-mix add returns gp-frame-entry-project.h, gp_post_mix_add_next_project (worktree-only) Recognize three return addresses and reload guarded pointers for the next add.
GP add to mix gp-frame-entry-project.h, gp_add_to_mix3_project (worktree-only) Reload three audio buffer pointers and loop state before the tested mix.
GP mix to gain gp-frame-entry-project.h, gp_mix3_to_gain_project (worktree-only) Reload buffer/gain and enter the existing native gain.
GP post-mix gain returns gp-frame-entry-project.h, gp_post_mix_gain_next_project (worktree-only) Handle tested return sites 0x663 and 0x669 by reloading gain/buffer or continuing directly.
GP post-gain add handoffs gp-frame-entry-project.h, gp_post_gain_add_project (worktree-only) Enter add through tested return sites 0x66b and 0x671, with pointer reload or direct continuation.
GP post-gain copy gp-frame-entry-project.h, gp_post_gain_copy_setup_project, gp_post_gain_copy_loop_project (worktree-only) Set up and perform a guarded 16-sample copy, preserving ordered overlap and recognized aliases.
GP post-gain copy continuation gp-frame-entry-project.h, gp_post_gain_copy_next_project (worktree-only) Set loop state for the next copy at the tested return site.
GP copy to feedback gp-frame-entry-project.h, gp_copy_to_feedback_project (worktree-only) Reload audio and set feedback pointer, accumulator, flags and return stack.
GP post-copy feedback returns gp-frame-entry-project.h, gp_post_copy_feedback_next_project (worktree-only) Handle two tested return sites; the second sets up a three-block feedback loop.
GP feedback loop returns gp-frame-entry-project.h, gp_feedback_loop_next_project (worktree-only) Advance buffer/state pointers and restore loop stack for tested continuation and final exit.
GP feedback to matrix gp-frame-entry-project.h, gp_feedback_to_matrix_project (worktree-only) Prepare guarded buffer/coefficient pointers and four-iteration matrix setup.
GP matrix loop returns gp-frame-entry-project.h, gp_matrix_loop_next_project (worktree-only) Preserve coefficient, buffer and loop state through tested matrix continuations and final exit.
GP matrix-to-add setup gp-frame-entry-project.h, gp_matrix_add_setup_project (worktree-only) Load two buffers and set the guarded four-channel loop and return stack.
GP matrix add returns gp-frame-entry-project.h, gp_matrix_add_next_project (worktree-only) Continue the four-channel add and restore the loop stack on exit.
GP matrix-to-feedback setup gp-frame-entry-project.h, gp_matrix_feedback_setup_project (worktree-only) Set buffer, feedback state pointer and loop stack; reject unverified accumulator states.
GP matrix feedback loop returns gp-frame-entry-project.h, gp_matrix_feedback_next_project (worktree-only) Advance feedback state, continue the loop or restore the saved stack at its exit.
GP matrix feedback to copy gp-frame-entry-project.h, gp_matrix_copy_setup_project (worktree-only) Load guarded source and destination pointers and prepare the existing 16-sample copy loop.
GP matrix sample-copy return gp-frame-entry-project.h, gp_matrix_copy_return_project (worktree-only) Restore the return stack and reload four pointers for subsequent work.
GP matrix mixer dispatch gp-frame-entry-project.h, gp_matrix_mix_dispatch_project (worktree-only) Load mixer gains and choose the observed control-4 branch. Other controls are rejected.
GP matrix mixer continuation gp-frame-entry-project.h, gp_matrix_mix_next_project (worktree-only) Restore pointers and gains and choose the tested control-4 path for a second mix.
GP second mixer to copy gp-frame-entry-project.h, gp_matrix_mix_to_copy_project (worktree-only) Load buffers and prepare the copy loop after the second mixer.
GP duplicate-sample copy gp-frame-entry-project.h, gp_matrix_duplicate_copy_project (worktree-only) Copy each of 16 input samples twice in DSP order, preserving overlap behavior.
GP duplicate-copy return gp-frame-entry-project.h, gp_matrix_duplicate_return_project (worktree-only) Restore the verified return stack and prepare the next add.
GP post-duplicate add returns gp-frame-entry-project.h, gp_matrix_post_duplicate_add_project (worktree-only) Continue the add or prepare the next duplicate-sample copy.
GP late DMA wait entry gp-frame-entry-project.h, gp_late_dma_wait_entry_project (worktree-only) Enter the existing DMA completion wait without executing the preceding DSP return.
GP late DMA completion gp-frame-entry-project.h, gp_late_dma_wait_complete_project (worktree-only) Acknowledge completed DMA and restore the return stack; reject incomplete transfers.
GP post-DMA audio entry gp-frame-entry-project.h, gp_post_dma_audio_entry_project (worktree-only) Select the verified active control path and initialize DSP address modes.
GP post-DMA delay setup gp-frame-entry-project.h, gp_post_dma_delay_entry_project (worktree-only) Load delay pointers and coefficients and restore verified status flags.
GP post-DMA next delay gp-frame-entry-project.h, gp_post_dma_delay_next_project (worktree-only) Save the first delay state and set pointers and coefficients for the second channel.
GP post-DMA final delay return gp-frame-entry-project.h, gp_post_dma_delay_final_project (worktree-only) Save the second delay state and choose the observed active next stage.
GP decimation setup gp-frame-entry-project.h, gp_decimate_setup_project (worktree-only) Load tested pointers, phase and gain and project DSP flags before the native decimator.
GP decimation DMA handoff gp-frame-entry-project.h, gp_decimate_dma_entry_project (worktree-only) Save phase and output count before entering the existing DMA routine.
GP decimation DMA stop call and return gp-frame-entry-project.h, gp_decimate_dma_stop_entry_project, gp_decimate_dma_stop_return_project (worktree-only) Preserve the call stack around the existing native DMA stop/freeze operation.
GP decimation DMA descriptor setup gp-frame-entry-project.h, gp_decimate_dma_prepare_project (worktree-only) Update status and stack, then write the next descriptor through the DMA peripheral.
GP decimation DMA completion gp-frame-entry-project.h, gp_decimate_dma_wait_entry_project, gp_decimate_dma_wait_complete_project (worktree-only) Enter the wait and acknowledge completed transfers through the DMA peripheral.
GP next decimation channel gp-frame-entry-project.h, gp_decimate_next_channel_project (worktree-only) Select the tested active channel and prepare pointers, gain, phase and status.
GP decimation frame exit gp-frame-entry-project.h, gp_decimate_frame_exit_project (worktree-only) Return from the fourth channel to the frame tail.
GP frame-tail counter gp-frame-entry-project.h, gp_frame_tail_counter_project (worktree-only) Read the emulated counter and prepare a comparison; only zero is qualified.
GP frame-tail comparison and DMA gp-frame-entry-project.h, gp_frame_tail_dispatch_project, gp_frame_tail_dma_prepare_project, gp_frame_tail_dma_complete_project, gp_frame_tail_second_dma_project (worktree-only) Compare, dispatch and complete two DMA transfers using the existing peripheral.
GP frame-tail finish and halt gp-frame-entry-project.h, gp_frame_tail_finish_project, gp_frame_tail_halt_project (worktree-only) Complete both tested comparison branches and request halt through the existing peripheral.
GP native-state replay dsp-replay.c, dsp_init_gp_native_state (worktree-only) Run the candidate frame without creating a DSP JIT; compare separately with a JIT-backed reference.

Filter admission

From the committed file:

if (!hle || cycles != 1000 || cpu->pc < 0x185 || cpu->pc > 0x413) {
    return false;
}

Gain saturation

From the uncommitted gp-gain-hle.h:

int64_t word = gp_mix2_floor_shift(product, 24);
word = word < -0x800000 ? -0x800000 :
       word > 0x7fffff ? 0x7fffff : word;
staged[i] = (uint32_t)word & 0xffffff;

Special effect controls

These excerpts are from uncommitted gp-frame-entry-project.h, after program and state guards. For control 0x100, the path clears the control and prepares the add loop:

after->jit.xram[0x3da] = 0;
after->jit.xram[0x3d9] = 0x2000;
after->jit.cpu.pc = 0x4a0;

For zero control, the tested path prepares a decreasing gain ramp:

after->jit.cpu.registers[DSP_REG_Y0] = 0xff0000;
after->jit.cpu.registers[DSP_REG_A1] = 0x7f0000;
after->jit.cpu.registers[DSP_REG_B1] = 0x7f0000;

These snippets show only part of each operation; guards, memory writes, flags and stack setup remain necessary. The guarded 0x80 path is now supported for the tested inputs in offline replay; unqualified inputs are rejected.

For control 0x80, the worktree-only effect helper computes the tested bounded wrap in native code:

uint32_t loops = delta < 0 ? ((uint32_t)(-delta) + stride - 1) / stride : 0;
int64_t final = (int64_t)delta + (int64_t)loops * stride;
if (loops > 4096 || final < 0 || final > 0x7fffff) return false;

This excerpt omits the program/state guards and DSP register updates. It does not establish correctness for rejected inputs or live playback.

Multiply-accumulate

The 16-sample MAC uses signed 24-bit inputs, fixed-point rounding and saturated output. This excerpt is from the worktree-only gp-mac-hle.h; the full function also validates inputs and stages its output.

int64_t acc = 2 * gain * gp_mix2_signed24(src[i]) +
              gp_mix2_signed24(dst[i]) * 0x1000000;
int64_t word = gp_mix2_floor_shift(gp_mix2_round24(acc), 24);

Decimation

This observed 32-sample route selects output by phase and applies signed gain. This is a fragment of worktree-only gp-decimate-hle.h, not the complete operation; it also clamps samples and returns the next phase.

if (phase >= 6) {
    int32_t sample = input[i] & 0x800000 ?
                         (int32_t)input[i] - 0x1000000 :
                         (int32_t)input[i];
    int64_t product = (int64_t)sample * signed_gain;

The guarded setup at 0x97e is now included in offline strict replay. The math helper does not prove that every decimation route or its following DMA works.

EP program identity

Program validation, from the uncommitted ep-native-engine.h:

engine->program_verified = false;
if (!check) {
    return false;
}
engine->program_verified = check(opaque, engine->state.jit.pram);

Frame state and handoffs

Meter transition, from the uncommitted gp-frame-entry-project.h:

after->jit.xram[dest] = r[DSP_REG_A1];
after->jit.cpu.pc = 0x431;
after->jit.cpu.pc_advance = 1;
after->jit.cpu.cycle_count += 12;

Final meter exit, from the same uncommitted file:

after->jit.xram[0x1c9] = r[DSP_REG_A1];
after->jit.cpu.pc = 0x422;
after->jit.cpu.pc_advance = 0;
after->jit.cpu.cycle_count += 8;

Add continuation, from the same uncommitted file:

after->jit.cpu.pc = 0x4a0;
after->jit.cpu.pc_advance = 0;
after->jit.cpu.cycle_count += 12;

Matrix-to-add setup, from the uncommitted gp-frame-entry-project.h (after the program and state guards):

after->jit.cpu.pc = 0x4a0;
after->jit.cpu.cycle_count += 16;
after->jit.cpu.registers[DSP_REG_R1] = before->jit.xram[0x1eb];
after->jit.cpu.registers[DSP_REG_R0] = before->jit.xram[0x1f1];

Replay results at a glance

Saved-input check Result CPU / wall Peak child RSS
Control 0x80, entry / effect / ramp setup / signed ramp 256 / 512 / 256 / 256 varied cases matched Included below Included below
JIT-free candidate full frames 16 / 16 matched recorded final state and I/O with zero DSP steps Included below Included below
Mixed full frames 16 / 16 matched; zero DSP steps 1.128 / 1.161 s 30,392 KiB

These are combined offline test costs, not a native-versus-DSP performance comparison. The full progression and resource measurements are in the evidence archive. The resource figures are from a combined offline test campaign and are not comparable to earlier campaigns. The JIT-backed strict run completed all 16 frames, and the separate native-state candidate matched its status, state and I/O without constructing a JIT.

A FIFO probe must be side-effect-free and its commit must either write every byte or write none. The offline engine is not connected to the live device; the separate experimental JIT-backed EP route has focused guest-RAM FIFO tests.

Run focused tests

The following commands require the experimental worktree and an existing configured build/. Some targets and scripts below are uncommitted and will not exist at the public commit. Build configuration and DSP provider dependencies follow the local project setup.

ninja -C build test-xbox-ep-mix-hle test-xbox-ep-native-engine \
  test-xbox-gp-gain-hle test-xbox-gp-mac-hle test-xbox-mcpx-apu-dsp-replay
build/test-xbox-ep-mix-hle
build/test-xbox-ep-native-engine
build/test-xbox-gp-gain-hle
build/test-xbox-gp-mac-hle

Use existing private captures for replay; they can contain game program and audio data. The strict mode stops at the first unhandled operation instead of executing a DSP instruction, but still constructs a JIT backend for state and DMA.

build/test-xbox-mcpx-apu-dsp-replay --replay-gp-hle-strict /path/to/private/gp-frame
build/test-xbox-mcpx-apu-dsp-replay --replay-native-ep-candidate /path/to/private/ep-frame
build/test-xbox-mcpx-apu-dsp-replay --replay-native-ep-sequence \
  --repeat 100 /path/to/private/ep-frame.bin.*

Offline DSP-vs-native synthetic checks require private host-ABI GP pairs and use the DSP JIT as the reference. Rejected cases are unsupported, not matches.

build/test-xbox-mcpx-apu-dsp-replay --fuzz-gp-gain /path/to/private/gain-pairs --variants 4096
build/test-xbox-mcpx-apu-dsp-replay --fuzz-gp-mac /path/to/private/mac-pairs --variants 4096
build/test-xbox-mcpx-apu-dsp-replay --fuzz-gp-decimate /path/to/private/decimate-pairs --variants 4096

Compact resource reference

These measurements have different scopes and are not interchangeable. The following earlier results are retained for context, not proof of current-head performance:

Offline test Median CPU Sampled process peak RSS Scope
EP standalone mixer, 256 stereo frames 2.6056 µs/block 1,612 KiB Native-only fixture, five runs; no DSP baseline.
GP gain, 16 samples 0.7893 µs/projection 1,776 KiB Native full-state projection, fixed input; no DSP baseline.
GP multiply-accumulate, 16 samples 0.7797 µs/projection 1,804 KiB Native full-state projection, fixed input; no DSP baseline.
EP verified 64-frame chain 36.32 µs/frame 30,004 KiB Linked replay process, including verification; no DSP execution or baseline.

A separate synthetic FIFO microbenchmark measured 86.86 → 115.39 ns/write, an increase of 28.52 ns / 32.83% cost, with mock dirty marking. It is not an overall emulator or game comparison. See the overview for all workloads, earlier results, variations and limitations.

Clone this wiki locally