@samitouri / QOSamiQemu / commits / deadb7c6e8

target/arm: Implement FCVT, FCVTN (FP32 to FP8) for SME

Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260609192110.752384-21-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Richard Henderson committed Jun 9, 2026 at 12:20 UTC deadb7c6e88286e992df1cbf078c74dce3302828
4 files changed +67
target/arm/tcg/fp8_helper.c
+59
@@ -509,3 +509,62 @@ void HELPER(sve2_fcvtnt_bs)(void *vd, void *vn, CPUARMState *env, uint32_t desc)
509
510 fp8_cvt_finish(env, &ctx);
511 }
512 +
513 +void HELPER(sme2_fcvt_bs)(void *vd, void *vn, CPUARMState *env, uint32_t desc)
514 +{
515 + ARMVectorReg scratch[4];
516 + FP8Context ctx = fp8_dst_start(env, desc, false);
517 + fcvt_fp8_output_fn *output_fmt = fcvt_fp8_output_fmt[ctx.f8fmt];
518 + uint32_t *n = vn;
519 + uint8_t *d = vd;
520 + bool osc = FIELD_EX64(env->vfp.fpmr, FPMR, OSC);
521 + size_t oprsz = simd_oprsz(desc);
522 + size_t nelem = oprsz / 4;
523 + size_t stride = sizeof(ARMVectorReg) / 4;
524 +
525 + if (vectors_overlap(vd, 1, vn, 4)) {
526 + n = memcpy(scratch, vn, sizeof(scratch));
527 + }
528 +
529 + for (size_t i = 0; i < nelem; i++) {
530 + for (size_t j = 0; j < 4; j++) {
531 + d[H1(i + nelem * j)] = fcvt_f32_to_fp8(n[H4(i) + stride * j],
532 + output_fmt, ctx.scale,
533 + osc, &ctx.stat);
534 + }
535 + }
536 +
537 + fp8_cvt_finish(env, &ctx);
538 +}
539 +
540 +void HELPER(sme2_fcvtn_bs)(void *vd, void *vn, CPUARMState *env, uint32_t desc)
541 +{
542 + FP8Context ctx = fp8_dst_start(env, desc, false);
543 + fcvt_fp8_output_fn *output_fmt = fcvt_fp8_output_fmt[ctx.f8fmt];
544 + uint32_t *n0 = vn;
545 + uint32_t *n1 = vn + sizeof(ARMVectorReg);
546 + uint32_t *n2 = vn + sizeof(ARMVectorReg) * 2;
547 + uint32_t *n3 = vn + sizeof(ARMVectorReg) * 3;
548 + uint8_t *d = vd;
549 + bool osc = FIELD_EX64(env->vfp.fpmr, FPMR, OSC);
550 + size_t oprsz = simd_oprsz(desc);
551 + size_t nelem = oprsz / 4;
552 +
553 + for (size_t i = 0; i < nelem; ++i) {
554 + float32 e0 = n0[H4(i)];
555 + float32 e1 = n1[H4(i)];
556 + float32 e2 = n2[H4(i)];
557 + float32 e3 = n3[H4(i)];
558 +
559 + d[H1(4 * i + 0)] = fcvt_f32_to_fp8(e0, output_fmt,
560 + ctx.scale, osc, &ctx.stat);
561 + d[H1(4 * i + 1)] = fcvt_f32_to_fp8(e1, output_fmt,
562 + ctx.scale, osc, &ctx.stat);
563 + d[H1(4 * i + 2)] = fcvt_f32_to_fp8(e2, output_fmt,
564 + ctx.scale, osc, &ctx.stat);
565 + d[H1(4 * i + 3)] = fcvt_f32_to_fp8(e3, output_fmt,
566 + ctx.scale, osc, &ctx.stat);
567 + }
568 +
569 + fp8_cvt_finish(env, &ctx);
570 +}
target/arm/tcg/helper-fp8-defs.h
+2
@@ -21,3 +21,5 @@ DEF_HELPER_FLAGS_4(sve2_fcvtn_bh, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
21 DEF_HELPER_FLAGS_5(advsimd_fcvt_bs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
22 DEF_HELPER_FLAGS_4(sve2_fcvtnb_bs, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
23 DEF_HELPER_FLAGS_4(sve2_fcvtnt_bs, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
24 +DEF_HELPER_FLAGS_4(sme2_fcvt_bs, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
25 +DEF_HELPER_FLAGS_4(sme2_fcvtn_bs, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
target/arm/tcg/sme.decode
+3
@@ -865,6 +865,9 @@ BF2CVTL 11000001 111 00110 111000 ..... ....1 @zz_2x1
865
866 FCVT_bh 11000001 001 00100 111000 ....0 ..... @zz_1x2
867
868 +FCVT_bs 11000001 001 10100 111000 ...00 ..... @zz_1x4
869 +FCVTN_bs 11000001 001 10100 111000 ...01 ..... @zz_1x4
870 +
871 ZIP_4 11000001 esz:2 1 10110 111000 ...00 ... 00 \
872 &zz_e zd=%zd_ax4 zn=%zn_ax4
873 ZIP_4 11000001 001 10111 111000 ...00 ... 00 \
target/arm/tcg/translate-sme.c
+3
@@ -1572,6 +1572,9 @@ static bool trans_FCVT_bh(DisasContext *s, arg_zz_n *a)
1572 return true;
1573 }
1574
1575 +TRANS_FEAT(FCVT_bs, aa64_sme2_f8cvt, do_f8cvt, a, gen_helper_sme2_fcvt_bs, 0)
1576 +TRANS_FEAT(FCVTN_bs, aa64_sme2_f8cvt, do_f8cvt, a, gen_helper_sme2_fcvtn_bs, 0)
1577 +
1578 static bool do_zipuzp_4(DisasContext *s, arg_zz_e *a,
1579 gen_helper_gvec_2 * const fn[5])
1580 {