@samitouri / QOSamiQemu / commits / f6fc67e058

target/arm: Implement FCVTN, FCVTN2 (32- to 8-bit fp) for AdvSIMD

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

Richard Henderson committed Jun 9, 2026 at 12:20 UTC f6fc67e05854998d10c39e4c5fc8549f9b9e723c
4 files changed +52
target/arm/tcg/a64.decode
+1
@@ -1213,6 +1213,7 @@ FSCALE 0.10 1110 110 ..... 00111 1 ..... ..... @qrrr_h
1213 FSCALE 0.10 1110 1.1 ..... 11111 1 ..... ..... @qrrr_sd
1214
1215 FCVTN_bh 0.00 1110 010 ..... 11110 1 ..... ..... @qrrr_h
1216 +FCVTN_bs 0.00 1110 000 ..... 11110 1 ..... ..... @qrrr_h
1217
1218 ### Advanced SIMD scalar x indexed element
1219
target/arm/tcg/fp8_helper.c
+33
@@ -187,6 +187,13 @@ static uint8_t fcvt_f16_to_fp8(float16 x, fcvt_fp8_output_fn *f8fmt,
187 return f8fmt(&p, scale, saturate, s);
188 }
189
190 +static uint8_t fcvt_f32_to_fp8(float32 x, fcvt_fp8_output_fn *f8fmt,
191 + int scale, bool saturate, float_status *s)
192 +{
193 + FloatParts64 p = float32_unpack_canonical(x, s);
194 + return f8fmt(&p, scale, saturate, s);
195 +}
196 +
197 void HELPER(advsimd_bfcvtl)(void *vd, void *vn, CPUARMState *env, uint32_t desc)
198 {
199 FP8Context ctx = fp8_src_start(env, desc, 0x3f);
@@ -406,3 +413,29 @@ void HELPER(gvec_fcvt_bh)(void *vd, void *vn, void *vm,
413 fp8_cvt_finish(env, &ctx);
414 clear_tail(vd, oprsz, simd_maxsz(desc));
415 }
416 +
417 +void HELPER(advsimd_fcvt_bs)(void *vd, void *vn, void *vm,
418 + CPUARMState *env, uint32_t desc)
419 +{
420 + FP8Context ctx = fp8_dst_start(env, desc, false);
421 + fcvt_fp8_output_fn *output_fmt = fcvt_fp8_output_fmt[ctx.f8fmt];
422 + uint32_t *n = vn, *m = vm, scratch[4];
423 + uint8_t *d = vd + 8 * ctx.high;
424 + bool osc = FIELD_EX64(env->vfp.fpmr, FPMR, OSC);
425 +
426 + if (vd == vm) {
427 + m = memcpy(scratch, vm, 16);
428 + }
429 +
430 + for (size_t i = 0; i < 4; ++i) {
431 + d[H1(i + 0)] = fcvt_f32_to_fp8(n[H4(i)], output_fmt,
432 + ctx.scale, osc, &ctx.stat);
433 + }
434 + for (size_t i = 0; i < 4; ++i) {
435 + d[H1(i + 4)] = fcvt_f32_to_fp8(m[H4(i)], output_fmt,
436 + ctx.scale, osc, &ctx.stat);
437 + }
438 +
439 + fp8_cvt_finish(env, &ctx);
440 + clear_tail(vd, ctx.high ? 16 : 8, simd_maxsz(desc));
441 +}
target/arm/tcg/helper-fp8-defs.h
+2
@@ -16,3 +16,5 @@ DEF_HELPER_FLAGS_4(sme2_fcvtl_hb, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
16 DEF_HELPER_FLAGS_4(sve2_bfcvtn_bh, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
17
18 DEF_HELPER_FLAGS_5(gvec_fcvt_bh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
19 +
20 +DEF_HELPER_FLAGS_5(advsimd_fcvt_bs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
target/arm/tcg/translate-a64.c
+16
@@ -6634,6 +6634,22 @@ static bool trans_FCVTN_bh(DisasContext *s, arg_qrrr_e *a)
6634 return true;
6635 }
6636
6637 +static bool trans_FCVTN_bs(DisasContext *s, arg_qrrr_e *a)
6638 +{
6639 + if (!dc_isar_feature(aa64_f8cvt, s)) {
6640 + return false;
6641 + }
6642 + if (fpmr_access_check(s) && fp_access_check(s)) {
6643 + tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd),
6644 + vec_full_reg_offset(s, a->rn),
6645 + vec_full_reg_offset(s, a->rm),
6646 + tcg_env, 16, vec_full_reg_size(s),
6647 + (a->q << 1) | FPST_A64 << 2,
6648 + gen_helper_advsimd_fcvt_bs);
6649 + }
6650 + return true;
6651 +}
6652 +
6653 static bool do_fmlal(DisasContext *s, arg_qrrr_e *a, bool is_s, bool is_2)
6654 {
6655 if (fp_access_check(s)) {