Skip to content

Commit

Permalink
Reverted fenv back to working changes
Browse files Browse the repository at this point in the history
  • Loading branch information
afxgroup committed Jul 27, 2023
1 parent 8278c1b commit ca1e102
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 568 deletions.
209 changes: 184 additions & 25 deletions library/include/fenv.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
#include <features.h>
#include <endian.h>

#ifndef __fenv_static
#define __fenv_static static
#endif

typedef uint32_t fenv_t;
typedef uint32_t fexcept_t;

Expand Down Expand Up @@ -58,46 +62,201 @@ extern const fenv_t __fe_dfl_env;
#define _FPUSW_SHIFT 22
#define _ENABLE_MASK ((FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) >> _FPUSW_SHIFT)

#ifndef _SOFT_FLOAT
#ifdef __SPE__
#define __mffs(__env) __asm __volatile("mfspr %0, 512" : "=r" (*(__env)))
#define __mtfsf(__env) __asm __volatile("mtspr 512, %0; isync" :: "r" ((__env)))
#define __mffs(__env) \
__asm __volatile("mfspr %0, 512" : "=r" ((__env)->__bits.__reg))
#define __mtfsf(__env) \
__asm __volatile("mtspr 512,%0;isync" :: "r" ((__env).__bits.__reg))
#else
/* Equivalent to fegetenv, but returns an unsigned int instead of taking a pointer. */
#define fegetenv_register() \
({ unsigned int fscr; asm volatile ("mfspefscr %0" : "=r" (fscr)); fscr; })

/* Equivalent to fesetenv, but takes an unsigned int instead of a pointer. */
#define fesetenv_register(fscr) \
({ asm volatile ("mtspefscr %0" : : "r" (fscr)); })
#define __mffs(__env) \
__asm __volatile("mffs %0" : "=f" ((__env)->__d))
#define __mtfsf(__env) \
__asm __volatile("mtfsf 255,%0" :: "f" ((__env).__d))
#endif
#else
#define __mffs(__env)
#define __mtfsf(__env)
#endif

union __fpscr {
double __d;
struct {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#if __BYTE_ORDER__ == LITTLE_ENDIAN
fenv_t __reg;
uint32_t __junk;
#else
uint32_t __junk;
fenv_t __reg;
fenv_t __reg;
#endif
} __bits;
};

extern int feclearexcept(int __excepts);
extern int fegetexceptflag(fexcept_t *__flagp, int __excepts);
extern int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
extern int feraiseexcept(int __excepts);
extern int fetestexcept(int __excepts);
extern int fegetround(void);
extern int fesetround(int __round);
extern int fegetenv(fenv_t *__envp);
extern int feholdexcept(fenv_t *__envp);
extern int fesetenv(const fenv_t *__envp);
extern int feupdateenv(const fenv_t *__envp);
extern int fegetexcept(void);
extern int feenableexcept(int __mask);
extern int fedisableexcept(int __mask);
__fenv_static inline int
feclearexcept(int __excepts)
{
union __fpscr __r;

if (__excepts & FE_INVALID)
__excepts |= FE_ALL_INVALID;
__mffs(&__r);
__r.__bits.__reg &= ~__excepts;
__mtfsf(__r);
return (0);
}

__fenv_static inline int
fegetexceptflag(fexcept_t *__flagp, int __excepts)
{
union __fpscr __r;

__mffs(&__r);
*__flagp = __r.__bits.__reg & __excepts;
return (0);
}

__fenv_static inline int
fesetexceptflag(const fexcept_t *__flagp, int __excepts)
{
union __fpscr __r;

if (__excepts & FE_INVALID)
__excepts |= FE_ALL_INVALID;
__mffs(&__r);
__r.__bits.__reg &= ~__excepts;
__r.__bits.__reg |= *__flagp & __excepts;
__mtfsf(__r);
return (0);
}

#ifdef __SPE__
extern int feraiseexcept(int __excepts);
#else
__fenv_static inline int
feraiseexcept(int __excepts)
{
union __fpscr __r;

if (__excepts & FE_INVALID)
__excepts |= FE_VXSOFT;
__mffs(&__r);
__r.__bits.__reg |= __excepts;
__mtfsf(__r);
return (0);
}
#endif

__fenv_static inline int
fetestexcept(int __excepts)
{
union __fpscr __r;

__mffs(&__r);
return (__r.__bits.__reg & __excepts);
}

__fenv_static inline int
fegetround(void)
{
union __fpscr __r;

__mffs(&__r);
return (__r.__bits.__reg & _ROUND_MASK);
}

__fenv_static inline int
fesetround(int __round)
{
union __fpscr __r;

if (__round & ~_ROUND_MASK)
return (-1);
__mffs(&__r);
__r.__bits.__reg &= ~_ROUND_MASK;
__r.__bits.__reg |= __round;
__mtfsf(__r);
return (0);
}

__fenv_static inline int
fegetenv(fenv_t *__envp)
{
union __fpscr __r;

__mffs(&__r);
*__envp = __r.__bits.__reg;
return (0);
}

__fenv_static inline int
feholdexcept(fenv_t *__envp)
{
union __fpscr __r;

__mffs(&__r);
*__envp = __r.__bits.__reg;
__r.__bits.__reg &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
__mtfsf(__r);
return (0);
}

__fenv_static inline int
fesetenv(const fenv_t *__envp)
{
union __fpscr __r;

__r.__bits.__reg = *__envp;
__mtfsf(__r);
return (0);
}

__fenv_static inline int
feupdateenv(const fenv_t *__envp)
{
union __fpscr __r;

__mffs(&__r);
__r.__bits.__reg &= FE_ALL_EXCEPT;
__r.__bits.__reg |= *__envp;
__mtfsf(__r);
return (0);
}

__fenv_static inline int
feenableexcept(int __mask)
{
union __fpscr __r;
fenv_t __oldmask;

__mffs(&__r);
__oldmask = __r.__bits.__reg;
__r.__bits.__reg |= (__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT;
__mtfsf(__r);
return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
}

__fenv_static inline int
fedisableexcept(int __mask)
{
union __fpscr __r;
fenv_t __oldmask;

__mffs(&__r);
__oldmask = __r.__bits.__reg;
__r.__bits.__reg &= ~((__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT);
__mtfsf(__r);
return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
}

/* We currently provide no external definition of fegetexcept(). */
static inline int
fegetexcept(void)
{
union __fpscr __r;

__mffs(&__r);
return ((__r.__bits.__reg & _ENABLE_MASK) << _FPUSW_SHIFT);
}

__END_DECLS

Expand Down
Loading

0 comments on commit ca1e102

Please sign in to comment.