target/hexagon: add v68 HVX IEEE float arithmetic insns
Add HVX IEEE floating-point arithmetic instructions: - vmpy_sf_sf, vmpy_sf_hf, vmpy_hf_hf: multiply operations - vdmpy_sf_hf: dot-product multiply - vmpy_sf_hf_acc, vmpy_hf_hf_acc, vdmpy_sf_hf_acc: multiply-accumulate - vadd_sf_sf, vsub_sf_sf, vadd_sf_hf, vsub_sf_hf: add/sub with sf output - vadd_hf_hf, vsub_hf_hf: add/sub with hf output 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/8923b6c6bc4fe750c07a07bcd490761f8bab52fe.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:38 UTC
69e46b28228441c5d064fb3b84691cbb23e71296
12 files changed
+179
target/hexagon/arch.c
+8
@@ -199,6 +199,10 @@ void arch_fpop_start(CPUHexagonState *env)
199
set_float_rounding_mode(
200
softfloat_roundingmodes[fREAD_REG_FIELD(USR, USR_FPRND)],
201
&env->fp_status);
202
+ /*
203
+ * No need to check env->hvx_fp_status, these instructions don't
204
+ * raise exceptions nor interact with usr fields.
205
+ */
206
}
207
208
#ifdef CONFIG_USER_ONLY
@@ -237,6 +241,10 @@ void arch_fpop_end(CPUHexagonState *env, bool pkt_need_commit)
241
SOFTFLOAT_TEST_FLAG(float_flag_overflow, FPOVFF, FPOVFE);
242
SOFTFLOAT_TEST_FLAG(float_flag_underflow, FPUNFF, FPUNFE);
243
}
244
+ /*
245
+ * No need to check env->hvx_fp_status, these instructions don't
246
+ * raise exceptions nor interact with usr fields.
247
+ */
248
}
249
250
int arch_sf_recip_common(float32 *Rs, float32 *Rt, float32 *Rd, int *adjust,
target/hexagon/attribs_def.h.inc
+4
@@ -198,6 +198,10 @@ DEF_ATTRIB(RESTRICT_LATEPRED, "Predicate can not be used as a .new.", "", "")
198
199
/* HVX IEEE FP extension attributes */
200
DEF_ATTRIB(HVX_IEEE_FP, "HVX IEEE FP extension instruction", "", "")
201
+DEF_ATTRIB(HVX_IEEE_FP_ACC, "HVX IEEE FP accumulate instruction", "", "")
202
+DEF_ATTRIB(HVX_IEEE_FP_OUT_16, "HVX IEEE FP 16-bit output", "", "")
203
+DEF_ATTRIB(HVX_IEEE_FP_OUT_32, "HVX IEEE FP 32-bit output", "", "")
204
+DEF_ATTRIB(CVI_VX_NO_TMP_LD, "HVX multiply without tmp load", "", "")
205
206
/* Keep this as the last attribute: */
207
DEF_ATTRIB(ZZ_LASTATTRIB, "Last attribute in the file", "", "")
target/hexagon/cpu.c
+3
@@ -420,6 +420,9 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
420
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
421
/* Default NaN value: sign bit set, all frac bits set */
422
set_float_default_nan_pattern(0b11111111, &env->fp_status);
423
+
424
+ set_default_nan_mode(1, &env->hvx_fp_status);
425
+ set_float_default_nan_pattern(0b01111111, &env->hvx_fp_status);
426
#ifndef CONFIG_USER_ONLY
427
memset(env->t_sreg, 0, sizeof(uint32_t) * NUM_SREGS);
428
memset(env->greg, 0, sizeof(uint32_t) * NUM_GREGS);
target/hexagon/cpu.h
+1
@@ -152,6 +152,7 @@ typedef struct CPUArchState {
152
MemLog mem_log_stores[STORES_MAX];
153
154
float_status fp_status;
155
+ float_status hvx_fp_status;
156
157
target_ulong llsc_addr;
158
target_ulong llsc_val;
target/hexagon/hex_common.py
+1
@@ -253,6 +253,7 @@ def need_env(tag):
253
"A_LOAD" in attribdict[tag] or
254
"A_CVI_GATHER" in attribdict[tag] or
255
"A_CVI_SCATTER" in attribdict[tag] or
256
+ "A_HVX_IEEE_FP" in attribdict[tag] or
257
"A_IMPLICIT_WRITES_USR" in attribdict[tag] or
258
"A_PRIV" in attribdict[tag] or
259
"J2_trap" in tag)
target/hexagon/imported/mmvec/encode_ext.def
+18
@@ -804,5 +804,23 @@ DEF_ENC(V6_vmpyewuh, ICLASS_CJ" 1 111 111 vvvvv PP 0 uuuuu 101 ddddd")
804
DEF_ENC(V6_vmpyowh, ICLASS_CJ" 1 111 111 vvvvv PP 0 uuuuu 111 ddddd")
805
DEF_ENC(V6_vmpyuhvs,"00011111110vvvvvPP1uuuuu111ddddd")
806
807
+/* IEEE FP multiply instructions */
808
+DEF_ENC(V6_vmpy_sf_sf,"00011111100vvvvvPP1uuuuu001ddddd")
809
+DEF_ENC(V6_vmpy_sf_hf,"00011111100vvvvvPP1uuuuu010ddddd")
810
+DEF_ENC(V6_vmpy_hf_hf,"00011111100vvvvvPP1uuuuu011ddddd")
811
+DEF_ENC(V6_vdmpy_sf_hf,"00011111101vvvvvPP1uuuuu110ddddd")
812
+
813
+/* IEEE FP multiply-accumulate instructions */
814
+DEF_ENC(V6_vmpy_sf_hf_acc,"00011100010vvvvvPP1uuuuu001xxxxx")
815
+DEF_ENC(V6_vmpy_hf_hf_acc,"00011100010vvvvvPP1uuuuu010xxxxx")
816
+DEF_ENC(V6_vdmpy_sf_hf_acc,"00011100010vvvvvPP1uuuuu011xxxxx")
817
+
818
+/* IEEE FP add/sub instructions */
819
+DEF_ENC(V6_vadd_sf_sf,"00011111100vvvvvPP1uuuuu110ddddd")
820
+DEF_ENC(V6_vsub_sf_sf,"00011111100vvvvvPP1uuuuu111ddddd")
821
+DEF_ENC(V6_vadd_sf_hf,"00011111100vvvvvPP1uuuuu100ddddd")
822
+DEF_ENC(V6_vsub_sf_hf,"00011111100vvvvvPP1uuuuu101ddddd")
823
+DEF_ENC(V6_vadd_hf_hf,"00011111101vvvvvPP1uuuuu111ddddd")
824
+DEF_ENC(V6_vsub_hf_hf,"00011111011vvvvvPP1uuuuu000ddddd")
825
826
#endif /* NO MMVEC */
target/hexagon/imported/mmvec/ext.idef
+101
@@ -2895,9 +2895,110 @@ EXTINSN(V6_vprefixqw,"Vd32.w=prefixsum(Qv4)", ATTRIBS(A_EXTENSION,A_CVI,A_CVI_
2895
}
2896
} )
2897
2898
+/* KVX - IEEE FP Instructions */
2899
2900
+/* Single pipe, 32-bit output */
2901
+#define ITERATOR_INSN_IEEE_FP_32(WIDTH,TAG,SYNTAX,DESCR,CODE) \
2902
+EXTINSN(V6_##TAG, SYNTAX, \
2903
+ATTRIBS(A_EXTENSION,A_HVX_IEEE_FP,A_CVI,A_CVI_VX,A_HVX_IEEE_FP_OUT_32), \
2904
+DESCR, DO_FOR_EACH_CODE(WIDTH, CODE))
2905
+
2906
+/* Single pipe, 16-bit output */
2907
+#define ITERATOR_INSN_IEEE_FP_16(WIDTH,TAG,SYNTAX,DESCR,CODE) \
2908
+EXTINSN(V6_##TAG, SYNTAX, \
2909
+ATTRIBS(A_EXTENSION,A_HVX_IEEE_FP,A_CVI,A_CVI_VX,A_HVX_IEEE_FP_OUT_16), \
2910
+DESCR, DO_FOR_EACH_CODE(WIDTH, CODE))
2911
+
2912
+/* Two pipes: P2 & P3, single output: P2, 32-bit output */
2913
+#define ITERATOR_INSN_IEEE_FP_DOUBLE_SINGLE_32(WIDTH,TAG,SYNTAX,DESCR,CODE) \
2914
+EXTINSN(V6_##TAG, SYNTAX, \
2915
+ATTRIBS(A_EXTENSION,A_HVX_IEEE_FP,A_CVI,A_CVI_VX_DV,A_HVX_IEEE_FP_OUT_32), \
2916
+DESCR, DO_FOR_EACH_CODE(WIDTH, CODE))
2917
+
2918
+/* Two pipes: P2 & P3, two outputs, 32-bit output */
2919
+#define ITERATOR_INSN_IEEE_FP_DOUBLE_32(WIDTH,TAG,SYNTAX,DESCR,CODE) \
2920
+EXTINSN(V6_##TAG, SYNTAX, \
2921
+ATTRIBS(A_EXTENSION,A_HVX_IEEE_FP,A_CVI,A_CVI_VX_DV,A_HVX_IEEE_FP_OUT_32), \
2922
+DESCR, DO_FOR_EACH_CODE(WIDTH, CODE))
2923
+
2924
+/*
2925
+ * single pipe, accumulate instruction, produces 16-bit output, requires 16-bit
2926
+ * accumulate input
2927
+ */
2928
+#define ITERATOR_INSN_IEEE_FP_ACC_16(WIDTH,TAG,SYNTAX,DESCR,CODE) \
2929
+EXTINSN(V6_##TAG, SYNTAX, \
2930
+ATTRIBS(A_EXTENSION,A_HVX_IEEE_FP,A_CVI,A_CVI_VX,A_HVX_IEEE_FP_ACC,A_HVX_IEEE_FP_OUT_16,A_CVI_VX_NO_TMP_LD), \
2931
+DESCR, DO_FOR_EACH_CODE(WIDTH, CODE))
2932
2933
+/*
2934
+ * single pipe, accumulate instruction, produces 32-bit output, requires 32-bit
2935
+ * accumulate input
2936
+ */
2937
+#define ITERATOR_INSN_IEEE_FP_ACC_32(WIDTH,TAG,SYNTAX,DESCR,CODE) \
2938
+EXTINSN(V6_##TAG, SYNTAX, \
2939
+ATTRIBS(A_EXTENSION,A_HVX_IEEE_FP,A_CVI,A_CVI_VX,A_HVX_IEEE_FP_ACC,A_HVX_IEEE_FP_OUT_32,A_CVI_VX_NO_TMP_LD), \
2940
+DESCR, DO_FOR_EACH_CODE(WIDTH, CODE))
2941
2942
+/* IEEE FP multiply instructions */
2943
+ITERATOR_INSN_IEEE_FP_DOUBLE_SINGLE_32(32, vmpy_sf_sf,
2944
+ "Vd32.sf=vmpy(Vu32.sf,Vv32.sf)", "Vector IEEE mul: sf",
2945
+ VdV.sf[i] = float32_mul(VuV.sf[i], VvV.sf[i], &env->hvx_fp_status))
2946
+ITERATOR_INSN_IEEE_FP_DOUBLE_32(32, vmpy_sf_hf,
2947
+ "Vdd32.sf=vmpy(Vu32.hf,Vv32.hf)", "Vector IEEE mul: hf widen to sf",
2948
+ VddV.v[0].sf[i] = fp_mult_sf_hf(VuV.hf[2*i], VvV.hf[2*i], &env->hvx_fp_status);
2949
+ VddV.v[1].sf[i] = fp_mult_sf_hf(VuV.hf[2*i+1], VvV.hf[2*i+1], &env->hvx_fp_status))
2950
+ITERATOR_INSN_IEEE_FP_16(16, vmpy_hf_hf, "Vd32.hf=vmpy(Vu32.hf,Vv32.hf)",
2951
+ "Vector IEEE mul: hf",
2952
+ VdV.hf[i] = float16_mul(VuV.hf[i], VvV.hf[i], &env->hvx_fp_status))
2953
+ITERATOR_INSN_IEEE_FP_32(32, vdmpy_sf_hf, "Vd32.sf=vdmpy(Vu32.hf,Vv32.hf)",
2954
+ "Vector IEEE mul reduction: hf widen to sf",
2955
+ VdV.sf[i] = fp_vdmpy(VuV.hf[2*i+1], VuV.hf[2*i], VvV.hf[2*i+1],
2956
+ VvV.hf[2*i], &env->hvx_fp_status))
2957
+
2958
+/* IEEE FP multiply-accumulate instructions */
2959
+ITERATOR_INSN_IEEE_FP_DOUBLE_32(32, vmpy_sf_hf_acc,
2960
+ "Vxx32.sf+=vmpy(Vu32.hf,Vv32.hf)", "Vector IEEE fma: hf widen to sf",
2961
+ VxxV.v[0].sf[i] = float32_muladd(f16_to_f32(VuV.hf[2*i]),
2962
+ f16_to_f32(VvV.hf[2*i]),
2963
+ VxxV.v[0].sf[i], 0, &env->hvx_fp_status);
2964
+ VxxV.v[1].sf[i] = float32_muladd(f16_to_f32(VuV.hf[2*i+1]),
2965
+ f16_to_f32(VvV.hf[2*i+1]),
2966
+ VxxV.v[1].sf[i], 0, &env->hvx_fp_status))
2967
+ITERATOR_INSN_IEEE_FP_ACC_16(16, vmpy_hf_hf_acc,
2968
+ "Vx32.hf+=vmpy(Vu32.hf,Vv32.hf)", "Vector IEEE fma: hf",
2969
+ VxV.hf[i] = float16_muladd(VuV.hf[i], VvV.hf[i], VxV.hf[i], 0, &env->hvx_fp_status))
2970
+ITERATOR_INSN_IEEE_FP_ACC_32(32, vdmpy_sf_hf_acc,
2971
+ "Vx32.sf+=vdmpy(Vu32.hf,Vv32.hf)", "Vector IEEE fma reduce: hf widen to sf",
2972
+ VxV.sf[i] = float32_add(fp_vdmpy(VuV.hf[2*i+1], VuV.hf[2*i],
2973
+ VvV.hf[2*i+1], VvV.hf[2*i],
2974
+ &env->hvx_fp_status),
2975
+ VxV.sf[i], &env->hvx_fp_status))
2976
+
2977
+/* IEEE FP add/sub instructions */
2978
+ITERATOR_INSN_IEEE_FP_32(32, vadd_sf_sf, "Vd32.sf=vadd(Vu32.sf,Vv32.sf)",
2979
+ "Vector IEEE add: sf",
2980
+ VdV.sf[i] = float32_add(VuV.sf[i], VvV.sf[i], &env->hvx_fp_status))
2981
+ITERATOR_INSN_IEEE_FP_32(32, vsub_sf_sf, "Vd32.sf=vsub(Vu32.sf,Vv32.sf)",
2982
+ "Vector IEEE sub: sf",
2983
+ VdV.sf[i] = float32_sub(VuV.sf[i], VvV.sf[i], &env->hvx_fp_status))
2984
+ITERATOR_INSN_IEEE_FP_16(16, vadd_hf_hf, "Vd32.hf=vadd(Vu32.hf,Vv32.hf)",
2985
+ "Vector IEEE add: hf",
2986
+ VdV.hf[i] = float16_add(VuV.hf[i], VvV.hf[i], &env->hvx_fp_status))
2987
+ITERATOR_INSN_IEEE_FP_16(16, vsub_hf_hf, "Vd32.hf=vsub(Vu32.hf,Vv32.hf)",
2988
+ "Vector IEEE sub: hf",
2989
+ VdV.hf[i] = float16_sub(VuV.hf[i], VvV.hf[i], &env->hvx_fp_status))
2990
+ITERATOR_INSN_IEEE_FP_DOUBLE_32(32, vadd_sf_hf,
2991
+ "Vdd32.sf=vadd(Vu32.hf,Vv32.hf)", "Vector IEEE add: hf widen to sf",
2992
+ VddV.v[0].sf[i] = float32_add(f16_to_f32(VuV.hf[2*i]),
2993
+ f16_to_f32(VvV.hf[2*i]), &env->hvx_fp_status);
2994
+ VddV.v[1].sf[i] = float32_add(f16_to_f32(VuV.hf[2*i+1]),
2995
+ f16_to_f32(VvV.hf[2*i+1]), &env->hvx_fp_status))
2996
+ITERATOR_INSN_IEEE_FP_DOUBLE_32(32, vsub_sf_hf,
2997
+ "Vdd32.sf=vsub(Vu32.hf,Vv32.hf)", "Vector IEEE sub: hf widen to sf",
2998
+ VddV.v[0].sf[i] = float32_sub(f16_to_f32(VuV.hf[2*i]),
2999
+ f16_to_f32(VvV.hf[2*i]), &env->hvx_fp_status);
3000
+ VddV.v[1].sf[i] = float32_sub(f16_to_f32(VuV.hf[2*i+1]),
3001
+ f16_to_f32(VvV.hf[2*i+1]), &env->hvx_fp_status))
3002
3003
/******************************************************************************
3004
DEBUG Vector/Register Printing
target/hexagon/meson.build
+1
@@ -252,6 +252,7 @@ hexagon_ss.add(files(
252
'fma_emu.c',
253
'mmvec/decode_ext_mmvec.c',
254
'mmvec/system_ext_mmvec.c',
255
+ 'mmvec/hvx_ieee_fp.c',
256
))
257
258
hexagon_softmmu_ss.add(files(
target/hexagon/mmvec/hvx_ieee_fp.c
new
+21
@@ -0,0 +1,21 @@
1
+/*
2
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
3
+ *
4
+ * SPDX-License-Identifier: GPL-2.0-or-later
5
+ */
6
+
7
+#include "qemu/osdep.h"
8
+#include "hvx_ieee_fp.h"
9
+
10
+float32 fp_mult_sf_hf(float16 a1, float16 a2, float_status *fp_status)
11
+{
12
+ return float32_mul(float16_to_float32(a1, true, fp_status),
13
+ float16_to_float32(a2, true, fp_status), fp_status);
14
+}
15
+
16
+float32 fp_vdmpy(float16 a1, float16 a2, float16 a3, float16 a4,
17
+ float_status *fp_status)
18
+{
19
+ return float32_add(fp_mult_sf_hf(a1, a3, fp_status),
20
+ fp_mult_sf_hf(a2, a4, fp_status), fp_status);
21
+}
target/hexagon/mmvec/hvx_ieee_fp.h
new
+18
@@ -0,0 +1,18 @@
1
+/*
2
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
3
+ *
4
+ * SPDX-License-Identifier: GPL-2.0-or-later
5
+ */
6
+
7
+#ifndef HEXAGON_HVX_IEEE_H
8
+#define HEXAGON_HVX_IEEE_H
9
+
10
+#include "fpu/softfloat.h"
11
+
12
+#define f16_to_f32(A) float16_to_float32((A), true, &env->hvx_fp_status)
13
+
14
+float32 fp_mult_sf_hf(float16 a1, float16 a2, float_status *fp_status);
15
+float32 fp_vdmpy(float16 a1, float16 a2, float16 a3, float16 a4,
16
+ float_status *fp_status);
17
+
18
+#endif
target/hexagon/mmvec/macros.h
+1
@@ -23,6 +23,7 @@
23
#include "mmvec/system_ext_mmvec.h"
24
#include "accel/tcg/getpc.h"
25
#include "accel/tcg/probe.h"
26
+#include "mmvec/hvx_ieee_fp.h"
27
28
#ifndef QEMU_GENERATE
29
#define VdV (*(MMVector *restrict)(VdV_void))
target/hexagon/mmvec/mmvec.h
+2
@@ -41,6 +41,8 @@ typedef union {
41
int16_t h[MAX_VEC_SIZE_BYTES / 2];
42
uint8_t ub[MAX_VEC_SIZE_BYTES / 1];
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
} MMVector;
47
48
typedef union {