2 * Copyright(c) 2020-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 * This test checks various FP operations performed on Hexagon
24 const int FPINVF_BIT
= 1; /* Invalid */
25 const int FPINVF
= 1 << FPINVF_BIT
;
26 const int FPDBZF_BIT
= 2; /* Divide by zero */
27 const int FPDBZF
= 1 << FPDBZF_BIT
;
28 const int FPOVFF_BIT
= 3; /* Overflow */
29 const int FPOVFF
= 1 << FPOVFF_BIT
;
30 const int FPUNFF_BIT
= 4; /* Underflow */
31 const int FPUNFF
= 1 << FPUNFF_BIT
;
32 const int FPINPF_BIT
= 5; /* Inexact */
33 const int FPINPF
= 1 << FPINPF_BIT
;
35 const int SF_ZERO
= 0x00000000;
36 const int SF_NaN
= 0x7fc00000;
37 const int SF_NaN_special
= 0x7f800001;
38 const int SF_ANY
= 0x3f800000;
39 const int SF_HEX_NAN
= 0xffffffff;
41 const long long DF_NaN
= 0x7ff8000000000000ULL
;
42 const long long DF_ANY
= 0x3f80000000000000ULL
;
43 const long long DF_HEX_NAN
= 0xffffffffffffffffULL
;
47 #define CLEAR_FPSTATUS \
49 "r2 = clrbit(r2, #1)\n\t" \
50 "r2 = clrbit(r2, #2)\n\t" \
51 "r2 = clrbit(r2, #3)\n\t" \
52 "r2 = clrbit(r2, #4)\n\t" \
53 "r2 = clrbit(r2, #5)\n\t" \
56 static void check_fpstatus_bit(int usr
, int expect
, int flag
, const char *n
)
59 if ((usr
& bit
) != (expect
& bit
)) {
60 printf("ERROR %s: usr = %d, expect = %d\n", n
,
61 (usr
>> flag
) & 1, (expect
>> flag
) & 1);
66 static void check_fpstatus(int usr
, int expect
)
68 check_fpstatus_bit(usr
, expect
, FPINVF_BIT
, "Invalid");
69 check_fpstatus_bit(usr
, expect
, FPDBZF_BIT
, "Div by zero");
70 check_fpstatus_bit(usr
, expect
, FPOVFF_BIT
, "Overflow");
71 check_fpstatus_bit(usr
, expect
, FPUNFF_BIT
, "Underflow");
72 check_fpstatus_bit(usr
, expect
, FPINPF_BIT
, "Inexact");
75 static void check32(int val
, int expect
)
78 printf("ERROR: 0x%x != 0x%x\n", val
, expect
);
82 static void check64(unsigned long long val
, unsigned long long expect
)
85 printf("ERROR: 0x%llx != 0x%llx\n", val
, expect
);
90 static void check_compare_exception(void)
95 /* Check that FP compares are quiet (don't raise any execptions) */
97 "p0 = sfcmp.eq(%2, %3)\n\t"
100 : "=r"(cmp
), "=r"(usr
) : "r"(SF_NaN
), "r"(SF_ANY
)
101 : "r2", "p0", "usr");
103 check_fpstatus(usr
, 0);
106 "p0 = sfcmp.gt(%2, %3)\n\t"
109 : "=r"(cmp
), "=r"(usr
) : "r"(SF_NaN
), "r"(SF_ANY
)
110 : "r2", "p0", "usr");
112 check_fpstatus(usr
, 0);
115 "p0 = sfcmp.ge(%2, %3)\n\t"
118 : "=r"(cmp
), "=r"(usr
) : "r"(SF_NaN
), "r"(SF_ANY
)
119 : "r2", "p0", "usr");
121 check_fpstatus(usr
, 0);
124 "p0 = dfcmp.eq(%2, %3)\n\t"
127 : "=r"(cmp
), "=r"(usr
) : "r"(DF_NaN
), "r"(DF_ANY
)
128 : "r2", "p0", "usr");
130 check_fpstatus(usr
, 0);
133 "p0 = dfcmp.gt(%2, %3)\n\t"
136 : "=r"(cmp
), "=r"(usr
) : "r"(DF_NaN
), "r"(DF_ANY
)
137 : "r2", "p0", "usr");
139 check_fpstatus(usr
, 0);
142 "p0 = dfcmp.ge(%2, %3)\n\t"
145 : "=r"(cmp
), "=r"(usr
) : "r"(DF_NaN
), "r"(DF_ANY
)
146 : "r2", "p0", "usr");
148 check_fpstatus(usr
, 0);
151 static void check_sfminmax(void)
157 * Execute sfmin/sfmax instructions with one operand as NaN
159 * Result is the other operand
160 * Invalid bit in USR is not set
163 "%0 = sfmin(%2, %3)\n\t"
165 : "=r"(minmax
), "=r"(usr
) : "r"(SF_NaN
), "r"(SF_ANY
)
167 check64(minmax
, SF_ANY
);
168 check_fpstatus(usr
, 0);
171 "%0 = sfmax(%2, %3)\n\t"
173 : "=r"(minmax
), "=r"(usr
) : "r"(SF_NaN
), "r"(SF_ANY
)
175 check64(minmax
, SF_ANY
);
176 check_fpstatus(usr
, 0);
179 * Execute sfmin/sfmax instructions with both operands NaN
181 * Result is SF_HEX_NAN
182 * Invalid bit in USR is set
185 "%0 = sfmin(%2, %3)\n\t"
187 : "=r"(minmax
), "=r"(usr
) : "r"(SF_NaN
), "r"(SF_NaN
)
189 check64(minmax
, SF_HEX_NAN
);
190 check_fpstatus(usr
, 0);
193 "%0 = sfmax(%2, %3)\n\t"
195 : "=r"(minmax
), "=r"(usr
) : "r"(SF_NaN
), "r"(SF_NaN
)
197 check64(minmax
, SF_HEX_NAN
);
198 check_fpstatus(usr
, 0);
201 static void check_dfminmax(void)
203 unsigned long long minmax
;
207 * Execute dfmin/dfmax instructions with one operand as NaN
209 * Result is the other operand
210 * Invalid bit in USR is set
213 "%0 = dfmin(%2, %3)\n\t"
215 : "=r"(minmax
), "=r"(usr
) : "r"(DF_NaN
), "r"(DF_ANY
)
217 check64(minmax
, DF_ANY
);
218 check_fpstatus(usr
, FPINVF
);
221 "%0 = dfmax(%2, %3)\n\t"
223 : "=r"(minmax
), "=r"(usr
) : "r"(DF_NaN
), "r"(DF_ANY
)
225 check64(minmax
, DF_ANY
);
226 check_fpstatus(usr
, FPINVF
);
229 * Execute dfmin/dfmax instructions with both operands NaN
231 * Result is DF_HEX_NAN
232 * Invalid bit in USR is set
235 "%0 = dfmin(%2, %3)\n\t"
237 : "=r"(minmax
), "=r"(usr
) : "r"(DF_NaN
), "r"(DF_NaN
)
239 check64(minmax
, DF_HEX_NAN
);
240 check_fpstatus(usr
, FPINVF
);
243 "%0 = dfmax(%2, %3)\n\t"
245 : "=r"(minmax
), "=r"(usr
) : "r"(DF_NaN
), "r"(DF_NaN
)
247 check64(minmax
, DF_HEX_NAN
);
248 check_fpstatus(usr
, FPINVF
);
251 static void check_canonical_NaN(void)
254 unsigned long long df_result
;
257 /* Check that each FP instruction properly returns SF_HEX_NAN/DF_HEX_NAN */
259 "%0 = sfadd(%2, %3)\n\t"
261 : "=r"(sf_result
), "=r"(usr
) : "r"(SF_NaN
), "r"(SF_ANY
)
263 check32(sf_result
, SF_HEX_NAN
);
264 check_fpstatus(usr
, 0);
267 "%0 = sfsub(%2, %3)\n\t"
269 : "=r"(sf_result
), "=r"(usr
) : "r"(SF_NaN
), "r"(SF_ANY
)
271 check32(sf_result
, SF_HEX_NAN
);
272 check_fpstatus(usr
, 0);
275 "%0 = sfmpy(%2, %3)\n\t"
277 : "=r"(sf_result
), "=r"(usr
) : "r"(SF_NaN
), "r"(SF_ANY
)
279 check32(sf_result
, SF_HEX_NAN
);
280 check_fpstatus(usr
, 0);
284 "%0 += sfmpy(%2, %3)\n\t"
286 : "+r"(sf_result
), "=r"(usr
) : "r"(SF_NaN
), "r"(SF_ANY
)
288 check32(sf_result
, SF_HEX_NAN
);
289 check_fpstatus(usr
, 0);
293 "p0 = !cmp.eq(r0, r0)\n\t"
294 "%0 += sfmpy(%2, %3, p0):scale\n\t"
296 : "+r"(sf_result
), "=r"(usr
) : "r"(SF_NaN
), "r"(SF_ANY
)
297 : "r2", "usr", "p0");
298 check32(sf_result
, SF_HEX_NAN
);
299 check_fpstatus(usr
, 0);
303 "%0 -= sfmpy(%2, %3)\n\t"
305 : "+r"(sf_result
), "=r"(usr
) : "r"(SF_NaN
), "r"(SF_ANY
)
307 check32(sf_result
, SF_HEX_NAN
);
308 check_fpstatus(usr
, 0);
312 "%0 += sfmpy(%2, %3):lib\n\t"
314 : "+r"(sf_result
), "=r"(usr
) : "r"(SF_NaN
), "r"(SF_ANY
)
316 check32(sf_result
, SF_HEX_NAN
);
317 check_fpstatus(usr
, 0);
321 "%0 -= sfmpy(%2, %3):lib\n\t"
323 : "+r"(sf_result
), "=r"(usr
) : "r"(SF_NaN
), "r"(SF_ANY
)
325 check32(sf_result
, SF_HEX_NAN
);
326 check_fpstatus(usr
, 0);
329 "%0 = convert_df2sf(%2)\n\t"
331 : "=r"(sf_result
), "=r"(usr
) : "r"(DF_NaN
)
333 check32(sf_result
, SF_HEX_NAN
);
334 check_fpstatus(usr
, 0);
337 "%0 = dfadd(%2, %3)\n\t"
339 : "=r"(df_result
), "=r"(usr
) : "r"(DF_NaN
), "r"(DF_ANY
)
341 check64(df_result
, DF_HEX_NAN
);
342 check_fpstatus(usr
, 0);
345 "%0 = dfsub(%2, %3)\n\t"
347 : "=r"(df_result
), "=r"(usr
) : "r"(DF_NaN
), "r"(DF_ANY
)
349 check64(df_result
, DF_HEX_NAN
);
350 check_fpstatus(usr
, 0);
353 "%0 = convert_sf2df(%2)\n\t"
355 : "=r"(df_result
), "=r"(usr
) : "r"(SF_NaN
)
357 check64(df_result
, DF_HEX_NAN
);
358 check_fpstatus(usr
, 0);
363 check_compare_exception();
366 check_canonical_NaN();
368 puts(err
? "FAIL" : "PASS");