/*-1* SPDX-License-Identifier: BSD-4-Clause2*3* Copyright (c) 2003 Peter Wemm.4* Copyright (c) 1990 Andrew Moore, Talke Studio5* All rights reserved.6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions9* are met:10* 1. Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer.12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15* 3. All advertising materials mentioning features or use of this software16* must display the following acknowledgement:17* This product includes software developed by the University of18* California, Berkeley and its contributors.19* 4. Neither the name of the University nor the names of its contributors20* may be used to endorse or promote products derived from this software21* without specific prior written permission.22*23* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND24* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE25* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE26* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE27* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL28* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS29* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)30* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT31* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY32* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF33* SUCH DAMAGE.34*/3536#ifndef _MACHINE_IEEEFP_H_37#define _MACHINE_IEEEFP_H_3839/* Deprecated historical FPU control interface */4041#include <x86/x86_ieeefp.h>4243/*44* IEEE floating point type, constant and function definitions.45* XXX: {FP,SSE}*FLD and {FP,SSE}*OFF are undocumented pollution.46*/4748/*49* SSE mxcsr register bit-field masks.50*/51#define SSE_STKY_FLD 0x3f /* exception flags */52#define SSE_DAZ_FLD 0x40 /* Denormals are zero */53#define SSE_MSKS_FLD 0x1f80 /* exception masks field */54#define SSE_RND_FLD 0x6000 /* rounding control */55#define SSE_FZ_FLD 0x8000 /* flush to zero on underflow */5657/*58* SSE mxcsr register bit-field offsets (shift counts).59*/60#define SSE_STKY_OFF 0 /* exception flags offset */61#define SSE_DAZ_OFF 6 /* DAZ exception mask offset */62#define SSE_MSKS_OFF 7 /* other exception masks offset */63#define SSE_RND_OFF 13 /* rounding control offset */64#define SSE_FZ_OFF 15 /* flush to zero offset */6566/*67* General notes about conflicting SSE vs FP status bits.68* This code assumes that software will not fiddle with the control69* bits of the SSE and x87 in such a way to get them out of sync and70* still expect this to work. Break this at your peril.71* Because I based this on the i386 port, the x87 state is used for72* the fpget*() functions, and is shadowed into the SSE state for73* the fpset*() functions. For dual source fpget*() functions, I74* merge the two together. I think.75*/7677static __inline fp_rnd_t78__fpgetround(void)79{80unsigned short _cw;8182__fnstcw(&_cw);83return ((fp_rnd_t)((_cw & FP_RND_FLD) >> FP_RND_OFF));84}8586static __inline fp_rnd_t87__fpsetround(fp_rnd_t _m)88{89fp_rnd_t _p;90unsigned _mxcsr;91unsigned short _cw, _newcw;9293__fnstcw(&_cw);94_p = (fp_rnd_t)((_cw & FP_RND_FLD) >> FP_RND_OFF);95_newcw = _cw & ~FP_RND_FLD;96_newcw |= (_m << FP_RND_OFF) & FP_RND_FLD;97__fnldcw(_cw, _newcw);98__stmxcsr(&_mxcsr);99_mxcsr &= ~SSE_RND_FLD;100_mxcsr |= (_m << SSE_RND_OFF) & SSE_RND_FLD;101__ldmxcsr(&_mxcsr);102return (_p);103}104105/*106* Get or set the rounding precision for x87 arithmetic operations.107* There is no equivalent SSE mode or control.108*/109110static __inline fp_prec_t111__fpgetprec(void)112{113unsigned short _cw;114115__fnstcw(&_cw);116return ((fp_prec_t)((_cw & FP_PRC_FLD) >> FP_PRC_OFF));117}118119static __inline fp_prec_t120__fpsetprec(fp_prec_t _m)121{122fp_prec_t _p;123unsigned short _cw, _newcw;124125__fnstcw(&_cw);126_p = (fp_prec_t)((_cw & FP_PRC_FLD) >> FP_PRC_OFF);127_newcw = _cw & ~FP_PRC_FLD;128_newcw |= (_m << FP_PRC_OFF) & FP_PRC_FLD;129__fnldcw(_cw, _newcw);130return (_p);131}132133/*134* Get or set the exception mask.135* Note that the x87 mask bits are inverted by the API -- a mask bit of 1136* means disable for x87 and SSE, but for fp*mask() it means enable.137*/138139static __inline fp_except_t140__fpgetmask(void)141{142unsigned short _cw;143144__fnstcw(&_cw);145return ((~_cw & FP_MSKS_FLD) >> FP_MSKS_OFF);146}147148static __inline fp_except_t149__fpsetmask(fp_except_t _m)150{151fp_except_t _p;152unsigned _mxcsr;153unsigned short _cw, _newcw;154155__fnstcw(&_cw);156_p = (~_cw & FP_MSKS_FLD) >> FP_MSKS_OFF;157_newcw = _cw & ~FP_MSKS_FLD;158_newcw |= (~_m << FP_MSKS_OFF) & FP_MSKS_FLD;159__fnldcw(_cw, _newcw);160__stmxcsr(&_mxcsr);161/* XXX should we clear non-ieee SSE_DAZ_FLD and SSE_FZ_FLD ? */162_mxcsr &= ~SSE_MSKS_FLD;163_mxcsr |= (~_m << SSE_MSKS_OFF) & SSE_MSKS_FLD;164__ldmxcsr(&_mxcsr);165return (_p);166}167168static __inline fp_except_t169__fpgetsticky(void)170{171unsigned _ex, _mxcsr;172unsigned short _sw;173174__fnstsw(&_sw);175_ex = (_sw & FP_STKY_FLD) >> FP_STKY_OFF;176__stmxcsr(&_mxcsr);177_ex |= (_mxcsr & SSE_STKY_FLD) >> SSE_STKY_OFF;178return ((fp_except_t)_ex);179}180181#if !defined(__IEEEFP_NOINLINES__)182183#define fpgetmask() __fpgetmask()184#define fpgetprec() __fpgetprec()185#define fpgetround() __fpgetround()186#define fpgetsticky() __fpgetsticky()187#define fpsetmask(m) __fpsetmask(m)188#define fpsetprec(m) __fpsetprec(m)189#define fpsetround(m) __fpsetround(m)190191#else /* __IEEEFP_NOINLINES__ */192193/* Augment the userland declarations. */194__BEGIN_DECLS195extern fp_rnd_t fpgetround(void);196extern fp_rnd_t fpsetround(fp_rnd_t);197extern fp_except_t fpgetmask(void);198extern fp_except_t fpsetmask(fp_except_t);199extern fp_except_t fpgetsticky(void);200extern fp_except_t fpsetsticky(fp_except_t);201fp_prec_t fpgetprec(void);202fp_prec_t fpsetprec(fp_prec_t);203__END_DECLS204205#endif /* !__IEEEFP_NOINLINES__ */206207#endif /* !_MACHINE_IEEEFP_H_ */208209210