1 /* 2 * Copyright (C) 2009 Android Open Source Project, All rights reserved. 3 * Derived from "bionic/libm/arm/fenv.h" 4 * Copyright (c) 2004-2005 David Schultz <das (at) FreeBSD.ORG> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 20 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 23 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #ifndef _FENV_H_ 31 #define _FENV_H_ 32 33 #include <stdio.h> 34 #include <sys/types.h> 35 36 typedef uint32_t fenv_t; 37 typedef uint32_t fexcept_t; 38 39 /* Exception flags */ 40 #define FE_INVALID 0x0010 41 #define FE_DIVBYZERO 0x0008 42 #define FE_OVERFLOW 0x0004 43 #define FE_UNDERFLOW 0x0002 44 #define FE_INEXACT 0x0001 45 #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 46 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 47 48 /* Rounding modes */ 49 #define FE_TONEAREST 0x0000 50 #define FE_TOWARDZERO 0x0001 51 #define FE_UPWARD 0x0002 /* not supporetd */ 52 #define FE_DOWNWARD 0x0003 /* not supporetd */ 53 #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 54 FE_UPWARD | FE_TOWARDZERO) 55 56 /* bit shift for FPSCR mapping */ 57 #define _FPUE_CAUSE_SHIFT 12 58 #define _FPUE_ENABLE_SHIFT 17 59 #define _FPUE_FLAG_SHIFT 2 60 61 /* bit shifters */ 62 #define _FPUE_CAUSE(_EXCS) ((_EXCS) << _FPUE_CAUSE_SHIFT) 63 #define _FPUE_ENABLE(_EXCS) ((_EXCS) << _FPUE_ENABLE_SHIFT) 64 #define _FPUE_FLAG(_EXCS) ((_EXCS) << _FPUE_FLAG_SHIFT) 65 66 #define _GET_FPUE_CAUSE(_FPUE) (((_FPUE) >> _FPUE_CAUSE_SHIFT) & FE_ALL_EXCEPT) 67 #define _GET_FPUE_ENABLE(_FPUE) (((_FPUE) >> _FPUE_ENABLE_SHIFT)& FE_ALL_EXCEPT) 68 #define _GET_FPUE_FLAG(_FPUE) (((_FPUE) >> _FPUE_FLAG_SHIFT) & FE_ALL_EXCEPT) 69 70 71 /* FPSCR register accessors */ 72 #ifdef __SH4_NOFPU__ 73 #define __read_fpscr(_ptr) 74 #define __write_fpscr(_val) 75 #else 76 #define __read_fpscr(_ptr) __asm __volatile("sts fpscr, %0" : "=r" (*(_ptr))) 77 #define __write_fpscr(_val) __asm __volatile("lds %0, fpscr" : : "r" (_val)) 78 #endif 79 80 81 /* functions for libm */ 82 static __inline int 83 feclearexcept(int __excepts) 84 { 85 uint32_t __fpscr; 86 87 __read_fpscr(&__fpscr); 88 __fpscr &= ~_FPUE_FLAG(__excepts); 89 __write_fpscr(__fpscr); 90 return (0); 91 } 92 93 static __inline int 94 fegetexceptflag(fexcept_t *__flagp, int __excepts) 95 { 96 uint32_t __fpscr; 97 98 __read_fpscr(&__fpscr); 99 *__flagp = _GET_FPUE_FLAG(__fpscr) & __excepts; 100 return (0); 101 } 102 103 104 static __inline int 105 fesetexceptflag(const fexcept_t *__flagp, int __excepts) 106 { 107 uint32_t __fpscr; 108 109 __read_fpscr(&__fpscr); 110 __fpscr &= ~_FPUE_FLAG(__excepts); 111 __fpscr |= ~_FPUE_FLAG(*__flagp & __excepts); 112 __write_fpscr(__fpscr); 113 return (0); 114 } 115 116 117 static __inline int 118 feraiseexcept(int __excepts) 119 { 120 fexcept_t __ex = __excepts; 121 122 fesetexceptflag(&__ex, __excepts); /* XXX */ 123 return (0); 124 } 125 126 127 static __inline int 128 fetestexcept(int __excepts) 129 { 130 fexcept_t __ex; 131 132 fegetexceptflag(&__ex, __excepts); 133 return (__ex); 134 } 135 136 137 static __inline int 138 fegetround(void) 139 { 140 uint32_t __fpscr = 0; 141 142 __read_fpscr(&__fpscr); 143 return (__fpscr & _ROUND_MASK); 144 } 145 146 static __inline int 147 fesetround(int __round) 148 { 149 uint32_t __fpscr = 0; 150 151 if (__round == FE_UPWARD || __round == FE_DOWNWARD) { 152 fprintf(stderr, "libm superh : " 153 "upward/downward rounding not supporetd.\n"); 154 return -1; 155 } 156 157 __read_fpscr(&__fpscr); 158 __fpscr &= ~_ROUND_MASK; 159 __fpscr |= (__round & _ROUND_MASK); 160 __write_fpscr(__fpscr); 161 return (0); 162 } 163 164 static __inline int 165 fegetenv(fenv_t *__envp) 166 { 167 __read_fpscr(__envp); 168 return (0); 169 } 170 171 static __inline int 172 feholdexcept(fenv_t *__envp) 173 { 174 uint32_t __fpscr; 175 176 __read_fpscr(&__fpscr); 177 *__envp = __fpscr; 178 __fpscr &= ~_FPUE_FLAG(FE_ALL_EXCEPT); 179 __write_fpscr(__fpscr); 180 return (0); 181 } 182 183 184 static __inline int 185 fesetenv(const fenv_t *__envp) 186 { 187 __write_fpscr(*__envp); 188 return (0); 189 } 190 191 192 static __inline int 193 feupdateenv(const fenv_t *__envp) 194 { 195 uint32_t __fpscr; 196 197 __read_fpscr(&__fpscr); 198 __write_fpscr(*__envp); 199 feraiseexcept(_GET_FPUE_FLAG(__fpscr)); 200 return (0); 201 } 202 203 #if __BSD_VISIBLE 204 205 static __inline int 206 feenableexcept(int __mask) 207 { 208 uint32_t __old_fpscr, __new_fpscr; 209 210 __read_fpscr(&__old_fpscr); 211 __new_fpscr = __old_fpscr | _FPUE_ENABLE(__mask & FE_ALL_EXCEPT); 212 __write_fpscr(__new_fpscr); 213 return (_GET_FPUE_ENABLE(__old_fpscr)); 214 } 215 216 static __inline int 217 fedisableexcept(int __mask) 218 { 219 uint32_t __old_fpscr, __new_fpscr; 220 221 __read_fpscr(&__old_fpscr); 222 __new_fpscr = __old_fpscr & ~(_FPUE_ENABLE(__mask & FE_ALL_EXCEPT)); 223 __write_fpscr(__new_fpscr); 224 return (_GET_FPUE_ENABLE(__old_fpscr)); 225 } 226 227 static __inline int 228 fegetexcept(void) 229 { 230 uint32_t __fpscr; 231 232 __read_fpscr(&__fpscr); 233 return (_GET_FPUE_ENABLE(__fpscr)); 234 } 235 236 #endif /* __BSD_VISIBLE */ 237 238 239 #endif /* _FENV_H_ */ 240 241