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:
parent
98a80542e7
commit
f107f876a6
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=175233
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user