1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-20 11:11:24 +00:00

Separate fpresetsticky() from the other fpset functions so that the

others can be replaced cleanly by the amd64 versions.   There is no
current amd64 version to merge, but there is an old one which is
similar.

Fix the following bugs in fpresetsticky():
- garbage args clobbered non-sticky bits in the status register
- the return value was usually garbage since it was masked with the
  arg instead of with the field selector.

Optimize fpresetsticky() to avoid using the environment as in
feclearexcept() (use only fnclex() if possible) and also to avoid
using fnclex() for null changes.  The second of these optimizations
might not be so good since its branch might cost more than it saves.
This commit is contained in:
Bruce Evans 2008-01-11 18:27:01 +00:00
parent 98a80542e7
commit f107f876a6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=175233

View File

@ -115,6 +115,7 @@ typedef enum {
#ifdef __GNUCLIKE_ASM
#define __fldenv(addr) __asm __volatile("fldenv %0" : : "m" (*(addr)))
#define __fnclex() __asm __volatile("fnclex")
#define __fnstcw(addr) __asm __volatile("fnstcw %0" : "=m" (*(addr)))
#define __fnstenv(addr) __asm __volatile("fnstenv %0" : "=m" (*(addr)))
#define __fnstsw(addr) __asm __volatile("fnstsw %0" : "=m" (*(addr)))
@ -165,8 +166,6 @@ __fpsetreg(int _m, int _reg, int _fld, int _off)
return _p;
}
#endif /* __GNUCLIKE_ASM */
/*
* SysV/386 FP control interface
*/
@ -185,8 +184,32 @@ __fpsetreg(int _m, int _reg, int _fld, int _off)
(FP_MSKS_FLD >> FP_MSKS_OFF))
#define fpgetsticky() ((fp_except_t) \
((__fpgetreg(FP_STKY_REG) & FP_STKY_FLD) >> FP_STKY_OFF))
#define fpresetsticky(m) ((fp_except_t) \
__fpsetreg(0, FP_STKY_REG, (m), FP_STKY_OFF))
static __inline fp_except_t
fpresetsticky(fp_except_t _m)
{
struct {
unsigned _cw;
unsigned _sw;
unsigned _other[5];
} _env;
fp_except_t _p;
_m &= FP_STKY_FLD >> FP_STKY_OFF;
_p = fpgetsticky();
if ((_p & ~_m) == _p)
return (_p);
if ((_p & ~_m) == 0) {
__fnclex();
return (_p);
}
__fnstenv(&_env);
_env._sw &= ~_m;
__fldenv(&_env);
return (_p);
}
#endif /* __GNUCLIKE_ASM */
/* Suppress prototypes in the MI header. */
#define _IEEEFP_INLINED_ 1