A64: Implement SQDMULH's by-element scalar variant

This commit is contained in:
Lioncash 2018-09-07 18:15:50 -04:00 committed by MerryMage
parent 40f0576995
commit f5fb496e7e
3 changed files with 28 additions and 2 deletions

View file

@ -497,7 +497,7 @@ INST(FCVTZU_fix_1, "FCVTZU (vector, fixed-point)", "01111
//INST(SQDMLAL_elt_1, "SQDMLAL, SQDMLAL2 (by element)", "01011111zzLMmmmm0011H0nnnnnddddd")
//INST(SQDMLSL_elt_1, "SQDMLSL, SQDMLSL2 (by element)", "01011111zzLMmmmm0111H0nnnnnddddd")
//INST(SQDMULL_elt_1, "SQDMULL, SQDMULL2 (by element)", "01011111zzLMmmmm1011H0nnnnnddddd")
//INST(SQDMULH_elt_1, "SQDMULH (by element)", "01011111zzLMmmmm1100H0nnnnnddddd")
INST(SQDMULH_elt_1, "SQDMULH (by element)", "01011111zzLMmmmm1100H0nnnnnddddd")
//INST(SQRDMULH_elt_1, "SQRDMULH (by element)", "01011111zzLMmmmm1101H0nnnnnddddd")
//INST(FMLA_elt_1, "FMLA (by element)", "0101111100LMmmmm0001H0nnnnnddddd")
INST(FMLA_elt_2, "FMLA (by element)", "010111111zLMmmmm0001H0nnnnnddddd")

View file

@ -606,7 +606,7 @@ struct TranslatorVisitor final {
bool SQDMLAL_elt_1(Imm<2> size, bool L, bool M, Vec Vm, bool H, Reg Rn, Vec Vd);
bool SQDMLSL_elt_1(Imm<2> size, bool L, bool M, Vec Vm, bool H, Reg Rn, Vec Vd);
bool SQDMULL_elt_1(Imm<2> size, bool L, bool M, Vec Vm, bool H, Reg Rn, Vec Vd);
bool SQDMULH_elt_1(Imm<2> size, bool L, bool M, Vec Vm, bool H, Vec Vn, Vec Vd);
bool SQDMULH_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd);
bool SQRDMULH_elt_1(Imm<2> size, bool L, bool M, Vec Vm, bool H, Vec Vn, Vec Vd);
bool FMLA_elt_1(Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd);
bool FMLA_elt_2(bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd);

View file

@ -4,6 +4,7 @@
* General Public License version 2 or any later version.
*/
#include <utility>
#include "frontend/A64/translate/impl/impl.h"
namespace Dynarmic::A64 {
@ -58,4 +59,29 @@ bool TranslatorVisitor::FMUL_elt_2(bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm
return MultiplyByElement(*this, sz, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::None);
}
bool TranslatorVisitor::SQDMULH_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
if (size == 0b00 || size == 0b11) {
return UnallocatedEncoding();
}
const size_t esize = 8 << size.ZeroExtend();
const auto [index, Vmhi] = [=] {
if (size == 0b01) {
return std::make_pair(concatenate(H, L, M).ZeroExtend(), Imm<1>{0});
}
return std::make_pair(concatenate(H, L).ZeroExtend(), M);
}();
const Vec Vm = concatenate(Vmhi, Vmlo).ZeroExtend<Vec>();
const IR::UAny operand1 = V_scalar(esize, Vn);
const IR::UAny operand2 = ir.VectorGetElement(esize, V(128, Vm), index);
const auto result = ir.SignedSaturatedDoublingMultiplyReturnHigh(operand1, operand2);
ir.OrQC(result.overflow);
V_scalar(esize, Vd, result.result);
return true;
}
} // namespace Dynarmic::A64