aboutsummaryrefslogtreecommitdiff
path: root/tests/tcg/multiarch
diff options
context:
space:
mode:
authorAlex Bennée <alex.bennee@linaro.org>2022-04-19 10:10:17 +0100
committerAlex Bennée <alex.bennee@linaro.org>2022-04-20 16:04:20 +0100
commit2931014c3ddd87b0dcb98788b5d50abee775bcea (patch)
treeff892a9919bc8d3af20ce8a9952626c7a10f05f9 /tests/tcg/multiarch
parent9730a27ef43d676807b8a0e84f2eff8124125902 (diff)
tests/tcg: add float_convd test
This is a simple transliteration of the float_convs test but this time working with doubles. I'm used it to test the handling of vector registers in gdbstub but wasn't able to find a non-ugly way to automate it. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20220419091020.3008144-23-alex.bennee@linaro.org>
Diffstat (limited to 'tests/tcg/multiarch')
-rw-r--r--tests/tcg/multiarch/float_convd.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/tests/tcg/multiarch/float_convd.c b/tests/tcg/multiarch/float_convd.c
new file mode 100644
index 0000000000..0a1f0f93dc
--- /dev/null
+++ b/tests/tcg/multiarch/float_convd.c
@@ -0,0 +1,106 @@
+/*
+ * Floating Point Convert Doubles to Various
+ *
+ * Copyright (c) 2019 Linaro
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <float.h>
+#include <fenv.h>
+
+
+#include "float_helpers.h"
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+typedef struct {
+ int flag;
+ char *desc;
+} float_mapping;
+
+float_mapping round_flags[] = {
+ { FE_TONEAREST, "to nearest" },
+#ifdef FE_UPWARD
+ { FE_UPWARD, "upwards" },
+#endif
+#ifdef FE_DOWNWARD
+ { FE_DOWNWARD, "downwards" },
+#endif
+#ifdef FE_TOWARDZERO
+ { FE_TOWARDZERO, "to zero" }
+#endif
+};
+
+static void print_input(double input)
+{
+ char *in_fmt = fmt_f64(input);
+ printf("from double: %s\n", in_fmt);
+ free(in_fmt);
+}
+
+static void convert_double_to_single(double input)
+{
+ float output;
+ char *out_fmt, *flag_fmt;
+
+ feclearexcept(FE_ALL_EXCEPT);
+
+ output = input;
+
+ flag_fmt = fmt_flags();
+ out_fmt = fmt_f32(output);
+ printf(" to single: %s (%s)\n", out_fmt, flag_fmt);
+ free(out_fmt);
+ free(flag_fmt);
+}
+
+#define xstr(a) str(a)
+#define str(a) #a
+
+#define CONVERT_DOUBLE_TO_INT(TYPE, FMT) \
+ static void convert_double_to_ ## TYPE(double input) \
+ { \
+ TYPE ## _t output; \
+ char *flag_fmt; \
+ const char to[] = "to " xstr(TYPE); \
+ feclearexcept(FE_ALL_EXCEPT); \
+ output = input; \
+ flag_fmt = fmt_flags(); \
+ printf("%11s: %" FMT " (%s)\n", to, output, flag_fmt); \
+ free(flag_fmt); \
+ }
+
+CONVERT_DOUBLE_TO_INT( int32, PRId32)
+CONVERT_DOUBLE_TO_INT(uint32, PRId32)
+CONVERT_DOUBLE_TO_INT( int64, PRId64)
+CONVERT_DOUBLE_TO_INT(uint64, PRId64)
+
+int main(int argc, char *argv[argc])
+{
+ int i, j, nums;
+
+ nums = get_num_f64();
+
+ for (i = 0; i < ARRAY_SIZE(round_flags); ++i) {
+ if (fesetround(round_flags[i].flag) != 0) {
+ printf("### Rounding %s skipped\n", round_flags[i].desc);
+ continue;
+ }
+ printf("### Rounding %s\n", round_flags[i].desc);
+ for (j = 0; j < nums; j++) {
+ double input = get_f64(j);
+ print_input(input);
+ convert_double_to_single(input);
+ convert_double_to_int32(input);
+ convert_double_to_int64(input);
+ convert_double_to_uint32(input);
+ convert_double_to_uint64(input);
+ }
+ }
+
+ return 0;
+}