ASIMD: Implement VCVT (between half-precision and single-precision)
This commit is contained in:
parent
d93145bd04
commit
c6ecc835b6
3 changed files with 36 additions and 1 deletions
|
@ -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----")
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue