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