diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index f8b4f018..4eec0016 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -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") diff --git a/src/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp b/src/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp index 0181b565..dcb2b52e 100644 --- a/src/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp +++ b/src/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp @@ -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((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();