Files
ARMSX2/pcsx2/arm64/Vif_UnpackNEON.h
Brian Degenhardt 3e077eff9b Merge yaps2: arm64 JIT transplant + test/perf/libretro infrastructure
Merges yaps2/main (github.com/yaps2/yaps2, c16b88cb7) into ARMSX2,
replacing the arm64 recompiler family with the yaps2 JITs and importing
the yaps2 testing, perf, and libretro infrastructure. Common ancestor is
upstream PCSX2 342db5152 (2026-06-19); git auto-merged all but 38 files.

Replaced (deleted in this merge, recoverable from history):
- arm64/aR5900*, aR3000A*, aVU* -> arm64/iR5900*/iR3000A*/microVU*-arm64:
  EE static-pin register file with lazy dirty tracking, dual-residence
  allocator, IOP block linking, native COP2 macro ops, inline unaligned
  fastmem, persisted VU program cache, call-ret shadow ring, VU0 spin
  fast-forward.
- MVU_DIFF shadow-run hooks in shared VU interpreter TUs (superseded by
  the offline vurunner JIT-vs-interp oracle).

Imported from yaps2:
- tests/ctest/core/recompilers: ~80 gtest suites (EE/IOP/VU differential
  harnesses, fuzzers, ABI digest tripwire, capture format pins) plus the
  gs_vertex_tests kernel oracle.
- pcsx2-vurunner / pcsx2-eerunner headless capture-replay runners.
- tools/perf counter-based A/B rigs, perf jitdump productionization,
  PmuCounters, clang-perf/clang-handheld presets.
- pcsx2-libretro core (ENABLE_LIBRETRO, default OFF; rename pending).
- GS vertex-kick fast path (GV series): TBL-based packed parse,
  register-resident kick, scalar-outcode cull, fused draw-rect/FindMinMax.
- Null renderer, VK_KHR_display direct WSI, swapchain PresentStats.
- SPU2 NEON mixer vectorization, EE timer read clamp (NFL 2K5 hang),
  IOP ioman signed-compare fix, assorted UB fixes.

Kept from ARMSX2 in the both-touched files:
- iOS dual-map W^X and fastmem-unavailable resilience (Memory, HostSys,
  vtlb). The split data/code area model is retained; both areas now take
  fixed VA hints so cached VU JIT code stays deterministic on Linux.
- Android thread-affinity model, VMState shutdown early-outs, all
  platform frontends, branding, CI, RetroAchievements identity/policy.
- GSDeviceVK: ARMSX2's push-descriptor decision logic (Mali crash gate,
  proprietary-vs-turnip Adreno split) merged with yaps2's descriptor-pool
  exhaustion recovery (flush + render-pass restart instead of dropped
  binds). Vendor feature policy is the union: Mali fbfetch policy with
  MediaTek/G57/Xclipse gates from ARMSX2; Adreno stencil/ROV/
  test-and-sample-depth hang avoidance and no_ps2_z_quantization from
  yaps2.

Build-system notes:
- The Qt debugger is now gated behind ENABLE_QT_DEBUGGER (default off on
  arm64) so handheld builds drop the KDDockWidgets dependency.
- GSDeviceNone and remaining yaps2 GS code were ported to the newer
  upstream GSTexture Usage-flags API.

The replaced backend's interpreter-fallback glue (intExecuteOneInst,
AndroidEEOpHist) and the EEDiffVerify runtime differ are retained for
now; dead pieces will be removed in a follow-up commit.
2026-07-19 10:24:29 -07:00

152 lines
4.4 KiB
C++

// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
// SPDX-FileCopyrightText: 2026 isztld <https://isztld.com/>
// SPDX-License-Identifier: GPL-3.0
#pragma once
#include "Common.h"
#include "Vif_Dma.h"
#include "Vif_Dynarec.h"
#include "arm64/AsmHelpers.h"
// Shared with microVU — single definition in arm64/microVU_Misc-arm64.inl
// (mirrors x86, where newVif.h declares the helper defined in microVU_Misc.inl).
extern void mVUmergeRegs(const vixl::aarch64::VRegister& dest, const vixl::aarch64::VRegister& src, int xyzw, bool modXYZW = false);
#define xmmCol0 vixl::aarch64::q2
#define xmmCol1 vixl::aarch64::q3
#define xmmCol2 vixl::aarch64::q4
#define xmmCol3 vixl::aarch64::q5
#define xmmRow vixl::aarch64::q6
#define xmmTemp vixl::aarch64::q7
// --------------------------------------------------------------------------------------
// VifUnpackSSE_Base
// --------------------------------------------------------------------------------------
class VifUnpackNEON_Base
{
public:
bool usn; // unsigned flag
bool doMask; // masking write enable flag
int UnpkLoopIteration;
int UnpkNoOfIterations;
int IsAligned;
protected:
vixl::aarch64::MemOperand dstIndirect;
vixl::aarch64::MemOperand srcIndirect;
vixl::aarch64::VRegister workReg;
vixl::aarch64::VRegister destReg;
vixl::aarch64::WRegister workGprW;
public:
VifUnpackNEON_Base();
virtual ~VifUnpackNEON_Base() = default;
virtual void xUnpack(int upktype) const;
virtual bool IsWriteProtectedOp() const = 0;
virtual bool IsInputMasked() const = 0;
virtual bool IsUnmaskedOp() const = 0;
virtual void xMovDest() const;
protected:
virtual void doMaskWrite(const vixl::aarch64::VRegister& regX) const = 0;
virtual void xShiftR(const vixl::aarch64::VRegister& regX, int n) const;
virtual void xPMOVXX8(const vixl::aarch64::VRegister& regX) const;
virtual void xPMOVXX16(const vixl::aarch64::VRegister& regX) const;
virtual void xUPK_S_32() const;
virtual void xUPK_S_16() const;
virtual void xUPK_S_8() const;
virtual void xUPK_V2_32() const;
virtual void xUPK_V2_16() const;
virtual void xUPK_V2_8() const;
virtual void xUPK_V3_32() const;
virtual void xUPK_V3_16() const;
virtual void xUPK_V3_8() const;
virtual void xUPK_V4_32() const;
virtual void xUPK_V4_16() const;
virtual void xUPK_V4_8() const;
virtual void xUPK_V4_5() const;
};
// --------------------------------------------------------------------------------------
// VifUnpackSSE_Simple
// --------------------------------------------------------------------------------------
class VifUnpackNEON_Simple : public VifUnpackNEON_Base
{
typedef VifUnpackNEON_Base _parent;
public:
int curCycle;
public:
VifUnpackNEON_Simple(bool usn_, bool domask_, int curCycle_);
virtual ~VifUnpackNEON_Simple() = default;
virtual bool IsWriteProtectedOp() const { return false; }
virtual bool IsInputMasked() const { return false; }
virtual bool IsUnmaskedOp() const { return !doMask; }
protected:
virtual void doMaskWrite(const vixl::aarch64::VRegister& regX) const;
};
// --------------------------------------------------------------------------------------
// VifUnpackSSE_Dynarec
// --------------------------------------------------------------------------------------
class VifUnpackNEON_Dynarec : public VifUnpackNEON_Base
{
typedef VifUnpackNEON_Base _parent;
public:
bool isFill;
int doMode; // two bit value representing difference mode
bool skipProcessing;
bool inputMasked;
protected:
const nVifStruct& v; // vif0 or vif1
const nVifBlock& vB; // some pre-collected data from VifStruct
int vCL; // internal copy of vif->cl
public:
VifUnpackNEON_Dynarec(const nVifStruct& vif_, const nVifBlock& vifBlock_);
VifUnpackNEON_Dynarec(const VifUnpackNEON_Dynarec& src) // copy constructor
: _parent(src)
, v(src.v)
, vB(src.vB)
{
isFill = src.isFill;
vCL = src.vCL;
}
virtual ~VifUnpackNEON_Dynarec() = default;
virtual bool IsWriteProtectedOp() const { return skipProcessing; }
virtual bool IsInputMasked() const { return inputMasked; }
virtual bool IsUnmaskedOp() const { return !doMode && !doMask; }
void ModUnpack(int upknum, bool PostOp);
void ProcessMasks();
void CompileRoutine();
protected:
virtual void doMaskWrite(const vixl::aarch64::VRegister& regX) const;
void SetMasks(int cS) const;
void writeBackRow() const;
static VifUnpackNEON_Dynarec FillingWrite(const VifUnpackNEON_Dynarec& src)
{
VifUnpackNEON_Dynarec fillingWrite(src);
fillingWrite.doMask = true;
fillingWrite.doMode = 0;
return fillingWrite;
}
};