block_of_code: Fix running under Rosetta

Rosetta doesn't have accurate emulation of the sahf instruction
This commit is contained in:
Merry 2022-08-05 23:43:01 +01:00
parent a38966a874
commit c60fd3f0ac

View file

@ -12,6 +12,12 @@
# include <sys/mman.h> # include <sys/mman.h>
#endif #endif
#ifdef __APPLE__
# include <errno.h>
# include <fmt/format.h>
# include <sys/sysctl.h>
#endif
#include <array> #include <array>
#include <cstring> #include <cstring>
@ -183,6 +189,19 @@ HostFeature GetHostFeatures() {
return features; return features;
} }
#ifdef __APPLE__
bool IsUnderRosetta() {
int result = 0;
size_t result_size = sizeof(result);
if (sysctlbyname("sysctl.proc_translated", &result, &result_size, nullptr, 0) == -1) {
if (errno != ENOENT)
fmt::print("IsUnderRosetta: Failed to detect Rosetta state, assuming not under Rosetta");
return false;
}
return result != 0;
}
#endif
} // anonymous namespace } // anonymous namespace
BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, size_t total_code_size, std::function<void(BlockOfCode&)> rcp) BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, size_t total_code_size, std::function<void(BlockOfCode&)> rcp)
@ -394,6 +413,10 @@ void BlockOfCode::LookupBlock() {
} }
void BlockOfCode::LoadRequiredFlagsForCondFromRax(IR::Cond cond) { void BlockOfCode::LoadRequiredFlagsForCondFromRax(IR::Cond cond) {
#ifdef __APPLE__
static const bool is_rosetta = IsUnderRosetta();
#endif
// sahf restores SF, ZF, CF // sahf restores SF, ZF, CF
// add al, 0x7F restores OF // add al, 0x7F restores OF
@ -419,6 +442,15 @@ void BlockOfCode::LoadRequiredFlagsForCondFromRax(IR::Cond cond) {
case IR::Cond::LT: // n != v case IR::Cond::LT: // n != v
case IR::Cond::GT: // !z & (n == v) case IR::Cond::GT: // !z & (n == v)
case IR::Cond::LE: // z | (n != v) case IR::Cond::LE: // z | (n != v)
#ifdef __APPLE__
if (is_rosetta) {
shl(al, 3);
xchg(al, ah);
push(rax);
popf();
break;
}
#endif
cmp(al, 0x81); cmp(al, 0x81);
sahf(); sahf();
break; break;