diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index df52f329..7334de8e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -106,6 +106,7 @@ add_library(dynarmic frontend/A64/translate/impl/load_store_register_unprivileged.cpp frontend/A64/translate/impl/load_store_single_structure.cpp frontend/A64/translate/impl/move_wide.cpp + frontend/A64/translate/impl/simd_across_lanes.cpp frontend/A64/translate/impl/simd_aes.cpp frontend/A64/translate/impl/simd_copy.cpp frontend/A64/translate/impl/simd_crypto_four_register.cpp diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index 06f90427..251cb362 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -662,7 +662,7 @@ INST(FCMLE_4, "FCMLE (zero)", "0Q101 //INST(SADDLV, "SADDLV", "0Q001110zz110000001110nnnnnddddd") //INST(SMAXV, "SMAXV", "0Q001110zz110000101010nnnnnddddd") //INST(SMINV, "SMINV", "0Q001110zz110001101010nnnnnddddd") -//INST(ADDV, "ADDV", "0Q001110zz110001101110nnnnnddddd") +INST(ADDV, "ADDV", "0Q001110zz110001101110nnnnnddddd") //INST(FMAXNMV_1, "FMAXNMV", "0Q00111000110000110010nnnnnddddd") //INST(FMAXNMV_2, "FMAXNMV", "0Q1011100z110000110010nnnnnddddd") //INST(FMAXV_1, "FMAXV", "0Q00111000110000111110nnnnnddddd") diff --git a/src/frontend/A64/translate/impl/simd_across_lanes.cpp b/src/frontend/A64/translate/impl/simd_across_lanes.cpp new file mode 100644 index 00000000..dc9a0202 --- /dev/null +++ b/src/frontend/A64/translate/impl/simd_across_lanes.cpp @@ -0,0 +1,42 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2018 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#include "frontend/A64/translate/impl/impl.h" + +namespace Dynarmic::A64 { + +bool TranslatorVisitor::ADDV(bool Q, Imm<2> size, Vec Vn, Vec Vd) { + if ((size == 0b10 && !Q) || size == 0b11) { + return ReservedValue(); + } + + const size_t esize = 8 << size.ZeroExtend(); + const size_t datasize = Q ? 128 : 64; + const size_t elements = datasize / esize; + + const IR::U128 operand = V(datasize, Vn); + + const auto get_element = [&](IR::U128 vec, size_t element) { + return ir.ZeroExtendToWord(ir.VectorGetElement(esize, vec, element)); + }; + + IR::U32 sum = get_element(operand, 0); + for (size_t i = 1; i < elements; i++) { + sum = ir.Add(sum, get_element(operand, i)); + } + + if (size == 0b00) { + V(datasize, Vd, ir.ZeroExtendToQuad(ir.LeastSignificantByte(sum))); + } else if (size == 0b01) { + V(datasize, Vd, ir.ZeroExtendToQuad(ir.LeastSignificantHalf(sum))); + } else { + V(datasize, Vd, ir.ZeroExtendToQuad(sum)); + } + + return true; +} + +} // namespace Dynarmic::A64