target/hexagon: add v68 HVX IEEE float compare insns
Add HVX IEEE floating-point compare instructions: - V6_vgthf, V6_vgtsf: greater-than compare - V6_vgthf_and, V6_vgtsf_and: greater-than with predicate-and - V6_vgthf_or, V6_vgtsf_or: greater-than with predicate-or - V6_vgthf_xor, V6_vgtsf_xor: greater-than with predicate-xor 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/96e27588ad5a7d47ba9f56f1d547729a19b691c5.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
7646bc0b72a78960d497371036d5841dc590412b
5 files changed
+128
-1
target/hexagon/imported/mmvec/encode_ext.def
+10
@@ -858,4 +858,14 @@ DEF_ENC(V6_vconv_w_sf,"00011110--0--101PP1uuuuu001ddddd")
858
DEF_ENC(V6_vconv_hf_h,"00011110--0--101PP1uuuuu100ddddd")
859
DEF_ENC(V6_vconv_h_hf,"00011110--0--101PP1uuuuu010ddddd")
860
861
+/* IEEE FP compare instructions */
862
+DEF_ENC(V6_vgtsf,"00011100100vvvvvPP1uuuuu011100dd")
863
+DEF_ENC(V6_vgthf,"00011100100vvvvvPP1uuuuu011101dd")
864
+DEF_ENC(V6_vgtsf_and,"00011100100vvvvvPP1uuuuu110010xx")
865
+DEF_ENC(V6_vgthf_and,"00011100100vvvvvPP1uuuuu110011xx")
866
+DEF_ENC(V6_vgtsf_or,"00011100100vvvvvPP1uuuuu001100xx")
867
+DEF_ENC(V6_vgthf_or,"00011100100vvvvvPP1uuuuu001101xx")
868
+DEF_ENC(V6_vgtsf_xor,"00011100100vvvvvPP1uuuuu111010xx")
869
+DEF_ENC(V6_vgthf_xor,"00011100100vvvvvPP1uuuuu111011xx")
870
+
871
#endif /* NO MMVEC */
target/hexagon/imported/mmvec/ext.idef
+61
@@ -3143,6 +3143,67 @@ ITERATOR_INSN_SHIFT_SLOT_FLT(16, vconv_hf_h,"Vd32.hf=Vu32.h",
3143
"Vector conversion of int hw format to hf16",
3144
VdV.hf[i] = float16_val(int16_to_float16(VuV.h[i], &env->hvx_fp_status)))
3145
3146
+/******************************************************************************
3147
+ * IEEE FP compare instructions
3148
+ ******************************************************************************/
3149
+
3150
+#define VCMPGT_SF(DEST, ASRC, ASRCOP, CMP, N, SRC, MASK, WIDTH) \
3151
+{ \
3152
+ for (fHIDE(int) i = 0; i < fVBYTES(); i += WIDTH) { \
3153
+ fHIDE(int) VAL = fCMPGT_SF(VuV.SRC[i/WIDTH],VvV.SRC[i/WIDTH]) ? MASK : 0; \
3154
+ fSETQBITS(DEST,WIDTH,MASK,i,ASRC ASRCOP VAL); \
3155
+ } \
3156
+}
3157
+
3158
+#define VCMPGT_HF(DEST, ASRC, ASRCOP, CMP, N, SRC, MASK, WIDTH) \
3159
+{ \
3160
+ for (fHIDE(int) i = 0; i < fVBYTES(); i += WIDTH) { \
3161
+ fHIDE(int) VAL = fCMPGT_HF(VuV.SRC[i/WIDTH],VvV.SRC[i/WIDTH]) ? MASK : 0; \
3162
+ fSETQBITS(DEST,WIDTH,MASK,i,ASRC ASRCOP VAL); \
3163
+ } \
3164
+}
3165
+
3166
+/* Vector SF compare */
3167
+#define MMVEC_CMPGT_SF(TYPE,TYPE2,DESCR,N,MASK,WIDTH,SRC) \
3168
+ EXTINSN(V6_vgt##TYPE##_and, "Qx4&=vcmp.gt(Vu32." TYPE2 ",Vv32." TYPE2 ")", \
3169
+ ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VA,A_CVI_VA_2SRC,A_HVX_FLT), \
3170
+ DESCR" greater than with predicate-and", \
3171
+ VCMPGT_SF(QxV, fGETQBITS(QxV,WIDTH,MASK,i), &, ">", N, SRC, MASK, WIDTH)) \
3172
+ EXTINSN(V6_vgt##TYPE##_xor, "Qx4^=vcmp.gt(Vu32." TYPE2 ",Vv32." TYPE2 ")", \
3173
+ ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VA,A_CVI_VA_2SRC,A_HVX_FLT), \
3174
+ DESCR" greater than with predicate-xor", \
3175
+ VCMPGT_SF(QxV, fGETQBITS(QxV,WIDTH,MASK,i), ^, ">", N, SRC, MASK, WIDTH)) \
3176
+ EXTINSN(V6_vgt##TYPE##_or, "Qx4|=vcmp.gt(Vu32." TYPE2 ",Vv32." TYPE2 ")", \
3177
+ ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VA,A_CVI_VA_2SRC,A_HVX_FLT), \
3178
+ DESCR" greater than with predicate-or", \
3179
+ VCMPGT_SF(QxV, fGETQBITS(QxV,WIDTH,MASK,i), |, ">", N, SRC, MASK, WIDTH)) \
3180
+ EXTINSN(V6_vgt##TYPE, "Qd4=vcmp.gt(Vu32." TYPE2 ",Vv32." TYPE2 ")", \
3181
+ ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VA,A_CVI_VA_2SRC,A_HVX_FLT), \
3182
+ DESCR" greater than", \
3183
+ VCMPGT_SF(QdV, , , ">", N, SRC, MASK, WIDTH))
3184
+
3185
+/* Vector HF compare */
3186
+#define MMVEC_CMPGT_HF(TYPE,TYPE2,DESCR,N,MASK,WIDTH,SRC) \
3187
+ EXTINSN(V6_vgt##TYPE##_and, "Qx4&=vcmp.gt(Vu32." TYPE2 ",Vv32." TYPE2 ")", \
3188
+ ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VA,A_CVI_VA_2SRC,A_HVX_FLT), \
3189
+ DESCR" greater than with predicate-and", \
3190
+ VCMPGT_HF(QxV, fGETQBITS(QxV,WIDTH,MASK,i), &, ">", N, SRC, MASK, WIDTH)) \
3191
+ EXTINSN(V6_vgt##TYPE##_xor, "Qx4^=vcmp.gt(Vu32." TYPE2 ",Vv32." TYPE2 ")", \
3192
+ ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VA,A_CVI_VA_2SRC,A_HVX_FLT), \
3193
+ DESCR" greater than with predicate-xor", \
3194
+ VCMPGT_HF(QxV, fGETQBITS(QxV,WIDTH,MASK,i), ^, ">", N, SRC, MASK, WIDTH)) \
3195
+ EXTINSN(V6_vgt##TYPE##_or, "Qx4|=vcmp.gt(Vu32." TYPE2 ",Vv32." TYPE2 ")", \
3196
+ ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VA,A_CVI_VA_2SRC,A_HVX_FLT), \
3197
+ DESCR" greater than with predicate-or", \
3198
+ VCMPGT_HF(QxV, fGETQBITS(QxV,WIDTH,MASK,i), |, ">", N, SRC, MASK, WIDTH)) \
3199
+ EXTINSN(V6_vgt##TYPE, "Qd4=vcmp.gt(Vu32." TYPE2 ",Vv32." TYPE2 ")", \
3200
+ ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VA,A_CVI_VA_2SRC,A_HVX_FLT), \
3201
+ DESCR" greater than", \
3202
+ VCMPGT_HF(QdV, , , ">", N, SRC, MASK, WIDTH))
3203
+
3204
+MMVEC_CMPGT_SF(sf,"sf","Vector sf Compare ", fVELEM(32), 0xF, 4, sf)
3205
+MMVEC_CMPGT_HF(hf,"hf","Vector hf Compare ", fVELEM(16), 0x3, 2, hf)
3206
+
3207
/******************************************************************************
3208
DEBUG Vector/Register Printing
3209
******************************************************************************/
target/hexagon/mmvec/hvx_ieee_fp.c
+48
@@ -87,3 +87,51 @@ int16_t conv_h_hf(float16 a, float_status *fp_status)
87
}
88
return float16_to_int16_round_to_zero(a, fp_status);
89
}
90
+
91
+/*
92
+ * Returns true if f1 > f2, where at least one of the elements is guaranteed
93
+ * to be NaN.
94
+ * Up to v73, Hexagon HVX IEEE FP follows this order:
95
+ * QNaN > SNaN > +Inf > numbers > -Inf > SNaN_neg > QNaN_neg
96
+ */
97
+static bool float32_nan_compare(float32 f1, float32 f2, float_status *fp_status)
98
+{
99
+ /* opposite signs case */
100
+ if (float32_is_neg(f1) != float32_is_neg(f2)) {
101
+ return !float32_is_neg(f1);
102
+ }
103
+
104
+ /* same sign case */
105
+ bool result = (float32_is_any_nan(f1) && !float32_is_any_nan(f2)) ||
106
+ (float32_is_quiet_nan(f1, fp_status) && !float32_is_quiet_nan(f2, fp_status));
107
+ return float32_is_neg(f1) ? !result : result;
108
+}
109
+
110
+static bool float16_nan_compare(float16 f1, float16 f2, float_status *fp_status)
111
+{
112
+ /* opposite signs case */
113
+ if (float16_is_neg(f1) != float16_is_neg(f2)) {
114
+ return !float16_is_neg(f1);
115
+ }
116
+
117
+ /* same sign case */
118
+ bool result = (float16_is_any_nan(f1) && !float16_is_any_nan(f2)) ||
119
+ (float16_is_quiet_nan(f1, fp_status) && !float16_is_quiet_nan(f2, fp_status));
120
+ return float16_is_neg(f1) ? !result : result;
121
+}
122
+
123
+uint32_t cmpgt_sf(float32 a1, float32 a2, float_status *fp_status)
124
+{
125
+ if (float32_is_any_nan(a1) || float32_is_any_nan(a2)) {
126
+ return float32_nan_compare(a1, a2, fp_status);
127
+ }
128
+ return float32_compare(a1, a2, fp_status) == float_relation_greater;
129
+}
130
+
131
+uint16_t cmpgt_hf(float16 a1, float16 a2, float_status *fp_status)
132
+{
133
+ if (float16_is_any_nan(a1) || float16_is_any_nan(a2)) {
134
+ return float16_nan_compare(a1, a2, fp_status);
135
+ }
136
+ return float16_compare(a1, a2, fp_status) == float_relation_greater;
137
+}
target/hexagon/mmvec/hvx_ieee_fp.h
+4
@@ -25,4 +25,8 @@ float16 qf_min_hf(float16 a1, float16 a2, float_status *fp_status);
25
int32_t conv_w_sf(float32 a, float_status *fp_status);
26
int16_t conv_h_hf(float16 a, float_status *fp_status);
27
28
+/* IEEE - FP compare instructions */
29
+uint32_t cmpgt_sf(float32 a1, float32 a2, float_status *fp_status);
30
+uint16_t cmpgt_hf(float16 a1, float16 a2, float_status *fp_status);
31
+
32
#endif
target/hexagon/mmvec/macros.h
+5
-1
@@ -354,6 +354,10 @@
354
do { \
355
COE = (sextract32(VAL, 24 + 2 * POS, 2) << 8) | \
356
extract32(VAL, POS * 8, 8); \
357
- } while (0);
357
+ } while (0) \
358
+ ;
359
+
360
+#define fCMPGT_SF(A, B) cmpgt_sf(A, B, &env->hvx_fp_status)
361
+#define fCMPGT_HF(A, B) cmpgt_hf(A, B, &env->hvx_fp_status)
362
363
#endif