|
|
1.1 ! root 1: /* $Id: float.c,v 1.2 2005/05/14 22:08:07 fredette Exp $ */ ! 2: ! 3: /* generic/float.c - generic native floating-point support: */ ! 4: ! 5: /* ! 6: * Copyright (c) 2004 Matt Fredette ! 7: * All rights reserved. ! 8: * ! 9: * Redistribution and use in source and binary forms, with or without ! 10: * modification, are permitted provided that the following conditions ! 11: * are met: ! 12: * 1. Redistributions of source code must retain the above copyright ! 13: * notice, this list of conditions and the following disclaimer. ! 14: * 2. Redistributions in binary form must reproduce the above copyright ! 15: * notice, this list of conditions and the following disclaimer in the ! 16: * documentation and/or other materials provided with the distribution. ! 17: * 3. All advertising materials mentioning features or use of this software ! 18: * must display the following acknowledgement: ! 19: * This product includes software developed by Matt Fredette. ! 20: * 4. The name of the author may not be used to endorse or promote products ! 21: * derived from this software without specific prior written permission. ! 22: * ! 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ! 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ! 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ! 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ! 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ! 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ! 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ! 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ! 33: * POSSIBILITY OF SUCH DAMAGE. ! 34: */ ! 35: ! 36: #include <tme/common.h> ! 37: _TME_RCSID("$Id: float.c,v 1.2 2005/05/14 22:08:07 fredette Exp $"); ! 38: ! 39: /* includes: */ ! 40: #include <tme/generic/float.h> ! 41: #include <signal.h> ! 42: ! 43: /* the mutex protecting the native floating point: */ ! 44: static tme_mutex_t _tme_float_mutex; ! 45: ! 46: /* this is nonzero if the SIGFPE handler has been installed: */ ! 47: /* XXX FIXME this assumes that a handler installed once in one thread ! 48: will catch signals for all threads. obviously, whether or not this ! 49: is true depends on how the threads package deals with signals: */ ! 50: static int _tme_float_sigfpe_handler_installed; ! 51: ! 52: /* the current exceptions: */ ! 53: static int _tme_float_exceptions; ! 54: ! 55: /* the user's exception handler: */ ! 56: static void (*_tme_float_exception_handler) _TME_P((int, void *)); ! 57: static void *_tme_float_exception_handler_private; ! 58: ! 59: /* update the current exceptions: */ ! 60: static void ! 61: _tme_float_exceptions_update(int at_least_one) ! 62: { ! 63: int exceptions_new; ! 64: #ifdef HAVE_FPGETSTICKY ! 65: int sticky; ! 66: #endif /* HAVE_FPGETSTICKY */ ! 67: ! 68: /* start with no new exceptions: */ ! 69: exceptions_new = 0; ! 70: ! 71: /* get the exception status: */ ! 72: #ifdef HAVE_FPGETSTICKY ! 73: sticky = fpgetsticky(); ! 74: #define TME_FP_X_MAP(fp_x, float_x) if (sticky & (fp_x)) exceptions_new |= (float_x) ! 75: #ifdef FP_X_INV ! 76: TME_FP_X_MAP(FP_X_INV, TME_FLOAT_EXCEPTION_INVALID); ! 77: #endif ! 78: #ifdef FP_X_DNML ! 79: TME_FP_X_MAP(FP_X_DNML, TME_FLOAT_EXCEPTION_DENORMAL); ! 80: #endif ! 81: #ifdef FP_X_DZ ! 82: TME_FP_X_MAP(FP_X_DZ, TME_FLOAT_EXCEPTION_DIVBYZERO); ! 83: #endif ! 84: #ifdef FP_X_OFL ! 85: TME_FP_X_MAP(FP_X_OFL, TME_FLOAT_EXCEPTION_OVERFLOW); ! 86: #endif ! 87: #ifdef FP_X_UFL ! 88: TME_FP_X_MAP(FP_X_UFL, TME_FLOAT_EXCEPTION_UNDERFLOW); ! 89: #endif ! 90: #ifdef FP_X_IMP ! 91: TME_FP_X_MAP(FP_X_IMP, TME_FLOAT_EXCEPTION_INEXACT); ! 92: #endif ! 93: #ifdef FP_X_IOV ! 94: TME_FP_X_MAP(FP_X_IOV, TME_FLOAT_EXCEPTION_OVERFLOW_INT); ! 95: #endif ! 96: #undef TME_FP_X_MAP ! 97: #endif /* HAVE_FPGETSTICKY */ ! 98: ! 99: /* if we have no new exceptions, but we should have at least one, ! 100: add in the generic exception: */ ! 101: if (exceptions_new == 0 ! 102: && at_least_one) { ! 103: exceptions_new |= TME_FLOAT_EXCEPTION_GENERIC; ! 104: } ! 105: ! 106: /* accumulate the new exceptions into the current exceptions: */ ! 107: _tme_float_exceptions |= exceptions_new; ! 108: ! 109: /* clear the exception status: */ ! 110: #ifdef HAVE_FPSETSTICKY ! 111: fpsetsticky(0); ! 112: #endif /* HAVE_FPSETSTICKY */ ! 113: } ! 114: ! 115: /* our SIGFPE handler: */ ! 116: static RETSIGTYPE ! 117: _tme_float_sigfpe_handler(int unused) ! 118: { ! 119: ! 120: /* update the current exceptions: */ ! 121: _tme_float_exceptions_update(TRUE); ! 122: ! 123: /* call any user exception handler with the new exceptions: */ ! 124: if (_tme_float_exception_handler != NULL) { ! 125: (*_tme_float_exception_handler)(_tme_float_exceptions, _tme_float_exception_handler_private); ! 126: } ! 127: } ! 128: ! 129: /* this enters native floating-point operation: */ ! 130: void ! 131: tme_float_enter(int rounding_mode, void (*exception_handler)(int, void *), void *exception_handler_private) ! 132: { ! 133: ! 134: /* lock the native floating-point mutex: */ ! 135: tme_mutex_lock(&_tme_float_mutex); ! 136: ! 137: /* set any user exception handler: */ ! 138: _tme_float_exception_handler = exception_handler; ! 139: _tme_float_exception_handler_private = exception_handler_private; ! 140: ! 141: /* establish a signal handler: */ ! 142: /* XXX FIXME this assumes that a handler installed once in one thread ! 143: will catch signals for all threads. obviously, whether or not this ! 144: is true depends on how the threads package deals with signals: */ ! 145: if (!_tme_float_sigfpe_handler_installed) { ! 146: signal(SIGFPE, _tme_float_sigfpe_handler); ! 147: _tme_float_sigfpe_handler_installed = TRUE; ! 148: } ! 149: ! 150: /* set the rounding mode: */ ! 151: #ifdef HAVE_FPSETROUND ! 152: fpsetround(rounding_mode); ! 153: #endif /* HAVE_FPSETROUND */ ! 154: ! 155: /* clear the exception status: */ ! 156: _tme_float_exceptions = 0; ! 157: #ifdef HAVE_FPSETSTICKY ! 158: fpsetsticky(0); ! 159: #endif /* HAVE_FPSETSTICKY */ ! 160: ! 161: /* unmask all exceptions: */ ! 162: #ifdef HAVE_FPSETMASK ! 163: fpsetmask(0 ! 164: #ifdef FP_X_INV ! 165: | FP_X_INV ! 166: #endif ! 167: #ifdef FP_X_DNML ! 168: | FP_X_DNML ! 169: #endif ! 170: #ifdef FP_X_DZ ! 171: | FP_X_DZ ! 172: #endif ! 173: #ifdef FP_X_OFL ! 174: | FP_X_OFL ! 175: #endif ! 176: #ifdef FP_X_UFL ! 177: | FP_X_UFL ! 178: #endif ! 179: #ifdef FP_X_IMP ! 180: | FP_X_IMP ! 181: #endif ! 182: #ifdef FP_X_IOV ! 183: | FP_X_IOV ! 184: #endif ! 185: ); ! 186: #endif /* HAVE_FPSETMASK */ ! 187: } ! 188: ! 189: /* this returns the current native floating-point exceptions: */ ! 190: int ! 191: tme_float_exceptions(void) ! 192: { ! 193: /* update and return the current exceptions: */ ! 194: _tme_float_exceptions_update(FALSE); ! 195: return (_tme_float_exceptions); ! 196: } ! 197: ! 198: /* this leaves native floating-point operation: */ ! 199: int ! 200: tme_float_leave(void) ! 201: { ! 202: int exceptions; ! 203: ! 204: /* get the final set of exceptions: */ ! 205: exceptions = tme_float_exceptions(); ! 206: ! 207: /* clear any user exception handler: */ ! 208: _tme_float_exception_handler = NULL; ! 209: ! 210: /* unlock the native floating-point mutex: */ ! 211: tme_mutex_unlock(&_tme_float_mutex); ! 212: ! 213: /* return the final set of exceptions: */ ! 214: return (exceptions); ! 215: } ! 216: ! 217: /* missing standard functions: */ ! 218: #ifndef HAVE_ISINFF ! 219: int ! 220: isinff(float x) ! 221: { ! 222: return (x > FLOAT_MAX_FLOAT ! 223: || x < (-FLOAT_MAX_FLOAT)); ! 224: } ! 225: #endif /* !HAVE_ISINFF */ ! 226: ! 227: /* include the automatically-generated code: */ ! 228: #include "float-auto.c"
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.