diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index 84cf2794..ca54d39d 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -477,7 +477,7 @@ INST(SHL_1, "SHL", "01011 //INST(SQSHRN_1, "SQSHRN, SQSHRN2", "010111110IIIIiii100101nnnnnddddd") //INST(SQRSHRN_1, "SQRSHRN, SQRSHRN2", "010111110IIIIiii100111nnnnnddddd") //INST(SCVTF_fix_1, "SCVTF (vector, fixed-point)", "010111110IIIIiii111001nnnnnddddd") -//INST(FCVTZS_fix_1, "FCVTZS (vector, fixed-point)", "010111110IIIIiii111111nnnnnddddd") +INST(FCVTZS_fix_1, "FCVTZS (vector, fixed-point)", "010111110IIIIiii111111nnnnnddddd") INST(USHR_1, "USHR", "011111110IIIIiii000001nnnnnddddd") INST(USRA_1, "USRA", "011111110IIIIiii000101nnnnnddddd") INST(URSHR_1, "URSHR", "011111110IIIIiii001001nnnnnddddd") @@ -491,7 +491,7 @@ INST(SLI_1, "SLI", "01111 //INST(UQSHRN_1, "UQSHRN, UQSHRN2", "011111110IIIIiii100101nnnnnddddd") //INST(UQRSHRN_1, "UQRSHRN, UQRSHRN2", "011111110IIIIiii100111nnnnnddddd") //INST(UCVTF_fix_1, "UCVTF (vector, fixed-point)", "011111110IIIIiii111001nnnnnddddd") -//INST(FCVTZU_fix_1, "FCVTZU (vector, fixed-point)", "011111110IIIIiii111111nnnnnddddd") +INST(FCVTZU_fix_1, "FCVTZU (vector, fixed-point)", "011111110IIIIiii111111nnnnnddddd") // Data Processing - FP and SIMD - SIMD Scalar x indexed element //INST(SQDMLAL_elt_1, "SQDMLAL, SQDMLAL2 (by element)", "01011111zzLMmmmm0011H0nnnnnddddd") 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 dcb2b52e..238f2edc 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 @@ -7,7 +7,7 @@ #include "frontend/A64/translate/impl/impl.h" namespace Dynarmic::A64 { - +namespace { enum class ShiftExtraBehavior { None, Accumulate, @@ -18,8 +18,8 @@ enum class Signedness { Unsigned, }; -static void ShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, - ShiftExtraBehavior behavior, Signedness signedness) { +void ShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, + ShiftExtraBehavior behavior, Signedness signedness) { const size_t esize = 64; const u8 shift_amount = static_cast((esize * 2) - concatenate(immh, immb).ZeroExtend()); @@ -39,8 +39,8 @@ static void ShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, V v.V_scalar(esize, Vd, result); } -static void RoundingShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, - ShiftExtraBehavior behavior, Signedness signedness) { +void RoundingShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, + ShiftExtraBehavior behavior, Signedness signedness) { const size_t esize = 64; const u8 shift_amount = static_cast((esize * 2) - concatenate(immh, immb).ZeroExtend()); @@ -71,8 +71,8 @@ enum class ShiftDirection { Right, }; -static void ShiftAndInsert(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, - ShiftDirection direction) { +void ShiftAndInsert(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, + ShiftDirection direction) { const size_t esize = 64; const u8 shift_amount = [&] { @@ -106,6 +106,52 @@ static void ShiftAndInsert(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec V v.V_scalar(esize, Vd, result); } +bool ScalarFPConvertWithRound(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, Signedness sign) { + const u32 immh_value = immh.ZeroExtend(); + + if ((immh_value & 0b1110) == 0b0000) { + return v.ReservedValue(); + } + + // TODO: We currently don't handle FP16, so bail like the ARM reference manual allows. + if ((immh_value & 0b1110) == 0b0010) { + return v.ReservedValue(); + } + + const size_t esize = (immh_value & 0b1000) != 0 ? 64 : 32; + const size_t concat = concatenate(immh, immb).ZeroExtend(); + const size_t fbits = (esize * 2) - concat; + + const IR::U32U64 operand = v.V_scalar(esize, Vn); + const IR::U32U64 result = [&]() -> IR::U32U64 { + if (esize == 64) { + if (sign == Signedness::Signed) { + return v.ir.FPDoubleToFixedS64(operand, fbits, FP::RoundingMode::TowardsZero); + } + + return v.ir.FPDoubleToFixedU64(operand, fbits, FP::RoundingMode::TowardsZero); + } + + if (sign == Signedness::Signed) { + return v.ir.FPSingleToFixedS32(operand, fbits, FP::RoundingMode::TowardsZero); + } + + return v.ir.FPSingleToFixedU32(operand, fbits, FP::RoundingMode::TowardsZero); + }(); + + v.V_scalar(esize, Vd, result); + return true; +} +} // Anonymous namespace + +bool TranslatorVisitor::FCVTZS_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { + return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, Signedness::Signed); +} + +bool TranslatorVisitor::FCVTZU_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { + return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, Signedness::Unsigned); +} + bool TranslatorVisitor::SLI_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { if (!immh.Bit<3>()) { return ReservedValue();