(root)/
glibc-2.38/
sysdeps/
mips/
fpu/
fenv_private.h
       1  /* Internal math stuff.  MIPS version.
       2     Copyright (C) 2013-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  #ifndef MIPS_FENV_PRIVATE_H
      20  #define MIPS_FENV_PRIVATE_H 1
      21  
      22  /* Inline functions to speed up the math library implementation.  The
      23     default versions of these routines are in generic/fenv_private.h
      24     and call fesetround, feholdexcept, etc.  These routines use inlined
      25     code instead.  */
      26  
      27  #include <fenv.h>
      28  #include <fenv_libc.h>
      29  #include <fpu_control.h>
      30  
      31  #define _FPU_MASK_ALL (_FPU_MASK_V | _FPU_MASK_Z | _FPU_MASK_O \
      32  		       |_FPU_MASK_U | _FPU_MASK_I | FE_ALL_EXCEPT)
      33  
      34  static __always_inline void
      35  libc_feholdexcept_mips (fenv_t *envp)
      36  {
      37    fpu_control_t cw;
      38  
      39    /* Save the current state.  */
      40    _FPU_GETCW (cw);
      41    envp->__fp_control_register = cw;
      42  
      43    /* Clear all exception enable bits and flags.  */
      44    cw &= ~(_FPU_MASK_ALL);
      45    _FPU_SETCW (cw);
      46  }
      47  #define libc_feholdexcept libc_feholdexcept_mips
      48  #define libc_feholdexceptf libc_feholdexcept_mips
      49  #define libc_feholdexceptl libc_feholdexcept_mips
      50  
      51  static __always_inline void
      52  libc_fesetround_mips (int round)
      53  {
      54    fpu_control_t cw;
      55  
      56    /* Get current state.  */
      57    _FPU_GETCW (cw);
      58  
      59    /* Set rounding bits.  */
      60    cw &= ~_FPU_RC_MASK;
      61    cw |= round;
      62  
      63    /* Set new state.  */
      64    _FPU_SETCW (cw);
      65  }
      66  #define libc_fesetround libc_fesetround_mips
      67  #define libc_fesetroundf libc_fesetround_mips
      68  #define libc_fesetroundl libc_fesetround_mips
      69  
      70  static __always_inline void
      71  libc_feholdexcept_setround_mips (fenv_t *envp, int round)
      72  {
      73    fpu_control_t cw;
      74  
      75    /* Save the current state.  */
      76    _FPU_GETCW (cw);
      77    envp->__fp_control_register = cw;
      78  
      79    /* Clear all exception enable bits and flags.  */
      80    cw &= ~(_FPU_MASK_ALL);
      81  
      82    /* Set rounding bits.  */
      83    cw &= ~_FPU_RC_MASK;
      84    cw |= round;
      85  
      86    /* Set new state.  */
      87    _FPU_SETCW (cw);
      88  }
      89  #define libc_feholdexcept_setround libc_feholdexcept_setround_mips
      90  #define libc_feholdexcept_setroundf libc_feholdexcept_setround_mips
      91  #define libc_feholdexcept_setroundl libc_feholdexcept_setround_mips
      92  
      93  #define libc_feholdsetround libc_feholdexcept_setround_mips
      94  #define libc_feholdsetroundf libc_feholdexcept_setround_mips
      95  #define libc_feholdsetroundl libc_feholdexcept_setround_mips
      96  
      97  static __always_inline void
      98  libc_fesetenv_mips (fenv_t *envp)
      99  {
     100    fpu_control_t cw __attribute__ ((unused));
     101  
     102    /* Read current state to flush fpu pipeline.  */
     103    _FPU_GETCW (cw);
     104  
     105    _FPU_SETCW (envp->__fp_control_register);
     106  }
     107  #define libc_fesetenv libc_fesetenv_mips
     108  #define libc_fesetenvf libc_fesetenv_mips
     109  #define libc_fesetenvl libc_fesetenv_mips
     110  
     111  static __always_inline int
     112  libc_feupdateenv_test_mips (fenv_t *envp, int excepts)
     113  {
     114    /* int ret = fetestexcept (excepts); feupdateenv (envp); return ret; */
     115    int cw, temp;
     116  
     117    /* Get current control word.  */
     118    _FPU_GETCW (cw);
     119  
     120    /* Set flag bits (which are accumulative), and *also* set the
     121       cause bits.  The setting of the cause bits is what actually causes
     122       the hardware to generate the exception, if the corresponding enable
     123       bit is set as well.  */
     124    temp = cw & FE_ALL_EXCEPT;
     125    temp |= envp->__fp_control_register | (temp << CAUSE_SHIFT);
     126  
     127    /* Set new state.  */
     128    _FPU_SETCW (temp);
     129  
     130    return cw & excepts & FE_ALL_EXCEPT;
     131  }
     132  #define libc_feupdateenv_test libc_feupdateenv_test_mips
     133  #define libc_feupdateenv_testf libc_feupdateenv_test_mips
     134  #define libc_feupdateenv_testl libc_feupdateenv_test_mips
     135  
     136  static __always_inline void
     137  libc_feupdateenv_mips (fenv_t *envp)
     138  {
     139    libc_feupdateenv_test_mips (envp, 0);
     140  }
     141  #define libc_feupdateenv libc_feupdateenv_mips
     142  #define libc_feupdateenvf libc_feupdateenv_mips
     143  #define libc_feupdateenvl libc_feupdateenv_mips
     144  
     145  #define libc_feresetround libc_feupdateenv_mips
     146  #define libc_feresetroundf libc_feupdateenv_mips
     147  #define libc_feresetroundl libc_feupdateenv_mips
     148  
     149  static __always_inline int
     150  libc_fetestexcept_mips (int excepts)
     151  {
     152    int cw;
     153  
     154    /* Get current control word.  */
     155    _FPU_GETCW (cw);
     156  
     157    return cw & excepts & FE_ALL_EXCEPT;
     158  }
     159  #define libc_fetestexcept libc_fetestexcept_mips
     160  #define libc_fetestexceptf libc_fetestexcept_mips
     161  #define libc_fetestexceptl libc_fetestexcept_mips
     162  
     163  /*  Enable support for rounding mode context.  */
     164  #define HAVE_RM_CTX 1
     165  
     166  static __always_inline void
     167  libc_feholdexcept_setround_mips_ctx (struct rm_ctx *ctx, int round)
     168  {
     169    fpu_control_t old, new;
     170  
     171    /* Save the current state.  */
     172    _FPU_GETCW (old);
     173    ctx->env.__fp_control_register = old;
     174  
     175    /* Clear all exception enable bits and flags.  */
     176    new = old & ~(_FPU_MASK_ALL);
     177  
     178    /* Set rounding bits.  */
     179    new = (new & ~_FPU_RC_MASK) | round;
     180  
     181    if (__glibc_unlikely (new != old))
     182      {
     183        _FPU_SETCW (new);
     184        ctx->updated_status = true;
     185      }
     186    else
     187      ctx->updated_status = false;
     188  }
     189  #define libc_feholdexcept_setround_ctx   libc_feholdexcept_setround_mips_ctx
     190  #define libc_feholdexcept_setroundf_ctx  libc_feholdexcept_setround_mips_ctx
     191  #define libc_feholdexcept_setroundl_ctx  libc_feholdexcept_setround_mips_ctx
     192  
     193  static __always_inline void
     194  libc_fesetenv_mips_ctx (struct rm_ctx *ctx)
     195  {
     196    libc_fesetenv_mips (&ctx->env);
     197  }
     198  #define libc_fesetenv_ctx                libc_fesetenv_mips_ctx
     199  #define libc_fesetenvf_ctx               libc_fesetenv_mips_ctx
     200  #define libc_fesetenvl_ctx               libc_fesetenv_mips_ctx
     201  
     202  static __always_inline void
     203  libc_feupdateenv_mips_ctx (struct rm_ctx *ctx)
     204  {
     205    if (__glibc_unlikely (ctx->updated_status))
     206      libc_feupdateenv_test_mips (&ctx->env, 0);
     207  }
     208  #define libc_feupdateenv_ctx             libc_feupdateenv_mips_ctx
     209  #define libc_feupdateenvf_ctx            libc_feupdateenv_mips_ctx
     210  #define libc_feupdateenvl_ctx            libc_feupdateenv_mips_ctx
     211  #define libc_feresetround_ctx            libc_feupdateenv_mips_ctx
     212  #define libc_feresetroundf_ctx           libc_feupdateenv_mips_ctx
     213  #define libc_feresetroundl_ctx           libc_feupdateenv_mips_ctx
     214  
     215  static __always_inline void
     216  libc_feholdsetround_mips_ctx (struct rm_ctx *ctx, int round)
     217  {
     218    fpu_control_t old, new;
     219  
     220    /* Save the current state.  */
     221    _FPU_GETCW (old);
     222    ctx->env.__fp_control_register = old;
     223  
     224    /* Set rounding bits.  */
     225    new = (old & ~_FPU_RC_MASK) | round;
     226  
     227    if (__glibc_unlikely (new != old))
     228      {
     229        _FPU_SETCW (new);
     230        ctx->updated_status = true;
     231      }
     232    else
     233      ctx->updated_status = false;
     234  }
     235  #define libc_feholdsetround_ctx          libc_feholdsetround_mips_ctx
     236  #define libc_feholdsetroundf_ctx         libc_feholdsetround_mips_ctx
     237  #define libc_feholdsetroundl_ctx         libc_feholdsetround_mips_ctx
     238  
     239  #include_next <fenv_private.h>
     240  
     241  #endif