diff --git a/External/FEXCore/Source/Common/SoftFloat.h b/External/FEXCore/Source/Common/SoftFloat.h index 64b3ba89d..5c7a51d7f 100644 --- a/External/FEXCore/Source/Common/SoftFloat.h +++ b/External/FEXCore/Source/Common/SoftFloat.h @@ -111,7 +111,9 @@ struct X80SoftFloat { static X80SoftFloat F2XM1(X80SoftFloat const &lhs) { WARN_ONCE("x87: Application used F2XM1 which may have accuracy problems"); BIGFLOAT Src1_d = lhs; - return exp2l(Src1_d) - 1.0; + BIGFLOAT Result = exp2l(Src1_d); + Result -= 1.0; + return Result; } static X80SoftFloat FYL2X(X80SoftFloat const &lhs, X80SoftFloat const &rhs) { diff --git a/External/FEXCore/Source/Interface/Core/Interpreter/InterpreterCore.cpp b/External/FEXCore/Source/Interface/Core/Interpreter/InterpreterCore.cpp index 0fb1bd027..73113c720 100644 --- a/External/FEXCore/Source/Interface/Core/Interpreter/InterpreterCore.cpp +++ b/External/FEXCore/Source/Interface/Core/Interpreter/InterpreterCore.cpp @@ -1,5 +1,6 @@ #include "LogManager.h" #include "Common/MathUtils.h" +#include "Common/SoftFloat.h" #include "Interface/Context/Context.h" #include "Interface/Core/DebugData.h" #include "Interface/Core/InternalThreadState.h" @@ -573,6 +574,22 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { memcpy(GDP, Data, OpSize); break; } + case IR::OP_VLOADMEMELEMENT: { + auto Op = IROp->C(); + void const *Data{}; + if (Thread->CTX->Config.UnifiedMemory) { + Data = *GetSrc(Op->Header.Args[0]); + } + else { + Data = Thread->CTX->MemoryMapper.GetPointer(*GetSrc(Op->Header.Args[0])); + LogMan::Throw::A(Data != nullptr, "Couldn't Map pointer to 0x%lx\n", *GetSrc(Op->Header.Args[0])); + } + + memcpy(GDP, GetSrc(Op->Header.Args[1]), 16); + memcpy(reinterpret_cast(reinterpret_cast(GDP) + (Op->Header.ElementSize * Op->Index)), + Data, Op->Header.ElementSize); + break; + } case IR::OP_STOREMEM: { #define STORE_DATA(x, y) \ case x: { \ @@ -614,6 +631,33 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { #undef STORE_DATA break; } + case IR::OP_VSTOREMEMELEMENT: { + #define STORE_DATA(x, y) \ + case x: { \ + y *Data{}; \ + if (Thread->CTX->Config.UnifiedMemory) { \ + Data = *GetSrc(Op->Header.Args[0]); \ + } \ + else { \ + Data = Thread->CTX->MemoryMapper.GetPointer(*GetSrc(Op->Header.Args[0])); \ + LogMan::Throw::A(Data != nullptr, "Couldn't Map pointer to 0x%lx\n", *GetSrc(Op->Header.Args[0])); \ + } \ + memcpy(Data, &GetSrc(Op->Header.Args[1])[Op->Index], sizeof(y)); \ + break; \ + } + + auto Op = IROp->C(); + + switch (OpSize) { + STORE_DATA(1, uint8_t) + STORE_DATA(2, uint16_t) + STORE_DATA(4, uint32_t) + STORE_DATA(8, uint64_t) + default: LogMan::Msg::A("Unhandled StoreMem size"); break; + } + #undef STORE_DATA + break; + } #define DO_OP(size, type, func) \ case size: { \ auto *Dst_d = reinterpret_cast(GDP); \ @@ -1163,6 +1207,17 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { GD = Res; break; } + case IR::OP_SBFE: { + auto Op = IROp->C(); + LogMan::Throw::A(OpSize < 16, "OpSize is too large for BFE: %d", OpSize); + int64_t Src = *GetSrc(Op->Header.Args[0]); + uint64_t ShiftLeftAmount = (64 - (Op->Width + Op->lsb)); + uint64_t ShiftRightAmount = ShiftLeftAmount - Op->lsb; + Src <<= ShiftLeftAmount; + Src >>= ShiftRightAmount; + GD = Src; + break; + } case IR::OP_BFE: { auto Op = IROp->C(); LogMan::Throw::A(OpSize <= 16, "OpSize is too large for BFE: %d", OpSize); @@ -3298,6 +3353,20 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { memcpy(GDP, Tmp, OpSize); break; } + + case IR::OP_VBSL: { + auto Op = IROp->C(); + __uint128_t Src1 = *GetSrc<__uint128_t*>(Op->Header.Args[0]); + __uint128_t Src2 = *GetSrc<__uint128_t*>(Op->Header.Args[1]); + __uint128_t Src3 = *GetSrc<__uint128_t*>(Op->Header.Args[2]); + + __uint128_t Tmp{}; + Tmp = Src2 & Src1; + Tmp |= Src3 & ~Src1; + + memcpy(GDP, &Tmp, 16); + break; + } case IR::OP_VCMPEQ: { auto Op = IROp->C(); void *Src1 = GetSrc(Op->Header.Args[0]); @@ -3865,6 +3934,270 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { memcpy(GDP, Tmp, OpSize); break; } + case IR::OP_F80ADD: { + auto Op = IROp->C(); + X80SoftFloat Src1 = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Src2 = *GetSrc(Op->Header.Args[1]); + X80SoftFloat Tmp; + Tmp = X80SoftFloat::FADD(Src1, Src2); + + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case IR::OP_F80SUB: { + auto Op = IROp->C(); + X80SoftFloat Src1 = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Src2 = *GetSrc(Op->Header.Args[1]); + X80SoftFloat Tmp; + Tmp = X80SoftFloat::FSUB(Src1, Src2); + + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case IR::OP_F80MUL: { + auto Op = IROp->C(); + X80SoftFloat Src1 = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Src2 = *GetSrc(Op->Header.Args[1]); + X80SoftFloat Tmp; + Tmp = X80SoftFloat::FMUL(Src1, Src2); + + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case IR::OP_F80DIV: { + auto Op = IROp->C(); + X80SoftFloat Src1 = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Src2 = *GetSrc(Op->Header.Args[1]); + X80SoftFloat Tmp; + Tmp = X80SoftFloat::FDIV(Src1, Src2); + + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case IR::OP_F80FYL2X: { + auto Op = IROp->C(); + X80SoftFloat Src1 = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Src2 = *GetSrc(Op->Header.Args[1]); + X80SoftFloat Tmp; + Tmp = X80SoftFloat::FYL2X(Src1, Src2); + + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case IR::OP_F80ATAN: { + auto Op = IROp->C(); + X80SoftFloat Src1 = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Src2 = *GetSrc(Op->Header.Args[1]); + X80SoftFloat Tmp; + Tmp = X80SoftFloat::FATAN(Src1, Src2); + + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case IR::OP_F80FPREM1: { + auto Op = IROp->C(); + X80SoftFloat Src1 = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Src2 = *GetSrc(Op->Header.Args[1]); + X80SoftFloat Tmp; + Tmp = X80SoftFloat::FREM1(Src1, Src2); + + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case IR::OP_F80FPREM: { + auto Op = IROp->C(); + X80SoftFloat Src1 = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Src2 = *GetSrc(Op->Header.Args[1]); + X80SoftFloat Tmp; + Tmp = X80SoftFloat::FREM(Src1, Src2); + + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case IR::OP_F80SCALE: { + auto Op = IROp->C(); + X80SoftFloat Src1 = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Src2 = *GetSrc(Op->Header.Args[1]); + X80SoftFloat Tmp; + Tmp = X80SoftFloat::FSCALE(Src1, Src2); + + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case IR::OP_F80CVT: { + auto Op = IROp->C(); + X80SoftFloat Src = *GetSrc(Op->Header.Args[0]); + + switch (OpSize) { + case 4: { + float Tmp = Src; + memcpy(GDP, &Tmp, OpSize); + break; + } + case 8: { + double Tmp = Src; + memcpy(GDP, &Tmp, OpSize); + break; + } + default: LogMan::Msg::D("Unhandled size: %d", OpSize); + } + break; + } + case IR::OP_F80CVTINT: { + auto Op = IROp->C(); + X80SoftFloat Src = *GetSrc(Op->Header.Args[0]); + + switch (OpSize) { + case 2: { + int16_t Tmp = Src; + memcpy(GDP, &Tmp, OpSize); + break; + } + case 4: { + int32_t Tmp = Src; + memcpy(GDP, &Tmp, OpSize); + break; + } + case 8: { + int64_t Tmp = Src; + memcpy(GDP, &Tmp, OpSize); + break; + } + default: LogMan::Msg::D("Unhandled size: %d", OpSize); + } + break; + } + case IR::OP_F80CVTTO: { + auto Op = IROp->C(); + + switch (Op->Size) { + case 4: { + float Src = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Tmp = Src; + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case 8: { + double Src = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Tmp = Src; + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + default: LogMan::Msg::D("Unhandled size: %d", OpSize); + } + break; + } + case IR::OP_F80CVTTOINT: { + auto Op = IROp->C(); + + switch (Op->Size) { + case 2: { + int16_t Src = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Tmp = Src; + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case 4: { + int32_t Src = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Tmp = Src; + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + default: LogMan::Msg::D("Unhandled size: %d", OpSize); + } + break; + } + case IR::OP_F80ROUND: { + auto Op = IROp->C(); + X80SoftFloat Src = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Tmp; + Tmp = X80SoftFloat::FRNDINT(Src); + + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case IR::OP_F80F2XM1: { + auto Op = IROp->C(); + X80SoftFloat Src = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Tmp; + Tmp = X80SoftFloat::F2XM1(Src); + + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case IR::OP_F80TAN: { + auto Op = IROp->C(); + X80SoftFloat Src = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Tmp; + Tmp = X80SoftFloat::FTAN(Src); + + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case IR::OP_F80SQRT: { + auto Op = IROp->C(); + X80SoftFloat Src = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Tmp; + Tmp = X80SoftFloat::FSQRT(Src); + + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case IR::OP_F80SIN: { + auto Op = IROp->C(); + X80SoftFloat Src = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Tmp; + Tmp = X80SoftFloat::FSIN(Src); + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case IR::OP_F80COS: { + auto Op = IROp->C(); + X80SoftFloat Src = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Tmp; + Tmp = X80SoftFloat::FCOS(Src); + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case IR::OP_F80XTRACT_EXP: { + auto Op = IROp->C(); + X80SoftFloat Src = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Tmp; + Tmp = X80SoftFloat::FXTRACT_EXP(Src); + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case IR::OP_F80XTRACT_SIG: { + auto Op = IROp->C(); + X80SoftFloat Src = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Tmp; + Tmp = X80SoftFloat::FXTRACT_SIG(Src); + memcpy(GDP, &Tmp, sizeof(X80SoftFloat)); + break; + } + case IR::OP_F80CMP: { + auto Op = IROp->C(); + uint32_t ResultFlags{}; + X80SoftFloat Src1 = *GetSrc(Op->Header.Args[0]); + X80SoftFloat Src2 = *GetSrc(Op->Header.Args[1]); + bool eq, lt, nan; + X80SoftFloat::FCMP(Src1, Src2, &eq, <, &nan); + if (Op->Flags & (1 << FCMP_FLAG_LT) && + lt) { + ResultFlags |= (1 << FCMP_FLAG_LT); + } + if (Op->Flags & (1 << FCMP_FLAG_UNORDERED) && + nan) { + ResultFlags |= (1 << FCMP_FLAG_UNORDERED); + } + if (Op->Flags & (1 << FCMP_FLAG_EQ) && + eq) { + ResultFlags |= (1 << FCMP_FLAG_EQ); + } + + GD = ResultFlags; + break; + } default: LogMan::Msg::A("Unknown IR Op: %d(%s)", IROp->Op, FEXCore::IR::GetName(IROp->Op).data()); break; diff --git a/External/FEXCore/Source/Interface/Core/LLVMJIT/LLVMCore.cpp b/External/FEXCore/Source/Interface/Core/LLVMJIT/LLVMCore.cpp index 19683a5d5..46ae82a75 100644 --- a/External/FEXCore/Source/Interface/Core/LLVMJIT/LLVMCore.cpp +++ b/External/FEXCore/Source/Interface/Core/LLVMJIT/LLVMCore.cpp @@ -777,7 +777,7 @@ private: void CreateGlobalVariables(llvm::ExecutionEngine *Engine, llvm::Module *FunctionModule); llvm::Value *CastVectorToType(llvm::Value *Arg, bool Integer, uint8_t RegisterSize, uint8_t ElementSize); - llvm::Value *CastScalarToType(llvm::Value *Arg, bool Integer, uint8_t RegisterSize, uint8_t ElementSize); + llvm::Value *CastScalarToType(llvm::Value *Arg, bool Integer, uint8_t ElementSize); llvm::Value *CastToOpaqueStructure(llvm::Value *Arg, llvm::Type *DstType); void SetDest(IR::OrderedNodeWrapper Op, llvm::Value *Val); llvm::Value *GetSrc(IR::OrderedNodeWrapper Src); @@ -1380,6 +1380,7 @@ llvm::Value *LLVMJITCore::CreateIndexedContextPtr(llvm::Value *Index, uint64_t O llvm::Value *LLVMJITCore::CastVectorToType(llvm::Value *Arg, bool Integer, uint8_t RegisterSize, uint8_t ElementSize) { uint8_t DestSizeInBits = RegisterSize * ElementSize * 8; uint8_t NumElements = RegisterSize / ElementSize; + llvm::Type *ElementType; if (Integer) { ElementType = llvm::Type::getIntNTy(*Con, ElementSize * 8); @@ -1418,8 +1419,8 @@ llvm::Value *LLVMJITCore::CastVectorToType(llvm::Value *Arg, bool Integer, uint8 return JITState.IRBuilder->CreateShuffleVector(Arg, Undef, Mask); } -llvm::Value *LLVMJITCore::CastScalarToType(llvm::Value *Arg, bool Integer, uint8_t RegisterSize, uint8_t ElementSize) { - llvm::Type *ElementType; +llvm::Value *LLVMJITCore::CastScalarToType(llvm::Value *Arg, bool Integer, uint8_t ElementSize) { + llvm::Type *ElementType{}; if (Integer) { ElementType = llvm::Type::getIntNTy(*Con, ElementSize * 8); } @@ -1427,11 +1428,15 @@ llvm::Value *LLVMJITCore::CastScalarToType(llvm::Value *Arg, bool Integer, uint8 if (ElementSize == 4) { ElementType = llvm::Type::getFloatTy(*Con); } - else { + else if (ElementSize == 8) { ElementType = llvm::Type::getDoubleTy(*Con); } + else { + LogMan::Msg::A("Unhandled ElementSize for scalar convert: %d", ElementSize); + } } + Arg = CastToOpaqueStructure(Arg, llvm::Type::getIntNTy(*Con, ElementSize * 8)); return JITState.IRBuilder->CreateBitCast(Arg, ElementType); } @@ -1443,6 +1448,10 @@ llvm::Value *LLVMJITCore::CastToOpaqueStructure(llvm::Value *Arg, llvm::Type *Ds auto NewIntegerType = llvm::Type::getIntNTy(*Con, ElementSize * NumElements); Arg = JITState.IRBuilder->CreateBitCast(Arg, NewIntegerType); } + else if (!Arg->getType()->isIntegerTy()) { + auto NewIntegerType = llvm::Type::getIntNTy(*Con, Arg->getType()->getPrimitiveSizeInBits()); + Arg = JITState.IRBuilder->CreateBitCast(Arg, NewIntegerType); + } return JITState.IRBuilder->CreateZExtOrTrunc(Arg, DstType); } @@ -2439,8 +2448,8 @@ void LLVMJITCore::HandleIR(FEXCore::IR::IRListView const *IR, IR::NodeWrap auto Src2 = GetSrc(Op->Header.Args[1]); // Cast to the type we want - Src1 = CastScalarToType(Src1, false, OpSize * 8, Op->ElementSize); - Src2 = CastScalarToType(Src2, false, OpSize * 8, Op->ElementSize); + Src1 = CastScalarToType(Src1, false, Op->ElementSize); + Src2 = CastScalarToType(Src2, false, Op->ElementSize); llvm::Value *Result = JITState.IRBuilder->getInt64(0); if (Op->Flags & (1 << IR::FCMP_FLAG_LT)) { @@ -2514,7 +2523,7 @@ void LLVMJITCore::HandleIR(FEXCore::IR::IRListView const *IR, IR::NodeWrap auto Src = GetSrc(Op->Header.Args[0]); // Cast to the type we want - Src = CastScalarToType(Src, true, OpSize, OpSize); + Src = CastScalarToType(Src, true, OpSize); SetDest(*WrapperOp, Src); break; } @@ -2532,7 +2541,7 @@ void LLVMJITCore::HandleIR(FEXCore::IR::IRListView const *IR, IR::NodeWrap auto Src = GetSrc(Op->Header.Args[0]); // Cast to the type we want - Src = CastVectorToType(Src, true, Src->getType()->getPrimitiveSizeInBits(), Op->Header.ElementSize); + Src = CastVectorToType(Src, true, Src->getType()->getPrimitiveSizeInBits() / 8, Op->Header.ElementSize); auto Result = JITState.IRBuilder->CreateExtractElement(Src, JITState.IRBuilder->getInt32(Op->Idx)); Result = JITState.IRBuilder->CreateZExt(Result, Type::getInt64Ty(*Con)); @@ -3593,7 +3602,7 @@ void LLVMJITCore::HandleIR(FEXCore::IR::IRListView const *IR, IR::NodeWrap // Cast to the type we want Src1 = CastVectorToType(Src1, true, OpSize, Op->Header.ElementSize); - Src2 = CastScalarToType(Src2, true, OpSize, Op->Header.ElementSize); + Src2 = CastScalarToType(Src2, true, Op->Header.ElementSize); // Extract our source index auto Result = JITState.IRBuilder->CreateInsertElement(Src1, Src2, JITState.IRBuilder->getInt32(Op->DestIdx)); @@ -3724,7 +3733,7 @@ void LLVMJITCore::HandleIR(FEXCore::IR::IRListView const *IR, IR::NodeWrap auto Src = GetSrc(Op->Header.Args[0]); // Cast to the type we want - Src = CastScalarToType(Src, false, OpSize * 8, Op->SrcElementSize); + Src = CastScalarToType(Src, false, Op->SrcElementSize); switch (Conv) { case 0x0804: { // Double <- float @@ -3746,7 +3755,7 @@ void LLVMJITCore::HandleIR(FEXCore::IR::IRListView const *IR, IR::NodeWrap auto Op = IROp->C(); auto Src = GetSrc(Op->Header.Args[0]); - Src = CastScalarToType(Src, false, Op->Header.ElementSize, Op->Header.ElementSize); + Src = CastScalarToType(Src, false, Op->Header.ElementSize); switch (Op->Header.ElementSize) { case 4: { @@ -3767,7 +3776,7 @@ void LLVMJITCore::HandleIR(FEXCore::IR::IRListView const *IR, IR::NodeWrap auto Op = IROp->C(); auto Src = GetSrc(Op->Header.Args[0]); - Src = CastScalarToType(Src, false, Op->Header.ElementSize, Op->Header.ElementSize); + Src = CastScalarToType(Src, false, Op->Header.ElementSize); switch (Op->Header.ElementSize) { case 4: { @@ -3869,7 +3878,7 @@ void LLVMJITCore::HandleIR(FEXCore::IR::IRListView const *IR, IR::NodeWrap } auto Type = Type::getIntNTy(*Con, Op->Size * 8); - Src = JITState.IRBuilder->CreateZExtOrTrunc(Src, Type); + Src = CastToOpaqueStructure(Src, Type); Dst = JITState.IRBuilder->CreateIntToPtr(Dst, Type->getPointerTo()); CreateMemoryStore(Dst, Src, Op->Align); break; @@ -3896,7 +3905,9 @@ void LLVMJITCore::HandleIR(FEXCore::IR::IRListView const *IR, IR::NodeWrap default: LogMan::Msg::A("Unknown Atomic Op: %d", IROp->Op); } // Cast the pointer type correctly - Src = JITState.IRBuilder->CreateIntToPtr(Src, Type::getIntNTy(*Con, Op->Size * 8)->getPointerTo()); + auto Type = Type::getIntNTy(*Con, Op->Size * 8); + Src = JITState.IRBuilder->CreateIntToPtr(Src, Type->getPointerTo()); + Value = CastToOpaqueStructure(Value, Type); auto Result = JITState.IRBuilder->CreateAtomicRMW(AtomicOp, Src, Value, AtomicOrdering::AcquireRelease); SetDest(*WrapperOp, Result); break; diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 030dbf985..bea30d291 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -3651,6 +3651,7 @@ void OpDispatchBuilder::ResetWorkingList() { BlockSetRIP = false; DecodeFailure = false; ShouldDump = false; + CurrentCodeBlock = nullptr; } template @@ -5035,26 +5036,41 @@ void OpDispatchBuilder::SetX87Top(OrderedNode *Value) { template void OpDispatchBuilder::FLD(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + // Update TOP auto orig_top = GetX87Top(); - auto top = _And(_Sub(orig_top, _Constant(1)), _Constant(7)); + auto mask = _Constant(7); + auto top = _And(_Sub(orig_top, _Constant(1)), mask); SetX87Top(top); size_t read_width = (width == 80) ? 16 : width / 8; - // Read from memory - auto data = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], read_width, Op->Flags, -1); + OrderedNode *data{}; - OrderedNode *converted; + if (Op->Src[0].TypeNone.Type != 0) { + // Read from memory + data = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], read_width, Op->Flags, -1); + } + else { + // Implicit arg + auto offset = _Constant(Op->OP & 7); + data = _And(_Add(top, offset), mask); + data = _LoadContextIndexed(data, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + } + OrderedNode *converted = data; // Convert to 80bit float if (width == 32 || width == 64) { + converted = _F80CVTTo(data, width / 8); + } + else if (width == 32 || width == 64) { _Zext(32, data); if (width == 32) data = _Zext(32, data); constexpr size_t mantissa_bits = (width == 32) ? 23 : 52; - constexpr size_t sign_bits = width - (mantissa_bits + 1); + constexpr size_t exponent_bits = width - (mantissa_bits + 1); uint64_t sign_mask = (width == 32) ? 0x80000000 : 0x8000000000000000; uint64_t exponent_mask = (width == 32) ? 0x7F800000 : 0x7FE0000000000000; @@ -5064,7 +5080,7 @@ void OpDispatchBuilder::FLD(OpcodeArgs) { auto lower = _Lshl(_And(data, _Constant(lower_mask)), _Constant(63 - mantissa_bits)); // XXX: Need to handle NaN/Infinities - constexpr size_t exponent_zero = (1 << (sign_bits-1)); + constexpr size_t exponent_zero = (1 << (exponent_bits-1)); auto adjusted_exponent = _Add(exponent, _Constant(0x4000 - exponent_zero)); auto upper = _Or(sign, adjusted_exponent); @@ -5074,23 +5090,80 @@ void OpDispatchBuilder::FLD(OpcodeArgs) { converted = _VCastFromGPR(16, 8, _Or(intergerBit, lower)); converted = _VInsElement(16, 8, 1, 0, converted, _VCastFromGPR(16, 8, upper)); } - else if (width == 80) { - // TODO - } // Write to ST[TOP] _StoreContextIndexed(converted, top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); //_StoreContext(converted, 16, offsetof(FEXCore::Core::CPUState, mm[7][0])); } +template +void OpDispatchBuilder::FLD_Const(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + // Update TOP + auto orig_top = GetX87Top(); + auto top = _And(_Sub(orig_top, _Constant(1)), _Constant(7)); + SetX87Top(top); + + auto low = _Constant(Lower); + auto high = _Constant(Upper); + OrderedNode *data = _VCastFromGPR(16, 8, low); + data = _VInsGPR(16, 8, data, high, 1); + // Write to ST[TOP] + _StoreContextIndexed(data, top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + +template +void OpDispatchBuilder::FILD(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + // Update TOP + auto orig_top = GetX87Top(); + auto top = _And(_Sub(orig_top, _Constant(1)), _Constant(7)); + SetX87Top(top); + + size_t read_width = width / 8; + + // Read from memory + auto data = LoadSource_WithOpSize(GPRClass, Op, Op->Src[0], read_width, Op->Flags, -1); + + auto zero = _Constant(0); + + // Sign extend to 64bits + if (width != 64) + data = _Sext(width, data); + + // Extract sign and make interger absolute + auto sign = _Select(COND_SLT, data, zero, _Constant(0x8000), zero); + auto absolute = _Select(COND_SLT, data, zero, _Sub(zero, data), data); + + // left justify the absolute interger + auto shift = _Sub(_Constant(63), _FindMSB(absolute)); + auto shifted = _Lshl(absolute, shift); + + auto adjusted_exponent = _Sub(_Constant(0x3fff + 63), shift); + auto zeroed_exponent = _Select(COND_EQ, absolute, zero, zero, adjusted_exponent); + auto upper = _Or(sign, zeroed_exponent); + + + OrderedNode *converted = _VCastFromGPR(16, 8, shifted); + converted = _VInsElement(16, 8, 1, 0, converted, _VCastFromGPR(16, 8, upper)); + + // Write to ST[TOP] + _StoreContextIndexed(converted, top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + template void OpDispatchBuilder::FST(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + auto orig_top = GetX87Top(); + auto data = _LoadContextIndexed(orig_top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); if (width == 80) { - auto data = _LoadContextIndexed(orig_top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); StoreResult_WithOpSize(FPRClass, Op, Op->Dest, data, 10, 1); } - - // TODO: Other widths + else if (width == 32 || width == 64) { + auto result = _F80CVT(data, width / 8); + StoreResult_WithOpSize(FPRClass, Op, Op->Dest, result, width / 8, 1); + } if (pop) { auto top = _And(_Add(orig_top, _Constant(1)), _Constant(7)); @@ -5098,74 +5171,956 @@ void OpDispatchBuilder::FST(OpcodeArgs) { } } +template +void OpDispatchBuilder::FIST(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + auto orig_top = GetX87Top(); + OrderedNode *data = _LoadContextIndexed(orig_top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + data = _F80CVTInt(data, width / 8); + + StoreResult_WithOpSize(GPRClass, Op, Op->Dest, data, width / 8, 1); + + if (pop) { + auto top = _And(_Add(orig_top, _Constant(1)), _Constant(7)); + SetX87Top(top); + } +} + +template void OpDispatchBuilder::FADD(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + auto top = GetX87Top(); - OrderedNode* arg; + OrderedNode *StackLocation = top; + + OrderedNode *arg{}; + OrderedNode *b{}; auto mask = _Constant(7); if (Op->Src[0].TypeNone.Type != 0) { // Memory arg arg = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1); + if (width == 16 || width == 32 || width == 64) { + if (Integer) { + b = _F80CVTToInt(arg, width / 8); + } + else { + b = _F80CVTTo(arg, width / 8); + } + } } else { // Implicit arg auto offset = _Constant(Op->OP & 7); arg = _And(_Add(top, offset), mask); + if (ResInST0 == OpResult::RES_STI) { + StackLocation = arg; + } + b = _LoadContextIndexed(arg, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); } auto a = _LoadContextIndexed(top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); - auto b = _LoadContextIndexed(arg, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); - - // _StoreContext(a, 16, offsetof(FEXCore::Core::CPUState, mm[0][0])); - // _StoreContext(b, 16, offsetof(FEXCore::Core::CPUState, mm[1][0])); - - auto ExponentMask = _Constant(0x7FFF); - - //auto result = _F80Add(a, b); - // TODO: Handle sign and negative additions. - - // TODO: handle NANs (and other weird numbers?) - - auto a_Exponent = _And(_VExtractToGPR(16, 8, a, 1), ExponentMask); - auto b_Exponent = _And(_VExtractToGPR(16, 8, b, 1), ExponentMask); - auto shift = _Sub(a_Exponent, b_Exponent); - - auto zero = _Constant(0); - - auto ExponentLarger = _Select(COND_ULT, shift, zero, a_Exponent, b_Exponent); - - auto a_Mantissa = _VExtractToGPR(16, 8, a, 0); - auto b_Mantissa = _VExtractToGPR(16, 8, b, 0); - auto MantissaLarger = _Select(COND_ULT, shift, zero, a_Mantissa, b_Mantissa); - auto MantissaSmaller = _Select(COND_ULT, shift, zero, b_Mantissa, a_Mantissa); - - auto invertedShift = _Select(COND_ULT, shift, zero, _Neg(shift), shift); - auto MantissaSmallerShifted = _Lshr(MantissaSmaller, invertedShift); - - auto MantissaSummed = _Add(MantissaLarger, MantissaSmallerShifted); - - auto one = _Constant(1); - // Hacky way to detect overflow and adjust - auto ExponentAdjusted = _Select(COND_ULT, MantissaLarger, MantissaSummed, ExponentLarger, _Add(ExponentLarger, one)); - auto MantissaShifted = _Or(_Constant(1ULL << 63), _Lshr(MantissaSummed, one)); - auto MantissaAdjusted = _Select(COND_ULT, MantissaLarger, MantissaSummed, MantissaSummed, MantissaShifted); - - // TODO: Rounding, Infinities, exceptions, precision, tags? - - auto lower = _VCastFromGPR(16, 8, MantissaAdjusted); - auto upper = _VCastFromGPR(16, 8, ExponentAdjusted); - - auto result = _VInsElement(16, 8, 1, 0, lower, upper); + auto result = _F80Add(a, b); if ((Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) != 0) { - top = _And(_Add(top, one), mask); + top = _And(_Add(top, _Constant(1)), mask); SetX87Top(top); } + // Write to ST[TOP] + _StoreContextIndexed(result, StackLocation, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + +template +void OpDispatchBuilder::FMUL(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + auto top = GetX87Top(); + OrderedNode *StackLocation = top; + OrderedNode *arg{}; + OrderedNode *b{}; + + auto mask = _Constant(7); + + if (Op->Src[0].TypeNone.Type != 0) { + // Memory arg + arg = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1); + + if (width == 16 || width == 32 || width == 64) { + if (Integer) { + b = _F80CVTToInt(arg, width / 8); + } + else { + b = _F80CVTTo(arg, width / 8); + } + } + } else { + // Implicit arg + auto offset = _Constant(Op->OP & 7); + arg = _And(_Add(top, offset), mask); + if (ResInST0 == OpResult::RES_STI) { + StackLocation = arg; + } + + b = _LoadContextIndexed(arg, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + } + + auto a = _LoadContextIndexed(top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + auto result = _F80Mul(a, b); + + if ((Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) != 0) { + top = _And(_Add(top, _Constant(1)), mask); + SetX87Top(top); + } + + // Write to ST[TOP] + _StoreContextIndexed(result, StackLocation, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + +template +void OpDispatchBuilder::FDIV(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + auto top = GetX87Top(); + OrderedNode *StackLocation = top; + OrderedNode *arg{}; + OrderedNode *b{}; + + auto mask = _Constant(7); + + if (Op->Src[0].TypeNone.Type != 0) { + // Memory arg + arg = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1); + + if (width == 16 || width == 32 || width == 64) { + if (Integer) { + b = _F80CVTToInt(arg, width / 8); + } + else { + b = _F80CVTTo(arg, width / 8); + } + } + } else { + // Implicit arg + auto offset = _Constant(Op->OP & 7); + arg = _And(_Add(top, offset), mask); + if (ResInST0 == OpResult::RES_STI) { + StackLocation = arg; + } + + b = _LoadContextIndexed(arg, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + } + + auto a = _LoadContextIndexed(top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + OrderedNode *result{}; + if (reverse) { + result = _F80Div(b, a); + } + else { + result = _F80Div(a, b); + } + + if ((Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) != 0) { + top = _And(_Add(top, _Constant(1)), mask); + SetX87Top(top); + } + + // Write to ST[TOP] + _StoreContextIndexed(result, StackLocation, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + +template +void OpDispatchBuilder::FSUB(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + auto top = GetX87Top(); + OrderedNode *StackLocation = top; + OrderedNode *arg{}; + OrderedNode *b{}; + + auto mask = _Constant(7); + + if (Op->Src[0].TypeNone.Type != 0) { + // Memory arg + arg = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1); + + if (width == 16 || width == 32 || width == 64) { + if (Integer) { + b = _F80CVTToInt(arg, width / 8); + } + else { + b = _F80CVTTo(arg, width / 8); + } + } + } else { + // Implicit arg + auto offset = _Constant(Op->OP & 7); + arg = _And(_Add(top, offset), mask); + if (ResInST0 == OpResult::RES_STI) { + StackLocation = arg; + } + b = _LoadContextIndexed(arg, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + } + + auto a = _LoadContextIndexed(top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + OrderedNode *result{}; + if (reverse) { + result = _F80Sub(b, a); + } + else { + result = _F80Sub(a, b); + } + + if ((Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) != 0) { + top = _And(_Add(top, _Constant(1)), mask); + SetX87Top(top); + } + + // Write to ST[TOP] + _StoreContextIndexed(result, StackLocation, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + +void OpDispatchBuilder::FCHS(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + auto top = GetX87Top(); + auto a = _LoadContextIndexed(top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + auto low = _Constant(0); + auto high = _Constant(0b1'000'0000'0000'0000); + OrderedNode *data = _VCastFromGPR(16, 8, low); + data = _VInsGPR(16, 8, data, high, 1); + + auto result = _VXor(a, data, 16, 1); + // Write to ST[TOP] _StoreContextIndexed(result, top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); } +void OpDispatchBuilder::FABS(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + auto top = GetX87Top(); + auto a = _LoadContextIndexed(top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + auto low = _Constant(~0ULL); + auto high = _Constant(0b0'111'1111'1111'1111); + OrderedNode *data = _VCastFromGPR(16, 8, low); + data = _VInsGPR(16, 8, data, high, 1); + + auto result = _VAnd(a, data, 16, 1); + + // Write to ST[TOP] + _StoreContextIndexed(result, top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + +void OpDispatchBuilder::FTST(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + auto top = GetX87Top(); + auto a = _LoadContextIndexed(top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 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(HostFlag_CF, HostFlag_Unordered); + HostFlag_ZF = _Or(HostFlag_ZF, HostFlag_Unordered); + + SetRFLAG(HostFlag_CF); + SetRFLAG(_Constant(0)); + SetRFLAG(HostFlag_Unordered); + SetRFLAG(HostFlag_ZF); +} + +void OpDispatchBuilder::FRNDINT(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + auto top = GetX87Top(); + auto a = _LoadContextIndexed(top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + auto result = _F80Round(a); + + // Write to ST[TOP] + _StoreContextIndexed(result, top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + +void OpDispatchBuilder::FXTRACT(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + auto orig_top = GetX87Top(); + auto top = _And(_Sub(orig_top, _Constant(1)), _Constant(7)); + SetX87Top(top); + + auto a = _LoadContextIndexed(orig_top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + auto exp = _F80XTRACT_EXP(a); + auto sig = _F80XTRACT_SIG(a); + + // Write to ST[TOP] + _StoreContextIndexed(exp, orig_top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + _StoreContextIndexed(sig, top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + +void OpDispatchBuilder::FNINIT(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + SetX87Top(_Constant(0)); +} + +template +void OpDispatchBuilder::FCOMI(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + auto top = GetX87Top(); + auto mask = _Constant(7); + + OrderedNode *arg{}; + OrderedNode *b{}; + + if (Op->Src[0].TypeNone.Type != 0) { + // Memory arg + arg = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1); + if (width == 16 || width == 32 || width == 64) { + if (Integer) { + b = _F80CVTToInt(arg, width / 8); + } + else { + b = _F80CVTTo(arg, width / 8); + } + } + } else { + // Implicit arg + auto offset = _Constant(Op->OP & 7); + arg = _And(_Add(top, offset), mask); + b = _LoadContextIndexed(arg, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + } + + auto a = _LoadContextIndexed(top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + OrderedNode *Res = _F80Cmp(a, b, + (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(HostFlag_CF, HostFlag_Unordered); + HostFlag_ZF = _Or(HostFlag_ZF, HostFlag_Unordered); + + if (whichflags == FCOMIFlags::FLAGS_X87) { + SetRFLAG(HostFlag_CF); + SetRFLAG(_Constant(0)); + SetRFLAG(HostFlag_Unordered); + SetRFLAG(HostFlag_ZF); + } + else { + SetRFLAG(HostFlag_CF); + SetRFLAG(HostFlag_ZF); + SetRFLAG(HostFlag_Unordered); + } + + if ((Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) != 0) { + top = _And(_Add(top, _Constant(1)), mask); + SetX87Top(top); + } +} + +void OpDispatchBuilder::FXCH(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + auto top = GetX87Top(); + OrderedNode* arg; + + auto mask = _Constant(7); + + // Implicit arg + auto offset = _Constant(Op->OP & 7); + arg = _And(_Add(top, offset), mask); + + auto a = _LoadContextIndexed(top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + auto b = _LoadContextIndexed(arg, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + // Write to ST[TOP] + _StoreContextIndexed(b, top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + _StoreContextIndexed(a, arg, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + +template +void OpDispatchBuilder::FST(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + auto top = GetX87Top(); + OrderedNode* arg; + + auto mask = _Constant(7); + + // Implicit arg + auto offset = _Constant(Op->OP & 7); + arg = _And(_Add(top, offset), mask); + + auto a = _LoadContextIndexed(top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + // Write to ST[TOP] + _StoreContextIndexed(a, arg, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + if (pop) { + top = _And(_Add(top, _Constant(1)), _Constant(7)); + SetX87Top(top); + } +} + +template +void OpDispatchBuilder::X87UnaryOp(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + auto top = GetX87Top(); + auto a = _LoadContextIndexed(top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + auto result = _F80Round(a); + // Overwrite the op + result.first->Header.Op = IROp; + + // Write to ST[TOP] + _StoreContextIndexed(result, top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + +template +void OpDispatchBuilder::X87BinaryOp(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + auto top = GetX87Top(); + + auto mask = _Constant(7); + OrderedNode *st1 = _And(_Add(top, _Constant(1)), mask); + + auto a = _LoadContextIndexed(top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + st1 = _LoadContextIndexed(st1, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + auto result = _F80Add(a, st1); + // Overwrite the op + result.first->Header.Op = IROp; + + // Write to ST[TOP] + _StoreContextIndexed(result, top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + +template +void OpDispatchBuilder::X87ModifySTP(OpcodeArgs) { + auto orig_top = GetX87Top(); + if (Inc) { + auto top = _And(_Add(orig_top, _Constant(1)), _Constant(7)); + SetX87Top(top); + } + else { + auto top = _And(_Sub(orig_top, _Constant(1)), _Constant(7)); + SetX87Top(top); + } +} + +void OpDispatchBuilder::X87SinCos(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + auto orig_top = GetX87Top(); + auto top = _And(_Sub(orig_top, _Constant(1)), _Constant(7)); + SetX87Top(top); + + auto a = _LoadContextIndexed(orig_top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + auto sin = _F80SIN(a); + auto cos = _F80COS(a); + + // Write to ST[TOP] + _StoreContextIndexed(sin, orig_top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + _StoreContextIndexed(cos, top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + +template +void OpDispatchBuilder::X87FYL2X(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + auto orig_top = GetX87Top(); + auto top = _And(_Add(orig_top, _Constant(1)), _Constant(7)); + SetX87Top(top); + + auto a = _LoadContextIndexed(orig_top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + OrderedNode *st1 = _LoadContextIndexed(top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + if (Plus1) { + auto low = _Constant(0x8000'0000'0000'0000); + auto high = _Constant(0b0'011'1111'1111'1111); + OrderedNode *data = _VCastFromGPR(16, 8, low); + data = _VInsGPR(16, 8, data, high, 1); + st1 = _F80Add(st1, data); + } + + auto result = _F80FYL2X(st1, a); + + // Write to ST[TOP] + _StoreContextIndexed(result, top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + +void OpDispatchBuilder::X87TAN(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + auto orig_top = GetX87Top(); + auto top = _And(_Sub(orig_top, _Constant(1)), _Constant(7)); + SetX87Top(top); + + auto a = _LoadContextIndexed(orig_top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + auto result = _F80TAN(a); + + auto low = _Constant(0x8000'0000'0000'0000); + auto high = _Constant(0b0'011'1111'1111'1111); + OrderedNode *data = _VCastFromGPR(16, 8, low); + data = _VInsGPR(16, 8, data, high, 1); + + // Write to ST[TOP] + _StoreContextIndexed(result, orig_top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + _StoreContextIndexed(data, top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + +void OpDispatchBuilder::X87ATAN(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + + auto orig_top = GetX87Top(); + auto top = _And(_Add(orig_top, _Constant(1)), _Constant(7)); + SetX87Top(top); + + auto a = _LoadContextIndexed(orig_top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + OrderedNode *st1 = _LoadContextIndexed(top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + auto result = _F80ATAN(st1, a); + + // Write to ST[TOP] + _StoreContextIndexed(result, top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + +void OpDispatchBuilder::X87LDENV(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + auto Size = GetSrcSize(Op); + OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1, false); + + OrderedNode *MemLocation = _Add(Mem, _Constant(Size * 1)); + auto NewFSW = _LoadMem(GPRClass, Size, MemLocation, Size); + + // Strip out the FSW information + auto Top = _Bfe(3, 11, NewFSW); + SetX87Top(Top); + + auto C0 = _Bfe(1, 8, NewFSW); + auto C1 = _Bfe(1, 9, NewFSW); + auto C2 = _Bfe(1, 10, NewFSW); + auto C3 = _Bfe(1, 14, NewFSW); + + SetRFLAG(C0); + SetRFLAG(C1); + SetRFLAG(C2); + SetRFLAG(C3); +} + +void OpDispatchBuilder::X87FNSTENV(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + // 14 bytes for 16bit + // 2 Bytes : FCW + // 2 Bytes : FSW + // 2 bytes : FTW + // 2 bytes : Instruction offset + // 2 bytes : Instruction CS selector + // 2 bytes : Data offset + // 2 bytes : Data selector + + // 28 bytes for 32bit + // 4 bytes : FCW + // 4 bytes : FSW + // 4 bytes : FTW + // 4 bytes : Instruction pointer + // 2 bytes : instruction pointer selector + // 2 bytes : Opcode + // 4 bytes : data pointer offset + // 4 bytes : data pointer selector + + auto Size = GetDstSize(Op); + OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, -1, false); + + { + // FCW store default + _StoreMem(GPRClass, Size, Mem, _Constant(0x37F), Size); + } + + { + OrderedNode *MemLocation = _Add(Mem, _Constant(Size * 1)); + // We must construct the FSW from our various bits + OrderedNode *FSW = _Constant(0); + auto Top = GetX87Top(); + FSW = _Or(FSW, _Lshl(Top, _Constant(11))); + + auto C0 = GetRFLAG(FEXCore::X86State::X87FLAG_C0_LOC); + auto C1 = GetRFLAG(FEXCore::X86State::X87FLAG_C1_LOC); + auto C2 = GetRFLAG(FEXCore::X86State::X87FLAG_C2_LOC); + auto C3 = GetRFLAG(FEXCore::X86State::X87FLAG_C3_LOC); + + FSW = _Or(FSW, _Lshl(C0, _Constant(8))); + FSW = _Or(FSW, _Lshl(C1, _Constant(9))); + FSW = _Or(FSW, _Lshl(C2, _Constant(10))); + FSW = _Or(FSW, _Lshl(C3, _Constant(14))); + _StoreMem(GPRClass, Size, MemLocation, FSW, Size); + } + + auto ZeroConst = _Constant(0); + + { + // FTW + OrderedNode *MemLocation = _Add(Mem, _Constant(Size * 2)); + _StoreMem(GPRClass, Size, MemLocation, ZeroConst, Size); + } + + { + // Instruction Offset + OrderedNode *MemLocation = _Add(Mem, _Constant(Size * 3)); + _StoreMem(GPRClass, Size, MemLocation, ZeroConst, Size); + } + + { + // Instruction CS selector (+ Opcode) + OrderedNode *MemLocation = _Add(Mem, _Constant(Size * 4)); + _StoreMem(GPRClass, Size, MemLocation, ZeroConst, Size); + } + + { + // Data pointer offset + OrderedNode *MemLocation = _Add(Mem, _Constant(Size * 5)); + _StoreMem(GPRClass, Size, MemLocation, ZeroConst, Size); + } + + { + // Data pointer selector + OrderedNode *MemLocation = _Add(Mem, _Constant(Size * 6)); + _StoreMem(GPRClass, Size, MemLocation, ZeroConst, Size); + } +} + +void OpDispatchBuilder::X87FSTCW(OpcodeArgs) { + StoreResult(GPRClass, Op, _Constant(0x37F), -1); +} + +void OpDispatchBuilder::X87LDSW(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + OrderedNode *NewFSW = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1); + // Strip out the FSW information + auto Top = _Bfe(3, 11, NewFSW); + SetX87Top(Top); + + auto C0 = _Bfe(1, 8, NewFSW); + auto C1 = _Bfe(1, 9, NewFSW); + auto C2 = _Bfe(1, 10, NewFSW); + auto C3 = _Bfe(1, 14, NewFSW); + + SetRFLAG(C0); + SetRFLAG(C1); + SetRFLAG(C2); + SetRFLAG(C3); +} + +void OpDispatchBuilder::X87FNSTSW(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + // We must construct the FSW from our various bits + OrderedNode *FSW = _Constant(0); + auto Top = GetX87Top(); + FSW = _Or(FSW, _Lshl(Top, _Constant(11))); + + auto C0 = GetRFLAG(FEXCore::X86State::X87FLAG_C0_LOC); + auto C1 = GetRFLAG(FEXCore::X86State::X87FLAG_C1_LOC); + auto C2 = GetRFLAG(FEXCore::X86State::X87FLAG_C2_LOC); + auto C3 = GetRFLAG(FEXCore::X86State::X87FLAG_C3_LOC); + + FSW = _Or(FSW, _Lshl(C0, _Constant(8))); + FSW = _Or(FSW, _Lshl(C1, _Constant(9))); + FSW = _Or(FSW, _Lshl(C2, _Constant(10))); + FSW = _Or(FSW, _Lshl(C3, _Constant(14))); + + StoreResult(GPRClass, Op, FSW, -1); +} + +void OpDispatchBuilder::X87FNSAVE(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + // 14 bytes for 16bit + // 2 Bytes : FCW + // 2 Bytes : FSW + // 2 bytes : FTW + // 2 bytes : Instruction offset + // 2 bytes : Instruction CS selector + // 2 bytes : Data offset + // 2 bytes : Data selector + + // 28 bytes for 32bit + // 4 bytes : FCW + // 4 bytes : FSW + // 4 bytes : FTW + // 4 bytes : Instruction pointer + // 2 bytes : instruction pointer selector + // 2 bytes : Opcode + // 4 bytes : data pointer offset + // 4 bytes : data pointer selector + + auto Size = GetDstSize(Op); + OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, -1, false); + + OrderedNode *Top = GetX87Top(); + { + // FCW store default + _StoreMem(GPRClass, Size, Mem, _Constant(0x37F), Size); + } + + { + OrderedNode *MemLocation = _Add(Mem, _Constant(Size * 1)); + // We must construct the FSW from our various bits + OrderedNode *FSW = _Constant(0); + FSW = _Or(FSW, _Lshl(Top, _Constant(11))); + + auto C0 = GetRFLAG(FEXCore::X86State::X87FLAG_C0_LOC); + auto C1 = GetRFLAG(FEXCore::X86State::X87FLAG_C1_LOC); + auto C2 = GetRFLAG(FEXCore::X86State::X87FLAG_C2_LOC); + auto C3 = GetRFLAG(FEXCore::X86State::X87FLAG_C3_LOC); + + FSW = _Or(FSW, _Lshl(C0, _Constant(8))); + FSW = _Or(FSW, _Lshl(C1, _Constant(9))); + FSW = _Or(FSW, _Lshl(C2, _Constant(10))); + FSW = _Or(FSW, _Lshl(C3, _Constant(14))); + _StoreMem(GPRClass, Size, MemLocation, FSW, Size); + } + + auto ZeroConst = _Constant(0); + + { + // FTW + OrderedNode *MemLocation = _Add(Mem, _Constant(Size * 2)); + _StoreMem(GPRClass, Size, MemLocation, ZeroConst, Size); + } + + { + // Instruction Offset + OrderedNode *MemLocation = _Add(Mem, _Constant(Size * 3)); + _StoreMem(GPRClass, Size, MemLocation, ZeroConst, Size); + } + + { + // Instruction CS selector (+ Opcode) + OrderedNode *MemLocation = _Add(Mem, _Constant(Size * 4)); + _StoreMem(GPRClass, Size, MemLocation, ZeroConst, Size); + } + + { + // Data pointer offset + OrderedNode *MemLocation = _Add(Mem, _Constant(Size * 5)); + _StoreMem(GPRClass, Size, MemLocation, ZeroConst, Size); + } + + { + // Data pointer selector + OrderedNode *MemLocation = _Add(Mem, _Constant(Size * 6)); + _StoreMem(GPRClass, Size, MemLocation, ZeroConst, Size); + } + + OrderedNode *ST0Location = _Add(Mem, _Constant(Size * 7)); + + auto OneConst = _Constant(1); + auto SevenConst = _Constant(7); + auto TenConst = _Constant(10); + for (int i = 0; i < 7; ++i) { + auto data = _LoadContextIndexed(Top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + _StoreMem(FPRClass, 16, ST0Location, data, 1); + ST0Location = _Add(ST0Location, TenConst); + Top = _And(_Add(Top, OneConst), SevenConst); + } + + // The final st(7) needs a bit of special handling here + auto data = _LoadContextIndexed(Top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + // ST7 broken in to two parts + // Lower 64bits [63:0] + // upper 16 bits [79:64] + _StoreMem(FPRClass, 8, ST0Location, data, 1); + ST0Location = _Add(ST0Location, _Constant(8)); + _VStoreMemElement(16, 2, ST0Location, data, 4, 1); +} + +void OpDispatchBuilder::X87FRSTOR(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + auto Size = GetSrcSize(Op); + OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1, false); + + OrderedNode *MemLocation = _Add(Mem, _Constant(Size * 1)); + auto NewFSW = _LoadMem(GPRClass, Size, MemLocation, Size); + + // Strip out the FSW information + OrderedNode *Top = _Bfe(3, 11, NewFSW); + SetX87Top(Top); + + auto C0 = _Bfe(1, 8, NewFSW); + auto C1 = _Bfe(1, 9, NewFSW); + auto C2 = _Bfe(1, 10, NewFSW); + auto C3 = _Bfe(1, 14, NewFSW); + + SetRFLAG(C0); + SetRFLAG(C1); + SetRFLAG(C2); + SetRFLAG(C3); + + OrderedNode *ST0Location = _Add(Mem, _Constant(Size * 7)); + + auto OneConst = _Constant(1); + auto SevenConst = _Constant(7); + auto TenConst = _Constant(10); + + auto low = _Constant(~0ULL); + auto high = _Constant(0xFFFF); + OrderedNode *Mask = _VCastFromGPR(16, 8, low); + Mask = _VInsGPR(16, 8, Mask, high, 1); + + for (int i = 0; i < 7; ++i) { + OrderedNode *Reg = _LoadMem(FPRClass, 16, ST0Location, 1); + // Mask off the top bits + Reg = _VAnd(16, 16, Reg, Mask); + + _StoreContextIndexed(Reg, Top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + + ST0Location = _Add(ST0Location, TenConst); + Top = _And(_Add(Top, OneConst), SevenConst); + } + + // The final st(7) needs a bit of special handling here + // ST7 broken in to two parts + // Lower 64bits [63:0] + // upper 16 bits [79:64] + + OrderedNode *Reg = _LoadMem(FPRClass, 8, ST0Location, 1); + ST0Location = _Add(ST0Location, _Constant(8)); + Reg = _VLoadMemElement(16, 2, ST0Location, Reg, 4, 1); + _StoreContextIndexed(Reg, Top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + +void OpDispatchBuilder::X87FXAM(OpcodeArgs) { + auto top = GetX87Top(); + auto a = _LoadContextIndexed(top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + OrderedNode *Result = _VExtractToGPR(16, 8, a, 1); + + // Extract the sign bit + Result = _Lshr(Result, _Constant(15)); + SetRFLAG(Result); + + // Claim this is a normal number + // We don't support anything else + auto ZeroConst = _Constant(0); + auto OneConst = _Constant(1); + SetRFLAG(ZeroConst); + SetRFLAG(OneConst); + SetRFLAG(ZeroConst); +} + +void OpDispatchBuilder::X87FCMOV(OpcodeArgs) { + Current_Header->ShouldInterpret = true; + enum CompareType { + COMPARE_ZERO, + COMPARE_NOTZERO, + }; + uint32_t FLAGMask{}; + CompareType Type = COMPARE_ZERO; + OrderedNode *SrcCond; + + auto ZeroConst = _Constant(0); + auto OneConst = _Constant(1); + + uint16_t Opcode = Op->OP & 0b1111'1111'1000; + switch (Opcode) { + case 0x3'C0: + FLAGMask = 1 << FEXCore::X86State::RFLAG_CF_LOC; + Type = COMPARE_NOTZERO; + break; + case 0x2'C0: + FLAGMask = 1 << FEXCore::X86State::RFLAG_CF_LOC; + Type = COMPARE_ZERO; + break; + case 0x2'C8: + FLAGMask = 1 << FEXCore::X86State::RFLAG_ZF_LOC; + Type = COMPARE_NOTZERO; + break; + case 0x3'C8: + FLAGMask = 1 << FEXCore::X86State::RFLAG_ZF_LOC; + Type = COMPARE_ZERO; + break; + case 0x2'D0: + FLAGMask = (1 << FEXCore::X86State::RFLAG_ZF_LOC) | (1 << FEXCore::X86State::RFLAG_CF_LOC); + Type = COMPARE_NOTZERO; + break; + case 0x3'D0: + FLAGMask = (1 << FEXCore::X86State::RFLAG_ZF_LOC) | (1 << FEXCore::X86State::RFLAG_CF_LOC); + Type = COMPARE_ZERO; + break; + case 0x2'D8: + FLAGMask = 1 << FEXCore::X86State::RFLAG_PF_LOC; + Type = COMPARE_NOTZERO; + break; + case 0x3'D8: + FLAGMask = 1 << FEXCore::X86State::RFLAG_PF_LOC; + Type = COMPARE_ZERO; + break; + default: + LogMan::Msg::A("Unhandled FCMOV op: 0x%x", Opcode); + break; + } + + auto MaskConst = _Constant(FLAGMask); + + auto RFLAG = GetPackedRFLAG(false); + + auto AndOp = _And(RFLAG, MaskConst); + switch (Type) { + case COMPARE_ZERO: { + SrcCond = _Select(FEXCore::IR::COND_EQ, + AndOp, ZeroConst, OneConst, ZeroConst); + break; + } + case COMPARE_NOTZERO: { + SrcCond = _Select(FEXCore::IR::COND_NEQ, + AndOp, ZeroConst, OneConst, ZeroConst); + break; + } + } + + SrcCond = _Sbfe(1, 0, SrcCond); + + OrderedNode *VecCond = _VCastFromGPR(16, 8, SrcCond); + VecCond = _VInsGPR(16, 8, VecCond, SrcCond, 1); + + auto top = GetX87Top(); + OrderedNode* arg; + + auto mask = _Constant(7); + + // Implicit arg + auto offset = _Constant(Op->OP & 7); + arg = _And(_Add(top, offset), mask); + + auto a = _LoadContextIndexed(top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + auto b = _LoadContextIndexed(arg, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); + auto Result = _VBSL(VecCond, b, a); + + // Write to ST[TOP] + _StoreContextIndexed(Result, top, 16, offsetof(FEXCore::Core::CPUState, mm[0][0]), 16, FPRClass); +} + void OpDispatchBuilder::FXSaveOp(OpcodeArgs) { OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, -1, false); @@ -5184,6 +6139,30 @@ void OpDispatchBuilder::FXSaveOp(OpcodeArgs) { // 16 | FDP[31:0] | FDS | | MXCSR | MXCSR_MASK| } + { + // FCW store default + _StoreMem(GPRClass, 2, Mem, _Constant(0x37F), 2); + } + + { + // We must construct the FSW from our various bits + OrderedNode *MemLocation = _Add(Mem, _Constant(2)); + OrderedNode *FSW = _Constant(0); + auto Top = GetX87Top(); + FSW = _Or(FSW, _Lshl(Top, _Constant(11))); + + auto C0 = GetRFLAG(FEXCore::X86State::X87FLAG_C0_LOC); + auto C1 = GetRFLAG(FEXCore::X86State::X87FLAG_C1_LOC); + auto C2 = GetRFLAG(FEXCore::X86State::X87FLAG_C2_LOC); + auto C3 = GetRFLAG(FEXCore::X86State::X87FLAG_C3_LOC); + + FSW = _Or(FSW, _Lshl(C0, _Constant(8))); + FSW = _Or(FSW, _Lshl(C1, _Constant(9))); + FSW = _Or(FSW, _Lshl(C2, _Constant(10))); + FSW = _Or(FSW, _Lshl(C3, _Constant(14))); + _StoreMem(GPRClass, 2, MemLocation, FSW, 2); + } + // BYTE | 0 1 | 2 3 | 4 | 5 | 6 7 | 8 9 | a b | c d | e f | // ------------------------------------------ // 32 | ST0/MM0 | @@ -5244,6 +6223,25 @@ void OpDispatchBuilder::FXSaveOp(OpcodeArgs) { void OpDispatchBuilder::FXRStoreOp(OpcodeArgs) { OrderedNode *Mem = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1, false); + { + OrderedNode *MemLocation = _Add(Mem, _Constant(2)); + auto NewFSW = _LoadMem(GPRClass, 2, MemLocation, 2); + + // Strip out the FSW information + auto Top = _Bfe(3, 11, NewFSW); + SetX87Top(Top); + + auto C0 = _Bfe(1, 8, NewFSW); + auto C1 = _Bfe(1, 9, NewFSW); + auto C2 = _Bfe(1, 10, NewFSW); + auto C3 = _Bfe(1, 14, NewFSW); + + SetRFLAG(C0); + SetRFLAG(C1); + SetRFLAG(C2); + SetRFLAG(C3); + } + for (unsigned i = 0; i < 8; ++i) { OrderedNode *MemLocation = _Add(Mem, _Constant(i * 16 + 32)); auto MMReg = _LoadMem(FPRClass, 16, MemLocation, 16); @@ -6136,27 +7134,345 @@ constexpr uint16_t PF_F2 = 3; #define OPDReg(op, reg) (((op - 0xD8) << 8) | (reg << 3)) #define OPD(op, modrmop) (((op - 0xD8) << 8) | modrmop) const std::vector> X87OpTable = { + {OPDReg(0xD8, 0) | 0x00, 8, &OpDispatchBuilder::FADD<32, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xD8, 0) | 0x40, 8, &OpDispatchBuilder::FADD<32, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xD8, 0) | 0x80, 8, &OpDispatchBuilder::FADD<32, false, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xD8, 1) | 0x00, 8, &OpDispatchBuilder::FMUL<32, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xD8, 1) | 0x40, 8, &OpDispatchBuilder::FMUL<32, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xD8, 1) | 0x80, 8, &OpDispatchBuilder::FMUL<32, false, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xD8, 2) | 0x00, 8, &OpDispatchBuilder::FCOMI<32, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + {OPDReg(0xD8, 2) | 0x40, 8, &OpDispatchBuilder::FCOMI<32, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + {OPDReg(0xD8, 2) | 0x80, 8, &OpDispatchBuilder::FCOMI<32, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + + {OPDReg(0xD8, 3) | 0x00, 8, &OpDispatchBuilder::FCOMI<32, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, + {OPDReg(0xD8, 3) | 0x40, 8, &OpDispatchBuilder::FCOMI<32, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, + {OPDReg(0xD8, 3) | 0x80, 8, &OpDispatchBuilder::FCOMI<32, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, + + {OPDReg(0xD8, 4) | 0x00, 8, &OpDispatchBuilder::FSUB<32, false, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xD8, 4) | 0x40, 8, &OpDispatchBuilder::FSUB<32, false, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xD8, 4) | 0x80, 8, &OpDispatchBuilder::FSUB<32, false, false, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xD8, 5) | 0x00, 8, &OpDispatchBuilder::FSUB<32, false, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xD8, 5) | 0x40, 8, &OpDispatchBuilder::FSUB<32, false, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xD8, 5) | 0x80, 8, &OpDispatchBuilder::FSUB<32, false, true, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xD8, 6) | 0x00, 8, &OpDispatchBuilder::FDIV<32, false, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xD8, 6) | 0x40, 8, &OpDispatchBuilder::FDIV<32, false, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xD8, 6) | 0x80, 8, &OpDispatchBuilder::FDIV<32, false, false, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xD8, 7) | 0x00, 8, &OpDispatchBuilder::FDIV<32, false, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xD8, 7) | 0x40, 8, &OpDispatchBuilder::FDIV<32, false, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xD8, 7) | 0x80, 8, &OpDispatchBuilder::FDIV<32, false, true, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPD(0xD8, 0xC0), 8, &OpDispatchBuilder::FADD<80, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPD(0xD8, 0xC8), 8, &OpDispatchBuilder::FMUL<80, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPD(0xD8, 0xD0), 8, &OpDispatchBuilder::FCOMI<80, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + {OPD(0xD8, 0xD8), 8, &OpDispatchBuilder::FCOMI<80, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, + {OPD(0xD8, 0xE0), 8, &OpDispatchBuilder::FSUB<80, false, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPD(0xD8, 0xE8), 8, &OpDispatchBuilder::FSUB<80, false, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPD(0xD8, 0xF0), 8, &OpDispatchBuilder::FDIV<80, false, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPD(0xD8, 0xF8), 8, &OpDispatchBuilder::FDIV<80, false, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xD9, 0) | 0x00, 8, &OpDispatchBuilder::FLD<32>}, {OPDReg(0xD9, 0) | 0x40, 8, &OpDispatchBuilder::FLD<32>}, {OPDReg(0xD9, 0) | 0x80, 8, &OpDispatchBuilder::FLD<32>}, + // 1 = Invalid + + {OPDReg(0xD9, 2) | 0x00, 8, &OpDispatchBuilder::FST<32, false>}, + {OPDReg(0xD9, 2) | 0x40, 8, &OpDispatchBuilder::FST<32, false>}, + {OPDReg(0xD9, 2) | 0x80, 8, &OpDispatchBuilder::FST<32, false>}, + + {OPDReg(0xD9, 3) | 0x00, 8, &OpDispatchBuilder::FST<32, true>}, + {OPDReg(0xD9, 3) | 0x40, 8, &OpDispatchBuilder::FST<32, true>}, + {OPDReg(0xD9, 3) | 0x80, 8, &OpDispatchBuilder::FST<32, true>}, + + {OPDReg(0xD9, 4) | 0x00, 8, &OpDispatchBuilder::X87LDENV}, + {OPDReg(0xD9, 4) | 0x40, 8, &OpDispatchBuilder::X87LDENV}, + {OPDReg(0xD9, 4) | 0x80, 8, &OpDispatchBuilder::X87LDENV}, + {OPDReg(0xD9, 5) | 0x00, 8, &OpDispatchBuilder::NOPOp}, // XXX: stubbed FLDCW {OPDReg(0xD9, 5) | 0x40, 8, &OpDispatchBuilder::NOPOp}, // XXX: stubbed FLDCW {OPDReg(0xD9, 5) | 0x80, 8, &OpDispatchBuilder::NOPOp}, // XXX: stubbed FLDCW - {OPDReg(0xD9, 7) | 0x00, 8, &OpDispatchBuilder::NOPOp}, // XXX: stubbed FNSTCW - {OPDReg(0xD9, 7) | 0x40, 8, &OpDispatchBuilder::NOPOp}, // XXX: stubbed FNSTCW - {OPDReg(0xD9, 7) | 0x80, 8, &OpDispatchBuilder::NOPOp}, // XXX: stubbed FNSTCW + {OPDReg(0xD9, 6) | 0x00, 8, &OpDispatchBuilder::X87FNSTENV}, + {OPDReg(0xD9, 6) | 0x40, 8, &OpDispatchBuilder::X87FNSTENV}, + {OPDReg(0xD9, 6) | 0x80, 8, &OpDispatchBuilder::X87FNSTENV}, + + {OPDReg(0xD9, 7) | 0x00, 8, &OpDispatchBuilder::X87FSTCW}, + {OPDReg(0xD9, 7) | 0x40, 8, &OpDispatchBuilder::X87FSTCW}, + {OPDReg(0xD9, 7) | 0x80, 8, &OpDispatchBuilder::X87FSTCW}, + + {OPD(0xD9, 0xC0), 8, &OpDispatchBuilder::FLD<80>}, + {OPD(0xD9, 0xC8), 8, &OpDispatchBuilder::FXCH}, + {OPD(0xD9, 0xD0), 1, &OpDispatchBuilder::NOPOp}, // FNOP + // D1 = Invalid + // D8 = Invalid + {OPD(0xD9, 0xE0), 1, &OpDispatchBuilder::FCHS}, + {OPD(0xD9, 0xE1), 1, &OpDispatchBuilder::FABS}, + // E2 = Invalid + {OPD(0xD9, 0xE4), 1, &OpDispatchBuilder::FTST}, + {OPD(0xD9, 0xE5), 1, &OpDispatchBuilder::X87FXAM}, + // E6 = Invalid + {OPD(0xD9, 0xE8), 1, &OpDispatchBuilder::FLD_Const<0x8000'0000'0000'0000, 0b0'011'1111'1111'1111>}, // 1.0 + {OPD(0xD9, 0xE9), 1, &OpDispatchBuilder::FLD_Const<0xD49A'784B'CD1B'8AFE, 0x4000>}, // log2l(10) + {OPD(0xD9, 0xEA), 1, &OpDispatchBuilder::FLD_Const<0xB8AA'3B29'5C17'F0BC, 0x3FFF>}, // log2l(e) + {OPD(0xD9, 0xEB), 1, &OpDispatchBuilder::FLD_Const<0xC90F'DAA2'2168'C235, 0x4000>}, // pi + {OPD(0xD9, 0xEC), 1, &OpDispatchBuilder::FLD_Const<0x9A20'9A84'FBCF'F799, 0x3FFD>}, // log10l(2) + {OPD(0xD9, 0xED), 1, &OpDispatchBuilder::FLD_Const<0xB172'17F7'D1CF'79AC, 0x3FFE>}, // log(2) + {OPD(0xD9, 0xEE), 1, &OpDispatchBuilder::FLD_Const<0, 0>}, // 0.0 + + // EF = Invalid + {OPD(0xD9, 0xF0), 1, &OpDispatchBuilder::X87UnaryOp}, + {OPD(0xD9, 0xF1), 1, &OpDispatchBuilder::X87FYL2X}, + {OPD(0xD9, 0xF2), 1, &OpDispatchBuilder::X87TAN}, + {OPD(0xD9, 0xF3), 1, &OpDispatchBuilder::X87ATAN}, + {OPD(0xD9, 0xF4), 1, &OpDispatchBuilder::FXTRACT}, + {OPD(0xD9, 0xF5), 1, &OpDispatchBuilder::X87BinaryOp}, + {OPD(0xD9, 0xF6), 1, &OpDispatchBuilder::X87ModifySTP}, + {OPD(0xD9, 0xF7), 1, &OpDispatchBuilder::X87ModifySTP}, + {OPD(0xD9, 0xF8), 1, &OpDispatchBuilder::X87BinaryOp}, + {OPD(0xD9, 0xF9), 1, &OpDispatchBuilder::X87FYL2X}, + {OPD(0xD9, 0xFA), 1, &OpDispatchBuilder::X87UnaryOp}, + {OPD(0xD9, 0xFB), 1, &OpDispatchBuilder::X87SinCos}, + {OPD(0xD9, 0xFC), 1, &OpDispatchBuilder::FRNDINT}, + {OPD(0xD9, 0xFD), 1, &OpDispatchBuilder::X87BinaryOp}, + {OPD(0xD9, 0xFE), 1, &OpDispatchBuilder::X87UnaryOp}, + {OPD(0xD9, 0xFF), 1, &OpDispatchBuilder::X87UnaryOp}, + + {OPDReg(0xDA, 0) | 0x00, 8, &OpDispatchBuilder::FADD<32, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDA, 0) | 0x40, 8, &OpDispatchBuilder::FADD<32, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDA, 0) | 0x80, 8, &OpDispatchBuilder::FADD<32, true, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xDA, 1) | 0x00, 8, &OpDispatchBuilder::FMUL<32, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDA, 1) | 0x40, 8, &OpDispatchBuilder::FMUL<32, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDA, 1) | 0x80, 8, &OpDispatchBuilder::FMUL<32, true, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xDA, 2) | 0x00, 8, &OpDispatchBuilder::FCOMI<32, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + {OPDReg(0xDA, 2) | 0x40, 8, &OpDispatchBuilder::FCOMI<32, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + {OPDReg(0xDA, 2) | 0x80, 8, &OpDispatchBuilder::FCOMI<32, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + + {OPDReg(0xDA, 3) | 0x00, 8, &OpDispatchBuilder::FCOMI<32, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, + {OPDReg(0xDA, 3) | 0x40, 8, &OpDispatchBuilder::FCOMI<32, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, + {OPDReg(0xDA, 3) | 0x80, 8, &OpDispatchBuilder::FCOMI<32, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, + + {OPDReg(0xDA, 4) | 0x00, 8, &OpDispatchBuilder::FSUB<32, true, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDA, 4) | 0x40, 8, &OpDispatchBuilder::FSUB<32, true, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDA, 4) | 0x80, 8, &OpDispatchBuilder::FSUB<32, true, false, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xDA, 5) | 0x00, 8, &OpDispatchBuilder::FSUB<32, true, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDA, 5) | 0x40, 8, &OpDispatchBuilder::FSUB<32, true, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDA, 5) | 0x80, 8, &OpDispatchBuilder::FSUB<32, true, true, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xDA, 6) | 0x00, 8, &OpDispatchBuilder::FDIV<32, true, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDA, 6) | 0x40, 8, &OpDispatchBuilder::FDIV<32, true, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDA, 6) | 0x80, 8, &OpDispatchBuilder::FDIV<32, true, false, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xDA, 7) | 0x00, 8, &OpDispatchBuilder::FDIV<32, true, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDA, 7) | 0x40, 8, &OpDispatchBuilder::FDIV<32, true, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDA, 7) | 0x80, 8, &OpDispatchBuilder::FDIV<32, true, true, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPD(0xDA, 0xC0), 8, &OpDispatchBuilder::X87FCMOV}, + {OPD(0xDA, 0xC8), 8, &OpDispatchBuilder::X87FCMOV}, + {OPD(0xDA, 0xD0), 8, &OpDispatchBuilder::X87FCMOV}, + {OPD(0xDA, 0xD8), 8, &OpDispatchBuilder::X87FCMOV}, + // E0 = Invalid + // E8 = Invalid + {OPD(0xDA, 0xE9), 1, &OpDispatchBuilder::FCOMI<80, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, + // EA = Invalid + // F0 = Invalid + // F8 = Invalid + + {OPDReg(0xDB, 0) | 0x00, 8, &OpDispatchBuilder::FILD<32>}, + {OPDReg(0xDB, 0) | 0x40, 8, &OpDispatchBuilder::FILD<32>}, + {OPDReg(0xDB, 0) | 0x80, 8, &OpDispatchBuilder::FILD<32>}, + + {OPDReg(0xDB, 1) | 0x00, 8, &OpDispatchBuilder::FIST<32, true>}, + {OPDReg(0xDB, 1) | 0x40, 8, &OpDispatchBuilder::FIST<32, true>}, + {OPDReg(0xDB, 1) | 0x80, 8, &OpDispatchBuilder::FIST<32, true>}, + + {OPDReg(0xDB, 2) | 0x00, 8, &OpDispatchBuilder::FIST<32, false>}, + {OPDReg(0xDB, 2) | 0x40, 8, &OpDispatchBuilder::FIST<32, false>}, + {OPDReg(0xDB, 2) | 0x80, 8, &OpDispatchBuilder::FIST<32, false>}, + + {OPDReg(0xDB, 3) | 0x00, 8, &OpDispatchBuilder::FIST<32, true>}, + {OPDReg(0xDB, 3) | 0x40, 8, &OpDispatchBuilder::FIST<32, true>}, + {OPDReg(0xDB, 3) | 0x80, 8, &OpDispatchBuilder::FIST<32, true>}, + + // 4 = Invalid + + {OPDReg(0xDB, 5) | 0x00, 8, &OpDispatchBuilder::FLD<80>}, + {OPDReg(0xDB, 5) | 0x40, 8, &OpDispatchBuilder::FLD<80>}, + {OPDReg(0xDB, 5) | 0x80, 8, &OpDispatchBuilder::FLD<80>}, + + // 6 = Invalid {OPDReg(0xDB, 7) | 0x00, 8, &OpDispatchBuilder::FST<80, true>}, {OPDReg(0xDB, 7) | 0x40, 8, &OpDispatchBuilder::FST<80, true>}, {OPDReg(0xDB, 7) | 0x80, 8, &OpDispatchBuilder::FST<80, true>}, + + {OPD(0xDB, 0xC0), 8, &OpDispatchBuilder::X87FCMOV}, + {OPD(0xDB, 0xC8), 8, &OpDispatchBuilder::X87FCMOV}, + {OPD(0xDB, 0xD0), 8, &OpDispatchBuilder::X87FCMOV}, + {OPD(0xDB, 0xD8), 8, &OpDispatchBuilder::X87FCMOV}, + // E0 = Invalid + {OPD(0xDB, 0xE2), 1, &OpDispatchBuilder::NOPOp}, // FNCLEX + {OPD(0xDB, 0xE3), 1, &OpDispatchBuilder::FNINIT}, + // E4 = Invalid + {OPD(0xDB, 0xE8), 8, &OpDispatchBuilder::FCOMI<80, false, OpDispatchBuilder::FCOMIFlags::FLAGS_RFLAGS, false>}, + {OPD(0xDB, 0xF0), 8, &OpDispatchBuilder::FCOMI<80, false, OpDispatchBuilder::FCOMIFlags::FLAGS_RFLAGS, false>}, + + // F8 = Invalid + + {OPDReg(0xDC, 0) | 0x00, 8, &OpDispatchBuilder::FADD<64, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDC, 0) | 0x40, 8, &OpDispatchBuilder::FADD<64, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDC, 0) | 0x80, 8, &OpDispatchBuilder::FADD<64, false, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xDC, 1) | 0x00, 8, &OpDispatchBuilder::FMUL<64, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDC, 1) | 0x40, 8, &OpDispatchBuilder::FMUL<64, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDC, 1) | 0x80, 8, &OpDispatchBuilder::FMUL<64, false, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xDC, 2) | 0x00, 8, &OpDispatchBuilder::FCOMI<64, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + {OPDReg(0xDC, 2) | 0x40, 8, &OpDispatchBuilder::FCOMI<64, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + {OPDReg(0xDC, 2) | 0x80, 8, &OpDispatchBuilder::FCOMI<64, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + + {OPDReg(0xDC, 3) | 0x00, 8, &OpDispatchBuilder::FCOMI<64, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, + {OPDReg(0xDC, 3) | 0x40, 8, &OpDispatchBuilder::FCOMI<64, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, + {OPDReg(0xDC, 3) | 0x80, 8, &OpDispatchBuilder::FCOMI<64, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, + + {OPDReg(0xDC, 4) | 0x00, 8, &OpDispatchBuilder::FSUB<64, false, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDC, 4) | 0x40, 8, &OpDispatchBuilder::FSUB<64, false, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDC, 4) | 0x80, 8, &OpDispatchBuilder::FSUB<64, false, false, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xDC, 5) | 0x00, 8, &OpDispatchBuilder::FSUB<64, false, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDC, 5) | 0x40, 8, &OpDispatchBuilder::FSUB<64, false, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDC, 5) | 0x80, 8, &OpDispatchBuilder::FSUB<64, false, true, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xDC, 6) | 0x00, 8, &OpDispatchBuilder::FDIV<64, false, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDC, 6) | 0x40, 8, &OpDispatchBuilder::FDIV<64, false, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDC, 6) | 0x80, 8, &OpDispatchBuilder::FDIV<64, false, false, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xDC, 7) | 0x00, 8, &OpDispatchBuilder::FDIV<64, false, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDC, 7) | 0x40, 8, &OpDispatchBuilder::FDIV<64, false, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDC, 7) | 0x80, 8, &OpDispatchBuilder::FDIV<64, false, true, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPD(0xDC, 0xC0), 8, &OpDispatchBuilder::FADD<80, false, OpDispatchBuilder::OpResult::RES_STI>}, + {OPD(0xDC, 0xC8), 8, &OpDispatchBuilder::FMUL<80, false, OpDispatchBuilder::OpResult::RES_STI>}, + {OPD(0xDC, 0xE0), 8, &OpDispatchBuilder::FSUB<80, false, false, OpDispatchBuilder::OpResult::RES_STI>}, + {OPD(0xDC, 0xE8), 8, &OpDispatchBuilder::FSUB<80, false, true, OpDispatchBuilder::OpResult::RES_STI>}, + {OPD(0xDC, 0xF0), 8, &OpDispatchBuilder::FDIV<80, false, false, OpDispatchBuilder::OpResult::RES_STI>}, + {OPD(0xDC, 0xF8), 8, &OpDispatchBuilder::FDIV<80, false, true, OpDispatchBuilder::OpResult::RES_STI>}, + {OPDReg(0xDD, 0) | 0x00, 8, &OpDispatchBuilder::FLD<64>}, {OPDReg(0xDD, 0) | 0x40, 8, &OpDispatchBuilder::FLD<64>}, {OPDReg(0xDD, 0) | 0x80, 8, &OpDispatchBuilder::FLD<64>}, - {OPD(0xDE, 0xC0), 8, &OpDispatchBuilder::FADD}, + {OPDReg(0xDD, 1) | 0x00, 8, &OpDispatchBuilder::FIST<64, true>}, + {OPDReg(0xDD, 1) | 0x40, 8, &OpDispatchBuilder::FIST<64, true>}, + {OPDReg(0xDD, 1) | 0x80, 8, &OpDispatchBuilder::FIST<64, true>}, + + {OPDReg(0xDD, 2) | 0x00, 8, &OpDispatchBuilder::FST<64, false>}, + {OPDReg(0xDD, 2) | 0x40, 8, &OpDispatchBuilder::FST<64, false>}, + {OPDReg(0xDD, 2) | 0x80, 8, &OpDispatchBuilder::FST<64, false>}, + + {OPDReg(0xDD, 3) | 0x00, 8, &OpDispatchBuilder::FST<64, true>}, + {OPDReg(0xDD, 3) | 0x40, 8, &OpDispatchBuilder::FST<64, true>}, + {OPDReg(0xDD, 3) | 0x80, 8, &OpDispatchBuilder::FST<64, true>}, + + {OPDReg(0xDD, 4) | 0x00, 8, &OpDispatchBuilder::X87FRSTOR}, + {OPDReg(0xDD, 4) | 0x40, 8, &OpDispatchBuilder::X87FRSTOR}, + {OPDReg(0xDD, 4) | 0x80, 8, &OpDispatchBuilder::X87FRSTOR}, + + // 5 = Invalid + {OPDReg(0xDD, 6) | 0x00, 8, &OpDispatchBuilder::X87FNSAVE}, + {OPDReg(0xDD, 6) | 0x40, 8, &OpDispatchBuilder::X87FNSAVE}, + {OPDReg(0xDD, 6) | 0x80, 8, &OpDispatchBuilder::X87FNSAVE}, + + {OPDReg(0xDD, 7) | 0x00, 8, &OpDispatchBuilder::X87FNSTSW}, + {OPDReg(0xDD, 7) | 0x40, 8, &OpDispatchBuilder::X87FNSTSW}, + {OPDReg(0xDD, 7) | 0x80, 8, &OpDispatchBuilder::X87FNSTSW}, + + {OPD(0xDD, 0xC0), 8, &OpDispatchBuilder::NOPOp}, // stubbed FFREE + {OPD(0xDD, 0xD0), 8, &OpDispatchBuilder::FST}, + {OPD(0xDD, 0xD8), 8, &OpDispatchBuilder::FST}, + + {OPD(0xDD, 0xE0), 8, &OpDispatchBuilder::FCOMI<80, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + {OPD(0xDD, 0xE8), 8, &OpDispatchBuilder::FCOMI<80, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, + + {OPDReg(0xDE, 0) | 0x00, 8, &OpDispatchBuilder::FADD<16, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDE, 0) | 0x40, 8, &OpDispatchBuilder::FADD<16, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDE, 0) | 0x80, 8, &OpDispatchBuilder::FADD<16, true, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xDE, 1) | 0x00, 8, &OpDispatchBuilder::FMUL<16, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDE, 1) | 0x40, 8, &OpDispatchBuilder::FMUL<16, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDE, 1) | 0x80, 8, &OpDispatchBuilder::FMUL<16, true, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xDE, 2) | 0x00, 8, &OpDispatchBuilder::FCOMI<16, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + {OPDReg(0xDE, 2) | 0x40, 8, &OpDispatchBuilder::FCOMI<16, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + {OPDReg(0xDE, 2) | 0x80, 8, &OpDispatchBuilder::FCOMI<16, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + + {OPDReg(0xDE, 3) | 0x00, 8, &OpDispatchBuilder::FCOMI<16, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, + {OPDReg(0xDE, 3) | 0x40, 8, &OpDispatchBuilder::FCOMI<16, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, + {OPDReg(0xDE, 3) | 0x80, 8, &OpDispatchBuilder::FCOMI<16, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, + + {OPDReg(0xDE, 4) | 0x00, 8, &OpDispatchBuilder::FSUB<16, true, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDE, 4) | 0x40, 8, &OpDispatchBuilder::FSUB<16, true, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDE, 4) | 0x80, 8, &OpDispatchBuilder::FSUB<16, true, false, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xDE, 5) | 0x00, 8, &OpDispatchBuilder::FSUB<16, true, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDE, 5) | 0x40, 8, &OpDispatchBuilder::FSUB<16, true, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDE, 5) | 0x80, 8, &OpDispatchBuilder::FSUB<16, true, true, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xDE, 6) | 0x00, 8, &OpDispatchBuilder::FDIV<16, true, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDE, 6) | 0x40, 8, &OpDispatchBuilder::FDIV<16, true, false, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDE, 6) | 0x80, 8, &OpDispatchBuilder::FDIV<16, true, false, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xDE, 7) | 0x00, 8, &OpDispatchBuilder::FDIV<16, true, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDE, 7) | 0x40, 8, &OpDispatchBuilder::FDIV<16, true, true, OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDE, 7) | 0x80, 8, &OpDispatchBuilder::FDIV<16, true, true, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPD(0xDE, 0xC0), 8, &OpDispatchBuilder::FADD<80, false, OpDispatchBuilder::OpResult::RES_STI>}, + {OPD(0xDE, 0xC8), 8, &OpDispatchBuilder::FMUL<80, false, OpDispatchBuilder::OpResult::RES_STI>}, + {OPD(0xDE, 0xD9), 1, &OpDispatchBuilder::FCOMI<80, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, true>}, + {OPD(0xDE, 0xE0), 8, &OpDispatchBuilder::FSUB<80, false, false, OpDispatchBuilder::OpResult::RES_STI>}, + {OPD(0xDE, 0xE8), 8, &OpDispatchBuilder::FSUB<80, false, true, OpDispatchBuilder::OpResult::RES_STI>}, + {OPD(0xDE, 0xF0), 8, &OpDispatchBuilder::FDIV<80, false, false, OpDispatchBuilder::OpResult::RES_STI>}, + {OPD(0xDE, 0xF8), 8, &OpDispatchBuilder::FDIV<80, false, true, OpDispatchBuilder::OpResult::RES_STI>}, + + {OPDReg(0xDF, 0) | 0x00, 8, &OpDispatchBuilder::FILD<16>}, + {OPDReg(0xDF, 0) | 0x40, 8, &OpDispatchBuilder::FILD<16>}, + {OPDReg(0xDF, 0) | 0x80, 8, &OpDispatchBuilder::FILD<16>}, + + {OPDReg(0xDF, 1) | 0x00, 8, &OpDispatchBuilder::FIST<16, true>}, + {OPDReg(0xDF, 1) | 0x40, 8, &OpDispatchBuilder::FIST<16, true>}, + {OPDReg(0xDF, 1) | 0x80, 8, &OpDispatchBuilder::FIST<16, true>}, + + {OPDReg(0xDF, 2) | 0x00, 8, &OpDispatchBuilder::FIST<16, false>}, + {OPDReg(0xDF, 2) | 0x40, 8, &OpDispatchBuilder::FIST<16, false>}, + {OPDReg(0xDF, 2) | 0x80, 8, &OpDispatchBuilder::FIST<16, false>}, + + {OPDReg(0xDF, 3) | 0x00, 8, &OpDispatchBuilder::FIST<16, true>}, + {OPDReg(0xDF, 3) | 0x40, 8, &OpDispatchBuilder::FIST<16, true>}, + {OPDReg(0xDF, 3) | 0x80, 8, &OpDispatchBuilder::FIST<16, true>}, + + // 4 = FBLD + + {OPDReg(0xDF, 5) | 0x00, 8, &OpDispatchBuilder::FILD<64>}, + {OPDReg(0xDF, 5) | 0x40, 8, &OpDispatchBuilder::FILD<64>}, + {OPDReg(0xDF, 5) | 0x80, 8, &OpDispatchBuilder::FILD<64>}, + + // 6 = FTSTB + + {OPDReg(0xDF, 7) | 0x00, 8, &OpDispatchBuilder::FIST<64, true>}, + {OPDReg(0xDF, 7) | 0x40, 8, &OpDispatchBuilder::FIST<64, true>}, + {OPDReg(0xDF, 7) | 0x80, 8, &OpDispatchBuilder::FIST<64, true>}, + + {OPD(0xDF, 0xE0), 8, &OpDispatchBuilder::X87FNSTSW}, + {OPD(0xDF, 0xE8), 8, &OpDispatchBuilder::FCOMI<80, false, OpDispatchBuilder::FCOMIFlags::FLAGS_RFLAGS, true>}, + {OPD(0xDF, 0xF0), 8, &OpDispatchBuilder::FCOMI<80, false, OpDispatchBuilder::FCOMIFlags::FLAGS_RFLAGS, true>}, }; #undef OPD #undef OPDReg diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 3dc1f3b9f..c308fa901 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -288,11 +288,70 @@ public: // X87 Ops template void FLD(OpcodeArgs); + template + void FLD_Const(OpcodeArgs); + + template + void FILD(OpcodeArgs); template void FST(OpcodeArgs); + template + void FST(OpcodeArgs); + + template + void FIST(OpcodeArgs); + + enum class OpResult { + RES_ST0, + RES_STI, + }; + template void FADD(OpcodeArgs); + template + void FMUL(OpcodeArgs); + template + void FDIV(OpcodeArgs); + template + void FSUB(OpcodeArgs); + void FCHS(OpcodeArgs); + void FABS(OpcodeArgs); + void FTST(OpcodeArgs); + void FRNDINT(OpcodeArgs); + void FXTRACT(OpcodeArgs); + void FNINIT(OpcodeArgs); + + template + void X87UnaryOp(OpcodeArgs); + template + void X87BinaryOp(OpcodeArgs); + template + void X87ModifySTP(OpcodeArgs); + void X87SinCos(OpcodeArgs); + template + void X87FYL2X(OpcodeArgs); + void X87TAN(OpcodeArgs); + void X87ATAN(OpcodeArgs); + void X87LDENV(OpcodeArgs); + void X87FNSTENV(OpcodeArgs); + void X87FSTCW(OpcodeArgs); + void X87LDSW(OpcodeArgs); + void X87FNSTSW(OpcodeArgs); + void X87FNSAVE(OpcodeArgs); + void X87FRSTOR(OpcodeArgs); + void X87FXAM(OpcodeArgs); + void X87FCMOV(OpcodeArgs); + + void FXCH(OpcodeArgs); + + enum class FCOMIFlags { + FLAGS_X87, + FLAGS_RFLAGS, + }; + template + void FCOMI(OpcodeArgs); + void FXSaveOp(OpcodeArgs); void FXRStoreOp(OpcodeArgs); diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/X87Tables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/X87Tables.cpp index 0c133081f..f3ed73bfe 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/X87Tables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/X87Tables.cpp @@ -8,14 +8,14 @@ void InitializeX87Tables() { #define OPDReg(op, reg) (((op - 0xD8) << 8) | (reg << 3)) const U16U8InfoStruct X87OpTable[] = { // 0xD8 - {OPDReg(0xD8, 0), 1, X86InstInfo{"FADD", TYPE_X87, FLAGS_NONE, 0, nullptr}}, + {OPDReg(0xD8, 0), 1, X86InstInfo{"FADD", TYPE_X87, FLAGS_MODRM, 0, nullptr}}, {OPDReg(0xD8, 1), 1, X86InstInfo{"FMUL", TYPE_X87, FLAGS_MODRM, 0, nullptr}}, - {OPDReg(0xD8, 2), 1, X86InstInfo{"FCOM", TYPE_X87, FLAGS_NONE, 0, nullptr}}, - {OPDReg(0xD8, 3), 1, X86InstInfo{"FCOMP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, - {OPDReg(0xD8, 4), 1, X86InstInfo{"FSUB", TYPE_X87, FLAGS_NONE, 0, nullptr}}, - {OPDReg(0xD8, 5), 1, X86InstInfo{"FSUBR", TYPE_X87, FLAGS_NONE, 0, nullptr}}, - {OPDReg(0xD8, 6), 1, X86InstInfo{"FDIV", TYPE_X87, FLAGS_NONE, 0, nullptr}}, - {OPDReg(0xD8, 7), 1, X86InstInfo{"FDIVR", TYPE_X87, FLAGS_NONE, 0, nullptr}}, + {OPDReg(0xD8, 2), 1, X86InstInfo{"FCOM", TYPE_X87, FLAGS_MODRM, 0, nullptr}}, + {OPDReg(0xD8, 3), 1, X86InstInfo{"FCOMP", TYPE_X87, FLAGS_MODRM | FLAGS_POP, 0, nullptr}}, + {OPDReg(0xD8, 4), 1, X86InstInfo{"FSUB", TYPE_X87, FLAGS_MODRM, 0, nullptr}}, + {OPDReg(0xD8, 5), 1, X86InstInfo{"FSUBR", TYPE_X87, FLAGS_MODRM, 0, nullptr}}, + {OPDReg(0xD8, 6), 1, X86InstInfo{"FDIV", TYPE_X87, FLAGS_MODRM, 0, nullptr}}, + {OPDReg(0xD8, 7), 1, X86InstInfo{"FDIVR", TYPE_X87, FLAGS_MODRM, 0, nullptr}}, // / 0 {OPD(0xD8, 0xC0), 8, X86InstInfo{"FADD", TYPE_X87, FLAGS_NONE, 0, nullptr}}, // / 1 @@ -35,7 +35,7 @@ void InitializeX87Tables() { // 0xD9 {OPDReg(0xD9, 0), 1, X86InstInfo{"FLD", TYPE_INST, FLAGS_MODRM, 0, nullptr}}, {OPDReg(0xD9, 1), 1, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, - {OPDReg(0xD9, 2), 1, X86InstInfo{"FST", TYPE_X87, FLAGS_NONE, 0, nullptr}}, + {OPDReg(0xD9, 2), 1, X86InstInfo{"FST", TYPE_X87, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0, nullptr}}, {OPDReg(0xD9, 3), 1, X86InstInfo{"FSTP", TYPE_X87, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0, nullptr}}, {OPDReg(0xD9, 4), 1, X86InstInfo{"FLDENV", TYPE_X87, FLAGS_MODRM, 0, nullptr}}, {OPDReg(0xD9, 5), 1, X86InstInfo{"FLDCW", TYPE_X87, GenFlagsSameSize(SIZE_16BIT) | FLAGS_MODRM, 0, nullptr}}, @@ -73,8 +73,8 @@ void InitializeX87Tables() { {OPD(0xD9, 0xF3), 1, X86InstInfo{"FPATAN", TYPE_X87, FLAGS_NONE, 0, nullptr}}, {OPD(0xD9, 0xF4), 1, X86InstInfo{"FXTRACT", TYPE_X87, FLAGS_NONE, 0, nullptr}}, {OPD(0xD9, 0xF5), 1, X86InstInfo{"FPREM1", TYPE_X87, FLAGS_NONE, 0, nullptr}}, - {OPD(0xD9, 0xF6), 1, X86InstInfo{"FDECSTP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, - {OPD(0xD9, 0xF7), 1, X86InstInfo{"FINCSTP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, + {OPD(0xD9, 0xF6), 1, X86InstInfo{"FDECSTP", TYPE_X87, FLAGS_POP, 0, nullptr}}, + {OPD(0xD9, 0xF7), 1, X86InstInfo{"FINCSTP", TYPE_X87, FLAGS_POP, 0, nullptr}}, // / 7 {OPD(0xD9, 0xF8), 1, X86InstInfo{"FPREM", TYPE_X87, FLAGS_NONE, 0, nullptr}}, {OPD(0xD9, 0xF9), 1, X86InstInfo{"FYL2XP1", TYPE_X87, FLAGS_NONE, 0, nullptr}}, @@ -105,7 +105,7 @@ void InitializeX87Tables() { {OPD(0xDA, 0xE0), 8, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, // / 5 {OPD(0xDA, 0xE8), 1, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, - {OPD(0xDA, 0xE9), 1, X86InstInfo{"FUCOMPP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, + {OPD(0xDA, 0xE9), 1, X86InstInfo{"FUCOMPP", TYPE_X87, FLAGS_POP, 0, nullptr}}, {OPD(0xDA, 0xEA), 6, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, // / 6 {OPD(0xDA, 0xF0), 8, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, @@ -113,13 +113,13 @@ void InitializeX87Tables() { {OPD(0xDA, 0xF8), 8, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, // 0xDB {OPDReg(0xDB, 0), 1, X86InstInfo{"FILD", TYPE_X87, FLAGS_MODRM, 0, nullptr}}, - {OPDReg(0xDB, 1), 1, X86InstInfo{"FISTTP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, - {OPDReg(0xDB, 2), 1, X86InstInfo{"FIST", TYPE_X87, FLAGS_NONE, 0, nullptr}}, - {OPDReg(0xDB, 3), 1, X86InstInfo{"FISTP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, + {OPDReg(0xDB, 1), 1, X86InstInfo{"FISTTP", TYPE_X87, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_POP, 0, nullptr}}, + {OPDReg(0xDB, 2), 1, X86InstInfo{"FIST", TYPE_X87, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0, nullptr}}, + {OPDReg(0xDB, 3), 1, X86InstInfo{"FISTP", TYPE_X87, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_POP, 0, nullptr}}, {OPDReg(0xDB, 4), 1, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, {OPDReg(0xDB, 5), 1, X86InstInfo{"FLD", TYPE_X87, FLAGS_MODRM, 0, nullptr}}, {OPDReg(0xDB, 6), 1, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, - {OPDReg(0xDB, 7), 1, X86InstInfo{"FSTP", TYPE_X87, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0, nullptr}}, + {OPDReg(0xDB, 7), 1, X86InstInfo{"FSTP", TYPE_X87, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_POP, 0, nullptr}}, // / 0 {OPD(0xDB, 0xC0), 8, X86InstInfo{"FCMOVNB", TYPE_X87, FLAGS_NONE, 0, nullptr}}, // / 1 @@ -166,10 +166,10 @@ void InitializeX87Tables() { {OPD(0xDC, 0xF8), 8, X86InstInfo{"FDIV", TYPE_X87, FLAGS_NONE, 0, nullptr}}, // 0xDD {OPDReg(0xDD, 0), 1, X86InstInfo{"FLD", TYPE_X87, FLAGS_MODRM, 0, nullptr}}, - {OPDReg(0xDD, 1), 1, X86InstInfo{"FISTTP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, - {OPDReg(0xDD, 2), 1, X86InstInfo{"FST", TYPE_X87, FLAGS_NONE, 0, nullptr}}, - {OPDReg(0xDD, 3), 1, X86InstInfo{"FSTP", TYPE_X87, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0, nullptr}}, - {OPDReg(0xDD, 4), 1, X86InstInfo{"FRSTOR", TYPE_X87, FLAGS_NONE, 0, nullptr}}, + {OPDReg(0xDD, 1), 1, X86InstInfo{"FISTTP", TYPE_X87, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_POP, 0, nullptr}}, + {OPDReg(0xDD, 2), 1, X86InstInfo{"FST", TYPE_X87, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0, nullptr}}, + {OPDReg(0xDD, 3), 1, X86InstInfo{"FSTP", TYPE_X87, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_POP, 0, nullptr}}, + {OPDReg(0xDD, 4), 1, X86InstInfo{"FRSTOR", TYPE_X87, FLAGS_MODRM, 0, nullptr}}, {OPDReg(0xDD, 5), 1, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, {OPDReg(0xDD, 6), 1, X86InstInfo{"FNSAVE", TYPE_X87, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0, nullptr}}, {OPDReg(0xDD, 7), 1, X86InstInfo{"FNSTSW", TYPE_X87, GenFlagsSameSize(SIZE_16BIT) | FLAGS_MODRM | FLAGS_SF_MOD_DST, 0, nullptr}}, @@ -178,13 +178,13 @@ void InitializeX87Tables() { // / 1 {OPD(0xDD, 0xC8), 8, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, // / 2 - {OPD(0xDD, 0xD0), 8, X86InstInfo{"FST", TYPE_INST, FLAGS_NONE, 0, nullptr}}, + {OPD(0xDD, 0xD0), 8, X86InstInfo{"FST", TYPE_INST, FLAGS_SF_MOD_DST, 0, nullptr}}, // / 3 - {OPD(0xDD, 0xD8), 8, X86InstInfo{"FSTP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, + {OPD(0xDD, 0xD8), 8, X86InstInfo{"FSTP", TYPE_X87, FLAGS_SF_MOD_DST | FLAGS_POP, 0, nullptr}}, // / 4 {OPD(0xDD, 0xE0), 8, X86InstInfo{"FUCOM", TYPE_X87, FLAGS_NONE, 0, nullptr}}, // / 5 - {OPD(0xDD, 0xE8), 8, X86InstInfo{"FUCOMP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, + {OPD(0xDD, 0xE8), 8, X86InstInfo{"FUCOMP", TYPE_X87, FLAGS_POP, 0, nullptr}}, // / 6 {OPD(0xDD, 0xF0), 8, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, // / 7 @@ -206,25 +206,25 @@ void InitializeX87Tables() { {OPD(0xDE, 0xD0), 8, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, // / 3 {OPD(0xDE, 0xD8), 1, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, - {OPD(0xDE, 0xD9), 1, X86InstInfo{"FCOMPP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, + {OPD(0xDE, 0xD9), 1, X86InstInfo{"FCOMPP", TYPE_X87, FLAGS_POP, 0, nullptr}}, {OPD(0xDE, 0xDA), 6, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, // / 4 - {OPD(0xDE, 0xE0), 8, X86InstInfo{"FSUBRP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, + {OPD(0xDE, 0xE0), 8, X86InstInfo{"FSUBRP", TYPE_X87, FLAGS_POP, 0, nullptr}}, // / 5 - {OPD(0xDE, 0xE8), 8, X86InstInfo{"FSUBP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, + {OPD(0xDE, 0xE8), 8, X86InstInfo{"FSUBP", TYPE_X87, FLAGS_POP, 0, nullptr}}, // / 6 - {OPD(0xDE, 0xF0), 8, X86InstInfo{"FDIVRP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, + {OPD(0xDE, 0xF0), 8, X86InstInfo{"FDIVRP", TYPE_X87, FLAGS_POP, 0, nullptr}}, // / 7 - {OPD(0xDE, 0xF8), 8, X86InstInfo{"FDIVP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, + {OPD(0xDE, 0xF8), 8, X86InstInfo{"FDIVP", TYPE_X87, FLAGS_POP, 0, nullptr}}, // 0xDF {OPDReg(0xDF, 0), 1, X86InstInfo{"FILD", TYPE_X87, FLAGS_MODRM, 0, nullptr}}, - {OPDReg(0xDF, 1), 1, X86InstInfo{"FISTTP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, - {OPDReg(0xDF, 2), 1, X86InstInfo{"FIST", TYPE_X87, FLAGS_NONE, 0, nullptr}}, - {OPDReg(0xDF, 3), 1, X86InstInfo{"FISTP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, - {OPDReg(0xDF, 4), 1, X86InstInfo{"FBLD", TYPE_X87, FLAGS_NONE, 0, nullptr}}, + {OPDReg(0xDF, 1), 1, X86InstInfo{"FISTTP", TYPE_X87, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_POP, 0, nullptr}}, + {OPDReg(0xDF, 2), 1, X86InstInfo{"FIST", TYPE_X87, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0, nullptr}}, + {OPDReg(0xDF, 3), 1, X86InstInfo{"FISTP", TYPE_X87, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_POP, 0, nullptr}}, + {OPDReg(0xDF, 4), 1, X86InstInfo{"FBLD", TYPE_X87, FLAGS_MODRM, 0, nullptr}}, {OPDReg(0xDF, 5), 1, X86InstInfo{"FILD", TYPE_X87, FLAGS_MODRM, 0, nullptr}}, - {OPDReg(0xDF, 6), 1, X86InstInfo{"FBSTP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, - {OPDReg(0xDF, 7), 1, X86InstInfo{"FISTP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, + {OPDReg(0xDF, 6), 1, X86InstInfo{"FBSTP", TYPE_X87, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_POP, 0, nullptr}}, + {OPDReg(0xDF, 7), 1, X86InstInfo{"FISTP", TYPE_X87, FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_POP, 0, nullptr}}, // / 0 {OPD(0xDF, 0xC0), 8, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, // / 1 @@ -237,9 +237,9 @@ void InitializeX87Tables() { {OPD(0xDF, 0xE0), 1, X86InstInfo{"FNSTSW", TYPE_INST, GenFlagsSameSize(SIZE_16BIT) | FLAGS_SF_DST_RAX, 0, nullptr}}, {OPD(0xDF, 0xE1), 7, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, // / 5 - {OPD(0xDF, 0xE8), 8, X86InstInfo{"FUCOMIP", TYPE_INST, FLAGS_NONE, 0, nullptr}}, + {OPD(0xDF, 0xE8), 8, X86InstInfo{"FUCOMIP", TYPE_INST, FLAGS_POP, 0, nullptr}}, // / 6 - {OPD(0xDF, 0xF0), 8, X86InstInfo{"FCOMIP", TYPE_X87, FLAGS_NONE, 0, nullptr}}, + {OPD(0xDF, 0xF0), 8, X86InstInfo{"FCOMIP", TYPE_X87, FLAGS_POP, 0, nullptr}}, // / 7 {OPD(0xDF, 0xF8), 8, X86InstInfo{"", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, }; diff --git a/External/FEXCore/Source/Interface/IR/IR.json b/External/FEXCore/Source/Interface/IR/IR.json index f22c87b62..cf63cdfc4 100644 --- a/External/FEXCore/Source/Interface/IR/IR.json +++ b/External/FEXCore/Source/Interface/IR/IR.json @@ -514,6 +514,47 @@ ] }, + "VLoadMemElement": { + "OpClass": "Memory", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "RegisterSize", + "NumElements": "RegisterSize / ElementSize", + "SSAArgs": "2", + "SSANames": [ + "Addr", + "Value" + ], + "HelperArgs": [ + "uint8_t", "RegisterSize", + "uint8_t", "ElementSize" + ], + "Args": [ + "uint8_t", "Align", + "uint8_t", "Index" + ] + }, + + "VStoreMemElement": { + "HasSideEffects": true, + "OpClass": "Memory", + "SSAArgs": "2", + "DestSize": "ElementSize", + "NumElements": "RegisterSize / ElementSize", + "SSANames": [ + "Addr", + "Value" + ], + "HelperArgs": [ + "uint8_t", "RegisterSize", + "uint8_t", "ElementSize" + ], + "Args": [ + "uint8_t", "Index", + "uint8_t", "Align" + ] + }, + "Add": { "Desc": [ "Integer Add" ], @@ -1792,6 +1833,24 @@ ] }, + "VBSL": { + "Desc": ["Does a vector bitwise select.", + "If the bit in the field is 1 then the corresponding bit is pulled from VectorTrue", + "If the bit in the field is 0 then the corresponding bit is pulled from VectorFalse" + ], + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "3", + "SSANames": [ + "VectorMask", + "VectorTrue", + "VectorFalse" + ] + }, + "VCMPEQ": { "OpClass": "Vector", "HasDest": true, @@ -2722,6 +2781,297 @@ ] }, + "F80Add": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "2", + "SSANames": [ + "X80Src1", + "X80Src2" + ] + }, + + "F80Sub": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "2", + "SSANames": [ + "X80Src1", + "X80Src2" + ] + }, + + "F80Mul": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "2", + "SSANames": [ + "X80Src1", + "X80Src2" + ] + }, + + "F80Div": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "2", + "SSANames": [ + "X80Src1", + "X80Src2" + ] + }, + + "F80ATAN": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "2", + "SSANames": [ + "X80Src1", + "X80Src2" + ] + }, + + "F80FPREM": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "2", + "SSANames": [ + "X80Src1", + "X80Src2" + ] + }, + + "F80FPREM1": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "2", + "SSANames": [ + "X80Src1", + "X80Src2" + ] + }, + + "F80SCALE": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "2", + "SSANames": [ + "X80Src1", + "X80Src2" + ] + }, + + "F80CVT": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "Size", + "NumElements": "1", + "SSAArgs": "1", + "SSANames": [ + "X80Src" + ], + "HelperArgs": [ + "uint8_t", "Size" + ] + }, + + "F80CVTInt": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "GPR", + "DestSize": "Size", + "NumElements": "1", + "SSAArgs": "1", + "SSANames": [ + "X80Src" + ], + "HelperArgs": [ + "uint8_t", "Size" + ] + }, + + "F80CVTTo": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "1", + "SSANames": [ + "X80Src" + ], + "Args": [ + "uint8_t", "Size" + ] + }, + + "F80CVTToInt": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "1", + "SSANames": [ + "X80Src" + ], + "Args": [ + "uint8_t", "Size" + ] + }, + + "F80Round": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "1", + "SSANames": [ + "X80Src" + ] + }, + + "F80F2XM1": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "1", + "SSANames": [ + "X80Src" + ] + }, + + "F80FYL2X": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "2", + "SSANames": [ + "X80Src1", + "X80Src2" + ] + }, + + "F80TAN": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "1", + "SSANames": [ + "X80Src" + ] + }, + + "F80SQRT": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "1", + "SSANames": [ + "X80Src" + ] + }, + + "F80SIN": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "1", + "SSANames": [ + "X80Src" + ] + }, + + "F80COS": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "1", + "SSANames": [ + "X80Src" + ] + }, + + "F80XTRACT_EXP": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "1", + "SSANames": [ + "X80Src" + ] + }, + + "F80XTRACT_SIG": { + "OpClass": "Vector", + "HasDest": true, + "DestClass": "FPR", + "DestSize": "16", + "NumElements": "1", + "SSAArgs": "1", + "SSANames": [ + "X80Src" + ] + }, + + "F80Cmp": { + "Desc": ["Does a scalar unordered compare and stores the asked for flags in to a GPR", + "Ordering flag result is true if either float input is NaN" + ], + "OpClass": "ALU", + "HasDest": true, + "DestClass": "GPR", + "DestSize": "4", + "SSAArgs": "2", + "SSANames": [ + "X80Src1", + "X80Src2" + ], + "Args": [ + "uint32_t", "Flags" + ] + }, + "Last": { "Last": true, "Args": [] diff --git a/External/FEXCore/Source/Interface/IR/Passes/IRValidation.cpp b/External/FEXCore/Source/Interface/IR/Passes/IRValidation.cpp index 9891d7884..6cc3607cc 100644 --- a/External/FEXCore/Source/Interface/IR/Passes/IRValidation.cpp +++ b/External/FEXCore/Source/Interface/IR/Passes/IRValidation.cpp @@ -42,7 +42,7 @@ bool IRValidation::Run(IREmitter *IREmit) { OrderedNode *BlockNode = HeaderOp->Blocks.GetNode(ListBegin); IR::RegisterAllocationPass * RAPass{}; - if (Manager->HasRAPass()) { + if (Manager->HasRAPass() && !HeaderOp->ShouldInterpret) { RAPass = Manager->GetRAPass(); } diff --git a/External/FEXCore/include/FEXCore/IR/IREmitter.h b/External/FEXCore/include/FEXCore/IR/IREmitter.h index cb69febe0..f790ebd66 100644 --- a/External/FEXCore/include/FEXCore/IR/IREmitter.h +++ b/External/FEXCore/include/FEXCore/IR/IREmitter.h @@ -64,15 +64,24 @@ friend class FEXCore::IR::PassManager; IRPair _Bfe(uint8_t Width, uint8_t lsb, OrderedNode *ssa0) { return _Bfe(ssa0, Width, lsb); } + IRPair _Sbfe(uint8_t Width, uint8_t lsb, OrderedNode *ssa0) { + return _Sbfe(ssa0, Width, lsb); + } IRPair _Bfi(uint8_t Width, uint8_t lsb, OrderedNode *ssa0, OrderedNode *ssa1) { return _Bfi(ssa0, ssa1, Width, lsb); } IRPair _StoreMem(FEXCore::IR::RegisterClassType Class, uint8_t Size, OrderedNode *ssa0, OrderedNode *ssa1, uint8_t Align = 1) { return _StoreMem(ssa0, ssa1, Size, Align, Class); } + IRPair _VStoreMemElement(uint8_t RegisterSize, uint8_t ElementSize, OrderedNode *ssa0, OrderedNode *ssa1, uint8_t Index, uint8_t Align = 1) { + return _VStoreMemElement(ssa0, ssa1, Index, Align, RegisterSize, ElementSize); + } IRPair _LoadMem(FEXCore::IR::RegisterClassType Class, uint8_t Size, OrderedNode *ssa0, uint8_t Align = 1) { return _LoadMem(ssa0, Size, Align, Class); } + IRPair _VLoadMemElement(uint8_t RegisterSize, uint8_t ElementSize, OrderedNode *ssa0, OrderedNode *ssa1, uint8_t Index, uint8_t Align = 1) { + return _VLoadMemElement(ssa0, ssa1, Index, Align, RegisterSize, ElementSize); + } IRPair _Select(uint8_t Cond, OrderedNode *ssa0, OrderedNode *ssa1, OrderedNode *ssa2, OrderedNode *ssa3) { return _Select(ssa0, ssa1, ssa2, ssa3, {Cond}); } diff --git a/Scripts/testharness_runner.py b/Scripts/testharness_runner.py index 6c977405d..de9d4a39f 100644 --- a/Scripts/testharness_runner.py +++ b/Scripts/testharness_runner.py @@ -2,25 +2,35 @@ import sys import subprocess -# Args: ... +# Args: ... -if (len(sys.argv) < 4): +if (len(sys.argv) < 5): sys.exit() known_failures = {} +disabled_tests = {} known_failures_file = sys.argv[1] +disabled_tests_file = sys.argv[2] -current_test = sys.argv[2] +current_test = sys.argv[3] # Open the known failures file and add it to a dictionary with open(known_failures_file) as kff: for line in kff: known_failures[line.strip()] = 1 -RunnerArgs = ["catchsegv", sys.argv[3]] +with open(disabled_tests_file) as dtf: + for line in dtf: + disabled_tests[line.strip()] = 1 + +RunnerArgs = ["catchsegv", sys.argv[4]] # Add the rest of the arguments -for i in range(len(sys.argv) - 4): - RunnerArgs.append(sys.argv[4 + i]) +for i in range(len(sys.argv) - 5): + RunnerArgs.append(sys.argv[5 + i]) + +if (disabled_tests.get(current_test)): + print("Skipping", current_test) + sys.exit(0) # Run the test and wait for it to end to get the result Process = subprocess.Popen(RunnerArgs) diff --git a/unittests/ASM/CMakeLists.txt b/unittests/ASM/CMakeLists.txt index 24967f6ab..bc248c5d6 100644 --- a/unittests/ASM/CMakeLists.txt +++ b/unittests/ASM/CMakeLists.txt @@ -55,6 +55,7 @@ foreach(ASM_SRC ${ASM_SOURCES}) add_test(NAME ${TEST_NAME} COMMAND "python3" "${CMAKE_SOURCE_DIR}/Scripts/testharness_runner.py" "${CMAKE_SOURCE_DIR}/unittests/ASM/Known_Failures" + "${CMAKE_SOURCE_DIR}/unittests/ASM/Disabled_Tests" "Test_${ASM_NAME}" "${CMAKE_BINARY_DIR}/Bin/TestHarnessRunner" ${ARGS_LIST} "${OUTPUT_NAME}" "${OUTPUT_CONFIG_NAME}") diff --git a/unittests/ASM/Disabled_Tests b/unittests/ASM/Disabled_Tests new file mode 100644 index 000000000..905af11af --- /dev/null +++ b/unittests/ASM/Disabled_Tests @@ -0,0 +1 @@ +Test_D9_F2.asm diff --git a/unittests/ASM/Known_Failures b/unittests/ASM/Known_Failures index 5ef292b3a..47e5a3310 100644 --- a/unittests/ASM/Known_Failures +++ b/unittests/ASM/Known_Failures @@ -1,4 +1,4 @@ Test_14_XX_02.asm Test_0F_2E.asm Test_0F_2F.asm -Test_fld.asm +Test_D9_FD.asm diff --git a/unittests/ASM/X87/D8_00.asm b/unittests/ASM/X87/D8_00.asm new file mode 100644 index 000000000..6275f11cb --- /dev/null +++ b/unittests/ASM/X87/D8_00.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0xc000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov rax, 0x40000000 ; 2.0 +mov [rdx + 8 * 1], rax + +fld qword [rdx + 8 * 0] +fadd dword [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/D8_01.asm b/unittests/ASM/X87/D8_01.asm new file mode 100644 index 000000000..3d0ef7779 --- /dev/null +++ b/unittests/ASM/X87/D8_01.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov rax, 0x40000000 ; 2.0 +mov [rdx + 8 * 1], rax + +fld qword [rdx + 8 * 0] +fmul dword [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/D8_04.asm b/unittests/ASM/X87/D8_04.asm new file mode 100644 index 000000000..a510b9940 --- /dev/null +++ b/unittests/ASM/X87/D8_04.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0xBFFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov rax, 0x40000000 ; 2.0 +mov [rdx + 8 * 1], rax + +fld qword [rdx + 8 * 0] +fsub dword [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/D8_05.asm b/unittests/ASM/X87/D8_05.asm new file mode 100644 index 000000000..22a72d313 --- /dev/null +++ b/unittests/ASM/X87/D8_05.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov rax, 0x40000000 ; 2.0 +mov [rdx + 8 * 1], rax + +fld qword [rdx + 8 * 0] +fsubr dword [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/D8_06.asm b/unittests/ASM/X87/D8_06.asm new file mode 100644 index 000000000..3f8617372 --- /dev/null +++ b/unittests/ASM/X87/D8_06.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x3FFE"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov rax, 0x40000000 ; 2.0 +mov [rdx + 8 * 1], rax + +fld qword [rdx + 8 * 0] +fdiv dword [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/D8_07.asm b/unittests/ASM/X87/D8_07.asm new file mode 100644 index 000000000..fb75dcf53 --- /dev/null +++ b/unittests/ASM/X87/D8_07.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov rax, 0x40000000 ; 2.0 +mov [rdx + 8 * 1], rax + +fld qword [rdx + 8 * 0] +fdivr dword [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/D8_C0.asm b/unittests/ASM/X87/D8_C0.asm new file mode 100644 index 000000000..57110fde9 --- /dev/null +++ b/unittests/ASM/X87/D8_C0.asm @@ -0,0 +1,26 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0xC000000000000000", "0x4000"], + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov rax, 0x4000000000000000 ; 2.0 +mov [rdx + 8 * 1], rax + +fld qword [rdx + 8 * 0] +fld qword [rdx + 8 * 1] + +; fadd st(0), st(i) +fadd st0, st1 + +hlt diff --git a/unittests/ASM/X87/D8_C8.asm b/unittests/ASM/X87/D8_C8.asm new file mode 100644 index 000000000..a2dedb4fe --- /dev/null +++ b/unittests/ASM/X87/D8_C8.asm @@ -0,0 +1,19 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x4001"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x4000000000000000 ; 2.0 +mov [rdx + 8 * 0], rax + +fld qword [rdx + 8 * 0] +fmul st0, st0 +hlt diff --git a/unittests/ASM/X87/D8_E0.asm b/unittests/ASM/X87/D8_E0.asm new file mode 100644 index 000000000..599f15f37 --- /dev/null +++ b/unittests/ASM/X87/D8_E0.asm @@ -0,0 +1,23 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0xBFFF"], + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x4000000000000000 ; 2.0 +mov [rdx + 8 * 0], rax +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 1], rax + +fld qword [rdx + 8 * 0] +fld qword [rdx + 8 * 1] +fsub st0, st1 +hlt diff --git a/unittests/ASM/X87/D8_E8.asm b/unittests/ASM/X87/D8_E8.asm new file mode 100644 index 000000000..b93357f4e --- /dev/null +++ b/unittests/ASM/X87/D8_E8.asm @@ -0,0 +1,23 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x4000000000000000 ; 2.0 +mov [rdx + 8 * 0], rax +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 1], rax + +fld qword [rdx + 8 * 0] +fld qword [rdx + 8 * 1] +fsubr st0, st1 +hlt diff --git a/unittests/ASM/X87/D8_F0.asm b/unittests/ASM/X87/D8_F0.asm new file mode 100644 index 000000000..a9224e5cc --- /dev/null +++ b/unittests/ASM/X87/D8_F0.asm @@ -0,0 +1,19 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x4000000000000000 ; 2.0 +mov [rdx + 8 * 0], rax + +fld qword [rdx + 8 * 0] +fdiv st0, st0 +hlt diff --git a/unittests/ASM/X87/D8_F8.asm b/unittests/ASM/X87/D8_F8.asm new file mode 100644 index 000000000..80e8249b0 --- /dev/null +++ b/unittests/ASM/X87/D8_F8.asm @@ -0,0 +1,24 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x3FFE"], + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x4000000000000000 ; 2.0 +mov [rdx + 8 * 0], rax +mov rax, 0x4010000000000000 ; 4.0 +mov [rdx + 8 * 1], rax + +fld qword [rdx + 8 * 0] +fld qword [rdx + 8 * 1] + +fdivr st0, st1 +hlt diff --git a/unittests/ASM/X87/D9_00.asm b/unittests/ASM/X87/D9_00.asm new file mode 100644 index 000000000..e51a7ab05 --- /dev/null +++ b/unittests/ASM/X87/D9_00.asm @@ -0,0 +1,18 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x3fff"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x3f800000 ; 1.0 +mov [rdx + 8 * 0], eax + +fld dword [rdx + 8 * 0] +hlt diff --git a/unittests/ASM/X87/D9_02.asm b/unittests/ASM/X87/D9_02.asm new file mode 100644 index 000000000..938463a19 --- /dev/null +++ b/unittests/ASM/X87/D9_02.asm @@ -0,0 +1,25 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0x3F800000", + "MM7": ["0x8000000000000000", "0x3fff"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x3f800000 ; 1.0 +mov [rdx + 8 * 0], eax +mov eax, 0x0 +mov [rdx + 8 * 1], eax + +fld dword [rdx + 8 * 0] +fst dword [rdx + 8 * 1] + +mov eax, [rdx + 8 * 1] + +hlt diff --git a/unittests/ASM/X87/D9_03.asm b/unittests/ASM/X87/D9_03.asm new file mode 100644 index 000000000..a7855f69b --- /dev/null +++ b/unittests/ASM/X87/D9_03.asm @@ -0,0 +1,28 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0x3F800000", + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x3f800000 ; 1.0 +mov [rdx + 8 * 0], eax +mov eax, 0x40000000 ; 2.0 +mov [rdx + 8 * 1], eax +mov eax, 0x0 ; 1.0 +mov [rdx + 8 * 2], eax + +fld dword [rdx + 8 * 0] +fstp dword [rdx + 8 * 2] +fld dword [rdx + 8 * 1] + +mov eax, [rdx + 8 * 2] + +hlt diff --git a/unittests/ASM/X87/D9_05.asm b/unittests/ASM/X87/D9_05.asm new file mode 100644 index 000000000..a0cd37fab --- /dev/null +++ b/unittests/ASM/X87/D9_05.asm @@ -0,0 +1,10 @@ +%ifdef CONFIG +{ +} +%endif + +mov rdx, 0xe0000000 +; Just to ensure execution +fldcw [rdx] + +hlt diff --git a/unittests/ASM/X87/D9_06.asm b/unittests/ASM/X87/D9_06.asm new file mode 100644 index 000000000..f5c064d1d --- /dev/null +++ b/unittests/ASM/X87/D9_06.asm @@ -0,0 +1,51 @@ +%ifdef CONFIG +{ + "RegData": { + "MM5": ["0x0000000000000000", "0x0000"], + "MM6": ["0x8000000000000000", "0x4000"], + "MM7": ["0x8000000000000000", "0x3fff"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x3f800000 ; 1.0 +mov [rdx + 8 * 0], eax +mov eax, 0x40000000 ; 2.0 +mov [rdx + 8 * 1], eax +mov eax, 0x40800000 ; 4.0 +mov [rdx + 8 * 2], eax + +fld dword [rdx + 8 * 0] +o16 fstenv [rdx + 8 * 3] +fld dword [rdx + 8 * 2] +o16 fldenv [rdx + 8 * 3] + +; This will overwrite the previous load +; This is since the control word is stored and reloaded +fld dword [rdx + 8 * 1] + +; 14 bytes for 16bit +; 2 Bytes : FCW +; 2 Bytes : FSW +; 2 bytes : FTW +; 2 bytes : Instruction offset +; 2 bytes : Instruction CS selector +; 2 bytes : Data offset +; 2 bytes : Data selector + +; 28 bytes for 32bit +; 4 bytes : FCW +; 4 bytes : FSW +; 4 bytes : FTW +; 4 bytes : Instruction pointer +; 2 bytes : instruction pointer selector +; 2 bytes : Opcode +; 4 bytes : data pointer offset +; 4 bytes : data pointer selector + +hlt diff --git a/unittests/ASM/X87/D9_06_2.asm b/unittests/ASM/X87/D9_06_2.asm new file mode 100644 index 000000000..0c2c1028c --- /dev/null +++ b/unittests/ASM/X87/D9_06_2.asm @@ -0,0 +1,51 @@ +%ifdef CONFIG +{ + "RegData": { + "MM5": ["0x0000000000000000", "0x0000"], + "MM6": ["0x8000000000000000", "0x4000"], + "MM7": ["0x8000000000000000", "0x3fff"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x3f800000 ; 1.0 +mov [rdx + 8 * 0], eax +mov eax, 0x40000000 ; 2.0 +mov [rdx + 8 * 1], eax +mov eax, 0x40800000 ; 4.0 +mov [rdx + 8 * 2], eax + +fld dword [rdx + 8 * 0] +o32 fstenv [rdx + 8 * 3] +fld dword [rdx + 8 * 2] +o32 fldenv [rdx + 8 * 3] + +; This will overwrite the previous load +; This is since the control word is stored and reloaded +fld dword [rdx + 8 * 1] + +; 14 bytes for 16bit +; 2 Bytes : FCW +; 2 Bytes : FSW +; 2 bytes : FTW +; 2 bytes : Instruction offset +; 2 bytes : Instruction CS selector +; 2 bytes : Data offset +; 2 bytes : Data selector + +; 28 bytes for 32bit +; 4 bytes : FCW +; 4 bytes : FSW +; 4 bytes : FTW +; 4 bytes : Instruction pointer +; 2 bytes : instruction pointer selector +; 2 bytes : Opcode +; 4 bytes : data pointer offset +; 4 bytes : data pointer selector + +hlt diff --git a/unittests/ASM/X87/D9_07.asm b/unittests/ASM/X87/D9_07.asm new file mode 100644 index 000000000..0fbcd52e6 --- /dev/null +++ b/unittests/ASM/X87/D9_07.asm @@ -0,0 +1,17 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0x37F" + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 +fnstcw [rdx] +mov eax, 0 +mov ax, [rdx] + +hlt diff --git a/unittests/ASM/X87/D9_C0.asm b/unittests/ASM/X87/D9_C0.asm new file mode 100644 index 000000000..718b8e023 --- /dev/null +++ b/unittests/ASM/X87/D9_C0.asm @@ -0,0 +1,30 @@ +%ifdef CONFIG +{ + "RegData": { + "MM5": ["0x8000000000000000", "0x4000"], + "MM6": ["0x8000000000000000", "0x4000"], + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] + +fld st1 + +hlt + +align 8 +data: + dt 1.0 + dq 0 +data2: + dt 2.0 + dq 0 diff --git a/unittests/ASM/X87/D9_C8.asm b/unittests/ASM/X87/D9_C8.asm new file mode 100644 index 000000000..98e20d1fd --- /dev/null +++ b/unittests/ASM/X87/D9_C8.asm @@ -0,0 +1,25 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x3f800000 ; 1.0 +mov [rdx + 8 * 0], eax +mov eax, 0x40000000 ; 2.0 +mov [rdx + 8 * 1], eax + +fld dword [rdx + 8 * 0] +fld dword [rdx + 8 * 1] + +fxch + +hlt diff --git a/unittests/ASM/X87/D9_D0.asm b/unittests/ASM/X87/D9_D0.asm new file mode 100644 index 000000000..3b9bf3c2a --- /dev/null +++ b/unittests/ASM/X87/D9_D0.asm @@ -0,0 +1,8 @@ +%ifdef CONFIG +{ +} +%endif + +; Just to ensure execution +fnop +hlt diff --git a/unittests/ASM/X87/D9_E0.asm b/unittests/ASM/X87/D9_E0.asm new file mode 100644 index 000000000..deb7f2a7e --- /dev/null +++ b/unittests/ASM/X87/D9_E0.asm @@ -0,0 +1,29 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0x8000000000000000", "0xC000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] +fchs + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] +fchs + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dt -1.0 + dq 0 diff --git a/unittests/ASM/X87/D9_E1.asm b/unittests/ASM/X87/D9_E1.asm new file mode 100644 index 000000000..63955b03c --- /dev/null +++ b/unittests/ASM/X87/D9_E1.asm @@ -0,0 +1,29 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] +fabs + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] +fabs + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dt -1.0 + dq 0 diff --git a/unittests/ASM/X87/D9_E8.asm b/unittests/ASM/X87/D9_E8.asm new file mode 100644 index 000000000..5dfdc775a --- /dev/null +++ b/unittests/ASM/X87/D9_E8.asm @@ -0,0 +1,11 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x3FFF"] + } +} +%endif + +fld1 + +hlt diff --git a/unittests/ASM/X87/D9_E9.asm b/unittests/ASM/X87/D9_E9.asm new file mode 100644 index 000000000..ef5d32117 --- /dev/null +++ b/unittests/ASM/X87/D9_E9.asm @@ -0,0 +1,11 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0xD49A784BCD1B8AFE", "0x4000"] + } +} +%endif + +fldl2t + +hlt diff --git a/unittests/ASM/X87/D9_EA.asm b/unittests/ASM/X87/D9_EA.asm new file mode 100644 index 000000000..7a8a352ad --- /dev/null +++ b/unittests/ASM/X87/D9_EA.asm @@ -0,0 +1,11 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0xB8AA3B295C17F0BC", "0x3FFF"] + } +} +%endif + +fldl2e + +hlt diff --git a/unittests/ASM/X87/D9_EB.asm b/unittests/ASM/X87/D9_EB.asm new file mode 100644 index 000000000..144af0fb0 --- /dev/null +++ b/unittests/ASM/X87/D9_EB.asm @@ -0,0 +1,11 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0xC90FDAA22168C235", "0x4000"] + } +} +%endif + +fldpi + +hlt diff --git a/unittests/ASM/X87/D9_EC.asm b/unittests/ASM/X87/D9_EC.asm new file mode 100644 index 000000000..a552c3e66 --- /dev/null +++ b/unittests/ASM/X87/D9_EC.asm @@ -0,0 +1,11 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x9A209A84FBCFF799", "0x3FFD"] + } +} +%endif + +fldlg2 + +hlt diff --git a/unittests/ASM/X87/D9_ED.asm b/unittests/ASM/X87/D9_ED.asm new file mode 100644 index 000000000..245cea384 --- /dev/null +++ b/unittests/ASM/X87/D9_ED.asm @@ -0,0 +1,11 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0xB17217F7D1CF79AC", "0x3FFE"] + } +} +%endif + +fldln2 + +hlt diff --git a/unittests/ASM/X87/D9_EE.asm b/unittests/ASM/X87/D9_EE.asm new file mode 100644 index 000000000..3375fc0f7 --- /dev/null +++ b/unittests/ASM/X87/D9_EE.asm @@ -0,0 +1,11 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0", "0"] + } +} +%endif + +fldz + +hlt diff --git a/unittests/ASM/X87/D9_F0.asm b/unittests/ASM/X87/D9_F0.asm new file mode 100644 index 000000000..0de8ba9de --- /dev/null +++ b/unittests/ASM/X87/D9_F0.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0xC000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] +f2xm1 + +hlt + +align 8 +data: + dt 2.0 + dq 0 diff --git a/unittests/ASM/X87/D9_F1.asm b/unittests/ASM/X87/D9_F1.asm new file mode 100644 index 000000000..3e4370755 --- /dev/null +++ b/unittests/ASM/X87/D9_F1.asm @@ -0,0 +1,31 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0x8000000000000000", "0x4002"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] + +fyl2x +fld1 + +hlt + +align 8 +data: + dt 16.0 + dq 0 + +data2: + dt 2.0 + dq 0 diff --git a/unittests/ASM/X87/D9_F2.asm b/unittests/ASM/X87/D9_F2.asm new file mode 100644 index 000000000..55c74e5f2 --- /dev/null +++ b/unittests/ASM/X87/D9_F2.asm @@ -0,0 +1,23 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0xC75922E5F71D2DC6", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +fptan + +hlt + +align 8 +data: + dt 1.0 + dq 0 diff --git a/unittests/ASM/X87/D9_F3.asm b/unittests/ASM/X87/D9_F3.asm new file mode 100644 index 000000000..b701bb9bf --- /dev/null +++ b/unittests/ASM/X87/D9_F3.asm @@ -0,0 +1,30 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0xC90FDAA22168C235", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] + +fpatan +fld1 + +hlt + +align 8 +data: + dt 7.0 + dq 0 +data2: + dt 0.0 + dq 0 diff --git a/unittests/ASM/X87/D9_F4.asm b/unittests/ASM/X87/D9_F4.asm new file mode 100644 index 000000000..3d8709138 --- /dev/null +++ b/unittests/ASM/X87/D9_F4.asm @@ -0,0 +1,23 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0xF000000000000000", "0xBFFF"], + "MM7": ["0xC000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +fxtract + +hlt + +align 8 +data: + dt -15.0 + dq 0 diff --git a/unittests/ASM/X87/D9_F5.asm b/unittests/ASM/X87/D9_F5.asm new file mode 100644 index 000000000..da8220e10 --- /dev/null +++ b/unittests/ASM/X87/D9_F5.asm @@ -0,0 +1,29 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0xE666666666666668", "0xBFFE"], + "MM7": ["0xC000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] + +fprem1 + +hlt + +align 8 +data: + dt 3.0 + dq 0 +data2: + dt 5.1 + dq 0 diff --git a/unittests/ASM/X87/D9_F6.asm b/unittests/ASM/X87/D9_F6.asm new file mode 100644 index 000000000..0bc22011d --- /dev/null +++ b/unittests/ASM/X87/D9_F6.asm @@ -0,0 +1,29 @@ +%ifdef CONFIG +{ + "RegData": { + "MM4": ["0x8000000000000000", "0x4001"], + "MM5": ["0x0000000000000000", "0x0000"], + "MM6": ["0x8000000000000000", "0x4000"], + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov rax, 0x4000000000000000 ; 2.0 +mov [rdx + 8 * 1], rax +mov rax, 0x4010000000000000 ; 4.0 +mov [rdx + 8 * 2], rax + +fld qword [rdx + 8 * 0] +fld qword [rdx + 8 * 1] +fdecstp +fld qword [rdx + 8 * 2] + +hlt diff --git a/unittests/ASM/X87/D9_F7.asm b/unittests/ASM/X87/D9_F7.asm new file mode 100644 index 000000000..8a03bdf60 --- /dev/null +++ b/unittests/ASM/X87/D9_F7.asm @@ -0,0 +1,27 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x4001"], + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov rax, 0x4000000000000000 ; 2.0 +mov [rdx + 8 * 1], rax +mov rax, 0x4010000000000000 ; 4.0 +mov [rdx + 8 * 2], rax + +fld qword [rdx + 8 * 0] +fld qword [rdx + 8 * 1] +fincstp +fld qword [rdx + 8 * 2] ; Overwrites previous value + +hlt diff --git a/unittests/ASM/X87/D9_F8.asm b/unittests/ASM/X87/D9_F8.asm new file mode 100644 index 000000000..df1cd0ca4 --- /dev/null +++ b/unittests/ASM/X87/D9_F8.asm @@ -0,0 +1,29 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8666666666666666", "0x4000"], + "MM7": ["0xC000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] + +fprem + +hlt + +align 8 +data: + dt 3.0 + dq 0 +data2: + dt 5.1 + dq 0 diff --git a/unittests/ASM/X87/D9_F9.asm b/unittests/ASM/X87/D9_F9.asm new file mode 100644 index 000000000..ec37d50e8 --- /dev/null +++ b/unittests/ASM/X87/D9_F9.asm @@ -0,0 +1,31 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0x8000000000000000", "0x4002"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] + +fyl2xp1 +fld1 + +hlt + +align 8 +data: + dt 15.0 + dq 0 + +data2: + dt 2.0 + dq 0 diff --git a/unittests/ASM/X87/D9_FA.asm b/unittests/ASM/X87/D9_FA.asm new file mode 100644 index 000000000..bed623acb --- /dev/null +++ b/unittests/ASM/X87/D9_FA.asm @@ -0,0 +1,22 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x4001"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +fsqrt + +hlt + +align 8 +data: + dt 16.0 + dq 0 diff --git a/unittests/ASM/X87/D9_FB.asm b/unittests/ASM/X87/D9_FB.asm new file mode 100644 index 000000000..23c00ca45 --- /dev/null +++ b/unittests/ASM/X87/D9_FB.asm @@ -0,0 +1,23 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8A51407DA8345C92", "0x3FFE"], + "MM7": ["0xD76AA47848677021", "0x3FFE"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +fsincos + +hlt + +align 8 +data: + dt 1.0 + dq 0 diff --git a/unittests/ASM/X87/D9_FC.asm b/unittests/ASM/X87/D9_FC.asm new file mode 100644 index 000000000..3fff74db9 --- /dev/null +++ b/unittests/ASM/X87/D9_FC.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x3fff"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x3f834241 ; 1.02546 +mov [rdx + 8 * 0], eax + +fld dword [rdx + 8 * 0] + +frndint + +hlt diff --git a/unittests/ASM/X87/D9_FD.asm b/unittests/ASM/X87/D9_FD.asm new file mode 100644 index 000000000..44e2d8361 --- /dev/null +++ b/unittests/ASM/X87/D9_FD.asm @@ -0,0 +1,30 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x4006"], + "MM7": ["0xB000000000000000", "0x4001"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +fscale + +hlt + +align 8 +data: + dt 4.0 + dq 0 + +data2: + dt 5.5 + dq 0 diff --git a/unittests/ASM/X87/D9_FE.asm b/unittests/ASM/X87/D9_FE.asm new file mode 100644 index 000000000..8ecbd8b90 --- /dev/null +++ b/unittests/ASM/X87/D9_FE.asm @@ -0,0 +1,22 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0xD76AA47848677021", "0x3FFE"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +fsin + +hlt + +align 8 +data: + dt 1.0 + dq 0 diff --git a/unittests/ASM/X87/D9_FF.asm b/unittests/ASM/X87/D9_FF.asm new file mode 100644 index 000000000..f812b5b6d --- /dev/null +++ b/unittests/ASM/X87/D9_FF.asm @@ -0,0 +1,22 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0xD51132BA9B902522", "0xBFFD"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +fcos + +hlt + +align 8 +data: + dt 2.0 + dq 0 diff --git a/unittests/ASM/X87/DA_00.asm b/unittests/ASM/X87/DA_00.asm new file mode 100644 index 000000000..5d64411eb --- /dev/null +++ b/unittests/ASM/X87/DA_00.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0xc000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov eax, 2 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +fiadd dword [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/DA_01.asm b/unittests/ASM/X87/DA_01.asm new file mode 100644 index 000000000..181c8e59a --- /dev/null +++ b/unittests/ASM/X87/DA_01.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov eax, 2 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +fimul dword [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/DA_04.asm b/unittests/ASM/X87/DA_04.asm new file mode 100644 index 000000000..940a234fa --- /dev/null +++ b/unittests/ASM/X87/DA_04.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0xBFFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov eax, 2 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +fisub dword [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/DA_05.asm b/unittests/ASM/X87/DA_05.asm new file mode 100644 index 000000000..14f4219fb --- /dev/null +++ b/unittests/ASM/X87/DA_05.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov eax, 2 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +fisubr dword [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/DA_06.asm b/unittests/ASM/X87/DA_06.asm new file mode 100644 index 000000000..0365eed41 --- /dev/null +++ b/unittests/ASM/X87/DA_06.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x3FFE"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov eax, 2 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +fidiv dword [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/DA_07.asm b/unittests/ASM/X87/DA_07.asm new file mode 100644 index 000000000..d2bb96bee --- /dev/null +++ b/unittests/ASM/X87/DA_07.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov eax, 2 +mov [rdx + 8 * 1], eax + +fld qword [rdx + 8 * 0] +fidivr dword [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/DA_C0.asm b/unittests/ASM/X87/DA_C0.asm new file mode 100644 index 000000000..fa1724e89 --- /dev/null +++ b/unittests/ASM/X87/DA_C0.asm @@ -0,0 +1,31 @@ +%ifdef CONFIG +{ + "RegData": { + "MM5": ["0x0000000000000000", "0x0000"], + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x3f800000 ; 1.0 +mov [rdx + 8 * 0], eax + +fld1 +fldz + +mov eax, 2 +cmp eax, 1 + +fcmovb st0, st1 + +fldz +cmp eax, 3 +fcmovb st0, st2 + +hlt diff --git a/unittests/ASM/X87/DA_C8.asm b/unittests/ASM/X87/DA_C8.asm new file mode 100644 index 000000000..8ab205816 --- /dev/null +++ b/unittests/ASM/X87/DA_C8.asm @@ -0,0 +1,31 @@ +%ifdef CONFIG +{ + "RegData": { + "MM5": ["0x0000000000000000", "0x0000"], + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x3f800000 ; 1.0 +mov [rdx + 8 * 0], eax + +fld1 +fldz + +mov eax, 1 +cmp eax, 1 + +fcmove st0, st1 + +fldz +cmp eax, 0 +fcmove st0, st2 + +hlt diff --git a/unittests/ASM/X87/DA_D0.asm b/unittests/ASM/X87/DA_D0.asm new file mode 100644 index 000000000..97b145847 --- /dev/null +++ b/unittests/ASM/X87/DA_D0.asm @@ -0,0 +1,31 @@ +%ifdef CONFIG +{ + "RegData": { + "MM5": ["0x0000000000000000", "0x0000"], + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x3f800000 ; 1.0 +mov [rdx + 8 * 0], eax + +fld1 +fldz + +mov eax, 2 +cmp eax, 2 + +fcmovbe st0, st1 + +fldz +cmp eax, 0 +fcmovbe st0, st2 + +hlt diff --git a/unittests/ASM/X87/DA_D8.asm b/unittests/ASM/X87/DA_D8.asm new file mode 100644 index 000000000..244291e7d --- /dev/null +++ b/unittests/ASM/X87/DA_D8.asm @@ -0,0 +1,31 @@ +%ifdef CONFIG +{ + "RegData": { + "MM5": ["0x8000000000000000", "0x3FFF"], + "MM6": ["0x0000000000000000", "0x0000"], + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x3f800000 ; 1.0 +mov [rdx + 8 * 0], eax + +fld1 +fldz + +mov eax, 0x0 +cmp eax, -1 + +fcmovu st0, st1 + +fldz +cmp eax, 1 +fcmovu st0, st2 + +hlt diff --git a/unittests/ASM/X87/DB_00.asm b/unittests/ASM/X87/DB_00.asm new file mode 100644 index 000000000..12d85898d --- /dev/null +++ b/unittests/ASM/X87/DB_00.asm @@ -0,0 +1,19 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x4009"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 1024 +mov [rdx + 8 * 0], eax + +fild dword [rdx + 8 * 0] + +hlt diff --git a/unittests/ASM/X87/DB_01.asm b/unittests/ASM/X87/DB_01.asm new file mode 100644 index 000000000..a7db4644e --- /dev/null +++ b/unittests/ASM/X87/DB_01.asm @@ -0,0 +1,28 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0x400", + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x44800000 ; 1024.0 +mov [rdx + 8 * 0], eax +mov eax, 0 +mov [rdx + 8 * 1], eax + +fld dword [rdx + 8 * 0] + +fisttp dword [rdx + 8 * 1] + +fld1 + +mov eax, [rdx + 8 * 1] + +hlt diff --git a/unittests/ASM/X87/DB_02.asm b/unittests/ASM/X87/DB_02.asm new file mode 100644 index 000000000..f21cb9585 --- /dev/null +++ b/unittests/ASM/X87/DB_02.asm @@ -0,0 +1,29 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0x400", + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0x8000000000000000", "0x4009"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x44800000 ; 1024.0 +mov [rdx + 8 * 0], eax +mov eax, 0 +mov [rdx + 8 * 1], eax + +fld dword [rdx + 8 * 0] + +fist dword [rdx + 8 * 1] + +fld1 + +mov eax, [rdx + 8 * 1] + +hlt diff --git a/unittests/ASM/X87/DB_03.asm b/unittests/ASM/X87/DB_03.asm new file mode 100644 index 000000000..593c8d9ae --- /dev/null +++ b/unittests/ASM/X87/DB_03.asm @@ -0,0 +1,28 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0x400", + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x44800000 ; 1024.0 +mov [rdx + 8 * 0], eax +mov eax, 0 +mov [rdx + 8 * 1], eax + +fld dword [rdx + 8 * 0] + +fistp dword [rdx + 8 * 1] + +fld1 + +mov eax, [rdx + 8 * 1] + +hlt diff --git a/unittests/ASM/X87/DB_05.asm b/unittests/ASM/X87/DB_05.asm new file mode 100644 index 000000000..6bcd69194 --- /dev/null +++ b/unittests/ASM/X87/DB_05.asm @@ -0,0 +1,20 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] + +fld tword [rdx + 8 * 0] +hlt + +align 8 +data: + dt 2.0 + dq 0 diff --git a/unittests/ASM/X87/DB_07.asm b/unittests/ASM/X87/DB_07.asm new file mode 100644 index 000000000..4c378e1e8 --- /dev/null +++ b/unittests/ASM/X87/DB_07.asm @@ -0,0 +1,27 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fstp tword [rdx + 8 * 0] +fld tword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dt 0.0 + dq 0 diff --git a/unittests/ASM/X87/DB_C0.asm b/unittests/ASM/X87/DB_C0.asm new file mode 100644 index 000000000..8e054a263 --- /dev/null +++ b/unittests/ASM/X87/DB_C0.asm @@ -0,0 +1,31 @@ +%ifdef CONFIG +{ + "RegData": { + "MM5": ["0x8000000000000000", "0x3FFF"], + "MM6": ["0x0000000000000000", "0x0000"], + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x3f800000 ; 1.0 +mov [rdx + 8 * 0], eax + +fld1 +fldz + +mov eax, 2 +cmp eax, 1 + +fcmovnb st0, st1 + +fldz +cmp eax, 3 +fcmovnb st0, st2 + +hlt diff --git a/unittests/ASM/X87/DB_C8.asm b/unittests/ASM/X87/DB_C8.asm new file mode 100644 index 000000000..a00d32ee1 --- /dev/null +++ b/unittests/ASM/X87/DB_C8.asm @@ -0,0 +1,31 @@ +%ifdef CONFIG +{ + "RegData": { + "MM5": ["0x8000000000000000", "0x3FFF"], + "MM6": ["0x0000000000000000", "0x0000"], + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x3f800000 ; 1.0 +mov [rdx + 8 * 0], eax + +fld1 +fldz + +mov eax, 1 +cmp eax, 1 + +fcmovne st0, st1 + +fldz +cmp eax, 0 +fcmovne st0, st2 + +hlt diff --git a/unittests/ASM/X87/DB_D0.asm b/unittests/ASM/X87/DB_D0.asm new file mode 100644 index 000000000..29ebfca8e --- /dev/null +++ b/unittests/ASM/X87/DB_D0.asm @@ -0,0 +1,31 @@ +%ifdef CONFIG +{ + "RegData": { + "MM5": ["0x8000000000000000", "0x3FFF"], + "MM6": ["0x0000000000000000", "0x0000"], + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x3f800000 ; 1.0 +mov [rdx + 8 * 0], eax + +fld1 +fldz + +mov eax, 2 +cmp eax, 2 + +fcmovnbe st0, st1 + +fldz +cmp eax, 0 +fcmovnbe st0, st2 + +hlt diff --git a/unittests/ASM/X87/DB_D8.asm b/unittests/ASM/X87/DB_D8.asm new file mode 100644 index 000000000..3db5556b5 --- /dev/null +++ b/unittests/ASM/X87/DB_D8.asm @@ -0,0 +1,31 @@ +%ifdef CONFIG +{ + "RegData": { + "MM5": ["0x0000000000000000", "0x0000"], + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x3f800000 ; 1.0 +mov [rdx + 8 * 0], eax + +fld1 +fldz + +mov eax, 0x0 +cmp eax, -1 + +fcmovnu st0, st1 + +fldz +cmp eax, 1 +fcmovnu st0, st2 + +hlt diff --git a/unittests/ASM/X87/DC_00.asm b/unittests/ASM/X87/DC_00.asm new file mode 100644 index 000000000..f41048a84 --- /dev/null +++ b/unittests/ASM/X87/DC_00.asm @@ -0,0 +1,25 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0xC000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fadd qword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 1.0 + dq 0 +data2: + dq 2.0 diff --git a/unittests/ASM/X87/DC_01.asm b/unittests/ASM/X87/DC_01.asm new file mode 100644 index 000000000..82be51ea6 --- /dev/null +++ b/unittests/ASM/X87/DC_01.asm @@ -0,0 +1,25 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fmul qword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 1.0 + dq 0 +data2: + dq 2.0 diff --git a/unittests/ASM/X87/DC_04.asm b/unittests/ASM/X87/DC_04.asm new file mode 100644 index 000000000..14cd41391 --- /dev/null +++ b/unittests/ASM/X87/DC_04.asm @@ -0,0 +1,25 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0xBFFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fsub qword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 1.0 + dq 0 +data2: + dq 2.0 diff --git a/unittests/ASM/X87/DC_05.asm b/unittests/ASM/X87/DC_05.asm new file mode 100644 index 000000000..683e303b9 --- /dev/null +++ b/unittests/ASM/X87/DC_05.asm @@ -0,0 +1,25 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fsubr qword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 1.0 + dq 0 +data2: + dq 2.0 diff --git a/unittests/ASM/X87/DC_06.asm b/unittests/ASM/X87/DC_06.asm new file mode 100644 index 000000000..8cdb855e6 --- /dev/null +++ b/unittests/ASM/X87/DC_06.asm @@ -0,0 +1,25 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x3FFE"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fdiv qword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 1.0 + dq 0 +data2: + dq 2.0 diff --git a/unittests/ASM/X87/DC_07.asm b/unittests/ASM/X87/DC_07.asm new file mode 100644 index 000000000..eaa8a2ff7 --- /dev/null +++ b/unittests/ASM/X87/DC_07.asm @@ -0,0 +1,25 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x4001"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fdivr qword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dq 8.0 diff --git a/unittests/ASM/X87/DC_C0.asm b/unittests/ASM/X87/DC_C0.asm new file mode 100644 index 000000000..f42e9bd77 --- /dev/null +++ b/unittests/ASM/X87/DC_C0.asm @@ -0,0 +1,30 @@ +%ifdef CONFIG +{ + "RegData": { + "MM5": ["0x8000000000000000", "0x4001"], + "MM6": ["0x8000000000000000", "0x4000"], + "MM7": ["0xA000000000000000", "0x4001"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov rax, 0x4000000000000000 ; 2.0 +mov [rdx + 8 * 1], rax +mov rax, 0x4010000000000000 ; 4.0 +mov [rdx + 8 * 2], rax + +fld qword [rdx + 8 * 0] +fld qword [rdx + 8 * 1] +fld qword [rdx + 8 * 2] + +; fadd st(i), st(0) +fadd st2, st0 + +hlt diff --git a/unittests/ASM/X87/DC_C8.asm b/unittests/ASM/X87/DC_C8.asm new file mode 100644 index 000000000..e5029d4b2 --- /dev/null +++ b/unittests/ASM/X87/DC_C8.asm @@ -0,0 +1,29 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x4001"], + "MM7": ["0x8000000000000000", "0x4002"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] + +fmul st1, st0 + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dt 4.0 + dq 0 diff --git a/unittests/ASM/X87/DC_E0.asm b/unittests/ASM/X87/DC_E0.asm new file mode 100644 index 000000000..f6a31b8a4 --- /dev/null +++ b/unittests/ASM/X87/DC_E0.asm @@ -0,0 +1,29 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x4000"], + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] + +fsubr st1, st0 + +hlt + +align 8 +data: + dt 1.0 + dq 0 +data2: + dt 2.0 + dq 0 diff --git a/unittests/ASM/X87/DC_E8.asm b/unittests/ASM/X87/DC_E8.asm new file mode 100644 index 000000000..159eeff59 --- /dev/null +++ b/unittests/ASM/X87/DC_E8.asm @@ -0,0 +1,29 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x4000"], + "MM7": ["0x8000000000000000", "0xBFFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] + +fsub st1, st0 + +hlt + +align 8 +data: + dt 1.0 + dq 0 +data2: + dt 2.0 + dq 0 diff --git a/unittests/ASM/X87/DC_F0.asm b/unittests/ASM/X87/DC_F0.asm new file mode 100644 index 000000000..7d5741e01 --- /dev/null +++ b/unittests/ASM/X87/DC_F0.asm @@ -0,0 +1,29 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0x8000000000000000", "0x3FFE"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] + +fdivr st1, st0 + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dt 1.0 + dq 0 diff --git a/unittests/ASM/X87/DC_F8.asm b/unittests/ASM/X87/DC_F8.asm new file mode 100644 index 000000000..7069383da --- /dev/null +++ b/unittests/ASM/X87/DC_F8.asm @@ -0,0 +1,29 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x4000"], + "MM7": ["0x8000000000000000", "0x4001"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] + +fdiv st1, st0 + +hlt + +align 8 +data: + dt 8.0 + dq 0 +data2: + dt 2.0 + dq 0 diff --git a/unittests/ASM/X87/DD_00.asm b/unittests/ASM/X87/DD_00.asm new file mode 100644 index 000000000..f2fe1a3ee --- /dev/null +++ b/unittests/ASM/X87/DD_00.asm @@ -0,0 +1,18 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x4000000000000000 ; 2.0 +mov [rdx + 8 * 0], rax + +fld qword [rdx + 8 * 0] +hlt diff --git a/unittests/ASM/X87/DD_01.asm b/unittests/ASM/X87/DD_01.asm new file mode 100644 index 000000000..d410bc9ca --- /dev/null +++ b/unittests/ASM/X87/DD_01.asm @@ -0,0 +1,35 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0x2", + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data3] +fisttp qword [rdx + 8 * 0] + +mov rax, [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dt 1.0 + dq 0 +data3: + dq 0 + dq 0 diff --git a/unittests/ASM/X87/DD_02.asm b/unittests/ASM/X87/DD_02.asm new file mode 100644 index 000000000..5d4558a9b --- /dev/null +++ b/unittests/ASM/X87/DD_02.asm @@ -0,0 +1,36 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0x4000000000000000", + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data3] +fst qword [rdx + 8 * 0] + +mov rax, [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dt 1.0 + dq 0 +data3: + dq 0 + dq 0 diff --git a/unittests/ASM/X87/DD_03.asm b/unittests/ASM/X87/DD_03.asm new file mode 100644 index 000000000..a184cc77a --- /dev/null +++ b/unittests/ASM/X87/DD_03.asm @@ -0,0 +1,35 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0x4000000000000000", + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data3] +fstp qword [rdx + 8 * 0] + +mov rax, [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dt 1.0 + dq 0 +data3: + dq 0 + dq 0 diff --git a/unittests/ASM/X87/DD_04.asm b/unittests/ASM/X87/DD_04.asm new file mode 100644 index 000000000..365dc845b --- /dev/null +++ b/unittests/ASM/X87/DD_04.asm @@ -0,0 +1,97 @@ +%ifdef CONFIG +{ + "RegData": { + "XMM0": ["0xc90fdaa22168c235", "0x4000"], + "XMM1": ["0x8000000000000000", "0x4005"], + "XMM2": ["0x8000000000000000", "0x4004"], + "XMM3": ["0x8000000000000000", "0x4003"], + "XMM4": ["0x8000000000000000", "0x4002"], + "XMM5": ["0x8000000000000000", "0x4001"], + "XMM6": ["0x8000000000000000", "0x4000"], + "XMM7": ["0x0000000000000000", "0x0000"], + "MM0": ["0xc90fdaa22168c235", "0x4000"], + "MM1": ["0x8000000000000000", "0x4005"], + "MM2": ["0x8000000000000000", "0x4004"], + "MM3": ["0x8000000000000000", "0x4003"], + "MM4": ["0x8000000000000000", "0x4002"], + "MM5": ["0x8000000000000000", "0x4001"], + "MM6": ["0x8000000000000000", "0x4000"], + "MM7": ["0x0000000000000000", "0x0000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 2 +mov [rdx + 2 * 1], rax +mov rax, 4 +mov [rdx + 2 * 2], rax +mov rax, 8 +mov [rdx + 2 * 3], rax +mov rax, 16 +mov [rdx + 2 * 4], rax +mov rax, 32 +mov [rdx + 2 * 5], rax +mov rax, 64 +mov [rdx + 2 * 6], rax + +fldz +fild word [rdx + 2 * 1] +fild word [rdx + 2 * 2] +fild word [rdx + 2 * 3] +fild word [rdx + 2 * 4] +fild word [rdx + 2 * 5] +fild word [rdx + 2 * 6] +fldpi + +o32 fnsave [rdx] + +fldpi +fldpi +fldpi +fldpi +fldpi +fldpi +fldpi +fldpi + +o32 frstor [rdx] + +movups xmm0, [rdx + (0x1C + 10 * 0)] +movups xmm1, [rdx + (0x1C + 10 * 1)] +movups xmm2, [rdx + (0x1C + 10 * 2)] +movups xmm3, [rdx + (0x1C + 10 * 3)] +movups xmm4, [rdx + (0x1C + 10 * 4)] +movups xmm5, [rdx + (0x1C + 10 * 5)] +movups xmm6, [rdx + (0x1C + 10 * 6)] +movups xmm7, [rdx + (0x1C + 10 * 7)] + +pslldq xmm0, 6 +psrldq xmm0, 6 + +pslldq xmm1, 6 +psrldq xmm1, 6 + +pslldq xmm2, 6 +psrldq xmm2, 6 + +pslldq xmm3, 6 +psrldq xmm3, 6 + +pslldq xmm4, 6 +psrldq xmm4, 6 + +pslldq xmm5, 6 +psrldq xmm5, 6 + +pslldq xmm6, 6 +psrldq xmm6, 6 + +pslldq xmm7, 6 +psrldq xmm7, 6 + +hlt diff --git a/unittests/ASM/X87/DD_04_2.asm b/unittests/ASM/X87/DD_04_2.asm new file mode 100644 index 000000000..3d79363ad --- /dev/null +++ b/unittests/ASM/X87/DD_04_2.asm @@ -0,0 +1,97 @@ +%ifdef CONFIG +{ + "RegData": { + "XMM0": ["0xc90fdaa22168c235", "0x4000"], + "XMM1": ["0x8000000000000000", "0x4005"], + "XMM2": ["0x8000000000000000", "0x4004"], + "XMM3": ["0x8000000000000000", "0x4003"], + "XMM4": ["0x8000000000000000", "0x4002"], + "XMM5": ["0x8000000000000000", "0x4001"], + "XMM6": ["0x8000000000000000", "0x4000"], + "XMM7": ["0x0000000000000000", "0x0000"], + "MM0": ["0xc90fdaa22168c235", "0x4000"], + "MM1": ["0x8000000000000000", "0x4005"], + "MM2": ["0x8000000000000000", "0x4004"], + "MM3": ["0x8000000000000000", "0x4003"], + "MM4": ["0x8000000000000000", "0x4002"], + "MM5": ["0x8000000000000000", "0x4001"], + "MM6": ["0x8000000000000000", "0x4000"], + "MM7": ["0x0000000000000000", "0x0000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 2 +mov [rdx + 2 * 1], rax +mov rax, 4 +mov [rdx + 2 * 2], rax +mov rax, 8 +mov [rdx + 2 * 3], rax +mov rax, 16 +mov [rdx + 2 * 4], rax +mov rax, 32 +mov [rdx + 2 * 5], rax +mov rax, 64 +mov [rdx + 2 * 6], rax + +fldz +fild word [rdx + 2 * 1] +fild word [rdx + 2 * 2] +fild word [rdx + 2 * 3] +fild word [rdx + 2 * 4] +fild word [rdx + 2 * 5] +fild word [rdx + 2 * 6] +fldpi + +o16 fnsave [rdx] + +fldpi +fldpi +fldpi +fldpi +fldpi +fldpi +fldpi +fldpi + +o16 frstor [rdx] + +movups xmm0, [rdx + (0xE + 10 * 0)] +movups xmm1, [rdx + (0xE + 10 * 1)] +movups xmm2, [rdx + (0xE + 10 * 2)] +movups xmm3, [rdx + (0xE + 10 * 3)] +movups xmm4, [rdx + (0xE + 10 * 4)] +movups xmm5, [rdx + (0xE + 10 * 5)] +movups xmm6, [rdx + (0xE + 10 * 6)] +movups xmm7, [rdx + (0xE + 10 * 7)] + +pslldq xmm0, 6 +psrldq xmm0, 6 + +pslldq xmm1, 6 +psrldq xmm1, 6 + +pslldq xmm2, 6 +psrldq xmm2, 6 + +pslldq xmm3, 6 +psrldq xmm3, 6 + +pslldq xmm4, 6 +psrldq xmm4, 6 + +pslldq xmm5, 6 +psrldq xmm5, 6 + +pslldq xmm6, 6 +psrldq xmm6, 6 + +pslldq xmm7, 6 +psrldq xmm7, 6 + +hlt diff --git a/unittests/ASM/X87/DD_07.asm b/unittests/ASM/X87/DD_07.asm new file mode 100644 index 000000000..8dc9aead7 --- /dev/null +++ b/unittests/ASM/X87/DD_07.asm @@ -0,0 +1,27 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0xFFFFFFFFFFFF3800", + "RBX": "0xFFFFFFFFFFFF0000" + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x3f800000 ; 1.0 +mov [rdx + 8 * 0], eax + +mov rax, -1 +mov rbx, -1 +fnstsw [rdx + 8 * 1] + +fld dword [rdx + 8 * 0] +fnstsw [rdx + 8 * 2] +mov ax, word [rdx + 8 * 2] +mov bx, word [rdx + 8 * 1] + +hlt diff --git a/unittests/ASM/X87/DD_C0.asm b/unittests/ASM/X87/DD_C0.asm new file mode 100644 index 000000000..fc6719ea5 --- /dev/null +++ b/unittests/ASM/X87/DD_C0.asm @@ -0,0 +1,15 @@ +%ifdef CONFIG +{ +} +%endif + +; Just to ensure execution +ffree st0 +ffree st1 +ffree st2 +ffree st3 +ffree st4 +ffree st5 +ffree st6 +ffree st7 +hlt diff --git a/unittests/ASM/X87/DD_D0.asm b/unittests/ASM/X87/DD_D0.asm new file mode 100644 index 000000000..43041a127 --- /dev/null +++ b/unittests/ASM/X87/DD_D0.asm @@ -0,0 +1,28 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] +fst st1 + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dt 1.0 + dq 0 diff --git a/unittests/ASM/X87/DD_D8.asm b/unittests/ASM/X87/DD_D8.asm new file mode 100644 index 000000000..7fb4fb27f --- /dev/null +++ b/unittests/ASM/X87/DD_D8.asm @@ -0,0 +1,35 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x4001"], + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] +fstp st1 + +lea rdx, [rel data3] +fld tword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dt 1.0 + dq 0 +data3: + dt 4.0 + dq 0 + diff --git a/unittests/ASM/X87/DE_00.asm b/unittests/ASM/X87/DE_00.asm new file mode 100644 index 000000000..2980c66bb --- /dev/null +++ b/unittests/ASM/X87/DE_00.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0xc000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov ax, 2 +mov [rdx + 8 * 1], ax + +fld qword [rdx + 8 * 0] +fiadd word [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/DE_01.asm b/unittests/ASM/X87/DE_01.asm new file mode 100644 index 000000000..7c2051214 --- /dev/null +++ b/unittests/ASM/X87/DE_01.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov ax, 2 +mov [rdx + 8 * 1], ax + +fld qword [rdx + 8 * 0] +fimul word [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/DE_04.asm b/unittests/ASM/X87/DE_04.asm new file mode 100644 index 000000000..842d28da5 --- /dev/null +++ b/unittests/ASM/X87/DE_04.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0xBFFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov ax, 2 +mov [rdx + 8 * 1], ax + +fld qword [rdx + 8 * 0] +fisub word [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/DE_05.asm b/unittests/ASM/X87/DE_05.asm new file mode 100644 index 000000000..9b76180b2 --- /dev/null +++ b/unittests/ASM/X87/DE_05.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov ax, 2 +mov [rdx + 8 * 1], ax + +fld qword [rdx + 8 * 0] +fisubr word [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/DE_06.asm b/unittests/ASM/X87/DE_06.asm new file mode 100644 index 000000000..dc820ac64 --- /dev/null +++ b/unittests/ASM/X87/DE_06.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x3FFE"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov ax, 2 +mov [rdx + 8 * 1], ax + +fld qword [rdx + 8 * 0] +fidiv word [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/DE_07.asm b/unittests/ASM/X87/DE_07.asm new file mode 100644 index 000000000..7b9450538 --- /dev/null +++ b/unittests/ASM/X87/DE_07.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x3ff0000000000000 ; 1.0 +mov [rdx + 8 * 0], rax +mov ax, 2 +mov [rdx + 8 * 1], ax + +fld qword [rdx + 8 * 0] +fidivr word [rdx + 8 * 1] +hlt diff --git a/unittests/ASM/X87/DE_C0.asm b/unittests/ASM/X87/DE_C0.asm new file mode 100644 index 000000000..37616df9b --- /dev/null +++ b/unittests/ASM/X87/DE_C0.asm @@ -0,0 +1,35 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x4001"], + "MM7": ["0xC000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] +faddp st1, st0 + +lea rdx, [rel data3] +fld tword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dt 1.0 + dq 0 +data3: + dt 4.0 + dq 0 + diff --git a/unittests/ASM/X87/DE_C8.asm b/unittests/ASM/X87/DE_C8.asm new file mode 100644 index 000000000..7bf3b9f8f --- /dev/null +++ b/unittests/ASM/X87/DE_C8.asm @@ -0,0 +1,34 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x4001"], + "MM7": ["0x8000000000000000", "0x4002"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] +fmulp st1, st0 + +lea rdx, [rel data3] +fld tword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dt 4.0 + dq 0 +data3: + dt 4.0 + dq 0 diff --git a/unittests/ASM/X87/DE_E0.asm b/unittests/ASM/X87/DE_E0.asm new file mode 100644 index 000000000..1c9fd4450 --- /dev/null +++ b/unittests/ASM/X87/DE_E0.asm @@ -0,0 +1,34 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x4001"], + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] +fsubrp st1, st0 + +lea rdx, [rel data3] +fld tword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dt 4.0 + dq 0 +data3: + dt 4.0 + dq 0 diff --git a/unittests/ASM/X87/DE_E8.asm b/unittests/ASM/X87/DE_E8.asm new file mode 100644 index 000000000..0ea6cc80e --- /dev/null +++ b/unittests/ASM/X87/DE_E8.asm @@ -0,0 +1,34 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x4001"], + "MM7": ["0x8000000000000000", "0xC000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] +fsubp st1, st0 + +lea rdx, [rel data3] +fld tword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dt 4.0 + dq 0 +data3: + dt 4.0 + dq 0 diff --git a/unittests/ASM/X87/DE_F0.asm b/unittests/ASM/X87/DE_F0.asm new file mode 100644 index 000000000..fd55c48b0 --- /dev/null +++ b/unittests/ASM/X87/DE_F0.asm @@ -0,0 +1,34 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x4001"], + "MM7": ["0x8000000000000000", "0x4000"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] +fdivrp st1, st0 + +lea rdx, [rel data3] +fld tword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dt 4.0 + dq 0 +data3: + dt 4.0 + dq 0 diff --git a/unittests/ASM/X87/DE_F8.asm b/unittests/ASM/X87/DE_F8.asm new file mode 100644 index 000000000..22ca157a0 --- /dev/null +++ b/unittests/ASM/X87/DE_F8.asm @@ -0,0 +1,37 @@ +%ifdef CONFIG +{ + "RegData": { + "MM6": ["0x8000000000000000", "0x4001"], + "MM7": ["0x8000000000000000", "0x3FFE"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] + +; fdivp 2.0, 4.0 +; == st1 = 2.0 / 4.0 +fdivp st1, st0 + +lea rdx, [rel data3] +fld tword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dt 4.0 + dq 0 +data3: + dt 4.0 + dq 0 diff --git a/unittests/ASM/X87/DF_00.asm b/unittests/ASM/X87/DF_00.asm new file mode 100644 index 000000000..d71dacf8e --- /dev/null +++ b/unittests/ASM/X87/DF_00.asm @@ -0,0 +1,21 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x4009"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 1024 +mov [rdx + 8 * 0], eax +mov eax, -1 +mov [rdx + 8 * 0 + 2], eax + +fild word [rdx + 8 * 0] + +hlt diff --git a/unittests/ASM/X87/DF_01.asm b/unittests/ASM/X87/DF_01.asm new file mode 100644 index 000000000..37213fd24 --- /dev/null +++ b/unittests/ASM/X87/DF_01.asm @@ -0,0 +1,35 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0x2", + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +lea rdx, [rel data] +fld tword [rdx + 8 * 0] + +lea rdx, [rel data3] +fisttp word [rdx + 8 * 0] + +mov ax, word [rdx + 8 * 0] + +lea rdx, [rel data2] +fld tword [rdx + 8 * 0] + +hlt + +align 8 +data: + dt 2.0 + dq 0 +data2: + dt 1.0 + dq 0 +data3: + dq -1 + dq -1 diff --git a/unittests/ASM/X87/DF_02.asm b/unittests/ASM/X87/DF_02.asm new file mode 100644 index 000000000..41c903a0b --- /dev/null +++ b/unittests/ASM/X87/DF_02.asm @@ -0,0 +1,30 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0x400", + "MM6": ["0x8000000000000000", "0x3FFF"], + "MM7": ["0x8000000000000000", "0x4009"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x44800000 ; 1024.0 +mov [rdx + 8 * 0], eax +mov eax, -1 +mov [rdx + 8 * 1], eax + +fld dword [rdx + 8 * 0] + +fist word [rdx + 8 * 1] + +fld1 + +mov eax, 0 +mov ax, word [rdx + 8 * 1] + +hlt diff --git a/unittests/ASM/X87/DF_03.asm b/unittests/ASM/X87/DF_03.asm new file mode 100644 index 000000000..aa950c7e8 --- /dev/null +++ b/unittests/ASM/X87/DF_03.asm @@ -0,0 +1,29 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0x400", + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x44800000 ; 1024.0 +mov [rdx + 8 * 0], eax +mov eax, -1 +mov [rdx + 8 * 1], eax + +fld dword [rdx + 8 * 0] + +fistp word [rdx + 8 * 1] + +fld1 + +mov eax, 0 +mov ax, word [rdx + 8 * 1] + +hlt diff --git a/unittests/ASM/X87/DF_05.asm b/unittests/ASM/X87/DF_05.asm new file mode 100644 index 000000000..1dd6b07ac --- /dev/null +++ b/unittests/ASM/X87/DF_05.asm @@ -0,0 +1,19 @@ +%ifdef CONFIG +{ + "RegData": { + "MM7": ["0x8000000000000000", "0x4009"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 1024 +mov [rdx + 8 * 0], rax + +fild qword [rdx + 8 * 0] + +hlt diff --git a/unittests/ASM/X87/DF_07.asm b/unittests/ASM/X87/DF_07.asm new file mode 100644 index 000000000..2ae3fca63 --- /dev/null +++ b/unittests/ASM/X87/DF_07.asm @@ -0,0 +1,28 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0x400", + "MM7": ["0x8000000000000000", "0x3FFF"] + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x44800000 ; 1024.0 +mov [rdx + 8 * 0], eax +mov rax, -1 +mov [rdx + 8 * 1], rax + +fld dword [rdx + 8 * 0] + +fistp qword [rdx + 8 * 1] + +fld1 + +mov rax, qword [rdx + 8 * 1] + +hlt diff --git a/unittests/ASM/X87/DF_E0.asm b/unittests/ASM/X87/DF_E0.asm new file mode 100644 index 000000000..cb38b67df --- /dev/null +++ b/unittests/ASM/X87/DF_E0.asm @@ -0,0 +1,26 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0xFFFFFFFFFFFF3800", + "RBX": "0xFFFFFFFFFFFF0000" + }, + "MemoryRegions": { + "0x100000000": "4096" + } +} +%endif + +mov rdx, 0xe0000000 + +mov eax, 0x3f800000 ; 1.0 +mov [rdx + 8 * 0], eax + +mov rax, -1 +mov rbx, -1 +fnstsw ax +mov bx, ax + +fld dword [rdx + 8 * 0] +fnstsw ax + +hlt diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt index c6923fe23..beaa48fd0 100644 --- a/unittests/IR/CMakeLists.txt +++ b/unittests/IR/CMakeLists.txt @@ -46,6 +46,7 @@ foreach(IR_SRC ${IR_SOURCES}) add_test(NAME ${TEST_NAME} COMMAND "python3" "${CMAKE_SOURCE_DIR}/Scripts/testharness_runner.py" "${CMAKE_SOURCE_DIR}/unittests/IR/Known_Failures" + "${CMAKE_SOURCE_DIR}/unittests/IR/Disabled_Tests" "Test_${IR_NAME}" "${CMAKE_BINARY_DIR}/Bin/IRLoader" ${ARGS_LIST} "${IR_SRC}" "${OUTPUT_CONFIG_NAME}") diff --git a/unittests/IR/Disabled_Tests b/unittests/IR/Disabled_Tests new file mode 100644 index 000000000..e69de29bb diff --git a/unittests/POSIX/Known_Failures b/unittests/POSIX/Known_Failures index 539721c30..a494384ae 100644 --- a/unittests/POSIX/Known_Failures +++ b/unittests/POSIX/Known_Failures @@ -8,7 +8,6 @@ conformance-interfaces-clock_settime-17-1.test conformance-interfaces-clock_settime-17-2.test conformance-interfaces-clock_settime-20-1.test conformance-interfaces-clock_settime-6-1.test -conformance-interfaces-difftime-1-1.test conformance-interfaces-kill-1-1.test conformance-interfaces-killpg-1-1.test conformance-interfaces-mlockall-8-1.test @@ -150,4 +149,4 @@ conformance-interfaces-sigwaitinfo-5-1.test conformance-interfaces-sigwaitinfo-6-1.test conformance-interfaces-sigwaitinfo-7-1.test conformance-interfaces-sigwaitinfo-8-1.test -conformance-interfaces-sigwaitinfo-9-1.test \ No newline at end of file +conformance-interfaces-sigwaitinfo-9-1.test