Merge remote-tracking branch 'armsx2/master' into ios/pr-ready

This commit is contained in:
Jeen
2026-07-13 00:41:14 +02:00
12 changed files with 110 additions and 4 deletions
+2
View File
@@ -11,6 +11,8 @@ function(detect_operating_system)
if(WIN32)
message(STATUS "Building for Windows.")
elseif(APPLE AND IOS)
message(STATUS "Building for iOS.")
elseif(APPLE AND NOT IOS)
message(STATUS "Building for MacOS.")
elseif(APPLE AND IOS)
+10
View File
@@ -113,14 +113,24 @@ struct FPControlRegister
__fi static FPControlRegister GetCurrent()
{
u64 value;
#if defined(_MSC_VER) && !defined(__clang__)
// MSVC's arm64 compiler doesn't accept GCC inline asm; read FPCR via the
// system-register intrinsic (ARM64_FPCR / _ReadStatusReg from <intrin.h>).
value = static_cast<u64>(_ReadStatusReg(ARM64_FPCR));
#else
asm volatile("\tmrs %0, FPCR\n"
: "=r"(value));
#endif
return FPControlRegister{value};
}
__fi static void SetCurrent(FPControlRegister value)
{
#if defined(_MSC_VER) && !defined(__clang__)
_WriteStatusReg(ARM64_FPCR, static_cast<__int64>(value.bitmask));
#else
asm volatile("\tmsr FPCR, %0\n" ::"r"(value.bitmask));
#endif
}
__fi static constexpr FPControlRegister GetDefault()
+78
View File
@@ -5,6 +5,84 @@
#include "common/Assertions.h"
// ---- MSVC arm64 shim: __builtin_shufflevector ------------------------------
// clang/clang-cl provide __builtin_shufflevector (a constant-index vector
// shuffle); MSVC's arm64 cl.exe does not. Where it's unavailable, route the
// existing call sites (this file + GSVector4_arm64.h, same TU via GSVector.h)
// through a NEON lane-by-lane shuffle built from the SAME compile-time indices
// -- correctness-exact. clang keeps its single-instruction lowering (this whole
// block is #if'd out there). Mirrors the __has_builtin(__builtin_nontemporal_*)
// idiom already used below.
// TODO: lower hot shuffles to dedicated NEON ops instead of lane-by-lane.
#if !defined(__has_builtin) || !__has_builtin(__builtin_shufflevector)
template <int I>
static __forceinline int32_t gsneon_pick(int32x4_t a, int32x4_t b)
{
if constexpr (I < 4)
return vgetq_lane_s32(a, I);
else
return vgetq_lane_s32(b, I - 4);
}
template <int I>
static __forceinline float32_t gsneon_pickf(float32x4_t a, float32x4_t b)
{
if constexpr (I < 4)
return vgetq_lane_f32(a, I);
else
return vgetq_lane_f32(b, I - 4);
}
template <int I>
static __forceinline int16_t gsneon_pick16(int16x8_t a, int16x8_t b)
{
if constexpr (I < 8)
return vgetq_lane_s16(a, I);
else
return vgetq_lane_s16(b, I - 8);
}
template <int I0, int I1, int I2, int I3>
static __forceinline int32x4_t gsneon_shuffle(int32x4_t a, int32x4_t b)
{
int32x4_t r = vdupq_n_s32(0);
r = vsetq_lane_s32(gsneon_pick<I0>(a, b), r, 0);
r = vsetq_lane_s32(gsneon_pick<I1>(a, b), r, 1);
r = vsetq_lane_s32(gsneon_pick<I2>(a, b), r, 2);
r = vsetq_lane_s32(gsneon_pick<I3>(a, b), r, 3);
return r;
}
template <int I0, int I1, int I2, int I3>
static __forceinline float32x4_t gsneon_shuffle(float32x4_t a, float32x4_t b)
{
float32x4_t r = vdupq_n_f32(0.0f);
r = vsetq_lane_f32(gsneon_pickf<I0>(a, b), r, 0);
r = vsetq_lane_f32(gsneon_pickf<I1>(a, b), r, 1);
r = vsetq_lane_f32(gsneon_pickf<I2>(a, b), r, 2);
r = vsetq_lane_f32(gsneon_pickf<I3>(a, b), r, 3);
return r;
}
template <int I0, int I1, int I2, int I3, int I4, int I5, int I6, int I7>
static __forceinline int16x8_t gsneon_shuffle(int16x8_t a, int16x8_t b)
{
int16x8_t r = vdupq_n_s16(0);
r = vsetq_lane_s16(gsneon_pick16<I0>(a, b), r, 0);
r = vsetq_lane_s16(gsneon_pick16<I1>(a, b), r, 1);
r = vsetq_lane_s16(gsneon_pick16<I2>(a, b), r, 2);
r = vsetq_lane_s16(gsneon_pick16<I3>(a, b), r, 3);
r = vsetq_lane_s16(gsneon_pick16<I4>(a, b), r, 4);
r = vsetq_lane_s16(gsneon_pick16<I5>(a, b), r, 5);
r = vsetq_lane_s16(gsneon_pick16<I6>(a, b), r, 6);
r = vsetq_lane_s16(gsneon_pick16<I7>(a, b), r, 7);
return r;
}
// cl.exe: __builtin_shufflevector isn't a keyword, so a guarded macro cleanly
// reroutes the call sites. Overload resolution picks the int32/float32/int16
// variant by the vector arg types; the index pack forwards as template args.
#define __builtin_shufflevector(a, b, ...) gsneon_shuffle<__VA_ARGS__>((a), (b))
#endif
class alignas(16) GSVector4i
{
static const GSVector4i m_xff[17];
+7 -4
View File
@@ -142,10 +142,13 @@ android {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
// NATIVE BUILD DISABLED for the recovered tree: the prebuilt native .so files
// (extracted from vc1063 into src/main/jniLibs/arm64-v8a) are packaged directly,
// so UI/Kotlin iteration doesn't require recompiling the C++ core. Re-enable this
// block (and the per-buildType cmake blocks above) to rebuild native from source.
// Native core (emucore_4k), its from-source deps (shaderc, SPIRV-Tools, ...) and
// the adrenotools runtime hooks (hook_impl/main_hook/file_redirect_hook/
// gsl_alloc_hook, built by 3rdparty/adrenotools) are all compiled here from
// src/main/cpp. src/main/jniLibs/arm64-v8a therefore holds ONLY genuine external
// prebuilts that are NOT built from source (currently just libandroidx.graphics.path.so).
// Anything the CMake build emits must NOT be duplicated there or AGP's
// mergeNativeLibs fails with DuplicateRelativeFileException.
externalNativeBuild {
cmake {
path = file("src/main/cpp/CMakeLists.txt")
Executable
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
RETRIES=10
for i in $(seq 1 "$RETRIES"); do
"$@" && break
if [ "$i" == "$RETRIES" ]; then
echo "Command \"$@\" failed after ${RETRIES} retries."
exit 1
fi
done
exit 0