cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

fpstuff.c (17231B)


      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}