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    { FE_TOWARDZERO, "to zero" }
  33};
  34
  35
  36static void print_inputs(float a, float b, float c)
  37{
  38    char *a_fmt, *b_fmt, *c_fmt;
  39
  40    a_fmt = fmt_f32(a);
  41    b_fmt = fmt_f32(b);
  42    c_fmt = fmt_f32(c);
  43
  44    printf("op : %s * %s + %s\n", a_fmt, b_fmt, c_fmt);
  45
  46    free(a_fmt);
  47    free(b_fmt);
  48    free(c_fmt);
  49}
  50
  51static void print_result(float r, int j, int k)
  52{
  53    char *r_fmt, *flag_fmt;
  54
  55    r_fmt = fmt_f32(r);
  56    flag_fmt = fmt_flags();
  57
  58    printf("res: %s flags=%s (%d/%d)\n", r_fmt, flag_fmt, j, k);
  59
  60    free(r_fmt);
  61    free(flag_fmt);
  62}
  63
  64static void do_madds(float a, float b, float c, int j, int k)
  65{
  66    float r;
  67
  68    print_inputs(a, b, c);
  69
  70    feclearexcept(FE_ALL_EXCEPT);
  71    r = __builtin_fmaf(a, b, c);
  72
  73    print_result(r, j, k);
  74}
  75
  76int main(int argc, char *argv[argc])
  77{
  78    int i, j, k, nums = get_num_f32();
  79    float a, b, c;
  80
  81    for (i = 0; i < ARRAY_SIZE(round_flags); ++i) {
  82        if (fesetround(round_flags[i].flag) != 0) {
  83            printf("### Rounding %s skipped\n", round_flags[i].desc);
  84            continue;
  85        }
  86        printf("### Rounding %s\n", round_flags[i].desc);
  87        for (j = 0; j < nums; j++) {
  88            for (k = 0; k < 3; k++) {
  89                a = get_f32(j + ((k)%3));
  90                b = get_f32(j + ((k+1)%3));
  91                c = get_f32(j + ((k+2)%3));
  92                do_madds(a, b, c, j, k);
  93            }
  94        }
  95
  96        /* From https://bugs.launchpad.net/qemu/+bug/1841491 */
  97        printf("# LP184149\n");
  98        do_madds(0x1.ffffffffffffcp-1022, 0x1.0000000000001p-1, 0x0.0000000000001p-1022, j, 0);
  99        do_madds(0x8p-152, 0x8p-152, 0x8p-152, j+1, 0);
 100    }
 101
 102    return 0;
 103}
 104