Skip to content

Windows/iOS: LRCPC2 on and AFP off for the ARM64EC module - #11

Merged
willfaust merged 1 commit into
willfaust:ios-port-2607from
spitefulowl:cpu-perf-fixes
Oct 4, 2026
Merged

willfaust merged 1 commit into
willfaust:ios-port-2607from
spitefulowl:cpu-perf-fixes

Conversation

@spitefulowl

@spitefulowl spitefulowl commented Oct 3, 2026 •

Copy link
Copy Markdown

A local change for the iOS port, not meant for FEX-Emu upstream: FEX's contribution policy forbids AI-generated code (see CLAUDE.md).

Why

Ori and the Will of the Wisps is CPU-bound (GPU busy 12-14 ms of a ~25 ms frame), mostly in translated x64 code. For the ARM64EC module, where Unity-class games spend their CPU:

  • FEAT_LRCPC2 lets a TSO guest access [reg+disp] be one LDAPUR/STLUR instead of an ADD plus LDAPR/STLR. In the game's hot JIT code nearly every LDAPR had that ADD in front of it.
  • FEAT_AFP makes FEX write FPCR on every entry to and exit from JIT code, twice per x64 → ARM64EC call. An FPCR write is expensive on Apple cores: ~9% of the render thread's samples sat on the instruction after the write in ExitFunctionEC.

Change

The FEX_IOS_HOST branch of FetchHostFeatures, for the ARM64EC module only:

  • LRCPC2 is taken only from an explicit LRCPC2=1 in the app's sysctl probe (FEX_MADEIRA_HOSTPROBE), because a wrong "present" is SIGILL.
  • AFP is off by default.
  • FEX_HOSTFEATURES=enableafp restores AFP (unless the probe says AFP=0), and FEX_HOSTFEATURES=disablelrcpc2 turns the offset forms off.
  • One FEX: ml1231 iOS ARM64EC host features line logs the result.

The WOW64 module is left alone: its guest window folds every displacement into the address.

Safe to merge on its own

The current Madeira app does not report LRCPC2 in its probe, so with this merged alone LRCPC2 stays off and only AFP changes. Once FEX emits LDAPUR/STLUR, Wine's fault emulators must decode them. That decoding, together with the probe key, is in willfaust/Madeira#184, which pins this commit together with willfaust/wine#23. Merge this one first.

Testing

Ran on the device with Ori and the Will of the Wisps. The log shows LRCPC2=true AFP=false, and the owner reported a large frame-rate and CPU gain. No before/after numbers were logged.

Notes

No binary is included. app/Madeira/arm64ec-windows/xtajit64.dll needs a rebuild (build/fex-arm64ec/build.sh).

🤖 Generated with Claude Code

Local Madeira change for the iOS port; not for FEX-Emu upstream (FEX's
contribution policy forbids AI-generated code, see CLAUDE.md).

The FEX_IOS_HOST branch of FetchHostFeatures hand-rolls the host features.
For the 64-bit (ARM64EC) module, where Unity-class games spend their CPU:

- FEAT_LRCPC2 lets a TSO guest access [reg+disp] be one LDAPUR/STLUR
  instead of an ADD plus LDAPR/STLR; in Ori and the Will of the Wisps' hot
  JIT code nearly every LDAPR had that ADD in front of it. A wrong `true`
  is SIGILL, so it is taken only from an explicit LRCPC2=1 in the app's
  sysctl probe (FEX_MADEIRA_HOSTPROBE, the Madeira branch of the same name
  adds it). The WOW64 module is left alone: its guest window folds every
  displacement into the address.
- FEAT_AFP is off by default. With it FEX writes FPCR on every entry to and
  exit from JIT code, twice per x64 -> ARM64EC call, and an FPCR write is
  expensive on Apple cores: ~9% of Ori and the Will of the Wisps'
  render-thread samples sat on the instruction after the write in
  ExitFunctionEC.

FEX_HOSTFEATURES=enableafp restores AFP (unless the probe says AFP=0) and
FEX_HOSTFEATURES=disablelrcpc2 turns the offset forms off. One
"FEX: ml1231 iOS ARM64EC host features" line logs the result.

Once FEX emits LDAPUR/STLUR, the unix-side fault emulators must decode them;
that is in the Madeira branch of the same name and must ship together.

Ran on the device (Ori and the Will of the Wisps): the log shows
"LRCPC2=true AFP=false" and the owner reported a large frame-rate and CPU
gain; no before/after numbers were logged. Rebuild
arm64ec-windows/xtajit64.dll with build/fex-arm64ec/build.sh (not committed).

Signed-off-by: spitefulowl <spitefulowll@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@willfaust
willfaust merged commit 09a86a8 into willfaust:ios-port-2607 Oct 4, 2026
willfaust added a commit to willfaust/Madeira that referenced this pull request Oct 4, 2026
…ebuilt DLLs

- wine (willfaust/wine#22, #23, #24): ntdll.dll (stripped, padded to
  SizeOfImage + 0x50000) and kernelbase.dll rebuilt; the provenance record
  lists the three changes.
- FEX (willfaust/FEX#11, #12, and the ARM64EC module honouring the app's
  host feature probe): xtajit64.dll and xtajit.dll rebuilt.
- DXMT (willfaust/dxmt#16, #17): the 64-bit d3d11.dll and dxgi.dll rebuilt;
  the unix side is rebuilt with the app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
willfaust added a commit to willfaust/Madeira that referenced this pull request Oct 4, 2026
Wine and FEX runtime fixes, DXMT texture and memory fixes, audio, the swap
tier and library launch options (#178-#187 and willfaust/wine#22-#24,
willfaust/FEX#11-#12, willfaust/dxmt#16-#17).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

2 participants