Files
LibretroAdmin 802e144624 arm7: an ARM7 recompiler for 32-bit x86, the same as x86-64's
Linux i686, Windows i686 and Android x86 ran the sound processor through
the interpreter: the old reicast recompiler's x86 backend is gone, and
upstream flycast has none. They now run the recompiler x86-64 and ARM64
run - arm7_rec.cpp's decoder, blocks, cycle counts and register
allocator - with a backend of its own, arm7_rec_x86.cpp, written with
xbyak in 32-bit mode after arm7_rec_x64.cpp, instruction for instruction:

- a block's cycles come off at its end, and the time slice is over at
  none left or less; each block jumps on to the next itself, through the
  address's entry point when it is fixed;
- the flags stay in the ARM's register file; a logical instruction that
  sets them leaves V and takes the shifter's or the constant's carry; RSB
  and RSC take their carry from the subtraction; a shift by a register
  takes its low byte;
- registers are written back before conditional code and around MSR, as
  the shared allocator does for every backend;
- loads and stores to sound memory are done in line, the rest through
  the same calls; the program counter loses its low two bits wherever it
  is written.

What differs is the processor: four host registers for the ARM's (ebx,
ebp, esi, edi, which C code keeps), eax/ecx/edx for the rest - the
operands in edx and eax, the carry in ecx, the values a shift by 32 or
more gives taken from memory by cmov, RRX done with bt and rcr; data
reached at its absolute address; every call fastcall (ecx, edx), as
every handler called is DYNACALL, with the stack at a multiple of 16;
four bytes to an entry point. The main loop is written into the code
buffer as on x86-64, so the library has no text relocations.

build.h turns the ARM7 recompiler on for 32-bit x86 (so the Makefile's
i686 unix and win32 builds and jni/Android.mk's x86 have it, through
Makefile.common), and the Sound CPU Recompiler core option with it,
whose text now names 32-bit x86. tools/arm7/run.sh runs on i686 too
(ARCH=i686 with the cross compiler in MAKEARGS).

Tested here:
- tools/arm7 on i686, 10000 programs (8844 compared) and 10000 with mode
  changes (8694 compared): the recompiler, the interpreter and switching
  between the two agree; what the recompiled programs leave is the same
  as on x86-64 and on AArch64 (qemu), line for line, in both sets
- tools/threads/headless.sh passes on Linux i686, on Windows i686 under
  32-bit wine, and on Linux x86-64
- tools/determinism, default options (the ARM7 recompiler on on both),
  Jet Grind Radio from a state, 1000 frames: i686 the same as x86-64 at
  every frame
- Android x86 (NDK r27d) builds and links with no TEXTREL
- speed, Linux i686, headless, Jet Grind Radio 1801 frames from a state,
  two runs each: 3.30-3.40 s with the recompiler, 4.21-4.29 s with the
  interpreter (about 540 against 425 frames a second)

No save-state change. Blocks are compiled as before, when first reached;
nothing is allocated or waited for while they run.
2026-10-23 21:11:57 +02:00
..