qemu/tests/tcg/hexagon/fpstuff.c
<<
>>
Prefs
   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
  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;
  40const int SF_small_neg =                  0xab98fba8;
  41
  42const long long DF_NaN =                  0x7ff8000000000000ULL;
  43const long long DF_ANY =                  0x3f80000000000000ULL;
  44const long long DF_HEX_NAN =              0xffffffffffffffffULL;
  45const long long DF_small_neg =            0xbd731f7500000000ULL;
  46
  47int 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
  58static 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
  68static 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
  77static 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}
  84static 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
  92static 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
 153static 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
 203static 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
 253static 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
 334static 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
 444static 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
 458static 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
 600int 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