ieeefp.h revision 175180
11834Swollman/*- 2122296Speter * Copyright (c) 2003 Peter Wemm. 31834Swollman * Copyright (c) 1990 Andrew Moore, Talke Studio 41834Swollman * All rights reserved. 51834Swollman * 61834Swollman * Redistribution and use in source and binary forms, with or without 71834Swollman * modification, are permitted provided that the following conditions 81834Swollman * are met: 91834Swollman * 1. Redistributions of source code must retain the above copyright 101834Swollman * notice, this list of conditions and the following disclaimer. 111834Swollman * 2. Redistributions in binary form must reproduce the above copyright 121834Swollman * notice, this list of conditions and the following disclaimer in the 131834Swollman * documentation and/or other materials provided with the distribution. 141834Swollman * 3. All advertising materials mentioning features or use of this software 151834Swollman * must display the following acknowledgement: 161834Swollman * This product includes software developed by the University of 171834Swollman * California, Berkeley and its contributors. 181834Swollman * 4. Neither the name of the University nor the names of its contributors 191834Swollman * may be used to endorse or promote products derived from this software 201834Swollman * without specific prior written permission. 211834Swollman * 221834Swollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 231834Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 241834Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 251834Swollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 261834Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 271834Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 281834Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 291834Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 301834Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 311834Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 321834Swollman * SUCH DAMAGE. 331834Swollman * 341834Swollman * from: @(#) ieeefp.h 1.0 (Berkeley) 9/23/93 3550477Speter * $FreeBSD: head/sys/amd64/include/ieeefp.h 175180 2008-01-09 15:03:03Z bde $ 361834Swollman */ 371834Swollman 38175178Sbde#ifndef _MACHINE_IEEEFP_H_ 39175178Sbde#define _MACHINE_IEEEFP_H_ 40175178Sbde 411834Swollman/* 42175178Sbde * IEEE floating point type, constant and function definitions. 431834Swollman */ 441834Swollman 45143063Sjoerg#ifndef _SYS_CDEFS_H_ 46143063Sjoerg#error this file needs sys/cdefs.h as a prerequisite 47143063Sjoerg#endif 48143063Sjoerg 491834Swollman/* 501834Swollman * FP rounding modes 511834Swollman */ 521834Swollmantypedef enum { 531834Swollman FP_RN=0, /* round to nearest */ 541834Swollman FP_RM, /* round down to minus infinity */ 551834Swollman FP_RP, /* round up to plus infinity */ 561834Swollman FP_RZ /* truncate */ 571834Swollman} fp_rnd_t; 581834Swollman 591834Swollman/* 6013765Smpp * FP precision modes 611834Swollman */ 621834Swollmantypedef enum { 6313765Smpp FP_PS=0, /* 24 bit (single-precision) */ 641834Swollman FP_PRS, /* reserved */ 651834Swollman FP_PD, /* 53 bit (double-precision) */ 6613765Smpp FP_PE /* 64 bit (extended-precision) */ 671834Swollman} fp_prec_t; 681834Swollman 691834Swollman#define fp_except_t int 701834Swollman 711834Swollman/* 721834Swollman * FP exception masks 731834Swollman */ 741834Swollman#define FP_X_INV 0x01 /* invalid operation */ 751834Swollman#define FP_X_DNML 0x02 /* denormal */ 761834Swollman#define FP_X_DZ 0x04 /* zero divide */ 771834Swollman#define FP_X_OFL 0x08 /* overflow */ 781834Swollman#define FP_X_UFL 0x10 /* underflow */ 791834Swollman#define FP_X_IMP 0x20 /* (im)precision */ 8049081Scracauer#define FP_X_STK 0x40 /* stack fault */ 811834Swollman 821834Swollman/* 831834Swollman * FP registers 841834Swollman */ 851834Swollman#define FP_MSKS_REG 0 /* exception masks */ 861834Swollman#define FP_PRC_REG 0 /* precision */ 871834Swollman#define FP_RND_REG 0 /* direction */ 881834Swollman#define FP_STKY_REG 1 /* sticky flags */ 891834Swollman 901834Swollman/* 911834Swollman * FP register bit field masks 921834Swollman */ 931834Swollman#define FP_MSKS_FLD 0x3f /* exception masks field */ 941834Swollman#define FP_PRC_FLD 0x300 /* precision control field */ 951834Swollman#define FP_RND_FLD 0xc00 /* round control field */ 961834Swollman#define FP_STKY_FLD 0x3f /* sticky flags field */ 971834Swollman 981834Swollman/* 99117863Speter * SSE mxcsr register bit field masks 100117863Speter */ 101117863Speter#define SSE_STKY_FLD 0x3f /* exception flags */ 102117863Speter#define SSE_DAZ_FLD 0x40 /* Denormals are zero */ 103117863Speter#define SSE_MSKS_FLD 0x1f80 /* exception masks field */ 104117863Speter#define SSE_RND_FLD 0x6000 /* rounding control */ 105117863Speter#define SSE_FZ_FLD 0x8000 /* flush to zero on underflow */ 106117863Speter 107117863Speter/* 1081834Swollman * FP register bit field offsets 1091834Swollman */ 1101834Swollman#define FP_MSKS_OFF 0 /* exception masks offset */ 1111834Swollman#define FP_PRC_OFF 8 /* precision control offset */ 1121834Swollman#define FP_RND_OFF 10 /* round control offset */ 1131834Swollman#define FP_STKY_OFF 0 /* sticky flags offset */ 1141834Swollman 115117863Speter/* 116117863Speter * SSE mxcsr register bit field offsets 117117863Speter */ 118117863Speter#define SSE_STKY_OFF 0 /* exception flags offset */ 119117863Speter#define SSE_DAZ_OFF 6 /* DAZ exception mask offset */ 120117863Speter#define SSE_MSKS_OFF 7 /* other exception masks offset */ 121117863Speter#define SSE_RND_OFF 13 /* rounding control offset */ 122117863Speter#define SSE_FZ_OFF 15 /* flush to zero offset */ 123109520Smarcel 124175180Sbde#ifdef __GNUCLIKE_ASM 125117863Speter 126175179Sbde#define __fldcw(addr) __asm __volatile("fldcw %0" : : "m" (*(addr))) 127175179Sbde#define __fnstcw(addr) __asm __volatile("fnstcw %0" : "=m" (*(addr))) 128109520Smarcel#define __fnstsw(addr) __asm __volatile("fnstsw %0" : "=m" (*(addr))) 129144968Sjhb#define __ldmxcsr(addr) __asm __volatile("ldmxcsr %0" : : "m" (*(addr))) 130117863Speter#define __stmxcsr(addr) __asm __volatile("stmxcsr %0" : "=m" (*(addr))) 131109520Smarcel 132109520Smarcel/* 133117863Speter * General notes about conflicting SSE vs FP status bits. 134117863Speter * This code assumes that software will not fiddle with the control 135117863Speter * bits of the SSE and x87 in such a way to get them out of sync and 136117863Speter * still expect this to work. Break this at your peril. 137117863Speter * Because I based this on the i386 port, the x87 state is used for 138117863Speter * the fpget*() functions, and is shadowed into the SSE state for 139117863Speter * the fpset*() functions. For dual source fpget*() functions, I 140117863Speter * merge the two together. I think. 141109520Smarcel */ 142117863Speter 143175179Sbdestatic __inline fp_rnd_t 144117863Speter__fpgetround(void) 145109520Smarcel{ 146117863Speter unsigned short _cw; 147109520Smarcel 148117863Speter __fnstcw(&_cw); 149175180Sbde return ((fp_rnd_t)((_cw & FP_RND_FLD) >> FP_RND_OFF)); 150109520Smarcel} 151109520Smarcel 152175179Sbdestatic __inline fp_rnd_t 153117863Speter__fpsetround(fp_rnd_t _m) 154117863Speter{ 155175180Sbde fp_rnd_t _p; 156175180Sbde unsigned _mxcsr; 157117863Speter unsigned short _cw; 158117863Speter 159117863Speter __fnstcw(&_cw); 160175180Sbde _p = (fp_rnd_t)((_cw & FP_RND_FLD) >> FP_RND_OFF); 161117863Speter _cw &= ~FP_RND_FLD; 162117863Speter _cw |= (_m << FP_RND_OFF) & FP_RND_FLD; 163117863Speter __fldcw(&_cw); 164117863Speter __stmxcsr(&_mxcsr); 165117863Speter _mxcsr &= ~SSE_RND_FLD; 166117863Speter _mxcsr |= (_m << SSE_RND_OFF) & SSE_RND_FLD; 167117863Speter __ldmxcsr(&_mxcsr); 168117863Speter return (_p); 169117863Speter} 170117863Speter 171109520Smarcel/* 172175178Sbde * Get or set the rounding precision for x87 arithmetic operations. 173117863Speter * There is no equivalent SSE mode or control. 174109520Smarcel */ 175175178Sbde 176175179Sbdestatic __inline fp_prec_t 177117863Speter__fpgetprec(void) 178109520Smarcel{ 179117863Speter unsigned short _cw; 180117863Speter 181117863Speter __fnstcw(&_cw); 182175180Sbde return ((fp_prec_t)((_cw & FP_PRC_FLD) >> FP_PRC_OFF)); 183117863Speter} 184117863Speter 185175179Sbdestatic __inline fp_prec_t 186175180Sbde__fpsetprec(fp_prec_t _m) 187117863Speter{ 188175179Sbde fp_prec_t _p; 189117863Speter unsigned short _cw; 190117863Speter 191117863Speter __fnstcw(&_cw); 192175180Sbde _p = (fp_prec_t)((_cw & FP_PRC_FLD) >> FP_PRC_OFF); 193117863Speter _cw &= ~FP_PRC_FLD; 194117863Speter _cw |= (_m << FP_PRC_OFF) & FP_PRC_FLD; 195117863Speter __fldcw(&_cw); 196117863Speter return (_p); 197117863Speter} 198117863Speter 199117863Speter/* 200175178Sbde * Get or set the exception mask. 201175178Sbde * Note that the x87 mask bits are inverted by the API -- a mask bit of 1 202175178Sbde * means disable for x87 and SSE, but for fp*mask() it means enable. 203117863Speter */ 204175178Sbde 205175179Sbdestatic __inline fp_except_t 206117863Speter__fpgetmask(void) 207117863Speter{ 208117863Speter unsigned short _cw; 209117863Speter 210117863Speter __fnstcw(&_cw); 211175179Sbde return ((~_cw & FP_MSKS_FLD) >> FP_MSKS_OFF); 212117863Speter} 213117863Speter 214175179Sbdestatic __inline fp_except_t 215117863Speter__fpsetmask(fp_except_t _m) 216117863Speter{ 217175179Sbde fp_except_t _p; 218175179Sbde unsigned _mxcsr; 219117863Speter unsigned short _cw; 220117863Speter 221117863Speter __fnstcw(&_cw); 222175179Sbde _p = (~_cw & FP_MSKS_FLD) >> FP_MSKS_OFF; 223117863Speter _cw &= ~FP_MSKS_FLD; 224175179Sbde _cw |= (~_m >> FP_MSKS_OFF) & FP_MSKS_FLD; 225117863Speter __fldcw(&_cw); 226117863Speter __stmxcsr(&_mxcsr); 227117863Speter /* XXX should we clear non-ieee SSE_DAZ_FLD and SSE_FZ_FLD ? */ 228117863Speter _mxcsr &= ~SSE_MSKS_FLD; 229175179Sbde _mxcsr |= (~_m << SSE_MSKS_OFF) & SSE_MSKS_FLD; 230117863Speter __ldmxcsr(&_mxcsr); 231117863Speter return (_p); 232117863Speter} 233117863Speter 234175179Sbdestatic __inline fp_except_t 235117863Speter__fpgetsticky(void) 236117863Speter{ 237175180Sbde unsigned _ex, _mxcsr; 238117863Speter unsigned short _sw; 239117863Speter 240117863Speter __fnstsw(&_sw); 241175179Sbde _ex = (_sw & FP_STKY_FLD) >> FP_STKY_OFF; 242117863Speter __stmxcsr(&_mxcsr); 243175179Sbde _ex |= (_mxcsr & SSE_STKY_FLD) >> SSE_STKY_OFF; 244175180Sbde return ((fp_except_t)_ex); 245117863Speter} 246117863Speter 247175180Sbde#endif /* __GNUCLIKE_ASM */ 248109520Smarcel 249175180Sbde#if !defined(__IEEEFP_NOINLINES__) && defined(__GNUCLIKE_ASM) 250109520Smarcel 251118331Speter#define fpgetround() __fpgetround() 252118331Speter#define fpsetround(_m) __fpsetround(_m) 253117863Speter#define fpgetprec() __fpgetprec() 254117863Speter#define fpsetprec(_m) __fpsetprec(_m) 255117863Speter#define fpgetmask() __fpgetmask() 256117863Speter#define fpsetmask(_m) __fpsetmask(_m) 257117863Speter#define fpgetsticky() __fpgetsticky() 258117863Speter 259109520Smarcel/* Suppress prototypes in the MI header. */ 260109520Smarcel#define _IEEEFP_INLINED_ 1 261109520Smarcel 262175180Sbde#else /* !(!__IEEEFP_NOINLINES__ && __GNUCLIKE_ASM) */ 263117863Speter 264175178Sbde/* Augment the userland declarations. */ 265117863Speter__BEGIN_DECLS 266175179Sbdefp_prec_t fpgetprec(void); 267175179Sbdefp_prec_t fpsetprec(fp_prec_t); 268117863Speter__END_DECLS 269117863Speter 270175180Sbde#endif /* !__IEEEFP_NOINLINES__ && __GNUCLIKE_ASM */ 271117863Speter 2721862Swollman#endif /* !_MACHINE_IEEEFP_H_ */ 273