mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-14 06:00:41 +02:00
Merge pull request #3303 from Sonicadvance1/initial_runtime_longmode_switch
OpcodeDispatcher: Initial support for runtime long-mode switch
This commit is contained in:
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
|
||||
|
||||
Reference in new issue
Block a user