loader: emulate immediate SSE4a instructions on macOS (#635)

* loader: emulate immediate SSE4a instructions on macOS

* tests: simplify macOS SSE4a test integration

Keep the Darwin target, CTest registration, and aggregate dependency in
one conditional block without a separate target list. Preserve the
standalone target when BUILD_TESTING is disabled.

Lowercase the test filename and diagnostic prefix, and drop unrelated
formatting changes from the instruction emulator.

Credit Brandon Strong's related SSE4a work in
https://github.com/KytyPS5/KytyPS5/pull/467.

Co-authored-by: Brandon Strong <brandostrong@gmail.com>

---------

Co-authored-by: nmzik <Nmzik@mail.ru>
Co-authored-by: Brandon Strong <brandostrong@gmail.com>
This commit is contained in:
Jean-Philippe
2026-09-17 09:23:50 +02:00
committed by GitHub
parent f30afc184e
commit 4e6f4f99d3
3 changed files with 283 additions and 6 deletions
+49 -6
View File
@@ -12,7 +12,9 @@
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
#include <windows.h> // IWYU pragma: keep
#elif !defined(__APPLE__)
#elif defined(__APPLE__)
#include <sys/ucontext.h>
#else
#include <sched.h>
#include <ucontext.h>
#endif
@@ -406,8 +408,6 @@ static bool ExecuteShaNiInsn(const ShaNiInsn& insn, const XmmWords& src2, const
}
}
#if !defined(__APPLE__)
// Keep instruction semantics shared; only access to the saved host context differs.
struct Context {
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
@@ -439,6 +439,38 @@ struct Context {
ymm[index] = {};
}
}
#elif defined(__APPLE__)
ucontext_t* native;
[[nodiscard]] uint64_t Rip() const {
return static_cast<uint64_t>(native->uc_mcontext->__ss.__rip);
}
void Advance(size_t length) {
native->uc_mcontext->__ss.__rip += static_cast<uint64_t>(length);
}
// Darwin names the XMM file __fpu_xmm0..__fpu_xmm15 instead of exposing an array.
[[nodiscard]] void* Xmm(uint8_t index) const {
auto* fs = &native->uc_mcontext->__fs;
switch (index) {
case 0: return &fs->__fpu_xmm0;
case 1: return &fs->__fpu_xmm1;
case 2: return &fs->__fpu_xmm2;
case 3: return &fs->__fpu_xmm3;
case 4: return &fs->__fpu_xmm4;
case 5: return &fs->__fpu_xmm5;
case 6: return &fs->__fpu_xmm6;
case 7: return &fs->__fpu_xmm7;
case 8: return &fs->__fpu_xmm8;
case 9: return &fs->__fpu_xmm9;
case 10: return &fs->__fpu_xmm10;
case 11: return &fs->__fpu_xmm11;
case 12: return &fs->__fpu_xmm12;
case 13: return &fs->__fpu_xmm13;
case 14: return &fs->__fpu_xmm14;
case 15: return &fs->__fpu_xmm15;
default: return nullptr;
}
}
#else
ucontext_t* native;
@@ -487,6 +519,8 @@ struct Context {
#endif
};
#if !defined(__APPLE__)
static bool TryEmulateShaNi(Context& context) {
const auto* rip = reinterpret_cast<const uint8_t*>(context.Rip());
ShaNiInsn insn {};
@@ -534,6 +568,8 @@ static bool TryEmulateShaNi(Context& context) {
return true;
}
#endif
static bool TryEmulateSse4a(Context& context) {
const auto* rip = reinterpret_cast<const uint8_t*>(context.Rip());
const uint8_t prefix = rip[0];
@@ -598,6 +634,8 @@ static bool TryEmulateSse4a(Context& context) {
return true;
}
#if !defined(__APPLE__)
static bool TryEmulateMonitorxMwaitx(Context& context) {
const auto* rip = reinterpret_cast<const uint8_t*>(context.Rip());
if (rip[0] != 0x0f || rip[1] != 0x01 || (rip[2] != 0xfa && rip[2] != 0xfb)) {
@@ -726,23 +764,28 @@ uint64_t PatchReciprocalSquareRoots(uint64_t address, uint64_t size) {
}
bool TryEmulate(void* native_context) {
#if !defined(__APPLE__)
if (native_context == nullptr) {
return false;
}
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
Context context {static_cast<PCONTEXT>(native_context)};
#elif defined(__APPLE__)
auto* saved_context = static_cast<ucontext_t*>(native_context);
if (saved_context->uc_mcontext == nullptr) {
return false;
}
Context context {saved_context};
#else
Context context {static_cast<ucontext_t*>(native_context)};
#endif
#if !defined(__APPLE__)
if (TryEmulateReciprocalSquareRoot(context)) {
return true;
}
return TryEmulateMonitorxMwaitx(context) || TryEmulateSse4a(context) ||
TryEmulateShaNi(context);
#else
(void)native_context;
return false;
return TryEmulateSse4a(context);
#endif
}