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