fenv.c raw

   1  #define _GNU_SOURCE
   2  #include <fenv.h>
   3  #include <features.h>
   4  
   5  static inline double get_fpscr_f(void)
   6  {
   7  	double d;
   8  	__asm__ __volatile__("mffs %0" : "=d"(d));
   9  	return d;
  10  }
  11  
  12  static inline long get_fpscr(void)
  13  {
  14  	return (union {double f; long i;}) {get_fpscr_f()}.i;
  15  }
  16  
  17  static inline void set_fpscr_f(double fpscr)
  18  {
  19  	__asm__ __volatile__("mtfsf 255, %0" : : "d"(fpscr));
  20  }
  21  
  22  static void set_fpscr(long fpscr)
  23  {
  24  	set_fpscr_f((union {long i; double f;}) {fpscr}.f);
  25  }
  26  
  27  int feclearexcept(int mask)
  28  {
  29  	mask &= FE_ALL_EXCEPT;
  30  	if (mask & FE_INVALID) mask |= FE_ALL_INVALID;
  31  	set_fpscr(get_fpscr() & ~mask);
  32  	return 0;
  33  }
  34  
  35  int feraiseexcept(int mask)
  36  {
  37  	mask &= FE_ALL_EXCEPT;
  38  	if (mask & FE_INVALID) mask |= FE_INVALID_SOFTWARE;
  39  	set_fpscr(get_fpscr() | mask);
  40  	return 0;
  41  }
  42  
  43  int fetestexcept(int mask)
  44  {
  45  	return get_fpscr() & mask & FE_ALL_EXCEPT;
  46  }
  47  
  48  int fegetround(void)
  49  {
  50  	return get_fpscr() & 3;
  51  }
  52  
  53  hidden int __fesetround(int r)
  54  {
  55  	set_fpscr(get_fpscr() & ~3L | r);
  56  	return 0;
  57  }
  58  
  59  int fegetenv(fenv_t *envp)
  60  {
  61  	*envp = get_fpscr_f();
  62  	return 0;
  63  }
  64  
  65  int fesetenv(const fenv_t *envp)
  66  {
  67  	set_fpscr_f(envp != FE_DFL_ENV ? *envp : 0);
  68  	return 0;
  69  }
  70