(root)/
glibc-2.38/
sysdeps/
x86/
fpu/
test-fenv-sse.c
       1  /* Test floating-point environment includes SSE state (bug 16064).
       2     Copyright (C) 2014-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <cpuid.h>
      20  #include <fenv.h>
      21  #include <float.h>
      22  #include <stdbool.h>
      23  #include <stdio.h>
      24  
      25  static bool
      26  have_sse2 (void)
      27  {
      28    unsigned int eax, ebx, ecx, edx;
      29  
      30    if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
      31      return false;
      32  
      33    return (edx & bit_SSE2) != 0;
      34  }
      35  
      36  static __attribute__ ((noinline)) int
      37  sse_tests (void)
      38  {
      39    int ret = 0;
      40    fenv_t base_env;
      41    if (fegetenv (&base_env) != 0)
      42      {
      43        puts ("fegetenv (&base_env) failed");
      44        return 1;
      45      }
      46    if (fesetround (FE_UPWARD) != 0)
      47      {
      48        puts ("fesetround (FE_UPWARD) failed");
      49        return 1;
      50      }
      51    if (fesetenv (&base_env) != 0)
      52      {
      53        puts ("fesetenv (&base_env) failed");
      54        return 1;
      55      }
      56    volatile float a = 1.0f, b = FLT_MIN, c;
      57    c = a + b;
      58    if (c != 1.0f)
      59      {
      60        puts ("fesetenv did not restore rounding mode");
      61        ret = 1;
      62      }
      63    if (fesetround (FE_DOWNWARD) != 0)
      64      {
      65        puts ("fesetround (FE_DOWNWARD) failed");
      66        return 1;
      67      }
      68    if (feupdateenv (&base_env) != 0)
      69      {
      70        puts ("feupdateenv (&base_env) failed");
      71        return 1;
      72      }
      73    volatile float d = -FLT_MIN, e;
      74    e = a + d;
      75    if (e != 1.0f)
      76      {
      77        puts ("feupdateenv did not restore rounding mode");
      78        ret = 1;
      79      }
      80    if (fesetround (FE_UPWARD) != 0)
      81      {
      82        puts ("fesetround (FE_UPWARD) failed");
      83        return 1;
      84      }
      85    fenv_t upward_env;
      86    if (feholdexcept (&upward_env) != 0)
      87      {
      88        puts ("feholdexcept (&upward_env) failed");
      89        return 1;
      90      }
      91    if (fesetround (FE_DOWNWARD) != 0)
      92      {
      93        puts ("fesetround (FE_DOWNWARD) failed");
      94        return 1;
      95      }
      96    if (fesetenv (&upward_env) != 0)
      97      {
      98        puts ("fesetenv (&upward_env) failed");
      99        return 1;
     100      }
     101    e = a + d;
     102    if (e != 1.0f)
     103      {
     104        puts ("fesetenv did not restore rounding mode from feholdexcept");
     105        ret = 1;
     106      }
     107    if (fesetround (FE_UPWARD) != 0)
     108      {
     109        puts ("fesetround (FE_UPWARD) failed");
     110        return 1;
     111      }
     112    if (fesetenv (FE_DFL_ENV) != 0)
     113      {
     114        puts ("fesetenv (FE_DFL_ENV) failed");
     115        return 1;
     116      }
     117    c = a + b;
     118    if (c != 1.0f)
     119      {
     120        puts ("fesetenv (FE_DFL_ENV) did not restore rounding mode");
     121        ret = 1;
     122      }
     123    return ret;
     124  }
     125  
     126  static int
     127  do_test (void)
     128  {
     129    if (!have_sse2 ())
     130      {
     131        puts ("CPU does not support SSE2, cannot test");
     132        return 0;
     133      }
     134    return sse_tests ();
     135  }
     136  
     137  #define TEST_FUNCTION do_test ()
     138  #include <test-skeleton.c>