Commit b059a62b authored by Alex Bennée's avatar Alex Bennée
Browse files

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: default avatarAlex Bennée <alex.bennee@linaro.org>
Reviewed-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Tested-by: default avatarPhilippe Mathieu-Daudé <philmd@redhat.com>
parent a4f3ed62
Loading
Loading
Loading
Loading
+748 −0

File added.

Preview size limit exceeded, changes collapsed.

+748 −0

File added.

Preview size limit exceeded, changes collapsed.

+3 −3
Original line number Diff line number Diff line
@@ -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)

+105 −0
Original line number Diff line number Diff line
/*
 * 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;
}