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 */ 49fenv_t __fe_dfl_env = 0; 50 51/* 52 * The feclearexcept() function clears the supported floating-point exceptions 53 * represented by `excepts'. 54 */ 55int 56feclearexcept(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} 66DEF_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 */ 73int 74fegetexceptflag(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 */ 88int 89feraiseexcept(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} 99DEF_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 */ 106int 107fesetexceptflag(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} 118DEF_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 */ 125int 126fetestexcept(int excepts) 127{ 128 fexcept_t r; 129 130 excepts &= FE_ALL_EXCEPT; 131 __get_flags(r); 132 return (r & excepts); 133} 134DEF_STD(fetestexcept); 135 136/* 137 * The fegetround() function gets the current rounding direction. 138 */ 139int 140fegetround(void) 141{ 142 fenv_t r; 143 144 __get_frm(r); 145 return (r & _ROUND_MASK); 146} 147DEF_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 */ 154int 155fesetround(int round) 156{ 157 fenv_t r; 158 159 if (round & ~_ROUND_MASK) 160 return (-1); 161 __set_frm(round); 162 return (0); 163} 164DEF_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 */ 170int 171fegetenv(fenv_t *envp) 172{ 173 fenv_t r; 174 175 __get_fcsr(r); 176 *envp = r; 177 178 return (0); 179} 180DEF_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 */ 188int 189feholdexcept(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} 200DEF_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 */ 210int 211fesetenv(const fenv_t *envp) 212{ 213 214 fenv_t r; 215 r = *envp; 216 __set_fcsr(r); 217 return (0); 218} 219DEF_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 */ 229int 230feupdateenv(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} 239DEF_STD(feupdateenv); 240 241/* 242 * The following functions are extensions to the standard 243 */ 244int 245feenableexcept(int mask) 246{ 247 return -1; 248} 249 250int 251fedisableexcept(int mask) 252{ 253 return 0; 254} 255 256int 257fegetexcept(void) 258{ 259 return 0; 260} 261