diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 751867959..6a71c7f34 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -583,6 +583,8 @@ public: template void AVXInsertScalar_CVT_Float_To_Float(OpcodeArgs); + RoundType TranslateRoundType(uint8_t Mode); + template void InsertScalarRound(OpcodeArgs); template diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index e25e0604f..0c46f883c 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -594,16 +594,7 @@ void OpDispatchBuilder::AVXInsertScalar_CVT_Float_To_Float(OpcodeArgs) { template void OpDispatchBuilder::AVXInsertScalar_CVT_Float_To_Float<4, 8>(OpcodeArgs); template void OpDispatchBuilder::AVXInsertScalar_CVT_Float_To_Float<8, 4>(OpcodeArgs); -Ref OpDispatchBuilder::InsertScalarRoundImpl(OpcodeArgs, size_t DstSize, size_t ElementSize, const X86Tables::DecodedOperand& Src1Op, - const X86Tables::DecodedOperand& Src2Op, uint64_t Mode, bool ZeroUpperBits) { - // We load the full vector width when dealing with a source vector, - // so that we don't do any unnecessary zero extension to the scalar - // element that we're going to operate on. - const auto SrcSize = GetSrcSize(Op); - - Ref Src1 = LoadSource_WithOpSize(FPRClass, Op, Src1Op, DstSize, Op->Flags); - Ref Src2 = LoadSource_WithOpSize(FPRClass, Op, Src2Op, SrcSize, Op->Flags, {.AllowUpperGarbage = true}); - +RoundType OpDispatchBuilder::TranslateRoundType(uint8_t Mode) { const uint64_t RoundControlSource = (Mode >> 2) & 1; uint64_t RoundControl = Mode & 0b11; @@ -614,8 +605,20 @@ Ref OpDispatchBuilder::InsertScalarRoundImpl(OpcodeArgs, size_t DstSize, size_t FEXCore::IR::Round_Towards_Zero, }; - const auto SourceMode = RoundControlSource ? Round_Host : SourceModes[RoundControl]; + return RoundControlSource ? Round_Host : SourceModes[RoundControl]; +} +Ref OpDispatchBuilder::InsertScalarRoundImpl(OpcodeArgs, size_t DstSize, size_t ElementSize, const X86Tables::DecodedOperand& Src1Op, + const X86Tables::DecodedOperand& Src2Op, uint64_t Mode, bool ZeroUpperBits) { + // We load the full vector width when dealing with a source vector, + // so that we don't do any unnecessary zero extension to the scalar + // element that we're going to operate on. + const auto SrcSize = GetSrcSize(Op); + + Ref Src1 = LoadSource_WithOpSize(FPRClass, Op, Src1Op, DstSize, Op->Flags); + Ref Src2 = LoadSource_WithOpSize(FPRClass, Op, Src2Op, SrcSize, Op->Flags, {.AllowUpperGarbage = true}); + + const auto SourceMode = TranslateRoundType(Mode); auto ALUOp = _VFToIScalarInsert(IR::SizeToOpSize(DstSize), ElementSize, Src1, Src2, SourceMode, ZeroUpperBits); return ALUOp; @@ -3703,20 +3706,7 @@ template void OpDispatchBuilder::ExtendVectorElements<2, 8, true>(OpcodeArgs); template void OpDispatchBuilder::ExtendVectorElements<4, 8, true>(OpcodeArgs); Ref OpDispatchBuilder::VectorRoundImpl(OpSize Size, size_t ElementSize, Ref Src, uint64_t Mode) { - const uint64_t RoundControlSource = (Mode >> 2) & 1; - uint64_t RoundControl = Mode & 0b11; - - if (RoundControlSource) { - RoundControl = 0; // MXCSR - } - - static constexpr std::array SourceModes = { - FEXCore::IR::Round_Nearest, FEXCore::IR::Round_Negative_Infinity, FEXCore::IR::Round_Positive_Infinity, FEXCore::IR::Round_Towards_Zero, - FEXCore::IR::Round_Host, - }; - - const auto SourceMode = SourceModes[(RoundControlSource << 2) | RoundControl]; - return _Vector_FToI(Size, ElementSize, Src, SourceMode); + return _Vector_FToI(Size, ElementSize, Src, TranslateRoundType(Mode)); } template