From 26d44738517ac00804697fa280bc00f3c08406ad Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 12 May 2018 14:56:24 -0400 Subject: [PATCH] A64: Implement UABAL/UABAL2 --- src/frontend/A64/decoder/a64.inc | 2 +- .../translate/impl/simd_three_different.cpp | 41 +++++++++++++++---- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index 52858b94..da4f3b1e 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -693,7 +693,7 @@ INST(UADDW, "UADDW, UADDW2", "0Q101 INST(USUBL, "USUBL, USUBL2", "0Q101110zz1mmmmm001000nnnnnddddd") INST(USUBW, "USUBW, USUBW2", "0Q101110zz1mmmmm001100nnnnnddddd") INST(RADDHN, "RADDHN, RADDHN2", "0Q101110zz1mmmmm010000nnnnnddddd") -//INST(UABAL, "UABAL, UABAL2", "0Q101110zz1mmmmm010100nnnnnddddd") +INST(UABAL, "UABAL, UABAL2", "0Q101110zz1mmmmm010100nnnnnddddd") INST(RSUBHN, "RSUBHN, RSUBHN2", "0Q101110zz1mmmmm011000nnnnnddddd") INST(UABDL, "UABDL, UABDL2", "0Q101110zz1mmmmm011100nnnnnddddd") //INST(UMLAL_vec, "UMLAL, UMLAL2 (vector)", "0Q101110zz1mmmmm100000nnnnnddddd") diff --git a/src/frontend/A64/translate/impl/simd_three_different.cpp b/src/frontend/A64/translate/impl/simd_three_different.cpp index 1a58d133..82b5e94e 100644 --- a/src/frontend/A64/translate/impl/simd_three_different.cpp +++ b/src/frontend/A64/translate/impl/simd_three_different.cpp @@ -7,6 +7,29 @@ #include "frontend/A64/translate/impl/impl.h" namespace Dynarmic::A64 { +namespace { +enum class AbsoluteDifferenceBehavior { + None, + Accumulate +}; + +void UnsignedAbsoluteDifferenceLong(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, + AbsoluteDifferenceBehavior behavior) { + const size_t esize = 8 << size.ZeroExtend(); + const size_t datasize = 64; + + const IR::U128 operand1 = v.ir.VectorZeroExtend(esize, v.Vpart(datasize, Vn, Q)); + const IR::U128 operand2 = v.ir.VectorZeroExtend(esize, v.Vpart(datasize, Vm, Q)); + IR::U128 result = v.ir.VectorUnsignedAbsoluteDifference(esize, operand1, operand2); + + if (behavior == AbsoluteDifferenceBehavior::Accumulate) { + const IR::U128 data = v.V(2 * datasize, Vd); + result = v.ir.VectorAdd(2 * esize, result, data); + } + + v.V(2 * datasize, Vd, result); +} +} // Anonymous namespace bool TranslatorVisitor::SADDL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { if (size == 0b11) { @@ -88,19 +111,21 @@ bool TranslatorVisitor::UADDL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { return true; } +bool TranslatorVisitor::UABAL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { + if (size == 0b11) { + return ReservedValue(); + } + + UnsignedAbsoluteDifferenceLong(*this, Q, size, Vm, Vn, Vd, AbsoluteDifferenceBehavior::Accumulate); + return true; +} + bool TranslatorVisitor::UABDL(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { if (size == 0b11) { return ReservedValue(); } - const size_t esize = 8 << size.ZeroExtend(); - const size_t datasize = 64; - - const IR::U128 operand1 = ir.VectorZeroExtend(esize, Vpart(datasize, Vn, Q)); - const IR::U128 operand2 = ir.VectorZeroExtend(esize, Vpart(datasize, Vm, Q)); - const IR::U128 result = ir.VectorUnsignedAbsoluteDifference(esize, operand1, operand2); - - V(2 * datasize, Vd, result); + UnsignedAbsoluteDifferenceLong(*this, Q, size, Vm, Vn, Vd, AbsoluteDifferenceBehavior::None); return true; }