(root)/
glibc-2.38/
sysdeps/
x86/
fpu/
test-fenv-sse-2.c
       1  /* Test x86-specific floating-point environment (bug 16068): SSE part.
       2     Copyright (C) 2015-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 <stdint.h>
      24  #include <stdio.h>
      25  
      26  static bool
      27  have_sse2 (void)
      28  {
      29    unsigned int eax, ebx, ecx, edx;
      30  
      31    if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
      32      return false;
      33  
      34    return (edx & bit_SSE2) != 0;
      35  }
      36  
      37  static uint32_t
      38  get_sse_mxcsr (void)
      39  {
      40    uint32_t temp;
      41    __asm__ __volatile__ ("stmxcsr %0" : "=m" (temp));
      42    return temp;
      43  }
      44  
      45  static void
      46  set_sse_mxcsr (uint32_t val)
      47  {
      48    __asm__ __volatile__ ("ldmxcsr %0" : : "m" (val));
      49  }
      50  
      51  static void
      52  set_sse_mxcsr_bits (uint32_t mask, uint32_t bits)
      53  {
      54    uint32_t mxcsr = get_sse_mxcsr ();
      55    mxcsr = (mxcsr & ~mask) | bits;
      56    set_sse_mxcsr (mxcsr);
      57  }
      58  
      59  static int
      60  test_sse_mxcsr_bits (const char *test, uint32_t mask, uint32_t bits)
      61  {
      62    uint32_t mxcsr = get_sse_mxcsr ();
      63    printf ("Testing %s: mxcsr = %x\n", test, mxcsr);
      64    if ((mxcsr & mask) == bits)
      65      {
      66        printf ("PASS: %s\n", test);
      67        return 0;
      68      }
      69    else
      70      {
      71        printf ("FAIL: %s\n", test);
      72        return 1;
      73      }
      74  }
      75  
      76  #define MXCSR_FZ 0x8000
      77  #define MXCSR_DAZ 0x40
      78  #define MXCSR_DE 0x2
      79  #define MXCSR_DM 0x100
      80  
      81  static __attribute__ ((noinline)) int
      82  sse_tests (void)
      83  {
      84    int result = 0;
      85    fenv_t env1, env2;
      86    /* Test FZ bit.  */
      87    fegetenv (&env1);
      88    set_sse_mxcsr_bits (MXCSR_FZ, MXCSR_FZ);
      89    fegetenv (&env2);
      90    fesetenv (&env1);
      91    result |= test_sse_mxcsr_bits ("fesetenv FZ restoration",
      92  				 MXCSR_FZ, 0);
      93    set_sse_mxcsr_bits (MXCSR_FZ, 0);
      94    fesetenv (&env2);
      95    result |= test_sse_mxcsr_bits ("fesetenv FZ restoration 2",
      96  				 MXCSR_FZ, MXCSR_FZ);
      97    set_sse_mxcsr_bits (MXCSR_FZ, MXCSR_FZ);
      98    fesetenv (FE_NOMASK_ENV);
      99    result |= test_sse_mxcsr_bits ("fesetenv (FE_NOMASK_ENV) FZ restoration",
     100  				 MXCSR_FZ, 0);
     101    set_sse_mxcsr_bits (MXCSR_FZ, MXCSR_FZ);
     102    fesetenv (FE_DFL_ENV);
     103    result |= test_sse_mxcsr_bits ("fesetenv (FE_DFL_ENV) FZ restoration",
     104  				 MXCSR_FZ, 0);
     105    /* Test DAZ bit.  */
     106    set_sse_mxcsr_bits (MXCSR_DAZ, MXCSR_DAZ);
     107    fegetenv (&env2);
     108    fesetenv (&env1);
     109    result |= test_sse_mxcsr_bits ("fesetenv DAZ restoration",
     110  				 MXCSR_DAZ, 0);
     111    set_sse_mxcsr_bits (MXCSR_DAZ, 0);
     112    fesetenv (&env2);
     113    result |= test_sse_mxcsr_bits ("fesetenv DAZ restoration 2",
     114  				 MXCSR_DAZ, MXCSR_DAZ);
     115    set_sse_mxcsr_bits (MXCSR_DAZ, MXCSR_DAZ);
     116    fesetenv (FE_NOMASK_ENV);
     117    result |= test_sse_mxcsr_bits ("fesetenv (FE_NOMASK_ENV) DAZ restoration",
     118  				 MXCSR_DAZ, 0);
     119    set_sse_mxcsr_bits (MXCSR_DAZ, MXCSR_DAZ);
     120    fesetenv (FE_DFL_ENV);
     121    result |= test_sse_mxcsr_bits ("fesetenv (FE_DFL_ENV) DAZ restoration",
     122  				 MXCSR_DAZ, 0);
     123    /* Test DM bit.  */
     124    set_sse_mxcsr_bits (MXCSR_DM, 0);
     125    fegetenv (&env2);
     126    fesetenv (&env1);
     127    result |= test_sse_mxcsr_bits ("fesetenv DM restoration",
     128  				 MXCSR_DM, MXCSR_DM);
     129    set_sse_mxcsr_bits (MXCSR_DM, MXCSR_DM);
     130    fesetenv (&env2);
     131    result |= test_sse_mxcsr_bits ("fesetenv DM restoration 2",
     132  				 MXCSR_DM, 0);
     133    set_sse_mxcsr_bits (MXCSR_DM, 0);
     134    /* Presume FE_NOMASK_ENV should leave the "denormal operand"
     135       exception masked, as not a standard exception.  */
     136    fesetenv (FE_NOMASK_ENV);
     137    result |= test_sse_mxcsr_bits ("fesetenv (FE_NOMASK_ENV) DM restoration",
     138  				 MXCSR_DM, MXCSR_DM);
     139    set_sse_mxcsr_bits (MXCSR_DM, 0);
     140    fesetenv (FE_DFL_ENV);
     141    result |= test_sse_mxcsr_bits ("fesetenv (FE_DFL_ENV) DM restoration",
     142  				 MXCSR_DM, MXCSR_DM);
     143    /* Test DE bit.  */
     144    set_sse_mxcsr_bits (MXCSR_DE, MXCSR_DE);
     145    fegetenv (&env2);
     146    fesetenv (&env1);
     147    result |= test_sse_mxcsr_bits ("fesetenv DE restoration",
     148  				 MXCSR_DE, 0);
     149    set_sse_mxcsr_bits (MXCSR_DE, 0);
     150    fesetenv (&env2);
     151    result |= test_sse_mxcsr_bits ("fesetenv DE restoration 2",
     152  				 MXCSR_DE, MXCSR_DE);
     153    set_sse_mxcsr_bits (MXCSR_DE, MXCSR_DE);
     154    fesetenv (FE_NOMASK_ENV);
     155    result |= test_sse_mxcsr_bits ("fesetenv (FE_NOMASK_ENV) DE restoration",
     156  				 MXCSR_DE, 0);
     157    set_sse_mxcsr_bits (MXCSR_DE, MXCSR_DE);
     158    fesetenv (FE_DFL_ENV);
     159    result |= test_sse_mxcsr_bits ("fesetenv (FE_DFL_ENV) DE restoration",
     160  				 MXCSR_DE, 0);
     161    return result;
     162  }
     163  
     164  static int
     165  do_test (void)
     166  {
     167    if (!have_sse2 ())
     168      {
     169        puts ("CPU does not support SSE2, cannot test");
     170        return 0;
     171      }
     172    return sse_tests ();
     173  }
     174  
     175  #define TEST_FUNCTION do_test ()
     176  #include <test-skeleton.c>