1 /* 2 * fp-test.c - test QEMU's softfloat implementation using Berkeley's Testfloat 3 * 4 * Copyright (C) 2018, Emilio G. Cota <cota@braap.org> 5 * 6 * License: GNU GPL, version 2 or later. 7 * See the COPYING file in the top-level directory. 8 * 9 * This file is derived from testfloat/source/testsoftfloat.c. Its copyright 10 * info follows: 11 * 12 * Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the 13 * University of California. All rights reserved. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions are met: 17 * 18 * 1. Redistributions of source code must retain the above copyright notice, 19 * this list of conditions, and the following disclaimer. 20 * 21 * 2. Redistributions in binary form must reproduce the above copyright notice, 22 * this list of conditions, and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 25 * 3. Neither the name of the University nor the names of its contributors may 26 * be used to endorse or promote products derived from this software without 27 * specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY 30 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 31 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE 32 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 33 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 35 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 36 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 */ 40 #ifndef HW_POISON_H 41 #error Must define HW_POISON_H to work around TARGET_* poisoning 42 #endif 43 44 #include "qemu/osdep.h" 45 #include "qemu/cutils.h" 46 #include <math.h> 47 #include "fpu/softfloat.h" 48 #include "platform.h" 49 50 #include "fail.h" 51 #include "slowfloat.h" 52 #include "functions.h" 53 #include "genCases.h" 54 #include "verCases.h" 55 #include "writeCase.h" 56 #include "testLoops.h" 57 58 typedef float16_t (*abz_f16)(float16_t, float16_t); 59 typedef bool (*ab_f16_z_bool)(float16_t, float16_t); 60 typedef float32_t (*abz_f32)(float32_t, float32_t); 61 typedef bool (*ab_f32_z_bool)(float32_t, float32_t); 62 typedef float64_t (*abz_f64)(float64_t, float64_t); 63 typedef bool (*ab_f64_z_bool)(float64_t, float64_t); 64 typedef void (*abz_extF80M)(const extFloat80_t *, const extFloat80_t *, 65 extFloat80_t *); 66 typedef bool (*ab_extF80M_z_bool)(const extFloat80_t *, const extFloat80_t *); 67 typedef void (*abz_f128M)(const float128_t *, const float128_t *, float128_t *); 68 typedef bool (*ab_f128M_z_bool)(const float128_t *, const float128_t *); 69 70 static const char * const round_mode_names[] = { 71 [ROUND_NEAR_EVEN] = "even", 72 [ROUND_MINMAG] = "zero", 73 [ROUND_MIN] = "down", 74 [ROUND_MAX] = "up", 75 [ROUND_NEAR_MAXMAG] = "tieaway", 76 [ROUND_ODD] = "odd", 77 }; 78 static unsigned int *test_ops; 79 static unsigned int n_test_ops; 80 static unsigned int n_max_errors = 20; 81 static unsigned int test_round_mode = ROUND_NEAR_EVEN; 82 static unsigned int *round_modes; 83 static unsigned int n_round_modes; 84 static int test_level = 1; 85 static uint8_t slow_init_flags; 86 static uint8_t qemu_init_flags; 87 88 /* qemu softfloat status */ 89 static float_status qsf; 90 91 static const char commands_string[] = 92 "operations:\n" 93 " <int>_to_<float> <float>_add <float>_eq\n" 94 " <float>_to_<int> <float>_sub <float>_le\n" 95 " <float>_to_<int>_r_minMag <float>_mul <float>_lt\n" 96 " <float>_to_<float> <float>_mulAdd <float>_eq_signaling\n" 97 " <float>_roundToInt <float>_div <float>_le_quiet\n" 98 " <float>_rem <float>_lt_quiet\n" 99 " <float>_sqrt\n" 100 " Where <int>: ui32, ui64, i32, i64\n" 101 " <float>: f16, f32, f64, extF80, f128\n" 102 " If no operation is provided, all the above are tested\n" 103 "options:\n" 104 " -e = max error count per test. Default: 20. Set no limit with 0\n" 105 " -f = initial FP exception flags (vioux). Default: none\n" 106 " -l = thoroughness level (1 (default), 2)\n" 107 " -r = rounding mode (even (default), zero, down, up, tieaway, odd)\n" 108 " Set to 'all' to test all rounding modes, if applicable\n" 109 " -s = stop when a test fails\n" 110 " -q = minimise noise when testing, just show each function being tested"; 111 112 static void usage_complete(int argc, char *argv[]) 113 { 114 fprintf(stderr, "Usage: %s [options] [operation1 ...]\n", argv[0]); 115 fprintf(stderr, "%s\n", commands_string); 116 exit(EXIT_FAILURE); 117 } 118 119 /* keep wrappers separate but do not bother defining headers for all of them */ 120 #include "wrap.c.inc" 121 122 static void not_implemented(void) 123 { 124 fprintf(stderr, "Not implemented.\n"); 125 } 126 127 static bool is_allowed(unsigned op, int rmode) 128 { 129 /* odd has not been implemented for any 80-bit ops */ 130 if (rmode == softfloat_round_odd) { 131 switch (op) { 132 case EXTF80_TO_UI32: 133 case EXTF80_TO_UI64: 134 case EXTF80_TO_I32: 135 case EXTF80_TO_I64: 136 case EXTF80_TO_UI32_R_MINMAG: 137 case EXTF80_TO_UI64_R_MINMAG: 138 case EXTF80_TO_I32_R_MINMAG: 139 case EXTF80_TO_I64_R_MINMAG: 140 case EXTF80_TO_F16: 141 case EXTF80_TO_F32: 142 case EXTF80_TO_F64: 143 case EXTF80_TO_F128: 144 case EXTF80_ROUNDTOINT: 145 case EXTF80_ADD: 146 case EXTF80_SUB: 147 case EXTF80_MUL: 148 case EXTF80_DIV: 149 case EXTF80_REM: 150 case EXTF80_SQRT: 151 case EXTF80_EQ: 152 case EXTF80_LE: 153 case EXTF80_LT: 154 case EXTF80_EQ_SIGNALING: 155 case EXTF80_LE_QUIET: 156 case EXTF80_LT_QUIET: 157 case UI32_TO_EXTF80: 158 case UI64_TO_EXTF80: 159 case I32_TO_EXTF80: 160 case I64_TO_EXTF80: 161 case F16_TO_EXTF80: 162 case F32_TO_EXTF80: 163 case F64_TO_EXTF80: 164 case F128_TO_EXTF80: 165 return false; 166 } 167 } 168 return true; 169 } 170 171 static void do_testfloat(int op, int rmode, bool exact) 172 { 173 abz_f16 true_abz_f16; 174 abz_f16 subj_abz_f16; 175 ab_f16_z_bool true_f16_z_bool; 176 ab_f16_z_bool subj_f16_z_bool; 177 abz_f32 true_abz_f32; 178 abz_f32 subj_abz_f32; 179 ab_f32_z_bool true_ab_f32_z_bool; 180 ab_f32_z_bool subj_ab_f32_z_bool; 181 abz_f64 true_abz_f64; 182 abz_f64 subj_abz_f64; 183 ab_f64_z_bool true_ab_f64_z_bool; 184 ab_f64_z_bool subj_ab_f64_z_bool; 185 abz_extF80M true_abz_extF80M; 186 abz_extF80M subj_abz_extF80M; 187 ab_extF80M_z_bool true_ab_extF80M_z_bool; 188 ab_extF80M_z_bool subj_ab_extF80M_z_bool; 189 abz_f128M true_abz_f128M; 190 abz_f128M subj_abz_f128M; 191 ab_f128M_z_bool true_ab_f128M_z_bool; 192 ab_f128M_z_bool subj_ab_f128M_z_bool; 193 194 if (verCases_verbosity) { 195 fputs(">> Testing ", stderr); 196 verCases_writeFunctionName(stderr); 197 fputs("\n", stderr); 198 } 199 200 if (!is_allowed(op, rmode)) { 201 not_implemented(); 202 return; 203 } 204 205 switch (op) { 206 case UI32_TO_F16: 207 test_a_ui32_z_f16(slow_ui32_to_f16, qemu_ui32_to_f16); 208 break; 209 case UI32_TO_F32: 210 test_a_ui32_z_f32(slow_ui32_to_f32, qemu_ui32_to_f32); 211 break; 212 case UI32_TO_F64: 213 test_a_ui32_z_f64(slow_ui32_to_f64, qemu_ui32_to_f64); 214 break; 215 case UI32_TO_EXTF80: 216 not_implemented(); 217 break; 218 case UI32_TO_F128: 219 not_implemented(); 220 break; 221 case UI64_TO_F16: 222 test_a_ui64_z_f16(slow_ui64_to_f16, qemu_ui64_to_f16); 223 break; 224 case UI64_TO_F32: 225 test_a_ui64_z_f32(slow_ui64_to_f32, qemu_ui64_to_f32); 226 break; 227 case UI64_TO_F64: 228 test_a_ui64_z_f64(slow_ui64_to_f64, qemu_ui64_to_f64); 229 break; 230 case UI64_TO_EXTF80: 231 not_implemented(); 232 break; 233 case UI64_TO_F128: 234 test_a_ui64_z_f128(slow_ui64_to_f128M, qemu_ui64_to_f128M); 235 break; 236 case I32_TO_F16: 237 test_a_i32_z_f16(slow_i32_to_f16, qemu_i32_to_f16); 238 break; 239 case I32_TO_F32: 240 test_a_i32_z_f32(slow_i32_to_f32, qemu_i32_to_f32); 241 break; 242 case I32_TO_F64: 243 test_a_i32_z_f64(slow_i32_to_f64, qemu_i32_to_f64); 244 break; 245 case I32_TO_EXTF80: 246 test_a_i32_z_extF80(slow_i32_to_extF80M, qemu_i32_to_extF80M); 247 break; 248 case I32_TO_F128: 249 test_a_i32_z_f128(slow_i32_to_f128M, qemu_i32_to_f128M); 250 break; 251 case I64_TO_F16: 252 test_a_i64_z_f16(slow_i64_to_f16, qemu_i64_to_f16); 253 break; 254 case I64_TO_F32: 255 test_a_i64_z_f32(slow_i64_to_f32, qemu_i64_to_f32); 256 break; 257 case I64_TO_F64: 258 test_a_i64_z_f64(slow_i64_to_f64, qemu_i64_to_f64); 259 break; 260 case I64_TO_EXTF80: 261 test_a_i64_z_extF80(slow_i64_to_extF80M, qemu_i64_to_extF80M); 262 break; 263 case I64_TO_F128: 264 test_a_i64_z_f128(slow_i64_to_f128M, qemu_i64_to_f128M); 265 break; 266 case F16_TO_UI32: 267 test_a_f16_z_ui32_rx(slow_f16_to_ui32, qemu_f16_to_ui32, rmode, exact); 268 break; 269 case F16_TO_UI64: 270 test_a_f16_z_ui64_rx(slow_f16_to_ui64, qemu_f16_to_ui64, rmode, exact); 271 break; 272 case F16_TO_I32: 273 test_a_f16_z_i32_rx(slow_f16_to_i32, qemu_f16_to_i32, rmode, exact); 274 break; 275 case F16_TO_I64: 276 test_a_f16_z_i64_rx(slow_f16_to_i64, qemu_f16_to_i64, rmode, exact); 277 break; 278 case F16_TO_UI32_R_MINMAG: 279 test_a_f16_z_ui32_x(slow_f16_to_ui32_r_minMag, 280 qemu_f16_to_ui32_r_minMag, exact); 281 break; 282 case F16_TO_UI64_R_MINMAG: 283 test_a_f16_z_ui64_x(slow_f16_to_ui64_r_minMag, 284 qemu_f16_to_ui64_r_minMag, exact); 285 break; 286 case F16_TO_I32_R_MINMAG: 287 test_a_f16_z_i32_x(slow_f16_to_i32_r_minMag, qemu_f16_to_i32_r_minMag, 288 exact); 289 break; 290 case F16_TO_I64_R_MINMAG: 291 test_a_f16_z_i64_x(slow_f16_to_i64_r_minMag, qemu_f16_to_i64_r_minMag, 292 exact); 293 break; 294 case F16_TO_F32: 295 test_a_f16_z_f32(slow_f16_to_f32, qemu_f16_to_f32); 296 break; 297 case F16_TO_F64: 298 test_a_f16_z_f64(slow_f16_to_f64, qemu_f16_to_f64); 299 break; 300 case F16_TO_EXTF80: 301 not_implemented(); 302 break; 303 case F16_TO_F128: 304 not_implemented(); 305 break; 306 case F16_ROUNDTOINT: 307 test_az_f16_rx(slow_f16_roundToInt, qemu_f16_roundToInt, rmode, exact); 308 break; 309 case F16_ADD: 310 true_abz_f16 = slow_f16_add; 311 subj_abz_f16 = qemu_f16_add; 312 goto test_abz_f16; 313 case F16_SUB: 314 true_abz_f16 = slow_f16_sub; 315 subj_abz_f16 = qemu_f16_sub; 316 goto test_abz_f16; 317 case F16_MUL: 318 true_abz_f16 = slow_f16_mul; 319 subj_abz_f16 = qemu_f16_mul; 320 goto test_abz_f16; 321 case F16_DIV: 322 true_abz_f16 = slow_f16_div; 323 subj_abz_f16 = qemu_f16_div; 324 goto test_abz_f16; 325 case F16_REM: 326 not_implemented(); 327 break; 328 test_abz_f16: 329 test_abz_f16(true_abz_f16, subj_abz_f16); 330 break; 331 case F16_MULADD: 332 test_abcz_f16(slow_f16_mulAdd, qemu_f16_mulAdd); 333 break; 334 case F16_SQRT: 335 test_az_f16(slow_f16_sqrt, qemu_f16_sqrt); 336 break; 337 case F16_EQ: 338 true_f16_z_bool = slow_f16_eq; 339 subj_f16_z_bool = qemu_f16_eq; 340 goto test_ab_f16_z_bool; 341 case F16_LE: 342 true_f16_z_bool = slow_f16_le; 343 subj_f16_z_bool = qemu_f16_le; 344 goto test_ab_f16_z_bool; 345 case F16_LT: 346 true_f16_z_bool = slow_f16_lt; 347 subj_f16_z_bool = qemu_f16_lt; 348 goto test_ab_f16_z_bool; 349 case F16_EQ_SIGNALING: 350 true_f16_z_bool = slow_f16_eq_signaling; 351 subj_f16_z_bool = qemu_f16_eq_signaling; 352 goto test_ab_f16_z_bool; 353 case F16_LE_QUIET: 354 true_f16_z_bool = slow_f16_le_quiet; 355 subj_f16_z_bool = qemu_f16_le_quiet; 356 goto test_ab_f16_z_bool; 357 case F16_LT_QUIET: 358 true_f16_z_bool = slow_f16_lt_quiet; 359 subj_f16_z_bool = qemu_f16_lt_quiet; 360 test_ab_f16_z_bool: 361 test_ab_f16_z_bool(true_f16_z_bool, subj_f16_z_bool); 362 break; 363 case F32_TO_UI32: 364 test_a_f32_z_ui32_rx(slow_f32_to_ui32, qemu_f32_to_ui32, rmode, exact); 365 break; 366 case F32_TO_UI64: 367 test_a_f32_z_ui64_rx(slow_f32_to_ui64, qemu_f32_to_ui64, rmode, exact); 368 break; 369 case F32_TO_I32: 370 test_a_f32_z_i32_rx(slow_f32_to_i32, qemu_f32_to_i32, rmode, exact); 371 break; 372 case F32_TO_I64: 373 test_a_f32_z_i64_rx(slow_f32_to_i64, qemu_f32_to_i64, rmode, exact); 374 break; 375 case F32_TO_UI32_R_MINMAG: 376 test_a_f32_z_ui32_x(slow_f32_to_ui32_r_minMag, 377 qemu_f32_to_ui32_r_minMag, exact); 378 break; 379 case F32_TO_UI64_R_MINMAG: 380 test_a_f32_z_ui64_x(slow_f32_to_ui64_r_minMag, 381 qemu_f32_to_ui64_r_minMag, exact); 382 break; 383 case F32_TO_I32_R_MINMAG: 384 test_a_f32_z_i32_x(slow_f32_to_i32_r_minMag, qemu_f32_to_i32_r_minMag, 385 exact); 386 break; 387 case F32_TO_I64_R_MINMAG: 388 test_a_f32_z_i64_x(slow_f32_to_i64_r_minMag, qemu_f32_to_i64_r_minMag, 389 exact); 390 break; 391 case F32_TO_F16: 392 test_a_f32_z_f16(slow_f32_to_f16, qemu_f32_to_f16); 393 break; 394 case F32_TO_F64: 395 test_a_f32_z_f64(slow_f32_to_f64, qemu_f32_to_f64); 396 break; 397 case F32_TO_EXTF80: 398 test_a_f32_z_extF80(slow_f32_to_extF80M, qemu_f32_to_extF80M); 399 break; 400 case F32_TO_F128: 401 test_a_f32_z_f128(slow_f32_to_f128M, qemu_f32_to_f128M); 402 break; 403 case F32_ROUNDTOINT: 404 test_az_f32_rx(slow_f32_roundToInt, qemu_f32_roundToInt, rmode, exact); 405 break; 406 case F32_ADD: 407 true_abz_f32 = slow_f32_add; 408 subj_abz_f32 = qemu_f32_add; 409 goto test_abz_f32; 410 case F32_SUB: 411 true_abz_f32 = slow_f32_sub; 412 subj_abz_f32 = qemu_f32_sub; 413 goto test_abz_f32; 414 case F32_MUL: 415 true_abz_f32 = slow_f32_mul; 416 subj_abz_f32 = qemu_f32_mul; 417 goto test_abz_f32; 418 case F32_DIV: 419 true_abz_f32 = slow_f32_div; 420 subj_abz_f32 = qemu_f32_div; 421 goto test_abz_f32; 422 case F32_REM: 423 true_abz_f32 = slow_f32_rem; 424 subj_abz_f32 = qemu_f32_rem; 425 test_abz_f32: 426 test_abz_f32(true_abz_f32, subj_abz_f32); 427 break; 428 case F32_MULADD: 429 test_abcz_f32(slow_f32_mulAdd, qemu_f32_mulAdd); 430 break; 431 case F32_SQRT: 432 test_az_f32(slow_f32_sqrt, qemu_f32_sqrt); 433 break; 434 case F32_EQ: 435 true_ab_f32_z_bool = slow_f32_eq; 436 subj_ab_f32_z_bool = qemu_f32_eq; 437 goto test_ab_f32_z_bool; 438 case F32_LE: 439 true_ab_f32_z_bool = slow_f32_le; 440 subj_ab_f32_z_bool = qemu_f32_le; 441 goto test_ab_f32_z_bool; 442 case F32_LT: 443 true_ab_f32_z_bool = slow_f32_lt; 444 subj_ab_f32_z_bool = qemu_f32_lt; 445 goto test_ab_f32_z_bool; 446 case F32_EQ_SIGNALING: 447 true_ab_f32_z_bool = slow_f32_eq_signaling; 448 subj_ab_f32_z_bool = qemu_f32_eq_signaling; 449 goto test_ab_f32_z_bool; 450 case F32_LE_QUIET: 451 true_ab_f32_z_bool = slow_f32_le_quiet; 452 subj_ab_f32_z_bool = qemu_f32_le_quiet; 453 goto test_ab_f32_z_bool; 454 case F32_LT_QUIET: 455 true_ab_f32_z_bool = slow_f32_lt_quiet; 456 subj_ab_f32_z_bool = qemu_f32_lt_quiet; 457 test_ab_f32_z_bool: 458 test_ab_f32_z_bool(true_ab_f32_z_bool, subj_ab_f32_z_bool); 459 break; 460 case F64_TO_UI32: 461 test_a_f64_z_ui32_rx(slow_f64_to_ui32, qemu_f64_to_ui32, rmode, exact); 462 break; 463 case F64_TO_UI64: 464 test_a_f64_z_ui64_rx(slow_f64_to_ui64, qemu_f64_to_ui64, rmode, exact); 465 break; 466 case F64_TO_I32: 467 test_a_f64_z_i32_rx(slow_f64_to_i32, qemu_f64_to_i32, rmode, exact); 468 break; 469 case F64_TO_I64: 470 test_a_f64_z_i64_rx(slow_f64_to_i64, qemu_f64_to_i64, rmode, exact); 471 break; 472 case F64_TO_UI32_R_MINMAG: 473 test_a_f64_z_ui32_x(slow_f64_to_ui32_r_minMag, 474 qemu_f64_to_ui32_r_minMag, exact); 475 break; 476 case F64_TO_UI64_R_MINMAG: 477 test_a_f64_z_ui64_x(slow_f64_to_ui64_r_minMag, 478 qemu_f64_to_ui64_r_minMag, exact); 479 break; 480 case F64_TO_I32_R_MINMAG: 481 test_a_f64_z_i32_x(slow_f64_to_i32_r_minMag, qemu_f64_to_i32_r_minMag, 482 exact); 483 break; 484 case F64_TO_I64_R_MINMAG: 485 test_a_f64_z_i64_x(slow_f64_to_i64_r_minMag, qemu_f64_to_i64_r_minMag, 486 exact); 487 break; 488 case F64_TO_F16: 489 test_a_f64_z_f16(slow_f64_to_f16, qemu_f64_to_f16); 490 break; 491 case F64_TO_F32: 492 test_a_f64_z_f32(slow_f64_to_f32, qemu_f64_to_f32); 493 break; 494 case F64_TO_EXTF80: 495 test_a_f64_z_extF80(slow_f64_to_extF80M, qemu_f64_to_extF80M); 496 break; 497 case F64_TO_F128: 498 test_a_f64_z_f128(slow_f64_to_f128M, qemu_f64_to_f128M); 499 break; 500 case F64_ROUNDTOINT: 501 test_az_f64_rx(slow_f64_roundToInt, qemu_f64_roundToInt, rmode, exact); 502 break; 503 case F64_ADD: 504 true_abz_f64 = slow_f64_add; 505 subj_abz_f64 = qemu_f64_add; 506 goto test_abz_f64; 507 case F64_SUB: 508 true_abz_f64 = slow_f64_sub; 509 subj_abz_f64 = qemu_f64_sub; 510 goto test_abz_f64; 511 case F64_MUL: 512 true_abz_f64 = slow_f64_mul; 513 subj_abz_f64 = qemu_f64_mul; 514 goto test_abz_f64; 515 case F64_DIV: 516 true_abz_f64 = slow_f64_div; 517 subj_abz_f64 = qemu_f64_div; 518 goto test_abz_f64; 519 case F64_REM: 520 true_abz_f64 = slow_f64_rem; 521 subj_abz_f64 = qemu_f64_rem; 522 test_abz_f64: 523 test_abz_f64(true_abz_f64, subj_abz_f64); 524 break; 525 case F64_MULADD: 526 test_abcz_f64(slow_f64_mulAdd, qemu_f64_mulAdd); 527 break; 528 case F64_SQRT: 529 test_az_f64(slow_f64_sqrt, qemu_f64_sqrt); 530 break; 531 case F64_EQ: 532 true_ab_f64_z_bool = slow_f64_eq; 533 subj_ab_f64_z_bool = qemu_f64_eq; 534 goto test_ab_f64_z_bool; 535 case F64_LE: 536 true_ab_f64_z_bool = slow_f64_le; 537 subj_ab_f64_z_bool = qemu_f64_le; 538 goto test_ab_f64_z_bool; 539 case F64_LT: 540 true_ab_f64_z_bool = slow_f64_lt; 541 subj_ab_f64_z_bool = qemu_f64_lt; 542 goto test_ab_f64_z_bool; 543 case F64_EQ_SIGNALING: 544 true_ab_f64_z_bool = slow_f64_eq_signaling; 545 subj_ab_f64_z_bool = qemu_f64_eq_signaling; 546 goto test_ab_f64_z_bool; 547 case F64_LE_QUIET: 548 true_ab_f64_z_bool = slow_f64_le_quiet; 549 subj_ab_f64_z_bool = qemu_f64_le_quiet; 550 goto test_ab_f64_z_bool; 551 case F64_LT_QUIET: 552 true_ab_f64_z_bool = slow_f64_lt_quiet; 553 subj_ab_f64_z_bool = qemu_f64_lt_quiet; 554 test_ab_f64_z_bool: 555 test_ab_f64_z_bool(true_ab_f64_z_bool, subj_ab_f64_z_bool); 556 break; 557 case EXTF80_TO_UI32: 558 not_implemented(); 559 break; 560 case EXTF80_TO_UI64: 561 not_implemented(); 562 break; 563 case EXTF80_TO_I32: 564 test_a_extF80_z_i32_rx(slow_extF80M_to_i32, qemu_extF80M_to_i32, rmode, 565 exact); 566 break; 567 case EXTF80_TO_I64: 568 test_a_extF80_z_i64_rx(slow_extF80M_to_i64, qemu_extF80M_to_i64, rmode, 569 exact); 570 break; 571 case EXTF80_TO_UI32_R_MINMAG: 572 not_implemented(); 573 break; 574 case EXTF80_TO_UI64_R_MINMAG: 575 not_implemented(); 576 break; 577 case EXTF80_TO_I32_R_MINMAG: 578 test_a_extF80_z_i32_x(slow_extF80M_to_i32_r_minMag, 579 qemu_extF80M_to_i32_r_minMag, exact); 580 break; 581 case EXTF80_TO_I64_R_MINMAG: 582 test_a_extF80_z_i64_x(slow_extF80M_to_i64_r_minMag, 583 qemu_extF80M_to_i64_r_minMag, exact); 584 break; 585 case EXTF80_TO_F16: 586 not_implemented(); 587 break; 588 case EXTF80_TO_F32: 589 test_a_extF80_z_f32(slow_extF80M_to_f32, qemu_extF80M_to_f32); 590 break; 591 case EXTF80_TO_F64: 592 test_a_extF80_z_f64(slow_extF80M_to_f64, qemu_extF80M_to_f64); 593 break; 594 case EXTF80_TO_F128: 595 test_a_extF80_z_f128(slow_extF80M_to_f128M, qemu_extF80M_to_f128M); 596 break; 597 case EXTF80_ROUNDTOINT: 598 test_az_extF80_rx(slow_extF80M_roundToInt, qemu_extF80M_roundToInt, 599 rmode, exact); 600 break; 601 case EXTF80_ADD: 602 true_abz_extF80M = slow_extF80M_add; 603 subj_abz_extF80M = qemu_extF80M_add; 604 goto test_abz_extF80; 605 case EXTF80_SUB: 606 true_abz_extF80M = slow_extF80M_sub; 607 subj_abz_extF80M = qemu_extF80M_sub; 608 goto test_abz_extF80; 609 case EXTF80_MUL: 610 true_abz_extF80M = slow_extF80M_mul; 611 subj_abz_extF80M = qemu_extF80M_mul; 612 goto test_abz_extF80; 613 case EXTF80_DIV: 614 true_abz_extF80M = slow_extF80M_div; 615 subj_abz_extF80M = qemu_extF80M_div; 616 goto test_abz_extF80; 617 case EXTF80_REM: 618 true_abz_extF80M = slow_extF80M_rem; 619 subj_abz_extF80M = qemu_extF80M_rem; 620 test_abz_extF80: 621 test_abz_extF80(true_abz_extF80M, subj_abz_extF80M); 622 break; 623 case EXTF80_SQRT: 624 test_az_extF80(slow_extF80M_sqrt, qemu_extF80M_sqrt); 625 break; 626 case EXTF80_EQ: 627 true_ab_extF80M_z_bool = slow_extF80M_eq; 628 subj_ab_extF80M_z_bool = qemu_extF80M_eq; 629 goto test_ab_extF80_z_bool; 630 case EXTF80_LE: 631 true_ab_extF80M_z_bool = slow_extF80M_le; 632 subj_ab_extF80M_z_bool = qemu_extF80M_le; 633 goto test_ab_extF80_z_bool; 634 case EXTF80_LT: 635 true_ab_extF80M_z_bool = slow_extF80M_lt; 636 subj_ab_extF80M_z_bool = qemu_extF80M_lt; 637 goto test_ab_extF80_z_bool; 638 case EXTF80_EQ_SIGNALING: 639 true_ab_extF80M_z_bool = slow_extF80M_eq_signaling; 640 subj_ab_extF80M_z_bool = qemu_extF80M_eq_signaling; 641 goto test_ab_extF80_z_bool; 642 case EXTF80_LE_QUIET: 643 true_ab_extF80M_z_bool = slow_extF80M_le_quiet; 644 subj_ab_extF80M_z_bool = qemu_extF80M_le_quiet; 645 goto test_ab_extF80_z_bool; 646 case EXTF80_LT_QUIET: 647 true_ab_extF80M_z_bool = slow_extF80M_lt_quiet; 648 subj_ab_extF80M_z_bool = qemu_extF80M_lt_quiet; 649 test_ab_extF80_z_bool: 650 test_ab_extF80_z_bool(true_ab_extF80M_z_bool, subj_ab_extF80M_z_bool); 651 break; 652 case F128_TO_UI32: 653 test_a_f128_z_ui32_rx(slow_f128M_to_ui32, qemu_f128M_to_ui32, rmode, 654 exact); 655 break; 656 case F128_TO_UI64: 657 test_a_f128_z_ui64_rx(slow_f128M_to_ui64, qemu_f128M_to_ui64, rmode, 658 exact); 659 break; 660 case F128_TO_I32: 661 test_a_f128_z_i32_rx(slow_f128M_to_i32, qemu_f128M_to_i32, rmode, 662 exact); 663 break; 664 case F128_TO_I64: 665 test_a_f128_z_i64_rx(slow_f128M_to_i64, qemu_f128M_to_i64, rmode, 666 exact); 667 break; 668 case F128_TO_UI32_R_MINMAG: 669 test_a_f128_z_ui32_x(slow_f128M_to_ui32_r_minMag, 670 qemu_f128M_to_ui32_r_minMag, exact); 671 break; 672 case F128_TO_UI64_R_MINMAG: 673 test_a_f128_z_ui64_x(slow_f128M_to_ui64_r_minMag, 674 qemu_f128M_to_ui64_r_minMag, exact); 675 break; 676 case F128_TO_I32_R_MINMAG: 677 test_a_f128_z_i32_x(slow_f128M_to_i32_r_minMag, 678 qemu_f128M_to_i32_r_minMag, exact); 679 break; 680 case F128_TO_I64_R_MINMAG: 681 test_a_f128_z_i64_x(slow_f128M_to_i64_r_minMag, 682 qemu_f128M_to_i64_r_minMag, exact); 683 break; 684 case F128_TO_F16: 685 not_implemented(); 686 break; 687 case F128_TO_F32: 688 test_a_f128_z_f32(slow_f128M_to_f32, qemu_f128M_to_f32); 689 break; 690 case F128_TO_F64: 691 test_a_f128_z_f64(slow_f128M_to_f64, qemu_f128M_to_f64); 692 break; 693 case F128_TO_EXTF80: 694 test_a_f128_z_extF80(slow_f128M_to_extF80M, qemu_f128M_to_extF80M); 695 break; 696 case F128_ROUNDTOINT: 697 test_az_f128_rx(slow_f128M_roundToInt, qemu_f128M_roundToInt, rmode, 698 exact); 699 break; 700 case F128_ADD: 701 true_abz_f128M = slow_f128M_add; 702 subj_abz_f128M = qemu_f128M_add; 703 goto test_abz_f128; 704 case F128_SUB: 705 true_abz_f128M = slow_f128M_sub; 706 subj_abz_f128M = qemu_f128M_sub; 707 goto test_abz_f128; 708 case F128_MUL: 709 true_abz_f128M = slow_f128M_mul; 710 subj_abz_f128M = qemu_f128M_mul; 711 goto test_abz_f128; 712 case F128_DIV: 713 true_abz_f128M = slow_f128M_div; 714 subj_abz_f128M = qemu_f128M_div; 715 goto test_abz_f128; 716 case F128_REM: 717 true_abz_f128M = slow_f128M_rem; 718 subj_abz_f128M = qemu_f128M_rem; 719 test_abz_f128: 720 test_abz_f128(true_abz_f128M, subj_abz_f128M); 721 break; 722 case F128_MULADD: 723 test_abcz_f128(slow_f128M_mulAdd, qemu_f128M_mulAdd); 724 break; 725 case F128_SQRT: 726 test_az_f128(slow_f128M_sqrt, qemu_f128M_sqrt); 727 break; 728 case F128_EQ: 729 true_ab_f128M_z_bool = slow_f128M_eq; 730 subj_ab_f128M_z_bool = qemu_f128M_eq; 731 goto test_ab_f128_z_bool; 732 case F128_LE: 733 true_ab_f128M_z_bool = slow_f128M_le; 734 subj_ab_f128M_z_bool = qemu_f128M_le; 735 goto test_ab_f128_z_bool; 736 case F128_LT: 737 true_ab_f128M_z_bool = slow_f128M_lt; 738 subj_ab_f128M_z_bool = qemu_f128M_lt; 739 goto test_ab_f128_z_bool; 740 case F128_EQ_SIGNALING: 741 true_ab_f128M_z_bool = slow_f128M_eq_signaling; 742 subj_ab_f128M_z_bool = qemu_f128M_eq_signaling; 743 goto test_ab_f128_z_bool; 744 case F128_LE_QUIET: 745 true_ab_f128M_z_bool = slow_f128M_le_quiet; 746 subj_ab_f128M_z_bool = qemu_f128M_le_quiet; 747 goto test_ab_f128_z_bool; 748 case F128_LT_QUIET: 749 true_ab_f128M_z_bool = slow_f128M_lt_quiet; 750 subj_ab_f128M_z_bool = qemu_f128M_lt_quiet; 751 test_ab_f128_z_bool: 752 test_ab_f128_z_bool(true_ab_f128M_z_bool, subj_ab_f128M_z_bool); 753 break; 754 } 755 if ((verCases_errorStop && verCases_anyErrors)) { 756 verCases_exitWithStatus(); 757 } 758 } 759 760 static unsigned int test_name_to_op(const char *arg) 761 { 762 unsigned int i; 763 764 /* counting begins at 1 */ 765 for (i = 1; i < NUM_FUNCTIONS; i++) { 766 const char *name = functionInfos[i].namePtr; 767 768 if (name && !strcmp(name, arg)) { 769 return i; 770 } 771 } 772 return 0; 773 } 774 775 static unsigned int round_name_to_mode(const char *name) 776 { 777 int i; 778 779 /* counting begins at 1 */ 780 for (i = 1; i < NUM_ROUNDINGMODES; i++) { 781 if (!strcmp(round_mode_names[i], name)) { 782 return i; 783 } 784 } 785 return 0; 786 } 787 788 static int set_init_flags(const char *flags) 789 { 790 const char *p; 791 792 for (p = flags; *p != '\0'; p++) { 793 switch (*p) { 794 case 'v': 795 slow_init_flags |= softfloat_flag_invalid; 796 qemu_init_flags |= float_flag_invalid; 797 break; 798 case 'i': 799 slow_init_flags |= softfloat_flag_infinite; 800 qemu_init_flags |= float_flag_divbyzero; 801 break; 802 case 'o': 803 slow_init_flags |= softfloat_flag_overflow; 804 qemu_init_flags |= float_flag_overflow; 805 break; 806 case 'u': 807 slow_init_flags |= softfloat_flag_underflow; 808 qemu_init_flags |= float_flag_underflow; 809 break; 810 case 'x': 811 slow_init_flags |= softfloat_flag_inexact; 812 qemu_init_flags |= float_flag_inexact; 813 break; 814 default: 815 return 1; 816 } 817 } 818 return 0; 819 } 820 821 static uint_fast8_t slow_clear_flags(void) 822 { 823 uint8_t prev = slowfloat_exceptionFlags; 824 825 slowfloat_exceptionFlags = slow_init_flags; 826 return prev; 827 } 828 829 static uint_fast8_t qemu_clear_flags(void) 830 { 831 uint8_t prev = qemu_flags_to_sf(qsf.float_exception_flags); 832 833 qsf.float_exception_flags = qemu_init_flags; 834 return prev; 835 } 836 837 static void parse_args(int argc, char *argv[]) 838 { 839 unsigned int i; 840 int c; 841 842 for (;;) { 843 c = getopt(argc, argv, "he:f:l:r:sq"); 844 if (c < 0) { 845 break; 846 } 847 switch (c) { 848 case 'h': 849 usage_complete(argc, argv); 850 exit(EXIT_SUCCESS); 851 case 'e': 852 if (qemu_strtoui(optarg, NULL, 0, &n_max_errors)) { 853 fprintf(stderr, "fatal: invalid max error count\n"); 854 exit(EXIT_FAILURE); 855 } 856 break; 857 case 'f': 858 if (set_init_flags(optarg)) { 859 fprintf(stderr, "fatal: flags must be a subset of 'vioux'\n"); 860 exit(EXIT_FAILURE); 861 } 862 break; 863 case 'l': 864 if (qemu_strtoi(optarg, NULL, 0, &test_level)) { 865 fprintf(stderr, "fatal: invalid test level\n"); 866 exit(EXIT_FAILURE); 867 } 868 break; 869 case 'r': 870 if (!strcmp(optarg, "all")) { 871 test_round_mode = 0; 872 } else { 873 test_round_mode = round_name_to_mode(optarg); 874 if (test_round_mode == 0) { 875 fprintf(stderr, "fatal: invalid rounding mode\n"); 876 exit(EXIT_FAILURE); 877 } 878 } 879 break; 880 /* 881 * The following flags are declared in testfloat/source/verCases_common.c 882 */ 883 case 's': 884 verCases_errorStop = true; 885 break; 886 case 'q': 887 verCases_verbosity = 0; 888 break; 889 case '?': 890 /* invalid option or missing argument; getopt prints error info */ 891 exit(EXIT_FAILURE); 892 } 893 } 894 895 /* set rounding modes */ 896 if (test_round_mode == 0) { 897 /* test all rounding modes; note that counting begins at 1 */ 898 n_round_modes = NUM_ROUNDINGMODES - 1; 899 round_modes = g_malloc_n(n_round_modes, sizeof(*round_modes)); 900 for (i = 0; i < n_round_modes; i++) { 901 round_modes[i] = i + 1; 902 } 903 } else { 904 n_round_modes = 1; 905 round_modes = g_malloc(sizeof(*round_modes)); 906 round_modes[0] = test_round_mode; 907 } 908 909 /* set test ops */ 910 if (optind == argc) { 911 /* test all ops; note that counting begins at 1 */ 912 n_test_ops = NUM_FUNCTIONS - 1; 913 test_ops = g_malloc_n(n_test_ops, sizeof(*test_ops)); 914 for (i = 0; i < n_test_ops; i++) { 915 test_ops[i] = i + 1; 916 } 917 } else { 918 n_test_ops = argc - optind; 919 test_ops = g_malloc_n(n_test_ops, sizeof(*test_ops)); 920 for (i = 0; i < n_test_ops; i++) { 921 const char *name = argv[i + optind]; 922 unsigned int op = test_name_to_op(name); 923 924 if (op == 0) { 925 fprintf(stderr, "fatal: invalid op '%s'\n", name); 926 exit(EXIT_FAILURE); 927 } 928 test_ops[i] = op; 929 } 930 } 931 } 932 933 static G_NORETURN 934 void run_test(void) 935 { 936 unsigned int i; 937 938 genCases_setLevel(test_level); 939 verCases_maxErrorCount = n_max_errors; 940 941 testLoops_trueFlagsFunction = slow_clear_flags; 942 testLoops_subjFlagsFunction = qemu_clear_flags; 943 944 for (i = 0; i < n_test_ops; i++) { 945 unsigned int op = test_ops[i]; 946 int j; 947 948 if (functionInfos[op].namePtr == NULL) { 949 continue; 950 } 951 verCases_functionNamePtr = functionInfos[op].namePtr; 952 953 for (j = 0; j < n_round_modes; j++) { 954 int attrs = functionInfos[op].attribs; 955 int round = round_modes[j]; 956 int rmode = roundingModes[round]; 957 int k; 958 959 verCases_roundingCode = 0; 960 slowfloat_roundingMode = rmode; 961 qsf.float_rounding_mode = sf_rounding_to_qemu(rmode); 962 963 if (attrs & (FUNC_ARG_ROUNDINGMODE | FUNC_EFF_ROUNDINGMODE)) { 964 /* print rounding mode if the op is affected by it */ 965 verCases_roundingCode = round; 966 } else if (j > 0) { 967 /* if the op is not sensitive to rounding, move on */ 968 break; 969 } 970 971 /* QEMU doesn't have !exact */ 972 verCases_exact = true; 973 verCases_usesExact = !!(attrs & FUNC_ARG_EXACT); 974 975 for (k = 0; k < 3; k++) { 976 FloatX80RoundPrec qsf_prec80 = floatx80_precision_x; 977 int prec80 = 80; 978 int l; 979 980 if (k == 1) { 981 prec80 = 64; 982 qsf_prec80 = floatx80_precision_d; 983 } else if (k == 2) { 984 prec80 = 32; 985 qsf_prec80 = floatx80_precision_s; 986 } 987 988 verCases_roundingPrecision = 0; 989 slow_extF80_roundingPrecision = prec80; 990 qsf.floatx80_rounding_precision = qsf_prec80; 991 992 if (attrs & FUNC_EFF_ROUNDINGPRECISION) { 993 verCases_roundingPrecision = prec80; 994 } else if (k > 0) { 995 /* if the op is not sensitive to prec80, move on */ 996 break; 997 } 998 999 /* note: the count begins at 1 */ 1000 for (l = 1; l < NUM_TININESSMODES; l++) { 1001 int tmode = tininessModes[l]; 1002 1003 verCases_tininessCode = 0; 1004 slowfloat_detectTininess = tmode; 1005 qsf.tininess_before_rounding = sf_tininess_to_qemu(tmode); 1006 1007 if (attrs & FUNC_EFF_TININESSMODE || 1008 ((attrs & FUNC_EFF_TININESSMODE_REDUCEDPREC) && 1009 prec80 && prec80 < 80)) { 1010 verCases_tininessCode = l; 1011 } else if (l > 1) { 1012 /* if the op is not sensitive to tininess, move on */ 1013 break; 1014 } 1015 1016 do_testfloat(op, rmode, true); 1017 } 1018 } 1019 } 1020 } 1021 verCases_exitWithStatus(); 1022 /* old compilers might miss that we exited */ 1023 g_assert_not_reached(); 1024 } 1025 1026 int main(int argc, char *argv[]) 1027 { 1028 parse_args(argc, argv); 1029 fail_programName = argv[0]; 1030 run_test(); /* does not return */ 1031 } 1032