Skip to content

Commit

Permalink
Merge pull request #4105 from pmatos/X87MMXState
Browse files Browse the repository at this point in the history
Implement explicit state switch between X87 and MMX
  • Loading branch information
Sonicadvance1 authored Oct 16, 2024
2 parents d66ed71 + def5619 commit 4b945a9
Show file tree
Hide file tree
Showing 40 changed files with 886 additions and 437 deletions.
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

0 comments on commit 4b945a9

Please sign in to comment.