A64: Implement URSHR (scalar) and URSRA (scalar)

Now that the utility function is all set up from implementing SRSRA, the
unsigned variants can now be trivially implemented by modifying the
utility function to perform a logical shift right instead of an
arithmetical shift right for the unsigned case.
This commit is contained in:
Lioncash 2018-05-11 10:42:31 -04:00 committed by MerryMage
parent 1e70a589b0
commit 7bce8d8757
2 changed files with 31 additions and 6 deletions

View file

@ -480,8 +480,8 @@ INST(SHL_1, "SHL", "01011
//INST(FCVTZS_fix_1, "FCVTZS (vector, fixed-point)", "010111110IIIIiii111111nnnnnddddd")
INST(USHR_1, "USHR", "011111110IIIIiii000001nnnnnddddd")
INST(USRA_1, "USRA", "011111110IIIIiii000101nnnnnddddd")
//INST(URSHR_1, "URSHR", "011111110IIIIiii001001nnnnnddddd")
//INST(URSRA_1, "URSRA", "011111110IIIIiii001101nnnnnddddd")
INST(URSHR_1, "URSHR", "011111110IIIIiii001001nnnnnddddd")
INST(URSRA_1, "URSRA", "011111110IIIIiii001101nnnnnddddd")
INST(SRI_1, "SRI", "011111110IIIIiii010001nnnnnddddd")
INST(SLI_1, "SLI", "011111110IIIIiii010101nnnnnddddd")
//INST(SQSHLU_1, "SQSHLU", "011111110IIIIiii011001nnnnnddddd")

View file

@ -40,14 +40,21 @@ static void ShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, V
}
static void RoundingShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
ShiftExtraBehavior behavior) {
ShiftExtraBehavior behavior, Signedness signedness) {
const size_t esize = 64;
const u8 shift_amount = static_cast<u8>((esize * 2) - concatenate(immh, immb).ZeroExtend());
const IR::U64 operand = v.V_scalar(esize, Vn);
const IR::U64 round_bit = v.ir.LogicalShiftRight(v.ir.LogicalShiftLeft(operand, v.ir.Imm8(64 - shift_amount)), v.ir.Imm8(63));
const IR::U64 result = [&] {
IR::U64 tmp = v.ir.Add(v.ir.ArithmeticShiftRight(operand, v.ir.Imm8(shift_amount)), round_bit);
const IR::U64 shifted = [&]() -> IR::U64 {
if (signedness == Signedness::Signed) {
return v.ir.ArithmeticShiftRight(operand, v.ir.Imm8(shift_amount));
}
return v.ir.LogicalShiftRight(operand, v.ir.Imm8(shift_amount));
}();
IR::U64 tmp = v.ir.Add(shifted, round_bit);
if (behavior == ShiftExtraBehavior::Accumulate) {
tmp = v.ir.Add(tmp, v.V_scalar(esize, Vd));
@ -122,7 +129,7 @@ bool TranslatorVisitor::SRSHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
return ReservedValue();
}
RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None);
RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Signed);
return true;
}
@ -131,7 +138,7 @@ bool TranslatorVisitor::SRSRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
return ReservedValue();
}
RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate);
RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Signed);
return true;
}
@ -168,6 +175,24 @@ bool TranslatorVisitor::SHL_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
return true;
}
bool TranslatorVisitor::URSHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (!immh.Bit<3>()) {
return ReservedValue();
}
RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Unsigned);
return true;
}
bool TranslatorVisitor::URSRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (!immh.Bit<3>()) {
return ReservedValue();
}
RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Unsigned);
return true;
}
bool TranslatorVisitor::USHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (!immh.Bit<3>()) {
return ReservedValue();