From 3759cbdb65135c60277e0995aacfefe97e99afa5 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 27 May 2020 19:07:16 -0700 Subject: [PATCH 1/5] Interpreter based x87 support! This implements support for 130 of the 132 x87 ops as interpreter fallbacks. The two missing ops are the BCD load and BCD store instructions and can be implemented another time. This allows us to no longer have to rely on a libstdc++ modification to handle their usage of long double. This instead works entirely through using `long double` directly in the interpreter. Which will either use real x87 on an x86 host. Or in the case of ARM devices, fall down glibc's long double soft float path. This doesn't necessarily need to be quick right now. It's more important to have the compatibility improvement from this. --- External/FEXCore/Source/Common/SoftFloat.h | 4 +- .../Core/Interpreter/InterpreterCore.cpp | 333 ++++ .../Interface/Core/LLVMJIT/LLVMCore.cpp | 39 +- .../Interface/Core/OpcodeDispatcher.cpp | 1436 ++++++++++++++++- .../Source/Interface/Core/OpcodeDispatcher.h | 59 + .../Interface/Core/X86Tables/X87Tables.cpp | 70 +- External/FEXCore/Source/Interface/IR/IR.json | 350 ++++ .../Interface/IR/Passes/IRValidation.cpp | 2 +- .../FEXCore/include/FEXCore/IR/IREmitter.h | 9 + 9 files changed, 2191 insertions(+), 111 deletions(-) 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}); } From 5efab1eff9c4cb42731236cd2726a663832e9820 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 19 May 2020 21:32:54 -0700 Subject: [PATCH 2/5] Updates list of known failures for unit tests x87 implementation has changed these --- unittests/ASM/Known_Failures | 2 +- unittests/POSIX/Known_Failures | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) 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/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 From 633e3ddb33139c295ae162717f7ae5b5b8a393d3 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 19 May 2020 21:42:18 -0700 Subject: [PATCH 3/5] x87 based unit tests! --- unittests/ASM/X87/D8_00.asm | 21 ++++++++ unittests/ASM/X87/D8_01.asm | 21 ++++++++ unittests/ASM/X87/D8_04.asm | 21 ++++++++ unittests/ASM/X87/D8_05.asm | 21 ++++++++ unittests/ASM/X87/D8_06.asm | 21 ++++++++ unittests/ASM/X87/D8_07.asm | 21 ++++++++ unittests/ASM/X87/D8_C0.asm | 26 ++++++++++ unittests/ASM/X87/D8_C8.asm | 19 +++++++ unittests/ASM/X87/D8_E0.asm | 23 +++++++++ unittests/ASM/X87/D8_E8.asm | 23 +++++++++ unittests/ASM/X87/D8_F0.asm | 19 +++++++ unittests/ASM/X87/D8_F8.asm | 24 +++++++++ unittests/ASM/X87/D9_00.asm | 18 +++++++ unittests/ASM/X87/D9_02.asm | 25 +++++++++ unittests/ASM/X87/D9_03.asm | 28 ++++++++++ unittests/ASM/X87/D9_05.asm | 10 ++++ unittests/ASM/X87/D9_06.asm | 51 ++++++++++++++++++ unittests/ASM/X87/D9_06_2.asm | 51 ++++++++++++++++++ unittests/ASM/X87/D9_07.asm | 17 ++++++ unittests/ASM/X87/D9_C0.asm | 30 +++++++++++ unittests/ASM/X87/D9_C8.asm | 25 +++++++++ unittests/ASM/X87/D9_D0.asm | 8 +++ unittests/ASM/X87/D9_E0.asm | 29 +++++++++++ unittests/ASM/X87/D9_E1.asm | 29 +++++++++++ unittests/ASM/X87/D9_E8.asm | 11 ++++ unittests/ASM/X87/D9_E9.asm | 11 ++++ unittests/ASM/X87/D9_EA.asm | 11 ++++ unittests/ASM/X87/D9_EB.asm | 11 ++++ unittests/ASM/X87/D9_EC.asm | 11 ++++ unittests/ASM/X87/D9_ED.asm | 11 ++++ unittests/ASM/X87/D9_EE.asm | 11 ++++ unittests/ASM/X87/D9_F0.asm | 21 ++++++++ unittests/ASM/X87/D9_F1.asm | 31 +++++++++++ unittests/ASM/X87/D9_F2.asm | 23 +++++++++ unittests/ASM/X87/D9_F3.asm | 30 +++++++++++ unittests/ASM/X87/D9_F4.asm | 23 +++++++++ unittests/ASM/X87/D9_F5.asm | 29 +++++++++++ unittests/ASM/X87/D9_F6.asm | 29 +++++++++++ unittests/ASM/X87/D9_F7.asm | 27 ++++++++++ unittests/ASM/X87/D9_F8.asm | 29 +++++++++++ unittests/ASM/X87/D9_F9.asm | 31 +++++++++++ unittests/ASM/X87/D9_FA.asm | 22 ++++++++ unittests/ASM/X87/D9_FB.asm | 23 +++++++++ unittests/ASM/X87/D9_FC.asm | 21 ++++++++ unittests/ASM/X87/D9_FD.asm | 30 +++++++++++ unittests/ASM/X87/D9_FE.asm | 22 ++++++++ unittests/ASM/X87/D9_FF.asm | 22 ++++++++ unittests/ASM/X87/DA_00.asm | 21 ++++++++ unittests/ASM/X87/DA_01.asm | 21 ++++++++ unittests/ASM/X87/DA_04.asm | 21 ++++++++ unittests/ASM/X87/DA_05.asm | 21 ++++++++ unittests/ASM/X87/DA_06.asm | 21 ++++++++ unittests/ASM/X87/DA_07.asm | 21 ++++++++ unittests/ASM/X87/DA_C0.asm | 31 +++++++++++ unittests/ASM/X87/DA_C8.asm | 31 +++++++++++ unittests/ASM/X87/DA_D0.asm | 31 +++++++++++ unittests/ASM/X87/DA_D8.asm | 31 +++++++++++ unittests/ASM/X87/DB_00.asm | 19 +++++++ unittests/ASM/X87/DB_01.asm | 28 ++++++++++ unittests/ASM/X87/DB_02.asm | 29 +++++++++++ unittests/ASM/X87/DB_03.asm | 28 ++++++++++ unittests/ASM/X87/DB_05.asm | 20 ++++++++ unittests/ASM/X87/DB_07.asm | 27 ++++++++++ unittests/ASM/X87/DB_C0.asm | 31 +++++++++++ unittests/ASM/X87/DB_C8.asm | 31 +++++++++++ unittests/ASM/X87/DB_D0.asm | 31 +++++++++++ unittests/ASM/X87/DB_D8.asm | 31 +++++++++++ unittests/ASM/X87/DC_00.asm | 25 +++++++++ unittests/ASM/X87/DC_01.asm | 25 +++++++++ unittests/ASM/X87/DC_04.asm | 25 +++++++++ unittests/ASM/X87/DC_05.asm | 25 +++++++++ unittests/ASM/X87/DC_06.asm | 25 +++++++++ unittests/ASM/X87/DC_07.asm | 25 +++++++++ unittests/ASM/X87/DC_C0.asm | 30 +++++++++++ unittests/ASM/X87/DC_C8.asm | 29 +++++++++++ unittests/ASM/X87/DC_E0.asm | 29 +++++++++++ unittests/ASM/X87/DC_E8.asm | 29 +++++++++++ unittests/ASM/X87/DC_F0.asm | 29 +++++++++++ unittests/ASM/X87/DC_F8.asm | 29 +++++++++++ unittests/ASM/X87/DD_00.asm | 18 +++++++ unittests/ASM/X87/DD_01.asm | 35 +++++++++++++ unittests/ASM/X87/DD_02.asm | 36 +++++++++++++ unittests/ASM/X87/DD_03.asm | 35 +++++++++++++ unittests/ASM/X87/DD_04.asm | 97 +++++++++++++++++++++++++++++++++++ unittests/ASM/X87/DD_04_2.asm | 97 +++++++++++++++++++++++++++++++++++ unittests/ASM/X87/DD_07.asm | 27 ++++++++++ unittests/ASM/X87/DD_C0.asm | 15 ++++++ unittests/ASM/X87/DD_D0.asm | 28 ++++++++++ unittests/ASM/X87/DD_D8.asm | 35 +++++++++++++ unittests/ASM/X87/DE_00.asm | 21 ++++++++ unittests/ASM/X87/DE_01.asm | 21 ++++++++ unittests/ASM/X87/DE_04.asm | 21 ++++++++ unittests/ASM/X87/DE_05.asm | 21 ++++++++ unittests/ASM/X87/DE_06.asm | 21 ++++++++ unittests/ASM/X87/DE_07.asm | 21 ++++++++ unittests/ASM/X87/DE_C0.asm | 35 +++++++++++++ unittests/ASM/X87/DE_C8.asm | 34 ++++++++++++ unittests/ASM/X87/DE_E0.asm | 34 ++++++++++++ unittests/ASM/X87/DE_E8.asm | 34 ++++++++++++ unittests/ASM/X87/DE_F0.asm | 34 ++++++++++++ unittests/ASM/X87/DE_F8.asm | 37 +++++++++++++ unittests/ASM/X87/DF_00.asm | 21 ++++++++ unittests/ASM/X87/DF_01.asm | 35 +++++++++++++ unittests/ASM/X87/DF_02.asm | 30 +++++++++++ unittests/ASM/X87/DF_03.asm | 29 +++++++++++ unittests/ASM/X87/DF_05.asm | 19 +++++++ unittests/ASM/X87/DF_07.asm | 28 ++++++++++ unittests/ASM/X87/DF_E0.asm | 26 ++++++++++ 108 files changed, 2866 insertions(+) create mode 100644 unittests/ASM/X87/D8_00.asm create mode 100644 unittests/ASM/X87/D8_01.asm create mode 100644 unittests/ASM/X87/D8_04.asm create mode 100644 unittests/ASM/X87/D8_05.asm create mode 100644 unittests/ASM/X87/D8_06.asm create mode 100644 unittests/ASM/X87/D8_07.asm create mode 100644 unittests/ASM/X87/D8_C0.asm create mode 100644 unittests/ASM/X87/D8_C8.asm create mode 100644 unittests/ASM/X87/D8_E0.asm create mode 100644 unittests/ASM/X87/D8_E8.asm create mode 100644 unittests/ASM/X87/D8_F0.asm create mode 100644 unittests/ASM/X87/D8_F8.asm create mode 100644 unittests/ASM/X87/D9_00.asm create mode 100644 unittests/ASM/X87/D9_02.asm create mode 100644 unittests/ASM/X87/D9_03.asm create mode 100644 unittests/ASM/X87/D9_05.asm create mode 100644 unittests/ASM/X87/D9_06.asm create mode 100644 unittests/ASM/X87/D9_06_2.asm create mode 100644 unittests/ASM/X87/D9_07.asm create mode 100644 unittests/ASM/X87/D9_C0.asm create mode 100644 unittests/ASM/X87/D9_C8.asm create mode 100644 unittests/ASM/X87/D9_D0.asm create mode 100644 unittests/ASM/X87/D9_E0.asm create mode 100644 unittests/ASM/X87/D9_E1.asm create mode 100644 unittests/ASM/X87/D9_E8.asm create mode 100644 unittests/ASM/X87/D9_E9.asm create mode 100644 unittests/ASM/X87/D9_EA.asm create mode 100644 unittests/ASM/X87/D9_EB.asm create mode 100644 unittests/ASM/X87/D9_EC.asm create mode 100644 unittests/ASM/X87/D9_ED.asm create mode 100644 unittests/ASM/X87/D9_EE.asm create mode 100644 unittests/ASM/X87/D9_F0.asm create mode 100644 unittests/ASM/X87/D9_F1.asm create mode 100644 unittests/ASM/X87/D9_F2.asm create mode 100644 unittests/ASM/X87/D9_F3.asm create mode 100644 unittests/ASM/X87/D9_F4.asm create mode 100644 unittests/ASM/X87/D9_F5.asm create mode 100644 unittests/ASM/X87/D9_F6.asm create mode 100644 unittests/ASM/X87/D9_F7.asm create mode 100644 unittests/ASM/X87/D9_F8.asm create mode 100644 unittests/ASM/X87/D9_F9.asm create mode 100644 unittests/ASM/X87/D9_FA.asm create mode 100644 unittests/ASM/X87/D9_FB.asm create mode 100644 unittests/ASM/X87/D9_FC.asm create mode 100644 unittests/ASM/X87/D9_FD.asm create mode 100644 unittests/ASM/X87/D9_FE.asm create mode 100644 unittests/ASM/X87/D9_FF.asm create mode 100644 unittests/ASM/X87/DA_00.asm create mode 100644 unittests/ASM/X87/DA_01.asm create mode 100644 unittests/ASM/X87/DA_04.asm create mode 100644 unittests/ASM/X87/DA_05.asm create mode 100644 unittests/ASM/X87/DA_06.asm create mode 100644 unittests/ASM/X87/DA_07.asm create mode 100644 unittests/ASM/X87/DA_C0.asm create mode 100644 unittests/ASM/X87/DA_C8.asm create mode 100644 unittests/ASM/X87/DA_D0.asm create mode 100644 unittests/ASM/X87/DA_D8.asm create mode 100644 unittests/ASM/X87/DB_00.asm create mode 100644 unittests/ASM/X87/DB_01.asm create mode 100644 unittests/ASM/X87/DB_02.asm create mode 100644 unittests/ASM/X87/DB_03.asm create mode 100644 unittests/ASM/X87/DB_05.asm create mode 100644 unittests/ASM/X87/DB_07.asm create mode 100644 unittests/ASM/X87/DB_C0.asm create mode 100644 unittests/ASM/X87/DB_C8.asm create mode 100644 unittests/ASM/X87/DB_D0.asm create mode 100644 unittests/ASM/X87/DB_D8.asm create mode 100644 unittests/ASM/X87/DC_00.asm create mode 100644 unittests/ASM/X87/DC_01.asm create mode 100644 unittests/ASM/X87/DC_04.asm create mode 100644 unittests/ASM/X87/DC_05.asm create mode 100644 unittests/ASM/X87/DC_06.asm create mode 100644 unittests/ASM/X87/DC_07.asm create mode 100644 unittests/ASM/X87/DC_C0.asm create mode 100644 unittests/ASM/X87/DC_C8.asm create mode 100644 unittests/ASM/X87/DC_E0.asm create mode 100644 unittests/ASM/X87/DC_E8.asm create mode 100644 unittests/ASM/X87/DC_F0.asm create mode 100644 unittests/ASM/X87/DC_F8.asm create mode 100644 unittests/ASM/X87/DD_00.asm create mode 100644 unittests/ASM/X87/DD_01.asm create mode 100644 unittests/ASM/X87/DD_02.asm create mode 100644 unittests/ASM/X87/DD_03.asm create mode 100644 unittests/ASM/X87/DD_04.asm create mode 100644 unittests/ASM/X87/DD_04_2.asm create mode 100644 unittests/ASM/X87/DD_07.asm create mode 100644 unittests/ASM/X87/DD_C0.asm create mode 100644 unittests/ASM/X87/DD_D0.asm create mode 100644 unittests/ASM/X87/DD_D8.asm create mode 100644 unittests/ASM/X87/DE_00.asm create mode 100644 unittests/ASM/X87/DE_01.asm create mode 100644 unittests/ASM/X87/DE_04.asm create mode 100644 unittests/ASM/X87/DE_05.asm create mode 100644 unittests/ASM/X87/DE_06.asm create mode 100644 unittests/ASM/X87/DE_07.asm create mode 100644 unittests/ASM/X87/DE_C0.asm create mode 100644 unittests/ASM/X87/DE_C8.asm create mode 100644 unittests/ASM/X87/DE_E0.asm create mode 100644 unittests/ASM/X87/DE_E8.asm create mode 100644 unittests/ASM/X87/DE_F0.asm create mode 100644 unittests/ASM/X87/DE_F8.asm create mode 100644 unittests/ASM/X87/DF_00.asm create mode 100644 unittests/ASM/X87/DF_01.asm create mode 100644 unittests/ASM/X87/DF_02.asm create mode 100644 unittests/ASM/X87/DF_03.asm create mode 100644 unittests/ASM/X87/DF_05.asm create mode 100644 unittests/ASM/X87/DF_07.asm create mode 100644 unittests/ASM/X87/DF_E0.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 From 2474ca14371909e62800212c8b2d2b98163e9d44 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 28 May 2020 15:09:51 -0700 Subject: [PATCH 4/5] Adds support for disabled tests in the IR and ASM runners --- Scripts/testharness_runner.py | 22 ++++++++++++++++------ unittests/ASM/CMakeLists.txt | 1 + unittests/ASM/Disabled_Tests | 0 unittests/IR/CMakeLists.txt | 1 + unittests/IR/Disabled_Tests | 0 5 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 unittests/ASM/Disabled_Tests create mode 100644 unittests/IR/Disabled_Tests 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..e69de29bb 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 From 98ed6fb8755f24f81f98cbbb14ed1e6d24fb835a Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 28 May 2020 15:10:19 -0700 Subject: [PATCH 5/5] Disables test D9_F2 This changes precision depending on if it is running on x86 or AArch64, so we can't nail down an exact answer --- unittests/ASM/Disabled_Tests | 1 + 1 file changed, 1 insertion(+) diff --git a/unittests/ASM/Disabled_Tests b/unittests/ASM/Disabled_Tests index e69de29bb..905af11af 100644 --- a/unittests/ASM/Disabled_Tests +++ b/unittests/ASM/Disabled_Tests @@ -0,0 +1 @@ +Test_D9_F2.asm