Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement explicit state switch between X87 and MMX #4105

Merged
merged 4 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion FEXCore/Scripts/json_ir_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -699,8 +699,12 @@ def print_ir_allocator_helpers():

# We gather the "has x87?" flag as we go. This saves the user from
# having to keep track of whether they emitted any x87.
# Also changes the mmx state to X87.
if op.LoweredX87:
output_file.write("\t\tRecordX87Use();\n")
output_file.write(
"\t\tif(MMXState == MMXState_MMX) ChgStateMMX_X87();\n"
)

output_file.write("\t\tauto _Op = AllocateOp<IROp_{}, IROps::OP_{}>();\n".format(op.Name, op.Name.upper()))

Expand Down Expand Up @@ -826,4 +830,3 @@ def print_ir_dispatcher_dispatch():
print_ir_dispatcher_dispatch()

output_dispatch_file.close()

10 changes: 7 additions & 3 deletions FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4407,9 +4407,13 @@ void OpDispatchBuilder::StoreResult_WithOpSize(FEXCore::IR::RegisterClassType Cl
LOGMAN_THROW_A_FMT(OpSize == 8, "full");
LOGMAN_THROW_A_FMT(Class == FPRClass, "MMX is floaty");

// Partial store into bottom 64-bits, leave the upper bits unaffected.
// XXX: We actually should set the upper bits to all-1s?
StoreContextPartial(MM0Index + gpr - FEXCore::X86State::REG_MM_0, Src);
if (MMXState != MMXState_MMX) {
ChgStateX87_MMX();
}

uint8_t Index = MM0Index + gpr - FEXCore::X86State::REG_MM_0;
StoreContext(Index, Src);
RegCache.Partial |= (1ull << (uint64_t)Index);
} else if (gpr >= FEXCore::X86State::REG_XMM_0) {
const auto gprIndex = gpr - X86State::REG_XMM_0;
const auto VectorSize = GetGuestVectorLength();
Expand Down
25 changes: 18 additions & 7 deletions FEXCore/Source/Interface/Core/OpcodeDispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,10 @@ class OpDispatchBuilder final : public IREmitter {
Bits &= ~NextBit;
} else {
_StoreContext(Size, Class, Value, Offset);
// If Partial and MMX register, then we need to store all 1s in bits 64-80
if (Partial && Index >= MM0Index && Index <= MM7Index) {
_StoreContext(2, IR::GPRClass, _Constant(0xFFFF), Offset + 8);
}
}
}

Expand Down Expand Up @@ -1964,12 +1968,6 @@ class OpDispatchBuilder final : public IREmitter {
RegCache.Written |= Bit;
}

void StoreContextPartial(uint8_t Index, Ref Value) {
StoreContext(Index, Value);

RegCache.Partial |= (1ull << (uint64_t)Index);
}

void StoreRegister(uint8_t Reg, bool FPR, Ref Value) {
StoreContext(Reg + (FPR ? FPR0Index : GPR0Index), Value);
}
Expand Down Expand Up @@ -2333,7 +2331,6 @@ class OpDispatchBuilder final : public IREmitter {
}
}

/** @} */
/** @} */

Ref GetX87Top();
Expand All @@ -2342,6 +2339,20 @@ class OpDispatchBuilder final : public IREmitter {
Ref GetX87FTW_Helper();
void SetX87Top(Ref Value);

void ChgStateX87_MMX() override {
LOGMAN_THROW_A_FMT(MMXState == MMXState_X87, "Expected state to be x87");
_StackForceSlow();
SetX87Top(_Constant(0)); // top reset to zero
StoreContext(AbridgedFTWIndex, _Constant(0xFFFFUL)); // all valid
MMXState = MMXState_MMX;
}

void ChgStateMMX_X87() override {
LOGMAN_THROW_A_FMT(MMXState == MMXState_MMX, "Expected state to be MMX");
FlushRegisterCache();
MMXState = MMXState_X87;
}

bool DestIsLockedMem(FEXCore::X86Tables::DecodedOp Op) const {
return DestIsMem(Op) && (Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_LOCK) != 0;
}
Expand Down
9 changes: 9 additions & 0 deletions FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,10 @@ void OpDispatchBuilder::MOVQOp(OpcodeArgs, VectorOpType VectorType) {
}

void OpDispatchBuilder::MOVQMMXOp(OpcodeArgs) {
// Partial store into bottom 64-bits, leave the upper bits unaffected.
if (MMXState == MMXState_X87) {
ChgStateX87_MMX();
}
Ref Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, {.Align = 1});
StoreResult(FPRClass, Op, Src, 1);
}
Expand Down Expand Up @@ -2298,6 +2302,11 @@ void OpDispatchBuilder::MMX_To_XMM_Vector_CVT_Int_To_Float(OpcodeArgs) {

template<size_t SrcElementSize, bool Narrow, bool HostRoundingMode>
void OpDispatchBuilder::XMM_To_MMX_Vector_CVT_Float_To_Int(OpcodeArgs) {
// This function causes a change in MMX state from X87 to MMX
if (MMXState == MMXState_X87) {
ChgStateX87_MMX();
}

// If loading a vector, use the full size, so we don't
// unnecessarily zero extend the vector. Otherwise, if
// memory, then we want to load the element size exactly.
Expand Down
5 changes: 5 additions & 0 deletions FEXCore/Source/Interface/IR/IREmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,13 @@ class IREmitter {
return Ptr;
}

// MMX State can be either MMX (for 64bit) or x87 FPU (for 80bit)
enum { MMXState_MMX, MMXState_X87 } MMXState = MMXState_MMX;

// Overriden by dispatcher, stubbed for IR tests
virtual void RecordX87Use() {}
virtual void ChgStateX87_MMX() {}
virtual void ChgStateMMX_X87() {}
virtual void SaveNZCV(IROps Op) {}

Ref CurrentWriteCursor = nullptr;
Expand Down
8 changes: 4 additions & 4 deletions unittests/ASM/3DNow/0C.asm
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0x3f800000bf800000", "0x0"],
"MM1": ["0x43000000c3000000", "0x0"],
"MM2": ["0xc700000046fffe00", "0x0"],
"MM3": ["0x0", "0x0"]
"MM0": "0x3f800000bf800000",
"MM1": "0x43000000c3000000",
"MM2": "0xc700000046fffe00",
"MM3": "0x0"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
8 changes: 4 additions & 4 deletions unittests/ASM/3DNow/0D.asm
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0x3f800000bf800000", "0x0"],
"MM1": ["0x43000000c3000000", "0x0"],
"MM2": ["0xbf8000003f800000", "0x0"],
"MM3": ["0x0", "0x0"]
"MM0": "0x3f800000bf800000",
"MM1": "0x43000000c3000000",
"MM2": "0xbf8000003f800000",
"MM3": "0x0"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
8 changes: 4 additions & 4 deletions unittests/ASM/3DNow/1C.asm
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0x00000001FFFFFFFF", "0x0"],
"MM1": ["0x00000080FFFFFF80", "0x0"],
"MM2": ["0xFFFF800000007FFF", "0x0"],
"MM3": ["0x0", "0x0"]
"MM0": "0x00000001FFFFFFFF",
"MM1": "0x00000080FFFFFF80",
"MM2": "0xFFFF800000007FFF",
"MM3": "0x0"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
8 changes: 4 additions & 4 deletions unittests/ASM/3DNow/1D.asm
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0x00000001FFFFFFFF", "0x0"],
"MM1": ["0x00000080FFFFFF80", "0x0"],
"MM2": ["0xFFFFFFFF00000001", "0x0"],
"MM3": ["0x0", "0x0"]
"MM0": "0x00000001FFFFFFFF",
"MM1": "0x00000080FFFFFF80",
"MM2": "0xFFFFFFFF00000001",
"MM3": "0x0"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
6 changes: 3 additions & 3 deletions unittests/ASM/3DNow/86.asm
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0x3f800000bf800000", "0x0"],
"MM1": ["0x3c000000bc000000", "0x0"],
"MM2": ["0xbf8000003f800000", "0x0"]
"MM0": "0x3f800000bf800000",
"MM1": "0x3c000000bc000000",
"MM2": "0xbf8000003f800000"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
6 changes: 3 additions & 3 deletions unittests/ASM/3DNow/87.asm
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0x3e8000003f800000", "0x0"],
"MM1": ["0x3e4ccccd3f000000", "0x0"],
"MM2": ["0x3f8000003eaaaaab", "0x0"]
"MM0": "0x3e8000003f800000",
"MM1": "0x3e4ccccd3f000000",
"MM2": "0x3f8000003eaaaaab"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
4 changes: 2 additions & 2 deletions unittests/ASM/3DNow/8A.asm
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0x44000000c0000000", "0x0"],
"MM1": ["0x44800000c3800000", "0x0"]
"MM0": "0x44000000c0000000",
"MM1": "0x44800000c3800000"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
4 changes: 2 additions & 2 deletions unittests/ASM/3DNow/8E.asm
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0x00000000c0000000", "0x0"],
"MM1": ["0x00000000c3800000", "0x0"]
"MM0": "0x00000000c0000000",
"MM1": "0x00000000c3800000"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
8 changes: 4 additions & 4 deletions unittests/ASM/3DNow/90.asm
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0x0", "0x0"],
"MM1": ["0xFFFFFFFF00000000", "0x0"],
"MM2": ["0xFFFFFFFFFFFFFFFF", "0x0"],
"MM3": ["0x00000000FFFFFFFF", "0x0"]
"MM0": "0x0",
"MM1": "0xFFFFFFFF00000000",
"MM2": "0xFFFFFFFFFFFFFFFF",
"MM3": "0x00000000FFFFFFFF"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
6 changes: 3 additions & 3 deletions unittests/ASM/3DNow/96.asm
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0xbf800000bf800000", "0x0"],
"MM1": ["0xbc000000bc000000", "0x0"],
"MM2": ["0x3f8000003f800000", "0x0"]
"MM0": "0xbf800000bf800000",
"MM1": "0xbc000000bc000000",
"MM2": "0x3f8000003f800000"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
6 changes: 3 additions & 3 deletions unittests/ASM/3DNow/97.asm
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0x3f8000003f800000", "0x0"],
"MM1": ["0x3f0000003f000000", "0x0"],
"MM2": ["0x3eaaaaab3eaaaaab", "0x0"]
"MM0": "0x3f8000003f800000",
"MM1": "0x3f0000003f000000",
"MM2": "0x3eaaaaab3eaaaaab"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
4 changes: 2 additions & 2 deletions unittests/ASM/3DNow/9A.asm
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0x43808000c3808000", "0x0"],
"MM1": ["0x44200000c4200000", "0x0"]
"MM0": "0x43808000c3808000",
"MM1": "0x44200000c4200000"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
4 changes: 2 additions & 2 deletions unittests/ASM/3DNow/9E.asm
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0xc37f0000437f0000", "0x0"],
"MM1": ["0xc3c0000043c00000", "0x0"]
"MM0": "0xc37f0000437f0000",
"MM1": "0xc3c0000043c00000"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
8 changes: 4 additions & 4 deletions unittests/ASM/3DNow/A0.asm
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0x0", "0x0"],
"MM1": ["0xFFFFFFFF00000000", "0x0"],
"MM2": ["0xFFFFFFFFFFFFFFFF", "0x0"],
"MM3": ["0x00000000FFFFFFFF", "0x0"]
"MM0": "0x0",
"MM1": "0xFFFFFFFF00000000",
"MM2": "0xFFFFFFFFFFFFFFFF",
"MM3": "0x00000000FFFFFFFF"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
8 changes: 4 additions & 4 deletions unittests/ASM/3DNow/A4.asm
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0x3f8000003f800000", "0x0"],
"MM1": ["0x3f8000003f800000", "0x0"],
"MM2": ["0x00000000bf800000", "0x0"],
"MM3": ["0x3f8000003f800000", "0x0"]
"MM0": "0x3f8000003f800000",
"MM1": "0x3f8000003f800000",
"MM2": "0x00000000bf800000",
"MM3": "0x3f8000003f800000"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
4 changes: 2 additions & 2 deletions unittests/ASM/3DNow/A6.asm
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0x9192939481828384", "0x0"],
"MM1": ["0xB1B2B3B4A1A2A3A4", "0x0"]
"MM0": "0x9192939481828384",
"MM1": "0xB1B2B3B4A1A2A3A4"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
4 changes: 2 additions & 2 deletions unittests/ASM/3DNow/A7.asm
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0x9192939481828384", "0x0"],
"MM1": ["0xB1B2B3B4A1A2A3A4", "0x0"]
"MM0": "0x9192939481828384",
"MM1": "0xB1B2B3B4A1A2A3A4"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
4 changes: 2 additions & 2 deletions unittests/ASM/3DNow/AA.asm
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0xc380800043808000", "0x0"],
"MM1": ["0xc420000044200000", "0x0"]
"MM0": "0xc380800043808000",
"MM1": "0xc420000044200000"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
4 changes: 2 additions & 2 deletions unittests/ASM/3DNow/AE.asm
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0x0", "0x0"],
"MM1": ["0x0", "0x0"]
"MM0": "0x0",
"MM1": "0x0"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
8 changes: 4 additions & 4 deletions unittests/ASM/3DNow/B0.asm
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0x0", "0x0"],
"MM1": ["0xFFFFFFFF00000000", "0x0"],
"MM2": ["0xFFFFFFFFFFFFFFFF", "0x0"],
"MM3": ["0x00000000FFFFFFFF", "0x0"]
"MM0": "0x0",
"MM1": "0xFFFFFFFF00000000",
"MM2": "0xFFFFFFFFFFFFFFFF",
"MM3": "0x00000000FFFFFFFF"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
4 changes: 2 additions & 2 deletions unittests/ASM/3DNow/B4.asm
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
%ifdef CONFIG
{
"RegData": {
"MM0": ["0xc3800000c3800000", "0x0"],
"MM1": ["0xc7800000c7800000", "0x0"]
"MM0": "0xc3800000c3800000",
"MM1": "0xc7800000c7800000"
},
"HostFeatures": ["3DNOW"]
}
Expand Down
Loading
Loading