@samitouri / QOSamiQemu / commits / 9d70629fa0

target/hexagon: add v73 HVX IEEE bfloat16 insns

Add HVX IEEE bfloat16 (bf16) instructions: Arithmetic operations: - V6_vadd_sf_bf, V6_vsub_sf_bf: add/sub bf16 widening to sf output - V6_vmpy_sf_bf: multiply bf16 widening to sf output - V6_vmpy_sf_bf_acc: multiply-accumulate bf16 widening to sf output Min/Max operations: - V6_vmin_bf, V6_vmax_bf: bf16 min/max Comparison operations: - V6_vgtbf: greater-than compare - V6_vgtbf_and, V6_vgtbf_or, V6_vgtbf_xor: predicate variants Conversion operations: - V6_vcvt_bf_sf: convert sf to bf16 Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com> Signed-off-by: Matheus Tavares Bernardino <matheus.bernardino@oss.qualcomm.com> Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com> Link: https://lore.kernel.org/qemu-devel/1a253373567781e0e141c34b41eaffad4789a493.1776339451.git.matheus.bernardino@oss.qualcomm.com Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>

Matheus Tavares Bernardino committed Apr 16, 2026 at 04:39 UTC 9d70629fa0e03ee2341f1aab4928d43ed1718d93
5 files changed +119
target/hexagon/imported/mmvec/encode_ext.def
+15
@@ -868,4 +868,19 @@ DEF_ENC(V6_vgthf_or,"00011100100vvvvvPP1uuuuu001101xx")
868 DEF_ENC(V6_vgtsf_xor,"00011100100vvvvvPP1uuuuu111010xx")
869 DEF_ENC(V6_vgthf_xor,"00011100100vvvvvPP1uuuuu111011xx")
870
871 +/* BFLOAT instructions */
872 +DEF_ENC(V6_vmpy_sf_bf,"00011101010vvvvvPP1uuuuu100ddddd")
873 +DEF_ENC(V6_vmpy_sf_bf_acc,"00011101000vvvvvPP1uuuuu000xxxxx")
874 +DEF_ENC(V6_vadd_sf_bf,"00011101010vvvvvPP1uuuuu110ddddd")
875 +DEF_ENC(V6_vsub_sf_bf,"00011101010vvvvvPP1uuuuu101ddddd")
876 +DEF_ENC(V6_vmax_bf,"00011101010vvvvvPP1uuuuu111ddddd")
877 +DEF_ENC(V6_vmin_bf,"00011101010vvvvvPP1uuuuu000ddddd")
878 +DEF_ENC(V6_vcvt_bf_sf,"00011101010vvvvvPP1uuuuu011ddddd")
879 +
880 +/* BFLOAT compare instructions */
881 +DEF_ENC(V6_vgtbf,"00011100100vvvvvPP1uuuuu011110dd")
882 +DEF_ENC(V6_vgtbf_and,"00011100100vvvvvPP1uuuuu110100xx")
883 +DEF_ENC(V6_vgtbf_or,"00011100100vvvvvPP1uuuuu001110xx")
884 +DEF_ENC(V6_vgtbf_xor,"00011100100vvvvvPP1uuuuu111100xx")
885 +
886 #endif /* NO MMVEC */
target/hexagon/imported/mmvec/ext.idef
+62
@@ -3163,6 +3163,15 @@ ITERATOR_INSN_SHIFT_SLOT_FLT(16, vconv_hf_h,"Vd32.hf=Vu32.h",
3163 } \
3164 }
3165
3166 +#define VCMPGT_BF(DEST, ASRC, ASRCOP, CMP, N, SRC, MASK, WIDTH) \
3167 +{ \
3168 + fBFLOAT(); \
3169 + for (fHIDE(int) i = 0; i < fVBYTES(); i += WIDTH) { \
3170 + fHIDE(int) VAL = fCMPGT_BF(VuV.SRC[i/WIDTH],VvV.SRC[i/WIDTH]) ? MASK : 0; \
3171 + fSETQBITS(DEST,WIDTH,MASK,i,ASRC ASRCOP VAL); \
3172 + } \
3173 +}
3174 +
3175 /* Vector SF compare */
3176 #define MMVEC_CMPGT_SF(TYPE,TYPE2,DESCR,N,MASK,WIDTH,SRC) \
3177 EXTINSN(V6_vgt##TYPE##_and, "Qx4&=vcmp.gt(Vu32." TYPE2 ",Vv32." TYPE2 ")", \
@@ -3201,8 +3210,61 @@ ITERATOR_INSN_SHIFT_SLOT_FLT(16, vconv_hf_h,"Vd32.hf=Vu32.h",
3210 DESCR" greater than", \
3211 VCMPGT_HF(QdV, , , ">", N, SRC, MASK, WIDTH))
3212
3213 +/* Vector BF compare */
3214 +#define MMVEC_CMPGT_BF(TYPE,TYPE2,DESCR,N,MASK,WIDTH,SRC) \
3215 + EXTINSN(V6_vgt##TYPE##_and, "Qx4&=vcmp.gt(Vu32." TYPE2 ",Vv32." TYPE2 ")",\
3216 + ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VA,A_CVI_VA_2SRC,A_HVX_FLT), \
3217 + DESCR" greater than with predicate-and", \
3218 + VCMPGT_BF(QxV, fGETQBITS(QxV,WIDTH,MASK,i), &, ">", N, SRC, MASK, WIDTH)) \
3219 + EXTINSN(V6_vgt##TYPE##_xor, "Qx4^=vcmp.gt(Vu32." TYPE2 ",Vv32." TYPE2 ")", \
3220 + ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VA,A_CVI_VA_2SRC,A_HVX_FLT), \
3221 + DESCR" greater than with predicate-xor", \
3222 + VCMPGT_BF(QxV, fGETQBITS(QxV,WIDTH,MASK,i), ^, ">", N, SRC, MASK, WIDTH)) \
3223 + EXTINSN(V6_vgt##TYPE##_or, "Qx4|=vcmp.gt(Vu32." TYPE2 ",Vv32." TYPE2 ")", \
3224 + ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VA,A_CVI_VA_2SRC,A_HVX_FLT), \
3225 + DESCR" greater than with predicate-or", \
3226 + VCMPGT_BF(QxV, fGETQBITS(QxV,WIDTH,MASK,i), |, ">", N, SRC, MASK, WIDTH)) \
3227 + EXTINSN(V6_vgt##TYPE, "Qd4=vcmp.gt(Vu32." TYPE2 ",Vv32." TYPE2 ")", \
3228 + ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VA,A_CVI_VA_2SRC,A_HVX_FLT), \
3229 + DESCR" greater than", \
3230 + VCMPGT_BF(QdV, , , ">", N, SRC, MASK, WIDTH))
3231 +
3232 MMVEC_CMPGT_SF(sf,"sf","Vector sf Compare ", fVELEM(32), 0xF, 4, sf)
3233 MMVEC_CMPGT_HF(hf,"hf","Vector hf Compare ", fVELEM(16), 0x3, 2, hf)
3234 +MMVEC_CMPGT_BF(bf,"bf","Vector bf Compare ", fVELEM(16), 0x3, 2, bf)
3235 +
3236 +/******************************************************************************
3237 + BFloat arithmetic and max/min instructions
3238 + ******************************************************************************/
3239 +
3240 +ITERATOR_INSN_IEEE_FP_DOUBLE_32(32, vadd_sf_bf,
3241 + "Vdd32.sf=vadd(Vu32.bf,Vv32.bf)", "Vector IEEE add: bf widen to sf",
3242 + VddV.v[0].sf[i] = fp_add_sf_bf(VuV.bf[2*i], VvV.bf[2*i]);
3243 + VddV.v[1].sf[i] = fp_add_sf_bf(VuV.bf[2*i+1], VvV.bf[2*i+1]); fBFLOAT())
3244 +ITERATOR_INSN_IEEE_FP_DOUBLE_32(32, vsub_sf_bf,
3245 + "Vdd32.sf=vsub(Vu32.bf,Vv32.bf)", "Vector IEEE sub: bf widen to sf",
3246 + VddV.v[0].sf[i] = fp_sub_sf_bf(VuV.bf[2*i], VvV.bf[2*i]);
3247 + VddV.v[1].sf[i] = fp_sub_sf_bf(VuV.bf[2*i+1], VvV.bf[2*i+1]); fBFLOAT())
3248 +ITERATOR_INSN_IEEE_FP_DOUBLE_32(32, vmpy_sf_bf,
3249 + "Vdd32.sf=vmpy(Vu32.bf,Vv32.bf)", "Vector IEEE mul: hf widen to sf",
3250 + VddV.v[0].sf[i] = fp_mult_sf_bf(VuV.bf[2*i], VvV.bf[2*i]);
3251 + VddV.v[1].sf[i] = fp_mult_sf_bf(VuV.bf[2*i+1], VvV.bf[2*i+1]); fBFLOAT())
3252 +ITERATOR_INSN_IEEE_FP_DOUBLE_32(32, vmpy_sf_bf_acc,
3253 + "Vxx32.sf+=vmpy(Vu32.bf,Vv32.bf)", "Vector IEEE fma: hf widen to sf",
3254 + VxxV.v[0].sf[i] = fp_mult_sf_bf_acc(VuV.bf[2*i], VvV.bf[2*i], VxxV.v[0].sf[i]);
3255 + VxxV.v[1].sf[i] = fp_mult_sf_bf_acc(VuV.bf[2*i+1], VvV.bf[2*i+1], VxxV.v[1].sf[i]);
3256 + fCVI_VX_NO_TMP_LD(); fBFLOAT())
3257 +ITERATOR_INSN_IEEE_FP_16(32, vcvt_bf_sf,
3258 + "Vd32.bf=vcvt(Vu32.sf,Vv32.sf)", "Vector IEEE cvt: sf to bf",
3259 + VdV.bf[2*i] = f32_to_bf16(VuV.sf[i], &env->hvx_fp_status);
3260 + VdV.bf[2*i+1] = f32_to_bf16(VvV.sf[i], &env->hvx_fp_status); fBFLOAT())
3261 +
3262 +ITERATOR_INSN_IEEE_FP_16_32_LATE(16, vmax_bf, "Vd32.bf=vmax(Vu32.bf,Vv32.bf)",
3263 + "Vector IEEE max: bf", VdV.bf[i] = fp_max_bf(VuV.bf[i], VvV.bf[i]);
3264 + fBFLOAT())
3265 +ITERATOR_INSN_IEEE_FP_16_32_LATE(16, vmin_bf, "Vd32.bf=vmin(Vu32.bf,Vv32.bf)",
3266 + "Vector IEEE min: bf", VdV.bf[i] = fp_min_bf(VuV.bf[i], VvV.bf[i]);
3267 + fBFLOAT())
3268
3269 /******************************************************************************
3270 DEBUG Vector/Register Printing
target/hexagon/mmvec/hvx_ieee_fp.h
+37
@@ -9,8 +9,11 @@
9
10 #include "fpu/softfloat.h"
11
12 +#define FP32_DEF_NAN 0x7FFFFFFF
13 +
14 #define f16_to_f32(A) float16_to_float32((A), true, &env->hvx_fp_status)
15 #define f32_to_f16(A) float32_to_float16((A), true, &env->hvx_fp_status)
16 +#define bf16_to_f32(A) bfloat16_to_float32(A, &env->hvx_fp_status)
17
18 float32 fp_mult_sf_hf(float16 a1, float16 a2, float_status *fp_status);
19 float32 fp_vdmpy(float16 a1, float16 a2, float16 a3, float16 a4,
@@ -29,4 +32,38 @@ int16_t conv_h_hf(float16 a, float_status *fp_status);
32 uint32_t cmpgt_sf(float32 a1, float32 a2, float_status *fp_status);
33 uint16_t cmpgt_hf(float16 a1, float16 a2, float_status *fp_status);
34
35 +/* IEEE BFloat instructions */
36 +
37 +#define fp_mult_sf_bf(A, B) \
38 + float32_mul(bf16_to_f32(A), bf16_to_f32(B), &env->hvx_fp_status)
39 +
40 +#define fp_add_sf_bf(A, B) \
41 + float32_add(bf16_to_f32(A), bf16_to_f32(B), &env->hvx_fp_status)
42 +
43 +#define fp_sub_sf_bf(A, B) \
44 + float32_sub(bf16_to_f32(A), bf16_to_f32(B), &env->hvx_fp_status)
45 +
46 +#define fp_mult_sf_bf_acc(f1, f2, f3) \
47 + float32_muladd(bf16_to_f32(f1), bf16_to_f32(f2), f3, 0, &env->hvx_fp_status)
48 +
49 +static inline bfloat16 f32_to_bf16(float32 A, float_status *fp_status)
50 +{
51 + uint32_t rslt = A;
52 + if ((rslt & 0x1FFFF) == 0x08000) {
53 + /* do not round up if exactly .5 and even already */
54 + } else if ((rslt & 0x8000) == 0x8000) {
55 + rslt += 0x8000; /* rounding to nearest number */
56 + }
57 + rslt = float32_is_any_nan(A) ? FP32_DEF_NAN : rslt;
58 + return float32_to_bfloat16(rslt, fp_status);
59 +}
60 +
61 +#define fp_min_bf(A, B) \
62 + f32_to_bf16(float32_min(bf16_to_f32(A), bf16_to_f32(B), &env->hvx_fp_status), \
63 + &env->hvx_fp_status);
64 +
65 +#define fp_max_bf(A, B) \
66 + f32_to_bf16(float32_max(bf16_to_f32(A), bf16_to_f32(B), &env->hvx_fp_status), \
67 + &env->hvx_fp_status);
68 +
69 #endif
target/hexagon/mmvec/macros.h
+4
@@ -25,6 +25,9 @@
25 #include "accel/tcg/probe.h"
26 #include "mmvec/hvx_ieee_fp.h"
27
28 +#define fBFLOAT()
29 +#define fCVI_VX_NO_TMP_LD()
30 +
31 #ifndef QEMU_GENERATE
32 #define VdV (*(MMVector *restrict)(VdV_void))
33 #define VsV (*(MMVector *restrict)(VsV_void))
@@ -359,5 +362,6 @@
362
363 #define fCMPGT_SF(A, B) cmpgt_sf(A, B, &env->hvx_fp_status)
364 #define fCMPGT_HF(A, B) cmpgt_hf(A, B, &env->hvx_fp_status)
365 +#define fCMPGT_BF(A, B) fCMPGT_SF((uint32_t)(A) << 16, (uint32_t)(B) << 16)
366
367 #endif
target/hexagon/mmvec/mmvec.h
+1
@@ -43,6 +43,7 @@ typedef union {
43 int8_t b[MAX_VEC_SIZE_BYTES / 1];
44 float32 sf[MAX_VEC_SIZE_BYTES / 4];
45 float16 hf[MAX_VEC_SIZE_BYTES / 2];
46 + bfloat16 bf[MAX_VEC_SIZE_BYTES / 2];
47 } MMVector;
48
49 typedef union {