tests/tcg: add generic version of float_convs

This is broadly similar to the existing fcvt test for ARM but using
the generic float testing framework. We should be able to pare down
the ARM fcvt test case to purely half-precision with or without the
Alt HP provision.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
This commit is contained in:
Alex Bennée 2019-09-16 14:50:56 +01:00
parent a4f3ed629e
commit b059a62bb6
4 changed files with 1604 additions and 3 deletions

View file

@ -17,11 +17,11 @@ MULTIARCH_TESTS =$(filter-out float_helpers, $(MULTIARCH_SRCS:.c=))
#
float_madds: LDFLAGS+=-lm
float_madds: float_madds.c float_helpers.c
float_%: LDFLAGS+=-lm
float_%: float_%.c float_helpers.c
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< $(MULTIARCH_SRC)/float_helpers.c -o $@ $(LDFLAGS)
run-float_madds: float_madds
run-float_%: float_%
$(call run-test,$<, $(QEMU) $(QEMU_OPTS) $<,"$< on $(TARGET_NAME)")
$(call conditional-diff-out,$<,$(SRC_PATH)/tests/tcg/$(TARGET_NAME)/$<.ref)

View file

@ -0,0 +1,105 @@
/*
* Floating Point Convert Single 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
{ FE_TOWARDZERO, "to zero" }
};
static void print_input(float input)
{
char *in_fmt = fmt_f32(input);
printf("from single: %s\n", in_fmt);
free(in_fmt);
}
static void convert_single_to_double(float input)
{
double output;
char *out_fmt, *flag_fmt;
feclearexcept(FE_ALL_EXCEPT);
output = input;
out_fmt = fmt_f64(output);
flag_fmt = fmt_flags();
printf(" to double: %s (%s)\n", out_fmt, flag_fmt);
free(out_fmt);
free(flag_fmt);
}
#define xstr(a) str(a)
#define str(a) #a
#define CONVERT_SINGLE_TO_INT(TYPE, FMT) \
static void convert_single_to_ ## TYPE(float 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_SINGLE_TO_INT( int32, PRId32)
CONVERT_SINGLE_TO_INT(uint32, PRId32)
CONVERT_SINGLE_TO_INT( int64, PRId64)
CONVERT_SINGLE_TO_INT(uint64, PRId64)
int main(int argc, char *argv[argc])
{
int i, j, nums;
nums = get_num_f32();
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++) {
float input = get_f32(j);
print_input(input);
/* convert_single_to_half(input); */
convert_single_to_double(input);
convert_single_to_int32(input);
convert_single_to_int64(input);
convert_single_to_uint32(input);
convert_single_to_uint64(input);
}
}
return 0;
}