target/arm: Implement BF1CVT, BF1CVTLT, BF2CVT, BF2CVTLT for SVE
Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260609192110.752384-9-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Richard Henderson committed
Jun 9, 2026 at 12:20 UTC
a309e51cefce692d94c159aea5fc8377341825aa
5 files changed
+52
target/arm/cpu-features.h
+6
@@ -1668,6 +1668,12 @@ isar_feature_aa64_sme2_or_sve2_faminmax(const ARMISARegisters *id)
1668
return isar_feature_aa64_sme2_or_sve2(id) && isar_feature_aa64_faminmax(id);
1669
}
1670
1671
+static inline bool
1672
+isar_feature_aa64_sme2_or_sve2_f8cvt(const ARMISARegisters *id)
1673
+{
1674
+ return isar_feature_aa64_sme2_or_sve2(id) && isar_feature_aa64_f8cvt(id);
1675
+}
1676
+
1677
/*
1678
* Feature tests for "does this exist in either 32-bit or 64-bit?"
1679
*/
target/arm/tcg/fp8_helper.c
+16
@@ -122,3 +122,19 @@ void HELPER(advsimd_bfcvtl)(void *vd, void *vn, CPUARMState *env, uint32_t desc)
122
fp8_cvt_finish(env, &ctx);
123
clear_tail(vd, 16, simd_maxsz(desc));
124
}
125
+
126
+void HELPER(sve2_bfcvt)(void *vd, void *vn, CPUARMState *env, uint32_t desc)
127
+{
128
+ FP8Context ctx = fp8_src_start(env, desc, 0x3f);
129
+ fp8_input_fn *input_fmt = fp8_input_fmt[ctx.f8fmt];
130
+ uint8_t *n = vn;
131
+ uint16_t *d = vd;
132
+ size_t nelem = simd_oprsz(desc) / 2;
133
+
134
+ for (size_t i = 0; i < nelem; ++i) {
135
+ d[H2(i)] = fcvt_fp8_to_b16(n[H1(2 * i + ctx.high)],
136
+ input_fmt, ctx.scale, &ctx.stat);
137
+ }
138
+
139
+ fp8_cvt_finish(env, &ctx);
140
+}
target/arm/tcg/helper-fp8-defs.h
+1
@@ -4,3 +4,4 @@
4
*/
5
6
DEF_HELPER_FLAGS_4(advsimd_bfcvtl, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
7
+DEF_HELPER_FLAGS_4(sve2_bfcvt, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
target/arm/tcg/sve.decode
+6
@@ -108,6 +108,7 @@
108
# Two operand
109
@pd_pn ........ esz:2 .. .... ....... rn:4 . rd:4 &rr_esz
110
@rd_rn ........ esz:2 ...... ...... rn:5 rd:5 &rr_esz
111
+@rd_rn_e0 ........ .. ...... ...... rn:5 rd:5 &rr_esz esz=0
112
@rd_rnx2 ........ ... ..... ...... ..... rd:5 &rr_esz rn=%rn_ax2
113
114
# Two operand with governing predicate, flags setting
@@ -1090,6 +1091,11 @@ FMINQV 01100100 .. 010 111 101 ... ..... ..... @rd_pg_rn
1091
FRECPE 01100101 .. 001 110 001100 ..... ..... @rd_rn
1092
FRSQRTE 01100101 .. 001 111 001100 ..... ..... @rd_rn
1093
1094
+BF1CVT 01100101 00 001 000 001110 ..... ..... @rd_rn_e0
1095
+BF2CVT 01100101 00 001 000 001111 ..... ..... @rd_rn_e0
1096
+BF1CVTLT 01100101 00 001 001 001110 ..... ..... @rd_rn_e0
1097
+BF2CVTLT 01100101 00 001 001 001111 ..... ..... @rd_rn_e0
1098
+
1099
### SVE FP Compare with Zero Group
1100
1101
FCMGE_ppz0 01100101 .. 0100 00 001 ... ..... 0 .... @pd_pg_rn
target/arm/tcg/translate-sve.c
+23
@@ -21,6 +21,7 @@
21
#include "cpu.h"
22
#include "helper-sme.h"
23
#include "helper-sve.h"
24
+#include "helper-fp8.h"
25
#include "translate.h"
26
#include "translate-a64.h"
27
#include "tcg/tcg-op.h"
@@ -4068,6 +4069,28 @@ TRANS_FEAT(FRSQRTE, aa64_sme_or_sve, gen_gvec_fpst_ah_arg_zz,
4069
s->fpcr_ah && dc_isar_feature(aa64_rpres, s) ?
4070
frsqrte_rpres_fns[a->esz] : frsqrte_fns[a->esz], a, 0)
4071
4072
+static bool do_f8cvt(DisasContext *s, arg_rr_esz *a,
4073
+ gen_helper_gvec_2_ptr *fn, bool issrc2, bool isodd)
4074
+{
4075
+ if (fpmr_access_check(s) && sve_access_check(s)) {
4076
+ unsigned vsz = vec_full_reg_size(s);
4077
+ tcg_gen_gvec_2_ptr(vec_full_reg_offset(s, a->rd),
4078
+ vec_full_reg_offset(s, a->rn),
4079
+ tcg_env, vsz, vsz,
4080
+ issrc2 | (isodd << 1) | (FPST_A64 << 2), fn);
4081
+ }
4082
+ return true;
4083
+}
4084
+
4085
+TRANS_FEAT_STREAMING_IF(BF1CVT, aa64_sme2_or_sve2_f8cvt, aa64_sme2,
4086
+ do_f8cvt, a, gen_helper_sve2_bfcvt, false, false)
4087
+TRANS_FEAT_STREAMING_IF(BF2CVT, aa64_sme2_or_sve2_f8cvt, aa64_sme2,
4088
+ do_f8cvt, a, gen_helper_sve2_bfcvt, true, false)
4089
+TRANS_FEAT_STREAMING_IF(BF1CVTLT, aa64_sme2_or_sve2_f8cvt, aa64_sme2,
4090
+ do_f8cvt, a, gen_helper_sve2_bfcvt, false, true)
4091
+TRANS_FEAT_STREAMING_IF(BF2CVTLT, aa64_sme2_or_sve2_f8cvt, aa64_sme2,
4092
+ do_f8cvt, a, gen_helper_sve2_bfcvt, true, true)
4093
+
4094
/*
4095
*** SVE Floating Point Compare with Zero Group
4096
*/