From 7ebba82b283466c37d5cb5afa6dc40173b1e7362 Mon Sep 17 00:00:00 2001 From: Paulo Matos Date: Mon, 22 Apr 2024 17:44:11 +0200 Subject: [PATCH] binary and unary ops 261 failures --- .../Interface/Core/OpcodeDispatcher.cpp | 272 ++++++------------ .../Source/Interface/Core/OpcodeDispatcher.h | 11 +- .../Interface/Core/OpcodeDispatcher/X87.cpp | 93 ------ .../Core/OpcodeDispatcher/X87New.cpp | 79 +++++ FEXCore/Source/Interface/IR/IR.json | 40 +++ .../IR/Passes/x87StackOptimizationPass.cpp | 234 +++++++++++++++ 6 files changed, 455 insertions(+), 274 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index ffd3457cdb..1593ee85c2 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -6392,81 +6392,47 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { {OPD(0xDF, 0xF0), 8, &OpDispatchBuilder::FCOMIF64<80, false, OpDispatchBuilder::FCOMIFlags::FLAGS_RFLAGS, false>}, }; - constexpr std::tuple - X87OpTable[] = { - {OPDReg(0xD8, 0) | 0x00, 8, - &OpDispatchBuilder::FADD<32, false, - OpDispatchBuilder::OpResult::RES_ST0>}, - - {OPDReg(0xD8, 1) | 0x00, 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, 3) | 0x00, 8, - &OpDispatchBuilder::FCOMI< - 32, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, - - {OPDReg(0xD8, 4) | 0x00, 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, 6) | 0x00, 8, - &OpDispatchBuilder::FDIV<32, false, false, - OpDispatchBuilder::OpResult::RES_ST0>}, - - {OPDReg(0xD8, 7) | 0x00, 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, false>}, - {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>}, - - // 1 = Invalid - - {OPDReg(0xD9, 2) | 0x00, 8, &OpDispatchBuilder::FST<32>}, - - {OPDReg(0xD9, 3) | 0x00, 8, &OpDispatchBuilder::FST<32>}, - - {OPDReg(0xD9, 4) | 0x00, 8, &OpDispatchBuilder::X87LDENV}, - - {OPDReg(0xD9, 5) | 0x00, 8, - &OpDispatchBuilder::X87FLDCW}, // XXX: stubbed FLDCW - - {OPDReg(0xD9, 6) | 0x00, 8, &OpDispatchBuilder::X87FNSTENV}, - - {OPDReg(0xD9, 7) | 0x00, 8, &OpDispatchBuilder::X87FSTCW}, + constexpr std::tuple X87OpTable[] = { + {OPDReg(0xD8, 0) | 0x00, 8, &OpDispatchBuilder::FADD<32, false, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xD8, 1) | 0x00, 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, 3) | 0x00, 8, &OpDispatchBuilder::FCOMI< 32, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + + {OPDReg(0xD8, 4) | 0x00, 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, 6) | 0x00, 8, &OpDispatchBuilder::FDIV<32, false, false, OpDispatchBuilder::OpResult::RES_ST0>}, + + {OPDReg(0xD8, 7) | 0x00, 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, false>}, + {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>}, + + // 1 = Invalid + + {OPDReg(0xD9, 2) | 0x00, 8, &OpDispatchBuilder::FST<32>}, + + {OPDReg(0xD9, 3) | 0x00, 8, &OpDispatchBuilder::FST<32>}, + + {OPDReg(0xD9, 4) | 0x00, 8, &OpDispatchBuilder::X87LDENV}, + + {OPDReg(0xD9, 5) | 0x00, 8, &OpDispatchBuilder::X87FLDCW}, // XXX: stubbed FLDCW + + {OPDReg(0xD9, 6) | 0x00, 8, &OpDispatchBuilder::X87FNSTENV}, + + {OPDReg(0xD9, 7) | 0x00, 8, &OpDispatchBuilder::X87FSTCW}, {OPD(0xD9, 0xC0), 8, &OpDispatchBuilder::FLD<80>}, {OPD(0xD9, 0xC8), 8, &OpDispatchBuilder::FXCH}, @@ -6488,54 +6454,38 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { {OPD(0xD9, 0xEE), 1, &OpDispatchBuilder::FLD_Const}, // 0.0 // EF = Invalid - {OPD(0xD9, 0xF0), 1, &OpDispatchBuilder::X87UnaryOp}, + {OPD(0xD9, 0xF0), 1, &OpDispatchBuilder::F80F2XM1}, {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, 0xF5), 1, &OpDispatchBuilder::F80FPREM1}, {OPD(0xD9, 0xF6), 1, &OpDispatchBuilder::X87ModifySTP}, {OPD(0xD9, 0xF7), 1, &OpDispatchBuilder::X87ModifySTP}, - {OPD(0xD9, 0xF8), 1, &OpDispatchBuilder::X87BinaryOp}, + {OPD(0xD9, 0xF8), 1, &OpDispatchBuilder::F80FPREM}, {OPD(0xD9, 0xF9), 1, &OpDispatchBuilder::X87FYL2X}, - {OPD(0xD9, 0xFA), 1, &OpDispatchBuilder::X87UnaryOp}, + {OPD(0xD9, 0xFA), 1, &OpDispatchBuilder::F80SQRT}, {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}, + {OPD(0xD9, 0xFD), 1, &OpDispatchBuilder::F80SCALE}, + {OPD(0xD9, 0xFE), 1, &OpDispatchBuilder::F80SIN}, + {OPD(0xD9, 0xFF), 1, &OpDispatchBuilder::F80COS}, - {OPDReg(0xDA, 0) | 0x00, 8, - &OpDispatchBuilder::FADD<32, true, - OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDA, 0) | 0x00, 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) | 0x00, 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) | 0x00, 8, &OpDispatchBuilder::FCOMI< 32, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, - {OPDReg(0xDA, 3) | 0x00, 8, - &OpDispatchBuilder::FCOMI< - 32, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + {OPDReg(0xDA, 3) | 0x00, 8, &OpDispatchBuilder::FCOMI< 32, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, - {OPDReg(0xDA, 4) | 0x00, 8, - &OpDispatchBuilder::FSUB<32, true, false, - OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDA, 4) | 0x00, 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) | 0x00, 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) | 0x00, 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) | 0x00, 8, &OpDispatchBuilder::FDIV<32, true, true, OpDispatchBuilder::OpResult::RES_ST0>}, {OPD(0xDA, 0xC0), 8, &OpDispatchBuilder::X87FCMOV}, {OPD(0xDA, 0xC8), 8, &OpDispatchBuilder::X87FCMOV}, @@ -6548,19 +6498,19 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { // F0 = Invalid // F8 = Invalid - {OPDReg(0xDB, 0) | 0x00, 8, &OpDispatchBuilder::FILD}, + {OPDReg(0xDB, 0) | 0x00, 8, &OpDispatchBuilder::FILD}, - {OPDReg(0xDB, 1) | 0x00, 8, &OpDispatchBuilder::FIST}, + {OPDReg(0xDB, 1) | 0x00, 8, &OpDispatchBuilder::FIST}, - {OPDReg(0xDB, 2) | 0x00, 8, &OpDispatchBuilder::FIST}, + {OPDReg(0xDB, 2) | 0x00, 8, &OpDispatchBuilder::FIST}, - {OPDReg(0xDB, 3) | 0x00, 8, &OpDispatchBuilder::FIST}, + {OPDReg(0xDB, 3) | 0x00, 8, &OpDispatchBuilder::FIST}, - // 4 = Invalid + // 4 = Invalid - {OPDReg(0xDB, 5) | 0x00, 8, &OpDispatchBuilder::FLD<80>}, + {OPDReg(0xDB, 5) | 0x00, 8, &OpDispatchBuilder::FLD<80>}, - // 6 = Invalid + // 6 = Invalid {OPDReg(0xDB, 7) | 0x00, 8, &OpDispatchBuilder::FST<80>}, @@ -6578,37 +6528,21 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { // F8 = Invalid - {OPDReg(0xDC, 0) | 0x00, 8, - &OpDispatchBuilder::FADD<64, false, - OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDC, 0) | 0x00, 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) | 0x00, 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) | 0x00, 8, &OpDispatchBuilder::FCOMI< 64, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, - {OPDReg(0xDC, 3) | 0x00, 8, - &OpDispatchBuilder::FCOMI< - 64, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + {OPDReg(0xDC, 3) | 0x00, 8, &OpDispatchBuilder::FCOMI< 64, false, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, - {OPDReg(0xDC, 4) | 0x00, 8, - &OpDispatchBuilder::FSUB<64, false, false, - OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDC, 4) | 0x00, 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) | 0x00, 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) | 0x00, 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) | 0x00, 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>}, @@ -6617,20 +6551,20 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { {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) | 0x00, 8, &OpDispatchBuilder::FLD<64>}, - {OPDReg(0xDD, 1) | 0x00, 8, &OpDispatchBuilder::FIST}, + {OPDReg(0xDD, 1) | 0x00, 8, &OpDispatchBuilder::FIST}, - {OPDReg(0xDD, 2) | 0x00, 8, &OpDispatchBuilder::FST<64>}, + {OPDReg(0xDD, 2) | 0x00, 8, &OpDispatchBuilder::FST<64>}, - {OPDReg(0xDD, 3) | 0x00, 8, &OpDispatchBuilder::FST<64>}, + {OPDReg(0xDD, 3) | 0x00, 8, &OpDispatchBuilder::FST<64>}, - {OPDReg(0xDD, 4) | 0x00, 8, &OpDispatchBuilder::X87FRSTOR}, + {OPDReg(0xDD, 4) | 0x00, 8, &OpDispatchBuilder::X87FRSTOR}, - // 5 = Invalid - {OPDReg(0xDD, 6) | 0x00, 8, &OpDispatchBuilder::X87FNSAVE}, + // 5 = Invalid + {OPDReg(0xDD, 6) | 0x00, 8, &OpDispatchBuilder::X87FNSAVE}, - {OPDReg(0xDD, 7) | 0x00, 8, &OpDispatchBuilder::X87FNSTSW}, + {OPDReg(0xDD, 7) | 0x00, 8, &OpDispatchBuilder::X87FNSTSW}, {OPD(0xDD, 0xC0), 8, &OpDispatchBuilder::X87FFREE}, {OPD(0xDD, 0xD0), 8, &OpDispatchBuilder::FST}, @@ -6639,37 +6573,21 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { {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, false>}, - {OPDReg(0xDE, 0) | 0x00, 8, - &OpDispatchBuilder::FADD<16, true, - OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDE, 0) | 0x00, 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) | 0x00, 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) | 0x00, 8, &OpDispatchBuilder::FCOMI< 16, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, - {OPDReg(0xDE, 3) | 0x00, 8, - &OpDispatchBuilder::FCOMI< - 16, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, + {OPDReg(0xDE, 3) | 0x00, 8, &OpDispatchBuilder::FCOMI< 16, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>}, - {OPDReg(0xDE, 4) | 0x00, 8, - &OpDispatchBuilder::FSUB<16, true, false, - OpDispatchBuilder::OpResult::RES_ST0>}, + {OPDReg(0xDE, 4) | 0x00, 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) | 0x00, 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) | 0x00, 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) | 0x00, 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>}, @@ -6679,21 +6597,21 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { {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}, + {OPDReg(0xDF, 0) | 0x00, 8, &OpDispatchBuilder::FILD}, - {OPDReg(0xDF, 1) | 0x00, 8, &OpDispatchBuilder::FIST}, + {OPDReg(0xDF, 1) | 0x00, 8, &OpDispatchBuilder::FIST}, - {OPDReg(0xDF, 2) | 0x00, 8, &OpDispatchBuilder::FIST}, + {OPDReg(0xDF, 2) | 0x00, 8, &OpDispatchBuilder::FIST}, - {OPDReg(0xDF, 3) | 0x00, 8, &OpDispatchBuilder::FIST}, + {OPDReg(0xDF, 3) | 0x00, 8, &OpDispatchBuilder::FIST}, - {OPDReg(0xDF, 4) | 0x00, 8, &OpDispatchBuilder::FBLD}, + {OPDReg(0xDF, 4) | 0x00, 8, &OpDispatchBuilder::FBLD}, - {OPDReg(0xDF, 5) | 0x00, 8, &OpDispatchBuilder::FILD}, + {OPDReg(0xDF, 5) | 0x00, 8, &OpDispatchBuilder::FILD}, - {OPDReg(0xDF, 6) | 0x00, 8, &OpDispatchBuilder::FBSTP}, + {OPDReg(0xDF, 6) | 0x00, 8, &OpDispatchBuilder::FBSTP}, - {OPDReg(0xDF, 7) | 0x00, 8, &OpDispatchBuilder::FIST}, + {OPDReg(0xDF, 7) | 0x00, 8, &OpDispatchBuilder::FIST}, // XXX: This should also set the x87 tag bits to empty // We don't support this currently, so just pop the stack diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 3dfd6bbf3b..3e101e95dc 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -759,11 +759,14 @@ class OpDispatchBuilder final : public IREmitter { void FRNDINT(OpcodeArgs); void FXTRACT(OpcodeArgs); void FNINIT(OpcodeArgs); + void F80FPREM(OpcodeArgs); + void F80FPREM1(OpcodeArgs); + void F80SCALE(OpcodeArgs); + void F80SIN(OpcodeArgs); + void F80COS(OpcodeArgs); + void F80SQRT(OpcodeArgs); + void F80F2XM1(OpcodeArgs); - template - void X87UnaryOp(OpcodeArgs); - template - void X87BinaryOp(OpcodeArgs); template void X87ModifySTP(OpcodeArgs); void X87SinCos(OpcodeArgs); diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp index a033f1a186..5f346032bd 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp @@ -247,22 +247,6 @@ void OpDispatchBuilder::FRNDINT(OpcodeArgs) { _StoreContextIndexed(result, top, 16, MMBaseOffset(), 16, FPRClass); } -void OpDispatchBuilder::FXTRACT(OpcodeArgs) { - auto orig_top = GetX87Top(); - auto top = _And(OpSize::i32Bit, _Sub(OpSize::i32Bit, orig_top, _Constant(1)), _Constant(7)); - SetX87ValidTag(top, true); - SetX87Top(top); - - auto a = _LoadContextIndexed(orig_top, 16, MMBaseOffset(), 16, FPRClass); - - auto exp = _F80XTRACT_EXP(a); - auto sig = _F80XTRACT_SIG(a); - - // Write to ST[TOP] - _StoreContextIndexed(exp, orig_top, 16, MMBaseOffset(), 16, FPRClass); - _StoreContextIndexed(sig, top, 16, MMBaseOffset(), 16, FPRClass); -} - void OpDispatchBuilder::FNINIT(OpcodeArgs) { auto Zero = _Constant(0); // Init FCW to 0x037F @@ -304,67 +288,6 @@ void OpDispatchBuilder::FST(OpcodeArgs) { } } -template -void OpDispatchBuilder::X87UnaryOp(OpcodeArgs) { - auto top = GetX87Top(); - auto a = _LoadContextIndexed(top, 16, MMBaseOffset(), 16, FPRClass); - - DeriveOp(result, IROp, _F80Round(a)); - - if constexpr (IROp == IR::OP_F80SIN || IROp == IR::OP_F80COS) { - // TODO: ACCURACY: should check source is in range –2^63 to +2^63 - SetRFLAG(_Constant(0)); - } - - // Write to ST[TOP] - _StoreContextIndexed(result, top, 16, MMBaseOffset(), 16, FPRClass); -} - -template void OpDispatchBuilder::X87UnaryOp(OpcodeArgs); -template void OpDispatchBuilder::X87UnaryOp(OpcodeArgs); -template void OpDispatchBuilder::X87UnaryOp(OpcodeArgs); -template void OpDispatchBuilder::X87UnaryOp(OpcodeArgs); - -template -void OpDispatchBuilder::X87BinaryOp(OpcodeArgs) { - auto top = GetX87Top(); - - auto mask = _Constant(7); - OrderedNode* st1 = _And(OpSize::i32Bit, _Add(OpSize::i32Bit, top, _Constant(1)), mask); - - auto a = _LoadContextIndexed(top, 16, MMBaseOffset(), 16, FPRClass); - st1 = _LoadContextIndexed(st1, 16, MMBaseOffset(), 16, FPRClass); - - DeriveOp(result, IROp, _F80Add(a, st1)); - - if constexpr (IROp == IR::OP_F80FPREM || IROp == IR::OP_F80FPREM1) { - // TODO: Set C0 to Q2, C3 to Q1, C1 to Q0 - SetRFLAG(_Constant(0)); - } - - // Write to ST[TOP] - _StoreContextIndexed(result, top, 16, MMBaseOffset(), 16, FPRClass); -} - -template void OpDispatchBuilder::X87BinaryOp(OpcodeArgs); -template void OpDispatchBuilder::X87BinaryOp(OpcodeArgs); -template void OpDispatchBuilder::X87BinaryOp(OpcodeArgs); - -template -void OpDispatchBuilder::X87ModifySTP(OpcodeArgs) { - auto orig_top = GetX87Top(); - if (Inc) { - auto top = _And(OpSize::i32Bit, _Add(OpSize::i32Bit, orig_top, _Constant(1)), _Constant(7)); - SetX87Top(top); - } else { - auto top = _And(OpSize::i32Bit, _Sub(OpSize::i32Bit, orig_top, _Constant(1)), _Constant(7)); - SetX87Top(top); - } -} - -template void OpDispatchBuilder::X87ModifySTP(OpcodeArgs); -template void OpDispatchBuilder::X87ModifySTP(OpcodeArgs); - void OpDispatchBuilder::X87SinCos(OpcodeArgs) { auto orig_top = GetX87Top(); auto top = _And(OpSize::i32Bit, _Sub(OpSize::i32Bit, orig_top, _Constant(1)), _Constant(7)); @@ -404,22 +327,6 @@ void OpDispatchBuilder::X87TAN(OpcodeArgs) { _StoreContextIndexed(data, top, 16, MMBaseOffset(), 16, FPRClass); } -void OpDispatchBuilder::X87ATAN(OpcodeArgs) { - auto orig_top = GetX87Top(); - // if we are popping then we must first mark this location as empty - SetX87ValidTag(orig_top, false); - auto top = _And(OpSize::i32Bit, _Add(OpSize::i32Bit, orig_top, _Constant(1)), _Constant(7)); - SetX87Top(top); - - auto a = _LoadContextIndexed(orig_top, 16, MMBaseOffset(), 16, FPRClass); - OrderedNode* st1 = _LoadContextIndexed(top, 16, MMBaseOffset(), 16, FPRClass); - - auto result = _F80ATAN(st1, a); - - // Write to ST[TOP] - _StoreContextIndexed(result, top, 16, MMBaseOffset(), 16, FPRClass); -} - void OpDispatchBuilder::X87FLDCW(OpcodeArgs) { OrderedNode* NewFCW = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags); _StoreContext(2, GPRClass, NewFCW, offsetof(FEXCore::Core::CPUState, FCW)); diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87New.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87New.cpp index 47dea32f72..1cdf820a39 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87New.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87New.cpp @@ -2,6 +2,7 @@ #include "FEXCore/IR/IR.h" #include "Interface/Core/OpcodeDispatcher.h" #include "Interface/Core/X86Tables/X86Tables.h" +#include "Interface/IR/IR.h" #include #include @@ -503,4 +504,82 @@ template void OpDispatchBuilder::FCOMI<16, true, OpDispatchBuilder::FCOMIFlags:: template void OpDispatchBuilder::FCOMI<32, true, OpDispatchBuilder::FCOMIFlags::FLAGS_X87, false>(OpcodeArgs); + +void OpDispatchBuilder::X87ATAN(OpcodeArgs) { + CurrentHeader->HasX87 = true; + _F80ATANStack(); + _PopStackDestroy(); +} + + +void OpDispatchBuilder::FXTRACT(OpcodeArgs) { + CurrentHeader->HasX87 = true; + _F80XTRACTStack(); +} + +// TODO: The following 3 functions were dealt with by a single templatized +// X80BinaryOp<>. Can we redo it as a template? +void OpDispatchBuilder::F80FPREM(OpcodeArgs) { + CurrentHeader->HasX87 = true; + _F80FPREMStack(); + // TODO: Set C0 to Q2, C3 to Q1, C1 to Q0 + SetRFLAG(_Constant(0)); +} + +void OpDispatchBuilder::F80FPREM1(OpcodeArgs) { + CurrentHeader->HasX87 = true; + _F80FPREM1Stack(); + // TODO: Set C0 to Q2, C3 to Q1, C1 to Q0 + SetRFLAG(_Constant(0)); +} + +void OpDispatchBuilder::F80SCALE(OpcodeArgs) { + CurrentHeader->HasX87 = true; + _F80SCALEStack(); +} + +template +void OpDispatchBuilder::X87ModifySTP(OpcodeArgs) { + CurrentHeader->HasX87 = true; + auto orig_top = GetX87Top(); + if (Inc) { + auto top = _And(OpSize::i32Bit, _Add(OpSize::i32Bit, orig_top, _Constant(1)), _Constant(7)); + SetX87Top(top); + } else { + auto top = _And(OpSize::i32Bit, _Sub(OpSize::i32Bit, orig_top, _Constant(1)), _Constant(7)); + SetX87Top(top); + } +} + +template void OpDispatchBuilder::X87ModifySTP(OpcodeArgs); +template void OpDispatchBuilder::X87ModifySTP(OpcodeArgs); + +// TODO(pmatos): the next 4 operations used to be abstracted into a UnaryOp templatized op. +// can we abstract it again? +void OpDispatchBuilder::F80SIN(OpcodeArgs) { + CurrentHeader->HasX87 = true; + _F80SINStack(); + + // TODO: ACCURACY: should check source is in range –2^63 to +2^63 + SetRFLAG(_Constant(0)); +} + +void OpDispatchBuilder::F80COS(OpcodeArgs) { + CurrentHeader->HasX87 = true; + _F80COSStack(); + + // TODO: ACCURACY: should check source is in range –2^63 to +2^63 + SetRFLAG(_Constant(0)); +} + +void OpDispatchBuilder::F80SQRT(OpcodeArgs) { + CurrentHeader->HasX87 = true; + _F80SQRTStack(); +} + +void OpDispatchBuilder::F80F2XM1(OpcodeArgs) { + CurrentHeader->HasX87 = true; + _F80F2XM1Stack(); +} + } // namespace FEXCore::IR \ No newline at end of file diff --git a/FEXCore/Source/Interface/IR/IR.json b/FEXCore/Source/Interface/IR/IR.json index da01b2ce8c..ea1aea37fa 100644 --- a/FEXCore/Source/Interface/IR/IR.json +++ b/FEXCore/Source/Interface/IR/IR.json @@ -2555,18 +2555,38 @@ "DestSize": "16", "JITDispatch": false }, + "FPR = F80ATANStack": { + "Desc": [ + "Computes arctan(st1/st0) and stores it in st0. Then pops the stack." + ], + "DestSize": "16", + "JITDispatch": false, + "HasSideEffects": true + }, "FPR = F80ATAN FPR:$X80Src1, FPR:$X80Src2": { "DestSize": "16", "JITDispatch": false }, + "F80FPREMStack": { + "JITDispatch": false, + "HasSideEffects": true + }, "FPR = F80FPREM FPR:$X80Src1, FPR:$X80Src2": { "DestSize": "16", "JITDispatch": false }, + "F80FPREM1Stack": { + "JITDispatch": false, + "HasSideEffects": true + }, "FPR = F80FPREM1 FPR:$X80Src1, FPR:$X80Src2": { "DestSize": "16", "JITDispatch": false }, + "F80SCALEStack": { + "JITDispatch": false, + "HasSideEffects": true + }, "FPR = F80SCALE FPR:$X80Src1, FPR:$X80Src2": { "DestSize": "16", "JITDispatch": false @@ -2591,6 +2611,10 @@ "DestSize": "16", "JITDispatch": false }, + "F80F2XM1Stack": { + "JITDispatch": false, + "HasSideEffects": true + }, "FPR = F80F2XM1 FPR:$X80Src": { "DestSize": "16", "JITDispatch": false @@ -2599,18 +2623,34 @@ "DestSize": "16", "JITDispatch": false }, + "F80SINStack": { + "JITDispatch": false, + "HasSideEffects": true + }, "FPR = F80SIN FPR:$X80Src": { "DestSize": "16", "JITDispatch": false }, + "F80COSStack": { + "JITDispatch": false, + "HasSideEffects": true + }, "FPR = F80COS FPR:$X80Src": { "DestSize": "16", "JITDispatch": false }, + "F80SQRTStack": { + "JITDispatch": false, + "HasSideEffects": true + }, "FPR = F80SQRT FPR:$X80Src": { "DestSize": "16", "JITDispatch": false }, + "F80XTRACTStack": { + "JITDispatch": false, + "HasSideEffects": true + }, "FPR = F80XTRACT_EXP FPR:$X80Src": { "DestSize": "16", "JITDispatch": false diff --git a/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp b/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp index 4cbda10ca2..345301093d 100644 --- a/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp +++ b/FEXCore/Source/Interface/IR/Passes/x87StackOptimizationPass.cpp @@ -98,6 +98,7 @@ class X87StackOptimization final : public FEXCore::IR::Pass { void StoreStackValueAtOffset_Slow(IREmitter* IREmit, uint8_t Offset, OrderedNode* Value); // Update Top value in slow path for a pop void UpdateTop4Pop_Slow(IREmitter* IREmit); + void UpdateTop4Push_Slow(IREmitter* IREmit); struct StackMemberInfo { IR::OpSize SourceDataSize; // Size of SourceDataNode @@ -154,6 +155,12 @@ void X87StackOptimization::UpdateTop4Pop_Slow(IREmitter* IREmit) { SetX87Top(IREmit, IREmit->_Add(OpSize::i32Bit, top, IREmit->_Constant(1))); } +void X87StackOptimization::UpdateTop4Push_Slow(IREmitter* IREmit) { + // Pop the top of the x87 stack + auto* top = GetX87Top(IREmit); + SetX87Top(IREmit, IREmit->_Sub(OpSize::i32Bit, top, IREmit->_Constant(1))); +} + bool X87StackOptimization::Run(IREmitter* IREmit) { FEXCORE_PROFILE_SCOPED("PassManager::x87StackOpt"); @@ -788,6 +795,233 @@ bool X87StackOptimization::Run(IREmitter* IREmit) { break; } + case IR::OP_F80ATANSTACK: { + LogMan::Msg::DFmt("OP_F80ATANSTACK"); + const auto& StackMember1 = StackData.top(); + const auto& StackMember2 = StackData.top(1); + + if (StackMember1 == std::nullopt || StackMember2 == std::nullopt) { + // slow path + auto* st0 = LoadStackValueAtTop_Slow(IREmit); + auto* st1 = LoadStackValueAtOffset_Slow(IREmit, 1); + OrderedNode* Result = IREmit->_F80ATAN(st1, st0); + StoreStackValueAtOffset_Slow(IREmit, 1, Result); + } else { + // fast path + auto* st0 = StackMember1->StackDataNode; + auto* st1 = StackMember2->StackDataNode; + + StackData.setTop(StackMemberInfo {.SourceDataSize = StackMember1->SourceDataSize, + .StackDataSize = StackMember1->StackDataSize, + .SourceDataNode = nullptr, + .StackDataNode = IREmit->_F80ATAN(st1, st0), + .InterpretAsFloat = StackMember1->InterpretAsFloat}, + 1); + } + + IREmit->Remove(CodeNode); + Changed = true; + break; + } + + case IR::OP_F80XTRACTSTACK: { + LogMan::Msg::DFmt("OP_F80XTRACTSTACK"); + const auto& StackMember = StackData.top(); + + if (StackMember == std::nullopt) { + // slow path + auto* st0 = LoadStackValueAtTop_Slow(IREmit); + + auto exp = IREmit->_F80XTRACT_EXP(st0); + auto sig = IREmit->_F80XTRACT_SIG(st0); + + // Write exp to top, update top for a push and set sig at new top. + StoreStackValueAtTop_Slow(IREmit, exp); + UpdateTop4Push_Slow(IREmit); + StoreStackValueAtTop_Slow(IREmit, sig); + } else { + // fast path + auto* st0 = StackMember->StackDataNode; + auto exp = IREmit->_F80XTRACT_EXP(st0); + auto sig = IREmit->_F80XTRACT_SIG(st0); + + StackData.setTop(StackMemberInfo {.SourceDataSize = StackMember->SourceDataSize, + .StackDataSize = StackMember->StackDataSize, + .SourceDataNode = nullptr, + .StackDataNode = exp, + .InterpretAsFloat = StackMember->InterpretAsFloat}); + StackData.push(StackMemberInfo {.SourceDataSize = StackMember->SourceDataSize, + .StackDataSize = StackMember->StackDataSize, + .SourceDataNode = nullptr, + .StackDataNode = sig, + .InterpretAsFloat = StackMember->InterpretAsFloat}); + } + + IREmit->Remove(CodeNode); + Changed = true; + break; + } + + case IR::OP_F80FPREMSTACK: { + LogMan::Msg::DFmt("F80FPREMStack"); + const auto& StackMember1 = StackData.top(); + const auto& StackMember2 = StackData.top(1); + + if (StackMember1 == std::nullopt || StackMember2 == std::nullopt) { + // slow path + auto* st0 = LoadStackValueAtTop_Slow(IREmit); + auto* st1 = LoadStackValueAtOffset_Slow(IREmit, 1); + + StoreStackValueAtTop_Slow(IREmit, IREmit->_F80FPREM(st0, st1)); + } else { // fast path + StackData.setTop(StackMemberInfo {.SourceDataSize = StackMember1->SourceDataSize, + .StackDataSize = StackMember1->StackDataSize, + .SourceDataNode = nullptr, + .StackDataNode = IREmit->_F80FPREM(StackMember1->StackDataNode, StackMember2->StackDataNode), + .InterpretAsFloat = StackMember1->InterpretAsFloat}); + } + + IREmit->Remove(CodeNode); + Changed = true; + break; + } + + case IR::OP_F80FPREM1STACK: { + LogMan::Msg::DFmt("F80FPREM1Stack"); + const auto& StackMember1 = StackData.top(); + const auto& StackMember2 = StackData.top(1); + + if (StackMember1 == std::nullopt || StackMember2 == std::nullopt) { + // slow path + auto* st0 = LoadStackValueAtTop_Slow(IREmit); + auto* st1 = LoadStackValueAtOffset_Slow(IREmit, 1); + + StoreStackValueAtTop_Slow(IREmit, IREmit->_F80FPREM1(st0, st1)); + } else { // fast path + StackData.setTop(StackMemberInfo {.SourceDataSize = StackMember1->SourceDataSize, + .StackDataSize = StackMember1->StackDataSize, + .SourceDataNode = nullptr, + .StackDataNode = IREmit->_F80FPREM1(StackMember1->StackDataNode, StackMember2->StackDataNode), + .InterpretAsFloat = StackMember1->InterpretAsFloat}); + } + + IREmit->Remove(CodeNode); + Changed = true; + break; + } + + case IR::OP_F80SCALESTACK: { + LogMan::Msg::DFmt("F80FPSCALE"); + const auto& StackMember1 = StackData.top(); + const auto& StackMember2 = StackData.top(1); + + if (StackMember1 == std::nullopt || StackMember2 == std::nullopt) { + // slow path + auto* st0 = LoadStackValueAtTop_Slow(IREmit); + auto* st1 = LoadStackValueAtOffset_Slow(IREmit, 1); + + StoreStackValueAtTop_Slow(IREmit, IREmit->_F80SCALE(st0, st1)); + } else { // fast path + StackData.setTop(StackMemberInfo {.SourceDataSize = StackMember1->SourceDataSize, + .StackDataSize = StackMember1->StackDataSize, + .SourceDataNode = nullptr, + .StackDataNode = IREmit->_F80SCALE(StackMember1->StackDataNode, StackMember2->StackDataNode), + .InterpretAsFloat = StackMember1->InterpretAsFloat}); + } + + IREmit->Remove(CodeNode); + Changed = true; + break; + } + + case IR::OP_F80SQRTSTACK: { + LogMan::Msg::DFmt("F80SQRTSTACK"); + const auto& StackMember1 = StackData.top(); + + if (StackMember1 == std::nullopt) { + // slow path + auto* st0 = LoadStackValueAtTop_Slow(IREmit); + StoreStackValueAtTop_Slow(IREmit, IREmit->_F80SQRT(st0)); + } else { + // fast path + StackData.setTop(StackMemberInfo {.SourceDataSize = StackMember1->SourceDataSize, + .StackDataSize = StackMember1->StackDataSize, + .SourceDataNode = nullptr, + .StackDataNode = IREmit->_F80SQRT(StackMember1->StackDataNode), + .InterpretAsFloat = StackMember1->InterpretAsFloat}); + } + + IREmit->Remove(CodeNode); + Changed = true; + break; + } + + case IR::OP_F80SINSTACK: { + LogMan::Msg::DFmt("F80SINSTACK"); + const auto& StackMember1 = StackData.top(); + + if (StackMember1 == std::nullopt) { + // slow path + auto* st0 = LoadStackValueAtTop_Slow(IREmit); + StoreStackValueAtTop_Slow(IREmit, IREmit->_F80SIN(st0)); + } else { + // fast path + StackData.setTop(StackMemberInfo {.SourceDataSize = StackMember1->SourceDataSize, + .StackDataSize = StackMember1->StackDataSize, + .SourceDataNode = nullptr, + .StackDataNode = IREmit->_F80SIN(StackMember1->StackDataNode), + .InterpretAsFloat = StackMember1->InterpretAsFloat}); + } + + IREmit->Remove(CodeNode); + Changed = true; + break; + } + + case IR::OP_F80COSSTACK: { + LogMan::Msg::DFmt("F80COSSTACK"); + const auto& StackMember1 = StackData.top(); + + if (StackMember1 == std::nullopt) { + // slow path + auto* st0 = LoadStackValueAtTop_Slow(IREmit); + StoreStackValueAtTop_Slow(IREmit, IREmit->_F80COS(st0)); + } else { + // fast path + StackData.setTop(StackMemberInfo {.SourceDataSize = StackMember1->SourceDataSize, + .StackDataSize = StackMember1->StackDataSize, + .SourceDataNode = nullptr, + .StackDataNode = IREmit->_F80COS(StackMember1->StackDataNode), + .InterpretAsFloat = StackMember1->InterpretAsFloat}); + } + + IREmit->Remove(CodeNode); + Changed = true; + break; + } + + case IR::OP_F80F2XM1STACK: { + LogMan::Msg::DFmt("F80F2XM1STACK"); + const auto& StackMember1 = StackData.top(); + + if (StackMember1 == std::nullopt) { + // slow path + auto* st0 = LoadStackValueAtTop_Slow(IREmit); + StoreStackValueAtTop_Slow(IREmit, IREmit->_F80F2XM1(st0)); + } else { + // fast path + StackData.setTop(StackMemberInfo {.SourceDataSize = StackMember1->SourceDataSize, + .StackDataSize = StackMember1->StackDataSize, + .SourceDataNode = nullptr, + .StackDataNode = IREmit->_F80F2XM1(StackMember1->StackDataNode), + .InterpretAsFloat = StackMember1->InterpretAsFloat}); + } + + IREmit->Remove(CodeNode); + Changed = true; + break; + } + default: break; } }