Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
24 failures
  • Loading branch information
pmatos committed May 2, 2024
1 parent 153d28b commit 7cee2d3
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 124 deletions.
91 changes: 0 additions & 91 deletions FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,55 +77,6 @@ void OpDispatchBuilder::SetX87Top(OrderedNode* Value) {
_StoreContext(1, GPRClass, Value, offsetof(FEXCore::Core::CPUState, flags) + FEXCore::X86State::X87FLAG_TOP_LOC);
}

void OpDispatchBuilder::FBLD(OpcodeArgs) {
// Update TOP
auto orig_top = GetX87Top();
auto mask = _Constant(7);
auto top = _And(OpSize::i32Bit, _Sub(OpSize::i32Bit, orig_top, _Constant(1)), mask);
SetX87ValidTag(top, true);
SetX87Top(top);

// Read from memory
OrderedNode* data = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], 16, Op->Flags);
OrderedNode* converted = _F80BCDLoad(data);
_StoreContextIndexed(converted, top, 16, MMBaseOffset(), 16, FPRClass);
}

void OpDispatchBuilder::FBSTP(OpcodeArgs) {
auto orig_top = GetX87Top();
auto data = _LoadContextIndexed(orig_top, 16, MMBaseOffset(), 16, FPRClass);

OrderedNode* converted = _F80BCDStore(data);

StoreResult_WithOpSize(FPRClass, Op, Op->Dest, converted, 10, 1);

// if we are popping then we must first mark this location as empty
SetX87ValidTag(orig_top, false);
auto top = _And(OpSize::i32Bit, _Add(OpSize::i32Bit, orig_top, _Constant(1)), _Constant(7));
SetX87Top(top);
}

void OpDispatchBuilder::FTST(OpcodeArgs) {
auto top = GetX87Top();
auto a = _LoadContextIndexed(top, 16, MMBaseOffset(), 16, FPRClass);

auto low = _Constant(0);
OrderedNode* data = _VCastFromGPR(16, 8, low);

OrderedNode* Res = _F80Cmp(a, data, (1 << FCMP_FLAG_EQ) | (1 << FCMP_FLAG_LT) | (1 << FCMP_FLAG_UNORDERED));

OrderedNode* HostFlag_CF = _GetHostFlag(Res, FCMP_FLAG_LT);
OrderedNode* HostFlag_ZF = _GetHostFlag(Res, FCMP_FLAG_EQ);
OrderedNode* HostFlag_Unordered = _GetHostFlag(Res, FCMP_FLAG_UNORDERED);
HostFlag_CF = _Or(OpSize::i32Bit, HostFlag_CF, HostFlag_Unordered);
HostFlag_ZF = _Or(OpSize::i32Bit, HostFlag_ZF, HostFlag_Unordered);

SetRFLAG<FEXCore::X86State::X87FLAG_C0_LOC>(HostFlag_CF);
SetRFLAG<FEXCore::X86State::X87FLAG_C1_LOC>(_Constant(0));
SetRFLAG<FEXCore::X86State::X87FLAG_C2_LOC>(HostFlag_Unordered);
SetRFLAG<FEXCore::X86State::X87FLAG_C3_LOC>(HostFlag_ZF);
}


void OpDispatchBuilder::X87TAN(OpcodeArgs) {
auto orig_top = GetX87Top();
Expand All @@ -147,46 +98,4 @@ void OpDispatchBuilder::X87TAN(OpcodeArgs) {
_StoreContextIndexed(data, top, 16, MMBaseOffset(), 16, FPRClass);
}

void OpDispatchBuilder::X87FLDCW(OpcodeArgs) {
OrderedNode* NewFCW = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags);
_StoreContext(2, GPRClass, NewFCW, offsetof(FEXCore::Core::CPUState, FCW));
}

void OpDispatchBuilder::X87FSTCW(OpcodeArgs) {
auto FCW = _LoadContext(2, GPRClass, offsetof(FEXCore::Core::CPUState, FCW));

StoreResult(GPRClass, Op, FCW, -1);
}

void OpDispatchBuilder::X87LDSW(OpcodeArgs) {
OrderedNode* NewFSW = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags);
ReconstructX87StateFromFSW_Helper(NewFSW);
}


void OpDispatchBuilder::X87FXAM(OpcodeArgs) {
auto top = GetX87Top();
auto a = _LoadContextIndexed(top, 16, MMBaseOffset(), 16, FPRClass);
OrderedNode* Result = _VExtractToGPR(16, 8, a, 1);

// Extract the sign bit
Result = _Bfe(OpSize::i64Bit, 1, 15, Result);
SetRFLAG<FEXCore::X86State::X87FLAG_C1_LOC>(Result);

// Claim this is a normal number
// We don't support anything else
auto TopValid = GetX87ValidTag(top);
auto ZeroConst = _Constant(0);
auto OneConst = _Constant(1);

// In the case of top being invalid then C3:C2:C0 is 0b101
auto C3 = _Select(FEXCore::IR::COND_NEQ, TopValid, OneConst, OneConst, ZeroConst);

auto C2 = TopValid;
auto C0 = C3; // Mirror C3 until something other than zero is supported
SetRFLAG<FEXCore::X86State::X87FLAG_C0_LOC>(C0);
SetRFLAG<FEXCore::X86State::X87FLAG_C2_LOC>(C2);
SetRFLAG<FEXCore::X86State::X87FLAG_C3_LOC>(C3);
}

} // namespace FEXCore::IR
78 changes: 78 additions & 0 deletions FEXCore/Source/Interface/Core/OpcodeDispatcher/X87New.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,25 @@ void OpDispatchBuilder::FST(OpcodeArgs) {
}
}


void OpDispatchBuilder::FBLD(OpcodeArgs) {
CurrentHeader->HasX87 = true;

// Read from memory
OrderedNode* data = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], 16, Op->Flags);
OrderedNode* converted = _F80BCDLoad(data);
_PushStack(converted, i128Bit, true, 16);
}

void OpDispatchBuilder::FBSTP(OpcodeArgs) {
CurrentHeader->HasX87 = true;
_ReadStackValue(0);
OrderedNode* converted = _F80BCDStore(_ReadStackValue(0));
StoreResult_WithOpSize(FPRClass, Op, Op->Dest, converted, 10, 1);

_PopStackDestroy();
}

template<size_t width, bool Integer, OpDispatchBuilder::OpResult ResInST0>
void OpDispatchBuilder::FADD(OpcodeArgs) {
static_assert(width == 16 || width == 32 || width == 64 || width == 80, "Unsupported FADD width");
Expand Down Expand Up @@ -604,6 +623,20 @@ void OpDispatchBuilder::X87FRSTOR(OpcodeArgs) {
Reg = _VInsElement(16, 2, 4, 0, Reg, RegHigh);
_StoreContextIndexed(Reg, Top, 16, MMBaseOffset(), 16, FPRClass);
}

// Load / Store Control Word
void OpDispatchBuilder::X87FSTCW(OpcodeArgs) {
auto FCW = _LoadContext(2, GPRClass, offsetof(FEXCore::Core::CPUState, FCW));
StoreResult(GPRClass, Op, FCW, -1);
}


void OpDispatchBuilder::X87FLDCW(OpcodeArgs) {
OrderedNode* NewFCW = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags);
_StoreContext(2, GPRClass, NewFCW, offsetof(FEXCore::Core::CPUState, FCW));
}


void OpDispatchBuilder::FXCH(OpcodeArgs) {
CurrentHeader->HasX87 = true;
_F80StackXchange(Op->OP & 7);
Expand Down Expand Up @@ -703,6 +736,23 @@ template void OpDispatchBuilder::FCOMI<16, true, OpDispatchBuilder::FCOMIFlags::
template void OpDispatchBuilder::FCOMI<32, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>(OpcodeArgs);


void OpDispatchBuilder::FTST(OpcodeArgs) {
CurrentHeader->HasX87 = true;
OrderedNode* Res = _F80StackTest(0, (1 << FCMP_FLAG_EQ) | (1 << FCMP_FLAG_LT) | (1 << FCMP_FLAG_UNORDERED));

OrderedNode* HostFlag_CF = _GetHostFlag(Res, FCMP_FLAG_LT);
OrderedNode* HostFlag_ZF = _GetHostFlag(Res, FCMP_FLAG_EQ);
OrderedNode* HostFlag_Unordered = _GetHostFlag(Res, FCMP_FLAG_UNORDERED);
HostFlag_CF = _Or(OpSize::i32Bit, HostFlag_CF, HostFlag_Unordered);
HostFlag_ZF = _Or(OpSize::i32Bit, HostFlag_ZF, HostFlag_Unordered);

SetRFLAG<FEXCore::X86State::X87FLAG_C0_LOC>(HostFlag_CF);
SetRFLAG<FEXCore::X86State::X87FLAG_C1_LOC>(_Constant(0));
SetRFLAG<FEXCore::X86State::X87FLAG_C2_LOC>(HostFlag_Unordered);
SetRFLAG<FEXCore::X86State::X87FLAG_C3_LOC>(HostFlag_ZF);
}


void OpDispatchBuilder::X87ATAN(OpcodeArgs) {
CurrentHeader->HasX87 = true;
_F80ATANStack();
Expand Down Expand Up @@ -826,6 +876,8 @@ OrderedNode* OpDispatchBuilder::ReconstructFSW_Helper(OrderedNode* T) {
return FSW;
}

// Store Status Word
// There's no load Status Word instruction
void OpDispatchBuilder::X87FNSTSW(OpcodeArgs) {
CurrentHeader->HasX87 = true;
StoreResult(GPRClass, Op, ReconstructFSW_Helper(_SyncStackToSlow()), -1);
Expand Down Expand Up @@ -960,4 +1012,30 @@ void OpDispatchBuilder::FILD(OpcodeArgs) {
_PushStack(converted, OpSize::i128Bit, false, read_width);
}


void OpDispatchBuilder::X87FXAM(OpcodeArgs) {
CurrentHeader->HasX87 = true;
auto ZeroConst = _Constant(0);
auto OneConst = _Constant(1);

auto a = _ReadStackValue(0);
OrderedNode* Result = _VExtractToGPR(16, 8, a, 1);

// Extract the sign bit
Result = _Bfe(OpSize::i64Bit, 1, 15, Result);
SetRFLAG<FEXCore::X86State::X87FLAG_C1_LOC>(Result);

// Claim this is a normal number
// We don't support anything else
auto TopValid = _StackValidTag(0);

// In the case of top being invalid then C3:C2:C0 is 0b101
auto C3 = _Select(FEXCore::IR::COND_NEQ, TopValid, OneConst, OneConst, ZeroConst);

auto C2 = TopValid;
auto C0 = C3; // Mirror C3 until something other than zero is supported
SetRFLAG<FEXCore::X86State::X87FLAG_C0_LOC>(C0);
SetRFLAG<FEXCore::X86State::X87FLAG_C2_LOC>(C2);
SetRFLAG<FEXCore::X86State::X87FLAG_C3_LOC>(C3);
}
} // namespace FEXCore::IR
20 changes: 17 additions & 3 deletions FEXCore/Source/Interface/IR/IR.json
Original file line number Diff line number Diff line change
Expand Up @@ -2368,13 +2368,14 @@
}
},
"F80": {
"SyncStackToSlow": {
"GPR = SyncStackToSlow": {
"Desc": [
"Synchronizes the virtual stack environment to the physical registers.",
"Returns the current stack top."
],
"JITDispatch": false,
"HasSideEffects": true
"HasSideEffects": true,
"DestSize": 8
},
"StackForceSlow": {
"Desc": [
Expand Down Expand Up @@ -2457,6 +2458,13 @@
"DestSize": "16",
"JITDispatch": false
},
"GPR = StackValidTag u8:$StackLocation": {
"Desc": [
"Returns the valid tag for value in location TOP+$StackLocation"
],
"DestSize": 8,
"JITDispatch": false
},
"F80AddStack u8:$SrcStack1, u8:$SrcStack2": {
"Desc": [
"Adds two stack locations together, storing the result in to the first stack location"
Expand Down Expand Up @@ -2698,13 +2706,19 @@
"DestSize": "16",
"JITDispatch": false
},
"GPR = F80StackTest u8:$SrcStack, u32:$Flags": {
"Desc": [
"Does comparison between value in stack at TOP + SrcStack"
],
"DestSize": "4",
"JITDispatch": false
},
"GPR = F80CmpStack u8:$SrcStack, u32:$Flags": {
"Desc": [
"Does a scalar unordered compare between the value at the top of the stack and the value in stack position TOP+$SrcStack and stores the asked for flags in to a GPR",
"Ordering flag result is true if either float input is NaN"
],
"DestSize": "4",
"HasSideEffects": true,
"JITDispatch": false
},
"GPR = F80CmpValue FPR:$X80Src, u32:$Flags": {
Expand Down
Loading

0 comments on commit 7cee2d3

Please sign in to comment.