@samitouri / QOSamiQemu / commits / d75f58d9ae

target/arm: Implement FCVTNB, FCVTNT for SVE

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

Richard Henderson committed Jun 9, 2026 at 12:20 UTC d75f58d9ae7f3c8b5b1a1701ed334dc378044876
4 files changed +55
target/arm/tcg/fp8_helper.c
+47
@@ -462,3 +462,50 @@ void HELPER(advsimd_fcvt_bs)(void *vd, void *vn, void *vm,
462 fp8_cvt_finish(env, &ctx);
463 clear_tail(vd, ctx.high ? 16 : 8, simd_maxsz(desc));
464 }
465 +
466 +void HELPER(sve2_fcvtnb_bs)(void *vd, void *vn, CPUARMState *env, uint32_t desc)
467 +{
468 + FP8Context ctx = fp8_dst_start(env, desc, false);
469 + fcvt_fp8_output_fn *output_fmt = fcvt_fp8_output_fmt[ctx.f8fmt];
470 + uint32_t *n0 = vn;
471 + uint32_t *n1 = vn + sizeof(ARMVectorReg);
472 + uint16_t *d = vd;
473 + bool osc = FIELD_EX64(env->vfp.fpmr, FPMR, OSC);
474 + size_t oprsz = simd_oprsz(desc);
475 + size_t nelem = oprsz / 4;
476 +
477 + for (size_t i = 0; i < nelem; ++i) {
478 + float32 e0 = n0[H4(i)];
479 + float32 e1 = n1[H4(i)];
480 + /* Zero-extend uint8_t to clear the odd lanes. */
481 + d[H2(2 * i + 0)] = fcvt_f32_to_fp8(e0, output_fmt,
482 + ctx.scale, osc, &ctx.stat);
483 + d[H2(2 * i + 1)] = fcvt_f32_to_fp8(e1, output_fmt,
484 + ctx.scale, osc, &ctx.stat);
485 + }
486 +
487 + fp8_cvt_finish(env, &ctx);
488 +}
489 +
490 +void HELPER(sve2_fcvtnt_bs)(void *vd, void *vn, CPUARMState *env, uint32_t desc)
491 +{
492 + FP8Context ctx = fp8_dst_start(env, desc, false);
493 + fcvt_fp8_output_fn *output_fmt = fcvt_fp8_output_fmt[ctx.f8fmt];
494 + uint32_t *n0 = vn;
495 + uint32_t *n1 = vn + sizeof(ARMVectorReg);
496 + uint8_t *d = vd;
497 + bool osc = FIELD_EX64(env->vfp.fpmr, FPMR, OSC);
498 + size_t oprsz = simd_oprsz(desc);
499 + size_t nelem = oprsz / 4;
500 +
501 + for (size_t i = 0; i < nelem; ++i) {
502 + float32 e0 = n0[H4(i)];
503 + float32 e1 = n1[H4(i)];
504 + d[H1(4 * i + 1)] = fcvt_f32_to_fp8(e0, output_fmt,
505 + ctx.scale, osc, &ctx.stat);
506 + d[H1(4 * i + 3)] = fcvt_f32_to_fp8(e1, output_fmt,
507 + ctx.scale, osc, &ctx.stat);
508 + }
509 +
510 + fp8_cvt_finish(env, &ctx);
511 +}
target/arm/tcg/helper-fp8-defs.h
+2
@@ -19,3 +19,5 @@ DEF_HELPER_FLAGS_5(gvec_fcvt_bh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
19 DEF_HELPER_FLAGS_4(sve2_fcvtn_bh, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
20
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)
target/arm/tcg/sve.decode
+2
@@ -1103,6 +1103,8 @@ BF2CVTLT 01100101 00 001 001 001111 ..... ..... @rd_rn_e0
1103
1104 FCVTN 01100101 00 001 010 001100 ....0 ..... @rd_rnx2 esz=1
1105 BFCVTN 01100101 00 001 010 001110 ....0 ..... @rd_rnx2 esz=1
1106 +FCVTNB 01100101 00 001 010 001101 ....0 ..... @rd_rnx2 esz=2
1107 +FCVTNT 01100101 00 001 010 001111 ....0 ..... @rd_rnx2 esz=2
1108
1109 ### SVE FP Compare with Zero Group
1110
target/arm/tcg/translate-sve.c
+4
@@ -4104,6 +4104,10 @@ TRANS_FEAT_STREAMING_IF(FCVTN, aa64_sme2_or_sve2_f8cvt, aa64_sme2,
4104 do_f8cvt, a, gen_helper_sve2_fcvtn_bh, false, false)
4105 TRANS_FEAT_STREAMING_IF(BFCVTN, aa64_sme2_or_sve2_f8cvt, aa64_sme2,
4106 do_f8cvt, a, gen_helper_sve2_bfcvtn_bh, false, false)
4107 +TRANS_FEAT_STREAMING_IF(FCVTNB, aa64_sme2_or_sve2_f8cvt, aa64_sme2,
4108 + do_f8cvt, a, gen_helper_sve2_fcvtnb_bs, false, false)
4109 +TRANS_FEAT_STREAMING_IF(FCVTNT, aa64_sme2_or_sve2_f8cvt, aa64_sme2,
4110 + do_f8cvt, a, gen_helper_sve2_fcvtnt_bs, false, false)
4111
4112 /*
4113 *** SVE Floating Point Compare with Zero Group