Skip to content

Add little-endian PowerPC (ppc64le) support to VM JIT compiler - #860

Open
runlevel5 wants to merge 2 commits into
ioquake:mainfrom
runlevel5:ppc64le-jit-support
Open

runlevel5 wants to merge 2 commits into
ioquake:mainfrom
runlevel5:ppc64le-jit-support

Conversation

@runlevel5

@runlevel5 runlevel5 commented Feb 9, 2026

Copy link
Copy Markdown

Summary

The PowerPC VM JIT (vm_powerpc.c) was written for big-endian ppc/ppc64 only. This adds little-endian ppc64le support and fixes a few bugs that affect all PowerPC platforms. Addresses #300.

JIT (vm_powerpc.c)

  • Endian-independent immediate decoding and half-word/FPR accesses (HI16/LO16, FPRHI/FPRLO)
  • ELFv1/ELFv2 detection via _CALL_ELF: ELFv1 keeps the OPD, ELFv2 uses direct code addresses and sets r12 before indirect calls
  • Sign-extend the syscall number on 64-bit targets (the ELF ABI requires the caller to sign-extend int args); 32-bit is untouched
  • Removed an incorrect Z_Free of Hunk_Alloc'd memory (crashed on VM reload) and added __builtin___clear_cache() before mprotect() for the split D/I caches

Renderer / sound

  • Added VSX variants of the AltiVec paths — the classic vec_lvsl alignment trick is big-endian only. The VMX paths are kept for G4/G5 and the altivec.h include stays gated for Apple PPC
  • Fixed two long-standing big-endian AltiVec bugs I found while testing the VMX paths: RB_CalcDiffuseColor_altivec rotated every normal after the first (stale vec_lvsl(12) from a 12-byte-stride layout), and the sound mixer read a stale sample block whenever sampleOffset was 16-byte aligned

Build

  • cmake: ppc64le targets -mcpu=power8 (the ppc64le baseline); big-endian ppc64 keeps the compiler default so pre-POWER8 CPUs (970/G5, POWER5–7) still work
  • A PPC64LE_CPU cmake option (power8 default, power9, power10, native) raises the baseline for machine-specific builds — worth ~2% server CPU on a POWER9 in my benchmarks

POWER8+ JIT conversions

On -mcpu=power8 or newer builds, OP_CVIF/OP_CVFI use direct GPR↔FPR moves (mtvsrwa+fcfids, fctiwz+mfvsrwz) instead of the classic 0x4330-magic sequences and their stack round-trips. Results are bit-identical (verified against the old sequences across NaN/∞/saturation edge cases on both endians) and the generated code shrinks ~1%. Pre-POWER8 builds keep the original sequences.

Testing

All with retail Quake III data, dedicated server with bots on q3dm17 plus the JIT (vm_game 2):

Environment ABI Result
Fedora ppc64le on POWER9 ELFv2 LE pass
Arch POWER ppc64 VM ELFv2 BE pass (default and -mcpu=970 builds)
Debian 12 ppc64 VM ELFv1 BE pass

I also unit-tested the VSX and VMX vector paths (sound mixer, diffuse lighting, mesh lerp, normalize) against scalar references on both endians — that's how the two big-endian AltiVec bugs above were caught.

@runlevel5

Copy link
Copy Markdown
Author

@classilla @MPC7500 I would really appreciate if you could help review this PR for me. Great thanks in advance

Make the JIT endian-independent, detect ELFv1/ELFv2 via _CALL_ELF and
follow each ABI's calling convention, fix a Z_Free of hunk memory and a
missing I-cache flush, add VSX variants of the AltiVec renderer and
sound paths, and fix two long-standing big-endian AltiVec bugs.
@runlevel5
runlevel5 force-pushed the ppc64le-jit-support branch from 2d8227a to ade8709 Compare August 14, 2026 07:36
When built with -mcpu=power8 or newer, emit mtvsrwa+fcfids for OP_CVIF
and fctiwz+mfvsrwz for OP_CVFI instead of the classic double-magic
sequences, removing the stack round-trips. Add a PPC64LE_CPU cmake
option (power8/power9/power10/native) and schedule for POWER9 by
default while keeping the POWER8 baseline.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant