blob: 90ce9a6ef35cd1c650cdabef9cb80d081ad31973 [file] [log] [blame]
Taylor Simpson703c08d2021-02-07 23:46:23 -06001/*
Taylor Simpson1a442c02023-03-06 18:58:25 -08002 * Copyright(c) 2020-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
Taylor Simpson703c08d2021-02-07 23:46:23 -06003 *
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.
8 *
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.
13 *
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/>.
16 */
17
18/*
19 * This test checks various FP operations performed on Hexagon
20 */
21
22#include <stdio.h>
23
24const int FPINVF_BIT = 1; /* Invalid */
25const int FPINVF = 1 << FPINVF_BIT;
26const int FPDBZF_BIT = 2; /* Divide by zero */
27const int FPDBZF = 1 << FPDBZF_BIT;
28const int FPOVFF_BIT = 3; /* Overflow */
29const int FPOVFF = 1 << FPOVFF_BIT;
30const int FPUNFF_BIT = 4; /* Underflow */
31const int FPUNFF = 1 << FPUNFF_BIT;
32const int FPINPF_BIT = 5; /* Inexact */
33const int FPINPF = 1 << FPINPF_BIT;
34
35const int SF_ZERO = 0x00000000;
36const int SF_NaN = 0x7fc00000;
37const int SF_NaN_special = 0x7f800001;
38const int SF_ANY = 0x3f800000;
39const int SF_HEX_NAN = 0xffffffff;
Taylor Simpsonb3f37ab2021-04-08 20:07:40 -050040const int SF_small_neg = 0xab98fba8;
Taylor Simpson77ccf442022-02-09 18:15:49 -080041const int SF_denorm = 0x00000001;
42const int SF_random = 0x346001d6;
Taylor Simpson1a442c02023-03-06 18:58:25 -080043const int SF_neg_zero = 0x80000000;
Taylor Simpson703c08d2021-02-07 23:46:23 -060044
Taylor Simpsond76dd812022-02-15 20:39:39 -080045const long long DF_QNaN = 0x7ff8000000000000ULL;
46const long long DF_SNaN = 0x7ff7000000000000ULL;
Taylor Simpson703c08d2021-02-07 23:46:23 -060047const long long DF_ANY = 0x3f80000000000000ULL;
48const long long DF_HEX_NAN = 0xffffffffffffffffULL;
Taylor Simpsonb3f37ab2021-04-08 20:07:40 -050049const long long DF_small_neg = 0xbd731f7500000000ULL;
Taylor Simpson703c08d2021-02-07 23:46:23 -060050
51int err;
52
53#define CLEAR_FPSTATUS \
54 "r2 = usr\n\t" \
55 "r2 = clrbit(r2, #1)\n\t" \
56 "r2 = clrbit(r2, #2)\n\t" \
57 "r2 = clrbit(r2, #3)\n\t" \
58 "r2 = clrbit(r2, #4)\n\t" \
59 "r2 = clrbit(r2, #5)\n\t" \
60 "usr = r2\n\t"
61
62static void check_fpstatus_bit(int usr, int expect, int flag, const char *n)
63{
64 int bit = 1 << flag;
65 if ((usr & bit) != (expect & bit)) {
66 printf("ERROR %s: usr = %d, expect = %d\n", n,
67 (usr >> flag) & 1, (expect >> flag) & 1);
68 err++;
69 }
70}
71
72static void check_fpstatus(int usr, int expect)
73{
74 check_fpstatus_bit(usr, expect, FPINVF_BIT, "Invalid");
75 check_fpstatus_bit(usr, expect, FPDBZF_BIT, "Div by zero");
76 check_fpstatus_bit(usr, expect, FPOVFF_BIT, "Overflow");
77 check_fpstatus_bit(usr, expect, FPUNFF_BIT, "Underflow");
78 check_fpstatus_bit(usr, expect, FPINPF_BIT, "Inexact");
79}
80
81static void check32(int val, int expect)
82{
83 if (val != expect) {
84 printf("ERROR: 0x%x != 0x%x\n", val, expect);
85 err++;
86 }
87}
88static void check64(unsigned long long val, unsigned long long expect)
89{
90 if (val != expect) {
91 printf("ERROR: 0x%llx != 0x%llx\n", val, expect);
92 err++;
93 }
94}
95
96static void check_compare_exception(void)
97{
98 int cmp;
99 int usr;
100
101 /* Check that FP compares are quiet (don't raise any execptions) */
102 asm (CLEAR_FPSTATUS
103 "p0 = sfcmp.eq(%2, %3)\n\t"
104 "%0 = p0\n\t"
105 "%1 = usr\n\t"
106 : "=r"(cmp), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
107 : "r2", "p0", "usr");
108 check32(cmp, 0);
109 check_fpstatus(usr, 0);
110
111 asm (CLEAR_FPSTATUS
112 "p0 = sfcmp.gt(%2, %3)\n\t"
113 "%0 = p0\n\t"
114 "%1 = usr\n\t"
115 : "=r"(cmp), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
116 : "r2", "p0", "usr");
117 check32(cmp, 0);
118 check_fpstatus(usr, 0);
119
120 asm (CLEAR_FPSTATUS
121 "p0 = sfcmp.ge(%2, %3)\n\t"
122 "%0 = p0\n\t"
123 "%1 = usr\n\t"
124 : "=r"(cmp), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
125 : "r2", "p0", "usr");
126 check32(cmp, 0);
127 check_fpstatus(usr, 0);
128
129 asm (CLEAR_FPSTATUS
130 "p0 = dfcmp.eq(%2, %3)\n\t"
131 "%0 = p0\n\t"
132 "%1 = usr\n\t"
Taylor Simpsond76dd812022-02-15 20:39:39 -0800133 : "=r"(cmp), "=r"(usr) : "r"(DF_QNaN), "r"(DF_ANY)
Taylor Simpson703c08d2021-02-07 23:46:23 -0600134 : "r2", "p0", "usr");
135 check32(cmp, 0);
136 check_fpstatus(usr, 0);
137
138 asm (CLEAR_FPSTATUS
139 "p0 = dfcmp.gt(%2, %3)\n\t"
140 "%0 = p0\n\t"
141 "%1 = usr\n\t"
Taylor Simpsond76dd812022-02-15 20:39:39 -0800142 : "=r"(cmp), "=r"(usr) : "r"(DF_QNaN), "r"(DF_ANY)
Taylor Simpson703c08d2021-02-07 23:46:23 -0600143 : "r2", "p0", "usr");
144 check32(cmp, 0);
145 check_fpstatus(usr, 0);
146
147 asm (CLEAR_FPSTATUS
148 "p0 = dfcmp.ge(%2, %3)\n\t"
149 "%0 = p0\n\t"
150 "%1 = usr\n\t"
Taylor Simpsond76dd812022-02-15 20:39:39 -0800151 : "=r"(cmp), "=r"(usr) : "r"(DF_QNaN), "r"(DF_ANY)
Taylor Simpson703c08d2021-02-07 23:46:23 -0600152 : "r2", "p0", "usr");
153 check32(cmp, 0);
154 check_fpstatus(usr, 0);
155}
156
157static void check_sfminmax(void)
158{
159 int minmax;
160 int usr;
161
162 /*
163 * Execute sfmin/sfmax instructions with one operand as NaN
164 * Check that
165 * Result is the other operand
166 * Invalid bit in USR is not set
167 */
168 asm (CLEAR_FPSTATUS
169 "%0 = sfmin(%2, %3)\n\t"
170 "%1 = usr\n\t"
171 : "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
172 : "r2", "usr");
173 check64(minmax, SF_ANY);
174 check_fpstatus(usr, 0);
175
176 asm (CLEAR_FPSTATUS
177 "%0 = sfmax(%2, %3)\n\t"
178 "%1 = usr\n\t"
179 : "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
180 : "r2", "usr");
181 check64(minmax, SF_ANY);
182 check_fpstatus(usr, 0);
183
184 /*
185 * Execute sfmin/sfmax instructions with both operands NaN
186 * Check that
187 * Result is SF_HEX_NAN
188 * Invalid bit in USR is set
189 */
190 asm (CLEAR_FPSTATUS
191 "%0 = sfmin(%2, %3)\n\t"
192 "%1 = usr\n\t"
193 : "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_NaN)
194 : "r2", "usr");
195 check64(minmax, SF_HEX_NAN);
196 check_fpstatus(usr, 0);
197
198 asm (CLEAR_FPSTATUS
199 "%0 = sfmax(%2, %3)\n\t"
200 "%1 = usr\n\t"
201 : "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_NaN)
202 : "r2", "usr");
203 check64(minmax, SF_HEX_NAN);
204 check_fpstatus(usr, 0);
205}
206
207static void check_dfminmax(void)
208{
209 unsigned long long minmax;
210 int usr;
211
212 /*
Taylor Simpsond76dd812022-02-15 20:39:39 -0800213 * Execute dfmin/dfmax instructions with one operand as SNaN
Taylor Simpson703c08d2021-02-07 23:46:23 -0600214 * Check that
215 * Result is the other operand
216 * Invalid bit in USR is set
217 */
218 asm (CLEAR_FPSTATUS
219 "%0 = dfmin(%2, %3)\n\t"
220 "%1 = usr\n\t"
Taylor Simpsond76dd812022-02-15 20:39:39 -0800221 : "=r"(minmax), "=r"(usr) : "r"(DF_SNaN), "r"(DF_ANY)
Taylor Simpson703c08d2021-02-07 23:46:23 -0600222 : "r2", "usr");
223 check64(minmax, DF_ANY);
224 check_fpstatus(usr, FPINVF);
225
226 asm (CLEAR_FPSTATUS
227 "%0 = dfmax(%2, %3)\n\t"
228 "%1 = usr\n\t"
Taylor Simpsond76dd812022-02-15 20:39:39 -0800229 : "=r"(minmax), "=r"(usr) : "r"(DF_SNaN), "r"(DF_ANY)
Taylor Simpson703c08d2021-02-07 23:46:23 -0600230 : "r2", "usr");
231 check64(minmax, DF_ANY);
232 check_fpstatus(usr, FPINVF);
233
234 /*
Taylor Simpsond76dd812022-02-15 20:39:39 -0800235 * Execute dfmin/dfmax instructions with one operand as QNaN
236 * Check that
237 * Result is the other operand
238 * No bit in USR is set
239 */
240 asm (CLEAR_FPSTATUS
241 "%0 = dfmin(%2, %3)\n\t"
242 "%1 = usr\n\t"
243 : "=r"(minmax), "=r"(usr) : "r"(DF_QNaN), "r"(DF_ANY)
244 : "r2", "usr");
245 check64(minmax, DF_ANY);
246 check_fpstatus(usr, 0);
247
248 asm (CLEAR_FPSTATUS
249 "%0 = dfmax(%2, %3)\n\t"
250 "%1 = usr\n\t"
251 : "=r"(minmax), "=r"(usr) : "r"(DF_QNaN), "r"(DF_ANY)
252 : "r2", "usr");
253 check64(minmax, DF_ANY);
254 check_fpstatus(usr, 0);
255
256 /*
257 * Execute dfmin/dfmax instructions with both operands SNaN
Taylor Simpson703c08d2021-02-07 23:46:23 -0600258 * Check that
259 * Result is DF_HEX_NAN
260 * Invalid bit in USR is set
261 */
262 asm (CLEAR_FPSTATUS
263 "%0 = dfmin(%2, %3)\n\t"
264 "%1 = usr\n\t"
Taylor Simpsond76dd812022-02-15 20:39:39 -0800265 : "=r"(minmax), "=r"(usr) : "r"(DF_SNaN), "r"(DF_SNaN)
Taylor Simpson703c08d2021-02-07 23:46:23 -0600266 : "r2", "usr");
267 check64(minmax, DF_HEX_NAN);
268 check_fpstatus(usr, FPINVF);
269
270 asm (CLEAR_FPSTATUS
271 "%0 = dfmax(%2, %3)\n\t"
272 "%1 = usr\n\t"
Taylor Simpsond76dd812022-02-15 20:39:39 -0800273 : "=r"(minmax), "=r"(usr) : "r"(DF_SNaN), "r"(DF_SNaN)
Taylor Simpson703c08d2021-02-07 23:46:23 -0600274 : "r2", "usr");
275 check64(minmax, DF_HEX_NAN);
276 check_fpstatus(usr, FPINVF);
Taylor Simpsond76dd812022-02-15 20:39:39 -0800277
278 /*
279 * Execute dfmin/dfmax instructions with both operands QNaN
280 * Check that
281 * Result is DF_HEX_NAN
282 * No bit in USR is set
283 */
284 asm (CLEAR_FPSTATUS
285 "%0 = dfmin(%2, %3)\n\t"
286 "%1 = usr\n\t"
287 : "=r"(minmax), "=r"(usr) : "r"(DF_QNaN), "r"(DF_QNaN)
288 : "r2", "usr");
289 check64(minmax, DF_HEX_NAN);
290 check_fpstatus(usr, 0);
291
292 asm (CLEAR_FPSTATUS
293 "%0 = dfmax(%2, %3)\n\t"
294 "%1 = usr\n\t"
295 : "=r"(minmax), "=r"(usr) : "r"(DF_QNaN), "r"(DF_QNaN)
296 : "r2", "usr");
297 check64(minmax, DF_HEX_NAN);
298 check_fpstatus(usr, 0);
Taylor Simpson703c08d2021-02-07 23:46:23 -0600299}
300
Taylor Simpson77ccf442022-02-09 18:15:49 -0800301static void check_sfrecipa(void)
Taylor Simpsond934c162021-04-08 20:07:45 -0500302{
303 int result;
304 int usr;
Taylor Simpson77ccf442022-02-09 18:15:49 -0800305 int pred;
Taylor Simpsond934c162021-04-08 20:07:45 -0500306
307 /*
308 * Check that sfrecipa doesn't set status bits when
309 * a NaN with bit 22 non-zero is passed
310 */
311 asm (CLEAR_FPSTATUS
312 "%0,p0 = sfrecipa(%2, %3)\n\t"
313 "%1 = usr\n\t"
314 : "=r"(result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
315 : "r2", "p0", "usr");
316 check32(result, SF_HEX_NAN);
317 check_fpstatus(usr, 0);
318
319 asm (CLEAR_FPSTATUS
320 "%0,p0 = sfrecipa(%2, %3)\n\t"
321 "%1 = usr\n\t"
322 : "=r"(result), "=r"(usr) : "r"(SF_ANY), "r"(SF_NaN)
323 : "r2", "p0", "usr");
324 check32(result, SF_HEX_NAN);
325 check_fpstatus(usr, 0);
326
327 asm (CLEAR_FPSTATUS
328 "%0,p0 = sfrecipa(%2, %2)\n\t"
329 "%1 = usr\n\t"
330 : "=r"(result), "=r"(usr) : "r"(SF_NaN)
331 : "r2", "p0", "usr");
332 check32(result, SF_HEX_NAN);
333 check_fpstatus(usr, 0);
334
335 /*
336 * Check that sfrecipa doesn't set status bits when
337 * a NaN with bit 22 zero is passed
338 */
339 asm (CLEAR_FPSTATUS
340 "%0,p0 = sfrecipa(%2, %3)\n\t"
341 "%1 = usr\n\t"
342 : "=r"(result), "=r"(usr) : "r"(SF_NaN_special), "r"(SF_ANY)
343 : "r2", "p0", "usr");
344 check32(result, SF_HEX_NAN);
345 check_fpstatus(usr, FPINVF);
346
347 asm (CLEAR_FPSTATUS
348 "%0,p0 = sfrecipa(%2, %3)\n\t"
349 "%1 = usr\n\t"
350 : "=r"(result), "=r"(usr) : "r"(SF_ANY), "r"(SF_NaN_special)
351 : "r2", "p0", "usr");
352 check32(result, SF_HEX_NAN);
353 check_fpstatus(usr, FPINVF);
354
355 asm (CLEAR_FPSTATUS
356 "%0,p0 = sfrecipa(%2, %2)\n\t"
357 "%1 = usr\n\t"
358 : "=r"(result), "=r"(usr) : "r"(SF_NaN_special)
359 : "r2", "p0", "usr");
360 check32(result, SF_HEX_NAN);
361 check_fpstatus(usr, FPINVF);
362
363 /*
364 * Check that sfrecipa properly sets divid-by-zero
365 */
366 asm (CLEAR_FPSTATUS
367 "%0,p0 = sfrecipa(%2, %3)\n\t"
368 "%1 = usr\n\t"
369 : "=r"(result), "=r"(usr) : "r"(0x885dc960), "r"(0x80000000)
370 : "r2", "p0", "usr");
371 check32(result, 0x3f800000);
372 check_fpstatus(usr, FPDBZF);
373
374 asm (CLEAR_FPSTATUS
375 "%0,p0 = sfrecipa(%2, %3)\n\t"
376 "%1 = usr\n\t"
377 : "=r"(result), "=r"(usr) : "r"(0x7f800000), "r"(SF_ZERO)
378 : "r2", "p0", "usr");
379 check32(result, 0x3f800000);
380 check_fpstatus(usr, 0);
Taylor Simpson77ccf442022-02-09 18:15:49 -0800381
382 /*
383 * Check that sfrecipa properly handles denorm
384 */
385 asm (CLEAR_FPSTATUS
386 "%0,p0 = sfrecipa(%2, %3)\n\t"
387 "%1 = p0\n\t"
388 : "=r"(result), "=r"(pred) : "r"(SF_denorm), "r"(SF_random)
389 : "p0", "usr");
390 check32(result, 0x6a920001);
391 check32(pred, 0x80);
Taylor Simpsond934c162021-04-08 20:07:45 -0500392}
393
Taylor Simpson703c08d2021-02-07 23:46:23 -0600394static void check_canonical_NaN(void)
395{
396 int sf_result;
397 unsigned long long df_result;
398 int usr;
399
400 /* Check that each FP instruction properly returns SF_HEX_NAN/DF_HEX_NAN */
401 asm(CLEAR_FPSTATUS
402 "%0 = sfadd(%2, %3)\n\t"
403 "%1 = usr\n\t"
404 : "=r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
405 : "r2", "usr");
406 check32(sf_result, SF_HEX_NAN);
407 check_fpstatus(usr, 0);
408
409 asm(CLEAR_FPSTATUS
410 "%0 = sfsub(%2, %3)\n\t"
411 "%1 = usr\n\t"
412 : "=r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
413 : "r2", "usr");
414 check32(sf_result, SF_HEX_NAN);
415 check_fpstatus(usr, 0);
416
417 asm(CLEAR_FPSTATUS
418 "%0 = sfmpy(%2, %3)\n\t"
419 "%1 = usr\n\t"
420 : "=r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
421 : "r2", "usr");
422 check32(sf_result, SF_HEX_NAN);
423 check_fpstatus(usr, 0);
424
425 sf_result = SF_ZERO;
426 asm(CLEAR_FPSTATUS
427 "%0 += sfmpy(%2, %3)\n\t"
428 "%1 = usr\n\t"
429 : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
430 : "r2", "usr");
431 check32(sf_result, SF_HEX_NAN);
432 check_fpstatus(usr, 0);
433
434 sf_result = SF_ZERO;
435 asm(CLEAR_FPSTATUS
436 "p0 = !cmp.eq(r0, r0)\n\t"
437 "%0 += sfmpy(%2, %3, p0):scale\n\t"
438 "%1 = usr\n\t"
439 : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
440 : "r2", "usr", "p0");
441 check32(sf_result, SF_HEX_NAN);
442 check_fpstatus(usr, 0);
443
444 sf_result = SF_ZERO;
445 asm(CLEAR_FPSTATUS
446 "%0 -= sfmpy(%2, %3)\n\t"
447 "%1 = usr\n\t"
448 : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
449 : "r2", "usr");
450 check32(sf_result, SF_HEX_NAN);
451 check_fpstatus(usr, 0);
452
453 sf_result = SF_ZERO;
454 asm(CLEAR_FPSTATUS
455 "%0 += sfmpy(%2, %3):lib\n\t"
456 "%1 = usr\n\t"
457 : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
458 : "r2", "usr");
459 check32(sf_result, SF_HEX_NAN);
460 check_fpstatus(usr, 0);
461
462 sf_result = SF_ZERO;
463 asm(CLEAR_FPSTATUS
464 "%0 -= sfmpy(%2, %3):lib\n\t"
465 "%1 = usr\n\t"
466 : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
467 : "r2", "usr");
468 check32(sf_result, SF_HEX_NAN);
469 check_fpstatus(usr, 0);
470
471 asm(CLEAR_FPSTATUS
472 "%0 = convert_df2sf(%2)\n\t"
473 "%1 = usr\n\t"
Taylor Simpsond76dd812022-02-15 20:39:39 -0800474 : "=r"(sf_result), "=r"(usr) : "r"(DF_QNaN)
Taylor Simpson703c08d2021-02-07 23:46:23 -0600475 : "r2", "usr");
476 check32(sf_result, SF_HEX_NAN);
477 check_fpstatus(usr, 0);
478
479 asm(CLEAR_FPSTATUS
480 "%0 = dfadd(%2, %3)\n\t"
481 "%1 = usr\n\t"
Taylor Simpsond76dd812022-02-15 20:39:39 -0800482 : "=r"(df_result), "=r"(usr) : "r"(DF_QNaN), "r"(DF_ANY)
Taylor Simpson703c08d2021-02-07 23:46:23 -0600483 : "r2", "usr");
484 check64(df_result, DF_HEX_NAN);
485 check_fpstatus(usr, 0);
486
487 asm(CLEAR_FPSTATUS
488 "%0 = dfsub(%2, %3)\n\t"
489 "%1 = usr\n\t"
Taylor Simpsond76dd812022-02-15 20:39:39 -0800490 : "=r"(df_result), "=r"(usr) : "r"(DF_QNaN), "r"(DF_ANY)
Taylor Simpson703c08d2021-02-07 23:46:23 -0600491 : "r2", "usr");
492 check64(df_result, DF_HEX_NAN);
493 check_fpstatus(usr, 0);
494
495 asm(CLEAR_FPSTATUS
496 "%0 = convert_sf2df(%2)\n\t"
497 "%1 = usr\n\t"
498 : "=r"(df_result), "=r"(usr) : "r"(SF_NaN)
499 : "r2", "usr");
500 check64(df_result, DF_HEX_NAN);
501 check_fpstatus(usr, 0);
502}
503
Taylor Simpsondd8705b2021-04-08 20:07:46 -0500504static void check_invsqrta(void)
505{
506 int result;
507 int predval;
508
509 asm volatile("%0,p0 = sfinvsqrta(%2)\n\t"
510 "%1 = p0\n\t"
511 : "+r"(result), "=r"(predval)
512 : "r"(0x7f800000)
513 : "p0");
514 check32(result, 0xff800000);
515 check32(predval, 0x0);
516}
517
Taylor Simpson77ccf442022-02-09 18:15:49 -0800518static void check_sffixupn(void)
519{
520 int result;
521
522 /* Check that sffixupn properly deals with denorm */
523 asm volatile("%0 = sffixupn(%1, %2)\n\t"
524 : "=r"(result)
525 : "r"(SF_random), "r"(SF_denorm));
526 check32(result, 0x246001d6);
527}
528
529static void check_sffixupd(void)
530{
531 int result;
532
533 /* Check that sffixupd properly deals with denorm */
534 asm volatile("%0 = sffixupd(%1, %2)\n\t"
535 : "=r"(result)
536 : "r"(SF_denorm), "r"(SF_random));
537 check32(result, 0x146001d6);
538}
539
Taylor Simpson1a442c02023-03-06 18:58:25 -0800540static void check_sffms(void)
541{
542 int result;
543
544 /* Check that sffms properly deals with -0 */
545 result = SF_neg_zero;
546 asm ("%0 -= sfmpy(%1 , %2)\n\t"
547 : "+r"(result)
548 : "r"(SF_ZERO), "r"(SF_ZERO)
549 : "r12", "r8");
550 check32(result, SF_neg_zero);
551
552 result = SF_ZERO;
553 asm ("%0 -= sfmpy(%1 , %2)\n\t"
554 : "+r"(result)
555 : "r"(SF_neg_zero), "r"(SF_ZERO)
556 : "r12", "r8");
557 check32(result, SF_ZERO);
558
559 result = SF_ZERO;
560 asm ("%0 -= sfmpy(%1 , %2)\n\t"
561 : "+r"(result)
562 : "r"(SF_ZERO), "r"(SF_neg_zero)
563 : "r12", "r8");
564 check32(result, SF_ZERO);
565}
566
Taylor Simpsonb3f37ab2021-04-08 20:07:40 -0500567static void check_float2int_convs()
568{
569 int res32;
570 long long res64;
571 int usr;
572
573 /*
574 * Check that the various forms of float-to-unsigned
575 * check sign before rounding
576 */
577 asm(CLEAR_FPSTATUS
578 "%0 = convert_sf2uw(%2)\n\t"
579 "%1 = usr\n\t"
580 : "=r"(res32), "=r"(usr) : "r"(SF_small_neg)
581 : "r2", "usr");
582 check32(res32, 0);
583 check_fpstatus(usr, FPINVF);
584
585 asm(CLEAR_FPSTATUS
586 "%0 = convert_sf2uw(%2):chop\n\t"
587 "%1 = usr\n\t"
588 : "=r"(res32), "=r"(usr) : "r"(SF_small_neg)
589 : "r2", "usr");
590 check32(res32, 0);
591 check_fpstatus(usr, FPINVF);
592
593 asm(CLEAR_FPSTATUS
594 "%0 = convert_sf2ud(%2)\n\t"
595 "%1 = usr\n\t"
596 : "=r"(res64), "=r"(usr) : "r"(SF_small_neg)
597 : "r2", "usr");
598 check64(res64, 0);
599 check_fpstatus(usr, FPINVF);
600
601 asm(CLEAR_FPSTATUS
602 "%0 = convert_sf2ud(%2):chop\n\t"
603 "%1 = usr\n\t"
604 : "=r"(res64), "=r"(usr) : "r"(SF_small_neg)
605 : "r2", "usr");
606 check64(res64, 0);
607 check_fpstatus(usr, FPINVF);
608
609 asm(CLEAR_FPSTATUS
610 "%0 = convert_df2uw(%2)\n\t"
611 "%1 = usr\n\t"
612 : "=r"(res32), "=r"(usr) : "r"(DF_small_neg)
613 : "r2", "usr");
614 check32(res32, 0);
615 check_fpstatus(usr, FPINVF);
616
617 asm(CLEAR_FPSTATUS
618 "%0 = convert_df2uw(%2):chop\n\t"
619 "%1 = usr\n\t"
620 : "=r"(res32), "=r"(usr) : "r"(DF_small_neg)
621 : "r2", "usr");
622 check32(res32, 0);
623 check_fpstatus(usr, FPINVF);
624
625 asm(CLEAR_FPSTATUS
626 "%0 = convert_df2ud(%2)\n\t"
627 "%1 = usr\n\t"
628 : "=r"(res64), "=r"(usr) : "r"(DF_small_neg)
629 : "r2", "usr");
630 check64(res64, 0);
631 check_fpstatus(usr, FPINVF);
632
633 asm(CLEAR_FPSTATUS
634 "%0 = convert_df2ud(%2):chop\n\t"
635 "%1 = usr\n\t"
636 : "=r"(res64), "=r"(usr) : "r"(DF_small_neg)
637 : "r2", "usr");
638 check64(res64, 0);
639 check_fpstatus(usr, FPINVF);
640
641 /*
642 * Check that the various forms of float-to-signed return -1 for NaN
643 */
644 asm(CLEAR_FPSTATUS
645 "%0 = convert_sf2w(%2)\n\t"
646 "%1 = usr\n\t"
647 : "=r"(res32), "=r"(usr) : "r"(SF_NaN)
648 : "r2", "usr");
649 check32(res32, -1);
650 check_fpstatus(usr, FPINVF);
651
652 asm(CLEAR_FPSTATUS
653 "%0 = convert_sf2w(%2):chop\n\t"
654 "%1 = usr\n\t"
655 : "=r"(res32), "=r"(usr) : "r"(SF_NaN)
656 : "r2", "usr");
657 check32(res32, -1);
658 check_fpstatus(usr, FPINVF);
659
660 asm(CLEAR_FPSTATUS
661 "%0 = convert_sf2d(%2)\n\t"
662 "%1 = usr\n\t"
663 : "=r"(res64), "=r"(usr) : "r"(SF_NaN)
664 : "r2", "usr");
665 check64(res64, -1);
666 check_fpstatus(usr, FPINVF);
667
668 asm(CLEAR_FPSTATUS
669 "%0 = convert_sf2d(%2):chop\n\t"
670 "%1 = usr\n\t"
671 : "=r"(res64), "=r"(usr) : "r"(SF_NaN)
672 : "r2", "usr");
673 check64(res64, -1);
674 check_fpstatus(usr, FPINVF);
675
676 asm(CLEAR_FPSTATUS
677 "%0 = convert_df2w(%2)\n\t"
678 "%1 = usr\n\t"
Taylor Simpsond76dd812022-02-15 20:39:39 -0800679 : "=r"(res32), "=r"(usr) : "r"(DF_QNaN)
Taylor Simpsonb3f37ab2021-04-08 20:07:40 -0500680 : "r2", "usr");
681 check32(res32, -1);
682 check_fpstatus(usr, FPINVF);
683
684 asm(CLEAR_FPSTATUS
685 "%0 = convert_df2w(%2):chop\n\t"
686 "%1 = usr\n\t"
Taylor Simpsond76dd812022-02-15 20:39:39 -0800687 : "=r"(res32), "=r"(usr) : "r"(DF_QNaN)
Taylor Simpsonb3f37ab2021-04-08 20:07:40 -0500688 : "r2", "usr");
689 check32(res32, -1);
690 check_fpstatus(usr, FPINVF);
691
692 asm(CLEAR_FPSTATUS
693 "%0 = convert_df2d(%2)\n\t"
694 "%1 = usr\n\t"
Taylor Simpsond76dd812022-02-15 20:39:39 -0800695 : "=r"(res64), "=r"(usr) : "r"(DF_QNaN)
Taylor Simpsonb3f37ab2021-04-08 20:07:40 -0500696 : "r2", "usr");
697 check64(res64, -1);
698 check_fpstatus(usr, FPINVF);
699
700 asm(CLEAR_FPSTATUS
701 "%0 = convert_df2d(%2):chop\n\t"
702 "%1 = usr\n\t"
Taylor Simpsond76dd812022-02-15 20:39:39 -0800703 : "=r"(res64), "=r"(usr) : "r"(DF_QNaN)
Taylor Simpsonb3f37ab2021-04-08 20:07:40 -0500704 : "r2", "usr");
705 check64(res64, -1);
706 check_fpstatus(usr, FPINVF);
707}
708
Taylor Simpson703c08d2021-02-07 23:46:23 -0600709int main()
710{
711 check_compare_exception();
712 check_sfminmax();
713 check_dfminmax();
Taylor Simpson77ccf442022-02-09 18:15:49 -0800714 check_sfrecipa();
Taylor Simpson703c08d2021-02-07 23:46:23 -0600715 check_canonical_NaN();
Taylor Simpsondd8705b2021-04-08 20:07:46 -0500716 check_invsqrta();
Taylor Simpson77ccf442022-02-09 18:15:49 -0800717 check_sffixupn();
718 check_sffixupd();
Taylor Simpson1a442c02023-03-06 18:58:25 -0800719 check_sffms();
Taylor Simpsonb3f37ab2021-04-08 20:07:40 -0500720 check_float2int_convs();
Taylor Simpson703c08d2021-02-07 23:46:23 -0600721
722 puts(err ? "FAIL" : "PASS");
723 return err ? 1 : 0;
724}