OpcodeDispatcher: Initial support for runtime long-mode switch

This has the Frontend and OpcodeDispatcher select their operating mode
depending on the incoming code segment long-mode flag.

Adds some asserts since currently it is unexpected if the configuration
changes at runtime.

This is fairly straightforward for an initial setup but isn't fully
fleshed out.

Right now FEX's x86 tables aren't setup in a way to support choosing a
different instruction decoding depending on runtime operating mode
change, so that would break in interesting ways.

Primarily this just gets FEX setup to start piping the operating mode
through from the frontend to the backend. This is a long term task, so
it is going to take a long time to iron out all the issues.
This commit is contained in:
Ryan Houdek committed 2023-12-21 01:54:19 -08:00
1 parent 8648fb1485
commit 9e5d7aa5fe
8 files changed
+140 -125

No files matched your search

@@ -309,8 +309,6 @@ namespace FEXCore::Context {
void CopyMemoryMapping(FEXCore::Core::InternalThreadState *ParentThread, FEXCore::Core::InternalThreadState *ChildThread);
uint8_t GetGPRSize() const { return Config.Is64BitMode ? 8 : 4; }
FEXCore::JITSymbols Symbols;
void GetVDSOSigReturn(VDSOSigReturn *VDSOPointers) override {
+3 -5
View File
@@ -544,7 +544,7 @@ namespace FEXCore::Context {
bool HadDispatchError {false};
Thread->FrontendDecoder->DecodeInstructionsAtEntry(GuestCode, GuestRIP, MaxInst, [Thread](uint64_t BlockEntry, uint64_t Start, uint64_t Length) {
Thread->FrontendDecoder->DecodeInstructionsAtEntry(Thread, GuestCode, GuestRIP, MaxInst, [Thread](uint64_t BlockEntry, uint64_t Start, uint64_t Length) {
if (Thread->LookupCache->AddBlockExecutableRange(BlockEntry, Start, Length)) {
static_cast<ContextImpl*>(Thread->CTX)->SyscallHandler->MarkGuestExecutableRange(Thread, Start, Length);
}
@@ -553,9 +553,9 @@ namespace FEXCore::Context {
auto BlockInfo = Thread->FrontendDecoder->GetDecodedBlockInfo();
auto CodeBlocks = &BlockInfo->Blocks;
Thread->OpDispatcher->BeginFunction(GuestRIP, CodeBlocks, BlockInfo->TotalInstructionCount);
Thread->OpDispatcher->BeginFunction(GuestRIP, CodeBlocks, BlockInfo->TotalInstructionCount, BlockInfo->Is64BitMode);
const uint8_t GPRSize = GetGPRSize();
const uint8_t GPRSize = Thread->OpDispatcher->GetGPRSize();
for (size_t j = 0; j < CodeBlocks->size(); ++j) {
FEXCore::Frontend::Decoder::DecodedBlocks const &Block = CodeBlocks->at(j);
@@ -640,8 +640,6 @@ namespace FEXCore::Context {
}
if (NeedsBlockEnd) {
const uint8_t GPRSize = GetGPRSize();
// We had some instructions. Early exit
Thread->OpDispatcher->_ExitFunction(Thread->OpDispatcher->_EntrypointOffset(IR::SizeToOpSize(GPRSize), Block.Entry + BlockInstructionsLength - GuestRIP));
break;
+21 -16
View File
@@ -311,7 +311,7 @@ bool Decoder::NormalOp(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op,
uint8_t DestSize{};
const bool HasWideningDisplacement = (FEXCore::X86Tables::DecodeFlags::GetOpAddr(DecodeInst->Flags, 0) & FEXCore::X86Tables::DecodeFlags::FLAG_WIDENING_SIZE_LAST) != 0 ||
(Options.w && CTX->Config.Is64BitMode);
(Options.w && BlockInfo.Is64BitMode);
const bool HasNarrowingDisplacement = (FEXCore::X86Tables::DecodeFlags::GetOpAddr(DecodeInst->Flags, 0) & FEXCore::X86Tables::DecodeFlags::FLAG_OPERAND_SIZE_LAST) != 0;
const bool HasXMMFlags = (Info->Flags & InstFlags::FLAGS_XMM_FLAGS) != 0;
@@ -332,7 +332,7 @@ bool Decoder::NormalOp(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op,
const bool HasMODRM = !!(Info->Flags & FEXCore::X86Tables::InstFlags::FLAGS_MODRM);
const bool HasREX = !!(DecodeInst->Flags & DecodeFlags::FLAG_REX_PREFIX);
const bool Has16BitAddressing = !CTX->Config.Is64BitMode &&
const bool Has16BitAddressing = !BlockInfo.Is64BitMode &&
DecodeInst->Flags & DecodeFlags::FLAG_ADDRESS_SIZE;
// This is used for ModRM register modification
@@ -387,7 +387,7 @@ bool Decoder::NormalOp(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op,
DestSize = 2;
}
else if (
(HasXMMDst || HasMMDst || CTX->Config.Is64BitMode) &&
(HasXMMDst || HasMMDst || BlockInfo.Is64BitMode) &&
(HasWideningDisplacement ||
DstSizeFlag == FEXCore::X86Tables::InstFlags::SIZE_64BIT ||
DstSizeFlag == FEXCore::X86Tables::InstFlags::SIZE_64BITDEF)) {
@@ -425,7 +425,7 @@ bool Decoder::NormalOp(FEXCore::X86Tables::X86InstInfo const *Info, uint16_t Op,
DecodeInst->Flags |= DecodeFlags::GenSizeSrcSize(DecodeFlags::SIZE_16BIT);
}
else if (
(HasXMMSrc || HasMMSrc || CTX->Config.Is64BitMode) &&
(HasXMMSrc || HasMMSrc || BlockInfo.Is64BitMode) &&
(HasWideningDisplacement ||
SrcSizeFlag == FEXCore::X86Tables::InstFlags::SIZE_64BIT ||
SrcSizeFlag == FEXCore::X86Tables::InstFlags::SIZE_64BITDEF)) {
@@ -693,7 +693,7 @@ bool Decoder::NormalOpHeader(FEXCore::X86Tables::X86InstInfo const *Info, uint16
DecodedHeader options{};
if ((Byte1 & 0b10000000) == 0) {
LOGMAN_THROW_A_FMT(CTX->Config.Is64BitMode, "VEX.R shouldn't be 0 in 32-bit mode!");
LOGMAN_THROW_A_FMT(BlockInfo.Is64BitMode, "VEX.R shouldn't be 0 in 32-bit mode!");
DecodeInst->Flags |= DecodeFlags::FLAG_REX_XGPR_R;
}
@@ -710,10 +710,10 @@ bool Decoder::NormalOpHeader(FEXCore::X86Tables::X86InstInfo const *Info, uint16
options.w = (Byte2 & 0b10000000) != 0;
options.L = (Byte2 & 0b100) != 0;
if ((Byte1 & 0b01000000) == 0) {
LOGMAN_THROW_A_FMT(CTX->Config.Is64BitMode, "VEX.X shouldn't be 0 in 32-bit mode!");
LOGMAN_THROW_A_FMT(BlockInfo.Is64BitMode, "VEX.X shouldn't be 0 in 32-bit mode!");
DecodeInst->Flags |= DecodeFlags::FLAG_REX_XGPR_X;
}
if (CTX->Config.Is64BitMode && (Byte1 & 0b00100000) == 0) {
if (BlockInfo.Is64BitMode && (Byte1 & 0b00100000) == 0) {
DecodeInst->Flags |= DecodeFlags::FLAG_REX_XGPR_B;
}
if (!(map_select >= 1 && map_select <= 3)) {
@@ -788,7 +788,7 @@ bool Decoder::DecodeInstruction(uint64_t PC) {
FEXCore::X86Tables::ModRMDecoded ModRM;
ModRM.Hex = DecodeInst->ModRM;
const bool Has16BitAddressing = !CTX->Config.Is64BitMode &&
const bool Has16BitAddressing = !BlockInfo.Is64BitMode &&
DecodeInst->Flags & DecodeFlags::FLAG_ADDRESS_SIZE;
// All 3DNow! instructions have the second argument as the rm handler
@@ -899,17 +899,17 @@ bool Decoder::DecodeInstruction(uint64_t PC) {
DecodeInst->Flags |= DecodeFlags::FLAG_ADDRESS_SIZE;
break;
case 0x26: // ES legacy prefix
if (!CTX->Config.Is64BitMode) {
if (!BlockInfo.Is64BitMode) {
DecodeInst->Flags |= DecodeFlags::FLAG_ES_PREFIX;
}
break;
case 0x2E: // CS legacy prefix
if (!CTX->Config.Is64BitMode) {
if (!BlockInfo.Is64BitMode) {
DecodeInst->Flags |= DecodeFlags::FLAG_CS_PREFIX;
}
break;
case 0x36: // SS legacy prefix
if (!CTX->Config.Is64BitMode) {
if (!BlockInfo.Is64BitMode) {
DecodeInst->Flags |= DecodeFlags::FLAG_SS_PREFIX;
}
break;
@@ -917,7 +917,7 @@ bool Decoder::DecodeInstruction(uint64_t PC) {
// Annoyingly GCC generates NOP ops with these prefixes
// Just ignore them for now
// eg. 66 2e 0f 1f 84 00 00 00 00 00 nop WORD PTR cs:[rax+rax*1+0x0]
if (!CTX->Config.Is64BitMode) {
if (!BlockInfo.Is64BitMode) {
DecodeInst->Flags |= DecodeFlags::FLAG_DS_PREFIX;
}
break;
@@ -943,7 +943,7 @@ bool Decoder::DecodeInstruction(uint64_t PC) {
auto Info = &FEXCore::X86Tables::BaseOps[Op];
if (Info->Type == FEXCore::X86Tables::TYPE_REX_PREFIX) {
LOGMAN_THROW_A_FMT(CTX->Config.Is64BitMode, "Got REX prefix in 32bit mode");
LOGMAN_THROW_A_FMT(BlockInfo.Is64BitMode, "Got REX prefix in 32bit mode");
DecodeInst->Flags |= DecodeFlags::FLAG_REX_PREFIX;
// Widening displacement
@@ -986,7 +986,7 @@ void Decoder::BranchTargetInMultiblockRange() {
// If the RIP setting is conditional AND within our symbol range then it can be considered for multiblock
uint64_t TargetRIP = 0;
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
bool Conditional = true;
switch (DecodeInst->OP) {
@@ -1053,7 +1053,7 @@ bool Decoder::BranchTargetCanContinue(bool FinalInstruction) const {
}
uint64_t TargetRIP = 0;
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
if (DecodeInst->OP == 0xE8) { // Call - immediate target
const uint64_t NextRIP = DecodeInst->PC + DecodeInst->InstSize;
@@ -1095,7 +1095,7 @@ const uint8_t *Decoder::AdjustAddrForSpecialRegion(uint8_t const* _InstStream, u
return _InstStream - EntryPoint + RIP;
}
void Decoder::DecodeInstructionsAtEntry(uint8_t const* _InstStream, uint64_t PC, uint64_t MaxInst, std::function<void(uint64_t BlockEntry, uint64_t Start, uint64_t Length)> AddContainedCodePage) {
void Decoder::DecodeInstructionsAtEntry(FEXCore::Core::InternalThreadState *Thread, uint8_t const* _InstStream, uint64_t PC, uint64_t MaxInst, std::function<void(uint64_t BlockEntry, uint64_t Start, uint64_t Length)> AddContainedCodePage) {
FEXCORE_PROFILE_SCOPED("DecodeInstructions");
BlockInfo.TotalInstructionCount = 0;
BlockInfo.Blocks.clear();
@@ -1107,6 +1107,11 @@ void Decoder::DecodeInstructionsAtEntry(uint8_t const* _InstStream, uint64_t PC,
MaxCondBranchBackwards = ~0ULL;
DecodedBuffer = PoolObject.ReownOrClaimBuffer();
// Decode operating mode from thread's CS segment.
const auto CSSegment = Thread->CurrentFrame->State.gdt[Thread->CurrentFrame->State.cs_idx >> 3];
BlockInfo.Is64BitMode = CSSegment.L == 1;
LOGMAN_THROW_A_FMT(BlockInfo.Is64BitMode == CTX->Config.Is64BitMode, "Expected operating mode to not change at runtime!");
// XXX: Load symbol data
SymbolAvailable = false;
EntryPoint = PC;
+3 -1
View File
@@ -29,12 +29,13 @@ public:
struct DecodedBlockInformation final {
uint64_t TotalInstructionCount;
bool Is64BitMode{};
fextl::vector<DecodedBlocks> Blocks;
};
Decoder(FEXCore::Context::ContextImpl *ctx);
~Decoder();
void DecodeInstructionsAtEntry(uint8_t const* InstStream, uint64_t PC, uint64_t MaxInst, std::function<void(uint64_t BlockEntry, uint64_t Start, uint64_t Length)> AddContainedCodePage);
void DecodeInstructionsAtEntry(FEXCore::Core::InternalThreadState *Thread, uint8_t const* InstStream, uint64_t PC, uint64_t MaxInst, std::function<void(uint64_t BlockEntry, uint64_t Start, uint64_t Length)> AddContainedCodePage);
DecodedBlockInformation const *GetDecodedBlockInfo() const {
return &BlockInfo;
@@ -81,6 +82,7 @@ private:
size_t DecodedSize {};
uint8_t const *InstStream;
uint8_t GetGPRSize() const { return BlockInfo.Is64BitMode ? 8 : 4; }
static constexpr size_t MAX_INST_SIZE = 15;
uint8_t InstructionSize;
@@ -106,7 +106,7 @@ void OpDispatchBuilder::SyscallOp(OpcodeArgs) {
// Calculate flags early.
CalculateDeferredFlags();
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
auto NewRIP = GetRelocatedPC(Op, -Op->InstSize);
_StoreContext(GPRSize, GPRClass, NewRIP, offsetof(FEXCore::Core::CPUState, rip));
@@ -154,10 +154,10 @@ void OpDispatchBuilder::ThunkOp(OpcodeArgs) {
// Calculate flags early.
CalculateDeferredFlags();
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
uint8_t *sha256 = (uint8_t *)(Op->PC + 2);
if (CTX->Config.Is64BitMode) {
if (Is64BitMode) {
// x86-64 ABI puts the function argument in RDI
_Thunk(
LoadGPRRegister(X86State::REG_RDI),
@@ -190,14 +190,14 @@ void OpDispatchBuilder::LEAOp(OpcodeArgs) {
// LEA specifically ignores segment prefixes
const auto SrcSize = GetSrcSize(Op);
if (CTX->Config.Is64BitMode) {
if (Is64BitMode) {
const uint32_t DstSize = X86Tables::DecodeFlags::GetOpAddr(Op->Flags, 0) == X86Tables::DecodeFlags::FLAG_OPERAND_SIZE_LAST ? 2 :
X86Tables::DecodeFlags::GetOpAddr(Op->Flags, 0) == X86Tables::DecodeFlags::FLAG_WIDENING_SIZE_LAST ? 8 : 4;
auto Src = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], SrcSize, Op->Flags, {.LoadData = false});
if (DstSize != SrcSize) {
// If the SrcSize isn't the DstSize then we need to zero extend.
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
Src = _Bfe(IR::SizeToOpSize(GPRSize), SrcSize * 8, 0, Src);
}
StoreResult_WithOpSize(GPRClass, Op, Op->Dest, Src, DstSize, -1);
@@ -214,7 +214,7 @@ void OpDispatchBuilder::NOPOp(OpcodeArgs) {
}
void OpDispatchBuilder::RETOp(OpcodeArgs) {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
// ABI Optimization: Flags don't survive calls or rets
if (CTX->Config.ABILocalFlags) {
@@ -269,7 +269,7 @@ void OpDispatchBuilder::IRETOp(OpcodeArgs) {
// Calculate flags early.
CalculateDeferredFlags();
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
auto Constant = _Constant(GPRSize);
@@ -289,7 +289,7 @@ void OpDispatchBuilder::IRETOp(OpcodeArgs) {
SetPackedRFLAG(false, eflags);
SP = _Add(IR::SizeToOpSize(GPRSize), SP, Constant);
if (CTX->Config.Is64BitMode) {
if (Is64BitMode) {
// RSP and SS only happen in 64-bit mode or if this is a CPL mode jump!
// FEX doesn't support a CPL mode switch, so don't need to worry about this on 32-bit
StoreGPRRegister(X86State::REG_RSP, _LoadMem(GPRClass, GPRSize, SP, GPRSize));
@@ -313,7 +313,7 @@ void OpDispatchBuilder::IRETOp(OpcodeArgs) {
}
void OpDispatchBuilder::CallbackReturnOp(OpcodeArgs) {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
// Store the new RIP
_CallbackReturn();
auto NewRIP = _LoadContext(GPRSize, GPRClass, offsetof(FEXCore::Core::CPUState, rip));
@@ -507,7 +507,7 @@ void OpDispatchBuilder::PUSHOp(OpcodeArgs) {
auto OldSP = LoadGPRRegister(X86State::REG_RSP);
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
auto NewSP = _Push(GPRSize, Size, Src, OldSP);
// Store the new stack pointer
@@ -521,7 +521,7 @@ void OpDispatchBuilder::PUSHREGOp(OpcodeArgs) {
{.AllowUpperGarbage = true});
auto OldSP = LoadGPRRegister(X86State::REG_RSP);
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
auto NewSP = _Push(GPRSize, Size, Src, OldSP);
// Store the new stack pointer
StoreGPRRegister(X86State::REG_RSP, NewSP);
@@ -546,7 +546,7 @@ void OpDispatchBuilder::PUSHAOp(OpcodeArgs) {
OrderedNode *Src{};
OrderedNode *NewSP = OldSP;
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
Src = LoadGPRRegister(X86State::REG_RAX);
NewSP = _Push(GPRSize, Size, Src, NewSP);
@@ -584,7 +584,7 @@ void OpDispatchBuilder::PUSHSegmentOp(OpcodeArgs) {
auto OldSP = LoadGPRRegister(X86State::REG_RSP);
OrderedNode *Src{};
if (!CTX->Config.Is64BitMode()) {
if (!Is64BitMode) {
switch (SegmentReg) {
case FEXCore::X86Tables::DecodeFlags::FLAG_ES_PREFIX:
Src = _LoadContext(SrcSize, GPRClass, offsetof(FEXCore::Core::CPUState, es_idx));
@@ -631,7 +631,7 @@ void OpDispatchBuilder::PUSHSegmentOp(OpcodeArgs) {
}
}
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
// Store our value to the new stack location
// AMD hardware zexts segment selector to 32bit
// Intel hardware inserts segment selector
@@ -764,7 +764,7 @@ void OpDispatchBuilder::LEAVEOp(OpcodeArgs) {
}
void OpDispatchBuilder::CALLOp(OpcodeArgs) {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
BlockSetRIP = true;
@@ -935,7 +935,7 @@ void OpDispatchBuilder::SETccOp(OpcodeArgs) {
}
void OpDispatchBuilder::CMOVOp(OpcodeArgs) {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
// Calculate flags early.
CalculateDeferredFlags();
@@ -967,7 +967,7 @@ void OpDispatchBuilder::CondJUMPOp(OpcodeArgs) {
uint64_t InstRIP = Op->PC + Op->InstSize;
uint64_t Target = InstRIP + TargetOffset;
if (CTX->GetGPRSize() == 4) {
if (GetGPRSize() == 4) {
// If the GPRSize is 4 then we need to be careful about PC wrapping
if (TargetOffset < 0 && -TargetOffset > InstRIP) {
// Invert the signed value if we are underflowing
@@ -1042,7 +1042,7 @@ void OpDispatchBuilder::CondJUMPRCXOp(OpcodeArgs) {
CalculateDeferredFlags();
BlockSetRIP = true;
uint8_t JcxGPRSize = CTX->GetGPRSize();
uint8_t JcxGPRSize = GetGPRSize();
JcxGPRSize = (Op->Flags & X86Tables::DecodeFlags::FLAG_ADDRESS_SIZE) ? (JcxGPRSize >> 1) : JcxGPRSize;
IRPair<IROp_Constant> TakeBranch;
@@ -1195,7 +1195,7 @@ void OpDispatchBuilder::JUMPOp(OpcodeArgs) {
uint64_t InstRIP = Op->PC + Op->InstSize;
uint64_t TargetRIP = InstRIP + TargetOffset;
if (CTX->GetGPRSize() == 4) {
if (GetGPRSize() == 4) {
// If the GPRSize is 4 then we need to be careful about PC wrapping
if (TargetOffset < 0 && -TargetOffset > InstRIP) {
// Invert the signed value if we are underflowing
@@ -1481,7 +1481,7 @@ void OpDispatchBuilder::MOVSegOp(OpcodeArgs) {
break;
case FEXCore::X86State::REG_RBP: // GS
case FEXCore::X86State::REG_R13: // GS
if (!CTX->Config.Is64BitMode) {
if (!Is64BitMode) {
_StoreContext(2, GPRClass, Src, offsetof(FEXCore::Core::CPUState, gs_idx));
UpdatePrefixFromSegment(Src, FEXCore::X86Tables::DecodeFlags::FLAG_GS_PREFIX);
} else {
@@ -1491,7 +1491,7 @@ void OpDispatchBuilder::MOVSegOp(OpcodeArgs) {
break;
case FEXCore::X86State::REG_RSP: // FS
case FEXCore::X86State::REG_R12: // FS
if (!CTX->Config.Is64BitMode) {
if (!Is64BitMode) {
_StoreContext(2, GPRClass, Src, offsetof(FEXCore::Core::CPUState, fs_idx));
UpdatePrefixFromSegment(Src, FEXCore::X86Tables::DecodeFlags::FLAG_FS_PREFIX);
} else {
@@ -1527,7 +1527,7 @@ void OpDispatchBuilder::MOVSegOp(OpcodeArgs) {
break;
case FEXCore::X86State::REG_RBP: // GS
case FEXCore::X86State::REG_R13: // GS
if (CTX->Config.Is64BitMode) {
if (Is64BitMode) {
Segment = _Constant(0);
}
else {
@@ -1536,7 +1536,7 @@ void OpDispatchBuilder::MOVSegOp(OpcodeArgs) {
break;
case FEXCore::X86State::REG_RSP: // FS
case FEXCore::X86State::REG_R12: // FS
if (CTX->Config.Is64BitMode) {
if (Is64BitMode) {
Segment = _Constant(0);
}
else {
@@ -1583,7 +1583,7 @@ void OpDispatchBuilder::MOVOffsetOp(OpcodeArgs) {
}
void OpDispatchBuilder::CPUIDOp(OpcodeArgs) {
const auto GPRSize = CTX->GetGPRSize();
const auto GPRSize = GetGPRSize();
OrderedNode *Src = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], GPRSize, Op->Flags);
OrderedNode *Leaf = LoadGPRRegister(X86State::REG_RCX);
@@ -2174,7 +2174,7 @@ void OpDispatchBuilder::BLSRBMIOp(OpcodeArgs) {
void OpDispatchBuilder::BMI2Shift(OpcodeArgs) {
// In the event the source is a memory operand, use the
// exact width instead of the GPR size.
const auto GPRSize = CTX->GetGPRSize();
const auto GPRSize = GetGPRSize();
const auto Size = GetSrcSize(Op);
const auto SrcSize = Op->Src[0].IsGPR() ? GPRSize : Size;
@@ -2236,7 +2236,7 @@ void OpDispatchBuilder::RORX(OpcodeArgs) {
const auto Amount = Op->Src[1].Data.Literal.Value;
const auto SrcSize = GetSrcSize(Op);
const auto SrcSizeBits = SrcSize * 8;
const auto GPRSize = CTX->GetGPRSize();
const auto GPRSize = GetGPRSize();
const auto DoRotation = Amount != 0 && Amount < SrcSizeBits;
const auto IsSameGPR = Op->Src[0].IsGPR() && Op->Dest.IsGPR() &&
@@ -2269,7 +2269,7 @@ void OpDispatchBuilder::MULX(OpcodeArgs) {
// Src1 can be a memory operand, so ensure we constrain to the
// absolute width of the access in that scenario.
const auto GPRSize = CTX->GetGPRSize();
const auto GPRSize = GetGPRSize();
const auto Src1Size = Op->Src[1].IsGPR() ? GPRSize : OperandSize;
OrderedNode* Src1 = LoadSource_WithOpSize(GPRClass, Op, Op->Src[1], Src1Size, Op->Flags);
@@ -2756,7 +2756,7 @@ void OpDispatchBuilder::BTOp(OpcodeArgs) {
if (Op->Dest.IsGPR()) {
// When the destination is a GPR, we don't care about garbage in the upper bits.
// Load the full register.
auto Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, CTX->GetGPRSize(), Op->Flags);
auto Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, GetGPRSize(), Op->Flags);
Value = Dest;
// Get the bit selection from the src. We need to mask for 8/16-bit, but
@@ -2992,7 +2992,7 @@ void OpDispatchBuilder::IMULOp(OpcodeArgs) {
StoreGPRRegister(X86State::REG_RDX, LocalResultHigh);
}
else if (Size == 8) {
if (!CTX->Config.Is64BitMode) {
if (!Is64BitMode) {
LogMan::Msg::EFmt("Doesn't exist in 32bit mode");
DecodeFailure = true;
return;
@@ -3042,7 +3042,7 @@ void OpDispatchBuilder::MULOp(OpcodeArgs) {
StoreGPRRegister(X86State::REG_RDX, ResultHigh);
}
else if (Size == 8) {
if (!CTX->Config.Is64BitMode) {
if (!Is64BitMode) {
LogMan::Msg::EFmt("Doesn't exist in 32bit mode");
DecodeFailure = true;
return;
@@ -3089,7 +3089,7 @@ void OpDispatchBuilder::NOTOp(OpcodeArgs) {
// Always load full size, we explicitly want the upper bits to get the
// insert behaviour for free/implicitly.
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
OrderedNode *Src = LoadSource_WithOpSize(GPRClass, Op, Dest, GPRSize, Op->Flags);
// For 8/16-bit, use 64-bit invert so we invert in place, while getting
@@ -3453,7 +3453,7 @@ void OpDispatchBuilder::WriteSegmentReg(OpcodeArgs) {
}
void OpDispatchBuilder::EnterOp(OpcodeArgs) {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
LOGMAN_THROW_A_FMT(Op->Src[0].IsLiteral(), "Src1 needs to be literal here");
const uint64_t Value = Op->Src[0].Data.Literal.Value;
@@ -3462,7 +3462,7 @@ void OpDispatchBuilder::EnterOp(OpcodeArgs) {
const uint8_t Level = (Value >> 16) & 0x1F;
const auto PushValue = [&](uint8_t Size, OrderedNode *Src) -> OrderedNode* {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
auto OldSP = LoadGPRRegister(X86State::REG_RSP);
auto NewSP = _Push(GPRSize, Size, Src, OldSP);
@@ -3503,7 +3503,7 @@ void OpDispatchBuilder::SGDTOp(OpcodeArgs) {
// Operand size prefix is ignored on this instruction, size purely depends on operating mode.
uint64_t GDTAddress = 0xFFFFFFFFFFFE0000ULL;
size_t GDTStoreSize = 8;
if (!CTX->Config.Is64BitMode) {
if (!Is64BitMode) {
// Mask off upper bits if 32-bit result.
GDTAddress &= ~0U;
GDTStoreSize = 4;
@@ -3607,7 +3607,7 @@ void OpDispatchBuilder::STOSOp(OpcodeArgs) {
// Calculate direction.
auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC);
auto SizeConst = _Constant(Size);
auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1);
auto PtrDir = _SubShift(IR::SizeToOpSize(GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1);
// Offset the pointer
OrderedNode *TailDest = LoadGPRRegister(X86State::REG_RDI);
@@ -3669,7 +3669,7 @@ void OpDispatchBuilder::MOVSOp(OpcodeArgs) {
}
else {
auto SizeConst = _Constant(Size);
auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1);
auto PtrDir = _SubShift(IR::SizeToOpSize(GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1);
OrderedNode *RSI = LoadGPRRegister(X86State::REG_RSI);
OrderedNode *RDI = LoadGPRRegister(X86State::REG_RDI);
@@ -3716,7 +3716,7 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) {
auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC);
auto SizeConst = _Constant(Size);
auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1);
auto PtrDir = _SubShift(IR::SizeToOpSize(GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1);
// Offset the pointer
Dest_RDI = _Add(OpSize::i64Bit, Dest_RDI, PtrDir);
@@ -3735,7 +3735,7 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) {
// read DF once
auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC);
auto SizeConst = _Constant(Size);
auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1);
auto PtrDir = _SubShift(IR::SizeToOpSize(GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1);
auto JumpStart = Jump();
// Make sure to start a new block after ending this one
@@ -3829,7 +3829,7 @@ void OpDispatchBuilder::LODSOp(OpcodeArgs) {
auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC);
auto SizeConst = _Constant(Size);
auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1);
auto PtrDir = _SubShift(IR::SizeToOpSize(GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1);
// Offset the pointer
OrderedNode *TailDest_RSI = LoadGPRRegister(X86State::REG_RSI);
@@ -3850,7 +3850,7 @@ void OpDispatchBuilder::LODSOp(OpcodeArgs) {
// Read DF once
auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC);
auto SizeConst = _Constant(Size);
auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1);
auto PtrDir = _SubShift(IR::SizeToOpSize(GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1);
auto JumpStart = Jump();
// Make sure to start a new block after ending this one
@@ -3927,7 +3927,7 @@ void OpDispatchBuilder::SCASOp(OpcodeArgs) {
auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC);
auto SizeConst = _Constant(Size);
auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1);
auto PtrDir = _SubShift(IR::SizeToOpSize(GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1);
// Offset the pointer
OrderedNode *TailDest_RDI = LoadGPRRegister(X86State::REG_RDI);
@@ -3944,7 +3944,7 @@ void OpDispatchBuilder::SCASOp(OpcodeArgs) {
// read DF once
auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC);
auto SizeConst = _Constant(Size);
auto PtrDir = _SubShift(IR::SizeToOpSize(CTX->GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1);
auto PtrDir = _SubShift(IR::SizeToOpSize(GetGPRSize()), SizeConst, DF, ShiftType::LSL, FEXCore::ilog2(Size) + 1);
auto JumpStart = Jump();
// Make sure to start a new block after ending this one
@@ -4019,7 +4019,7 @@ void OpDispatchBuilder::BSWAPOp(OpcodeArgs) {
Dest = _Constant(0);
}
else {
Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, CTX->GetGPRSize(), Op->Flags);
Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, GetGPRSize(), Op->Flags);
Dest = _Rev(IR::SizeToOpSize(Size), Dest);
}
StoreResult(GPRClass, Op, Dest, -1);
@@ -4035,7 +4035,7 @@ void OpDispatchBuilder::PUSHFOp(OpcodeArgs) {
auto OldSP = LoadGPRRegister(X86State::REG_RSP);
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
auto NewSP = _Push(GPRSize, Size, Src, OldSP);
// Store the new stack pointer
@@ -4092,7 +4092,7 @@ void OpDispatchBuilder::DIVOp(OpcodeArgs) {
// This loads the divisor
OrderedNode *Divisor = LoadSource(GPRClass, Op, Op->Dest, Op->Flags);
const auto GPRSize = CTX->GetGPRSize();
const auto GPRSize = GetGPRSize();
const auto Size = GetSrcSize(Op);
if (Size == 1) {
@@ -4125,7 +4125,7 @@ void OpDispatchBuilder::DIVOp(OpcodeArgs) {
StoreGPRRegister(X86State::REG_RDX, URemOp);
}
else if (Size == 8) {
if (!CTX->Config.Is64BitMode) {
if (!Is64BitMode) {
LogMan::Msg::EFmt("Doesn't exist in 32bit mode");
DecodeFailure = true;
return;
@@ -4145,7 +4145,7 @@ void OpDispatchBuilder::IDIVOp(OpcodeArgs) {
// This loads the divisor
OrderedNode *Divisor = LoadSource(GPRClass, Op, Op->Dest, Op->Flags);
const auto GPRSize = CTX->GetGPRSize();
const auto GPRSize = GetGPRSize();
const auto Size = GetSrcSize(Op);
if (Size == 1) {
@@ -4180,7 +4180,7 @@ void OpDispatchBuilder::IDIVOp(OpcodeArgs) {
StoreGPRRegister(X86State::REG_RDX, URemOp);
}
else if (Size == 8) {
if (!CTX->Config.Is64BitMode) {
if (!Is64BitMode) {
LogMan::Msg::EFmt("Doesn't exist in 32bit mode");
DecodeFailure = true;
return;
@@ -4197,7 +4197,7 @@ void OpDispatchBuilder::IDIVOp(OpcodeArgs) {
}
void OpDispatchBuilder::BSFOp(OpcodeArgs) {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
const uint8_t DstSize = GetDstSize(Op) == 2 ? 2 : GPRSize;
OrderedNode *Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, DstSize, Op->Flags);
OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags);
@@ -4218,7 +4218,7 @@ void OpDispatchBuilder::BSFOp(OpcodeArgs) {
}
void OpDispatchBuilder::BSROp(OpcodeArgs) {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
const uint8_t DstSize = GetDstSize(Op) == 2 ? 2 : GPRSize;
OrderedNode *Dest = LoadSource_WithOpSize(GPRClass, Op, Op->Dest, DstSize, Op->Flags);
OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags);
@@ -4254,7 +4254,7 @@ void OpDispatchBuilder::CMPXCHGOp(OpcodeArgs) {
// *Xn = Xt
// Xs = MemData
const auto GPRSize = CTX->GetGPRSize();
const auto GPRSize = GetGPRSize();
auto Size = GetSrcSize(Op);
// This is our source register
@@ -4448,8 +4448,11 @@ void OpDispatchBuilder::CreateJumpBlocks(fextl::vector<FEXCore::Frontend::Decode
}
}
void OpDispatchBuilder::BeginFunction(uint64_t RIP, fextl::vector<FEXCore::Frontend::Decoder::DecodedBlocks> const *Blocks, uint32_t NumInstructions) {
void OpDispatchBuilder::BeginFunction(uint64_t RIP, fextl::vector<FEXCore::Frontend::Decoder::DecodedBlocks> const *Blocks, uint32_t NumInstructions, bool _Is64BitMode) {
Entry = RIP;
Is64BitMode = _Is64BitMode;
LOGMAN_THROW_A_FMT(Is64BitMode == CTX->Config.Is64BitMode, "Expected operating mode to not change at runtime!");
auto IRHeader = _IRHeader(InvalidNode, RIP, 0, NumInstructions);
CreateJumpBlocks(Blocks);
@@ -4464,7 +4467,7 @@ void OpDispatchBuilder::Finalize() {
// Calculate flags early.
// This usually doesn't emit any IR but in the case of hitting the block instruction limit it will
CalculateDeferredFlags();
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
// Node 0 is invalid node
OrderedNode *RealNode = reinterpret_cast<OrderedNode*>(GetNode(1));
@@ -4505,7 +4508,7 @@ uint32_t OpDispatchBuilder::GetDstBitSize(X86Tables::DecodedOp Op) const {
}
OrderedNode *OpDispatchBuilder::GetSegment(uint32_t Flags, uint32_t DefaultPrefix, bool Override) {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
if (CTX->Config.Is64BitMode) {
if (Flags & FEXCore::X86Tables::DecodeFlags::FLAG_FS_PREFIX) {
@@ -4652,8 +4655,14 @@ void OpDispatchBuilder::UpdatePrefixFromSegment(OrderedNode *Segment, uint32_t S
// Use BFE to extract the selector index in bits [15,3] of the segment register.
// In some cases the upper 16-bits of the 32-bit GPR contain garbage to ignore.
Segment = _Bfe(OpSize::i32Bit, 16 - 3, 3, Segment);
auto NewSegment = _LoadContextIndexed(Segment, 4, offsetof(FEXCore::Core::CPUState, gdt[0]), 4, GPRClass);
OrderedNode *NewSegment = _LoadContextIndexed(Segment, 8, offsetof(FEXCore::Core::CPUState, gdt[0]), 8, GPRClass);
CheckLegacySegmentWrite(NewSegment, SegmentReg);
// Extract the 32-bit base from the GDT segment.
auto Upper32 = _Lshr(OpSize::i64Bit, NewSegment, _Constant(32));
auto Masked = _And(OpSize::i32Bit, Upper32, _Constant(0xFF00'0000));
OrderedNode *Merged = _Orlshr(OpSize::i32Bit, Masked, NewSegment, 16);
NewSegment = _Bfi(OpSize::i32Bit, 8, 16, Merged, Upper32);
switch (SegmentReg) {
case FEXCore::X86Tables::DecodeFlags::FLAG_ES_PREFIX:
_StoreContext(4, GPRClass, NewSegment, offsetof(FEXCore::Core::CPUState, es_cached));
@@ -4691,7 +4700,7 @@ OrderedNode *OpDispatchBuilder::LoadSource_WithOpSize(RegisterClassType Class, X
OrderedNode *Src {nullptr};
bool LoadableType = false;
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
const uint32_t AddrSize = (Op->Flags & X86Tables::DecodeFlags::FLAG_ADDRESS_SIZE) != 0 ? (GPRSize >> 1) : GPRSize;
if (Operand.IsLiteral()) {
@@ -4749,7 +4758,7 @@ OrderedNode *OpDispatchBuilder::LoadSource_WithOpSize(RegisterClassType Class, X
}
}
else if (Operand.IsRIPRelative()) {
if (CTX->Config.Is64BitMode) {
if (Is64BitMode) {
Src = GetRelocatedPC(Op, Operand.Data.RIPLiteral.Value.s);
}
else {
@@ -4851,12 +4860,12 @@ OrderedNode *OpDispatchBuilder::LoadSource_WithOpSize(RegisterClassType Class, X
}
OrderedNode *OpDispatchBuilder::GetRelocatedPC(FEXCore::X86Tables::DecodedOp const& Op, int64_t Offset) {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
return _EntrypointOffset(IR::SizeToOpSize(GPRSize), Op->PC + Op->InstSize + Offset - Entry);
}
OrderedNode *OpDispatchBuilder::LoadGPRRegister(uint32_t GPR, int8_t Size, uint8_t Offset, bool AllowUpperGarbage) {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
if (Size == -1) {
Size = GPRSize;
}
@@ -4884,7 +4893,7 @@ OrderedNode *OpDispatchBuilder::LoadXMMRegister(uint32_t XMM) {
}
void OpDispatchBuilder::StoreGPRRegister(uint32_t GPR, OrderedNode *const Src, int8_t Size, uint8_t Offset) {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
if (Size == -1) {
Size = GPRSize;
}
@@ -4927,7 +4936,7 @@ void OpDispatchBuilder::StoreResult_WithOpSize(FEXCore::IR::RegisterClassType Cl
// 32bit ops ZEXT the result to 64bit
OrderedNode *MemStoreDst {nullptr};
bool MemStore = false;
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
const uint32_t AddrSize = (Op->Flags & X86Tables::DecodeFlags::FLAG_ADDRESS_SIZE) != 0 ? (GPRSize >> 1) : GPRSize;
if (Operand.IsLiteral()) {
@@ -5005,7 +5014,7 @@ void OpDispatchBuilder::StoreResult_WithOpSize(FEXCore::IR::RegisterClassType Cl
}
}
else if (Operand.IsRIPRelative()) {
if (CTX->Config.Is64BitMode) {
if (Is64BitMode) {
MemStoreDst = GetRelocatedPC(Op, Operand.Data.RIPLiteral.Value.s);
}
else {
@@ -5272,7 +5281,7 @@ void OpDispatchBuilder::INTOp(OpcodeArgs) {
// Calculate flags early.
CalculateDeferredFlags();
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
if (SetRIPToNext) {
BlockSetRIP = SetRIPToNext;
@@ -5331,7 +5340,7 @@ void OpDispatchBuilder::LZCNT(OpcodeArgs) {
}
void OpDispatchBuilder::MOVBEOp(OpcodeArgs) {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
const auto SrcSize = GetSrcSize(Op);
OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.Align = 1});
@@ -5421,7 +5430,7 @@ void OpDispatchBuilder::RDTSCPOp(OpcodeArgs) {
}
void OpDispatchBuilder::CRC32(OpcodeArgs) {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
// Destination GPR size is always 4 or 8 bytes depending on widening
uint8_t DstSize = Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REX_WIDENING ? 8 : 4;
@@ -5454,7 +5463,7 @@ void OpDispatchBuilder::UnimplementedOp(OpcodeArgs) {
// Ensure flags are calculated on invalid op.
CalculateDeferredFlags();
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
// We don't actually support this instruction
// Multiblock may hit it though
@@ -5479,7 +5488,7 @@ void OpDispatchBuilder::InvalidOp(OpcodeArgs) {
// Ensure flags are calculated on invalid op.
CalculateDeferredFlags();
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
// We don't actually support this instruction
// Multiblock may hit it though
@@ -186,7 +186,7 @@ public:
auto it = JumpTargets.find(NextRIP);
if (it == JumpTargets.end()) {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
// If we don't have a jump target to a new block then we have to leave
// Set the RIP to the next instruction and leave
auto RelocatedNextRIP = _EntrypointOffset(IR::SizeToOpSize(GPRSize), NextRIP - Entry);
@@ -246,7 +246,7 @@ public:
void SetDumpIR(bool DumpIR) { ShouldDump = DumpIR; }
bool ShouldDumpIR() const { return ShouldDump; }
void BeginFunction(uint64_t RIP, fextl::vector<FEXCore::Frontend::Decoder::DecodedBlocks> const *Blocks, uint32_t NumInstructions);
void BeginFunction(uint64_t RIP, fextl::vector<FEXCore::Frontend::Decoder::DecodedBlocks> const *Blocks, uint32_t NumInstructions, bool Is64BitMode);
void Finalize();
// Dispatch builder functions
@@ -923,6 +923,8 @@ public:
}
}
uint8_t GetGPRSize() const { return Is64BitMode ? 8 : 4; }
protected:
void SaveNZCV(IROps Op = OP_DUMMY) override {
/* Some opcodes are conservatively marked as clobbering flags, but in fact
@@ -1365,9 +1367,9 @@ private:
if (IsNZCV(BitOffset)) {
InsertNZCV(BitOffset, Value, ValueOffset, MustMask);
} else if (BitOffset == FEXCore::X86State::RFLAG_PF_RAW_LOC) {
_StoreRegister(Value, false, offsetof(FEXCore::Core::CPUState, pf_raw), GPRClass, GPRFixedClass, CTX->GetGPRSize());
_StoreRegister(Value, false, offsetof(FEXCore::Core::CPUState, pf_raw), GPRClass, GPRFixedClass, GetGPRSize());
} else if (BitOffset == FEXCore::X86State::RFLAG_AF_RAW_LOC) {
_StoreRegister(Value, false, offsetof(FEXCore::Core::CPUState, af_raw), GPRClass, GPRFixedClass, CTX->GetGPRSize());
_StoreRegister(Value, false, offsetof(FEXCore::Core::CPUState, af_raw), GPRClass, GPRFixedClass, GetGPRSize());
} else {
if (ValueOffset || MustMask)
Value = _Bfe(OpSize::i32Bit, 1, ValueOffset, Value);
@@ -1421,9 +1423,9 @@ private:
_Constant(1), _Constant(0));
}
} else if (BitOffset == FEXCore::X86State::RFLAG_PF_RAW_LOC) {
return _LoadRegister(false, offsetof(FEXCore::Core::CPUState, pf_raw), GPRClass, GPRFixedClass, CTX->GetGPRSize());
return _LoadRegister(false, offsetof(FEXCore::Core::CPUState, pf_raw), GPRClass, GPRFixedClass, GetGPRSize());
} else if (BitOffset == FEXCore::X86State::RFLAG_AF_RAW_LOC) {
return _LoadRegister(false, offsetof(FEXCore::Core::CPUState, af_raw), GPRClass, GPRFixedClass, CTX->GetGPRSize());
return _LoadRegister(false, offsetof(FEXCore::Core::CPUState, af_raw), GPRClass, GPRFixedClass, GetGPRSize());
} else {
return _LoadFlag(BitOffset);
}
@@ -2152,6 +2154,7 @@ private:
bool Multiblock{};
uint64_t Entry;
bool Is64BitMode{};
OrderedNode* _StoreMemAutoTSO(FEXCore::IR::RegisterClassType Class, uint8_t Size, OrderedNode *Addr, OrderedNode *Value, uint8_t Align = 1) {
if (CTX->IsAtomicTSOEnabled())
@@ -698,7 +698,7 @@ OrderedNode* OpDispatchBuilder::InsertCVTGPR_To_FPRImpl(OpcodeArgs,
if (Src2Op.IsGPR()) {
// If the source is a GPR then convert directly from the GPR.
auto Src2 = LoadSource_WithOpSize(GPRClass, Op, Src2Op, CTX->GetGPRSize(), Op->Flags);
auto Src2 = LoadSource_WithOpSize(GPRClass, Op, Src2Op, GetGPRSize(), Op->Flags);
return _VSToFGPRInsert(IR::SizeToOpSize(DstSize), DstElementSize, SrcSize, Src1, Src2, ZeroUpperBits);
}
else if (SrcSize != DstElementSize) {
@@ -1060,7 +1060,7 @@ void OpDispatchBuilder::MOVMSKOp(OpcodeArgs) {
GPR = _Bfi(OpSize::i64Bit, 32, 31, GPR, GPR);
// Shift right to only get the two sign bits we care about.
GPR = _Lshr(OpSize::i64Bit, GPR, _Constant(62));
StoreResult_WithOpSize(GPRClass, Op, Op->Dest, GPR, CTX->GetGPRSize(), -1);
StoreResult_WithOpSize(GPRClass, Op, Op->Dest, GPR, GetGPRSize(), -1);
}
else if (Size == 16 && ElementSize == 4) {
// Shift all the sign bits to the bottom of their respective elements.
@@ -1073,7 +1073,7 @@ void OpDispatchBuilder::MOVMSKOp(OpcodeArgs) {
Src = _VAddV(Size, 4, Src);
// Extract to a GPR.
OrderedNode *GPR = _VExtractToGPR(Size, 4, Src, 0);
StoreResult_WithOpSize(GPRClass, Op, Op->Dest, GPR, CTX->GetGPRSize(), -1);
StoreResult_WithOpSize(GPRClass, Op, Op->Dest, GPR, GetGPRSize(), -1);
}
else {
OrderedNode *CurrentVal = _Constant(0);
@@ -1759,7 +1759,7 @@ void OpDispatchBuilder::VBROADCASTOp(OpcodeArgs) {
Result = _VDupElement(DstSize, ElementSize, Src, 0);
} else {
// Get the address to broadcast from into a GPR.
OrderedNode *Address = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], CTX->GetGPRSize(), Op->Flags,
OrderedNode *Address = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], GetGPRSize(), Op->Flags,
{.LoadData = false});
Address = AppendSegmentOffset(Address, Op->Flags);
@@ -1795,7 +1795,7 @@ OrderedNode* OpDispatchBuilder::PINSROpImpl(OpcodeArgs, size_t ElementSize,
if (Src2Op.IsGPR()) {
// If the source is a GPR then convert directly from the GPR.
auto Src2 = LoadSource_WithOpSize(GPRClass, Op, Src2Op, CTX->GetGPRSize(), Op->Flags);
auto Src2 = LoadSource_WithOpSize(GPRClass, Op, Src2Op, GetGPRSize(), Op->Flags);
return _VInsGPR(Size, ElementSize, Index, Src1, Src2);
}
@@ -1924,7 +1924,7 @@ void OpDispatchBuilder::PExtrOp(OpcodeArgs) {
Index &= NumElements - 1;
if (Op->Dest.IsGPR()) {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
// Extract already zero extends the result.
OrderedNode *Result = _VExtractToGPR(16, OverridenElementSize, Src, Index);
StoreResult_WithOpSize(GPRClass, Op, Op->Dest, Result, GPRSize, -1);
@@ -2477,7 +2477,7 @@ OrderedNode* OpDispatchBuilder::CVTGPR_To_FPRImpl(OpcodeArgs, size_t DstElementS
OrderedNode *Converted{};
if (Src2Op.IsGPR()) {
// If the source is a GPR then convert directly from the GPR.
auto Src2 = LoadSource_WithOpSize(GPRClass, Op, Src2Op, CTX->GetGPRSize(), Op->Flags);
auto Src2 = LoadSource_WithOpSize(GPRClass, Op, Src2Op, GetGPRSize(), Op->Flags);
Converted = _Float_FromGPR_S(DstElementSize, SrcSize, Src2);
}
else if (SrcSize != DstElementSize) {
@@ -2826,7 +2826,7 @@ void OpDispatchBuilder::VMASKMOVOpImpl(OpcodeArgs, size_t ElementSize, size_t Da
const X86Tables::DecodedOperand& DataOp) {
const auto MakeAddress = [this, Op](const X86Tables::DecodedOperand& Data) {
OrderedNode *BaseAddr = LoadSource_WithOpSize(GPRClass, Op, Data, CTX->GetGPRSize(), Op->Flags,
OrderedNode *BaseAddr = LoadSource_WithOpSize(GPRClass, Op, Data, GetGPRSize(), Op->Flags,
{.LoadData = false});
return AppendSegmentOffset(BaseAddr, Op->Flags);
};
@@ -2877,7 +2877,7 @@ void OpDispatchBuilder::MOVBetweenGPR_FPR(OpcodeArgs) {
Op->Dest.Data.GPR.GPR >= FEXCore::X86State::REG_XMM_0) {
if (Op->Src[0].IsGPR()) {
// Loading from GPR and moving to Vector.
OrderedNode *Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], CTX->GetGPRSize(), Op->Flags);
OrderedNode *Src = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], GetGPRSize(), Op->Flags);
// zext to 128bit
auto Converted = _VCastFromGPR(16, GetSrcSize(Op), Src);
StoreResult(FPRClass, Op, Op->Dest, Converted, -1);
@@ -3011,7 +3011,7 @@ void OpDispatchBuilder::XSaveOpImpl(OpcodeArgs) {
// for features that are in the lower 32 bits, so EAX only is sufficient.
OrderedNode *Mask = LoadGPRRegister(X86State::REG_RAX);
OrderedNode *Base = XSaveBase();
const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize());
const auto OpSize = IR::SizeToOpSize(GetGPRSize());
const auto StoreIfFlagSet = [&](uint32_t BitIndex, auto fn, uint32_t FieldSize = 1){
OrderedNode *BitFlag = _Bfe(OpSize, FieldSize, BitIndex, Mask);
@@ -3065,7 +3065,7 @@ void OpDispatchBuilder::XSaveOpImpl(OpcodeArgs) {
}
void OpDispatchBuilder::SaveX87State(OpcodeArgs, OrderedNode *MemBase) {
const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize());
const auto OpSize = IR::SizeToOpSize(GetGPRSize());
// Saves 512bytes to the memory location provided
// Header changes depending on if REX.W is set or not
if (Op->Flags & X86Tables::DecodeFlags::FLAG_REX_WIDENING) {
@@ -3151,8 +3151,8 @@ void OpDispatchBuilder::SaveX87State(OpcodeArgs, OrderedNode *MemBase) {
}
void OpDispatchBuilder::SaveSSEState(OrderedNode *MemBase) {
const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize());
const auto NumRegs = CTX->Config.Is64BitMode ? 16U : 8U;
const auto OpSize = IR::SizeToOpSize(GetGPRSize());
const auto NumRegs = Is64BitMode ? 16U : 8U;
for (uint32_t i = 0; i < NumRegs; ++i) {
OrderedNode *XMMReg = LoadXMMRegister(i);
@@ -3163,7 +3163,7 @@ void OpDispatchBuilder::SaveSSEState(OrderedNode *MemBase) {
}
void OpDispatchBuilder::SaveMXCSRState(OrderedNode *MemBase) {
const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize());
const auto OpSize = IR::SizeToOpSize(GetGPRSize());
OrderedNode *MXCSR = GetMXCSR();
OrderedNode *MXCSRLocation = _Add(OpSize, MemBase, _Constant(24));
@@ -3175,8 +3175,8 @@ void OpDispatchBuilder::SaveMXCSRState(OrderedNode *MemBase) {
}
void OpDispatchBuilder::SaveAVXState(OrderedNode *MemBase) {
const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize());
const auto NumRegs = CTX->Config.Is64BitMode ? 16U : 8U;
const auto OpSize = IR::SizeToOpSize(GetGPRSize());
const auto NumRegs = Is64BitMode ? 16U : 8U;
for (uint32_t i = 0; i < NumRegs; ++i) {
OrderedNode *Upper = _VDupElement(32, 16, LoadXMMRegister(i), 1);
@@ -3194,7 +3194,7 @@ OrderedNode *OpDispatchBuilder::GetMXCSR() {
}
void OpDispatchBuilder::FXRStoreOp(OpcodeArgs) {
const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize());
const auto OpSize = IR::SizeToOpSize(GetGPRSize());
OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.LoadData = false});
Mem = AppendSegmentOffset(Mem, Op->Flags);
@@ -3208,7 +3208,7 @@ void OpDispatchBuilder::FXRStoreOp(OpcodeArgs) {
}
void OpDispatchBuilder::XRstorOpImpl(OpcodeArgs) {
const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize());
const auto OpSize = IR::SizeToOpSize(GetGPRSize());
const auto XSaveBase = [this, Op] {
OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false});
@@ -3283,7 +3283,7 @@ void OpDispatchBuilder::XRstorOpImpl(OpcodeArgs) {
}
void OpDispatchBuilder::RestoreX87State(OrderedNode *MemBase) {
const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize());
const auto OpSize = IR::SizeToOpSize(GetGPRSize());
auto NewFCW = _LoadMem(GPRClass, 2, MemBase, 2);
_StoreContext(2, GPRClass, NewFCW, offsetof(FEXCore::Core::CPUState, FCW));
@@ -3309,8 +3309,8 @@ void OpDispatchBuilder::RestoreX87State(OrderedNode *MemBase) {
}
void OpDispatchBuilder::RestoreSSEState(OrderedNode *MemBase) {
const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize());
const auto NumRegs = CTX->Config.Is64BitMode ? 16U : 8U;
const auto OpSize = IR::SizeToOpSize(GetGPRSize());
const auto NumRegs = Is64BitMode ? 16U : 8U;
for (uint32_t i = 0; i < NumRegs; ++i) {
OrderedNode *MemLocation = _Add(OpSize, MemBase, _Constant(i * 16 + 160));
@@ -3326,8 +3326,8 @@ void OpDispatchBuilder::RestoreMXCSRState(OrderedNode *MXCSR) {
}
void OpDispatchBuilder::RestoreAVXState(OrderedNode *MemBase) {
const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize());
const auto NumRegs = CTX->Config.Is64BitMode ? 16U : 8U;
const auto OpSize = IR::SizeToOpSize(GetGPRSize());
const auto NumRegs = Is64BitMode ? 16U : 8U;
for (uint32_t i = 0; i < NumRegs; ++i) {
OrderedNode *XMMReg = LoadXMMRegister(i);
@@ -3352,7 +3352,7 @@ void OpDispatchBuilder::DefaultX87State(OpcodeArgs) {
}
void OpDispatchBuilder::DefaultSSEState() {
const auto NumRegs = CTX->Config.Is64BitMode ? 16U : 8U;
const auto NumRegs = Is64BitMode ? 16U : 8U;
OrderedNode *ZeroVector = LoadAndCacheNamedVectorConstant(Core::CPUState::XMM_SSE_REG_SIZE, FEXCore::IR::NamedVectorConstant::NAMED_VECTOR_ZERO);
for (uint32_t i = 0; i < NumRegs; ++i) {
@@ -3361,7 +3361,7 @@ void OpDispatchBuilder::DefaultSSEState() {
}
void OpDispatchBuilder::DefaultAVXState() {
const auto NumRegs = CTX->Config.Is64BitMode ? 16U : 8U;
const auto NumRegs = Is64BitMode ? 16U : 8U;
for (uint32_t i = 0; i < NumRegs; i++) {
OrderedNode* Reg = LoadXMMRegister(i);
@@ -5360,7 +5360,7 @@ void OpDispatchBuilder::VPBLENDWOp(OpcodeArgs) {
void OpDispatchBuilder::VZEROOp(OpcodeArgs) {
const auto DstSize = GetDstSize(Op);
const auto IsVZEROALL = DstSize == Core::CPUState::XMM_AVX_REG_SIZE;
const auto NumRegs = CTX->Config.Is64BitMode ? 16U : 8U;
const auto NumRegs = Is64BitMode ? 16U : 8U;
if (IsVZEROALL) {
// NOTE: Despite the name being VZEROALL, this will still only ever
@@ -5564,7 +5564,7 @@ void OpDispatchBuilder::PCMPXSTRXOpImpl(OpcodeArgs, bool IsExplicit, bool IsMask
OrderedNode *Result = _Select(IR::COND_EQ, ResultNoFlags, ZeroConst,
IfZero, IfNotZero);
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
if (GPRSize == 8) {
// If being stored to an 8-byte register, zero extend the 4-byte result.
Result = _Bfe(OpSize::i64Bit, 32, 0, Result);
@@ -239,7 +239,7 @@ namespace FEXCore {
IRHeader.first->Blocks = emit->WrapNode(Block);
emit->SetCurrentCodeBlock(Block);
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = CTX->Config.Is64BitMode ? 8 : 4;
if (GPRSize == 8) {
emit->_StoreRegister(emit->_Constant(Entrypoint), false, offsetof(Core::CPUState, gregs[X86State::REG_R11]), IR::GPRClass, IR::GPRFixedClass, GPRSize);