示例#1
0
void
__atomic_feclearexcept (void)
{
    unsigned int fpescr, old_fpescr;

    /* Get the current state.  */
    old_fpescr = fpescr = fegetenv_register ();

    /* Clear the relevant bits.  */
    fpescr &= ~SPEFSCR_ALL_EXCEPT;

    /* Put the new state in effect.  */
    fesetenv_register (fpescr);

    /* Let the kernel know if the "invalid" or "underflow" bit was
       cleared.  */
    if (old_fpescr & (SPEFSCR_FINVS | SPEFSCR_FUNFS))
    {
        int pflags __attribute__ ((__unused__)), r;

        r = prctl(PR_GET_FPEXC, (unsigned long)&pflags);
        if (r < 0)
            abort ();
    }
}
示例#2
0
int
fedisableexcept (int excepts)
{
  int result = 0, pflags, r;
  INTERNAL_SYSCALL_DECL (err);

  r = INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &pflags);
  if (INTERNAL_SYSCALL_ERROR_P (r, err))
    return -1;

  /* Save old enable bits.  */
  result = __fexcepts_from_prctl (pflags);

  pflags &= ~__fexcepts_to_prctl (excepts);
  r = INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC,
			pflags | PR_FP_EXC_SW_ENABLE);
  if (INTERNAL_SYSCALL_ERROR_P (r, err))
    return -1;

  /* If disabling signals for "inexact", also disable trapping to the
     kernel.  */
  if ((excepts & FE_INEXACT) != 0)
    {
      unsigned long fpescr;

      fpescr = fegetenv_register ();
      fpescr &= ~SPEFSCR_FINXE;
      fesetenv_register (fpescr);
    }

  return result;
}
示例#3
0
int
fedisableexcept (int excepts)
{
  fenv_union_t fe;
  int result;

  result = fegetexcept ();

  if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID)
    excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID;

  fe.fenv = fegetenv_register ();
  if (excepts & FE_INEXACT)
    fe.l[1] &= ~(1 << (31 - FPSCR_XE));
  if (excepts & FE_DIVBYZERO)
    fe.l[1] &= ~(1 << (31 - FPSCR_ZE));
  if (excepts & FE_UNDERFLOW)
    fe.l[1] &= ~(1 << (31 - FPSCR_UE));
  if (excepts & FE_OVERFLOW)
    fe.l[1] &= ~(1 << (31 - FPSCR_OE));
  if (excepts & FE_INVALID)
    fe.l[1] &= ~(1 << (31 - FPSCR_VE));
  fesetenv_register (fe.fenv);

  if ((fegetexcept () & excepts) != 0)
    result = -1;
  return result;
}
示例#4
0
int
__FERAISEEXCEPT_INTERNAL (int excepts)
{
  unsigned long f;

  f = fegetenv_register ();
  f |= (excepts & SPEFSCR_ALL_EXCEPT);
  fesetenv_register (f);

  /* Force the operations that cause the exceptions.  */
  if ((SPEFSCR_FINVS & excepts) != 0)
    /* 0 / 0 */
    asm volatile ("efsdiv %0,%0,%1" : : "r" (0), "r" (0));

  if ((SPEFSCR_FDBZS & excepts) != 0)
    /* 1.0 / 0.0 */
    asm volatile ("efsdiv %0,%0,%1" : : "r" (1.0F), "r" (0));

  if ((SPEFSCR_FOVFS & excepts) != 0)
    /* Largest normalized number plus itself.  */
    asm volatile ("efsadd %0,%0,%1" : : "r" (0x7f7fffff), "r" (0x7f7fffff));

  if ((SPEFSCR_FUNFS & excepts) != 0)
    /* Smallest normalized number times itself.  */
    asm volatile ("efsmul %0,%0,%1" : : "r" (0x800000), "r" (0x800000));

  if ((SPEFSCR_FINXS & excepts) != 0)
    /* Smallest normalized minus 1.0 raises the inexact flag.  */
    asm volatile ("efssub %0,%0,%1" : : "r" (0x00800000), "r" (1.0F));

  /* Success.  */
  return 0;
}
示例#5
0
int
__feholdexcept (fenv_t *envp)
{
  fenv_union_t u;
  INTERNAL_SYSCALL_DECL (err);
  int r;

  /* Get the current state.  */
  r = INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &u.l[0]);
  if (INTERNAL_SYSCALL_ERROR_P (r, err))
    return -1;

  u.l[1] = fegetenv_register ();
  *envp = u.fenv;

  /* Clear everything except for the rounding mode and trapping to the
     kernel.  */
  u.l[0] &= ~(PR_FP_EXC_DIV
	      | PR_FP_EXC_OVF
	      | PR_FP_EXC_UND
	      | PR_FP_EXC_RES
	      | PR_FP_EXC_INV);
  u.l[1] &= SPEFSCR_FRMC | (SPEFSCR_ALL_EXCEPT_ENABLE & ~SPEFSCR_FINXE);

  /* Put the new state in effect.  */
  fesetenv_register (u.l[1]);
  r = INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC,
			u.l[0] | PR_FP_EXC_SW_ENABLE);
  if (INTERNAL_SYSCALL_ERROR_P (r, err))
    return -1;

  return 0;
}
示例#6
0
int
__fesetexceptflag (const fexcept_t *flagp, int excepts)
{
  unsigned long old_spefscr, spefscr;
  fexcept_t flag;
  int excepts_spe = __fexcepts_to_spe (excepts);

  /* Get the current state.  */
  old_spefscr = fegetenv_register ();

  /* Ignore exceptions not listed in 'excepts'.  */
  flag = *flagp & excepts_spe;

  /* Replace the exception status */
  spefscr = (old_spefscr & ~excepts_spe) | flag;

  /* Store the new status word (along with the rest of the environment).  */
  fesetenv_register (spefscr);

  /* If the state of the "invalid" or "underflow" flag has changed,
     inform the kernel.  */
  if (((spefscr ^ old_spefscr) & (SPEFSCR_FINVS | SPEFSCR_FUNFS)) != 0)
    __fe_note_change ();

  /* Success.  */
  return 0;
}
示例#7
0
int
__fegetenv (fenv_t *envp)
{
  *envp = fegetenv_register ();

  /* Success.  */
  return 0;
}
示例#8
0
int
fegetround (void)
{
  unsigned long fpescr;

  fpescr = fegetenv_register ();
  return fpescr & 3;
}
示例#9
0
int
fetestexcept (int excepts)
{
  unsigned long f;

  /* Get the current state.  */
  f = fegetenv_register ();

  return __fexcepts_from_spe (f) & excepts;
}
示例#10
0
int
fetestexcept (int excepts)
{
  unsigned long f;

  /* Get the current state.  */
  f = fegetenv_register ();

  return f & excepts;
}
示例#11
0
int
fetestexcept (int excepts)
{
  fenv_union_t u;

  /* Get the current state.  */
  u.fenv = fegetenv_register ();

  /* The FE_INVALID bit is dealt with correctly by the hardware, so we can
     just:  */
  return u.l[1] & excepts;
}
示例#12
0
int
__fegetenv (fenv_t *envp)
{
  fenv_union_t u;
  INTERNAL_SYSCALL_DECL (err);

  INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &u.l[0]);
  u.l[1] = fegetenv_register ();
  *envp = u.fenv;

  /* Success.  */
  return 0;
}
示例#13
0
int
__fegetexceptflag (fexcept_t *flagp, int excepts)
{
  unsigned long fpescr;

  /* Get the current state.  */
  fpescr = fegetenv_register ();

  *flagp = fpescr & SPEFSCR_ALL_EXCEPT;

  /* Success.  */
  return 0;
}
示例#14
0
int
__fegetexceptflag (fexcept_t *flagp, int excepts)
{
  fenv_union_t u;

  /* Get the current state.  */
  u.fenv = fegetenv_register ();

  /* Return (all of) it.  */
  *flagp = u.l[1] & excepts & FE_ALL_EXCEPT;

  /* Success.  */
  return 0;
}
示例#15
0
int
__fegetexceptflag (fexcept_t *flagp, int excepts)
{
  unsigned long fpescr;

  /* Get the current state.  */
  fpescr = fegetenv_register ();

  /* ?? Classic PPC doesn't do anything with `excepts', so we'll do
     the same here.  (We should really be ignoring exceptions in
     excepts) ??  */
  *flagp = fpescr & FE_ALL_EXCEPT;

  /* Success.  */
  return 0;
}
int
feholdexcept (fenv_t *envp)
{
  fenv_union_t u;

  /* Get the current state.  */
  u.fenv = *envp = fegetenv_register ();

  /* Clear everything except for the rounding mode and non-IEEE arithmetic
     flag.  */
  u.l[1] = u.l[1] & 7;

  /* Put the new state in effect.  */
  fesetenv_register (u.fenv);

  return 0;
}
示例#17
0
文件: spe-raise.c 项目: OPSF/uClinux
int
__FERAISEEXCEPT_INTERNAL (int excepts)
{
  unsigned long f;

  f = fegetenv_register ();
  f |= (excepts & FE_ALL_EXCEPT);
  fesetenv_register (f);

  /* Force the operations that cause the exceptions.  */
  if ((FE_INVALID & excepts) != 0)
    {
      /* ?? Does not set sticky bit ?? */
      /* 0 / 0 */
      asm volatile ("efsdiv %0,%0,%1" : : "r" (0), "r" (0));
    }

  if ((FE_DIVBYZERO & excepts) != 0)
    {
      /* 1.0 / 0.0 */
      asm volatile ("efsdiv %0,%0,%1" : : "r" (1.0F), "r" (0));
    }

  if ((FE_OVERFLOW & excepts) != 0)
    {
      /* ?? Does not set sticky bit ?? */
      /* Largest normalized number plus itself.  */
      asm volatile ("efsadd %0,%0,%1" : : "r" (0x7f7fffff), "r" (0x7f7fffff));
    }

  if ((FE_UNDERFLOW & excepts) != 0)
    {
      /* ?? Does not set sticky bit ?? */
      /* Smallest normalized number times itself.  */
      asm volatile ("efsmul %0,%0,%1" : : "r" (0x800000), "r" (0x800000));
    }

  if ((FE_INEXACT & excepts) != 0)
    {
      /* Smallest normalized minus 1.0 raises the inexact flag.  */
      asm volatile ("efssub %0,%0,%1" : : "r" (0x00800000), "r" (1.0F));
    }

  /* Success.  */
  return 0;
}
示例#18
0
int
__feupdateenv (const fenv_t *envp)
{
  int exc;

  /* Save the currently set exceptions.  */
  exc = fegetenv_register () & SPEFSCR_ALL_EXCEPT;

  /* Install new environment.  */
  __fesetenv (envp);

  /* Raise (if appropriate) saved exceptions. */
  __feraiseexcept_spe (exc);

  /* Success.  */
  return 0;
}
示例#19
0
int
__flt_rounds (void)
{
  switch (fegetenv_register () & SPEFSCR_FRMC)
    {
    case FE_TOWARDZERO:
      return 0;
    case FE_TONEAREST:
      return 1;
    case FE_UPWARD:
      return 2;
    case FE_DOWNWARD:
      return 3;
    default:
      abort ();
    }
}
示例#20
0
int
feholdexcept (fenv_t *envp)
{
  fenv_union_t u;
  INTERNAL_SYSCALL_DECL (err);


  /* Get the current state.  */
  INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &u.l[0]);
  u.l[1] = fegetenv_register ();
  *envp = u.fenv;

  /* Clear everything except for the rounding mode.  */
  u.l[1] &= 3;

  /* Put the new state in effect.  */
  fesetenv_register (u.l[1]);

  return 0;
}
示例#21
0
int
__fegetexcept (void)
{
  fenv_union_t fe;
  int result = 0;

  fe.fenv = fegetenv_register ();

  if (fe.l & (1 << (31 - FPSCR_XE)))
      result |= FE_INEXACT;
  if (fe.l & (1 << (31 - FPSCR_ZE)))
      result |= FE_DIVBYZERO;
  if (fe.l & (1 << (31 - FPSCR_UE)))
      result |= FE_UNDERFLOW;
  if (fe.l & (1 << (31 - FPSCR_OE)))
      result |= FE_OVERFLOW;
  if (fe.l & (1 << (31 - FPSCR_VE)))
      result |= FE_INVALID;

  return result;
}
示例#22
0
int
__feclearexcept (int excepts)
{
  unsigned int fpescr;
  int excepts_spe = __fexcepts_to_spe (excepts);

  /* Get the current state.  */
  fpescr = fegetenv_register ();

  /* Clear the relevant bits.  */
  fpescr &= ~excepts_spe;

  /* Put the new state in effect.  */
  fesetenv_register (fpescr);

  /* Let the kernel know if the "invalid" or "underflow" bit was
     cleared.  */
  if (excepts & (FE_INVALID | FE_UNDERFLOW))
    __fe_note_change ();

  /* Success.  */
  return 0;
}
示例#23
0
int
__fesetexceptflag (const fexcept_t *flagp, int excepts)
{
  unsigned long spefscr;
  fexcept_t flag;

  /* Get the current state.  */
  spefscr = fegetenv_register ();

  /* Ignore exceptions not listed in 'excepts'.  */
  flag = *flagp & excepts;

  /* Replace the exception status */
  spefscr = (spefscr & ~FE_ALL_EXCEPT) | flag;

  /* Store the new status word (along with the rest of the environment).
     This may cause floating-point exceptions if the restored state
     requests it.  */
  fesetenv_register (spefscr);
  feraiseexcept (spefscr & FE_ALL_EXCEPT);

  /* Success.  */
  return 0;
}
示例#24
0
   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <http://www.gnu.org/licenses/>.  */

#include <fenv_libc.h>
#include <fpu_control.h>
#define _FPU_MASK_ALL (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM | _FPU_MASK_XM | _FPU_MASK_IM)

int
feholdexcept (fenv_t *envp)
{
  fenv_union_t old, new;

  /* Save the currently set exceptions.  */
  old.fenv = *envp = fegetenv_register ();

  /* Clear everything except for the rounding modes and non-IEEE arithmetic
     flag.  */
  new.l = old.l & 0xffffffff00000007LL;

  /* If the old env had any enabled exceptions, then mask SIGFPE in the
     MSR FE0/FE1 bits.  This may allow the FPU to run faster because it
     always takes the default action and can not generate SIGFPE. */
  if ((old.l & _FPU_MASK_ALL) != 0)
    (void)__fe_mask_env ();

  /* Put the new state in effect.  */
  fesetenv_register (new.fenv);

  return 0;