1 /* Software floating-point emulation. 2 Copyright (C) 1997-2022 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 In addition to the permissions in the GNU Lesser General Public 11 License, the Free Software Foundation gives you unlimited 12 permission to link the compiled version of this file into 13 combinations with other programs, and to distribute those 14 combinations without any restriction coming from the use of this 15 file. (The Lesser General Public License restrictions do apply in 16 other respects; for example, they cover modification of the file, 17 and distribution when not linked into a combine executable.) 18 19 The GNU C Library is distributed in the hope that it will be useful, 20 but WITHOUT ANY WARRANTY; without even the implied warranty of 21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 Lesser General Public License for more details. 23 24 You should have received a copy of the GNU Lesser General Public 25 License along with the GNU C Library; if not, see 26 <https://www.gnu.org/licenses/>. */ 27 28 #ifndef SOFT_FP_H 29 #define SOFT_FP_H 1 30 31 #ifdef _LIBC 32 # include <sfp-machine.h> 33 #elif defined __KERNEL__ 34 /* The Linux kernel uses asm/ names for architecture-specific 35 files. */ 36 # include <asm/sfp-machine.h> 37 #else 38 # include "sfp-machine.h" 39 #endif 40 41 /* Allow sfp-machine to have its own byte order definitions. */ 42 #ifndef __BYTE_ORDER 43 # ifdef _LIBC 44 # include <endian.h> 45 # else 46 # error "endianness not defined by sfp-machine.h" 47 # endif 48 #endif 49 50 /* For unreachable default cases in switch statements over bitwise OR 51 of FP_CLS_* values. */ 52 #if (defined __GNUC__ \ 53 && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))) 54 # define _FP_UNREACHABLE __builtin_unreachable () 55 #else 56 # define _FP_UNREACHABLE abort () 57 #endif 58 59 #if ((defined __GNUC__ \ 60 && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) \ 61 || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L)) 62 # define _FP_STATIC_ASSERT(expr, msg) \ 63 _Static_assert ((expr), msg) 64 #else 65 # define _FP_STATIC_ASSERT(expr, msg) \ 66 extern int (*__Static_assert_function (void)) \ 67 [!!sizeof (struct { int __error_if_negative: (expr) ? 2 : -1; })] 68 #endif 69 70 /* In the Linux kernel, some architectures have a single function that 71 uses different kinds of unpacking and packing depending on the 72 instruction being emulated, meaning it is not readily visible to 73 the compiler that variables from _FP_DECL and _FP_FRAC_DECL_* 74 macros are only used in cases where they were initialized. */ 75 #ifdef __KERNEL__ 76 # define _FP_ZERO_INIT = 0 77 #else 78 # define _FP_ZERO_INIT 79 #endif 80 81 #define _FP_WORKBITS 3 82 #define _FP_WORK_LSB ((_FP_W_TYPE) 1 << 3) 83 #define _FP_WORK_ROUND ((_FP_W_TYPE) 1 << 2) 84 #define _FP_WORK_GUARD ((_FP_W_TYPE) 1 << 1) 85 #define _FP_WORK_STICKY ((_FP_W_TYPE) 1 << 0) 86 87 #ifndef FP_RND_NEAREST 88 # define FP_RND_NEAREST 0 89 # define FP_RND_ZERO 1 90 # define FP_RND_PINF 2 91 # define FP_RND_MINF 3 92 #endif 93 #ifndef FP_ROUNDMODE 94 # define FP_ROUNDMODE FP_RND_NEAREST 95 #endif 96 97 /* By default don't care about exceptions. */ 98 #ifndef FP_EX_INVALID 99 # define FP_EX_INVALID 0 100 #endif 101 #ifndef FP_EX_OVERFLOW 102 # define FP_EX_OVERFLOW 0 103 #endif 104 #ifndef FP_EX_UNDERFLOW 105 # define FP_EX_UNDERFLOW 0 106 #endif 107 #ifndef FP_EX_DIVZERO 108 # define FP_EX_DIVZERO 0 109 #endif 110 #ifndef FP_EX_INEXACT 111 # define FP_EX_INEXACT 0 112 #endif 113 #ifndef FP_EX_DENORM 114 # define FP_EX_DENORM 0 115 #endif 116 117 /* Sub-exceptions of "invalid". */ 118 /* Signaling NaN operand. */ 119 #ifndef FP_EX_INVALID_SNAN 120 # define FP_EX_INVALID_SNAN 0 121 #endif 122 /* Inf * 0. */ 123 #ifndef FP_EX_INVALID_IMZ 124 # define FP_EX_INVALID_IMZ 0 125 #endif 126 /* fma (Inf, 0, c). */ 127 #ifndef FP_EX_INVALID_IMZ_FMA 128 # define FP_EX_INVALID_IMZ_FMA 0 129 #endif 130 /* Inf - Inf. */ 131 #ifndef FP_EX_INVALID_ISI 132 # define FP_EX_INVALID_ISI 0 133 #endif 134 /* 0 / 0. */ 135 #ifndef FP_EX_INVALID_ZDZ 136 # define FP_EX_INVALID_ZDZ 0 137 #endif 138 /* Inf / Inf. */ 139 #ifndef FP_EX_INVALID_IDI 140 # define FP_EX_INVALID_IDI 0 141 #endif 142 /* sqrt (negative). */ 143 #ifndef FP_EX_INVALID_SQRT 144 # define FP_EX_INVALID_SQRT 0 145 #endif 146 /* Invalid conversion to integer. */ 147 #ifndef FP_EX_INVALID_CVI 148 # define FP_EX_INVALID_CVI 0 149 #endif 150 /* Invalid comparison. */ 151 #ifndef FP_EX_INVALID_VC 152 # define FP_EX_INVALID_VC 0 153 #endif 154 155 /* _FP_STRUCT_LAYOUT may be defined as an attribute to determine the 156 struct layout variant used for structures where bit-fields are used 157 to access specific parts of binary floating-point numbers. This is 158 required for systems where the default ABI uses struct layout with 159 differences in how consecutive bit-fields are laid out from the 160 default expected by soft-fp. */ 161 #ifndef _FP_STRUCT_LAYOUT 162 # define _FP_STRUCT_LAYOUT 163 #endif 164 165 #ifdef _FP_DECL_EX 166 # define FP_DECL_EX \ 167 int _fex = 0; \ 168 _FP_DECL_EX 169 #else 170 # define FP_DECL_EX int _fex = 0 171 #endif 172 173 /* Initialize any machine-specific state used in FP_ROUNDMODE, 174 FP_TRAPPING_EXCEPTIONS or FP_HANDLE_EXCEPTIONS. */ 175 #ifndef FP_INIT_ROUNDMODE 176 # define FP_INIT_ROUNDMODE do {} while (0) 177 #endif 178 179 /* Initialize any machine-specific state used in 180 FP_TRAPPING_EXCEPTIONS or FP_HANDLE_EXCEPTIONS. */ 181 #ifndef FP_INIT_TRAPPING_EXCEPTIONS 182 # define FP_INIT_TRAPPING_EXCEPTIONS FP_INIT_ROUNDMODE 183 #endif 184 185 /* Initialize any machine-specific state used in 186 FP_HANDLE_EXCEPTIONS. */ 187 #ifndef FP_INIT_EXCEPTIONS 188 # define FP_INIT_EXCEPTIONS FP_INIT_TRAPPING_EXCEPTIONS 189 #endif 190 191 #ifndef FP_HANDLE_EXCEPTIONS 192 # define FP_HANDLE_EXCEPTIONS do {} while (0) 193 #endif 194 195 /* Whether to flush subnormal inputs to zero with the same sign. */ 196 #ifndef FP_DENORM_ZERO 197 # define FP_DENORM_ZERO 0 198 #endif 199 200 #ifndef FP_INHIBIT_RESULTS 201 /* By default we write the results always. 202 sfp-machine may override this and e.g. 203 check if some exceptions are unmasked 204 and inhibit it in such a case. */ 205 # define FP_INHIBIT_RESULTS 0 206 #endif 207 208 #define FP_SET_EXCEPTION(ex) \ 209 _fex |= (ex) 210 211 #define FP_CUR_EXCEPTIONS \ 212 (_fex) 213 214 #ifndef FP_TRAPPING_EXCEPTIONS 215 # define FP_TRAPPING_EXCEPTIONS 0 216 #endif 217 218 /* A file using soft-fp may define FP_NO_EXCEPTIONS before including 219 soft-fp.h to indicate that, although a macro used there could raise 220 exceptions, or do rounding and potentially thereby raise 221 exceptions, for some arguments, for the particular arguments used 222 in that file no exceptions or rounding can occur. Such a file 223 should not itself use macros relating to handling exceptions and 224 rounding modes; this is only for indirect uses (in particular, in 225 _FP_FROM_INT and the macros it calls). */ 226 #ifdef FP_NO_EXCEPTIONS 227 228 # undef FP_SET_EXCEPTION 229 # define FP_SET_EXCEPTION(ex) do {} while (0) 230 231 # undef FP_CUR_EXCEPTIONS 232 # define FP_CUR_EXCEPTIONS 0 233 234 # undef FP_TRAPPING_EXCEPTIONS 235 # define FP_TRAPPING_EXCEPTIONS 0 236 237 # undef FP_ROUNDMODE 238 # define FP_ROUNDMODE FP_RND_ZERO 239 240 # undef _FP_TININESS_AFTER_ROUNDING 241 # define _FP_TININESS_AFTER_ROUNDING 0 242 243 #endif 244 245 /* A file using soft-fp may define FP_NO_EXACT_UNDERFLOW before 246 including soft-fp.h to indicate that, although a macro used there 247 could allow for the case of exact underflow requiring the underflow 248 exception to be raised if traps are enabled, for the particular 249 arguments used in that file no exact underflow can occur. */ 250 #ifdef FP_NO_EXACT_UNDERFLOW 251 # undef FP_TRAPPING_EXCEPTIONS 252 # define FP_TRAPPING_EXCEPTIONS 0 253 #endif 254 255 #define _FP_ROUND_NEAREST(wc, X) \ 256 do \ 257 { \ 258 if ((_FP_FRAC_LOW_##wc (X) & 15) != _FP_WORK_ROUND) \ 259 _FP_FRAC_ADDI_##wc (X, _FP_WORK_ROUND); \ 260 } \ 261 while (0) 262 263 #define _FP_ROUND_ZERO(wc, X) (void) 0 264 265 #define _FP_ROUND_PINF(wc, X) \ 266 do \ 267 { \ 268 if (!X##_s && (_FP_FRAC_LOW_##wc (X) & 7)) \ 269 _FP_FRAC_ADDI_##wc (X, _FP_WORK_LSB); \ 270 } \ 271 while (0) 272 273 #define _FP_ROUND_MINF(wc, X) \ 274 do \ 275 { \ 276 if (X##_s && (_FP_FRAC_LOW_##wc (X) & 7)) \ 277 _FP_FRAC_ADDI_##wc (X, _FP_WORK_LSB); \ 278 } \ 279 while (0) 280 281 #define _FP_ROUND(wc, X) \ 282 do \ 283 { \ 284 if (_FP_FRAC_LOW_##wc (X) & 7) \ 285 { \ 286 FP_SET_EXCEPTION (FP_EX_INEXACT); \ 287 switch (FP_ROUNDMODE) \ 288 { \ 289 case FP_RND_NEAREST: \ 290 _FP_ROUND_NEAREST (wc, X); \ 291 break; \ 292 case FP_RND_ZERO: \ 293 _FP_ROUND_ZERO (wc, X); \ 294 break; \ 295 case FP_RND_PINF: \ 296 _FP_ROUND_PINF (wc, X); \ 297 break; \ 298 case FP_RND_MINF: \ 299 _FP_ROUND_MINF (wc, X); \ 300 break; \ 301 } \ 302 } \ 303 } \ 304 while (0) 305 306 #define FP_CLS_NORMAL 0 307 #define FP_CLS_ZERO 1 308 #define FP_CLS_INF 2 309 #define FP_CLS_NAN 3 310 311 #define _FP_CLS_COMBINE(x, y) (((x) << 2) | (y)) 312 313 #include "op-1.h" 314 #include "op-2.h" 315 #include "op-4.h" 316 #include "op-8.h" 317 #include "op-common.h" 318 319 /* Sigh. Silly things longlong.h needs. */ 320 #define UWtype _FP_W_TYPE 321 #define W_TYPE_SIZE _FP_W_TYPE_SIZE 322 323 typedef int QItype __attribute__ ((mode (QI))); 324 typedef int SItype __attribute__ ((mode (SI))); 325 typedef int DItype __attribute__ ((mode (DI))); 326 typedef unsigned int UQItype __attribute__ ((mode (QI))); 327 typedef unsigned int USItype __attribute__ ((mode (SI))); 328 typedef unsigned int UDItype __attribute__ ((mode (DI))); 329 #if _FP_W_TYPE_SIZE == 32 330 typedef unsigned int UHWtype __attribute__ ((mode (HI))); 331 #elif _FP_W_TYPE_SIZE == 64 332 typedef USItype UHWtype; 333 #endif 334 335 #ifndef CMPtype 336 # define CMPtype int 337 #endif 338 339 #define SI_BITS (__CHAR_BIT__ * (int) sizeof (SItype)) 340 #define DI_BITS (__CHAR_BIT__ * (int) sizeof (DItype)) 341 342 #ifndef umul_ppmm 343 # ifdef _LIBC 344 # include <stdlib/longlong.h> 345 # else 346 # include "longlong.h" 347 # endif 348 #endif 349 350 #endif /* !SOFT_FP_H */ 351