blob: 36b5712cda0db600e16e2f839c3a1bb5906ed8c4 [file] [log] [blame]
Emilio G. Cota3ac1f812018-03-08 21:09:40 -05001/*
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
58typedef float16_t (*abz_f16)(float16_t, float16_t);
59typedef bool (*ab_f16_z_bool)(float16_t, float16_t);
60typedef float32_t (*abz_f32)(float32_t, float32_t);
61typedef bool (*ab_f32_z_bool)(float32_t, float32_t);
62typedef float64_t (*abz_f64)(float64_t, float64_t);
63typedef bool (*ab_f64_z_bool)(float64_t, float64_t);
64typedef void (*abz_extF80M)(const extFloat80_t *, const extFloat80_t *,
65 extFloat80_t *);
66typedef bool (*ab_extF80M_z_bool)(const extFloat80_t *, const extFloat80_t *);
67typedef void (*abz_f128M)(const float128_t *, const float128_t *, float128_t *);
68typedef bool (*ab_f128M_z_bool)(const float128_t *, const float128_t *);
69
70static 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};
78static unsigned int *test_ops;
79static unsigned int n_test_ops;
80static unsigned int n_max_errors = 20;
81static unsigned int test_round_mode = ROUND_NEAR_EVEN;
82static unsigned int *round_modes;
83static unsigned int n_round_modes;
84static int test_level = 1;
85static uint8_t slow_init_flags;
86static uint8_t qemu_init_flags;
87
88/* qemu softfloat status */
89static float_status qsf;
90
91static 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"
Alex Bennée6348a542023-02-28 19:06:33 +0000109 " -s = stop when a test fails\n"
110 " -q = minimise noise when testing, just show each function being tested";
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500111
112static 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 */
Paolo Bonzini139c1832020-02-04 12:41:01 +0100120#include "wrap.c.inc"
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500121
122static void not_implemented(void)
123{
124 fprintf(stderr, "Not implemented.\n");
125}
126
Philippe Mathieu-Daudéd5f84682021-03-03 19:46:44 +0100127static bool is_allowed(unsigned op, int rmode)
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500128{
Richard Henderson5d64abb2019-02-15 09:02:25 -0800129 /* odd has not been implemented for any 80-bit ops */
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500130 if (rmode == softfloat_round_odd) {
131 switch (op) {
Richard Henderson5d64abb2019-02-15 09:02:25 -0800132 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:
Philippe Mathieu-Daudéd5f84682021-03-03 19:46:44 +0100165 return false;
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500166 }
167 }
Philippe Mathieu-Daudéd5f84682021-03-03 19:46:44 +0100168 return true;
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500169}
170
171static 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
Alex Bennée6348a542023-02-28 19:06:33 +0000194 if (verCases_verbosity) {
195 fputs(">> Testing ", stderr);
196 verCases_writeFunctionName(stderr);
197 fputs("\n", stderr);
198 }
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500199
Philippe Mathieu-Daudéd5f84682021-03-03 19:46:44 +0100200 if (!is_allowed(op, rmode)) {
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500201 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:
Alex Bennée80d491f2019-02-06 14:31:40 +0000653 test_a_f128_z_ui32_rx(slow_f128M_to_ui32, qemu_f128M_to_ui32, rmode,
654 exact);
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500655 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:
Richard Hendersondedd1232020-10-24 06:04:19 -0700723 test_abcz_f128(slow_f128M_mulAdd, qemu_f128M_mulAdd);
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500724 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
760static 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
775static 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
788static 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
Emilio G. Cota710fbcd2019-01-17 13:22:12 -0500821static uint_fast8_t slow_clear_flags(void)
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500822{
823 uint8_t prev = slowfloat_exceptionFlags;
824
825 slowfloat_exceptionFlags = slow_init_flags;
826 return prev;
827}
828
Emilio G. Cota710fbcd2019-01-17 13:22:12 -0500829static uint_fast8_t qemu_clear_flags(void)
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500830{
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
837static void parse_args(int argc, char *argv[])
838{
839 unsigned int i;
840 int c;
841
842 for (;;) {
Alex Bennée6348a542023-02-28 19:06:33 +0000843 c = getopt(argc, argv, "he:f:l:r:sq");
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500844 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;
Alex Bennée6348a542023-02-28 19:06:33 +0000880 /*
881 * The following flags are declared in testfloat/source/verCases_common.c
882 */
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500883 case 's':
884 verCases_errorStop = true;
885 break;
Alex Bennée6348a542023-02-28 19:06:33 +0000886 case 'q':
887 verCases_verbosity = 0;
888 break;
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500889 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
Marc-André Lureau89057702022-04-20 17:26:02 +0400933static G_NORETURN
934void run_test(void)
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500935{
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++) {
Richard Henderson7ccae4c2020-11-21 17:32:01 -0800976 FloatX80RoundPrec qsf_prec80 = floatx80_precision_x;
977 int prec80 = 80;
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500978 int l;
979
980 if (k == 1) {
981 prec80 = 64;
Richard Henderson8da5f1d2020-11-21 09:33:36 -0800982 qsf_prec80 = floatx80_precision_d;
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500983 } else if (k == 2) {
Richard Henderson7ccae4c2020-11-21 17:32:01 -0800984 prec80 = 32;
985 qsf_prec80 = floatx80_precision_s;
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500986 }
987
988 verCases_roundingPrecision = 0;
989 slow_extF80_roundingPrecision = prec80;
Richard Henderson8da5f1d2020-11-21 09:33:36 -0800990 qsf.floatx80_rounding_precision = qsf_prec80;
Emilio G. Cota3ac1f812018-03-08 21:09:40 -0500991
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;
Richard Hendersona828b372020-05-04 21:19:39 -07001005 qsf.tininess_before_rounding = sf_tininess_to_qemu(tmode);
Emilio G. Cota3ac1f812018-03-08 21:09:40 -05001006
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
1026int main(int argc, char *argv[])
1027{
1028 parse_args(argc, argv);
1029 fail_programName = argv[0];
1030 run_test(); /* does not return */
1031}