mirror of
https://github.com/FEX-Emu/FEX.git
synced 2024-12-15 09:59:28 +00:00
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:
parent
e91e1d5533
commit
b0aeb501f4
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
|
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user