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