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