1 /* $OpenBSD: fenv.c,v 1.4 2022/12/27 17:10:07 jmc Exp $ */ 2 /*- 3 * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> 4 * All rights reserved. 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 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD: head/lib/msun/aarch64/fenv.h 280857 2015-03-30 16:42:08Z emaste $ 28 */ 29 30 #include <fenv.h> 31 #include <machine/ieeefp.h> 32 33 #define __get_fcsr(r) asm volatile("frcsr %0" : "=r" (r)) 34 #define __set_fcsr(r) asm volatile("fscsr %0" : "+r" (r)) 35 #define __get_flags(r) asm volatile("frflags %0" : "=r" (r)) 36 #define __set_flags(r) asm volatile("fsflags %0" : "+r" (r)) 37 #define __get_frm(r) asm volatile("frrm %0" : "=r" (r)) 38 #define __set_frm(r) asm volatile("fsrm %0" : "+r"(r) ) 39 40 /* 41 * The following constant represents the default floating-point environment 42 * (that is, the one installed at program startup) and has type pointer to 43 * const-qualified fenv_t. 44 * 45 * It can be used as an argument to the functions within the <fenv.h> header 46 * that manage the floating-point environment, namely fesetenv() and 47 * feupdateenv(). 48 */ 49 fenv_t __fe_dfl_env = 0; 50 51 /* 52 * The feclearexcept() function clears the supported floating-point exceptions 53 * represented by `excepts'. 54 */ 55 int 56 feclearexcept(int excepts) 57 { 58 fexcept_t r; 59 60 excepts &= FE_ALL_EXCEPT; 61 __get_flags(r); 62 r &= ~excepts; 63 __set_flags(r); 64 return (0); 65 } 66 DEF_STD(feclearexcept); 67 68 /* 69 * The fegetexceptflag() function stores an implementation-defined 70 * representation of the states of the floating-point status flags indicated by 71 * the argument excepts in the object pointed to by the argument flagp. 72 */ 73 int 74 fegetexceptflag(fexcept_t *flagp, int excepts) 75 { 76 fexcept_t r; 77 78 excepts &= FE_ALL_EXCEPT; 79 __get_flags(r); 80 *flagp = r & excepts; 81 return (0); 82 } 83 84 /* 85 * The feraiseexcept() function raises the supported floating-point exceptions 86 * represented by the argument `excepts'. 87 */ 88 int 89 feraiseexcept(int excepts) 90 { 91 fexcept_t r; 92 93 excepts &= FE_ALL_EXCEPT; 94 __get_flags(r); 95 r |= excepts; 96 __set_flags(r); 97 return (0); 98 } 99 DEF_STD(feraiseexcept); 100 101 /* 102 * This function sets the floating-point status flags indicated by the argument 103 * `excepts' to the states stored in the object pointed to by `flagp'. It does 104 * NOT raise any floating-point exceptions, but only sets the state of the flags. 105 */ 106 int 107 fesetexceptflag(const fexcept_t *flagp, int excepts) 108 { 109 fexcept_t r; 110 111 excepts &= FE_ALL_EXCEPT; 112 __get_flags(r); 113 r &= ~excepts; 114 r |= *flagp & excepts; 115 __set_flags(r); 116 return (0); 117 } 118 DEF_STD(fesetexceptflag); 119 120 /* 121 * The fetestexcept() function determines which of a specified subset of the 122 * floating-point exception flags are currently set. The `excepts' argument 123 * specifies the floating-point status flags to be queried. 124 */ 125 int 126 fetestexcept(int excepts) 127 { 128 fexcept_t r; 129 130 excepts &= FE_ALL_EXCEPT; 131 __get_flags(r); 132 return (r & excepts); 133 } 134 DEF_STD(fetestexcept); 135 136 /* 137 * The fegetround() function gets the current rounding direction. 138 */ 139 int 140 fegetround(void) 141 { 142 fenv_t r; 143 144 __get_frm(r); 145 return (r & _ROUND_MASK); 146 } 147 DEF_STD(fegetround); 148 149 /* 150 * The fesetround() function establishes the rounding direction represented by 151 * its argument `round'. If the argument is not equal to the value of a rounding 152 * direction macro, the rounding direction is not changed. 153 */ 154 int 155 fesetround(int round) 156 { 157 fenv_t r; 158 159 if (round & ~_ROUND_MASK) 160 return (-1); 161 __set_frm(round); 162 return (0); 163 } 164 DEF_STD(fesetround); 165 166 /* 167 * The fegetenv() function attempts to store the current floating-point 168 * environment in the object pointed to by envp. 169 */ 170 int 171 fegetenv(fenv_t *envp) 172 { 173 fenv_t r; 174 175 __get_fcsr(r); 176 *envp = r; 177 178 return (0); 179 } 180 DEF_STD(fegetenv); 181 182 /* 183 * The feholdexcept() function saves the current floating-point environment 184 * in the object pointed to by envp, clears the floating-point status flags, and 185 * then installs a non-stop (continue on floating-point exceptions) mode, if 186 * available, for all floating-point exceptions. 187 */ 188 int 189 feholdexcept(fenv_t *envp) 190 { 191 fenv_t r; 192 193 __get_fcsr(r); 194 *envp = r; 195 r &= ~FE_ALL_EXCEPT; 196 __set_fcsr(r); 197 198 return (0); 199 } 200 DEF_STD(feholdexcept); 201 202 /* 203 * The fesetenv() function attempts to establish the floating-point environment 204 * represented by the object pointed to by envp. The argument `envp' points 205 * to an object set by a call to fegetenv() or feholdexcept(), or equal a 206 * floating-point environment macro. The fesetenv() function does not raise 207 * floating-point exceptions, but only installs the state of the floating-point 208 * status flags represented through its argument. 209 */ 210 int 211 fesetenv(const fenv_t *envp) 212 { 213 214 fenv_t r; 215 r = *envp; 216 __set_fcsr(r); 217 return (0); 218 } 219 DEF_STD(fesetenv); 220 221 /* 222 * The feupdateenv() function saves the currently raised floating-point 223 * exceptions in its automatic storage, installs the floating-point environment 224 * represented by the object pointed to by `envp', and then raises the saved 225 * floating-point exceptions. The argument `envp' shall point to an object set 226 * by a call to feholdexcept() or fegetenv(), or equal a floating-point 227 * environment macro. 228 */ 229 int 230 feupdateenv(const fenv_t *envp) 231 { 232 fexcept_t r; 233 234 __get_fcsr(r); 235 fesetenv(envp); 236 feraiseexcept(r & FE_ALL_EXCEPT); 237 return (0); 238 } 239 DEF_STD(feupdateenv); 240 241 /* 242 * The following functions are extensions to the standard 243 */ 244 int 245 feenableexcept(int mask) 246 { 247 return -1; 248 } 249 250 int 251 fedisableexcept(int mask) 252 { 253 return 0; 254 } 255 256 int 257 fegetexcept(void) 258 { 259 return 0; 260 } 261