Compare commits

...
13 Commits
Author SHA1 Message Date
LC ae495b971b Merge pull request #6106 from Sonicadvance1/310
Minor fixes
2026-11-06 09:52:49 -05:00
Ryan Houdek feee41a768 ImageTracker: Actually wire up config option for Volatile Metadata
I forgot to wire this up, so you couldn't turn off an application's
volatile metadata for testing.
2026-11-06 00:12:26 -08:00
Ryan Houdek cf2f831ad9 Windows: Fixes forced assert
This wasn't ever wired up for Windows.
2026-11-05 20:26:44 -08:00
Ryan Houdek b9fc587ac8 CPUID: Fixes crash in CPUID
When affinity changes are in play this can cause a crash because core
index is larger than the number of cores known about.

Happens on Frame.
2026-11-05 20:25:03 -08:00
LC c985199ed5 Merge pull request #6104 from Sonicadvance1/308
FEX: Implement support for CPUID faulting
2026-11-05 19:49:40 -05:00
LC e67bbd3ecf Merge pull request #6105 from Sonicadvance1/309
DiskCache: Moves SVE/AVX from HostFeatureHash to ProcessHash
2026-11-05 18:55:39 -05:00
Ryan Houdek 02e932d9f4 InstcountCI: Remove CPUID with constant. This no longer optimizes 2026-11-05 15:04:25 -08:00
Ryan Houdek a3f5700c33 InstcountCI: Update 2026-11-05 14:48:10 -08:00
Ryan Houdek a2b15c8e0f FEXLinuxTests: Adds a unittest for CPUID fault testing
Tests various instruction lengths to ensure it works robustly.
2026-11-05 14:48:08 -08:00
Ryan Houdek 05293166ce FEX: Implement support for CPUID faulting 2026-11-05 14:31:03 -08:00
Ryan Houdek ef586f03a8 Arm64Emitter: Add a way to query SRA x86 registers to their arm64 mapping 2026-11-05 14:31:03 -08:00
Ryan Houdek 6a3d85a26f InstcountCI: Update 2026-11-05 13:45:15 -08:00
Ryan Houdek 36aec0d54d DiskCache: Moves SVE/AVX from HostFeatureHash to ProcessHash
Annoyingly these are technically host features but they end up being
process feature hash bits because they change between Linux, wow64, and
arm64ec.

This now makes the HostFeaturesHash match between the three which is
what we want. While the process feature bits change between them.

Adds an info log to the DiskCache startup for confirmation.
2026-11-05 13:45:13 -08:00
139 changed files with 814 additions and 432 deletions

No files matched your search

@@ -665,11 +665,11 @@ void Arm64Emitter::FillSpecialRegs(ARMEmitter::Register TmpReg, ARMEmitter::Regi
// We don't bother spilling these in SpillStaticRegs,
// since all that matters is we restore them on a fill.
// It's not a concern if they get trounced by something else.
if (EmitterCTX->HostFeatures.SupportsSVE256) {
if (EmitterCTX->HostFeatures.SupportsSVE256()) {
ptrue(ARMEmitter::SubRegSize::i8Bit, PRED_TMP_32B, ARMEmitter::PredicatePattern::SVE_VL32);
}
if (EmitterCTX->HostFeatures.SupportsSVE128) {
if (EmitterCTX->HostFeatures.SupportsSVE128()) {
ptrue(ARMEmitter::SubRegSize::i8Bit, PRED_TMP_16B, ARMEmitter::PredicatePattern::SVE_VL16);
}
@@ -739,7 +739,7 @@ void Arm64Emitter::SpillStaticRegs(ARMEmitter::Register TmpReg, SpillStaticRegOp
}
if (Options.FPRs) {
if (EmitterCTX->HostFeatures.SupportsAVX && EmitterCTX->HostFeatures.SupportsSVE256) {
if (EmitterCTX->HostFeatures.SupportsAVX() && EmitterCTX->HostFeatures.SupportsSVE256()) {
for (size_t i = 0; i < StaticFPRegisters.size(); i++) {
const auto Reg = StaticFPRegisters[i];
@@ -826,7 +826,7 @@ void Arm64Emitter::FillStaticRegs(FillStaticRegOptions Options) {
FillSpecialRegs(TmpReg, TmpReg2, {.SetFIZ = true, .SetPredRegs = Options.FPRs});
if (Options.FPRs) {
if (EmitterCTX->HostFeatures.SupportsAVX && EmitterCTX->HostFeatures.SupportsSVE256) {
if (EmitterCTX->HostFeatures.SupportsAVX() && EmitterCTX->HostFeatures.SupportsSVE256()) {
for (size_t i = 0; i < StaticFPRegisters.size(); i++) {
const auto Reg = StaticFPRegisters[i];
if (((1U << Reg.Idx()) & Options.FPRFillMask) != 0) {
@@ -990,7 +990,7 @@ void Arm64Emitter::PopGeneralRegisters(std::span<const ARMEmitter::Register> Reg
}
size_t Arm64Emitter::PushDynamicRegs(ARMEmitter::Register TmpReg) {
const auto CanUseSVE256 = EmitterCTX->HostFeatures.SupportsSVE256;
const auto CanUseSVE256 = EmitterCTX->HostFeatures.SupportsSVE256();
const auto GPRSize = GeneralRegistersNotPreserved.size() * Core::CPUState::GPR_REG_SIZE;
const auto FPRRegSize = CanUseSVE256 ? 32 : 16;
const auto FPRSize = GeneralFPRegisters.size() * FPRRegSize;
@@ -1013,7 +1013,7 @@ size_t Arm64Emitter::PushDynamicRegs(ARMEmitter::Register TmpReg) {
}
void Arm64Emitter::PopDynamicRegs() {
const auto CanUseSVE256 = EmitterCTX->HostFeatures.SupportsSVE256;
const auto CanUseSVE256 = EmitterCTX->HostFeatures.SupportsSVE256();
// Pop vectors first
PopVectorRegisters(CanUseSVE256, GeneralFPRegisters);
@@ -1023,7 +1023,7 @@ void Arm64Emitter::PopDynamicRegs() {
}
size_t Arm64Emitter::SpillForPreserveAllABICall(ARMEmitter::Register TmpReg, bool FPRs) {
const auto CanUseSVE256 = EmitterCTX->HostFeatures.SupportsSVE256;
const auto CanUseSVE256 = EmitterCTX->HostFeatures.SupportsSVE256();
const auto FPRRegSize = CanUseSVE256 ? 32 : 16;
std::span<const ARMEmitter::Register> DynamicGPRs {};
@@ -1078,7 +1078,7 @@ size_t Arm64Emitter::SpillForPreserveAllABICall(ARMEmitter::Register TmpReg, boo
}
void Arm64Emitter::FillForPreserveAllABICall(bool FPRs) {
const auto CanUseSVE256 = EmitterCTX->HostFeatures.SupportsSVE256;
const auto CanUseSVE256 = EmitterCTX->HostFeatures.SupportsSVE256();
std::span<const ARMEmitter::Register> DynamicGPRs {};
std::span<const ARMEmitter::VRegister> DynamicFPRs {};
@@ -1129,4 +1129,9 @@ void Arm64Emitter::Align16B() {
}
}
ARMEmitter::Register Arm64Emitter::GetX86GPRMapping(FEXCore::X86State::X86Reg Reg) {
LOGMAN_THROW_A_FMT(Reg <= FEXCore::X86State::X86Reg::REG_R15, "Incorrect register");
return StaticRegisters[Reg];
}
} // namespace FEXCore::CPU
@@ -235,6 +235,8 @@ protected:
void Align16B();
ARMEmitter::Register GetX86GPRMapping(FEXCore::X86State::X86Reg Reg);
#ifdef VIXL_SIMULATOR
// Generates a vixl simulator runtime call.
//
+4 -4
View File
@@ -443,7 +443,7 @@ void CPUIDEmu::SetupHostHybridFlag() {}
void CPUIDEmu::SetupFeatures() {
if (CTX->HostFeatures.SupportsAVX) {
if (CTX->HostFeatures.SupportsAVX()) {
XCR0 |= XCR0_AVX;
}
@@ -1162,14 +1162,14 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0004h(uint32_t Leaf) con
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0002h(uint32_t Leaf, uint32_t CPU) const {
FEXCore::CPUID::FunctionResults Res {};
auto& Data = PerCPUData[CPU];
auto& Data = PerCPUData[std::min<uint32_t>(CPU, PerCPUData.size() - 1)];
memcpy(&Res, Data.ProductName, std::min(strlen(Data.ProductName), sizeof(FEXCore::CPUID::FunctionResults)));
return Res;
}
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0003h(uint32_t Leaf, uint32_t CPU) const {
FEXCore::CPUID::FunctionResults Res {};
auto& Data = PerCPUData[CPU];
auto& Data = PerCPUData[std::min<uint32_t>(CPU, PerCPUData.size() - 1)];
const auto RemainingStringSize = std::max<ssize_t>(0, strlen(Data.ProductName) - 16);
memcpy(&Res, Data.ProductName + 16, std::min<size_t>(RemainingStringSize, sizeof(FEXCore::CPUID::FunctionResults)));
return Res;
@@ -1177,7 +1177,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0003h(uint32_t Leaf, uin
FEXCore::CPUID::FunctionResults CPUIDEmu::Function_8000_0004h(uint32_t Leaf, uint32_t CPU) const {
FEXCore::CPUID::FunctionResults Res {};
auto& Data = PerCPUData[CPU];
auto& Data = PerCPUData[std::min<uint32_t>(CPU, PerCPUData.size() - 1)];
const auto RemainingStringSize = std::max<ssize_t>(0, strlen(Data.ProductName) - 32);
memcpy(&Res, Data.ProductName + 32, std::min<size_t>(RemainingStringSize, sizeof(FEXCore::CPUID::FunctionResults)));
return Res;
+4 -4
View File
@@ -264,8 +264,8 @@ uint32_t ContextImpl::ReconstructCompactedEFLAGS(FEXCore::Core::InternalThreadSt
void ContextImpl::ReconstructXMMRegisters(const FEXCore::Core::InternalThreadState* Thread, __uint128_t* XMM_Low, __uint128_t* YMM_High) {
const size_t MaximumRegisters = Config.Is64BitMode ? FEXCore::Core::CPUState::NUM_XMMS : 8;
if (YMM_High != nullptr && HostFeatures.SupportsAVX) {
const bool SupportsConvergedRegisters = HostFeatures.SupportsSVE256;
if (YMM_High != nullptr && HostFeatures.SupportsAVX()) {
const bool SupportsConvergedRegisters = HostFeatures.SupportsSVE256();
if (SupportsConvergedRegisters) {
///< Output wants to de-interleave
@@ -288,8 +288,8 @@ void ContextImpl::ReconstructXMMRegisters(const FEXCore::Core::InternalThreadSta
void ContextImpl::SetXMMRegistersFromState(FEXCore::Core::InternalThreadState* Thread, const __uint128_t* XMM_Low, const __uint128_t* YMM_High) {
const size_t MaximumRegisters = Config.Is64BitMode ? FEXCore::Core::CPUState::NUM_XMMS : 8;
if (YMM_High != nullptr && HostFeatures.SupportsAVX) {
const bool SupportsConvergedRegisters = HostFeatures.SupportsSVE256;
if (YMM_High != nullptr && HostFeatures.SupportsAVX()) {
const bool SupportsConvergedRegisters = HostFeatures.SupportsSVE256();
if (SupportsConvergedRegisters) {
///< Output wants to de-interleave
@@ -409,6 +409,12 @@ namespace DiskCache {
uint64_t HostFeaturesHash;
} MachineBucketData = {FormatVersion, HostFeatureHash.HostFeaturesHash};
uint8_t ProcessFeaturesHash {};
memcpy(&ProcessFeaturesHash, &HostFeatureHash.ProcessFeaturesHash, sizeof(ProcessFeaturesHash));
LogMan::Msg::IFmt("Disk Cache features:");
LogMan::Msg::IFmt("HostFeatures Hash: 0x{:016x}", HostFeatureHash.HostFeaturesHash);
LogMan::Msg::IFmt("ProcessFeaturesHash: 0x{:02x}", ProcessFeaturesHash);
fextl::vector<uint8_t> BucketBytes(sizeof(MachineBucketData) + sizeof(HostFeatureHash.ProcessFeaturesHash) + SerializedConfig.size());
memcpy(BucketBytes.data(), &MachineBucketData, sizeof(MachineBucketData));
+1 -1
View File
@@ -249,7 +249,7 @@ namespace DiskCache {
// The current version of the diskcache.
// This must be changed any time codegen changes occur!
// Be aware of the impact of changing this frequently!
static constexpr uint16_t FormatVersion = 42;
static constexpr uint16_t FormatVersion = 43;
static constexpr uint32_t LOOKUP_KEY_MAX_BUCKET_DEPTH = 500;
@@ -417,6 +417,7 @@ void Dispatcher::EmitDispatcher() {
brk(0);
}
ARMEmitter::BackwardLabel GuestSIGSEGVLabelPostSpill;
{
// Guest Overflow handler
// Needs to be distinct from the SignalHandlerReturnAddress
@@ -424,6 +425,8 @@ void Dispatcher::EmitDispatcher() {
SpillStaticRegs(TMP1);
(void)Bind(&GuestSIGSEGVLabelPostSpill);
// hlt/udf = SIGILL
// brk = SIGTRAP
// ??? = SIGSEGV
@@ -534,6 +537,28 @@ void Dispatcher::EmitDispatcher() {
(void)b(&LoopTop);
}
auto EmitL1Lookup = [&](int rip_offset = 0) {
// L1 lookup after syscall. Mirrors the implementation in `ExitFunction`.
// Most syscall instructions just return to the following RIP, so it is highly likely to be in the L1 in tight loops.
ldr(TMP3, STATE_PTR(CpuStateFrame, State.rip));
ldp<ARMEmitter::IndexType::OFFSET>(TMP1, TMP2, STATE, offsetof(FEXCore::Core::CpuStateFrame, State.L1Pointer));
if (rip_offset) {
add(ARMEmitter::Size::i64Bit, TMP3, TMP3, rip_offset);
}
// Calculate (tmp1 + ((ripreg & L1_ENTRIES_MASK) << 4)) for the address
// L1Mask is pre-shifted.
and_(ARMEmitter::Size::i64Bit, TMP2, TMP2, TMP3, ARMEmitter::ShiftType::LSL, FEXCore::ilog2(sizeof(LookupCache::LookupCacheEntry)));
add(TMP1, TMP1, TMP2);
ldp<ARMEmitter::IndexType::OFFSET>(TMP2, TMP1, TMP1, 0);
sub(TMP1, TMP1, TMP3);
(void)cbnz(ARMEmitter::Size::i64Bit, TMP1, &LoopTop);
br(TMP2);
};
{
// All dynamic and static registers are spilled coming in to this handler.
// It's also the end of block and RIP might have changed, so we jump directly to the top of the loop.
@@ -566,23 +591,90 @@ void Dispatcher::EmitDispatcher() {
// We can safely claim we are no longer in a syscall
str(ARMEmitter::XReg::zr, STATE, offsetof(FEXCore::Core::CpuStateFrame, InSyscallInfo));
{
// L1 lookup after syscall. Mirrors the implementation in `ExitFunction`.
// Most syscall instructions just return to the following RIP, so it is highly likely to be in the L1 in tight loops.
ldr(TMP3, STATE_PTR(CpuStateFrame, State.rip));
ldp<ARMEmitter::IndexType::OFFSET>(TMP1, TMP2, STATE, offsetof(FEXCore::Core::CpuStateFrame, State.L1Pointer));
EmitL1Lookup();
}
// Calculate (tmp1 + ((ripreg & L1_ENTRIES_MASK) << 4)) for the address
// L1Mask is pre-shifted.
and_(ARMEmitter::Size::i64Bit, TMP2, TMP2, TMP3, ARMEmitter::ShiftType::LSL, FEXCore::ilog2(sizeof(LookupCache::LookupCacheEntry)));
add(TMP1, TMP1, TMP2);
{
// All dynamic and static registers are spilled coming in to this handler.
// It's also the end of block and RIP might have changed, so we jump directly to the top of the loop.
ThreadDispatchCPUIDHandler = GetCursorAddress<uint64_t>();
ldp<ARMEmitter::IndexType::OFFSET>(TMP2, TMP1, TMP1, 0);
// CPUID behaves like an ISB.
isb();
sub(TMP1, TMP1, TMP3);
(void)cbnz(ARMEmitter::Size::i64Bit, TMP1, &LoopTop);
br(TMP2);
auto RAXReg = GetX86GPRMapping(FEXCore::X86State::REG_RAX);
auto RBXReg = GetX86GPRMapping(FEXCore::X86State::REG_RBX);
auto RCXReg = GetX86GPRMapping(FEXCore::X86State::REG_RCX);
auto RDXReg = GetX86GPRMapping(FEXCore::X86State::REG_RDX);
ARMEmitter::ForwardLabel SetupCPUIDFault {};
ldr(TMP2, STATE, offsetof(FEXCore::Core::CPUState, CoreFlags));
(void)tbz(TMP2, FEXCore::ilog2(FEXCore::ToUnderlying(FEXCore::Core::CoreFlagsEnum::CPUID_ENABLED)), &SetupCPUIDFault);
// TMP1 passes the instruction size. Usually only 2-bytes but prefixes can make it 15.
ldr(TMP2, STATE_PTR(CpuStateFrame, State.rip));
add(TMP2, TMP2, TMP1);
str(TMP2, STATE_PTR(CpuStateFrame, State.rip));
mov(ARMEmitter::XReg::x1, RAXReg.X());
mov(ARMEmitter::XReg::x2, RCXReg.X());
// x0 = CPUID Handler
// x1 = CPUID Function (RAX)
// x2 = CPUID Leaf (RCX)
ldr(ARMEmitter::XReg::x0, STATE, offsetof(FEXCore::Core::CpuStateFrame, Pointers.CPUIDObj));
ldr(ARMEmitter::XReg::x3, STATE, offsetof(FEXCore::Core::CpuStateFrame, Pointers.CPUIDFunction));
if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] {
GenerateIndirectRuntimeCall<__uint128_t, void*, uint64_t, uint64_t>(ARMEmitter::Reg::r3);
} else {
blr(ARMEmitter::Reg::r3);
}
// Results are in x0, x1
auto Res0 = ARMEmitter::Reg::r0;
auto Res1 = ARMEmitter::Reg::r1;
if (!TMP_ABIARGS) {
// SRA Overlaps, need to move.
mov(ARMEmitter::Size::i64Bit, TMP1, Res0);
mov(ARMEmitter::Size::i64Bit, TMP2, Res1);
Res0 = TMP1;
Res1 = TMP2;
}
FillStaticRegs();
// Results need to be moved to 32-bit EAX, ECX, EBX, EDX.
mov(ARMEmitter::Size::i32Bit, RAXReg, Res0);
mov(ARMEmitter::Size::i32Bit, RCXReg, Res1);
ubfx(ARMEmitter::Size::i64Bit, RBXReg, Res0, 32, 32);
ubfx(ARMEmitter::Size::i64Bit, RDXReg, Res1, 32, 32);
EmitL1Lookup();
// CPUID fault handling
(void)Bind(&SetupCPUIDFault);
constexpr Core::CpuStateFrame::SynchronousFaultDataStruct State = {
.FaultToTopAndGeneratedException = 1,
.Signal = Core::FAULT_SIGSEGV,
.TrapNo = X86State::X86_TRAPNO_GP,
.si_code = 0x80,
.err_code = 0,
.FaultAddress = 0, // Comes from register.
};
uint64_t Constant {};
memcpy(&Constant, &State, sizeof(uint64_t));
LoadConstant(ARMEmitter::Size::i64Bit, TMP1, static_cast<uint64_t>(Constant));
str(TMP1, STATE, offsetof(FEXCore::Core::CpuStateFrame, SynchronousFaultData));
ldr(TMP2, STATE_PTR(CpuStateFrame, State.rip));
str(TMP2, STATE, offsetof(FEXCore::Core::CpuStateFrame, SynchronousFaultData) + 8);
(void)b(&GuestSIGSEGVLabelPostSpill);
}
{
@@ -2683,6 +2775,7 @@ void Dispatcher::InitThreadPointers(FEXCore::Core::InternalThreadState* Thread)
Ptrs.ThreadStopHandlerSpillSRA = ThreadStopHandlerAddressSpillSRA;
Ptrs.ThreadPauseHandlerSpillSRA = ThreadPauseHandlerAddressSpillSRA;
Ptrs.ThreadDispatchSyscallHandler = ThreadDispatchSyscallHandler;
Ptrs.ThreadDispatchCPUIDHandler = ThreadDispatchCPUIDHandler;
Ptrs.ThreadDispatchRemoveCodeEntry = ThreadDispatchRemoveCodeEntry;
Ptrs.GuestSignal_SIGILL = GuestSignal_SIGILL;
Ptrs.GuestSignal_SIGTRAP = GuestSignal_SIGTRAP;
@@ -82,6 +82,7 @@ private:
uint64_t ThreadPauseHandlerAddress {};
uint64_t ThreadPauseHandlerAddressSpillSRA {};
uint64_t ThreadDispatchSyscallHandler {};
uint64_t ThreadDispatchCPUIDHandler {};
uint64_t ThreadDispatchRemoveCodeEntry {};
uint64_t ExitFunctionLinkerAddress {};
uint64_t SignalHandlerReturnAddress {};
+2 -2
View File
@@ -79,10 +79,10 @@ Decoder::Decoder(FEXCore::Core::InternalThreadState* Thread)
X87Table = &FEXCore::X86Tables::X87F80Ops;
}
if (CTX->HostFeatures.SupportsAVX && CTX->HostFeatures.SupportsSVE256) {
if (CTX->HostFeatures.SupportsAVX() && CTX->HostFeatures.SupportsSVE256()) {
VEXTable = &FEXCore::X86Tables::VEXTableOps;
VEXTableGroup = &FEXCore::X86Tables::VEXTableGroupOps;
} else if (CTX->HostFeatures.SupportsAVX) {
} else if (CTX->HostFeatures.SupportsAVX()) {
VEXTable = &FEXCore::X86Tables::VEXTableOps_AVX128;
VEXTableGroup = &FEXCore::X86Tables::VEXTableGroupOps_AVX128;
}
@@ -395,45 +395,12 @@ DEF_OP(ThreadRemoveCodeEntry) {
DEF_OP(CPUID) {
auto Op = IROp->C<IR::IROp_CPUID>();
isb();
mov(ARMEmitter::Size::i64Bit, TMP2, GetReg(Op->Function));
mov(ARMEmitter::Size::i64Bit, TMP3, GetReg(Op->Leaf));
SpillStaticRegs(TMP1);
PushDynamicRegs(TMP4);
SpillStaticRegs(TMP4);
// x0 = CPUID Handler
// x1 = CPUID Function
// x2 = CPUID Leaf
ldr(ARMEmitter::XReg::x0, STATE, offsetof(FEXCore::Core::CpuStateFrame, Pointers.CPUIDObj));
ldr(ARMEmitter::XReg::x3, STATE, offsetof(FEXCore::Core::CpuStateFrame, Pointers.CPUIDFunction));
if (!TMP_ABIARGS) {
mov(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::r1, TMP2);
mov(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::r2, TMP3);
}
if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] {
GenerateIndirectRuntimeCall<__uint128_t, void*, uint64_t, uint64_t>(ARMEmitter::Reg::r3);
} else {
blr(ARMEmitter::Reg::r3);
}
if (!TMP_ABIARGS) {
mov(ARMEmitter::Size::i64Bit, TMP1, ARMEmitter::Reg::r0);
mov(ARMEmitter::Size::i64Bit, TMP2, ARMEmitter::Reg::r1);
}
FillStaticRegs();
PopDynamicRegs();
// Results are in x0, x1
// Results want to be 4xi32 scalars
mov(ARMEmitter::Size::i32Bit, GetReg(Op->OutEAX), TMP1);
mov(ARMEmitter::Size::i32Bit, GetReg(Op->OutECX), TMP2);
ubfx(ARMEmitter::Size::i64Bit, GetReg(Op->OutEBX), TMP1, 32, 32);
ubfx(ARMEmitter::Size::i64Bit, GetReg(Op->OutEDX), TMP2, 32, 32);
LoadConstant(ARMEmitter::Size::i32Bit, TMP1, Op->InstSize);
// Jump to the syscall dispatch handler. We won't return after this.
ldr(TMP2, STATE, offsetof(FEXCore::Core::CpuStateFrame, Pointers.ThreadDispatchCPUIDHandler));
br(TMP2);
}
DEF_OP(XGetBV) {
+3 -3
View File
@@ -625,9 +625,9 @@ void Arm64JITCore::Op_NoOp(const IR::IROp_Header* IROp, IR::Ref Node) {}
Arm64JITCore::Arm64JITCore(FEXCore::Context::ContextImpl* ctx, FEXCore::Core::InternalThreadState* Thread)
: CPUBackend(*ctx, Thread)
, Arm64Emitter(ctx)
, HostSupportsSVE128 {ctx->HostFeatures.SupportsSVE128 != 0}
, HostSupportsSVE256 {ctx->HostFeatures.SupportsSVE256 != 0}
, HostSupportsAVX256 {ctx->HostFeatures.SupportsAVX && ctx->HostFeatures.SupportsSVE256}
, HostSupportsSVE128 {ctx->HostFeatures.SupportsSVE128()}
, HostSupportsSVE256 {ctx->HostFeatures.SupportsSVE256()}
, HostSupportsAVX256 {ctx->HostFeatures.SupportsAVX() && ctx->HostFeatures.SupportsSVE256()}
, HostSupportsRPRES {ctx->HostFeatures.SupportsRPRES != 0}
, HostSupportsAFP {ctx->HostFeatures.SupportsAFP != 0}
, CTX {ctx}
@@ -1370,20 +1370,19 @@ void OpDispatchBuilder::MOVOffsetOp(OpcodeArgs) {
}
void OpDispatchBuilder::CPUIDOp(OpcodeArgs) {
Ref Src = LoadGPRRegister(X86State::REG_RAX);
Ref Leaf = LoadGPRRegister(X86State::REG_RCX);
BlockSetRIP = true;
Ref RAX = _AllocateGPR(false);
Ref RBX = _AllocateGPR(false);
Ref RCX = _AllocateGPR(false);
Ref RDX = _AllocateGPR(false);
// Calculate flags early.
CalculateDeferredFlags();
_CPUID(Src, Leaf, RAX, RBX, RCX, RDX);
// Similar to Syscall. Store the RIP to the start of the instruction.
// CPUID operation will modify the RIP itself.
const auto GPRSize = GetGPROpSize();
auto NewRIP = GetRelocatedPC(Op, -Op->InstSize);
_StoreContextGPR(GPRSize, NewRIP, offsetof(FEXCore::Core::CPUState, rip));
StoreGPRRegister(X86State::REG_RAX, RAX);
StoreGPRRegister(X86State::REG_RBX, RBX);
StoreGPRRegister(X86State::REG_RCX, RCX);
StoreGPRRegister(X86State::REG_RDX, RDX);
FlushRegisterCache();
_CPUID(Op->InstSize);
}
uint32_t OpDispatchBuilder::GetConstantShift(X86Tables::DecodedOp Op, bool Is1Bit) {
@@ -4752,11 +4751,11 @@ OpDispatchBuilder::OpDispatchBuilder(FEXCore::Context::ContextImpl* ctx, FEXCore
: IREmitter {ctx->OpDispatcherAllocator, ctx->HostFeatures.SupportsTSOImm9 != 0}
, CTX {ctx}
, Thread {Thread} {
if (CTX->HostFeatures.SupportsAVX && CTX->HostFeatures.SupportsSVE256) {
if (CTX->HostFeatures.SupportsAVX() && CTX->HostFeatures.SupportsSVE256()) {
SaveAVXStateFunc = &OpDispatchBuilder::SaveAVXState;
RestoreAVXStateFunc = &OpDispatchBuilder::RestoreAVXState;
DefaultAVXStateFunc = &OpDispatchBuilder::DefaultAVXState;
} else if (CTX->HostFeatures.SupportsAVX) {
} else if (CTX->HostFeatures.SupportsAVX()) {
SaveAVXStateFunc = &OpDispatchBuilder::AVX128_SaveAVXState;
RestoreAVXStateFunc = &OpDispatchBuilder::AVX128_RestoreAVXState;
DefaultAVXStateFunc = &OpDispatchBuilder::AVX128_DefaultAVXState;
@@ -1330,7 +1330,7 @@ protected:
/* On ASIMD platforms, the emulation happens to preserve NZCV, unlike the
* more optimal SVE implementation that clobbers.
*/
if (!CTX->HostFeatures.SupportsSVE128 && !CTX->HostFeatures.SupportsSVE256) {
if (!CTX->HostFeatures.SupportsSVE()) {
return;
}
@@ -1677,7 +1677,7 @@ private:
}
constexpr OpSize GetGuestVectorLength() const {
return (CTX->HostFeatures.SupportsSVE256 && CTX->HostFeatures.SupportsAVX) ? OpSize::i256Bit : OpSize::i128Bit;
return (CTX->HostFeatures.SupportsSVE256() && CTX->HostFeatures.SupportsAVX()) ? OpSize::i256Bit : OpSize::i128Bit;
}
[[nodiscard]]
@@ -2067,7 +2067,7 @@ OpDispatchBuilder::RefPair OpDispatchBuilder::AVX128_VPGatherImpl(OpcodeArgs, Op
BaseAddr = Invalid();
}
if (CTX->HostFeatures.SupportsSVE128) {
if (CTX->HostFeatures.SupportsSVE128()) {
if (ElementLoadSize == OpSize::i64Bit && AddrElementSize == OpSize::i32Bit) {
// In the case that FEX is loading double the amount of data than the number of address bits then we can optimize this case.
// For 256-bits of data we need to sign extend all four 32-bit address elements to be 64-bit.
@@ -2170,7 +2170,7 @@ OpDispatchBuilder::RefPair OpDispatchBuilder::AVX128_VPGatherQPSImpl(OpcodeArgs,
bool NeedsSVEScale = (VSIB.Scale == 2 || VSIB.Scale == 8) || (BaseAddr == Invalid() && VSIB.Scale != 1);
if (CTX->HostFeatures.SupportsSVE128 && NeedsSVEScale) {
if (CTX->HostFeatures.SupportsSVE128() && NeedsSVEScale) {
// SVE gather instructions don't support scaling their vector elements by anything other than 1 or the address element size.
// Pre-scale 64-bit addresses in the case that scale doesn't match in-order to hit SVE code paths more frequently.
// Only hit this path if the host supports SVE. Otherwise it's a degradation for the ASIMD codepath.
@@ -2236,7 +2236,7 @@ void OpDispatchBuilder::AVX128_VPGATHER(OpcodeArgs, OpSize AddrElementSize) {
bool NeedsSVEScale = (VSIB.Scale == 2 || VSIB.Scale == 8) || (VSIB.BaseAddr == Invalid() && VSIB.Scale != 1);
const bool NeedsExplicitSVEPath =
CTX->HostFeatures.SupportsSVE128 && AddrElementSize == OpSize::i32Bit && ElementLoadSize == OpSize::i32Bit && NeedsSVEScale;
CTX->HostFeatures.SupportsSVE128() && AddrElementSize == OpSize::i32Bit && ElementLoadSize == OpSize::i32Bit && NeedsSVEScale;
RefPair Result {};
if (NeedsExplicitSVEPath) {
@@ -27,7 +27,7 @@ void OpDispatchBuilder::SHA1NEXTEOp(OpcodeArgs) {
Ref Src = LoadSourceFPR(Op, Op->Src[0], Op->Flags);
Ref Result {};
if (CTX->HostFeatures.SupportsSVE128) {
if (CTX->HostFeatures.SupportsSVE128()) {
auto ZeroVec = LoadZeroVector(OpSize::i128Bit);
auto Tmp = _VInsElement(OpSize::i128Bit, OpSize::i32Bit, 3, 3, ZeroVec, Dest);
auto Xar = _VXar(OpSize::i128Bit, OpSize::i32Bit, ZeroVec, Tmp, 2);
@@ -3025,7 +3025,7 @@ void OpDispatchBuilder::XSaveOpImpl(OpcodeArgs) {
StoreIfFlagSet(1, [this, Op] { SaveSSEState(XSaveBase(Op)); });
}
// AVX
if (CTX->HostFeatures.SupportsAVX) {
if (CTX->HostFeatures.SupportsAVX()) {
StoreIfFlagSet(2, [this, Op] { std::invoke(SaveAVXStateFunc, this, XSaveBase(Op)); });
}
@@ -3232,7 +3232,7 @@ void OpDispatchBuilder::XRstorOpImpl(OpcodeArgs) {
RestoreIfFlagSetOrDefault(1, [this, Op] { RestoreSSEState(XSaveBase(Op)); }, [this] { DefaultSSEState(); });
}
// AVX
if (CTX->HostFeatures.SupportsAVX) {
if (CTX->HostFeatures.SupportsAVX()) {
RestoreIfFlagSetOrDefault(
2, [this, Op] { std::invoke(RestoreAVXStateFunc, this, XSaveBase(Op)); }, [this] { std::invoke(DefaultAVXStateFunc, this); });
}
@@ -204,7 +204,7 @@ constexpr std::array<X86InstInfo, MAX_SECOND_TABLE_SIZE> SecondBaseOps = []() co
{0xA0, 1, X86InstInfo{"", TYPE_ARCH_DISPATCHER, FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, { .Indirect = Secondary_ArchSelect_LUT[ENTRY_A0] }}},
{0xA1, 1, X86InstInfo{"", TYPE_ARCH_DISPATCHER, FLAGS_DEBUG_MEM_ACCESS | FLAGS_NO_OVERLAY, 0, { .Indirect = Secondary_ArchSelect_LUT[ENTRY_A1] }}},
{0xA2, 1, X86InstInfo{"CPUID", TYPE_INST, FLAGS_NO_OVERLAY, 0}},
{0xA2, 1, X86InstInfo{"CPUID", TYPE_INST, FLAGS_NO_OVERLAY | FLAGS_BLOCK_END, 0}},
{0xA3, 1, X86InstInfo{"BT", TYPE_INST, FLAGS_DEBUG_MEM_ACCESS | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_NO_OVERLAY | FLAGS_SUPPORTS_LOCK, 0}},
{0xA4, 1, X86InstInfo{"SHLD", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_NO_OVERLAY, 1}},
{0xA5, 1, X86InstInfo{"SHLD", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_NO_OVERLAY, 0}},
+1 -2
View File
@@ -337,9 +337,8 @@
"HasSideEffects": true
},
"GPR:$EAX, GPR:$EBX, GPR:$ECX, GPR:$EDX = CPUID GPR:$Function, GPR:$Leaf": {
"CPUID i8:$InstSize": {
"Desc": ["Calls in to the CPUID handler function to return emulated CPUID"],
"DestSize": "OpSize::i32Bit",
"HasSideEffects": true
},
"GPR:$EAX, GPR:$EDX = XGetBV GPR:$Function": {
@@ -21,6 +21,7 @@ static bool IsFragmentExit(FEXCore::IR::IROps Op) {
switch (Op) {
case OP_THREADREMOVECODEENTRY:
case OP_SYSCALL:
case OP_CPUID:
case OP_EXITFUNCTION:
case OP_BREAK: return true;
default: return false;
@@ -527,27 +527,6 @@ bool ConstrainedRAPass::TryPostRAMerge(Ref LastNode, Ref CodeNode, IROp_Header*
IREmit->RemovePostRA(CodeNode);
return false;
}
} else if (IROp->Op == OP_CPUID && PhysicalRegister(IROp->Args[0]) == PhysicalRegister(LastNode) && LastOp->Op == OP_CONSTANT) {
// Try to constant fold. As a limitation of merging only 2 instructions, we
// can only handle constant functions, not constant leafs. This could be
// lifted if we generalized at a (significant) complexity cost.
uint64_t ConstantFunction = LastOp->C<IROp_Constant>()->Constant;
auto Op = IROp->CW<IR::IROp_CPUID>();
const auto SupportsConstant = CPUID->DoesFunctionReportConstantData(ConstantFunction);
if (SupportsConstant.SupportsConstantFunction == CPUIDEmu::SupportsConstant::CONSTANT &&
SupportsConstant.NeedsLeaf != CPUIDEmu::NeedsLeafConstant::NEEDSLEAFCONSTANT) {
const auto Result = CPUID->RunFunction(ConstantFunction, 0 /* leaf */);
IREmit->SetWriteCursorBefore(CodeNode);
IREmit->_Fence(IR::FenceType::Inst);
IREmit->_Constant(Result.eax).Node->Reg = PhysicalRegister(Op->OutEAX).Raw;
IREmit->_Constant(Result.ebx).Node->Reg = PhysicalRegister(Op->OutEBX).Raw;
IREmit->_Constant(Result.ecx).Node->Reg = PhysicalRegister(Op->OutECX).Raw;
IREmit->_Constant(Result.edx).Node->Reg = PhysicalRegister(Op->OutEDX).Raw;
IREmit->RemovePostRA(CodeNode);
return false;
}
}
// Merge moves that are immediately consumed.
+10 -1
View File
@@ -71,6 +71,12 @@ static_assert(std::is_standard_layout_v<NonAtomicRefCounter<uint64_t>>, "Needs t
static_assert(std::is_trivially_copyable_v<NonAtomicRefCounter<uint64_t>>, "needs to be trivially copyable");
static_assert(sizeof(NonAtomicRefCounter<uint64_t>) == sizeof(uint64_t), "Needs to be correct size");
// Flags about the core state that the JIT can query.
enum class CoreFlagsEnum : uint64_t {
CPUID_ENABLED = (1ULL << 0),
};
FEX_DEF_NUM_OPS(CoreFlagsEnum)
struct alignas(64) CPUState {
// Allows more efficient handling of the register
// file in the event AVX is not supported.
@@ -107,7 +113,9 @@ struct alignas(64) CPUState {
uint64_t L1Pointer {};
uint64_t L1Mask {};
uint64_t callret_sp {};
uint64_t _pad1 {};
// CPUID is default enabled.
CoreFlagsEnum CoreFlags {CoreFlagsEnum::CPUID_ENABLED};
// Cacheline: 1,2,3,4
// The high 128-bits of AVX registers when not being emulated by SVE256.
@@ -406,6 +414,7 @@ struct JITPointers {
uint64_t ThreadStopHandlerSpillSRA {};
uint64_t ThreadPauseHandlerSpillSRA {};
uint64_t ThreadDispatchSyscallHandler {};
uint64_t ThreadDispatchCPUIDHandler {};
uint64_t ThreadDispatchRemoveCodeEntry {};
uint64_t GuestSignal_SIGILL {};
uint64_t GuestSignal_SIGTRAP {};
+47 -29
View File
@@ -24,7 +24,22 @@ struct HostFeatures {
// Whether or not the host supports any kind of SVE implementation.
[[nodiscard]]
bool SupportsSVE() const {
return SupportsSVE128 || SupportsSVE256;
return ProcessFeatures.SupportsSVE128 || ProcessFeatures.SupportsSVE256;
}
[[nodiscard]]
bool SupportsSVE128() const {
return ProcessFeatures.SupportsSVE128;
}
[[nodiscard]]
bool SupportsSVE256() const {
return ProcessFeatures.SupportsSVE256;
}
[[nodiscard]]
bool SupportsAVX() const {
return ProcessFeatures.SupportsAVX;
}
[[nodiscard]]
@@ -42,7 +57,13 @@ struct HostFeatures {
// This only determines the starting mode a process started in.
// The process can technically long jump to-from the other modes.
uint8_t Is64BitMode : 1 {};
uint8_t pad : 4 {};
// These are technically HostFeatures, but they differ between Linux, wow64, arm64.
uint8_t SupportsAVX : 1 {};
uint8_t SupportsSVE128 : 1 {};
uint8_t SupportsSVE256 : 1 {};
uint8_t pad : 1 {};
};
static_assert(sizeof(ProcessFeaturesHash) == 1);
@@ -76,35 +97,32 @@ struct HostFeatures {
uint32_t SupportsRCPC : 1 {}; // [9]
uint32_t SupportsTSOImm9 : 1 {}; // [10]
uint32_t SupportsRAND : 1 {}; // [11]
uint32_t SupportsAVX : 1 {}; // [12] // Not enabled on wine?
uint32_t SupportsSVE128 : 1 {}; // [13]
uint32_t SupportsSVE256 : 1 {}; // [14]
uint32_t SupportsSHA : 1 {}; // [15]
uint32_t SupportsPMULL_128Bit : 1 {}; // [16]
uint32_t SupportsCSSC : 1 {}; // [17]
uint32_t SupportsFCMA : 1 {}; // [18]
uint32_t SupportsFlagM : 1 {}; // [19]
uint32_t SupportsFlagM2 : 1 {}; // [20]
uint32_t SupportsRPRES : 1 {}; // [21]
uint32_t SupportsPreserveAllABI : 1 {}; // [22] // Not enabled on wine
uint32_t SupportsAES256 : 1 {}; // [23]
uint32_t SupportsSVEBitPerm : 1 {}; // [24]
uint32_t SupportsCPUIndexInTPIDRRO : 1 {}; // [25]
uint32_t SupportsFRINTTS : 1 {}; // [26]
uint32_t SupportsECV : 1 {}; // [27]
uint32_t SupportsWFXT : 1 {}; // [28]
uint32_t Supports3DNow : 1 {}; // [29]
uint32_t SupportsSSE4a : 1 {}; // [30]
uint32_t SupportsMOPS : 1 {}; // [31]
uint32_t SupportsI8MM : 1 {}; // [32]
uint32_t SupportsDotProd : 1 {}; // [33]
uint32_t PreferZVAForVZero : 1 {}; // [34]
uint32_t SupportsAFP : 1 {}; // [35]
uint32_t SupportsFloatExceptions : 1 {}; // [36]
uint32_t SupportsBF16 : 1 {}; // [37]
uint32_t SupportsSHA : 1 {}; // [12]
uint32_t SupportsPMULL_128Bit : 1 {}; // [13]
uint32_t SupportsCSSC : 1 {}; // [14]
uint32_t SupportsFCMA : 1 {}; // [15]
uint32_t SupportsFlagM : 1 {}; // [16]
uint32_t SupportsFlagM2 : 1 {}; // [17]
uint32_t SupportsRPRES : 1 {}; // [18]
uint32_t SupportsPreserveAllABI : 1 {}; // [19]
uint32_t SupportsAES256 : 1 {}; // [20]
uint32_t SupportsSVEBitPerm : 1 {}; // [21]
uint32_t SupportsCPUIndexInTPIDRRO : 1 {}; // [22]
uint32_t SupportsFRINTTS : 1 {}; // [23]
uint32_t SupportsECV : 1 {}; // [24]
uint32_t SupportsWFXT : 1 {}; // [25]
uint32_t Supports3DNow : 1 {}; // [26]
uint32_t SupportsSSE4a : 1 {}; // [27]
uint32_t SupportsMOPS : 1 {}; // [28]
uint32_t SupportsI8MM : 1 {}; // [29]
uint32_t SupportsDotProd : 1 {}; // [30]
uint32_t PreferZVAForVZero : 1 {}; // [31]
uint32_t SupportsAFP : 1 {}; // [32]
uint32_t SupportsFloatExceptions : 1 {}; // [33]
uint32_t SupportsBF16 : 1 {}; // [34]
// Flag if this is InstCountCI
uint32_t IsInstCountCI : 1 {}; // [38]
uint32_t pad : 25 {}; // [63:39]
uint32_t pad : 28 {}; // [63:35]
// This affects codegen, but it isn't machine state
ProcessFeaturesHash ProcessFeatures {};
+11 -11
View File
@@ -354,8 +354,8 @@ static void OverrideFeatures(FEXCore::HostFeatures* Features, uint64_t ForceSVEW
const bool Enable##name = (HostFeatures() & FEXCore::Config::HostFeatures::ENABLE##enum_name) != 0; \
LogMan::Throw::AFmt(!(Disable##name && Enable##name), "Disabling and Enabling CPU feature (" #name ") is mutually exclusive");
ENABLE_DISABLE_OPTION(SupportsAVX, AVX, AVX);
ENABLE_DISABLE_OPTION(SupportsSVE128, SVE, SVE);
ENABLE_DISABLE_OPTION(ProcessFeatures.SupportsAVX, AVX, AVX);
ENABLE_DISABLE_OPTION(ProcessFeatures.SupportsSVE128, SVE, SVE);
ENABLE_DISABLE_OPTION(SupportsAFP, AFP, AFP);
ENABLE_DISABLE_OPTION(SupportsRCPC, LRCPC, LRCPC);
ENABLE_DISABLE_OPTION(SupportsTSOImm9, LRCPC2, LRCPC2);
@@ -399,7 +399,7 @@ static void OverrideFeatures(FEXCore::HostFeatures* Features, uint64_t ForceSVEW
}
///< Only force enable SVE256 if SVE is already enabled and ForceSVEWidth is set to >= 256.
Features->SupportsSVE256 = ForceSVEWidth && ForceSVEWidth >= 256;
Features->ProcessFeatures.SupportsSVE256 = ForceSVEWidth && ForceSVEWidth >= 256;
}
static void HandleErrata(FEXCore::HostFeatures* HostFeatures, uint64_t MIDR) {
@@ -515,15 +515,15 @@ void FetchHostFeatures(FEX::CPUFeatures& Features, FEXCore::HostFeatures& HostFe
#ifdef VIXL_SIMULATOR
// Hardcode enable SVE with 256-bit wide registers.
HostFeatures.SupportsSVE128 = ForceSVEWidth() ? ForceSVEWidth() >= 128 : true;
HostFeatures.SupportsSVE256 = ForceSVEWidth() ? ForceSVEWidth() >= 256 : true;
HostFeatures.ProcessFeatures.SupportsSVE128 = ForceSVEWidth() ? ForceSVEWidth() >= 128 : true;
HostFeatures.ProcessFeatures.SupportsSVE256 = ForceSVEWidth() ? ForceSVEWidth() >= 256 : true;
HostFeatures.SupportsMOPS = true;
// Simulator has a hardcoded ZVA size of 64-bytes.
HostFeatures.SupportsCLZERO = true;
HostFeatures.SupportsAES = true;
HostFeatures.SupportsCRC = true;
HostFeatures.SupportsAVX = true;
HostFeatures.ProcessFeatures.SupportsAVX = true;
HostFeatures.SupportsSHA = true;
HostFeatures.SupportsPMULL_128Bit = true;
HostFeatures.SupportsAES256 = true;
@@ -532,8 +532,8 @@ void FetchHostFeatures(FEX::CPUFeatures& Features, FEXCore::HostFeatures& HostFe
HostFeatures.SupportsRPRES = false;
HostFeatures.SupportsAFP = false;
#else
HostFeatures.SupportsSVE128 = Features.Supports(CPUFeatures::Feature::SVE2);
HostFeatures.SupportsSVE256 = Features.Supports(CPUFeatures::Feature::SVE2) && Features.GetSVEVectorLengthInBits() >= 256;
HostFeatures.ProcessFeatures.SupportsSVE128 = Features.Supports(CPUFeatures::Feature::SVE2);
HostFeatures.ProcessFeatures.SupportsSVE256 = Features.Supports(CPUFeatures::Feature::SVE2) && Features.GetSVEVectorLengthInBits() >= 256;
HostFeatures.SupportsMOPS = Features.Supports(CPUFeatures::Feature::MOPS);
// Check if we can support cacheline clears
@@ -546,8 +546,8 @@ void FetchHostFeatures(FEX::CPUFeatures& Features, FEXCore::HostFeatures& HostFe
#endif
HostFeatures.Supports3DNow = true;
HostFeatures.SupportsAVX = true;
HostFeatures.SupportsAES256 = HostFeatures.SupportsAVX && HostFeatures.SupportsAES;
HostFeatures.ProcessFeatures.SupportsAVX = true;
HostFeatures.SupportsAES256 = HostFeatures.SupportsAVX() && HostFeatures.SupportsAES;
HostFeatures.SupportsPreserveAllABI = FEX_HAS_PRESERVE_ALL_ATTR;
HostFeatures.PreferZVAForVZero = false;
@@ -589,7 +589,7 @@ void FetchHostFeatures(FEX::CPUFeatures& Features, FEXCore::HostFeatures& HostFe
HostFeatures.SupportsRAND = Feature.Feat_rand;
HostFeatures.SupportsRCPC = true;
HostFeatures.SupportsTSOImm9 = true;
HostFeatures.SupportsAVX = Feature.Feat_avx;
HostFeatures.ProcessFeatures.SupportsAVX = Feature.Feat_avx;
HostFeatures.SupportsSHA = Feature.Feat_sha;
HostFeatures.SupportsPMULL_128Bit = Feature.Feat_pclmulqdq;
HostFeatures.SupportsAES256 = Feature.Feat_aes;
@@ -552,8 +552,8 @@ int main(int argc, char** argv, char** const envp) {
{
auto HostFeatures = FEX::FetchHostFeatures(Loader.Is64BitMode());
CTX = FEXCore::Context::Context::CreateNewContext(HostFeatures);
SupportsAVX = HostFeatures.SupportsAVX;
SupportsSVE256 = HostFeatures.SupportsSVE256;
SupportsAVX = HostFeatures.SupportsAVX();
SupportsSVE256 = HostFeatures.SupportsSVE256();
}
FEX::Kernel::Init(Loader.Is64BitMode(), CTX.get());
@@ -546,11 +546,16 @@ void RegisterThread(FEX::HLE::SyscallHandler* Handler) {
Result = -EINVAL; // We don't support CET, return EINVAL
break;
case 0x1011: // ARCH_GET_CPUID
return 1;
break;
case 0x1012: // ARCH_SET_CPUID
return -ENODEV; // Claim we don't support faulting on CPUID
break;
return (Frame->State.CoreFlags & FEXCore::Core::CoreFlagsEnum::CPUID_ENABLED) == FEXCore::Core::CoreFlagsEnum::CPUID_ENABLED ? 1 : 0;
case 0x1012: // ARCH_SET_CPUID
if (addr == 0) {
// Disable CPUID (thus enabling CPUID faulting)
Frame->State.CoreFlags = Frame->State.CoreFlags & ~FEXCore::Core::CoreFlagsEnum::CPUID_ENABLED;
} else {
// Enable CPUID (thus disabling CPUID faulting)
Frame->State.CoreFlags = Frame->State.CoreFlags | FEXCore::Core::CoreFlagsEnum::CPUID_ENABLED;
}
return 0;
default:
LogMan::Msg::EFmt("Unknown prctl: 0x{:x}", code);
Result = -EINVAL;
@@ -247,7 +247,7 @@ int main(int argc, char** argv, char** const envp) {
auto CTX = FEXCore::Context::Context::CreateNewContext(HostFeatures);
#ifndef _WIN32
auto SignalDelegation = FEX::HLE::CreateSignalDelegator(CTX.get(), {}, HostFeatures.SupportsAVX, HostFeatures.SupportsSVE256);
auto SignalDelegation = FEX::HLE::CreateSignalDelegator(CTX.get(), {}, HostFeatures.SupportsAVX(), HostFeatures.SupportsSVE256());
#else
// Enable exit on HLT while Wine's longjump is broken.
//
@@ -257,7 +257,7 @@ int main(int argc, char** argv, char** const envp) {
#endif
// Skip any tests that the host doesn't support features for
SupportsAVX = HostFeatures.SupportsAVX;
SupportsAVX = HostFeatures.SupportsAVX();
bool TestUnsupported = (!SupportsAVX && Loader.RequiresAVX()) || (!HostFeatures.SupportsRAND && Loader.RequiresRAND()) ||
(!HostFeatures.SupportsSHA && Loader.RequiresSHA()) || (!HostFeatures.SupportsCLZERO && Loader.RequiresCLZERO()) ||
+5
View File
@@ -903,6 +903,11 @@ bool ResetToConsistentStateImpl(const ThreadCPUArea CPUArea, EXCEPTION_RECORD* E
return true;
}
if (NativeContext->Pc == reinterpret_cast<uint64_t>(&FEXCore::Assert::ForcedAssert)) {
LogMan::Msg::DFmt("FEX: Forced assert");
NtTerminateProcess(NtCurrentProcess(), 0x42);
}
if (!IsJIT && !IsDispatcherAddress(NativeContext->Pc)) {
LogMan::Msg::DFmt("Passing through exception");
return false;
+3 -3
View File
@@ -79,15 +79,15 @@ FEXCore::HostFeatures CPUFeatures::FetchHostFeatures(bool IsWine, FEXCore::HostF
FEX::FetchHostFeatures(Features, HostFeatures, IsWine, CTR, MIDR);
// Force-disable SVE until wine/windows gain support for SVE context save/restore
HostFeatures.SupportsSVE128 = false;
HostFeatures.SupportsSVE256 = false;
HostFeatures.ProcessFeatures.SupportsSVE128 = false;
HostFeatures.ProcessFeatures.SupportsSVE256 = false;
HostFeatures.SupportsCPUIndexInTPIDRRO = !IsWine || FEX::Windows::UnixLib::SupportsTPIDRRO_CPU();
HostFeatures.ProcessPID = ProcessPID;
// AVX is unsupported for WOW64
HostFeatures.SupportsAVX = HostType == FEXCore::HostFeatures::HostTypeEnum::Arm64ec;
HostFeatures.ProcessFeatures.SupportsAVX = HostType == FEXCore::HostFeatures::HostTypeEnum::Arm64ec;
HostFeatures.ProcessFeatures.HostType = HostType;
HostFeatures.ProcessFeatures.Is64BitMode = HostType == FEXCore::HostFeatures::HostTypeEnum::Arm64ec;
+16 -13
View File
@@ -182,20 +182,23 @@ FEXCore::ExecutableFileSectionInfo ImageTracker::HandleImageMap(std::string_view
}
}
uint64_t EndAddress = Address + Nt->OptionalHeader.SizeOfImage;
fextl::set<uint64_t> VolatileInstructions {};
FEXCore::IntervalList<uint64_t> VolatileValidRanges {};
LoadImageVolatileMetadata(VolatileInstructions, VolatileValidRanges, Module, Nt, Address, EndAddress);
if (auto It = ExtendedMetaData.find(ID); It != ExtendedMetaData.end()) {
FEX::VolatileMetadata::ApplyFEXExtendedVolatileMetadata(It->second, VolatileInstructions, VolatileValidRanges, Address, EndAddress);
}
if (auto It = ExtendedMetaData.find(fextl::string {ModuleName}); It != ExtendedMetaData.end()) {
FEX::VolatileMetadata::ApplyFEXExtendedVolatileMetadata(It->second, VolatileInstructions, VolatileValidRanges, Address, EndAddress);
}
if (!VolatileInstructions.empty() || !VolatileValidRanges.Empty()) {
LogMan::Msg::DFmt("Loaded volatile metadata for {:X}: {} entries", Address, VolatileInstructions.size());
CTX.AddForceTSOInformation(VolatileValidRanges, std::move(VolatileInstructions));
if (FEXCore::Config::Get_VOLATILEMETADATA()) {
uint64_t EndAddress = Address + Nt->OptionalHeader.SizeOfImage;
fextl::set<uint64_t> VolatileInstructions {};
FEXCore::IntervalList<uint64_t> VolatileValidRanges {};
LoadImageVolatileMetadata(VolatileInstructions, VolatileValidRanges, Module, Nt, Address, EndAddress);
if (auto It = ExtendedMetaData.find(ID); It != ExtendedMetaData.end()) {
FEX::VolatileMetadata::ApplyFEXExtendedVolatileMetadata(It->second, VolatileInstructions, VolatileValidRanges, Address, EndAddress);
}
if (auto It = ExtendedMetaData.find(fextl::string {ModuleName}); It != ExtendedMetaData.end()) {
FEX::VolatileMetadata::ApplyFEXExtendedVolatileMetadata(It->second, VolatileInstructions, VolatileValidRanges, Address, EndAddress);
}
if (!VolatileInstructions.empty() || !VolatileValidRanges.Empty()) {
LogMan::Msg::DFmt("Loaded volatile metadata for {:X}: {} entries", Address, VolatileInstructions.size());
CTX.AddForceTSOInformation(VolatileValidRanges, std::move(VolatileInstructions));
}
}
return ImageInfo->SectionInfo;
+5
View File
@@ -833,6 +833,11 @@ bool BTCpuResetToConsistentStateImpl(EXCEPTION_POINTERS* Ptrs) {
}
}
if (Context->Pc == reinterpret_cast<uint64_t>(&FEXCore::Assert::ForcedAssert)) {
LogMan::Msg::DFmt("FEX: Forced assert");
NtTerminateProcess(NtCurrentProcess(), 0x42);
}
if (!Thread || !IsAddressInJit(Context->Pc)) {
return false;
}
@@ -0,0 +1,309 @@
#include <catch2/catch_test_macros.hpp>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <signal.h>
#include <unistd.h>
#ifndef ARCH_GET_CPUID
#define ARCH_GET_CPUID 0x1011
#endif
#ifndef ARCH_SET_CPUID
#define ARCH_SET_CPUID 0x1012
#endif
struct cpuid_fn {
uint32_t eax, ebx, ecx, edx;
};
static cpuid_fn get_cpuid(uint32_t func, uint32_t leaf = 0) {
cpuid_fn fn {};
__asm volatile("cpuid" : "=a"(fn.eax), "=b"(fn.ebx), "=c"(fn.ecx), "=d"(fn.edx) : "a"(func), "c"(leaf));
return fn;
}
static cpuid_fn get_looooong_cpuid(uint32_t func, uint32_t leaf = 0) {
cpuid_fn fn {};
__asm volatile(".byte 0x66, 0x66, 0x66, 0x66;"
".byte 0x66, 0x66, 0x66, 0x66;"
".byte 0x66, 0x66, 0x66, 0x66;"
".byte 0x66;"
"cpuid"
: "=a"(fn.eax), "=b"(fn.ebx), "=c"(fn.ecx), "=d"(fn.edx)
: "a"(func), "c"(leaf));
return fn;
}
static cpuid_fn get_cpuid_2(uint32_t func, uint32_t leaf = 0) {
cpuid_fn fn {};
__asm volatile(".byte 0x26;"
"cpuid"
: "=a"(fn.eax), "=b"(fn.ebx), "=c"(fn.ecx), "=d"(fn.edx)
: "a"(func), "c"(leaf));
return fn;
}
static cpuid_fn get_cpuid_3(uint32_t func, uint32_t leaf = 0) {
cpuid_fn fn {};
__asm volatile(".byte 0x2e;"
"cpuid"
: "=a"(fn.eax), "=b"(fn.ebx), "=c"(fn.ecx), "=d"(fn.edx)
: "a"(func), "c"(leaf));
return fn;
}
static cpuid_fn get_cpuid_4(uint32_t func, uint32_t leaf = 0) {
cpuid_fn fn {};
__asm volatile(".byte 0x36;"
"cpuid"
: "=a"(fn.eax), "=b"(fn.ebx), "=c"(fn.ecx), "=d"(fn.edx)
: "a"(func), "c"(leaf));
return fn;
}
static cpuid_fn get_cpuid_5(uint32_t func, uint32_t leaf = 0) {
cpuid_fn fn {};
__asm volatile(".byte 0x3E;"
"cpuid"
: "=a"(fn.eax), "=b"(fn.ebx), "=c"(fn.ecx), "=d"(fn.edx)
: "a"(func), "c"(leaf));
return fn;
}
static cpuid_fn get_cpuid_6(uint32_t func, uint32_t leaf = 0) {
cpuid_fn fn {};
__asm volatile(".byte 0x64;"
"cpuid"
: "=a"(fn.eax), "=b"(fn.ebx), "=c"(fn.ecx), "=d"(fn.edx)
: "a"(func), "c"(leaf));
return fn;
}
static cpuid_fn get_cpuid_7(uint32_t func, uint32_t leaf = 0) {
cpuid_fn fn {};
__asm volatile(".byte 0x65;"
"cpuid"
: "=a"(fn.eax), "=b"(fn.ebx), "=c"(fn.ecx), "=d"(fn.edx)
: "a"(func), "c"(leaf));
return fn;
}
static cpuid_fn get_cpuid_8(uint32_t func, uint32_t leaf = 0) {
cpuid_fn fn {};
__asm volatile(".byte 0x66;"
"cpuid"
: "=a"(fn.eax), "=b"(fn.ebx), "=c"(fn.ecx), "=d"(fn.edx)
: "a"(func), "c"(leaf));
return fn;
}
static cpuid_fn get_cpuid_9(uint32_t func, uint32_t leaf = 0) {
cpuid_fn fn {};
__asm volatile(".byte 0x67;"
"cpuid"
: "=a"(fn.eax), "=b"(fn.ebx), "=c"(fn.ecx), "=d"(fn.edx)
: "a"(func), "c"(leaf));
return fn;
}
static cpuid_fn get_cpuid_10(uint32_t func, uint32_t leaf = 0) {
cpuid_fn fn {};
__asm volatile(".byte 0xF2;"
"cpuid"
: "=a"(fn.eax), "=b"(fn.ebx), "=c"(fn.ecx), "=d"(fn.edx)
: "a"(func), "c"(leaf));
return fn;
}
static cpuid_fn get_cpuid_11(uint32_t func, uint32_t leaf = 0) {
cpuid_fn fn {};
__asm volatile(".byte 0xf3;"
"cpuid"
: "=a"(fn.eax), "=b"(fn.ebx), "=c"(fn.ecx), "=d"(fn.edx)
: "a"(func), "c"(leaf));
return fn;
}
#ifdef REG_RIP
// 0x40 isn't REX prefix on 32-bit.
static cpuid_fn get_cpuid_12(uint32_t func, uint32_t leaf = 0) {
cpuid_fn fn {};
__asm volatile(".byte 0x40;"
"cpuid"
: "=a"(fn.eax), "=b"(fn.ebx), "=c"(fn.ecx), "=d"(fn.edx)
: "a"(func), "c"(leaf));
return fn;
}
#endif
static size_t is_cpuid(uint8_t* data) {
size_t inst_size {};
while (true) {
if (inst_size == 15) {
return 0;
}
uint8_t byte = data[inst_size];
switch (byte) {
case 0x26: // ES
case 0x2e: // CS
case 0x36: // SS
case 0x3E: // DS
case 0x64: // FS
case 0x65: // GS
case 0x66: // Opcode size
case 0x67: // Addr size
case 0xF2: // REPNE
case 0xF3: // REPE
#ifdef REG_RIP
case 0x40 ... 0x4f: // REX
#endif
break;
case 0xF0: return 0; // Lock explicitly isn't supported on CPUID, should fault.
case 0xf: {
++inst_size;
byte = data[inst_size];
if (byte == 0xa2) {
return inst_size + 1;
}
// Nope
return 0;
}
}
++inst_size;
}
return inst_size;
}
static int faults {};
static void SignalHandler(int signal, siginfo_t* siginfo, void* context) {
ucontext_t* _context = (ucontext_t*)context;
#ifdef REG_RIP
#define FEX_IP_REG REG_RIP
#define FEX_RAX_REG REG_RAX
#define FEX_RBX_REG REG_RBX
#define FEX_RCX_REG REG_RCX
#define FEX_RDX_REG REG_RDX
#else
#define FEX_IP_REG REG_EIP
#define FEX_RAX_REG REG_EAX
#define FEX_RBX_REG REG_EBX
#define FEX_RCX_REG REG_ECX
#define FEX_RDX_REG REG_EDX
#endif
if (signal != SIGSEGV) {
FAIL("Incorrect signal");
}
if (_context->uc_mcontext.gregs[REG_TRAPNO] != 13) {
FAIL("Incorrect trapno");
}
if (_context->uc_mcontext.gregs[REG_ERR] != 0) {
FAIL("Incorrect reg_err");
}
if (siginfo->si_code != 0x80) {
FAIL("Incorrect si_code");
}
size_t inst_size = is_cpuid(reinterpret_cast<uint8_t*>(_context->uc_mcontext.gregs[FEX_IP_REG]));
if (inst_size == 0) {
FAIL("Isn't cpuid");
}
// Return bogus data
_context->uc_mcontext.gregs[FEX_RAX_REG] = 0x41424344U + faults;
_context->uc_mcontext.gregs[FEX_RBX_REG] = 0x51525354U + faults;
_context->uc_mcontext.gregs[FEX_RCX_REG] = 0x61626364U + faults;
_context->uc_mcontext.gregs[FEX_RDX_REG] = 0x71727374U + faults;
_context->uc_mcontext.gregs[FEX_IP_REG] += inst_size;
++faults;
}
TEST_CASE("cpuid faulting") {
cpuid_fn fn0 = get_cpuid(0);
if (syscall(SYS_arch_prctl, ARCH_SET_CPUID, (void*)1) != 0) {
// Unsupported, just skip.
return;
}
struct sigaction act {};
act.sa_sigaction = SignalHandler;
act.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &act, nullptr);
using ptr_type = cpuid_fn (*)(uint32_t, uint32_t);
ptr_type test_funcs[] = {
get_cpuid, get_cpuid_2, get_cpuid_3, get_cpuid_4, get_cpuid_5, get_cpuid_6,
get_cpuid_7, get_cpuid_8, get_cpuid_9, get_cpuid_10, get_cpuid_11,
#ifdef REG_RIP
get_cpuid_12,
#endif
get_looooong_cpuid,
};
// Just attempt regular CPUID for now.
for (auto ptr : test_funcs) {
faults = 0;
cpuid_fn fn_emu = ptr(0, 0);
REQUIRE(faults == 0);
CHECK(fn0.eax == fn_emu.eax);
CHECK(fn0.ebx == fn_emu.ebx);
CHECK(fn0.ecx == fn_emu.ecx);
CHECK(fn0.edx == fn_emu.edx);
}
// Enable faulting.
REQUIRE(syscall(SYS_arch_prctl, ARCH_SET_CPUID, (void*)0) == 0);
for (auto ptr : test_funcs) {
faults = 0;
cpuid_fn fn_emu = ptr(0, 0);
REQUIRE(faults == 1);
CHECK(fn0.eax != fn_emu.eax);
CHECK(fn0.ebx != fn_emu.ebx);
CHECK(fn0.ecx != fn_emu.ecx);
CHECK(fn0.edx != fn_emu.edx);
CHECK(fn_emu.eax == 0x41424344U);
CHECK(fn_emu.ebx == 0x51525354U);
CHECK(fn_emu.ecx == 0x61626364U);
CHECK(fn_emu.edx == 0x71727374U);
}
// Disable faulting.
REQUIRE(syscall(SYS_arch_prctl, ARCH_SET_CPUID, (void*)1) == 0);
// Just attempt regular CPUID for now.
for (auto ptr : test_funcs) {
faults = 0;
cpuid_fn fn_emu = ptr(0, 0);
REQUIRE(faults == 0);
CHECK(fn0.eax == fn_emu.eax);
CHECK(fn0.ebx == fn_emu.ebx);
CHECK(fn0.ecx == fn_emu.ecx);
CHECK(fn0.edx == fn_emu.edx);
}
}
+1 -1
View File
@@ -8,7 +8,7 @@
"SVE128",
"SVE256"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"roundss xmm0, xmm1, 00000000b": {
@@ -7,7 +7,7 @@
"AFP"
],
"DisabledHostFeatures": [],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"cvtpi2ps xmm0, [rax]": {
@@ -9,7 +9,7 @@
"DisabledHostFeatures": [
"RPRES"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"cvtsi2ss xmm0, eax": {
@@ -7,7 +7,7 @@
"AFP"
],
"DisabledHostFeatures": [],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"cvtsi2sd xmm0, eax": {
@@ -8,7 +8,7 @@
"SVE128",
"SVE256"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"cvtpi2ps xmm0, [rax]": {
@@ -9,7 +9,7 @@
"SVE256",
"RPRES"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"cvtsi2ss xmm0, eax": {
@@ -8,7 +8,7 @@
"SVE128",
"SVE256"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"cvtsi2sd xmm0, eax": {
@@ -9,7 +9,7 @@
"DisabledHostFeatures": [
"RPRES"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vsqrtss xmm0, xmm1, xmm2": {
@@ -7,7 +7,7 @@
"AFP"
],
"DisabledHostFeatures": [],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vroundss xmm0, xmm1, 00000000b": {
+31 -31
View File
@@ -7,7 +7,7 @@
"SVE256",
"SVE128"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vfmaddsubps xmm0, xmm1, xmm2, xmm3": {
@@ -22,7 +22,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -38,7 +38,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -54,7 +54,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -70,7 +70,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -86,7 +86,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -102,7 +102,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -118,7 +118,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -134,7 +134,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -150,7 +150,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -166,7 +166,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -182,7 +182,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -198,7 +198,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -214,7 +214,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -230,7 +230,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -246,7 +246,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -262,7 +262,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -278,7 +278,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -294,7 +294,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -310,7 +310,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -326,7 +326,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -342,7 +342,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -358,7 +358,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -374,7 +374,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -390,7 +390,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -406,7 +406,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -422,7 +422,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -438,7 +438,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -454,7 +454,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -470,7 +470,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -486,7 +486,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
}
@@ -13,7 +13,7 @@
"SVE256",
"SVE128"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vmovups xmm0, xmm0": {
@@ -9,7 +9,7 @@
"SVE256",
"SVE128"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vaddsubpd xmm0, xmm1, xmm2": {
@@ -10,7 +10,7 @@
"FLAGM2",
"SVE256"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vmovntps [rax], xmm0": {
@@ -10,7 +10,7 @@
"SVE128",
"SVE256"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vucomiss xmm0, xmm1": {
@@ -13,7 +13,7 @@
"I8MM",
"DOTPROD"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vpshufb xmm0, xmm1, xmm2": {
@@ -2224,7 +2224,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -2241,7 +2241,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -2258,7 +2258,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -2275,7 +2275,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -2292,7 +2292,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -2309,7 +2309,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -2326,7 +2326,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -2343,7 +2343,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -2360,7 +2360,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -2377,7 +2377,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -2394,7 +2394,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -2411,7 +2411,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -6268,7 +6268,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -6284,7 +6284,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -6300,7 +6300,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -6316,7 +6316,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -6457,7 +6457,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -6474,7 +6474,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -6491,7 +6491,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -6508,7 +6508,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -6525,7 +6525,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -6542,7 +6542,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -6559,7 +6559,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -6576,7 +6576,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -6593,7 +6593,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -6610,7 +6610,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -6627,7 +6627,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -6644,7 +6644,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -8,7 +8,7 @@
"SVE256",
"SVE128"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vfmadd132ss xmm0, xmm1, xmm2": {
@@ -12,7 +12,7 @@
"SVE256",
"I8MM"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vpdpbusd xmm0, xmm1, xmm2": {
@@ -11,7 +11,7 @@
"SVE128",
"SVE256"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vpdpbusd xmm0, xmm1, xmm2": {
@@ -10,7 +10,7 @@
"FLAGM2",
"SVE256"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vmovntdqa xmm0, [rax]": {
@@ -11,7 +11,7 @@
"SVE256",
"SVEBITPERM"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vtestps xmm0, xmm1": {
@@ -7,7 +7,7 @@
"SVE256",
"SVE128"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vpermq ymm0, ymm1, 1": {
@@ -8,7 +8,7 @@
"AFP",
"SVE256"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vblendvps xmm0, xmm1, xmm2, xmm3": {
@@ -9,7 +9,7 @@
"SVE256",
"SVE128"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vpsrlw xmm0, xmm1, 0": {
+1 -1
View File
@@ -9,7 +9,7 @@
"FLAGM",
"FLAGM2"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"lock add byte [rax], cl": {
@@ -9,7 +9,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"sha1nexte xmm0, xmm1": {
@@ -91,7 +91,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -107,7 +107,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -123,7 +123,7 @@
"mov w0, #0x401",
"str x0, [x28, #1296]",
"str x20, [x28, #1304]",
"ldr x0, [x28, #2800]",
"ldr x0, [x28, #2808]",
"br x0"
]
},
@@ -9,7 +9,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"sha1nexte xmm0, xmm1": {
@@ -9,7 +9,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"pclmulqdq xmm0, xmm1, 00000b": {
+1 -1
View File
@@ -10,7 +10,7 @@
"AFP",
"RPRES"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Comment": [
"These 3DNow! instructions are optimal assuming that FEX doesn't SRA MMX registers",
@@ -8,7 +8,7 @@
"RPRES",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Comment": [
"Instructions that explicitly push against the limits of ARM's loadstore instructions"
@@ -8,7 +8,7 @@
"RPRES",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Comment": [
"Instructions that explicitly push against the limits of ARM's loadstore instructions"
@@ -13,36 +13,12 @@
"RPRES",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Comment": [
"These are instruction combinations that could be more optimal if FEX optimized for them"
],
"Instructions": {
"cpuid constant": {
"x86InstructionCount": 2,
"ExpectedInstructionCount": 11,
"Comment": [
"CPUID function call with constant function id"
],
"x86Insts": [
"mov rax, 0",
"cpuid"
],
"ExpectedArm64ASM": [
"mov w4, #0x0",
"isb",
"mov w20, #0x16",
"mov w6, #0x6547",
"movk w6, #0x756e, lsl #16",
"mov w21, #0x746e",
"movk w21, #0x6c65, lsl #16",
"mov w5, #0x6e69",
"movk w5, #0x4965, lsl #16",
"mov x7, x21",
"mov x4, x20"
]
},
"xgetbv constant": {
"x86InstructionCount": 2,
"ExpectedInstructionCount": 3,
@@ -11,7 +11,7 @@
"RPRES",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Comment": [
"These are instruction combinations that could be more optimal if FEX optimized for them"
@@ -9,7 +9,7 @@
"SVE256",
"RPRES"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Comment": [
"These are instruction combinations that could be more optimal if FEX optimized for them"
@@ -14,7 +14,7 @@
"RPRES",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Comment": [
"These are instruction combinations that could be more optimal if FEX optimized for them"
@@ -14,7 +14,7 @@
"RPRES",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Comment": [
"These are instruction combinations that could be more optimal if FEX optimized for them"
@@ -13,7 +13,7 @@
"I8MM",
"DOTPROD"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Comment": [
"This file tracks the translations for the 'peephole' optimizations in FEX.",
@@ -10,7 +10,7 @@
"FLAGM2",
"SVE256"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Comment": [
"This file tracks the translations for the 'peephole' optimizations in FEX.",
@@ -12,7 +12,7 @@
"RPRES",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Comment": [],
"Instructions": {
@@ -10,7 +10,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"lock add byte [rax], cl": {
@@ -9,7 +9,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"Chained add": {
@@ -10,7 +10,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"ptest xmm0, xmm1": {
@@ -10,7 +10,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"The Witcher 3": {
@@ -10,7 +10,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"Sonic Mania movie player": {
@@ -10,7 +10,7 @@
"SVE128",
"SVE256"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"FMOD scalar loop": {
@@ -13,7 +13,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"The Sims 1 hot block": {
@@ -10,7 +10,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"add bl, cl": {
@@ -10,7 +10,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"add al, 1": {
@@ -10,7 +10,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"push es": {
@@ -11,7 +11,7 @@
"RPRES",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"ucomiss xmm0, xmm1": {
@@ -11,7 +11,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"sgdt [rax]": {
@@ -11,7 +11,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"xgetbv": {
@@ -11,7 +11,7 @@
"AFP",
"FCMA"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"ucomisd xmm0, xmm1": {
@@ -12,7 +12,7 @@
"AFP",
"CSSC"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"popcnt ax, bx": {
@@ -12,7 +12,7 @@
"RPRES",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"popcnt ax, bx": {
@@ -12,7 +12,7 @@
"RPRES",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vucomiss xmm0, xmm1": {
@@ -10,7 +10,7 @@
"AFP",
"SVEBITPERM"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"vtestps xmm0, xmm1": {
@@ -9,7 +9,7 @@
"DisabledHostFeatures": [
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"blsr eax, ebx": {
@@ -10,7 +10,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"Block1": {
@@ -10,7 +10,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"Block1": {
@@ -10,7 +10,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"Block1": {
@@ -10,7 +10,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"Block1": {
+1 -1
View File
@@ -11,7 +11,7 @@
"CSSC",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"fadd dword [rax]": {
@@ -13,7 +13,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"Block1": {
@@ -13,7 +13,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"Block1": {
@@ -13,7 +13,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"Block1": {
@@ -13,7 +13,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"Block1": {
+13 -13
View File
@@ -13,7 +13,7 @@
"SVE256",
"AFP"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"fadd dword [rax]": {
@@ -2232,7 +2232,7 @@
"add x20, x28, x20, lsl #4",
"ldr d2, [x20, #1056]",
"fmov d0, d2",
"ldr x0, [x28, #2880]",
"ldr x0, [x28, #2888]",
"str x30, [sp, #-16]!",
"blr x0",
"ldr x30, [sp], #16",
@@ -2255,7 +2255,7 @@
"ldr d3, [x23, #1056]",
"fmov d0, d3",
"fmov d1, d2",
"ldr x0, [x28, #2904]",
"ldr x0, [x28, #2912]",
"str x30, [sp, #-16]!",
"blr x0",
"ldr x30, [sp], #16",
@@ -2279,7 +2279,7 @@
"add x21, x28, x20, lsl #4",
"ldr d2, [x21, #1056]",
"fmov d0, d2",
"ldr x0, [x28, #2872]",
"ldr x0, [x28, #2880]",
"str x30, [sp, #-16]!",
"blr x0",
"ldr x30, [sp], #16",
@@ -2315,7 +2315,7 @@
"ldr d3, [x22, #1056]",
"fmov d0, d3",
"fmov d1, d2",
"ldr x0, [x28, #2896]",
"ldr x0, [x28, #2904]",
"str x30, [sp, #-16]!",
"blr x0",
"ldr x30, [sp], #16",
@@ -2392,7 +2392,7 @@
"ldr d3, [x20, #1056]",
"fmov d0, d3",
"fmov d1, d2",
"ldr x0, [x28, #2928]",
"ldr x0, [x28, #2936]",
"str x30, [sp, #-16]!",
"blr x0",
"ldr x30, [sp], #16",
@@ -2442,7 +2442,7 @@
"ldr d3, [x20, #1056]",
"fmov d0, d3",
"fmov d1, d2",
"ldr x0, [x28, #2920]",
"ldr x0, [x28, #2928]",
"str x30, [sp, #-16]!",
"blr x0",
"ldr x30, [sp], #16",
@@ -2466,7 +2466,7 @@
"ldr d3, [x23, #1056]",
"fmov d0, d3",
"fmov d1, d2",
"ldr x0, [x28, #2912]",
"ldr x0, [x28, #2920]",
"str x30, [sp, #-16]!",
"blr x0",
"ldr x30, [sp], #16",
@@ -2503,13 +2503,13 @@
"add x21, x28, x20, lsl #4",
"ldr d2, [x21, #1056]",
"fmov d0, d2",
"ldr x0, [x28, #2856]",
"ldr x0, [x28, #2864]",
"str x30, [sp, #-16]!",
"blr x0",
"ldr x30, [sp], #16",
"fmov d3, d0",
"fmov d0, d2",
"ldr x0, [x28, #2864]",
"ldr x0, [x28, #2872]",
"str x30, [sp, #-16]!",
"blr x0",
"ldr x30, [sp], #16",
@@ -2556,7 +2556,7 @@
"ldr d3, [x20, #1056]",
"fmov d0, d3",
"fmov d1, d2",
"ldr x0, [x28, #2888]",
"ldr x0, [x28, #2896]",
"str x30, [sp, #-16]!",
"blr x0",
"ldr x30, [sp], #16",
@@ -2574,7 +2574,7 @@
"add x20, x28, x20, lsl #4",
"ldr d2, [x20, #1056]",
"fmov d0, d2",
"ldr x0, [x28, #2856]",
"ldr x0, [x28, #2864]",
"str x30, [sp, #-16]!",
"blr x0",
"ldr x30, [sp], #16",
@@ -2593,7 +2593,7 @@
"add x20, x28, x20, lsl #4",
"ldr d2, [x20, #1056]",
"fmov d0, d2",
"ldr x0, [x28, #2864]",
"ldr x0, [x28, #2872]",
"str x30, [sp, #-16]!",
"blr x0",
"ldr x30, [sp], #16",
+1 -1
View File
@@ -10,7 +10,7 @@
"FLAGM2",
"CRYPTO"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Instructions": {
"pshufb mm0, mm1": {
+1 -1
View File
@@ -8,7 +8,7 @@
"AFP",
"CRYPTO"
],
"BinaryCacheVersion": 42
"BinaryCacheVersion": 43
},
"Comment": [
"SSE4.2 string instructions are skipped here.",
Loaded 100 of 139 files, more files were not shown because too many files have changed in this diff. Show more