@samitouri / QOSamiQemu / commits / da67267541

target/arm: Implement FCVTN (16- 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-16-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Richard Henderson committed Jun 9, 2026 at 12:20 UTC da6726754193221c5f57ec368c3dc5e35617b953
4 files changed +56
target/arm/tcg/a64.decode
+2
@@ -1212,6 +1212,8 @@ FAMIN 0.10 1110 1.1 ..... 11011 1 ..... ..... @qrrr_sd
1212 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 +
1217 ### Advanced SIMD scalar x indexed element
1218
1219 FMUL_si 0101 1111 00 .. .... 1001 . 0 ..... ..... @rrx_h
target/arm/tcg/fp8_helper.c
+37
@@ -180,6 +180,13 @@ static uint8_t fcvt_b16_to_fp8(bfloat16 x, fcvt_fp8_output_fn *f8fmt,
180 return f8fmt(&p, scale, saturate, s);
181 }
182
183 +static uint8_t fcvt_f16_to_fp8(float16 x, fcvt_fp8_output_fn *f8fmt,
184 + int scale, bool saturate, float_status *s)
185 +{
186 + FloatParts64 p = float16_unpack_canonical(x, s);
187 + return f8fmt(&p, scale, saturate, s);
188 +}
189 +
190 void HELPER(advsimd_bfcvtl)(void *vd, void *vn, CPUARMState *env, uint32_t desc)
191 {
192 FP8Context ctx = fp8_src_start(env, desc, 0x3f);
@@ -369,3 +376,33 @@ void HELPER(sve2_bfcvtn_bh)(void *vd, void *vn, CPUARMState *env, uint32_t desc)
376
377 fp8_cvt_finish(env, &ctx);
378 }
379 +
380 +void HELPER(gvec_fcvt_bh)(void *vd, void *vn, void *vm,
381 + CPUARMState *env, uint32_t desc)
382 +{
383 + FP8Context ctx = fp8_dst_start(env, desc, true);
384 + fcvt_fp8_output_fn *output_fmt = fcvt_fp8_output_fmt[ctx.f8fmt];
385 + uint16_t *n = vn;
386 + uint16_t *m = vm;
387 + uint8_t *d = vd;
388 + bool osc = FIELD_EX64(env->vfp.fpmr, FPMR, OSC);
389 + size_t oprsz = simd_oprsz(desc);
390 + size_t nelem = oprsz / 2;
391 + ARMVectorReg scratch;
392 +
393 + if (vd == vm) {
394 + m = memcpy(&scratch, vm, oprsz);
395 + }
396 +
397 + for (size_t i = 0; i < nelem; ++i) {
398 + d[H1(i)] = fcvt_f16_to_fp8(n[H2(i)], output_fmt,
399 + ctx.scale, osc, &ctx.stat);
400 + }
401 + for (size_t i = 0; i < nelem; ++i) {
402 + d[H1(i) + nelem] = fcvt_f16_to_fp8(m[H2(i)], output_fmt,
403 + ctx.scale, osc, &ctx.stat);
404 + }
405 +
406 + fp8_cvt_finish(env, &ctx);
407 + clear_tail(vd, oprsz, simd_maxsz(desc));
408 +}
target/arm/tcg/helper-fp8-defs.h
+2
@@ -14,3 +14,5 @@ DEF_HELPER_FLAGS_4(sme2_fcvt_hb, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
14 DEF_HELPER_FLAGS_4(sme2_fcvtl_hb, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
15
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)
target/arm/tcg/translate-a64.c
+15
@@ -6619,6 +6619,21 @@ static gen_helper_gvec_3_ptr * const f_vector_fscale[3] = {
6619 };
6620 TRANS_FEAT(FSCALE, aa64_f8cvt, do_fp3_vector, a, 0, f_vector_fscale)
6621
6622 +static bool trans_FCVTN_bh(DisasContext *s, arg_qrrr_e *a)
6623 +{
6624 + if (!dc_isar_feature(aa64_f8cvt, s)) {
6625 + return false;
6626 + }
6627 + if (fpmr_access_check(s) && fp_access_check(s)) {
6628 + tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd),
6629 + vec_full_reg_offset(s, a->rn),
6630 + vec_full_reg_offset(s, a->rm),
6631 + tcg_env, a->q ? 16 : 8, vec_full_reg_size(s),
6632 + FPST_A64 << 2, gen_helper_gvec_fcvt_bh);
6633 + }
6634 + return true;
6635 +}
6636 +
6637 static bool do_fmlal(DisasContext *s, arg_qrrr_e *a, bool is_s, bool is_2)
6638 {
6639 if (fp_access_check(s)) {