ieeefp.h revision 143063
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 143063 2005-03-02 21:33:29Z joerg $ 361834Swollman */ 371834Swollman 381834Swollman/* 391834Swollman * IEEE floating point type and constant definitions. 401834Swollman */ 411834Swollman 421862Swollman#ifndef _MACHINE_IEEEFP_H_ 431862Swollman#define _MACHINE_IEEEFP_H_ 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 124143063Sjoerg#if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE__) \ 125143063Sjoerg && !defined(__cplusplus) 126117863Speter 127109520Smarcel#define __fldenv(addr) __asm __volatile("fldenv %0" : : "m" (*(addr))) 128109520Smarcel#define __fnstenv(addr) __asm __volatile("fnstenv %0" : "=m" (*(addr))) 129117863Speter#define __fldcw(addr) __asm __volatile("fldcw %0" : "=m" (*(addr))) 130109520Smarcel#define __fnstcw(addr) __asm __volatile("fnstcw %0" : "=m" (*(addr))) 131109520Smarcel#define __fnstsw(addr) __asm __volatile("fnstsw %0" : "=m" (*(addr))) 132117863Speter#define __ldmxcsr(addr) __asm __volatile("ldmxcsr %0" : "=m" (*(addr))) 133117863Speter#define __stmxcsr(addr) __asm __volatile("stmxcsr %0" : "=m" (*(addr))) 134109520Smarcel 135109520Smarcel/* 136117863Speter * General notes about conflicting SSE vs FP status bits. 137117863Speter * This code assumes that software will not fiddle with the control 138117863Speter * bits of the SSE and x87 in such a way to get them out of sync and 139117863Speter * still expect this to work. Break this at your peril. 140117863Speter * Because I based this on the i386 port, the x87 state is used for 141117863Speter * the fpget*() functions, and is shadowed into the SSE state for 142117863Speter * the fpset*() functions. For dual source fpget*() functions, I 143117863Speter * merge the two together. I think. 144109520Smarcel */ 145117863Speter 146117863Speter/* Set rounding control */ 147117863Speterstatic __inline__ fp_rnd_t 148117863Speter__fpgetround(void) 149109520Smarcel{ 150117863Speter unsigned short _cw; 151109520Smarcel 152117863Speter __fnstcw(&_cw); 153117863Speter return ((_cw & FP_RND_FLD) >> FP_RND_OFF); 154109520Smarcel} 155109520Smarcel 156117863Speterstatic __inline__ fp_rnd_t 157117863Speter__fpsetround(fp_rnd_t _m) 158117863Speter{ 159117863Speter unsigned short _cw; 160117863Speter unsigned int _mxcsr; 161117863Speter fp_rnd_t _p; 162117863Speter 163117863Speter __fnstcw(&_cw); 164117863Speter _p = (_cw & FP_RND_FLD) >> FP_RND_OFF; 165117863Speter _cw &= ~FP_RND_FLD; 166117863Speter _cw |= (_m << FP_RND_OFF) & FP_RND_FLD; 167117863Speter __fldcw(&_cw); 168117863Speter __stmxcsr(&_mxcsr); 169117863Speter _mxcsr &= ~SSE_RND_FLD; 170117863Speter _mxcsr |= (_m << SSE_RND_OFF) & SSE_RND_FLD; 171117863Speter __ldmxcsr(&_mxcsr); 172117863Speter return (_p); 173117863Speter} 174117863Speter 175109520Smarcel/* 176117863Speter * Set precision for fadd/fsub/fsqrt etc x87 instructions 177117863Speter * There is no equivalent SSE mode or control. 178109520Smarcel */ 179117863Speterstatic __inline__ fp_prec_t 180117863Speter__fpgetprec(void) 181109520Smarcel{ 182117863Speter unsigned short _cw; 183117863Speter 184117863Speter __fnstcw(&_cw); 185117863Speter return ((_cw & FP_PRC_FLD) >> FP_PRC_OFF); 186117863Speter} 187117863Speter 188117863Speterstatic __inline__ fp_prec_t 189117863Speter__fpsetprec(fp_rnd_t _m) 190117863Speter{ 191117863Speter unsigned short _cw; 192117863Speter fp_prec_t _p; 193117863Speter 194117863Speter __fnstcw(&_cw); 195117863Speter _p = (_cw & FP_PRC_FLD) >> FP_PRC_OFF; 196117863Speter _cw &= ~FP_PRC_FLD; 197117863Speter _cw |= (_m << FP_PRC_OFF) & FP_PRC_FLD; 198117863Speter __fldcw(&_cw); 199117863Speter return (_p); 200117863Speter} 201117863Speter 202117863Speter/* 203117863Speter * Look at the exception masks 204117863Speter * Note that x87 masks are inverse of the fp*() functions 205117863Speter * API. ie: mask = 1 means disable for x87 and SSE, but 206117863Speter * for the fp*() api, mask = 1 means enabled. 207117863Speter */ 208117863Speterstatic __inline__ fp_except_t 209117863Speter__fpgetmask(void) 210117863Speter{ 211117863Speter unsigned short _cw; 212117863Speter 213117863Speter __fnstcw(&_cw); 214117863Speter return ((~_cw) & FP_MSKS_FLD); 215117863Speter} 216117863Speter 217117863Speterstatic __inline__ fp_except_t 218117863Speter__fpsetmask(fp_except_t _m) 219117863Speter{ 220117863Speter unsigned short _cw; 221117863Speter unsigned int _mxcsr; 222117863Speter fp_except_t _p; 223117863Speter 224117863Speter __fnstcw(&_cw); 225117863Speter _p = (~_cw) & FP_MSKS_FLD; 226117863Speter _cw &= ~FP_MSKS_FLD; 227117863Speter _cw |= (~_m) & FP_MSKS_FLD; 228117863Speter __fldcw(&_cw); 229117863Speter __stmxcsr(&_mxcsr); 230117863Speter /* XXX should we clear non-ieee SSE_DAZ_FLD and SSE_FZ_FLD ? */ 231117863Speter _mxcsr &= ~SSE_MSKS_FLD; 232117863Speter _mxcsr |= ((~_m) << SSE_MSKS_OFF) & SSE_MSKS_FLD; 233117863Speter __ldmxcsr(&_mxcsr); 234117863Speter return (_p); 235117863Speter} 236117863Speter 237117863Speter/* See which sticky exceptions are pending, and reset them */ 238117863Speterstatic __inline__ fp_except_t 239117863Speter__fpgetsticky(void) 240117863Speter{ 241117863Speter unsigned short _sw; 242117863Speter unsigned int _mxcsr; 243117863Speter fp_except_t _ex; 244117863Speter 245117863Speter __fnstsw(&_sw); 246117863Speter _ex = _sw & FP_STKY_FLD; 247117863Speter __stmxcsr(&_mxcsr); 248117863Speter _ex |= _mxcsr & SSE_STKY_FLD; 249117863Speter return (_ex); 250117863Speter} 251117863Speter 252117863Speter/* Note that this should really be called fpresetsticky() */ 253117863Speterstatic __inline__ fp_except_t 254117863Speter__fpsetsticky(fp_except_t _m) 255117863Speter{ 256109520Smarcel unsigned _env[7]; 257117863Speter unsigned int _mxcsr; 258117863Speter fp_except_t _p; 259109520Smarcel 260109520Smarcel __fnstenv(_env); 261117863Speter _p = _env[FP_STKY_REG] & _m; 262117863Speter __stmxcsr(&_mxcsr); 263117863Speter _p |= _mxcsr & SSE_STKY_FLD; 264117863Speter _env[FP_STKY_REG] &= ~_m; 265109520Smarcel __fldenv(_env); 266117863Speter _mxcsr &= ~_m; 267117863Speter __ldmxcsr(&_mxcsr); 268117863Speter return (_p); 269109520Smarcel} 270109520Smarcel 271143063Sjoerg#endif /* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE__ && !__cplusplus */ 272109520Smarcel 273143063Sjoerg#if !defined(__IEEEFP_NOINLINES__) && !defined(__cplusplus) \ 274143063Sjoerg && defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE__) 275109520Smarcel 276118331Speter#define fpgetround() __fpgetround() 277118331Speter#define fpsetround(_m) __fpsetround(_m) 278117863Speter#define fpgetprec() __fpgetprec() 279117863Speter#define fpsetprec(_m) __fpsetprec(_m) 280117863Speter#define fpgetmask() __fpgetmask() 281117863Speter#define fpsetmask(_m) __fpsetmask(_m) 282117863Speter#define fpgetsticky() __fpgetsticky() 283117863Speter#define fpsetsticky(_m) __fpsetsticky(_m) 284117863Speter 285109520Smarcel/* Suppress prototypes in the MI header. */ 286109520Smarcel#define _IEEEFP_INLINED_ 1 287109520Smarcel 288143063Sjoerg#else /* !__IEEEFP_NOINLINES__ && !__cplusplus && __GNUCLIKE_ASM 289143063Sjoerg && __CC_SUPPORTS___INLINE__ */ 290117863Speter 291117863Speter/* Augment the userland declarations */ 292117863Speter__BEGIN_DECLS 293117863Speterextern fp_prec_t fpgetprec(void); 294117863Speterextern fp_prec_t fpsetprec(fp_prec_t); 295117863Speter__END_DECLS 296117863Speter 297143063Sjoerg#endif /* !__IEEEFP_NOINLINES__ && !__cplusplus && __GNUCLIKE_ASM 298143063Sjoerg && __CC_SUPPORTS___INLINE__ */ 299117863Speter 3001862Swollman#endif /* !_MACHINE_IEEEFP_H_ */ 301