diff --git a/src/backend_x64/emit_x64_vector.cpp b/src/backend_x64/emit_x64_vector.cpp index 8a3e8e94..23e949bb 100644 --- a/src/backend_x64/emit_x64_vector.cpp +++ b/src/backend_x64/emit_x64_vector.cpp @@ -2385,25 +2385,25 @@ void EmitX64::EmitVectorRoundingShiftLeftS64(EmitContext& ctx, IR::Inst* inst) { } void EmitX64::EmitVectorRoundingShiftLeftU8(EmitContext& ctx, IR::Inst* inst) { - EmitTwoArgumentFallback(code, ctx, inst, [](VectorArray& result, const VectorArray& lhs, const VectorArray& rhs) { + EmitTwoArgumentFallback(code, ctx, inst, [](VectorArray& result, const VectorArray& lhs, const VectorArray& rhs) { RoundingShiftLeft(result, lhs, rhs); }); } void EmitX64::EmitVectorRoundingShiftLeftU16(EmitContext& ctx, IR::Inst* inst) { - EmitTwoArgumentFallback(code, ctx, inst, [](VectorArray& result, const VectorArray& lhs, const VectorArray& rhs) { + EmitTwoArgumentFallback(code, ctx, inst, [](VectorArray& result, const VectorArray& lhs, const VectorArray& rhs) { RoundingShiftLeft(result, lhs, rhs); }); } void EmitX64::EmitVectorRoundingShiftLeftU32(EmitContext& ctx, IR::Inst* inst) { - EmitTwoArgumentFallback(code, ctx, inst, [](VectorArray& result, const VectorArray& lhs, const VectorArray& rhs) { + EmitTwoArgumentFallback(code, ctx, inst, [](VectorArray& result, const VectorArray& lhs, const VectorArray& rhs) { RoundingShiftLeft(result, lhs, rhs); }); } void EmitX64::EmitVectorRoundingShiftLeftU64(EmitContext& ctx, IR::Inst* inst) { - EmitTwoArgumentFallback(code, ctx, inst, [](VectorArray& result, const VectorArray& lhs, const VectorArray& rhs) { + EmitTwoArgumentFallback(code, ctx, inst, [](VectorArray& result, const VectorArray& lhs, const VectorArray& rhs) { RoundingShiftLeft(result, lhs, rhs); }); } diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index 5f9cd343..00b359a6 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -450,7 +450,7 @@ INST(CMGT_reg_1, "CMGT (register)", "01011 INST(CMGE_reg_1, "CMGE (register)", "01011110zz1mmmmm001111nnnnnddddd") INST(SSHL_1, "SSHL", "01011110zz1mmmmm010001nnnnnddddd") //INST(SQSHL_reg_1, "SQSHL (register)", "01011110zz1mmmmm010011nnnnnddddd") -//INST(SRSHL_1, "SRSHL", "01011110zz1mmmmm010101nnnnnddddd") +INST(SRSHL_1, "SRSHL", "01011110zz1mmmmm010101nnnnnddddd") //INST(SQRSHL_1, "SQRSHL", "01011110zz1mmmmm010111nnnnnddddd") INST(ADD_1, "ADD (vector)", "01011110zz1mmmmm100001nnnnnddddd") INST(CMTST_1, "CMTST", "01011110zz1mmmmm100011nnnnnddddd") @@ -461,7 +461,7 @@ INST(CMHI_1, "CMHI (register)", "01111 INST(CMHS_1, "CMHS (register)", "01111110zz1mmmmm001111nnnnnddddd") INST(USHL_1, "USHL", "01111110zz1mmmmm010001nnnnnddddd") //INST(UQSHL_reg_1, "UQSHL (register)", "01111110zz1mmmmm010011nnnnnddddd") -//INST(URSHL_1, "URSHL", "01111110zz1mmmmm010101nnnnnddddd") +INST(URSHL_1, "URSHL", "01111110zz1mmmmm010101nnnnnddddd") //INST(UQRSHL_1, "UQRSHL", "01111110zz1mmmmm010111nnnnnddddd") INST(SUB_1, "SUB (vector)", "01111110zz1mmmmm100001nnnnnddddd") INST(CMEQ_reg_1, "CMEQ (register)", "01111110zz1mmmmm100011nnnnnddddd") @@ -710,7 +710,7 @@ INST(CMGT_reg_2, "CMGT (register)", "0Q001 INST(CMGE_reg_2, "CMGE (register)", "0Q001110zz1mmmmm001111nnnnnddddd") INST(SSHL_2, "SSHL", "0Q001110zz1mmmmm010001nnnnnddddd") //INST(SQSHL_reg_2, "SQSHL (register)", "0Q001110zz1mmmmm010011nnnnnddddd") -//INST(SRSHL_2, "SRSHL", "0Q001110zz1mmmmm010101nnnnnddddd") +INST(SRSHL_2, "SRSHL", "0Q001110zz1mmmmm010101nnnnnddddd") //INST(SQRSHL_2, "SQRSHL", "0Q001110zz1mmmmm010111nnnnnddddd") INST(SMAX, "SMAX", "0Q001110zz1mmmmm011001nnnnnddddd") INST(SMIN, "SMIN", "0Q001110zz1mmmmm011011nnnnnddddd") @@ -751,7 +751,7 @@ INST(CMHI_2, "CMHI (register)", "0Q101 INST(CMHS_2, "CMHS (register)", "0Q101110zz1mmmmm001111nnnnnddddd") INST(USHL_2, "USHL", "0Q101110zz1mmmmm010001nnnnnddddd") //INST(UQSHL_reg_2, "UQSHL (register)", "0Q101110zz1mmmmm010011nnnnnddddd") -//INST(URSHL_2, "URSHL", "0Q101110zz1mmmmm010101nnnnnddddd") +INST(URSHL_2, "URSHL", "0Q101110zz1mmmmm010101nnnnnddddd") //INST(UQRSHL_2, "UQRSHL", "0Q101110zz1mmmmm010111nnnnnddddd") INST(UMAX, "UMAX", "0Q101110zz1mmmmm011001nnnnnddddd") INST(UMIN, "UMIN", "0Q101110zz1mmmmm011011nnnnnddddd") diff --git a/src/frontend/A64/translate/impl/simd_scalar_three_same.cpp b/src/frontend/A64/translate/impl/simd_scalar_three_same.cpp index 2a7260f5..cb3bf880 100644 --- a/src/frontend/A64/translate/impl/simd_scalar_three_same.cpp +++ b/src/frontend/A64/translate/impl/simd_scalar_three_same.cpp @@ -25,6 +25,30 @@ enum class ComparisonVariant { Zero, }; +enum class Signedness { + Signed, + Unsigned, +}; + +bool RoundingShiftLeft(TranslatorVisitor& v, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, Signedness sign) { + if (size != 0b11) { + return v.ReservedValue(); + } + + const IR::U128 operand1 = v.V(64, Vn); + const IR::U128 operand2 = v.V(64, Vm); + const IR::U128 result = [&] { + if (sign == Signedness::Signed) { + return v.ir.VectorRoundingShiftLeftSigned(64, operand1, operand2); + } + + return v.ir.VectorRoundingShiftLeftUnsigned(64, operand1, operand2); + }(); + + v.V(64, Vd, result); + return true; +} + bool ScalarCompare(TranslatorVisitor& v, Imm<2> size, boost::optional Vm, Vec Vn, Vec Vd, ComparisonType type, ComparisonVariant variant) { if (size != 0b11) { @@ -278,6 +302,10 @@ bool TranslatorVisitor::FCMGT_reg_2(bool sz, Vec Vm, Vec Vn, Vec Vd) { return ScalarFPCompareRegister(*this, sz, Vm, Vn, Vd, FPComparisonType::GT); } +bool TranslatorVisitor::SRSHL_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { + return RoundingShiftLeft(*this, size, Vm, Vn, Vd, Signedness::Signed); +} + bool TranslatorVisitor::SSHL_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { if (size != 0b11) { return ReservedValue(); @@ -305,6 +333,10 @@ bool TranslatorVisitor::SUB_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { return true; } +bool TranslatorVisitor::URSHL_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { + return RoundingShiftLeft(*this, size, Vm, Vn, Vd, Signedness::Unsigned); +} + bool TranslatorVisitor::USHL_1(Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { if (size != 0b11) { return ReservedValue(); diff --git a/src/frontend/A64/translate/impl/simd_three_same.cpp b/src/frontend/A64/translate/impl/simd_three_same.cpp index 4217b528..06da5ea6 100644 --- a/src/frontend/A64/translate/impl/simd_three_same.cpp +++ b/src/frontend/A64/translate/impl/simd_three_same.cpp @@ -102,6 +102,28 @@ bool RoundingHalvingAdd(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec V return true; } +bool RoundingShiftLeft(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, Signedness sign) { + if (size == 0b11 && !Q) { + return v.ReservedValue(); + } + + const size_t esize = 8 << size.ZeroExtend(); + const size_t datasize = Q ? 128 : 64; + + const IR::U128 operand1 = v.V(datasize, Vn); + const IR::U128 operand2 = v.V(datasize, Vm); + const IR::U128 result = [&] { + if (sign == Signedness::Signed) { + return v.ir.VectorRoundingShiftLeftSigned(esize, operand1, operand2); + } + + return v.ir.VectorRoundingShiftLeftUnsigned(esize, operand1, operand2); + }(); + + v.V(datasize, Vd, result); + return true; +} + enum class ComparisonType { EQ, GE, @@ -723,6 +745,10 @@ bool TranslatorVisitor::CMTST_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { return true; } +bool TranslatorVisitor::SRSHL_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { + return RoundingShiftLeft(*this, Q, size, Vm, Vn, Vd, Signedness::Signed); +} + bool TranslatorVisitor::SSHL_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { if (size == 0b11 && !Q) { return ReservedValue(); @@ -737,6 +763,10 @@ bool TranslatorVisitor::SSHL_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { return true; } +bool TranslatorVisitor::URSHL_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { + return RoundingShiftLeft(*this, Q, size, Vm, Vn, Vd, Signedness::Unsigned); +} + bool TranslatorVisitor::USHL_2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { if (size == 0b11 && !Q) { return ReservedValue();