OpcodeDispatcher: Add helper for making segment offset addresses

There's quite a few places where the segment offset appending is open-coded
throughout the opcode dispatcher, but we can pull these out into a few
helpers to make the sites a little more compact and declarative.
This commit is contained in:
Lioncache 2024-04-08 16:37:24 -04:00
parent e91e1d5533
commit b0aeb501f4
5 changed files with 77 additions and 107 deletions

View File

@ -395,8 +395,8 @@ void OpDispatchBuilder::ADCOp(OpcodeArgs) {
auto ALUOp = _Adc(OpSize, _Constant(0), Src); auto ALUOp = _Adc(OpSize, _Constant(0), Src);
HandledLock = true; HandledLock = true;
OrderedNode *DestMem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false});
DestMem = AppendSegmentOffset(DestMem, Op->Flags); OrderedNode *DestMem = MakeSegmentAddress(Op, Op->Dest);
Before = _AtomicFetchAdd(IR::SizeToOpSize(Size), ALUOp, DestMem); Before = _AtomicFetchAdd(IR::SizeToOpSize(Size), ALUOp, DestMem);
} }
else { else {
@ -421,9 +421,8 @@ void OpDispatchBuilder::SBBOp(OpcodeArgs) {
OrderedNode *Before{}; OrderedNode *Before{};
if (DestIsLockedMem(Op)) { if (DestIsLockedMem(Op)) {
HandledLock = true; HandledLock = true;
OrderedNode *DestMem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false});
DestMem = AppendSegmentOffset(DestMem, Op->Flags);
OrderedNode *DestMem = MakeSegmentAddress(Op, Op->Dest);
auto SrcPlusCF = _Adc(OpSize, _Constant(0), Src); auto SrcPlusCF = _Adc(OpSize, _Constant(0), Src);
Before = _AtomicFetchSub(IR::SizeToOpSize(Size), SrcPlusCF, DestMem); Before = _AtomicFetchSub(IR::SizeToOpSize(Size), SrcPlusCF, DestMem);
} }
@ -1305,11 +1304,9 @@ void OpDispatchBuilder::XCHGOp(OpcodeArgs) {
OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags,
{.AllowUpperGarbage = true}); {.AllowUpperGarbage = true});
if (DestIsMem(Op)) { if (DestIsMem(Op)) {
HandledLock = Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_LOCK; HandledLock = (Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_LOCK) != 0;
OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false});
Dest = AppendSegmentOffset(Dest, Op->Flags);
OrderedNode *Dest = MakeSegmentAddress(Op, Op->Dest);
auto Result = _AtomicSwap(OpSizeFromSrc(Op), Src, Dest); auto Result = _AtomicSwap(OpSizeFromSrc(Op), Src, Dest);
StoreResult(GPRClass, Op, Op->Src[0], Result, -1); StoreResult(GPRClass, Op, Op->Src[0], Result, -1);
} }
@ -2615,8 +2612,7 @@ void OpDispatchBuilder::BTOp(OpcodeArgs) {
} }
} else { } else {
// Load the address to the memory location // Load the address to the memory location
OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false}); OrderedNode *Dest = MakeSegmentAddress(Op, Op->Dest);
Dest = AppendSegmentOffset(Dest, Op->Flags);
// Get the bit selection from the src // Get the bit selection from the src
OrderedNode *BitSelect = _Bfe(IR::SizeToOpSize(std::max<uint8_t>(4u, GetOpSize(Src))), 3, 0, Src); OrderedNode *BitSelect = _Bfe(IR::SizeToOpSize(std::max<uint8_t>(4u, GetOpSize(Src))), 3, 0, Src);
@ -2883,8 +2879,7 @@ void OpDispatchBuilder::NOTOp(OpcodeArgs) {
if (DestIsLockedMem(Op)) { if (DestIsLockedMem(Op)) {
HandledLock = true; HandledLock = true;
OrderedNode *DestMem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false}); OrderedNode *DestMem = MakeSegmentAddress(Op, Op->Dest);
DestMem = AppendSegmentOffset(DestMem, Op->Flags);
_AtomicXor(IR::SizeToOpSize(Size), MaskConst, DestMem); _AtomicXor(IR::SizeToOpSize(Size), MaskConst, DestMem);
} else if (!Op->Dest.IsGPR()) { } else if (!Op->Dest.IsGPR()) {
// GPR version plays fast and loose with sizes, be safe for memory tho. // GPR version plays fast and loose with sizes, be safe for memory tho.
@ -3089,10 +3084,10 @@ void OpDispatchBuilder::AADOp(OpcodeArgs) {
} }
void OpDispatchBuilder::XLATOp(OpcodeArgs) { void OpDispatchBuilder::XLATOp(OpcodeArgs) {
OrderedNode *Src = LoadGPRRegister(X86State::REG_RBX); OrderedNode *Src = MakeSegmentAddress(X86State::REG_RBX, Op->Flags,
X86Tables::DecodeFlags::FLAG_DS_PREFIX);
OrderedNode *Offset = LoadGPRRegister(X86State::REG_RAX, 1); OrderedNode *Offset = LoadGPRRegister(X86State::REG_RAX, 1);
Src = AppendSegmentOffset(Src, Op->Flags, FEXCore::X86Tables::DecodeFlags::FLAG_DS_PREFIX);
Src = _Add(OpSize::i64Bit, Src, Offset); Src = _Add(OpSize::i64Bit, Src, Offset);
auto Res = _LoadMemAutoTSO(GPRClass, 1, Src, 1); auto Res = _LoadMemAutoTSO(GPRClass, 1, Src, 1);
@ -3234,10 +3229,9 @@ void OpDispatchBuilder::INCOp(OpcodeArgs) {
if (IsLocked) { if (IsLocked) {
HandledLock = true; HandledLock = true;
auto DestAddress = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false});
DestAddress = AppendSegmentOffset(DestAddress, Op->Flags);
Dest = _AtomicFetchAdd(OpSizeFromSrc(Op), OneConst, DestAddress);
OrderedNode *DestAddress = MakeSegmentAddress(Op, Op->Dest);
Dest = _AtomicFetchAdd(OpSizeFromSrc(Op), OneConst, DestAddress);
} else { } else {
Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.AllowUpperGarbage = Size >= 32}); Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.AllowUpperGarbage = Size >= 32});
} }
@ -3282,8 +3276,8 @@ void OpDispatchBuilder::DECOp(OpcodeArgs) {
if (IsLocked) { if (IsLocked) {
HandledLock = true; HandledLock = true;
auto DestAddress = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false});
DestAddress = AppendSegmentOffset(DestAddress, Op->Flags); OrderedNode *DestAddress = MakeSegmentAddress(Op, Op->Dest);
// Use Add instead of Sub to avoid a NEG // Use Add instead of Sub to avoid a NEG
Dest = _AtomicFetchAdd(OpSizeFromSrc(Op), _Constant(Size, -1), DestAddress); Dest = _AtomicFetchAdd(OpSizeFromSrc(Op), _Constant(Size, -1), DestAddress);
@ -3328,10 +3322,9 @@ void OpDispatchBuilder::STOSOp(OpcodeArgs) {
if (!Repeat) { if (!Repeat) {
// Src is used only for a store of the same size so allow garbage // Src is used only for a store of the same size so allow garbage
OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.AllowUpperGarbage = true}); OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.AllowUpperGarbage = true});
OrderedNode *Dest = LoadGPRRegister(X86State::REG_RDI);
// Only ES prefix // Only ES prefix
Dest = AppendSegmentOffset(Dest, 0, FEXCore::X86Tables::DecodeFlags::FLAG_ES_PREFIX, true); OrderedNode *Dest = MakeSegmentAddress(X86State::REG_RDI, 0, X86Tables::DecodeFlags::FLAG_ES_PREFIX, true);
// Store to memory where RDI points // Store to memory where RDI points
_StoreMemAutoTSO(GPRClass, Size, Dest, Src, Size); _StoreMemAutoTSO(GPRClass, Size, Dest, Src, Size);
@ -3390,10 +3383,8 @@ void OpDispatchBuilder::MOVSOp(OpcodeArgs) {
StoreGPRRegister(X86State::REG_RSI, Result_Src); StoreGPRRegister(X86State::REG_RSI, Result_Src);
} }
else { else {
OrderedNode *RSI = LoadGPRRegister(X86State::REG_RSI); OrderedNode *RSI = MakeSegmentAddress(X86State::REG_RSI, Op->Flags, X86Tables::DecodeFlags::FLAG_DS_PREFIX);
OrderedNode *RDI = LoadGPRRegister(X86State::REG_RDI); OrderedNode *RDI = MakeSegmentAddress(X86State::REG_RDI, 0, X86Tables::DecodeFlags::FLAG_ES_PREFIX, true);
RDI= AppendSegmentOffset(RDI, 0, FEXCore::X86Tables::DecodeFlags::FLAG_ES_PREFIX, true);
RSI = AppendSegmentOffset(RSI, Op->Flags, FEXCore::X86Tables::DecodeFlags::FLAG_DS_PREFIX);
auto Src = _LoadMemAutoTSO(GPRClass, Size, RSI, Size); auto Src = _LoadMemAutoTSO(GPRClass, Size, RSI, Size);
@ -3420,13 +3411,12 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) {
bool Repeat = Op->Flags & (FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX | FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX); bool Repeat = Op->Flags & (FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX | FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX);
if (!Repeat) { if (!Repeat) {
OrderedNode *Dest_RSI = LoadGPRRegister(X86State::REG_RSI);
OrderedNode *Dest_RDI = LoadGPRRegister(X86State::REG_RDI);
// Only ES prefix
Dest_RDI = AppendSegmentOffset(Dest_RDI, 0, FEXCore::X86Tables::DecodeFlags::FLAG_ES_PREFIX, true);
// Default DS prefix // Default DS prefix
Dest_RSI = AppendSegmentOffset(Dest_RSI, Op->Flags, FEXCore::X86Tables::DecodeFlags::FLAG_DS_PREFIX); OrderedNode *Dest_RSI = MakeSegmentAddress(X86State::REG_RSI, Op->Flags,
X86Tables::DecodeFlags::FLAG_DS_PREFIX);
// Only ES prefix
OrderedNode *Dest_RDI = MakeSegmentAddress(X86State::REG_RDI, 0,
X86Tables::DecodeFlags::FLAG_ES_PREFIX, true);
auto Src1 = _LoadMemAutoTSO(GPRClass, Size, Dest_RDI, Size); auto Src1 = _LoadMemAutoTSO(GPRClass, Size, Dest_RDI, Size);
auto Src2 = _LoadMemAutoTSO(GPRClass, Size, Dest_RSI, Size); auto Src2 = _LoadMemAutoTSO(GPRClass, Size, Dest_RSI, Size);
@ -3470,13 +3460,12 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) {
// Working loop // Working loop
{ {
OrderedNode *Dest_RSI = LoadGPRRegister(X86State::REG_RSI);
OrderedNode *Dest_RDI = LoadGPRRegister(X86State::REG_RDI);
// Only ES prefix
Dest_RDI = AppendSegmentOffset(Dest_RDI, 0, FEXCore::X86Tables::DecodeFlags::FLAG_ES_PREFIX, true);
// Default DS prefix // Default DS prefix
Dest_RSI = AppendSegmentOffset(Dest_RSI, Op->Flags, FEXCore::X86Tables::DecodeFlags::FLAG_DS_PREFIX); OrderedNode *Dest_RSI = MakeSegmentAddress(X86State::REG_RSI, Op->Flags,
X86Tables::DecodeFlags::FLAG_DS_PREFIX);
// Only ES prefix
OrderedNode *Dest_RDI = MakeSegmentAddress(X86State::REG_RDI, 0,
X86Tables::DecodeFlags::FLAG_ES_PREFIX, true);
auto Src1 = _LoadMemAutoTSO(GPRClass, Size, Dest_RDI, Size); auto Src1 = _LoadMemAutoTSO(GPRClass, Size, Dest_RDI, Size);
auto Src2 = _LoadMem(GPRClass, Size, Dest_RSI, Size); auto Src2 = _LoadMem(GPRClass, Size, Dest_RSI, Size);
@ -3548,8 +3537,8 @@ void OpDispatchBuilder::LODSOp(OpcodeArgs) {
const bool Repeat = (Op->Flags & (FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX | FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX)) != 0; const bool Repeat = (Op->Flags & (FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX | FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX)) != 0;
if (!Repeat) { if (!Repeat) {
OrderedNode *Dest_RSI = LoadGPRRegister(X86State::REG_RSI); OrderedNode *Dest_RSI = MakeSegmentAddress(X86State::REG_RSI, Op->Flags,
Dest_RSI = AppendSegmentOffset(Dest_RSI, Op->Flags, FEXCore::X86Tables::DecodeFlags::FLAG_DS_PREFIX); X86Tables::DecodeFlags::FLAG_DS_PREFIX);
auto Src = _LoadMemAutoTSO(GPRClass, Size, Dest_RSI, Size); auto Src = _LoadMemAutoTSO(GPRClass, Size, Dest_RSI, Size);
@ -3591,9 +3580,8 @@ void OpDispatchBuilder::LODSOp(OpcodeArgs) {
// Working loop // Working loop
{ {
OrderedNode *Dest_RSI = LoadGPRRegister(X86State::REG_RSI); OrderedNode *Dest_RSI = MakeSegmentAddress(X86State::REG_RSI, Op->Flags,
X86Tables::DecodeFlags::FLAG_DS_PREFIX);
Dest_RSI = AppendSegmentOffset(Dest_RSI, Op->Flags, FEXCore::X86Tables::DecodeFlags::FLAG_DS_PREFIX);
auto Src = _LoadMemAutoTSO(GPRClass, Size, Dest_RSI, Size); auto Src = _LoadMemAutoTSO(GPRClass, Size, Dest_RSI, Size);
@ -3635,8 +3623,8 @@ void OpDispatchBuilder::SCASOp(OpcodeArgs) {
const bool Repeat = (Op->Flags & (FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX | FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX)) != 0; const bool Repeat = (Op->Flags & (FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX | FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX)) != 0;
if (!Repeat) { if (!Repeat) {
OrderedNode *Dest_RDI = LoadGPRRegister(X86State::REG_RDI); OrderedNode *Dest_RDI = MakeSegmentAddress(X86State::REG_RDI, 0,
Dest_RDI = AppendSegmentOffset(Dest_RDI, 0, FEXCore::X86Tables::DecodeFlags::FLAG_ES_PREFIX, true); X86Tables::DecodeFlags::FLAG_ES_PREFIX, true);
auto Src1 = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.AllowUpperGarbage = true}); auto Src1 = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.AllowUpperGarbage = true});
auto Src2 = _LoadMemAutoTSO(GPRClass, Size, Dest_RDI, Size); auto Src2 = _LoadMemAutoTSO(GPRClass, Size, Dest_RDI, Size);
@ -3675,9 +3663,8 @@ void OpDispatchBuilder::SCASOp(OpcodeArgs) {
// Working loop // Working loop
{ {
OrderedNode *Dest_RDI = LoadGPRRegister(X86State::REG_RDI); OrderedNode *Dest_RDI = MakeSegmentAddress(X86State::REG_RDI, 0,
X86Tables::DecodeFlags::FLAG_ES_PREFIX, true);
Dest_RDI = AppendSegmentOffset(Dest_RDI, 0, FEXCore::X86Tables::DecodeFlags::FLAG_ES_PREFIX, true);
auto Src1 = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.AllowUpperGarbage = true}); auto Src1 = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.AllowUpperGarbage = true});
auto Src2 = _LoadMemAutoTSO(GPRClass, Size, Dest_RDI, Size); auto Src2 = _LoadMemAutoTSO(GPRClass, Size, Dest_RDI, Size);
@ -3776,9 +3763,7 @@ void OpDispatchBuilder::NEGOp(OpcodeArgs) {
auto ZeroConst = _Constant(0); auto ZeroConst = _Constant(0);
if (DestIsLockedMem(Op)) { if (DestIsLockedMem(Op)) {
OrderedNode *DestMem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false}); OrderedNode *DestMem = MakeSegmentAddress(Op, Op->Dest);
DestMem = AppendSegmentOffset(DestMem, Op->Flags);
OrderedNode *Dest = _AtomicFetchNeg(IR::SizeToOpSize(Size), DestMem); OrderedNode *Dest = _AtomicFetchNeg(IR::SizeToOpSize(Size), DestMem);
CalculateFlags_SUB(Size, ZeroConst, Dest); CalculateFlags_SUB(Size, ZeroConst, Dest);
} }
@ -4041,9 +4026,7 @@ void OpDispatchBuilder::CMPXCHGOp(OpcodeArgs) {
Src3Lower = Src3; Src3Lower = Src3;
} }
// If this is a memory location then we want the pointer to it // If this is a memory location then we want the pointer to it
OrderedNode *Src1 = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false}); OrderedNode *Src1 = MakeSegmentAddress(Op, Op->Dest);
Src1 = AppendSegmentOffset(Src1, Op->Flags);
// DataSrc = *Src1 // DataSrc = *Src1
// if (DataSrc == Src3) { *Src1 == Src2; } Src2 = DataSrc // if (DataSrc == Src3) { *Src1 == Src2; } Src2 = DataSrc
@ -4076,10 +4059,9 @@ void OpDispatchBuilder::CMPXCHGPairOp(OpcodeArgs) {
uint8_t Size = Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REX_WIDENING ? 8 : 4; uint8_t Size = Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REX_WIDENING ? 8 : 4;
HandledLock = (Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_LOCK) != 0; HandledLock = (Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_LOCK) != 0;
// If this is a memory location then we want the pointer to it
OrderedNode *Src1 = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false});
Src1 = AppendSegmentOffset(Src1, Op->Flags); // If this is a memory location then we want the pointer to it
OrderedNode *Src1 = MakeSegmentAddress(Op, Op->Dest);
OrderedNode *Expected_Lower = LoadGPRRegister(X86State::REG_RAX, Size); OrderedNode *Expected_Lower = LoadGPRRegister(X86State::REG_RAX, Size);
OrderedNode *Expected_Upper = LoadGPRRegister(X86State::REG_RDX, Size); OrderedNode *Expected_Upper = LoadGPRRegister(X86State::REG_RDX, Size);
@ -4862,9 +4844,7 @@ void OpDispatchBuilder::ALUOpImpl(OpcodeArgs, FEXCore::IR::IROps ALUIROp, FEXCor
if (DestIsLockedMem(Op)) { if (DestIsLockedMem(Op)) {
HandledLock = true; HandledLock = true;
OrderedNode *DestMem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false}); OrderedNode *DestMem = MakeSegmentAddress(Op, Op->Dest);
DestMem = AppendSegmentOffset(DestMem, Op->Flags);
DeriveOp(FetchOp, AtomicFetchOp, _AtomicFetchAdd(IR::SizeToOpSize(Size), Src, DestMem)); DeriveOp(FetchOp, AtomicFetchOp, _AtomicFetchAdd(IR::SizeToOpSize(Size), Src, DestMem));
Dest = FetchOp; Dest = FetchOp;
} }
@ -5055,14 +5035,12 @@ void OpDispatchBuilder::MOVBEOp(OpcodeArgs) {
} }
void OpDispatchBuilder::CLWB(OpcodeArgs) { void OpDispatchBuilder::CLWB(OpcodeArgs) {
OrderedNode *DestMem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false}); OrderedNode *DestMem = MakeSegmentAddress(Op, Op->Dest);
DestMem = AppendSegmentOffset(DestMem, Op->Flags);
_CacheLineClean(DestMem); _CacheLineClean(DestMem);
} }
void OpDispatchBuilder::CLFLUSHOPT(OpcodeArgs) { void OpDispatchBuilder::CLFLUSHOPT(OpcodeArgs) {
OrderedNode *DestMem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false}); OrderedNode *DestMem = MakeSegmentAddress(Op, Op->Dest);
DestMem = AppendSegmentOffset(DestMem, Op->Flags);
_CacheLineClear(DestMem, false); _CacheLineClear(DestMem, false);
} }
@ -5093,8 +5071,7 @@ void OpDispatchBuilder::StoreFenceOrCLFlush(OpcodeArgs) {
} }
else { else {
// This is a CLFlush // This is a CLFlush
OrderedNode *DestMem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false}); OrderedNode *DestMem = MakeSegmentAddress(Op, Op->Dest);
DestMem = AppendSegmentOffset(DestMem, Op->Flags);
_CacheLineClear(DestMem, true); _CacheLineClear(DestMem, true);
} }
} }

View File

@ -1236,6 +1236,20 @@ private:
void StoreResult(FEXCore::IR::RegisterClassType Class, FEXCore::X86Tables::DecodedOp Op, FEXCore::X86Tables::DecodedOperand const& Operand, OrderedNode *const Src, int8_t Align, MemoryAccessType AccessType = MemoryAccessType::DEFAULT); void StoreResult(FEXCore::IR::RegisterClassType Class, FEXCore::X86Tables::DecodedOp Op, FEXCore::X86Tables::DecodedOperand const& Operand, OrderedNode *const Src, int8_t Align, MemoryAccessType AccessType = MemoryAccessType::DEFAULT);
void StoreResult(FEXCore::IR::RegisterClassType Class, FEXCore::X86Tables::DecodedOp Op, OrderedNode *const Src, int8_t Align, MemoryAccessType AccessType = MemoryAccessType::DEFAULT); void StoreResult(FEXCore::IR::RegisterClassType Class, FEXCore::X86Tables::DecodedOp Op, OrderedNode *const Src, int8_t Align, MemoryAccessType AccessType = MemoryAccessType::DEFAULT);
// In several instances, it's desirable to get a base address with the segment offset
// applied to it. This pulls all the common-case appending into a single set of functions.
[[nodiscard]] OrderedNode *MakeSegmentAddress(const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, uint8_t OpSize) {
OrderedNode *Mem = LoadSource_WithOpSize(GPRClass, Op, Operand, OpSize, Op->Flags, {.LoadData = false});
return AppendSegmentOffset(Mem, Op->Flags);
}
[[nodiscard]] OrderedNode *MakeSegmentAddress(const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand) {
return MakeSegmentAddress(Op, Operand, GetSrcSize(Op));
}
[[nodiscard]] OrderedNode *MakeSegmentAddress(X86State::X86Reg Reg, uint32_t Flags, uint32_t DefaultPrefix = 0, bool Override = false) {
OrderedNode *Address = LoadGPRRegister(Reg);
return AppendSegmentOffset(Address, Flags, DefaultPrefix, Override);
}
constexpr OpSize GetGuestVectorLength() const { constexpr OpSize GetGuestVectorLength() const {
return CTX->HostFeatures.SupportsAVX ? OpSize::i256Bit : OpSize::i128Bit; return CTX->HostFeatures.SupportsAVX ? OpSize::i256Bit : OpSize::i128Bit;
} }

View File

@ -1758,10 +1758,7 @@ void OpDispatchBuilder::VBROADCASTOp(OpcodeArgs) {
Result = _VDupElement(DstSize, ElementSize, Src, 0); Result = _VDupElement(DstSize, ElementSize, Src, 0);
} else { } else {
// Get the address to broadcast from into a GPR. // Get the address to broadcast from into a GPR.
OrderedNode *Address = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], CTX->GetGPRSize(), Op->Flags, OrderedNode *Address = MakeSegmentAddress(Op, Op->Src[0], CTX->GetGPRSize());
{.LoadData = false});
Address = AppendSegmentOffset(Address, Op->Flags);
Result = _VBroadcastFromMem(DstSize, ElementSize, Address); Result = _VBroadcastFromMem(DstSize, ElementSize, Address);
} }
@ -2807,11 +2804,8 @@ void OpDispatchBuilder::MASKMOVOp(OpcodeArgs) {
// Vector that will overwrite byte elements. // Vector that will overwrite byte elements.
OrderedNode *VectorSrc = LoadSource(GPRClass, Op, Op->Dest, Op->Flags); OrderedNode *VectorSrc = LoadSource(GPRClass, Op, Op->Dest, Op->Flags);
// RDI source // RDI source (DS prefix by default)
auto MemDest = LoadGPRRegister(X86State::REG_RDI); auto MemDest = MakeSegmentAddress(X86State::REG_RDI, Op->Flags, X86Tables::DecodeFlags::FLAG_DS_PREFIX);
// DS prefix by default.
MemDest = AppendSegmentOffset(MemDest, Op->Flags, FEXCore::X86Tables::DecodeFlags::FLAG_DS_PREFIX);
OrderedNode *XMMReg = _LoadMem(FPRClass, Size, MemDest, 1); OrderedNode *XMMReg = _LoadMem(FPRClass, Size, MemDest, 1);
@ -2825,9 +2819,7 @@ void OpDispatchBuilder::VMASKMOVOpImpl(OpcodeArgs, size_t ElementSize, size_t Da
const X86Tables::DecodedOperand& DataOp) { const X86Tables::DecodedOperand& DataOp) {
const auto MakeAddress = [this, Op](const X86Tables::DecodedOperand& Data) { const auto MakeAddress = [this, Op](const X86Tables::DecodedOperand& Data) {
OrderedNode *BaseAddr = LoadSource_WithOpSize(GPRClass, Op, Data, CTX->GetGPRSize(), Op->Flags, return MakeSegmentAddress(Op, Data, CTX->GetGPRSize());
{.LoadData = false});
return AppendSegmentOffset(BaseAddr, Op->Flags);
}; };
OrderedNode *Mask = LoadSource_WithOpSize(FPRClass, Op, MaskOp, DataSize, Op->Flags); OrderedNode *Mask = LoadSource_WithOpSize(FPRClass, Op, MaskOp, DataSize, Op->Flags);
@ -2988,8 +2980,7 @@ template
void OpDispatchBuilder::AVXVFCMPOp<8>(OpcodeArgs); void OpDispatchBuilder::AVXVFCMPOp<8>(OpcodeArgs);
void OpDispatchBuilder::FXSaveOp(OpcodeArgs) { void OpDispatchBuilder::FXSaveOp(OpcodeArgs) {
OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false}); OrderedNode *Mem = MakeSegmentAddress(Op, Op->Dest);
Mem = AppendSegmentOffset(Mem, Op->Flags);
SaveX87State(Op, Mem); SaveX87State(Op, Mem);
SaveSSEState(Mem); SaveSSEState(Mem);
@ -3001,8 +2992,7 @@ void OpDispatchBuilder::XSaveOp(OpcodeArgs) {
} }
OrderedNode *OpDispatchBuilder::XSaveBase(X86Tables::DecodedOp Op) { OrderedNode *OpDispatchBuilder::XSaveBase(X86Tables::DecodedOp Op) {
OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false}); return MakeSegmentAddress(Op, Op->Dest);
return AppendSegmentOffset(Mem, Op->Flags);
} }
void OpDispatchBuilder::XSaveOpImpl(OpcodeArgs) { void OpDispatchBuilder::XSaveOpImpl(OpcodeArgs) {
@ -3195,9 +3185,7 @@ OrderedNode *OpDispatchBuilder::GetMXCSR() {
void OpDispatchBuilder::FXRStoreOp(OpcodeArgs) { void OpDispatchBuilder::FXRStoreOp(OpcodeArgs) {
const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize()); const auto OpSize = IR::SizeToOpSize(CTX->GetGPRSize());
OrderedNode *Mem = MakeSegmentAddress(Op, Op->Src[0]);
OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.LoadData = false});
Mem = AppendSegmentOffset(Mem, Op->Flags);
RestoreX87State(Mem); RestoreX87State(Mem);
RestoreSSEState(Mem); RestoreSSEState(Mem);

View File

@ -1011,9 +1011,8 @@ void OpDispatchBuilder::X87ATAN(OpcodeArgs) {
} }
void OpDispatchBuilder::X87LDENV(OpcodeArgs) { void OpDispatchBuilder::X87LDENV(OpcodeArgs) {
auto Size = GetSrcSize(Op); const auto Size = GetSrcSize(Op);
OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.LoadData = false}); OrderedNode *Mem = MakeSegmentAddress(Op, Op->Src[0]);
Mem = AppendSegmentOffset(Mem, Op->Flags);
auto NewFCW = _LoadMem(GPRClass, 2, Mem, 2); auto NewFCW = _LoadMem(GPRClass, 2, Mem, 2);
_StoreContext(2, GPRClass, NewFCW, offsetof(FEXCore::Core::CPUState, FCW)); _StoreContext(2, GPRClass, NewFCW, offsetof(FEXCore::Core::CPUState, FCW));
@ -1049,9 +1048,8 @@ void OpDispatchBuilder::X87FNSTENV(OpcodeArgs) {
// 4 bytes : data pointer offset // 4 bytes : data pointer offset
// 4 bytes : data pointer selector // 4 bytes : data pointer selector
auto Size = GetDstSize(Op); const auto Size = GetDstSize(Op);
OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false}); OrderedNode *Mem = MakeSegmentAddress(Op, Op->Dest);
Mem = AppendSegmentOffset(Mem, Op->Flags);
{ {
auto FCW = _LoadContext(2, GPRClass, offsetof(FEXCore::Core::CPUState, FCW)); auto FCW = _LoadContext(2, GPRClass, offsetof(FEXCore::Core::CPUState, FCW));
@ -1136,10 +1134,8 @@ void OpDispatchBuilder::X87FNSAVE(OpcodeArgs) {
// 4 bytes : data pointer offset // 4 bytes : data pointer offset
// 4 bytes : data pointer selector // 4 bytes : data pointer selector
auto Size = GetDstSize(Op); const auto Size = GetDstSize(Op);
OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false}); OrderedNode *Mem = MakeSegmentAddress(Op, Op->Dest);
Mem = AppendSegmentOffset(Mem, Op->Flags);
OrderedNode *Top = GetX87Top(); OrderedNode *Top = GetX87Top();
{ {
auto FCW = _LoadContext(2, GPRClass, offsetof(FEXCore::Core::CPUState, FCW)); auto FCW = _LoadContext(2, GPRClass, offsetof(FEXCore::Core::CPUState, FCW));
@ -1210,9 +1206,8 @@ void OpDispatchBuilder::X87FNSAVE(OpcodeArgs) {
} }
void OpDispatchBuilder::X87FRSTOR(OpcodeArgs) { void OpDispatchBuilder::X87FRSTOR(OpcodeArgs) {
auto Size = GetSrcSize(Op); const auto Size = GetSrcSize(Op);
OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.LoadData = false}); OrderedNode *Mem = MakeSegmentAddress(Op, Op->Src[0]);
Mem = AppendSegmentOffset(Mem, Op->Flags);
auto NewFCW = _LoadMem(GPRClass, 2, Mem, 2); auto NewFCW = _LoadMem(GPRClass, 2, Mem, 2);
_StoreContext(2, GPRClass, NewFCW, offsetof(FEXCore::Core::CPUState, FCW)); _StoreContext(2, GPRClass, NewFCW, offsetof(FEXCore::Core::CPUState, FCW));

View File

@ -64,9 +64,8 @@ void OpDispatchBuilder::FNINITF64(OpcodeArgs) {
} }
void OpDispatchBuilder::X87LDENVF64(OpcodeArgs) { void OpDispatchBuilder::X87LDENVF64(OpcodeArgs) {
auto Size = GetSrcSize(Op); const auto Size = GetSrcSize(Op);
OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.LoadData = false}); OrderedNode *Mem = MakeSegmentAddress(Op, Op->Src[0]);
Mem = AppendSegmentOffset(Mem, Op->Flags);
auto NewFCW = _LoadMem(GPRClass, 2, Mem, 2); auto NewFCW = _LoadMem(GPRClass, 2, Mem, 2);
//ignore the rounding precision, we're always 64-bit in F64. //ignore the rounding precision, we're always 64-bit in F64.
@ -893,10 +892,8 @@ void OpDispatchBuilder::X87FNSAVEF64(OpcodeArgs) {
// 4 bytes : data pointer offset // 4 bytes : data pointer offset
// 4 bytes : data pointer selector // 4 bytes : data pointer selector
auto Size = GetDstSize(Op); const auto Size = GetDstSize(Op);
OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.LoadData = false}); OrderedNode *Mem = MakeSegmentAddress(Op, Op->Dest);
Mem = AppendSegmentOffset(Mem, Op->Flags);
OrderedNode *Top = GetX87Top(); OrderedNode *Top = GetX87Top();
{ {
auto FCW = _LoadContext(2, GPRClass, offsetof(FEXCore::Core::CPUState, FCW)); auto FCW = _LoadContext(2, GPRClass, offsetof(FEXCore::Core::CPUState, FCW));
@ -971,9 +968,8 @@ void OpDispatchBuilder::X87FNSAVEF64(OpcodeArgs) {
//This function converts from F80 on load for compatibility //This function converts from F80 on load for compatibility
void OpDispatchBuilder::X87FRSTORF64(OpcodeArgs) { void OpDispatchBuilder::X87FRSTORF64(OpcodeArgs) {
auto Size = GetSrcSize(Op); const auto Size = GetSrcSize(Op);
OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, {.LoadData = false}); OrderedNode *Mem = MakeSegmentAddress(Op, Op->Src[0]);
Mem = AppendSegmentOffset(Mem, Op->Flags);
auto NewFCW = _LoadMem(GPRClass, 2, Mem, 2); auto NewFCW = _LoadMem(GPRClass, 2, Mem, 2);
//ignore the rounding precision, we're always 64-bit in F64. //ignore the rounding precision, we're always 64-bit in F64.