xref: /openbmc/qemu/tests/tcg/hexagon/fpstuff.c (revision f101c9fe)
1 /*
2  *  Copyright(c) 2020-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
3  *
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 
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;
34 
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;
40 const int SF_small_neg =                  0xab98fba8;
41 
42 const long long DF_NaN =                  0x7ff8000000000000ULL;
43 const long long DF_ANY =                  0x3f80000000000000ULL;
44 const long long DF_HEX_NAN =              0xffffffffffffffffULL;
45 const long long DF_small_neg =            0xbd731f7500000000ULL;
46 
47 int err;
48 
49 #define CLEAR_FPSTATUS \
50     "r2 = usr\n\t" \
51     "r2 = clrbit(r2, #1)\n\t" \
52     "r2 = clrbit(r2, #2)\n\t" \
53     "r2 = clrbit(r2, #3)\n\t" \
54     "r2 = clrbit(r2, #4)\n\t" \
55     "r2 = clrbit(r2, #5)\n\t" \
56     "usr = r2\n\t"
57 
58 static void check_fpstatus_bit(int usr, int expect, int flag, const char *n)
59 {
60     int bit = 1 << flag;
61     if ((usr & bit) != (expect & bit)) {
62         printf("ERROR %s: usr = %d, expect = %d\n", n,
63                (usr >> flag) & 1, (expect >> flag) & 1);
64         err++;
65     }
66 }
67 
68 static void check_fpstatus(int usr, int expect)
69 {
70     check_fpstatus_bit(usr, expect, FPINVF_BIT, "Invalid");
71     check_fpstatus_bit(usr, expect, FPDBZF_BIT, "Div by zero");
72     check_fpstatus_bit(usr, expect, FPOVFF_BIT, "Overflow");
73     check_fpstatus_bit(usr, expect, FPUNFF_BIT, "Underflow");
74     check_fpstatus_bit(usr, expect, FPINPF_BIT, "Inexact");
75 }
76 
77 static void check32(int val, int expect)
78 {
79     if (val != expect) {
80         printf("ERROR: 0x%x != 0x%x\n", val, expect);
81         err++;
82     }
83 }
84 static void check64(unsigned long long val, unsigned long long expect)
85 {
86     if (val != expect) {
87         printf("ERROR: 0x%llx != 0x%llx\n", val, expect);
88         err++;
89     }
90 }
91 
92 static void check_compare_exception(void)
93 {
94     int cmp;
95     int usr;
96 
97     /* Check that FP compares are quiet (don't raise any execptions) */
98     asm (CLEAR_FPSTATUS
99          "p0 = sfcmp.eq(%2, %3)\n\t"
100          "%0 = p0\n\t"
101          "%1 = usr\n\t"
102          : "=r"(cmp), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
103          : "r2", "p0", "usr");
104     check32(cmp, 0);
105     check_fpstatus(usr, 0);
106 
107     asm (CLEAR_FPSTATUS
108          "p0 = sfcmp.gt(%2, %3)\n\t"
109          "%0 = p0\n\t"
110          "%1 = usr\n\t"
111          : "=r"(cmp), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
112          : "r2", "p0", "usr");
113     check32(cmp, 0);
114     check_fpstatus(usr, 0);
115 
116     asm (CLEAR_FPSTATUS
117          "p0 = sfcmp.ge(%2, %3)\n\t"
118          "%0 = p0\n\t"
119          "%1 = usr\n\t"
120          : "=r"(cmp), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
121          : "r2", "p0", "usr");
122     check32(cmp, 0);
123     check_fpstatus(usr, 0);
124 
125     asm (CLEAR_FPSTATUS
126          "p0 = dfcmp.eq(%2, %3)\n\t"
127          "%0 = p0\n\t"
128          "%1 = usr\n\t"
129          : "=r"(cmp), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
130          : "r2", "p0", "usr");
131     check32(cmp, 0);
132     check_fpstatus(usr, 0);
133 
134     asm (CLEAR_FPSTATUS
135          "p0 = dfcmp.gt(%2, %3)\n\t"
136          "%0 = p0\n\t"
137          "%1 = usr\n\t"
138          : "=r"(cmp), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
139          : "r2", "p0", "usr");
140     check32(cmp, 0);
141     check_fpstatus(usr, 0);
142 
143     asm (CLEAR_FPSTATUS
144          "p0 = dfcmp.ge(%2, %3)\n\t"
145          "%0 = p0\n\t"
146          "%1 = usr\n\t"
147          : "=r"(cmp), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
148          : "r2", "p0", "usr");
149     check32(cmp, 0);
150     check_fpstatus(usr, 0);
151 }
152 
153 static void check_sfminmax(void)
154 {
155     int minmax;
156     int usr;
157 
158     /*
159      * Execute sfmin/sfmax instructions with one operand as NaN
160      * Check that
161      *     Result is the other operand
162      *     Invalid bit in USR is not set
163      */
164      asm (CLEAR_FPSTATUS
165          "%0 = sfmin(%2, %3)\n\t"
166          "%1 = usr\n\t"
167          : "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
168          : "r2", "usr");
169     check64(minmax, SF_ANY);
170     check_fpstatus(usr, 0);
171 
172     asm (CLEAR_FPSTATUS
173          "%0 = sfmax(%2, %3)\n\t"
174          "%1 = usr\n\t"
175          : "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
176          : "r2", "usr");
177     check64(minmax, SF_ANY);
178     check_fpstatus(usr, 0);
179 
180     /*
181      * Execute sfmin/sfmax instructions with both operands NaN
182      * Check that
183      *     Result is SF_HEX_NAN
184      *     Invalid bit in USR is set
185      */
186     asm (CLEAR_FPSTATUS
187          "%0 = sfmin(%2, %3)\n\t"
188          "%1 = usr\n\t"
189          : "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_NaN)
190          : "r2", "usr");
191     check64(minmax, SF_HEX_NAN);
192     check_fpstatus(usr, 0);
193 
194     asm (CLEAR_FPSTATUS
195          "%0 = sfmax(%2, %3)\n\t"
196          "%1 = usr\n\t"
197          : "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_NaN)
198          : "r2", "usr");
199     check64(minmax, SF_HEX_NAN);
200     check_fpstatus(usr, 0);
201 }
202 
203 static void check_dfminmax(void)
204 {
205     unsigned long long minmax;
206     int usr;
207 
208     /*
209      * Execute dfmin/dfmax instructions with one operand as NaN
210      * Check that
211      *     Result is the other operand
212      *     Invalid bit in USR is set
213      */
214      asm (CLEAR_FPSTATUS
215          "%0 = dfmin(%2, %3)\n\t"
216          "%1 = usr\n\t"
217          : "=r"(minmax), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
218          : "r2", "usr");
219     check64(minmax, DF_ANY);
220     check_fpstatus(usr, FPINVF);
221 
222     asm (CLEAR_FPSTATUS
223          "%0 = dfmax(%2, %3)\n\t"
224          "%1 = usr\n\t"
225          : "=r"(minmax), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
226          : "r2", "usr");
227     check64(minmax, DF_ANY);
228     check_fpstatus(usr, FPINVF);
229 
230     /*
231      * Execute dfmin/dfmax instructions with both operands NaN
232      * Check that
233      *     Result is DF_HEX_NAN
234      *     Invalid bit in USR is set
235      */
236     asm (CLEAR_FPSTATUS
237          "%0 = dfmin(%2, %3)\n\t"
238          "%1 = usr\n\t"
239          : "=r"(minmax), "=r"(usr) : "r"(DF_NaN), "r"(DF_NaN)
240          : "r2", "usr");
241     check64(minmax, DF_HEX_NAN);
242     check_fpstatus(usr, FPINVF);
243 
244     asm (CLEAR_FPSTATUS
245          "%0 = dfmax(%2, %3)\n\t"
246          "%1 = usr\n\t"
247          : "=r"(minmax), "=r"(usr) : "r"(DF_NaN), "r"(DF_NaN)
248          : "r2", "usr");
249     check64(minmax, DF_HEX_NAN);
250     check_fpstatus(usr, FPINVF);
251 }
252 
253 static void check_recip_exception(void)
254 {
255     int result;
256     int usr;
257 
258     /*
259      * Check that sfrecipa doesn't set status bits when
260      * a NaN with bit 22 non-zero is passed
261      */
262     asm (CLEAR_FPSTATUS
263          "%0,p0 = sfrecipa(%2, %3)\n\t"
264          "%1 = usr\n\t"
265          : "=r"(result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
266          : "r2", "p0", "usr");
267     check32(result, SF_HEX_NAN);
268     check_fpstatus(usr, 0);
269 
270     asm (CLEAR_FPSTATUS
271          "%0,p0 = sfrecipa(%2, %3)\n\t"
272          "%1 = usr\n\t"
273          : "=r"(result), "=r"(usr) : "r"(SF_ANY), "r"(SF_NaN)
274          : "r2", "p0", "usr");
275     check32(result, SF_HEX_NAN);
276     check_fpstatus(usr, 0);
277 
278     asm (CLEAR_FPSTATUS
279          "%0,p0 = sfrecipa(%2, %2)\n\t"
280          "%1 = usr\n\t"
281          : "=r"(result), "=r"(usr) : "r"(SF_NaN)
282          : "r2", "p0", "usr");
283     check32(result, SF_HEX_NAN);
284     check_fpstatus(usr, 0);
285 
286     /*
287      * Check that sfrecipa doesn't set status bits when
288      * a NaN with bit 22 zero is passed
289      */
290     asm (CLEAR_FPSTATUS
291          "%0,p0 = sfrecipa(%2, %3)\n\t"
292          "%1 = usr\n\t"
293          : "=r"(result), "=r"(usr) : "r"(SF_NaN_special), "r"(SF_ANY)
294          : "r2", "p0", "usr");
295     check32(result, SF_HEX_NAN);
296     check_fpstatus(usr, FPINVF);
297 
298     asm (CLEAR_FPSTATUS
299          "%0,p0 = sfrecipa(%2, %3)\n\t"
300          "%1 = usr\n\t"
301          : "=r"(result), "=r"(usr) : "r"(SF_ANY), "r"(SF_NaN_special)
302          : "r2", "p0", "usr");
303     check32(result, SF_HEX_NAN);
304     check_fpstatus(usr, FPINVF);
305 
306     asm (CLEAR_FPSTATUS
307          "%0,p0 = sfrecipa(%2, %2)\n\t"
308          "%1 = usr\n\t"
309          : "=r"(result), "=r"(usr) : "r"(SF_NaN_special)
310          : "r2", "p0", "usr");
311     check32(result, SF_HEX_NAN);
312     check_fpstatus(usr, FPINVF);
313 
314     /*
315      * Check that sfrecipa properly sets divid-by-zero
316      */
317         asm (CLEAR_FPSTATUS
318          "%0,p0 = sfrecipa(%2, %3)\n\t"
319          "%1 = usr\n\t"
320          : "=r"(result), "=r"(usr) : "r"(0x885dc960), "r"(0x80000000)
321          : "r2", "p0", "usr");
322     check32(result, 0x3f800000);
323     check_fpstatus(usr, FPDBZF);
324 
325     asm (CLEAR_FPSTATUS
326          "%0,p0 = sfrecipa(%2, %3)\n\t"
327          "%1 = usr\n\t"
328          : "=r"(result), "=r"(usr) : "r"(0x7f800000), "r"(SF_ZERO)
329          : "r2", "p0", "usr");
330     check32(result, 0x3f800000);
331     check_fpstatus(usr, 0);
332 }
333 
334 static void check_canonical_NaN(void)
335 {
336     int sf_result;
337     unsigned long long df_result;
338     int usr;
339 
340     /* Check that each FP instruction properly returns SF_HEX_NAN/DF_HEX_NAN */
341     asm(CLEAR_FPSTATUS
342         "%0 = sfadd(%2, %3)\n\t"
343         "%1 = usr\n\t"
344         : "=r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
345         : "r2", "usr");
346     check32(sf_result, SF_HEX_NAN);
347     check_fpstatus(usr, 0);
348 
349     asm(CLEAR_FPSTATUS
350         "%0 = sfsub(%2, %3)\n\t"
351         "%1 = usr\n\t"
352         : "=r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
353         : "r2", "usr");
354     check32(sf_result, SF_HEX_NAN);
355     check_fpstatus(usr, 0);
356 
357     asm(CLEAR_FPSTATUS
358         "%0 = sfmpy(%2, %3)\n\t"
359         "%1 = usr\n\t"
360         : "=r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
361         : "r2", "usr");
362     check32(sf_result, SF_HEX_NAN);
363     check_fpstatus(usr, 0);
364 
365     sf_result = SF_ZERO;
366     asm(CLEAR_FPSTATUS
367         "%0 += sfmpy(%2, %3)\n\t"
368         "%1 = usr\n\t"
369         : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
370         : "r2", "usr");
371     check32(sf_result, SF_HEX_NAN);
372     check_fpstatus(usr, 0);
373 
374     sf_result = SF_ZERO;
375     asm(CLEAR_FPSTATUS
376         "p0 = !cmp.eq(r0, r0)\n\t"
377         "%0 += sfmpy(%2, %3, p0):scale\n\t"
378         "%1 = usr\n\t"
379         : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
380         : "r2", "usr", "p0");
381     check32(sf_result, SF_HEX_NAN);
382     check_fpstatus(usr, 0);
383 
384     sf_result = SF_ZERO;
385     asm(CLEAR_FPSTATUS
386         "%0 -= sfmpy(%2, %3)\n\t"
387         "%1 = usr\n\t"
388         : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
389         : "r2", "usr");
390     check32(sf_result, SF_HEX_NAN);
391     check_fpstatus(usr, 0);
392 
393     sf_result = SF_ZERO;
394     asm(CLEAR_FPSTATUS
395         "%0 += sfmpy(%2, %3):lib\n\t"
396         "%1 = usr\n\t"
397         : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
398         : "r2", "usr");
399     check32(sf_result, SF_HEX_NAN);
400     check_fpstatus(usr, 0);
401 
402     sf_result = SF_ZERO;
403     asm(CLEAR_FPSTATUS
404         "%0 -= sfmpy(%2, %3):lib\n\t"
405         "%1 = usr\n\t"
406         : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
407         : "r2", "usr");
408     check32(sf_result, SF_HEX_NAN);
409     check_fpstatus(usr, 0);
410 
411     asm(CLEAR_FPSTATUS
412         "%0 = convert_df2sf(%2)\n\t"
413         "%1 = usr\n\t"
414         : "=r"(sf_result), "=r"(usr) : "r"(DF_NaN)
415         : "r2", "usr");
416     check32(sf_result, SF_HEX_NAN);
417     check_fpstatus(usr, 0);
418 
419     asm(CLEAR_FPSTATUS
420         "%0 = dfadd(%2, %3)\n\t"
421         "%1 = usr\n\t"
422         : "=r"(df_result), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
423         : "r2", "usr");
424     check64(df_result, DF_HEX_NAN);
425     check_fpstatus(usr, 0);
426 
427     asm(CLEAR_FPSTATUS
428         "%0 = dfsub(%2, %3)\n\t"
429         "%1 = usr\n\t"
430         : "=r"(df_result), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
431         : "r2", "usr");
432     check64(df_result, DF_HEX_NAN);
433     check_fpstatus(usr, 0);
434 
435     asm(CLEAR_FPSTATUS
436         "%0 = convert_sf2df(%2)\n\t"
437         "%1 = usr\n\t"
438         : "=r"(df_result), "=r"(usr) : "r"(SF_NaN)
439         : "r2", "usr");
440     check64(df_result, DF_HEX_NAN);
441     check_fpstatus(usr, 0);
442 }
443 
444 static void check_invsqrta(void)
445 {
446     int result;
447     int predval;
448 
449     asm volatile("%0,p0 = sfinvsqrta(%2)\n\t"
450                  "%1 = p0\n\t"
451                  : "+r"(result), "=r"(predval)
452                  : "r"(0x7f800000)
453                  : "p0");
454     check32(result, 0xff800000);
455     check32(predval, 0x0);
456 }
457 
458 static void check_float2int_convs()
459 {
460     int res32;
461     long long res64;
462     int usr;
463 
464     /*
465      * Check that the various forms of float-to-unsigned
466      *  check sign before rounding
467      */
468         asm(CLEAR_FPSTATUS
469         "%0 = convert_sf2uw(%2)\n\t"
470         "%1 = usr\n\t"
471         : "=r"(res32), "=r"(usr) : "r"(SF_small_neg)
472         : "r2", "usr");
473     check32(res32, 0);
474     check_fpstatus(usr, FPINVF);
475 
476     asm(CLEAR_FPSTATUS
477         "%0 = convert_sf2uw(%2):chop\n\t"
478         "%1 = usr\n\t"
479         : "=r"(res32), "=r"(usr) : "r"(SF_small_neg)
480         : "r2", "usr");
481     check32(res32, 0);
482     check_fpstatus(usr, FPINVF);
483 
484     asm(CLEAR_FPSTATUS
485         "%0 = convert_sf2ud(%2)\n\t"
486         "%1 = usr\n\t"
487         : "=r"(res64), "=r"(usr) : "r"(SF_small_neg)
488         : "r2", "usr");
489     check64(res64, 0);
490     check_fpstatus(usr, FPINVF);
491 
492     asm(CLEAR_FPSTATUS
493         "%0 = convert_sf2ud(%2):chop\n\t"
494         "%1 = usr\n\t"
495         : "=r"(res64), "=r"(usr) : "r"(SF_small_neg)
496         : "r2", "usr");
497     check64(res64, 0);
498     check_fpstatus(usr, FPINVF);
499 
500     asm(CLEAR_FPSTATUS
501         "%0 = convert_df2uw(%2)\n\t"
502         "%1 = usr\n\t"
503         : "=r"(res32), "=r"(usr) : "r"(DF_small_neg)
504         : "r2", "usr");
505     check32(res32, 0);
506     check_fpstatus(usr, FPINVF);
507 
508     asm(CLEAR_FPSTATUS
509         "%0 = convert_df2uw(%2):chop\n\t"
510         "%1 = usr\n\t"
511         : "=r"(res32), "=r"(usr) : "r"(DF_small_neg)
512         : "r2", "usr");
513     check32(res32, 0);
514     check_fpstatus(usr, FPINVF);
515 
516     asm(CLEAR_FPSTATUS
517         "%0 = convert_df2ud(%2)\n\t"
518         "%1 = usr\n\t"
519         : "=r"(res64), "=r"(usr) : "r"(DF_small_neg)
520         : "r2", "usr");
521     check64(res64, 0);
522     check_fpstatus(usr, FPINVF);
523 
524     asm(CLEAR_FPSTATUS
525         "%0 = convert_df2ud(%2):chop\n\t"
526         "%1 = usr\n\t"
527         : "=r"(res64), "=r"(usr) : "r"(DF_small_neg)
528         : "r2", "usr");
529     check64(res64, 0);
530     check_fpstatus(usr, FPINVF);
531 
532     /*
533      * Check that the various forms of float-to-signed return -1 for NaN
534      */
535     asm(CLEAR_FPSTATUS
536         "%0 = convert_sf2w(%2)\n\t"
537         "%1 = usr\n\t"
538         : "=r"(res32), "=r"(usr) : "r"(SF_NaN)
539         : "r2", "usr");
540     check32(res32, -1);
541     check_fpstatus(usr, FPINVF);
542 
543     asm(CLEAR_FPSTATUS
544         "%0 = convert_sf2w(%2):chop\n\t"
545         "%1 = usr\n\t"
546         : "=r"(res32), "=r"(usr) : "r"(SF_NaN)
547         : "r2", "usr");
548     check32(res32, -1);
549     check_fpstatus(usr, FPINVF);
550 
551     asm(CLEAR_FPSTATUS
552         "%0 = convert_sf2d(%2)\n\t"
553         "%1 = usr\n\t"
554         : "=r"(res64), "=r"(usr) : "r"(SF_NaN)
555         : "r2", "usr");
556     check64(res64, -1);
557     check_fpstatus(usr, FPINVF);
558 
559     asm(CLEAR_FPSTATUS
560         "%0 = convert_sf2d(%2):chop\n\t"
561         "%1 = usr\n\t"
562         : "=r"(res64), "=r"(usr) : "r"(SF_NaN)
563         : "r2", "usr");
564     check64(res64, -1);
565     check_fpstatus(usr, FPINVF);
566 
567     asm(CLEAR_FPSTATUS
568         "%0 = convert_df2w(%2)\n\t"
569         "%1 = usr\n\t"
570         : "=r"(res32), "=r"(usr) : "r"(DF_NaN)
571         : "r2", "usr");
572     check32(res32, -1);
573     check_fpstatus(usr, FPINVF);
574 
575     asm(CLEAR_FPSTATUS
576         "%0 = convert_df2w(%2):chop\n\t"
577         "%1 = usr\n\t"
578         : "=r"(res32), "=r"(usr) : "r"(DF_NaN)
579         : "r2", "usr");
580     check32(res32, -1);
581     check_fpstatus(usr, FPINVF);
582 
583     asm(CLEAR_FPSTATUS
584         "%0 = convert_df2d(%2)\n\t"
585         "%1 = usr\n\t"
586         : "=r"(res64), "=r"(usr) : "r"(DF_NaN)
587         : "r2", "usr");
588     check64(res64, -1);
589     check_fpstatus(usr, FPINVF);
590 
591     asm(CLEAR_FPSTATUS
592         "%0 = convert_df2d(%2):chop\n\t"
593         "%1 = usr\n\t"
594         : "=r"(res64), "=r"(usr) : "r"(DF_NaN)
595         : "r2", "usr");
596     check64(res64, -1);
597     check_fpstatus(usr, FPINVF);
598 }
599 
600 int main()
601 {
602     check_compare_exception();
603     check_sfminmax();
604     check_dfminmax();
605     check_recip_exception();
606     check_canonical_NaN();
607     check_invsqrta();
608     check_float2int_convs();
609 
610     puts(err ? "FAIL" : "PASS");
611     return err ? 1 : 0;
612 }
613