1 /* 2 * Copyright(c) 2020-2023 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 const int SF_denorm = 0x00000001; 42 const int SF_random = 0x346001d6; 43 const int SF_neg_zero = 0x80000000; 44 45 const long long DF_QNaN = 0x7ff8000000000000ULL; 46 const long long DF_SNaN = 0x7ff7000000000000ULL; 47 const long long DF_ANY = 0x3f80000000000000ULL; 48 const long long DF_HEX_NAN = 0xffffffffffffffffULL; 49 const long long DF_small_neg = 0xbd731f7500000000ULL; 50 51 int 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 62 static 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 72 static 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 81 static 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 } 88 static 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 96 static 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" 133 : "=r"(cmp), "=r"(usr) : "r"(DF_QNaN), "r"(DF_ANY) 134 : "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" 142 : "=r"(cmp), "=r"(usr) : "r"(DF_QNaN), "r"(DF_ANY) 143 : "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" 151 : "=r"(cmp), "=r"(usr) : "r"(DF_QNaN), "r"(DF_ANY) 152 : "r2", "p0", "usr"); 153 check32(cmp, 0); 154 check_fpstatus(usr, 0); 155 } 156 157 static 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 207 static void check_dfminmax(void) 208 { 209 unsigned long long minmax; 210 int usr; 211 212 /* 213 * Execute dfmin/dfmax instructions with one operand as SNaN 214 * 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" 221 : "=r"(minmax), "=r"(usr) : "r"(DF_SNaN), "r"(DF_ANY) 222 : "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" 229 : "=r"(minmax), "=r"(usr) : "r"(DF_SNaN), "r"(DF_ANY) 230 : "r2", "usr"); 231 check64(minmax, DF_ANY); 232 check_fpstatus(usr, FPINVF); 233 234 /* 235 * 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 258 * 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" 265 : "=r"(minmax), "=r"(usr) : "r"(DF_SNaN), "r"(DF_SNaN) 266 : "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" 273 : "=r"(minmax), "=r"(usr) : "r"(DF_SNaN), "r"(DF_SNaN) 274 : "r2", "usr"); 275 check64(minmax, DF_HEX_NAN); 276 check_fpstatus(usr, FPINVF); 277 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); 299 } 300 301 static void check_sfrecipa(void) 302 { 303 int result; 304 int usr; 305 int pred; 306 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); 381 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); 392 } 393 394 static 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" 474 : "=r"(sf_result), "=r"(usr) : "r"(DF_QNaN) 475 : "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" 482 : "=r"(df_result), "=r"(usr) : "r"(DF_QNaN), "r"(DF_ANY) 483 : "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" 490 : "=r"(df_result), "=r"(usr) : "r"(DF_QNaN), "r"(DF_ANY) 491 : "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 504 static 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 518 static 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 529 static 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 540 static 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 567 static 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" 679 : "=r"(res32), "=r"(usr) : "r"(DF_QNaN) 680 : "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" 687 : "=r"(res32), "=r"(usr) : "r"(DF_QNaN) 688 : "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" 695 : "=r"(res64), "=r"(usr) : "r"(DF_QNaN) 696 : "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" 703 : "=r"(res64), "=r"(usr) : "r"(DF_QNaN) 704 : "r2", "usr"); 705 check64(res64, -1); 706 check_fpstatus(usr, FPINVF); 707 } 708 709 int main() 710 { 711 check_compare_exception(); 712 check_sfminmax(); 713 check_dfminmax(); 714 check_sfrecipa(); 715 check_canonical_NaN(); 716 check_invsqrta(); 717 check_sffixupn(); 718 check_sffixupd(); 719 check_sffms(); 720 check_float2int_convs(); 721 722 puts(err ? "FAIL" : "PASS"); 723 return err ? 1 : 0; 724 } 725