xref: /openbmc/qemu/tests/tcg/multiarch/float_convs.c (revision 542b10bd)
1b059a62bSAlex Bennée /*
2b059a62bSAlex Bennée  * Floating Point Convert Single to Various
3b059a62bSAlex Bennée  *
4*542b10bdSAlex Bennée  * Copyright (c) 2019, 2024 Linaro
5b059a62bSAlex Bennée  *
6*542b10bdSAlex Bennée  * SPDX-License-Identifier: GPL-2.0-or-later
7b059a62bSAlex Bennée  */
8b059a62bSAlex Bennée 
9b059a62bSAlex Bennée #include <stdio.h>
10b059a62bSAlex Bennée #include <stdlib.h>
11b059a62bSAlex Bennée #include <math.h>
12b059a62bSAlex Bennée #include <float.h>
13b059a62bSAlex Bennée #include <fenv.h>
14b059a62bSAlex Bennée 
15b059a62bSAlex Bennée 
16b059a62bSAlex Bennée #include "float_helpers.h"
17b059a62bSAlex Bennée 
18b059a62bSAlex Bennée #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
19b059a62bSAlex Bennée 
20b059a62bSAlex Bennée typedef struct {
21b059a62bSAlex Bennée     int flag;
22b059a62bSAlex Bennée     char *desc;
23b059a62bSAlex Bennée } float_mapping;
24b059a62bSAlex Bennée 
25b059a62bSAlex Bennée float_mapping round_flags[] = {
26b059a62bSAlex Bennée     { FE_TONEAREST, "to nearest" },
27b059a62bSAlex Bennée #ifdef FE_UPWARD
28b059a62bSAlex Bennée     { FE_UPWARD, "upwards" },
29b059a62bSAlex Bennée #endif
30b059a62bSAlex Bennée #ifdef FE_DOWNWARD
31b059a62bSAlex Bennée     { FE_DOWNWARD, "downwards" },
32b059a62bSAlex Bennée #endif
334c71dc37SRichard Henderson #ifdef FE_TOWARDZERO
34b059a62bSAlex Bennée     { FE_TOWARDZERO, "to zero" }
354c71dc37SRichard Henderson #endif
36b059a62bSAlex Bennée };
37b059a62bSAlex Bennée 
print_input(float input)38b059a62bSAlex Bennée static void print_input(float input)
39b059a62bSAlex Bennée {
40b059a62bSAlex Bennée     char *in_fmt = fmt_f32(input);
41b059a62bSAlex Bennée     printf("from single: %s\n", in_fmt);
42b059a62bSAlex Bennée     free(in_fmt);
43b059a62bSAlex Bennée }
44b059a62bSAlex Bennée 
convert_single_to_double(float input)45b059a62bSAlex Bennée static void convert_single_to_double(float input)
46b059a62bSAlex Bennée {
47b059a62bSAlex Bennée     double output;
48b059a62bSAlex Bennée     char *out_fmt, *flag_fmt;
49b059a62bSAlex Bennée 
50b059a62bSAlex Bennée     feclearexcept(FE_ALL_EXCEPT);
51b059a62bSAlex Bennée 
52b059a62bSAlex Bennée     output = input;
53b059a62bSAlex Bennée 
54b059a62bSAlex Bennée     flag_fmt = fmt_flags();
55603bd9c2SRichard Henderson     out_fmt = fmt_f64(output);
56b059a62bSAlex Bennée     printf("  to double: %s (%s)\n", out_fmt, flag_fmt);
57b059a62bSAlex Bennée     free(out_fmt);
58b059a62bSAlex Bennée     free(flag_fmt);
59b059a62bSAlex Bennée }
60b059a62bSAlex Bennée 
61b059a62bSAlex Bennée #define xstr(a) str(a)
62b059a62bSAlex Bennée #define str(a) #a
63b059a62bSAlex Bennée 
64b059a62bSAlex Bennée #define CONVERT_SINGLE_TO_INT(TYPE, FMT)                            \
65b059a62bSAlex Bennée     static void convert_single_to_ ## TYPE(float input)             \
66b059a62bSAlex Bennée     {                                                               \
67b059a62bSAlex Bennée         TYPE ## _t output;                                          \
68b059a62bSAlex Bennée         char *flag_fmt;                                             \
69b059a62bSAlex Bennée         const char to[] = "to " xstr(TYPE);                         \
70b059a62bSAlex Bennée         feclearexcept(FE_ALL_EXCEPT);                               \
71b059a62bSAlex Bennée         output = input;                                             \
72b059a62bSAlex Bennée         flag_fmt = fmt_flags();                                     \
73b059a62bSAlex Bennée         printf("%11s: %" FMT " (%s)\n", to, output, flag_fmt);      \
74b059a62bSAlex Bennée         free(flag_fmt);                                             \
75b059a62bSAlex Bennée     }
76b059a62bSAlex Bennée 
CONVERT_SINGLE_TO_INT(int32,PRId32)77b059a62bSAlex Bennée CONVERT_SINGLE_TO_INT( int32, PRId32)
78b059a62bSAlex Bennée CONVERT_SINGLE_TO_INT(uint32, PRId32)
79b059a62bSAlex Bennée CONVERT_SINGLE_TO_INT( int64, PRId64)
80b059a62bSAlex Bennée CONVERT_SINGLE_TO_INT(uint64, PRId64)
81b059a62bSAlex Bennée 
82b059a62bSAlex Bennée int main(int argc, char *argv[argc])
83b059a62bSAlex Bennée {
84b059a62bSAlex Bennée     int i, j, nums;
85b059a62bSAlex Bennée 
86b059a62bSAlex Bennée     nums = get_num_f32();
87b059a62bSAlex Bennée 
88b059a62bSAlex Bennée     for (i = 0; i < ARRAY_SIZE(round_flags); ++i) {
89b059a62bSAlex Bennée         if (fesetround(round_flags[i].flag) != 0) {
90b059a62bSAlex Bennée             printf("### Rounding %s skipped\n", round_flags[i].desc);
91b059a62bSAlex Bennée             continue;
92b059a62bSAlex Bennée         }
93b059a62bSAlex Bennée         printf("### Rounding %s\n", round_flags[i].desc);
94b059a62bSAlex Bennée         for (j = 0; j < nums; j++) {
95b059a62bSAlex Bennée             float input = get_f32(j);
96b059a62bSAlex Bennée             print_input(input);
97b059a62bSAlex Bennée             /* convert_single_to_half(input); */
98b059a62bSAlex Bennée             convert_single_to_double(input);
99b059a62bSAlex Bennée             convert_single_to_int32(input);
100b059a62bSAlex Bennée             convert_single_to_int64(input);
101b059a62bSAlex Bennée             convert_single_to_uint32(input);
102b059a62bSAlex Bennée             convert_single_to_uint64(input);
103b059a62bSAlex Bennée         }
104b059a62bSAlex Bennée     }
105b059a62bSAlex Bennée 
106b059a62bSAlex Bennée     return 0;
107b059a62bSAlex Bennée }
108