From: Richard Henderson Date: Tue, 9 Jun 2026 19:20:37 +0000 (-0700) Subject: target/arm: Implement F1CVT, F1CVTL, F2CVT, F2CVTL for SME X-Git-Tag: v11.1.0-rc0~69^2~32 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=cfbf701e7ab148f7de0eed9f93acf74b916e0ff2;p=thirdparty%2Fqemu.git target/arm: Implement F1CVT, F1CVTL, F2CVT, F2CVTL for SME Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20260609192110.752384-14-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- diff --git a/target/arm/tcg/fp8_helper.c b/target/arm/tcg/fp8_helper.c index 75c89203fe..e2330177ec 100644 --- a/target/arm/tcg/fp8_helper.c +++ b/target/arm/tcg/fp8_helper.c @@ -211,6 +211,33 @@ void HELPER(sme2_bfcvt_hb)(void *vd, void *vn, CPUARMState *env, uint32_t desc) fp8_cvt_finish(env, &ctx); } +void HELPER(sme2_fcvt_hb)(void *vd, void *vn, CPUARMState *env, uint32_t desc) +{ + FP8Context ctx = fp8_src_start(env, desc, 0xf); + fp8_input_fn *input_fmt = fp8_input_fmt[ctx.f8fmt]; + uint8_t *n = vn; + uint16_t *d0 = vd; + uint16_t *d1 = vd + sizeof(ARMVectorReg); + size_t oprsz = simd_oprsz(desc); + size_t nelem = oprsz / 2; + ARMVectorReg scratch; + + if (vectors_overlap(vd, 2, vn, 1)) { + n = memcpy(&scratch, vn, oprsz); + } + + for (size_t i = 0; i < nelem; ++i) { + d0[H2(i)] = fcvt_fp8_to_f16(n[H1(i)], input_fmt, + ctx.scale, &ctx.stat); + } + for (size_t i = 0; i < nelem; ++i) { + d1[H2(i)] = fcvt_fp8_to_f16(n[H1(i + nelem)], input_fmt, + ctx.scale, &ctx.stat); + } + + fp8_cvt_finish(env, &ctx); +} + void HELPER(sme2_bfcvtl_hb)(void *vd, void *vn, CPUARMState *env, uint32_t desc) { FP8Context ctx = fp8_src_start(env, desc, 0x3f); @@ -230,3 +257,23 @@ void HELPER(sme2_bfcvtl_hb)(void *vd, void *vn, CPUARMState *env, uint32_t desc) fp8_cvt_finish(env, &ctx); } + +void HELPER(sme2_fcvtl_hb)(void *vd, void *vn, CPUARMState *env, uint32_t desc) +{ + FP8Context ctx = fp8_src_start(env, desc, 0xf); + fp8_input_fn *input_fmt = fp8_input_fmt[ctx.f8fmt]; + uint8_t *n = vn; + uint16_t *d0 = vd; + uint16_t *d1 = vd + sizeof(ARMVectorReg); + size_t oprsz = simd_oprsz(desc); + size_t nelem = oprsz / 2; + + for (size_t i = 0; i < nelem; ++i) { + uint8_t e0 = n[H1(2 * i + 0)]; + uint8_t e1 = n[H1(2 * i + 1)]; + d0[H2(i)] = fcvt_fp8_to_f16(e0, input_fmt, ctx.scale, &ctx.stat); + d1[H2(i)] = fcvt_fp8_to_f16(e1, input_fmt, ctx.scale, &ctx.stat); + } + + fp8_cvt_finish(env, &ctx); +} diff --git a/target/arm/tcg/helper-fp8-defs.h b/target/arm/tcg/helper-fp8-defs.h index 3021dafd44..b5dc2b7064 100644 --- a/target/arm/tcg/helper-fp8-defs.h +++ b/target/arm/tcg/helper-fp8-defs.h @@ -10,3 +10,5 @@ DEF_HELPER_FLAGS_4(sme2_bfcvtl_hb, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32) DEF_HELPER_FLAGS_4(advsimd_fcvtl_hb, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32) DEF_HELPER_FLAGS_4(sve2_fcvt_hb, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32) +DEF_HELPER_FLAGS_4(sme2_fcvt_hb, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32) +DEF_HELPER_FLAGS_4(sme2_fcvtl_hb, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32) diff --git a/target/arm/tcg/sme.decode b/target/arm/tcg/sme.decode index df9586c1a5..d6192eb59d 100644 --- a/target/arm/tcg/sme.decode +++ b/target/arm/tcg/sme.decode @@ -853,6 +853,11 @@ UUNPK_4bh 11000001 011 10101 111000 ....0 ...01 @zz_4x2_n1 UUNPK_4hs 11000001 101 10101 111000 ....0 ...01 @zz_4x2_n1 UUNPK_4sd 11000001 111 10101 111000 ....0 ...01 @zz_4x2_n1 +F1CVT 11000001 001 00110 111000 ..... ....0 @zz_2x1 +F2CVT 11000001 101 00110 111000 ..... ....0 @zz_2x1 +F1CVTL 11000001 001 00110 111000 ..... ....1 @zz_2x1 +F2CVTL 11000001 101 00110 111000 ..... ....1 @zz_2x1 + BF1CVT 11000001 011 00110 111000 ..... ....0 @zz_2x1 BF2CVT 11000001 111 00110 111000 ..... ....0 @zz_2x1 BF1CVTL 11000001 011 00110 111000 ..... ....1 @zz_2x1 diff --git a/target/arm/tcg/translate-sme.c b/target/arm/tcg/translate-sme.c index 19a13a6506..c0fe77242b 100644 --- a/target/arm/tcg/translate-sme.c +++ b/target/arm/tcg/translate-sme.c @@ -1546,6 +1546,11 @@ static bool do_f8cvt(DisasContext *s, arg_zz_n *a, return true; } +TRANS_FEAT(F1CVT, aa64_sme2_f8cvt, do_f8cvt, a, gen_helper_sme2_fcvt_hb, 0) +TRANS_FEAT(F2CVT, aa64_sme2_f8cvt, do_f8cvt, a, gen_helper_sme2_fcvt_hb, 1) +TRANS_FEAT(F1CVTL, aa64_sme2_f8cvt, do_f8cvt, a, gen_helper_sme2_fcvtl_hb, 0) +TRANS_FEAT(F2CVTL, aa64_sme2_f8cvt, do_f8cvt, a, gen_helper_sme2_fcvtl_hb, 1) + TRANS_FEAT(BF1CVT, aa64_sme2_f8cvt, do_f8cvt, a, gen_helper_sme2_bfcvt_hb, 0) TRANS_FEAT(BF2CVT, aa64_sme2_f8cvt, do_f8cvt, a, gen_helper_sme2_bfcvt_hb, 1) TRANS_FEAT(BF1CVTL, aa64_sme2_f8cvt, do_f8cvt, a, gen_helper_sme2_bfcvtl_hb, 0)