A64: Implement SQSHRUN, SQRSHRUN (vector)
This commit is contained in:
parent
c5722ec963
commit
712c6c1d7e
2 changed files with 45 additions and 15 deletions
|
@ -811,8 +811,8 @@ INST(SRI_2, "SRI", "0Q101
|
|||
INST(SLI_2, "SLI", "0Q1011110IIIIiii010101nnnnnddddd")
|
||||
//INST(SQSHLU_2, "SQSHLU", "0Q1011110IIIIiii011001nnnnnddddd")
|
||||
//INST(UQSHL_imm_2, "UQSHL (immediate)", "0Q1011110IIIIiii011101nnnnnddddd")
|
||||
//INST(SQSHRUN_2, "SQSHRUN, SQSHRUN2", "0Q1011110IIIIiii100001nnnnnddddd")
|
||||
//INST(SQRSHRUN_2, "SQRSHRUN, SQRSHRUN2", "0Q1011110IIIIiii100011nnnnnddddd")
|
||||
INST(SQSHRUN_2, "SQSHRUN, SQSHRUN2", "0Q1011110IIIIiii100001nnnnnddddd")
|
||||
INST(SQRSHRUN_2, "SQRSHRUN, SQRSHRUN2", "0Q1011110IIIIiii100011nnnnnddddd")
|
||||
//INST(UQSHRN_2, "UQSHRN, UQSHRN2", "0Q1011110IIIIiii100101nnnnnddddd")
|
||||
//INST(UQRSHRN_2, "UQRSHRN, UQRSHRN2", "0Q1011110IIIIiii100111nnnnnddddd")
|
||||
INST(USHLL, "USHLL, USHLL2", "0Q1011110IIIIiii101001nnnnnddddd")
|
||||
|
|
|
@ -24,6 +24,17 @@ enum class Signedness {
|
|||
Unsigned
|
||||
};
|
||||
|
||||
enum class Narrowing {
|
||||
Truncation,
|
||||
SaturateToUnsigned,
|
||||
};
|
||||
|
||||
IR::U128 PerformRoundingCorrection(TranslatorVisitor& v, size_t esize, u64 round_value, IR::U128 original, IR::U128 shifted) {
|
||||
const IR::U128 round_const = v.ir.VectorBroadcast(esize, v.I(esize, round_value));
|
||||
const IR::U128 round_correction = v.ir.VectorEqual(esize, v.ir.VectorAnd(original, round_const), round_const);
|
||||
return v.ir.VectorSub(esize, shifted, round_correction);
|
||||
}
|
||||
|
||||
bool ShiftRight(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
|
||||
Rounding rounding, Accumulating accumulating, Signedness signedness) {
|
||||
if (immh == 0b0000) {
|
||||
|
@ -38,7 +49,6 @@ bool ShiftRight(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn,
|
|||
const size_t datasize = Q ? 128 : 64;
|
||||
|
||||
const u8 shift_amount = static_cast<u8>(2 * esize) - concatenate(immh, immb).ZeroExtend<u8>();
|
||||
const u64 round_value = 1ULL << (shift_amount - 1);
|
||||
|
||||
const IR::U128 operand = v.V(datasize, Vn);
|
||||
|
||||
|
@ -50,9 +60,8 @@ bool ShiftRight(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn,
|
|||
}();
|
||||
|
||||
if (rounding == Rounding::Round) {
|
||||
const IR::U128 round_const = v.ir.VectorBroadcast(esize, v.I(esize, round_value));
|
||||
const IR::U128 round_correction = v.ir.VectorEqual(esize, v.ir.VectorAnd(operand, round_const), round_const);
|
||||
result = v.ir.VectorSub(esize, result, round_correction);
|
||||
const u64 round_value = 1ULL << (shift_amount - 1);
|
||||
result = PerformRoundingCorrection(v, esize, round_value, operand, result);
|
||||
}
|
||||
|
||||
if (accumulating == Accumulating::Accumulate) {
|
||||
|
@ -65,7 +74,7 @@ bool ShiftRight(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn,
|
|||
}
|
||||
|
||||
bool ShiftRightNarrowing(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
|
||||
Rounding rounding) {
|
||||
Rounding rounding, Narrowing narrowing, Signedness signedness) {
|
||||
if (immh == 0b0000) {
|
||||
return v.DecodeError();
|
||||
}
|
||||
|
@ -79,19 +88,32 @@ bool ShiftRightNarrowing(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb,
|
|||
const size_t part = Q ? 1 : 0;
|
||||
|
||||
const u8 shift_amount = static_cast<u8>(source_esize - concatenate(immh, immb).ZeroExtend());
|
||||
const u64 round_value = 1ULL << (shift_amount - 1);
|
||||
|
||||
const IR::U128 operand = v.V(128, Vn);
|
||||
|
||||
IR::U128 wide_result = v.ir.VectorLogicalShiftRight(source_esize, operand, shift_amount);
|
||||
IR::U128 wide_result = [&] {
|
||||
if (signedness == Signedness::Signed) {
|
||||
return v.ir.VectorArithmeticShiftRight(source_esize, operand, shift_amount);
|
||||
}
|
||||
return v.ir.VectorLogicalShiftRight(source_esize, operand, shift_amount);
|
||||
}();
|
||||
|
||||
if (rounding == Rounding::Round) {
|
||||
const IR::U128 round_const = v.ir.VectorBroadcast(esize, v.I(esize, round_value));
|
||||
const IR::U128 round_correction = v.ir.VectorEqual(esize, v.ir.VectorAnd(operand, round_const), round_const);
|
||||
wide_result = v.ir.VectorSub(esize, wide_result, round_correction);
|
||||
const u64 round_value = 1ULL << (shift_amount - 1);
|
||||
wide_result = PerformRoundingCorrection(v, source_esize, round_value, operand, wide_result);
|
||||
}
|
||||
|
||||
const IR::U128 result = v.ir.VectorNarrow(source_esize, wide_result);
|
||||
const IR::U128 result = [&] {
|
||||
switch (narrowing) {
|
||||
case Narrowing::Truncation:
|
||||
return v.ir.VectorNarrow(source_esize, wide_result);
|
||||
case Narrowing::SaturateToUnsigned:
|
||||
ASSERT(signedness == Signedness::Signed);
|
||||
return v.ir.VectorSignedSaturatedNarrowToUnsigned(source_esize, wide_result);
|
||||
}
|
||||
UNREACHABLE();
|
||||
return IR::U128{};
|
||||
}();
|
||||
|
||||
v.Vpart(64, Vd, part, result);
|
||||
return true;
|
||||
|
@ -163,11 +185,19 @@ bool TranslatorVisitor::SHL_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd)
|
|||
}
|
||||
|
||||
bool TranslatorVisitor::SHRN(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
|
||||
return ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, Rounding::None);
|
||||
return ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, Rounding::None, Narrowing::Truncation, Signedness::Unsigned);
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::RSHRN(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
|
||||
return ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, Rounding::Round);
|
||||
return ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, Rounding::Round, Narrowing::Truncation, Signedness::Unsigned);
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::SQSHRUN_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
|
||||
return ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, Rounding::None, Narrowing::SaturateToUnsigned, Signedness::Signed);
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::SQRSHRUN_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
|
||||
return ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, Rounding::Round, Narrowing::SaturateToUnsigned, Signedness::Signed);
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::SSHLL(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
|
||||
|
|
Loading…
Reference in a new issue