Core: ARM64 compatibility

This commit is contained in:
Stenzek
2024-06-14 17:06:45 +10:00
committed by Connor McLaughlin
parent 7d098674f2
commit 71036c95a4
26 changed files with 411 additions and 361 deletions
-2
View File
@@ -954,7 +954,6 @@ set(pcsx2x86Sources
x86/ix86-32/iR5900Templates.cpp
x86/ix86-32/recVTLB.cpp
x86/newVif_Dynarec.cpp
x86/newVif_Unpack.cpp
x86/newVif_UnpackSSE.cpp
)
@@ -995,7 +994,6 @@ set(pcsx2x86Headers
x86/microVU_Tables.inl
x86/microVU_Upper.inl
x86/newVif.h
x86/newVif_HashBucket.h
x86/newVif_UnpackSSE.h
x86/R5900_Profiler.h
)
-1
View File
@@ -5,7 +5,6 @@
#include "GS.h"
#include "Gif_Unit.h"
#include "Vif_Dma.h"
#include "x86/iR5900.h"
// A three-way toggle used to determine if the GIF is stalling (transferring) or done (finished).
// Should be a gifstate_t rather then int, but I don't feel like possibly interfering with savestates right now.
+16
View File
@@ -118,6 +118,22 @@ struct Gif_Tag
// write out unpacked registers
_mm_storeu_si128(reinterpret_cast<__m128i*>(regs), vregs);
#elif defined(_M_ARM64)
// zero out bits for registers which shouldn't be tested
u64 REGS64;
std::memcpy(&REGS64, tag.REGS, sizeof(u64));
REGS64 &= (0xFFFFFFFFFFFFFFFFULL >> (64 - nRegs * 4));
uint8x16_t vregs = vsetq_lane_u64(REGS64, vdupq_n_u64(0), 0);
// get upper nibbles, interleave with lower nibbles, clear upper bits from low nibbles
vregs = vandq_u8(vzip1q_u8(vregs, vshrq_n_u8(vregs, 4)), vdupq_n_u8(0x0F));
// compare with GIF_REG_A_D, set hasAD if any lanes passed
const uint8x16_t comp = vceqq_u8(vregs, vdupq_n_u8(GIF_REG_A_D));
hasAD = vmaxvq_u8(comp) & 1;
// write out unpacked registers
vst1q_u8(regs, vregs);
#else
// Reference C implementation.
hasAD = false;
-1
View File
@@ -8,7 +8,6 @@
#include "R3000A.h"
#include "R5900.h"
#include "ps2/BiosTools.h"
#include "x86/iR3000A.h"
#include "VMManager.h"
#include <ctype.h>
-1
View File
@@ -11,7 +11,6 @@
#include "IopHw.h"
#include "Mdec.h"
#include "R3000A.h"
#include "x86/iR5900.h"
// NOTE: Any modifications to read/write fns should also go into their const counterparts
// found in iPsxHw.cpp.
+1 -1
View File
@@ -14,7 +14,7 @@ const uptr *psxMemRLUT = nullptr;
IopVM_MemoryAllocMess* iopMem = nullptr;
alignas(__pagesize) u8 iopHw[Ps2MemSize::IopHardware];
alignas(__pagealignsize) u8 iopHw[Ps2MemSize::IopHardware];
void iopMemAlloc()
{
+1 -1
View File
@@ -5,7 +5,7 @@
#include "Gif_Unit.h"
#include "MTVU.h"
#include "VMManager.h"
#include "x86/newVif.h"
#include "Vif_Dynarec.h"
#include <thread>
+8 -3
View File
@@ -98,7 +98,7 @@ u8* SysMemory::TryAllocateVirtualMemory(const char* name, void* file_handle, upt
if (!baseptr)
return nullptr;
if ((uptr)baseptr != base)
if (base != 0 && (uptr)baseptr != base)
{
if (file_handle)
{
@@ -122,6 +122,8 @@ u8* SysMemory::TryAllocateVirtualMemory(const char* name, void* file_handle, upt
u8* SysMemory::AllocateVirtualMemory(const char* name, void* file_handle, size_t size, size_t offset_from_base)
{
// ARM64 does not need the rec areas to be in +/- 2GB.
#ifdef _M_X86
pxAssertRel(Common::IsAlignedPow2(size, __pagesize), "Virtual memory size is page aligned");
// Everything looks nicer when the start of all the sections is a nice round looking number.
@@ -148,6 +150,9 @@ u8* SysMemory::AllocateVirtualMemory(const char* name, void* file_handle, size_t
DevCon.Warning("%s: host memory @ 0x%016" PRIXPTR " -> 0x%016" PRIXPTR " is unavailable; attempting to map elsewhere...", name,
base, base + size);
}
#else
return TryAllocateVirtualMemory(name, file_handle, 0, size);
#endif
return nullptr;
}
@@ -986,8 +991,8 @@ void memClearPageAddr(u32 vaddr)
///////////////////////////////////////////////////////////////////////////
// PS2 Memory Init / Reset / Shutdown
EEVM_MemoryAllocMess* eeMem = NULL;
alignas(__pagesize) u8 eeHw[Ps2MemSize::Hardware];
EEVM_MemoryAllocMess* eeMem = nullptr;
alignas(__pagealignsize) u8 eeHw[Ps2MemSize::Hardware];
void memBindConditionalHandlers()
+2 -2
View File
@@ -59,8 +59,8 @@ struct IopVM_MemoryAllocMess
// order to allow for simpler macros and reference handles to be defined (we can safely use
// compile-time references to registers instead of having to use instance variables).
alignas(__pagesize) extern u8 eeHw[Ps2MemSize::Hardware];
alignas(__pagesize) extern u8 iopHw[Ps2MemSize::IopHardware];
alignas(__pagealignsize) extern u8 eeHw[Ps2MemSize::Hardware];
alignas(__pagealignsize) extern u8 iopHw[Ps2MemSize::IopHardware];
extern EEVM_MemoryAllocMess* eeMem;
+1 -2
View File
@@ -34,8 +34,7 @@ using namespace R5900; // for R5900 disasm tools
s32 EEsCycle; // used to sync the IOP to the EE
u32 EEoCycle;
alignas(16) cpuRegisters cpuRegs;
alignas(16) fpuRegisters fpuRegs;
alignas(16) cpuRegistersPack _cpuRegistersPack;
alignas(16) tlbs tlb[48];
R5900cpu *Cpu = NULL;
+10 -2
View File
@@ -202,10 +202,18 @@ struct tlbs
#endif
alignas(16) extern cpuRegisters cpuRegs;
alignas(16) extern fpuRegisters fpuRegs;
struct cpuRegistersPack
{
alignas(16) cpuRegisters cpuRegs;
alignas(16) fpuRegisters fpuRegs;
};
alignas(16) extern cpuRegistersPack _cpuRegistersPack;
alignas(16) extern tlbs tlb[48];
static cpuRegisters& cpuRegs = _cpuRegistersPack.cpuRegs;
static fpuRegisters& fpuRegs = _cpuRegistersPack.fpuRegs;
extern bool eeEventTestIsActive;
void intUpdateCPUCycles();
+1 -1
View File
@@ -11,7 +11,7 @@
#include "DebugTools/Debug.h"
#include "R3000A.h"
#include "x86/iR5900.h"
#include "R5900.h"
#include "fmt/core.h"
+34 -4
View File
@@ -38,6 +38,7 @@
#include "SIO/Sio2.h"
#include "SPU2/spu2.h"
#include "USB/USB.h"
#include "Vif_Dynarec.h"
#include "VMManager.h"
#include "ps2/BiosTools.h"
#include "svnrev.h"
@@ -76,10 +77,6 @@
#include "common/Darwin/DarwinMisc.h"
#endif
#ifdef _M_X86
#include "x86/newVif.h"
#endif
namespace VMManager
{
static void SetDefaultLoggingSettings(SettingsInterface& si);
@@ -230,6 +227,14 @@ bool VMManager::PerformEarlyHardwareChecks(const char** error)
return false;
}
#endif
#elif defined(_M_ARM64)
// Check page size. If it doesn't match, it is a fatal error.
const size_t runtime_host_page_size = HostSys::GetRuntimePageSize();
if (__pagesize != runtime_host_page_size)
{
*error = "Page size mismatch. This build cannot run on your Mac.\n\n" COMMON_DOWNLOAD_MESSAGE;
return false;
}
#endif
#undef COMMON_DOWNLOAD_MESSAGE
@@ -2502,6 +2507,7 @@ void VMManager::LogCPUCapabilities()
LogUserPowerPlan();
#endif
#ifdef _M_X86
std::string features;
if (cpuinfo_has_x86_avx())
features += "AVX ";
@@ -2513,6 +2519,18 @@ void VMManager::LogCPUCapabilities()
Console.WriteLn(Color_StrongBlack, "x86 Features Detected:");
Console.WriteLnFmt(" {}", features);
Console.WriteLn();
#endif
#ifdef _M_ARM64
const size_t runtime_cache_line_size = HostSys::GetRuntimeCacheLineSize();
if (__cachelinesize != runtime_cache_line_size)
{
// Not fatal, but does have performance implications.
WARNING_LOG(
"Cache line size mismatch. This build was compiled with {} byte lines, but the system has {} byte lines.",
__cachelinesize, runtime_cache_line_size);
}
#endif
#if 0
LogGPUCapabilities();
@@ -3197,6 +3215,8 @@ void VMManager::WarnAboutUnsafeSettings()
append(ICON_FA_EXCLAMATION_CIRCLE,
TRANSLATE_SV("VMManager", "INTC Spin Detection is not enabled, this may reduce performance."));
}
if (!EmuConfig.Cpu.Recompiler.EnableFastmem)
append(ICON_FA_EXCLAMATION_CIRCLE, TRANSLATE_SV("VMManager", "Fastmem is not enabled, this will reduce performance."));
if (!EmuConfig.Speedhacks.vu1Instant)
{
append(ICON_FA_EXCLAMATION_CIRCLE,
@@ -3322,6 +3342,12 @@ static u32 GetProcessorIdForProcessor(const cpuinfo_processor* proc)
static void InitializeProcessorList()
{
if (!cpuinfo_initialize())
{
Console.Error("cpuinfo_initialize() failed");
return;
}
const u32 cluster_count = cpuinfo_get_clusters_count();
if (cluster_count == 0)
{
@@ -3448,6 +3474,10 @@ static void InitializeProcessorList()
static void SetMTVUAndAffinityControlDefault(SettingsInterface& si)
{
#ifdef __APPLE__
// Everything we support Mac-wise has enough cores for MTVU.
si.SetBoolValue("EmuCore/Speedhacks", "vuThread", true);
#endif
}
#endif
+2
View File
@@ -29,6 +29,8 @@ static __fi void vu0SetMicroFlags(u32* flags, u32 value)
{
#ifdef _M_X86
_mm_store_si128(reinterpret_cast<__m128i*>(flags), _mm_set1_epi32(value));
#elif defined(_M_ARM64)
vst1q_u32(flags, vdupq_n_u32(value));
#else
flags[0] = flags[1] = flags[2] = flags[3] = value;
#endif
+1 -1
View File
@@ -8,7 +8,7 @@
#include "MTVU.h"
#include "Vif.h"
#include "Vif_Dma.h"
#include "x86/newVif.h"
#include "Vif_Dynarec.h"
alignas(16) vifStruct vif0, vif1;
+1 -1
View File
@@ -3,8 +3,8 @@
#include "Common.h"
#include "Vif_Dma.h"
#include "Vif_Dynarec.h"
#include "VUmicro.h"
#include "x86/newVif.h"
u32 g_vif0Cycles = 0;
+1 -1
View File
@@ -7,7 +7,7 @@
#include "MTVU.h"
#include "VUmicro.h"
#include "Vif_Dma.h"
#include "x86/newVif.h"
#include "Vif_Dynarec.h"
u32 g_vif1Cycles = 0;
+1 -1
View File
@@ -7,7 +7,7 @@
#include "MTVU.h"
#include "VUmicro.h"
#include "Vif_Dma.h"
#include "x86/newVif.h"
#include "Vif_Dynarec.h"
#define vifOp(vifCodeName) _vifT int vifCodeName(int pass, const u32* data)
#define pass1 if (pass == 0)
+46
View File
@@ -0,0 +1,46 @@
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+
#pragma once
#include "Vif.h"
#include "Vif_HashBucket.h"
#include "VU.h"
typedef u32 (*nVifCall)(void*, const void*);
typedef void (*nVifrecCall)(uptr dest, uptr src);
extern void _nVifUnpack(int idx, const u8* data, uint mode, bool isFill);
extern void dVifReset(int idx);
extern void dVifRelease(int idx);
extern void VifUnpackSSE_Init();
_vifT extern void dVifUnpack(const u8* data, bool isFill);
struct nVifStruct
{
// Buffer for partial transfers (should always be first to ensure alignment)
// Maximum buffer size is 256 (vifRegs.Num max range) * 16 (quadword)
alignas(16) u8 buffer[256*16];
u32 bSize; // Size of 'buffer'
// VIF0 or VIF1 - provided for debugging helpfulness only, and is generally unused.
// (templates are used for most or all VIF indexing)
u32 idx;
u8* recWritePtr; // current write pos into the reserve
u8* recEndPtr;
HashBucket vifBlocks; // Vif Blocks
nVifStruct() = default;
};
extern void resetNewVif(int idx);
alignas(16) extern nVifStruct nVif[2];
alignas(16) extern nVifCall nVifUpk[(2 * 2 * 16) * 4]; // ([USN][Masking][Unpack Type]) [curCycle]
alignas(16) extern u32 nVifMask[3][4][4]; // [MaskNumber][CycleNumber][Vector]
static constexpr bool newVifDynaRec = 1; // Use code in newVif_Dynarec.inl

Some files were not shown because too many files have changed in this diff Show More