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