diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index 95eb2e59..dd0b6dd2 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -425,15 +425,15 @@ INST(NEG_1, "NEG (vector)", "01111 // Data Processing - FP and SIMD - SIMD Scalar pairwise INST(ADDP_pair, "ADDP (scalar)", "01011110zz110001101110nnnnnddddd") //INST(FMAXNMP_pair_1, "FMAXNMP (scalar)", "0101111000110000110010nnnnnddddd") -//INST(FMAXNMP_pair_2, "FMAXNMP (scalar)", "011111100z110000110010nnnnnddddd") +INST(FMAXNMP_pair_2, "FMAXNMP (scalar)", "011111100z110000110010nnnnnddddd") //INST(FADDP_pair_1, "FADDP (scalar)", "0101111000110000110110nnnnnddddd") INST(FADDP_pair_2, "FADDP (scalar)", "011111100z110000110110nnnnnddddd") //INST(FMAXP_pair_1, "FMAXP (scalar)", "0101111000110000111110nnnnnddddd") -//INST(FMAXP_pair_2, "FMAXP (scalar)", "011111100z110000111110nnnnnddddd") +INST(FMAXP_pair_2, "FMAXP (scalar)", "011111100z110000111110nnnnnddddd") //INST(FMINNMP_pair_1, "FMINNMP (scalar)", "0101111010110000110010nnnnnddddd") -//INST(FMINNMP_pair_2, "FMINNMP (scalar)", "011111101z110000110010nnnnnddddd") +INST(FMINNMP_pair_2, "FMINNMP (scalar)", "011111101z110000110010nnnnnddddd") //INST(FMINP_pair_1, "FMINP (scalar)", "0101111010110000111110nnnnnddddd") -//INST(FMINP_pair_2, "FMINP (scalar)", "011111101z110000111110nnnnnddddd") +INST(FMINP_pair_2, "FMINP (scalar)", "011111101z110000111110nnnnnddddd") // Data Processing - FP and SIMD - SIMD Scalar three different //INST(SQDMLAL_vec_1, "SQDMLAL, SQDMLAL2 (vector)", "01011110zz1mmmmm100100nnnnnddddd") diff --git a/src/frontend/A64/translate/impl/simd_scalar_pairwise.cpp b/src/frontend/A64/translate/impl/simd_scalar_pairwise.cpp index 4facf3ef..462914fe 100644 --- a/src/frontend/A64/translate/impl/simd_scalar_pairwise.cpp +++ b/src/frontend/A64/translate/impl/simd_scalar_pairwise.cpp @@ -6,8 +6,41 @@ #include "frontend/A64/translate/impl/impl.h" -namespace Dynarmic { -namespace A64 { +namespace Dynarmic::A64 { +namespace { +enum class MinMaxOperation { + Max, + MaxNumeric, + Min, + MinNumeric, +}; + +bool FPPairwiseMinMax(TranslatorVisitor& v, bool sz, Vec Vn, Vec Vd, MinMaxOperation operation) { + const size_t esize = sz ? 64 : 32; + + const IR::U128 operand = v.V(128, Vn); + const IR::U32U64 element1 = v.ir.VectorGetElement(esize, operand, 0); + const IR::U32U64 element2 = v.ir.VectorGetElement(esize, operand, 1); + const IR::U32U64 result = [&] { + switch (operation) { + case MinMaxOperation::Max: + return v.ir.FPMax(element1, element2, true); + case MinMaxOperation::MaxNumeric: + return v.ir.FPMaxNumeric(element1, element2, true); + case MinMaxOperation::Min: + return v.ir.FPMin(element1, element2, true); + case MinMaxOperation::MinNumeric: + return v.ir.FPMinNumeric(element1, element2, true); + default: + UNREACHABLE(); + return IR::U32U64{}; + } + }(); + + v.V(128, Vd, v.ir.ZeroExtendToQuad(result)); + return true; +} +} // Anonymous namespace bool TranslatorVisitor::ADDP_pair(Imm<2> size, Vec Vn, Vec Vd) { if (size != 0b11) { @@ -31,5 +64,19 @@ bool TranslatorVisitor::FADDP_pair_2(bool size, Vec Vn, Vec Vd) { return true; } -} // namespace A64 -} // namespace Dynarmic +bool TranslatorVisitor::FMAXNMP_pair_2(bool sz, Vec Vn, Vec Vd) { + return FPPairwiseMinMax(*this, sz, Vn, Vd, MinMaxOperation::MaxNumeric); +} + +bool TranslatorVisitor::FMAXP_pair_2(bool sz, Vec Vn, Vec Vd) { + return FPPairwiseMinMax(*this, sz, Vn, Vd, MinMaxOperation::Max); +} + +bool TranslatorVisitor::FMINNMP_pair_2(bool sz, Vec Vn, Vec Vd) { + return FPPairwiseMinMax(*this, sz, Vn, Vd, MinMaxOperation::MinNumeric); +} + +bool TranslatorVisitor::FMINP_pair_2(bool sz, Vec Vn, Vec Vd) { + return FPPairwiseMinMax(*this, sz, Vn, Vd, MinMaxOperation::Min); +} +} // namespace Dynarmic::A64