Commit Graph
3229 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5.5 3258bc2c8e Resistance: Retribution: Add smoke trail nodes at most every 1/30s
The debris smoke trails add a node on every update, so at 60fps the smoke was twice as dense
as at 30fps and spawned twice as many trails. Keep the nodes 1/30 of the effect's clock apart
instead. In the angel boss explosion the display list now peaks at 0x483ec bytes without the
overflow guard's help, against 0x637f4 before.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 11:42:18 +02:00
Henrik RydgårdandClaude Opus 5.5 6d9c85f366 Resistance: Retribution: Stop smoke trails overflowing the display list
- Fixes #19755

The game adds smoke trail nodes per update but expires them by time, so the faster we run, the
more trails are alive. After the angel boss in Bonn, the debris trails grow the display list
past its 0x5DC40 byte buffer at 60fps. The overflow lands in the music stream's Atrac buffer
(the "Invalid start bit" errors), corrupts textures, and crashes the game. Locking the CPU to
222MHz, the known workaround, slows the frame rate enough to avoid it.

Hook the trail draw and skip a trail when the current list buffer, whose limit the game keeps
next to its write pointer, is nearly full.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 11:42:17 +02:00
Henrik RydgårdandClaude Opus 5.5 a738fe9b86 Scan modules that only exist in a savestate for functions
A module the game loaded before the state was saved, but that this run never loaded, was never
scanned, so loading such a state left all of its code without function replacements and hooks
(and without functions in the debugger). Scan any loaded module with no analyzed functions in its
text range before rehashing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 11:22:06 +02:00
Henrik RydgårdandClaude Opus 5.5 9de0f6e45d bltzal and friends test rs from before they link
As on hardware (cpu/cpu_alu/branch_link_ra), with ra as rs the branch
sees its old value, not the return address. Every core linked first.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 09:55:35 +02:00
Henrik RydgårdandClaude Opus 5.5 38322d12ad IR: vmtvc to a masked control register reads vs
It read the VFPU register numbered like the control register instead.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 09:55:35 +02:00
Henrik RydgårdandClaude Opus 5.5 8c3f929615 IR: Keep d in vcmov's lanes that don't move under a D prefix
With a D prefix the result goes through temps, and a lane the condition
doesn't move kept whatever the temp held. They now start as d. That
exposed OptimizeFPMoves renaming the src3 of FCmovVfpuCC, which is also
its destination, so it no longer replaces a register an op reads as src3
and writes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 09:55:35 +02:00
Henrik RydgårdandClaude Opus 5.5 be09c1b25b IR: Compare store offsets as signed in OptimizeLoadsAfterStores
A store at a negative offset whose end wraps past zero, like 16 bytes at
-16, counted as ending before a load at -12, so the load reused an older
value from before the store.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 09:55:35 +02:00
Henrik RydgårdandClaude Opus 5.5 91a0ac7567 IR JITs: Flushing a host register that holds zero unmaps it
FlushNativeReg left a register caching MIPS zero mapped, as there's
nothing to store, but its callers flush to clobber the register. After
the dot product routine's call, a store of zero stored its result.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 09:55:35 +02:00
Henrik RydgårdandClaude Opus 5.5 130a637511 IR: vf2i and vi2f go through temps when the result overlaps the source
They wrote each lane straight to the destination, so with a destination
that holds a later lane's source (a wrapped row over a column, say) that
lane read the converted value.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 09:55:35 +02:00
Henrik RydgårdandClaude Opus 5.5 cc2fd7dcbb IR: Fix the matrix inits of transposed matrices with an offset
Like vmscl, they flipped the transposed bit to get Vec4s, which names
other registers for a matrix that wraps around. Taking the elements in
transposed order does it without.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 09:55:35 +02:00
Henrik RydgårdandClaude Opus 5.5 289c65d7a2 IR: Don't propagate an FP copy into a result that covers its source
OptimizeFPMoves replaced a temp read by vs2i (from a copy of a lane of
its own destination) with the original register, which the ARM64 JIT
then lost by mapping the destination without loading it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 09:55:35 +02:00
Henrik RydgårdandClaude Opus 5.5 8ca487910e IR: vc2i and vuc2i read their source at the size encoded
They read one lane, the first of the source vector at the size in the
instruction, as the interpreter does, which for the pair and quad
encodings is another register than the single the IR took.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 09:55:35 +02:00
Henrik RydgårdandClaude Opus 5.5 480ebbe601 VFPU: vfim converts its half float like vh2f
As on hardware (cpu/vfpu/vfim), a denormal half becomes a signed zero,
and inf and NaN keep their mantissa bits in place. The interpreter got
denormals half their value, the IR the IEEE one.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 09:55:35 +02:00
Henrik RydgårdandClaude Opus 5.5 a1b845d051 IR: Fix vmscl of two transposed matrices with an offset
Both were turned into their untransposed forms to get Vec4s, but for a
matrix whose offset makes it wrap around, flipping the transposed bit
names other registers. Taking the elements of both in transposed order
gets the same Vec4s without that.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 09:55:35 +02:00
Henrik RydgårdandClaude Opus 5.5 73f1b9465a Interpreter: Vector loads ignore the D prefix's write mask
As on hardware (cpu/vfpu/prefix_load), lv.q, lvl.q and lvr.q write every
lane whatever mask a pending D prefix has, and leave the prefix pending,
like lv.s and mtv already did. The IR cores fall back to the interpreter
for lvl.q and lvr.q, so they get this too.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 09:55:35 +02:00
Henrik RydgårdandClaude Opus 5.5 f3c69fc5d1 Remove FakeJit and the pre-IR JitBlockCache
FakeJit was the native JIT for architectures without one, but the config
already forces those onto the IR interpreter, so CreateNativeJit() now
returns that instead. The vertex decoder fallback no longer needs
FakeEmitter.

JitBlockCache was the block cache of the pre-IR JITs. Its header keeps
the debug interface types the IR block caches use. Also removes the
JitInterface link hooks only it called, and the JitState fields tied to
it. This fixes a null dereference in the ImDebugger memory section,
which read GetBlockCache(), always null with the IR JITs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 02:24:25 +02:00
Henrik Rydgård f672916c77 Merge pull request #22568 from hrydgard/accurate-vdot-ir
Accurate VFPU dot products in every IR backend, on by default
2026-10-15 00:38:49 +02:00
Henrik RydgårdandClaude Opus 5.5 961726dc88 VFPU: vrnds takes its seed from the vs field
The toolchain encodes vrnds's operand in vs and leaves vd zero, so we
always seeded from S000. Resistance: Retribution reseeds per particle
from S620, which made every particle in its smoke and explosions take
new random values each frame. They flickered, and some never drew.

Hardware test: cpu/vfpu/vrnd (vs and vd fields).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 00:09:25 +02:00
Henrik RydgårdandClaude Opus 5.5 6757fdc128 x86-64 IR JIT: Address the dot routine's operands from CTXREG's offset
CTXREG points at mips->f[0] in the x86-64 IR JIT, 128 bytes into MIPSState,
but the dot routine's inf and NaN path stored its operands at
offsetof(MIPSState, vfpuDotArgs) from it. It read them back from the same
place, so the results were right, but it wrote over invalidateAll_ and 16
bytes past the end of mipsr4k. On Alpine that crashed the unit tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 23:10:59 +02:00
Henrik RydgårdandClaude Opus 5.5 136e6ca927 IR: Include prefix constants past the vector size in the accurate dot products
On the PSP, lanes past the vector size where both the S and T prefixes are
constants add their product to vdot, and an S constant there is added in by vfad
and vavg (cpu/vfpu/prefix_lanes). Without AccurateVdot, the IR leaves those to
the interpreter; the accurate dot products now include them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:30:37 +02:00
Henrik RydgårdandClaude Opus 5.5 6207ef9ec7 x86-64 IR JIT: Call the dot routine with the operands in registers
The operands go in xmm0 and xmm1 and the result comes back in edi. The routine
saves nothing: the call site flushes whatever guest state is in the registers it
clobbers, the xmms allocated last and rax, rcx, rdx, rsi and rdi, the last two
never allocated outside Windows. 32-bit x86 keeps going through the IR
interpreter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:30:37 +02:00
Henrik RydgårdandClaude Opus 5.5 bc7afa8845 ARM32 IR JIT: Call a NEON dot routine for the accurate dot products
After clang's ARMv7 output for vfpu_dot_neon(), in Q8-Q15, which the register
cache leaves alone. The end is done in 32-bit integers instead of 64-bit ones,
checked bit-exact against vfpu_dot_finish(). The call site gathers the lanes into
Q8 and Q9 and flushes whatever guest state is in R2, R3, R12 and LR, usually
nothing. Inf and NaN go through a routine that calls vfpu_dot_reference().
Without NEON, Vec4VfpuDot still goes through the IR interpreter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:30:37 +02:00
Henrik RydgårdandClaude Opus 5.5 bd54c3e659 Compat: Replace MoreAccurateVMMUL with ForceAccurateVdot
The games that needed vmmul's accurate dot products (Tekken 6, Warriors Orochi,
Tomb Raider Anniversary) now get AccurateVdot for every dot product, even with
the setting turned off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:30:37 +02:00
Henrik RydgårdandClaude Opus 5.5 0b4b70e67e ARM64 IR JIT: Call the dot routine with the operands in registers
The operands go in q0 and q1 and the result comes back in w1. The routine saves
nothing: the call site flushes whatever guest state is in the few registers it
clobbers (q4-q6, w0-w3), which come late in the allocation order, so usually
there's nothing to do. That's about 20 bytes a call, with nothing going through
memory, and as fast as having the whole thing inline, which made a vmmul.q about
5 KB of code. Inf and NaN go through a routine that calls vfpu_dot_reference().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:30:37 +02:00
Henrik RydgårdandClaude Opus 5.5 27ef4e3c09 x86-64 JITs: Make the VFPU dot routine SSE2, after vfpu_dot_sse2
Inf and NaN still go to vfpu_dot_reference().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:30:36 +02:00
Henrik RydgårdandClaude Opus 5.5 605057864e ARM64 emitter: Add vector BIC, and use it for the dot routine's normal mask
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:30:36 +02:00
Henrik RydgårdandClaude Opus 5.5 3e1198bf22 ARM64 JITs: Make the VFPU dot routine NEON, after clang's vfpu_dot_neon
It was integer code, about four times the work. It also clobbers q0-q3 and
x16/x17 now, which both ARM64 JITs keep free, instead of saving them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:30:36 +02:00
Henrik RydgårdandClaude Opus 5.5 fa25caf905 x86-64 IR JIT: Run Vec4VfpuDot through a shared routine
GenerateX64VfpuDot() is the x86-64 counterpart of GenerateArm64VfpuDot(): the
same integer version of vfpu_dot(), preserving every register but the flags,
with inf and NaN operands going to vfpu_dot_reference(). A dest lane inside a
source Vec4 still takes the generic fallback, like Vec4Dot does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:30:36 +02:00
Henrik RydgårdandClaude Opus 5.5 8ac395c566 ARM64 IR JIT: Run Vec4VfpuDot through a shared routine
GenerateArm64VfpuDot() generates vfpu_dot() as integer code, once per JIT, to
be called with BL. The operands and result go through mips->vfpuDotArgs and
vfpuDotResult, and the routine preserves every register but x30, so a call
site is two stores, the BL and a load, with nothing flushed. Inf and NaN
operands go to vfpu_dot_reference(), with the caller-saved registers saved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:30:36 +02:00
Henrik RydgårdandClaude Opus 5.5 bbe2d79bea IR: Add Vec4VfpuDot, the VFPU's own dot product, and use it with AccurateVdot
The frontend lowers vdot, vhdp, vfad, vavg, vdet, vcrsp/vqmul, vtfm/vhtfm and
vmmul to it then, with the operands built from the same lanes, constants and
negations the interpreter feeds vfpu_dot(). BuildDotOperands() puts them in
Vec4 regs, using the free temps where they aren't one already, and the ops
fall back to the interpreter when there aren't enough. The IR interpreter runs
it through vfpu_dot(), and the native backends through their generic fallback
for now. vmmul takes the same path for the MoreAccurateVMMUL compat flag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:30:36 +02:00
Henrik RydgårdandClaude Opus 5.5 23fd6b4546 Interpreter: Use the accurate VFPU dot product when AccurateVdot is set
vdot, vhdp, vfad, vavg, vdet, vtfm/vhtfm, vcrsp/vqmul and vmmul compute
through vfpu_dot() then, as the PSP does. vmmul still also takes it from the
MoreAccurateVMMUL compat flag. With it, signed_zero matches the PSP, and
fcr31, nan_gen and specials get closer. What's left there is the single-lane
ops' NaNs and the VFPU's rounding.

vcrsp.t no longer zeroes infinities before its last dot: inf * 0 gives the
VFPU's NaN there on the PSP (cpu/vfpu/nan_gen). The NaN and denormal fixups in
vadd, vsub, vmul and vdiv shared the flag but aren't dot products, so they
get their own (still off).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:30:36 +02:00
Henrik RydgårdandClaude Opus 5.5 5633263580 x86-64 IR JIT: Keep NaNs through vsat0 and the [0:1] prefix
FSat0_1's MAXSS had the known 0 second, so a NaN came out as 0, unlike the
interpreter and the other backends, and the PSP (cpu/vfpu/prefix_sat, nan_gen).
-0.0 is now cleared by a compare and mask rather than by adding 0.0, which would
quiet a signaling NaN.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:05:21 +02:00
Henrik RydgårdandClaude Opus 5.5 124f86d7d0 VFPU: Decode prefixes with shared helpers
The prefix fields were decoded by hand in the interpreter, the IR frontend,
JitState, MIPSState and the disassembler, with three copies of the constant
table. They now share small decoders and one table, in MIPS.h. The backends'
Vec4Shuffle lane decoding gets a helper of its own in IRInst.h.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:34:05 +02:00
Henrik RydgårdandClaude Opus 5.5 66b26d08c1 IR: Leave the dot products with prefix constants past the vector size to the interpreter
On the PSP, lanes past the vector size where both the S and T prefixes are
constants add their product to vdot, and an S constant there is added in by vfad
and vavg (cpu/vfpu/prefix_lanes). The interpreter does that; the IR dropped those
lanes. Such prefixes are rare, so the IR leaves them to the interpreter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:11:03 +02:00
Henrik RydgårdandClaude Opus 5.5 e920666d72 ARM32 IR JIT: Pass float helper arguments the softfp way where needed
Android's armeabi-v7a uses the softfp calling convention, where floats travel in R0/R1, not S0/S1.
The math helper calls (vfpu_sin and the rest) only did the hard float version, so on Android they
got garbage and returned it (broken 3D in Virtua Tennis: World Tour). Like the old ArmJit, check
__ARM_PCS_VFP. With an armel softfp build under qemu, the fuzzer found 41 of 3000 cases where the
JIT differed from the IR interpreter before this, and none after.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 18:23:00 +02:00
Henrik RydgårdandClaude Opus 5.5 74703b031e Remove the legacy ARM32 JIT
The IR-based one replaces it. With that, every native JIT is IR-based, which the JIT viewer and
the settings' comments now assume. The ARM emitter test loses its part that drove the old FPU
register cache.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 17:32:53 +02:00
Henrik RydgårdandClaude Opus 5.5 e97ea7bea5 ARM32 IR JIT: Vec4 operations
With each lane in its own S register, these are scalar VFP ops per lane, and the packs go
through integer registers.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 17:32:53 +02:00
Henrik RydgårdandClaude Opus 5.5 adf31324ac ARM32 IR JIT: FPU arithmetic, compares, conversions and math helpers
VFPv3 has no scalar min/max and no conversions with a rounding mode of their own, so saturation
is compares and conditional moves, and round/ceil/floor swap FPSCR's RMode around the conversion
as the old ArmJit did. vmin/vmax compare by vfpu_minmax_key in integer registers.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 17:32:53 +02:00
Henrik RydgårdandClaude Opus 5.5 b7f361a0c1 ARM32 IR JIT: Loads and stores
The address is masked into a scratch register and used as an offset from the memory base.
VLDR/VSTR have no register offset form, so float and Vec4 accesses add the base first.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 17:32:53 +02:00
Henrik RydgårdandClaude Opus 5.5 c6f04ae4d6 ARM32 IR JIT: Integer arithmetic, logic, shifts, compares, mult and div
Mostly as on ARM64, with HI and LO in separate registers. Register shifts mask the amount to
five bits first, since ARM shifts by the whole bottom byte, and msub is a multiply followed by a
64-bit subtract. Division needs the IDIV extension and goes to the IR interpreter without it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 17:32:53 +02:00
Henrik RydgårdandClaude Opus 5.5 6d105ae35d ARM32: Start an IR-based JIT
The backend follows the ARM64 one: a dispatcher, a register cache on top of the IR one, and
native exits, syscalls, breakpoints and transfers. Everything else goes to the IR interpreter
for now. Floats are mapped one lane per S register (no SIMD mapping yet), and addresses are
masked, as on every 32-bit build.

The JIT core now uses it on ARM32 in place of the old ArmJit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 17:32:53 +02:00
Henrik RydgårdandClaude Opus 5.5 a56e5f2f6a ARM64 IR JIT: Keep the address out of SCRATCH1 across flushes
A flush stores pending imms through SCRATCH1, so in a non-constant MemoryCheck, and in
ValidateAddress's bad-address path, the address computed into SCRATCH1 could be replaced by an imm
before IRRunMemCheck or ReportBadAddress saw it. It now waits in SCRATCH2, which flushes don't use.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 17:10:35 +02:00
Henrik RydgårdandClaude Opus 5.5 985440a0c6 IR regcache: Load a dest that's a later lane of a source
When floats are mapped one lane at a time (RISC-V and LoongArch), a NOINIT dest was only upgraded
to a loaded one when a source had the same first reg. In Vec2Pack32To16 vf3, vf2,vf3 the dest is
the source's second lane, so it could be mapped without a load and the op read garbage. Found
with an IR-based ARM32 JIT, which failed vi2s.q C002, C000 in cpu/vfpu/overlap because of it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 17:10:35 +02:00
Henrik RydgårdandClaude Opus 5.5 f27b86c687 VFPU: Don't assert on mfv/mtv past the control registers
The encodings are reachable from guest code, and the CPUEquivalence fuzzer generates them, which
stopped a debug-build "UnitTest all" at the interpreter's assert. Every core already leaves rt
alone for mfv and writes nothing for mtv there (the IR interprets them), so only the asserts go.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 17:10:35 +02:00
Henrik RydgårdandClaude Opus 5.5 66d7975e7f Remove the legacy (non-IR) x86-64 and ARM64 JITs
Their IR-based replacements stay. The JIT core now creates the IR JIT on both, so "JIT using
IR" is the same as "JIT" on every architecture (ARM32 still uses its legacy JIT for both). The
settings no longer offer it, a saved JIT_IR loads as JIT, and the JIT harness and CPUEquivalence
fuzzer drop the duplicate run.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 14:39:45 +02:00
Henrik RydgårdandClaude Opus 5.5 48f9752235 ARM JIT: Leave matrix inits with a prefix to the interpreter, like the others
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:29:49 +02:00
Henrik RydgårdandClaude Opus 5.5 ad6f0ceea2 ARM JIT: Fix mtvc masking and vsgn of denormals, and interpret vh2f
mtvc masks the written control register like the other JITs, vsgn tests the
exponent (so a denormal gives 0, as in the interpreter), and the hardware
half-to-float conversion quiets NaNs, so vh2f goes to the interpreter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:29:49 +02:00
Henrik RydgårdandClaude Opus 5.5 0e908f466c ARM JIT: Gate VFPU ops on prefixes like the other JITs, and drop its vasin
The ARM32 JIT only checked for unknown prefixes, so a swizzle naming a lane
past the op's size, or a T prefix on vscl, read the wrong register or
asserted in VMOV. It now uses the ARM64 JIT's gates, and sends what they
refuse to the interpreter.

Its vasin was a polynomial approximation, not the bit-exact function the
other cores use (cpu/vfpu/exact failed 364 lines), so it goes to the
interpreter too, like vsin and vcos already did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:29:49 +02:00
Henrik RydgårdandClaude Opus 5.5 d7e449ab75 ARM JIT: Fix ins with msb below pos, ext past bit 31, and constant max/min
ins with msb below pos encoded an invalid BFI instead of doing nothing,
as the interpreter and the other JITs do, and ext with pos + size past 32
an invalid UBFX. max and min of two constants compared them unsigned.
Found by CPUEquivalence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:29:49 +02:00
Henrik RydgårdandClaude Opus 5.5 b025e9f819 VFPU: vcmov with imm3 = 7 tests a CC bit that is always clear
So vcmovt never moves and vcmovf always moves (cpu/vfpu/undefined). The
interpreter did nothing for either, and the JITs took it as imm3 = 6,
one CC bit per lane.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 11:59:35 +02:00