(root)/
glibc-2.38/
sysdeps/
x86/
fpu/
test-fenv-x87.c
       1  /* Test x86-specific floating-point environment (bug 16068): x87 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 <fenv.h>
      20  #include <float.h>
      21  #include <fpu_control.h>
      22  #include <stdint.h>
      23  #include <stdio.h>
      24  
      25  static uint16_t
      26  get_x87_cw (void)
      27  {
      28    fpu_control_t cw;
      29    _FPU_GETCW (cw);
      30    return cw;
      31  }
      32  
      33  static void
      34  set_x87_cw (uint16_t val)
      35  {
      36    fpu_control_t cw = val;
      37    _FPU_SETCW (cw);
      38  }
      39  
      40  static void
      41  set_x87_cw_bits (uint16_t mask, uint16_t bits)
      42  {
      43    uint16_t cw = get_x87_cw ();
      44    cw = (cw & ~mask) | bits;
      45    set_x87_cw (cw);
      46  }
      47  
      48  static int
      49  test_x87_cw_bits (const char *test, uint16_t mask, uint16_t bits)
      50  {
      51    uint16_t cw = get_x87_cw ();
      52    printf ("Testing %s: cw = %x\n", test, cw);
      53    if ((cw & mask) == bits)
      54      {
      55        printf ("PASS: %s\n", test);
      56        return 0;
      57      }
      58    else
      59      {
      60        printf ("FAIL: %s\n", test);
      61        return 1;
      62      }
      63  }
      64  
      65  static uint16_t
      66  get_x87_sw (void)
      67  {
      68    uint16_t temp;
      69    __asm__ __volatile__ ("fnstsw %0" : "=a" (temp));
      70    return temp;
      71  }
      72  
      73  static void
      74  set_x87_sw_bits (uint16_t mask, uint16_t bits)
      75  {
      76    fenv_t temp;
      77    __asm__ __volatile__ ("fnstenv %0" : "=m" (temp));
      78    temp.__status_word = (temp.__status_word & ~mask) | bits;
      79    __asm__ __volatile__ ("fldenv %0" : : "m" (temp));
      80  }
      81  
      82  static int
      83  test_x87_sw_bits (const char *test, uint16_t mask, uint16_t bits)
      84  {
      85    uint16_t sw = get_x87_sw ();
      86    printf ("Testing %s: sw = %x\n", test, sw);
      87    if ((sw & mask) == bits)
      88      {
      89        printf ("PASS: %s\n", test);
      90        return 0;
      91      }
      92    else
      93      {
      94        printf ("FAIL: %s\n", test);
      95        return 1;
      96      }
      97  }
      98  
      99  #define X87_CW_PREC_MASK _FPU_EXTENDED
     100  
     101  static int
     102  do_test (void)
     103  {
     104    int result = 0;
     105    fenv_t env1, env2;
     106    /* Test precision mask.  */
     107    fegetenv (&env1);
     108    set_x87_cw_bits (X87_CW_PREC_MASK, _FPU_SINGLE);
     109    fegetenv (&env2);
     110    fesetenv (&env1);
     111    result |= test_x87_cw_bits ("fesetenv precision restoration",
     112  			      X87_CW_PREC_MASK, _FPU_EXTENDED);
     113    set_x87_cw_bits (X87_CW_PREC_MASK, _FPU_EXTENDED);
     114    fesetenv (&env2);
     115    result |= test_x87_cw_bits ("fesetenv precision restoration 2",
     116  			      X87_CW_PREC_MASK, _FPU_SINGLE);
     117    set_x87_cw_bits (X87_CW_PREC_MASK, _FPU_DOUBLE);
     118    fesetenv (FE_NOMASK_ENV);
     119    result |= test_x87_cw_bits ("fesetenv (FE_NOMASK_ENV) precision restoration",
     120  			      X87_CW_PREC_MASK, _FPU_EXTENDED);
     121    set_x87_cw_bits (X87_CW_PREC_MASK, _FPU_SINGLE);
     122    fesetenv (FE_DFL_ENV);
     123    result |= test_x87_cw_bits ("fesetenv (FE_DFL_ENV) precision restoration",
     124  			      X87_CW_PREC_MASK, _FPU_EXTENDED);
     125    /* Test x87 denormal operand masking.  */
     126    set_x87_cw_bits (_FPU_MASK_DM, 0);
     127    fegetenv (&env2);
     128    fesetenv (&env1);
     129    result |= test_x87_cw_bits ("fesetenv denormal mask restoration",
     130  			      _FPU_MASK_DM, _FPU_MASK_DM);
     131    set_x87_cw_bits (_FPU_MASK_DM, _FPU_MASK_DM);
     132    fesetenv (&env2);
     133    result |= test_x87_cw_bits ("fesetenv denormal mask restoration 2",
     134  			      _FPU_MASK_DM, 0);
     135    set_x87_cw_bits (_FPU_MASK_DM, 0);
     136    /* Presume FE_NOMASK_ENV should leave the "denormal operand"
     137       exception masked, as not a standard exception.  */
     138    fesetenv (FE_NOMASK_ENV);
     139    result |= test_x87_cw_bits ("fesetenv (FE_NOMASK_ENV) denormal mask "
     140  			      "restoration",
     141  			      _FPU_MASK_DM, _FPU_MASK_DM);
     142    set_x87_cw_bits (_FPU_MASK_DM, 0);
     143    fesetenv (FE_DFL_ENV);
     144    result |= test_x87_cw_bits ("fesetenv (FE_DFL_ENV) denormal mask "
     145  			      "restoration",
     146  			      _FPU_MASK_DM, _FPU_MASK_DM);
     147    /* Test x87 denormal operand exception.  */
     148    set_x87_sw_bits (__FE_DENORM, __FE_DENORM);
     149    fegetenv (&env2);
     150    fesetenv (&env1);
     151    result |= test_x87_sw_bits ("fesetenv denormal exception restoration",
     152  			      __FE_DENORM, 0);
     153    set_x87_sw_bits (__FE_DENORM, 0);
     154    fesetenv (&env2);
     155    result |= test_x87_sw_bits ("fesetenv denormal exception restoration 2",
     156  			      __FE_DENORM, __FE_DENORM);
     157    set_x87_sw_bits (__FE_DENORM, __FE_DENORM);
     158    fesetenv (FE_NOMASK_ENV);
     159    result |= test_x87_sw_bits ("fesetenv (FE_NOMASK_ENV) exception restoration",
     160  			      __FE_DENORM, 0);
     161    set_x87_sw_bits (__FE_DENORM, __FE_DENORM);
     162    fesetenv (FE_DFL_ENV);
     163    result |= test_x87_sw_bits ("fesetenv (FE_DFL_ENV) exception restoration",
     164  			      __FE_DENORM, 0);
     165    return result;
     166  }
     167  
     168  #define TEST_FUNCTION do_test ()
     169  #include <test-skeleton.c>