Skip to main content
The recompile-tests command generates Catch2 test cases from PowerPC assembly source files with embedded test specifications. This is used for validating the recompiler’s correctness.
This command is primarily for ReXGlue SDK development and testing the recompiler itself. End-user projects typically don’t need this command.

Usage

rexglue recompile-tests --bin-dir <path> --asm-dir <path> --output <path>

Required Flags

--bin-dir
string
required
Directory containing linked .bin and .map filesThese are PowerPC binaries linked at address 0x82010000 (matching the -Ttext linker flag).
--asm-dir
string
required
Directory containing .s assembly source filesAssembly files must include test specification comments (#_REGISTER_IN, #_REGISTER_OUT, etc.).
--output
string
required
Output directory for generated test codeThe command generates:
  • ppc_config.h - Test memory layout configuration
  • ppc_test_functions.cpp - Recompiled PPC functions
  • ppc_test_cases.cpp - Catch2 test cases
  • ppc_test_decls.h - Function declarations

Test Specification Format

Assembly files use special comments to specify test cases:
# Test function with register inputs/outputs
test_add:
#_REGISTER_IN r3 0x10
#_REGISTER_IN r4 0x20
    add r5, r3, r4
#_REGISTER_OUT r5 0x30
    blr

# Test with vector registers
test_vector_add:
#_REGISTER_IN v0 [0x00000001, 0x00000002, 0x00000003, 0x00000004]
#_REGISTER_IN v1 [0x00000010, 0x00000020, 0x00000030, 0x00000040]
    vadduwm v2, v0, v1
#_REGISTER_OUT v2 [0x00000011, 0x00000022, 0x00000033, 0x00000044]
    blr

# Test with memory operations
test_load_store:
#_REGISTER_IN r3 0x1000
#_MEMORY_IN 0x1000 01 02 03 04
    lwz r4, 0(r3)
#_REGISTER_OUT r4 0x01020304
#_MEMORY_OUT 0x1000 01 02 03 04
    blr

Supported Test Directives

  • #_REGISTER_IN <reg> <value> - Set register before function call
  • #_REGISTER_OUT <reg> <value> - Assert register after function call
  • #_MEMORY_IN <addr> <hex bytes> - Initialize memory before function call
  • #_MEMORY_OUT <addr> <hex bytes> - Assert memory after function call

Register Types

  • General purpose: r0-r31 (64-bit integer values)
  • Floating point: f0-f31 (64-bit floating point, use decimal notation)
  • Vector: v0-v127 (128-bit, four 32-bit values in [w3, w2, w1, w0] order)
  • Condition register: cr (32-bit combined condition flags)

Examples

Basic Test Generation

rexglue recompile-tests \
  --bin-dir ./tests/ppc/bin \
  --asm-dir ./tests/ppc/asm \
  --output ./tests/generated
Output:
ReXGlue v0.1.0 - Xbox 360 Recompilation Toolkit
Recompiling PPC tests...
  Bin dir: ./tests/ppc/bin
  ASM dir: ./tests/ppc/asm
  Output dir: ./tests/generated
[Debug] Processing binary file: test_arithmetic
[Debug]   Found 24 functions
[Debug] Processing binary file: test_vector
[Debug]   Found 18 functions
Generated 42 test cases
Operation completed successfully in 1.234s

Generated Output

ppc_config.h

Defines the memory layout for test execution:
// Generated by rexglue recompile-tests
#ifndef PPC_CONFIG_H_INCLUDED
#define PPC_CONFIG_H_INCLUDED

// Test code base address (matches -Ttext=0x82010000 linker option)
#define PPC_IMAGE_BASE 0x82010000ull
#define PPC_IMAGE_SIZE 0x100000ull
#define PPC_CODE_BASE 0x82010000ull
#define PPC_CODE_SIZE 0x100000ull

#endif // PPC_CONFIG_H_INCLUDED

ppc_test_functions.cpp

Contains recompiled PPC functions:
// Generated by rexglue recompile-tests
#include "ppc_config.h"
#include <rex/ppc.h>
#include <rex/logging.h>

// Forward declarations
PPC_EXTERN_FUNC(test_arithmetic_82010000);
PPC_EXTERN_FUNC(test_arithmetic_82010010);
// ...

PPC_FUNC(test_arithmetic_82010000) {
  // Recompiled code
}

ppc_test_cases.cpp

Generated Catch2 test cases:
// Generated by rexglue recompile-tests
#include <catch2/catch_test_macros.hpp>
#include "ppc_config.h"
#include <rex/ppc.h>
#include <rex/system/xmemory.h>
#include "ppc_test_decls.h"

TEST_CASE("test_add", "[ppc][arithmetic][test_arithmetic]") {
    auto& mem = get_memory();
    uint8_t* memory = mem.virtual_membase();
    PPCContext ctx{};
    ctx.fpscr.loadFromHost();

    ctx.r3.u64 = 0x10;
    ctx.r4.u64 = 0x20;

    test_arithmetic_82010000(ctx, memory);

    REQUIRE(ctx.r5.u64 == 0x30);
}

ppc_test_decls.h

Function declarations for test cases:
// Generated by rexglue recompile-tests
#pragma once

#include "ppc_config.h"
#include <rex/ppc.h>

PPC_EXTERN_FUNC(test_arithmetic_82010000);
PPC_EXTERN_FUNC(test_vector_82010020);
// ...

Building Test Binaries

The .bin and .map files are typically generated from assembly sources using a PowerPC cross-compiler:
# Assemble and link (example using powerpc-eabi-gcc)
powerpc-eabi-gcc -c test_arithmetic.s -o test_arithmetic.o
powerpc-eabi-ld -Ttext=0x82010000 test_arithmetic.o -o test_arithmetic.elf
powerpc-eabi-objcopy -O binary test_arithmetic.elf test_arithmetic.bin
powerpc-eabi-nm test_arithmetic.elf > test_arithmetic.map
The base address must be 0x82010000 to match the TEST_BASE_ADDRESS constant in the recompile-tests implementation.

Running Generated Tests

The generated test files integrate with Catch2:
# Build test executable (example CMake configuration)
cmake --build build --target ppc_tests

# Run all tests
./build/ppc_tests

# Run specific category
./build/ppc_tests "[arithmetic]"

# Run specific test
./build/ppc_tests "test_add"

Test Categories

Tests are automatically tagged based on file naming:
File PatternCategoryDescription
*add*, *sub*, *mul*, *div*arithmeticInteger arithmetic
*cmp*comparisonComparison operations
*and*, *or*, *xor*, *rl*logicalLogical and rotate
f*, *_f*floating_pointFloating point operations
v*, *_v*vectorVMX/AltiVec vector operations
l*, st*memoryLoad/store operations
OthermiscMiscellaneous instructions

Common Errors

Missing Required Flags

--bin-dir, --asm-dir, and --output are required
Solution: Provide all three required directory paths.

No Symbols in Map File

No symbols found in map file: ./tests/ppc/bin/test_arithmetic.map
Solution: Ensure your map file is in nm format with symbols at the correct base address.

Test Recompilation Failed

Test recompilation failed
Solution: Check logs for details about which function failed to recompile. The assembly may contain unimplemented instructions.

Limitations

  • Fixed base address: Tests must be linked at 0x82010000
  • No imports: Test functions cannot call external libraries
  • Single module: All test functions must be self-contained
  • No OS calls: Tests run in isolated memory without kernel/OS support

Use Cases

  1. Recompiler validation - Ensure instructions are recompiled correctly
  2. Regression testing - Catch recompiler bugs during development
  3. Instruction coverage - Track which PPC instructions are implemented
  4. Accuracy testing - Verify edge cases and corner conditions

Next Steps

Build docs developers (and LLMs) love