mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-11-07 09:16:08 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae495b971b | ||
|
|
feee41a768 | ||
|
|
cf2f831ad9 | ||
|
|
b9fc587ac8 | ||
|
|
c985199ed5 | ||
|
|
e67bbd3ecf | ||
|
|
02e932d9f4 | ||
|
|
a3f5700c33 | ||
|
|
a2b15c8e0f | ||
|
|
05293166ce | ||
|
|
ef586f03a8 | ||
|
|
6a3d85a26f | ||
|
|
36aec0d54d |
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.
|
||||
//
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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 {};
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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}},
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {};
|
||||
|
||||
@@ -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 {};
|
||||
|
||||
@@ -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()) ||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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": {
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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,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",
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"FLAGM2",
|
||||
"CRYPTO"
|
||||
],
|
||||
"BinaryCacheVersion": 42
|
||||
"BinaryCacheVersion": 43
|
||||
},
|
||||
"Instructions": {
|
||||
"pshufb mm0, mm1": {
|
||||
|
||||
@@ -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
Reference in new issue
Block a user