@samitouri / QOSamiQemu / commits / 69e46b2822

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 {