Merge pull request #3303 from Sonicadvance1/initial_runtime_longmode_switch

OpcodeDispatcher: Initial support for runtime long-mode switch
This commit is contained in:
Ryan Houdek authored and GitHub committed 2024-01-04 18:17:54 -08:00
commit 4b3792196f
34 files changed
+2897 -2786

No files matched your search

@@ -107,7 +107,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));
@@ -155,10 +155,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),
@@ -191,14 +191,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);
@@ -215,7 +215,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) {
@@ -270,7 +270,7 @@ void OpDispatchBuilder::IRETOp(OpcodeArgs) {
// Calculate flags early.
CalculateDeferredFlags();
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
auto Constant = _Constant(GPRSize);
@@ -290,7 +290,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));
@@ -314,7 +314,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));
@@ -508,7 +508,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
@@ -522,7 +522,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);
@@ -547,7 +547,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);
@@ -585,7 +585,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));
@@ -632,7 +632,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
@@ -765,7 +765,7 @@ void OpDispatchBuilder::LEAVEOp(OpcodeArgs) {
}
void OpDispatchBuilder::CALLOp(OpcodeArgs) {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
BlockSetRIP = true;
@@ -936,7 +936,7 @@ void OpDispatchBuilder::SETccOp(OpcodeArgs) {
}
void OpDispatchBuilder::CMOVOp(OpcodeArgs) {
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
// Calculate flags early.
CalculateDeferredFlags();
@@ -968,7 +968,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
@@ -1043,7 +1043,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;
@@ -1196,7 +1196,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
@@ -1482,7 +1482,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 {
@@ -1492,7 +1492,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 {
@@ -1528,7 +1528,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 {
@@ -1537,7 +1537,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 {
@@ -1584,7 +1584,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);
@@ -2175,7 +2175,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;
@@ -2237,7 +2237,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() &&
@@ -2270,7 +2270,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);
@@ -2757,7 +2757,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
@@ -2993,7 +2993,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;
@@ -3043,7 +3043,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;
@@ -3090,7 +3090,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
@@ -3454,7 +3454,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;
@@ -3463,7 +3463,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);
@@ -3504,7 +3504,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;
@@ -3608,7 +3608,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);
@@ -3670,7 +3670,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);
@@ -3717,7 +3717,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);
@@ -3736,7 +3736,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
@@ -3830,7 +3830,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);
@@ -3851,7 +3851,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
@@ -3928,7 +3928,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);
@@ -3945,7 +3945,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
@@ -4020,7 +4020,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);
@@ -4036,7 +4036,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
@@ -4093,7 +4093,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) {
@@ -4126,7 +4126,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;
@@ -4146,7 +4146,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) {
@@ -4181,7 +4181,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;
@@ -4198,7 +4198,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);
@@ -4219,7 +4219,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);
@@ -4255,7 +4255,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
@@ -4449,8 +4449,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);
@@ -4465,7 +4468,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));
@@ -4506,7 +4509,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) {
@@ -4653,8 +4656,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));
@@ -4692,7 +4701,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()) {
@@ -4750,7 +4759,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 {
@@ -4852,12 +4861,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;
}
@@ -4885,7 +4894,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;
}
@@ -4928,7 +4937,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()) {
@@ -5006,7 +5015,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 {
@@ -5273,7 +5282,7 @@ void OpDispatchBuilder::INTOp(OpcodeArgs) {
// Calculate flags early.
CalculateDeferredFlags();
const uint8_t GPRSize = CTX->GetGPRSize();
const uint8_t GPRSize = GetGPRSize();
if (SetRIPToNext) {
BlockSetRIP = SetRIPToNext;
@@ -5332,7 +5341,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});
@@ -5422,7 +5431,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;
@@ -5455,7 +5464,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
@@ -5480,7 +5489,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