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