diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index 4d245f28..b2498072 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -878,8 +878,8 @@ INST(SHA512SU0, "SHA512SU0", "11001 INST(SM4E, "SM4E", "1100111011000000100001nnnnnddddd") // Data Processing - FP and SIMD - Conversion between floating point and fixed point -//INST(SCVTF_float_fix, "SCVTF (scalar, fixed-point)", "z0011110yy000010ppppppnnnnnddddd") -//INST(UCVTF_float_fix, "UCVTF (scalar, fixed-point)", "z0011110yy000011ppppppnnnnnddddd") +INST(SCVTF_float_fix, "SCVTF (scalar, fixed-point)", "z0011110yy000010ppppppnnnnnddddd") +INST(UCVTF_float_fix, "UCVTF (scalar, fixed-point)", "z0011110yy000011ppppppnnnnnddddd") INST(FCVTZS_float_fix, "FCVTZS (scalar, fixed-point)", "z0011110yy011000ppppppnnnnnddddd") INST(FCVTZU_float_fix, "FCVTZU (scalar, fixed-point)", "z0011110yy011001ppppppnnnnnddddd") diff --git a/src/frontend/A64/translate/impl/floating_point_conversion_fixed_point.cpp b/src/frontend/A64/translate/impl/floating_point_conversion_fixed_point.cpp index 4d3b9011..f2c6f350 100644 --- a/src/frontend/A64/translate/impl/floating_point_conversion_fixed_point.cpp +++ b/src/frontend/A64/translate/impl/floating_point_conversion_fixed_point.cpp @@ -10,6 +10,62 @@ namespace Dynarmic::A64 { +bool TranslatorVisitor::SCVTF_float_fix(bool sf, Imm<2> type, Imm<6> scale, Reg Rn, Vec Vd) { + const size_t intsize = sf ? 64 : 32; + const auto fltsize = FPGetDataSize(type); + if (!fltsize || *fltsize == 16) { + return UnallocatedEncoding(); + } + if (!sf && !scale.Bit<5>()) { + return UnallocatedEncoding(); + } + const u8 fracbits = 64 - scale.ZeroExtend(); + const FP::RoundingMode rounding_mode = ir.current_location->FPCR().RMode(); + + const IR::U32U64 intval = X(intsize, Rn); + const IR::U32U64 fltval = [&]() -> IR::U32U64 { + switch (*fltsize) { + case 32: + return ir.FPSignedFixedToSingle(intval, fracbits, rounding_mode); + case 64: + return ir.FPSignedFixedToDouble(intval, fracbits, rounding_mode); + } + UNREACHABLE(); + return {}; + }(); + + V_scalar(*fltsize, Vd, fltval); + return true; +} + +bool TranslatorVisitor::UCVTF_float_fix(bool sf, Imm<2> type, Imm<6> scale, Reg Rn, Vec Vd) { + const size_t intsize = sf ? 64 : 32; + const auto fltsize = FPGetDataSize(type); + if (!fltsize || *fltsize == 16) { + return UnallocatedEncoding(); + } + if (!sf && !scale.Bit<5>()) { + return UnallocatedEncoding(); + } + const u8 fracbits = 64 - scale.ZeroExtend(); + const FP::RoundingMode rounding_mode = ir.current_location->FPCR().RMode(); + + const IR::U32U64 intval = X(intsize, Rn); + const IR::U32U64 fltval = [&]() -> IR::U32U64 { + switch (*fltsize) { + case 32: + return ir.FPUnsignedFixedToSingle(intval, fracbits, rounding_mode); + case 64: + return ir.FPUnsignedFixedToDouble(intval, fracbits, rounding_mode); + } + UNREACHABLE(); + return {}; + }(); + + V_scalar(*fltsize, Vd, fltval); + return true; +} + bool TranslatorVisitor::FCVTZS_float_fix(bool sf, Imm<2> type, Imm<6> scale, Vec Vn, Reg Rd) { const size_t intsize = sf ? 64 : 32; const auto fltsize = FPGetDataSize(type);