ASIMD: Implement VCVT (between half-precision and single-precision)

This commit is contained in:
MerryMage 2021-05-16 23:48:29 +01:00
parent d93145bd04
commit c6ecc835b6
3 changed files with 36 additions and 1 deletions

View file

@ -126,7 +126,7 @@ INST(arm_UDF, "UNALLOCATED (VRINTA)", "111100111-11--10----010
INST(arm_UDF, "UNALLOCATED (VRINTZ)", "111100111-11--10----01011--0----")
INST(arm_UDF, "UNALLOCATED (VRINTM)", "111100111-11--10----01101--0----")
INST(arm_UDF, "UNALLOCATED (VRINTP)", "111100111-11--10----01111--0----")
INST(arm_UDF, "UNALLOCATED (VCVT half)", "111100111-11--10----011-00-0----") // ASIMD
INST(asimd_VCVT_half, "VCVT (half-precision)", "111100111D11zz10dddd011o00M0mmmm") // ASIMD
INST(arm_UDF, "UNALLOCATED", "111100111-11--10----011-01-0----") // ASIMD
INST(arm_UDF, "UNALLOCATED (VCVTA)", "111100111-11--11----0000---0----")
INST(arm_UDF, "UNALLOCATED (VCVTN)", "111100111-11--11----0001---0----")

View file

@ -611,6 +611,40 @@ bool TranslatorVisitor::asimd_VSHLL_max(bool D, size_t sz, size_t Vd, bool M, si
return true;
}
bool TranslatorVisitor::asimd_VCVT_half(bool D, size_t sz, size_t Vd, bool half_to_single, bool M, size_t Vm) {
if (sz != 0b01) {
return UndefinedInstruction();
}
if (half_to_single && Common::Bit<0>(Vd)) {
return UndefinedInstruction();
}
if (!half_to_single && Common::Bit<0>(Vm)) {
return UndefinedInstruction();
}
const size_t esize = 8U << sz;
const size_t num_elements = 4;
const auto rounding_mode = FP::RoundingMode::ToNearest_TieEven; // StandardFPSCRValue().RMode
const auto d = ToVector(half_to_single, Vd, D);
const auto m = ToVector(!half_to_single, Vm, M);
const auto operand = ir.GetVector(m);
IR::U128 result = ir.ZeroVector();
for (size_t i = 0; i < num_elements; i++) {
if (half_to_single) {
const IR::U16 old_element = ir.VectorGetElement(esize, operand, i);
const IR::U32 new_element = ir.FPHalfToSingle(old_element, rounding_mode);
result = ir.VectorSetElement(esize * 2, result, i, new_element);
} else {
const IR::U32 old_element = ir.VectorGetElement(esize * 2, operand, i);
const IR::U16 new_element = ir.FPSingleToHalf(old_element, rounding_mode);
result = ir.VectorSetElement(esize, result, i, new_element);
}
}
ir.SetVector(d, result);
return true;
}
bool TranslatorVisitor::asimd_VRECPE(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm) {
if (Q && (Common::Bit<0>(Vd) || Common::Bit<0>(Vm))) {
return UndefinedInstruction();

View file

@ -940,6 +940,7 @@ struct TranslatorVisitor final {
bool asimd_VQMOVUN(bool D, size_t sz, size_t Vd, bool M, size_t Vm);
bool asimd_VQMOVN(bool D, size_t sz, size_t Vd, bool op, bool M, size_t Vm);
bool asimd_VSHLL_max(bool D, size_t sz, size_t Vd, bool M, size_t Vm);
bool asimd_VCVT_half(bool D, size_t sz, size_t Vd, bool op, bool M, size_t Vm);
bool asimd_VRECPE(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm);
bool asimd_VRSQRTE(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm);
bool asimd_VCVT_integer(bool D, size_t sz, size_t Vd, bool op, bool U, bool Q, bool M, size_t Vm);