Add sentinel bits after the left-shift so clz stops at the correct
count (8 or 16) instead of counting through all 32 bits of the
widened register. Unlikely to hit in practice since PPC only has
cntlzw/cntlzd, but corrects existing sub-word variants.
Expands the vector register allocator from 20 to 28 registers by
including v8-v15. The HostToGuestThunk now saves/restores full Q8-Q15
(128-bit) instead of just D8-D15, and the GuestToHostThunk adds Q8-Q15
to its save/restore set since AAPCS64 only preserves their lower 64
bits across C calls.
Reduces register pressure for VMX-heavy guest code at the cost of
slightly larger thunk stack frames.
Reserves x19 to permanently hold the A64BackendContext pointer
(x20 - sizeof(A64BackendContext)), set once in the HostToGuestThunk.
Since x19 is AAPCS64 callee-saved, it survives all host calls for free.
Eliminates repeated 2-instruction mov+sub sequences in stackpoint
push/pop, stack synchronization, FPCR management, and reserved
load/store paths.
Reduces allocatable GPRs from 8 to 7 (like on x64).
Use the provided scratch register-index, defaults to W0/X0, and insert 64-bit elements directly into the vector-register rather than writing/reading to scratch memory.
Should allow certain splats to opportunistically emit the best assembly when possible.
Also use `std::bit_cast` rather than an inline `union` type to directly
cast a `float` into a `uint32_t`.
The `BRK` instruction code needs to be specified correctly so that a debugger can handle it properly(and continue from it). `brk 0xF000` implements a debug-breakpoint that can be continued from, and `brk 0xF001` is implemented an assertion failing. Any other codes like `0` and `F1` will not be able to be continued from or handled correctly by debuggers.
These seem to be standard brk codes:
```
Breakpoint 0xF000
Assert 0xF001
Debug Service 0xF002
Fastfail 0xF003
Divide by 0 0xF004
```
Rather than using a `mov` and vector-`dup` for vector-splats, just use the `movi` instruction where applicable(8-bit element-splats).
Eventually we might want to detect opportunities to use `FMOV` and the 64-bit form of `MOVI` over in `LoadV128Const`.
Track PPC scalar FP state in the backend context and restore it at
host/guest boundaries so translated FP code has a stable rounding mode.
Convert remaining VMX sequences to scoped EmitWithVmxFpcr. Remove
unnecessary ChangeFpcrMode from sequences that only call native helpers.
Co-Authored-By: Reality <reality@xenios.jp>
Save and restore FPCR around each VMX FP operation so vector code
doesn't leak FPCR state into scalar paths. Drop the DN bit so NaN
propagation fixup can inspect original payloads.
The A64 sequence table is populated by registration statics spread across
multiple translation units. Keeping the backing map as a global object makes
registration depend on cross-TU initialization order and can hit the table
before it has been constructed.
Move the sequence table behind a function-local static so sequence
registration is safe regardless of which unit initializes first.
Based entirely off existing xbyak x86 implementation and available
tests. Still needs a lot of optimization and testing on non-Windows
platforms.
So far passes all tests and boots at least some games on Windows.
On posix run tests in parallel using a thread pool with fork-per-test
isolation (ported from edge).
On all platforms add progress output showing suite name and test count,
as well as elapsed time in the summary.
Copy src1 into dest before the masked vrangeps so that unmasked lanes
(normal/inf/NaN values) are preserved via merge-masking. Previously,
when the register allocator assigned different physical registers for
dest and src1, unmasked lanes would retain stale values from dest.
Tested with Intel SDE and AVX-512 cpu to verify.
Also shift unused FpRangeSign constants into bits [3:2] of the vrangeps
immediate, matching the Intel encoding. Only one used in the code was 0
so it was already correct by accident but using the others in the future
would produce incorrect results.
Use the `vptestnmd`-instruction to quickly test if the exponent bits of
each element is zero and put these results into a mask register. This
mask register can then be used to write `+0.0` or `-0.0` values
depending on the original value's sign-bit.
A masked `vrangeps` instruction is used to move zero-values into the effected
elements while preserving the sign-bit without having to touch memory.
Adds support for systems with host pages > 4KB (some Linux distros,
MacOS) where guest 4KB page operations can't map 1:1 to host mprotect calls.
No-op on windows and posix systems with 4KB page size.
Co-authored-by: Will Martin <wmarti@bu.edu>
When emit_inline_mmio_checks is enabled, the x64 backend emits
explicit address range checks (0x7FC00000–0x7FFFFFFF) before I32 memory
ops and routes hits through MMIOAwareLoad/Store directly, avoiding the
cost of trapping access violations for MMIO regions. The MMIO page
commit in AddVirtualMappedRange is skipped in this mode since accesses
are handled inline rather than via exception.
version.h is now found via CMAKE_BINARY_DIR on the include path instead
of a hardcoded "build/version.h" path. This allows out-of-tree and
multi-config builds to each generate and find their own version header
without colliding.