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