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)) {