xref: /openbmc/qemu/tests/tcg/multiarch/float_madds.c (revision 401e311f)
1 /*
2  * Fused Multiply Add (Single)
3  *
4  * Copyright (c) 2019, 2024 Linaro
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <math.h>
12 #include <float.h>
13 #include <fenv.h>
14 
15 #include "float_helpers.h"
16 
17 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
18 
19 typedef struct {
20     int flag;
21     char *desc;
22 } float_mapping;
23 
24 float_mapping round_flags[] = {
25     { FE_TONEAREST, "to nearest" },
26 #ifdef FE_UPWARD
27     { FE_UPWARD, "upwards" },
28 #endif
29 #ifdef FE_DOWNWARD
30     { FE_DOWNWARD, "downwards" },
31 #endif
32 #ifdef FE_TOWARDZERO
33     { FE_TOWARDZERO, "to zero" }
34 #endif
35 };
36 
37 
38 static void print_inputs(float a, float b, float c)
39 {
40     char *a_fmt, *b_fmt, *c_fmt;
41 
42     a_fmt = fmt_f32(a);
43     b_fmt = fmt_f32(b);
44     c_fmt = fmt_f32(c);
45 
46     printf("op : %s * %s + %s\n", a_fmt, b_fmt, c_fmt);
47 
48     free(a_fmt);
49     free(b_fmt);
50     free(c_fmt);
51 }
52 
53 static void print_result(float r, int j, int k)
54 {
55     char *r_fmt, *flag_fmt;
56 
57     flag_fmt = fmt_flags();
58     r_fmt = fmt_f32(r);
59 
60     printf("res: %s flags=%s (%d/%d)\n", r_fmt, flag_fmt, j, k);
61 
62     free(r_fmt);
63     free(flag_fmt);
64 }
65 
66 static void do_madds(float a, float b, float c, int j, int k)
67 {
68     float r;
69 
70     print_inputs(a, b, c);
71 
72     feclearexcept(FE_ALL_EXCEPT);
73     r = __builtin_fmaf(a, b, c);
74 
75     print_result(r, j, k);
76 }
77 
78 int main(int argc, char *argv[argc])
79 {
80     int i, j, k, nums = get_num_f32();
81     float a, b, c;
82 
83     for (i = 0; i < ARRAY_SIZE(round_flags); ++i) {
84         if (fesetround(round_flags[i].flag) != 0) {
85             printf("### Rounding %s skipped\n", round_flags[i].desc);
86             continue;
87         }
88         printf("### Rounding %s\n", round_flags[i].desc);
89         for (j = 0; j < nums; j++) {
90             for (k = 0; k < 3; k++) {
91                 a = get_f32(j + ((k)%3));
92                 b = get_f32(j + ((k+1)%3));
93                 c = get_f32(j + ((k+2)%3));
94                 do_madds(a, b, c, j, k);
95             }
96         }
97 
98         /* From https://bugs.launchpad.net/qemu/+bug/1841491 */
99         printf("# LP184149\n");
100         do_madds(0x1.ffffffffffffcp-1022, 0x1.0000000000001p-1, 0x0.0000000000001p-1022, j, 0);
101         do_madds(0x8p-152, 0x8p-152, 0x8p-152, j+1, 0);
102     }
103 
104     return 0;
105 }
106