From cb456f914b2902bb0c2a0705981e0803e26f493c Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 15 May 2018 10:58:04 -0400 Subject: [PATCH] A64: Implement UMLAL{2}, UMLSL{2}, and UMULL{2} Now that we have the helper function set up for the signed variants, we can also modify it to be used with the unigned ones by performing a zero extension instead of a sign extension. --- src/frontend/A64/decoder/a64.inc | 6 +-- .../translate/impl/simd_three_different.cpp | 51 ++++++++++++++++--- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index 65f4751f..c011936b 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -696,9 +696,9 @@ INST(RADDHN, "RADDHN, RADDHN2", "0Q101 INST(UABAL, "UABAL, UABAL2", "0Q101110zz1mmmmm010100nnnnnddddd") INST(RSUBHN, "RSUBHN, RSUBHN2", "0Q101110zz1mmmmm011000nnnnnddddd") INST(UABDL, "UABDL, UABDL2", "0Q101110zz1mmmmm011100nnnnnddddd") -//INST(UMLAL_vec, "UMLAL, UMLAL2 (vector)", "0Q101110zz1mmmmm100000nnnnnddddd") -//INST(UMLSL_vec, "UMLSL, UMLSL2 (vector)", "0Q101110zz1mmmmm101000nnnnnddddd") -//INST(UMULL_vec, "UMULL, UMULL2 (vector)", "0Q101110zz1mmmmm110000nnnnnddddd") +INST(UMLAL_vec, "UMLAL, UMLAL2 (vector)", "0Q101110zz1mmmmm100000nnnnnddddd") +INST(UMLSL_vec, "UMLSL, UMLSL2 (vector)", "0Q101110zz1mmmmm101000nnnnnddddd") +INST(UMULL_vec, "UMULL, UMULL2 (vector)", "0Q101110zz1mmmmm110000nnnnnddddd") // Data Processing - FP and SIMD - SIMD three same INST(SHADD, "SHADD", "0Q001110zz1mmmmm000001nnnnnddddd") diff --git a/src/frontend/A64/translate/impl/simd_three_different.cpp b/src/frontend/A64/translate/impl/simd_three_different.cpp index 51a35323..fe5078b8 100644 --- a/src/frontend/A64/translate/impl/simd_three_different.cpp +++ b/src/frontend/A64/translate/impl/simd_three_different.cpp @@ -43,14 +43,26 @@ enum class MultiplyLongBehavior { }; void MultiplyLong(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, - MultiplyLongBehavior behavior) { + MultiplyLongBehavior behavior, Signedness sign) { const size_t esize = 8 << size.ZeroExtend(); const size_t doubled_esize = 2 * esize; const size_t datasize = 64; const size_t doubled_datasize = datasize * 2; - const IR::U128 operand1 = v.ir.VectorSignExtend(esize, v.Vpart(datasize, Vn, Q)); - const IR::U128 operand2 = v.ir.VectorSignExtend(esize, v.Vpart(datasize, Vm, Q)); + const auto get_operands = [&] { + const auto p1 = v.Vpart(datasize, Vn, Q); + const auto p2 = v.Vpart(datasize, Vm, Q); + + if (sign == Signedness::Signed) { + return std::make_pair(v.ir.VectorSignExtend(esize, p1), + v.ir.VectorSignExtend(esize, p2)); + } + + return std::make_pair(v.ir.VectorZeroExtend(esize, p1), + v.ir.VectorZeroExtend(esize, p2)); + }; + + const auto [operand1, operand2] = get_operands(); IR::U128 result = v.ir.VectorMultiply(doubled_esize, operand1, operand2); if (behavior == MultiplyLongBehavior::Accumulate) { @@ -120,7 +132,7 @@ bool TranslatorVisitor::SMLAL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { return ReservedValue(); } - MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::Accumulate); + MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::Accumulate, Signedness::Signed); return true; } @@ -129,7 +141,7 @@ bool TranslatorVisitor::SMLSL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { return ReservedValue(); } - MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::Subtract); + MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::Subtract, Signedness::Signed); return true; } @@ -138,7 +150,7 @@ bool TranslatorVisitor::SMULL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { return ReservedValue(); } - MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::None); + MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::None, Signedness::Signed); return true; } @@ -225,6 +237,33 @@ bool TranslatorVisitor::UADDW(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { return true; } +bool TranslatorVisitor::UMLAL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { + if (size == 0b11) { + return ReservedValue(); + } + + MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::Accumulate, Signedness::Unsigned); + return true; +} + +bool TranslatorVisitor::UMLSL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { + if (size == 0b11) { + return ReservedValue(); + } + + MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::Subtract, Signedness::Unsigned); + return true; +} + +bool TranslatorVisitor::UMULL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { + if (size == 0b11) { + return ReservedValue(); + } + + MultiplyLong(*this, Q, size, Vm, Vn, Vd, MultiplyLongBehavior::None, Signedness::Unsigned); + return true; +} + bool TranslatorVisitor::USUBW(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { if (size == 0b11) { return ReservedValue();