|  | /* Software floating-point emulation. | 
|  | Copyright (C) 1997-2015 Free Software Foundation, Inc. | 
|  | This file is part of the GNU C Library. | 
|  | Contributed by Richard Henderson (rth@cygnus.com), | 
|  | Jakub Jelinek (jj@ultra.linux.cz), | 
|  | David S. Miller (davem@redhat.com) and | 
|  | Peter Maydell (pmaydell@chiark.greenend.org.uk). | 
|  |  | 
|  | The GNU C Library is free software; you can redistribute it and/or | 
|  | modify it under the terms of the GNU Lesser General Public | 
|  | License as published by the Free Software Foundation; either | 
|  | version 2.1 of the License, or (at your option) any later version. | 
|  |  | 
|  | In addition to the permissions in the GNU Lesser General Public | 
|  | License, the Free Software Foundation gives you unlimited | 
|  | permission to link the compiled version of this file into | 
|  | combinations with other programs, and to distribute those | 
|  | combinations without any restriction coming from the use of this | 
|  | file.  (The Lesser General Public License restrictions do apply in | 
|  | other respects; for example, they cover modification of the file, | 
|  | and distribution when not linked into a combine executable.) | 
|  |  | 
|  | The GNU C Library is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | Lesser General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU Lesser General Public | 
|  | License along with the GNU C Library; if not, see | 
|  | <http://www.gnu.org/licenses/>.  */ | 
|  |  | 
|  | #ifndef SOFT_FP_H | 
|  | #define SOFT_FP_H	1 | 
|  |  | 
|  | #ifdef _LIBC | 
|  | # include <sfp-machine.h> | 
|  | #elif defined __KERNEL__ | 
|  | /* The Linux kernel uses asm/ names for architecture-specific | 
|  | files.  */ | 
|  | # include <asm/sfp-machine.h> | 
|  | #else | 
|  | # include "sfp-machine.h" | 
|  | #endif | 
|  |  | 
|  | /* Allow sfp-machine to have its own byte order definitions.  */ | 
|  | #ifndef __BYTE_ORDER | 
|  | # ifdef _LIBC | 
|  | #  include <endian.h> | 
|  | # else | 
|  | #  error "endianness not defined by sfp-machine.h" | 
|  | # endif | 
|  | #endif | 
|  |  | 
|  | /* For unreachable default cases in switch statements over bitwise OR | 
|  | of FP_CLS_* values.  */ | 
|  | #if (defined __GNUC__							\ | 
|  | && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))) | 
|  | # define _FP_UNREACHABLE	__builtin_unreachable () | 
|  | #else | 
|  | # define _FP_UNREACHABLE	abort () | 
|  | #endif | 
|  |  | 
|  | #if ((defined __GNUC__							\ | 
|  | && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))	\ | 
|  | || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L)) | 
|  | # define _FP_STATIC_ASSERT(expr, msg)		\ | 
|  | _Static_assert ((expr), msg) | 
|  | #else | 
|  | # define _FP_STATIC_ASSERT(expr, msg)					\ | 
|  | extern int (*__Static_assert_function (void))				\ | 
|  | [!!sizeof (struct { int __error_if_negative: (expr) ? 2 : -1; })] | 
|  | #endif | 
|  |  | 
|  | /* In the Linux kernel, some architectures have a single function that | 
|  | uses different kinds of unpacking and packing depending on the | 
|  | instruction being emulated, meaning it is not readily visible to | 
|  | the compiler that variables from _FP_DECL and _FP_FRAC_DECL_* | 
|  | macros are only used in cases where they were initialized.  */ | 
|  | #ifdef __KERNEL__ | 
|  | # define _FP_ZERO_INIT		= 0 | 
|  | #else | 
|  | # define _FP_ZERO_INIT | 
|  | #endif | 
|  |  | 
|  | #define _FP_WORKBITS		3 | 
|  | #define _FP_WORK_LSB		((_FP_W_TYPE) 1 << 3) | 
|  | #define _FP_WORK_ROUND		((_FP_W_TYPE) 1 << 2) | 
|  | #define _FP_WORK_GUARD		((_FP_W_TYPE) 1 << 1) | 
|  | #define _FP_WORK_STICKY		((_FP_W_TYPE) 1 << 0) | 
|  |  | 
|  | #ifndef FP_RND_NEAREST | 
|  | # define FP_RND_NEAREST		0 | 
|  | # define FP_RND_ZERO		1 | 
|  | # define FP_RND_PINF		2 | 
|  | # define FP_RND_MINF		3 | 
|  | #endif | 
|  | #ifndef FP_ROUNDMODE | 
|  | # define FP_ROUNDMODE		FP_RND_NEAREST | 
|  | #endif | 
|  |  | 
|  | /* By default don't care about exceptions.  */ | 
|  | #ifndef FP_EX_INVALID | 
|  | # define FP_EX_INVALID		0 | 
|  | #endif | 
|  | #ifndef FP_EX_OVERFLOW | 
|  | # define FP_EX_OVERFLOW		0 | 
|  | #endif | 
|  | #ifndef FP_EX_UNDERFLOW | 
|  | # define FP_EX_UNDERFLOW	0 | 
|  | #endif | 
|  | #ifndef FP_EX_DIVZERO | 
|  | # define FP_EX_DIVZERO		0 | 
|  | #endif | 
|  | #ifndef FP_EX_INEXACT | 
|  | # define FP_EX_INEXACT		0 | 
|  | #endif | 
|  | #ifndef FP_EX_DENORM | 
|  | # define FP_EX_DENORM		0 | 
|  | #endif | 
|  |  | 
|  | /* Sub-exceptions of "invalid".  */ | 
|  | /* Signaling NaN operand.  */ | 
|  | #ifndef FP_EX_INVALID_SNAN | 
|  | # define FP_EX_INVALID_SNAN	0 | 
|  | #endif | 
|  | /* Inf * 0.  */ | 
|  | #ifndef FP_EX_INVALID_IMZ | 
|  | # define FP_EX_INVALID_IMZ	0 | 
|  | #endif | 
|  | /* fma (Inf, 0, c).  */ | 
|  | #ifndef FP_EX_INVALID_IMZ_FMA | 
|  | # define FP_EX_INVALID_IMZ_FMA	0 | 
|  | #endif | 
|  | /* Inf - Inf.  */ | 
|  | #ifndef FP_EX_INVALID_ISI | 
|  | # define FP_EX_INVALID_ISI	0 | 
|  | #endif | 
|  | /* 0 / 0.  */ | 
|  | #ifndef FP_EX_INVALID_ZDZ | 
|  | # define FP_EX_INVALID_ZDZ	0 | 
|  | #endif | 
|  | /* Inf / Inf.  */ | 
|  | #ifndef FP_EX_INVALID_IDI | 
|  | # define FP_EX_INVALID_IDI	0 | 
|  | #endif | 
|  | /* sqrt (negative).  */ | 
|  | #ifndef FP_EX_INVALID_SQRT | 
|  | # define FP_EX_INVALID_SQRT	0 | 
|  | #endif | 
|  | /* Invalid conversion to integer.  */ | 
|  | #ifndef FP_EX_INVALID_CVI | 
|  | # define FP_EX_INVALID_CVI	0 | 
|  | #endif | 
|  | /* Invalid comparison.  */ | 
|  | #ifndef FP_EX_INVALID_VC | 
|  | # define FP_EX_INVALID_VC	0 | 
|  | #endif | 
|  |  | 
|  | /* _FP_STRUCT_LAYOUT may be defined as an attribute to determine the | 
|  | struct layout variant used for structures where bit-fields are used | 
|  | to access specific parts of binary floating-point numbers.  This is | 
|  | required for systems where the default ABI uses struct layout with | 
|  | differences in how consecutive bit-fields are laid out from the | 
|  | default expected by soft-fp.  */ | 
|  | #ifndef _FP_STRUCT_LAYOUT | 
|  | # define _FP_STRUCT_LAYOUT | 
|  | #endif | 
|  |  | 
|  | #ifdef _FP_DECL_EX | 
|  | # define FP_DECL_EX					\ | 
|  | int _fex = 0;						\ | 
|  | _FP_DECL_EX | 
|  | #else | 
|  | # define FP_DECL_EX int _fex = 0 | 
|  | #endif | 
|  |  | 
|  | /* Initialize any machine-specific state used in FP_ROUNDMODE, | 
|  | FP_TRAPPING_EXCEPTIONS or FP_HANDLE_EXCEPTIONS.  */ | 
|  | #ifndef FP_INIT_ROUNDMODE | 
|  | # define FP_INIT_ROUNDMODE do {} while (0) | 
|  | #endif | 
|  |  | 
|  | /* Initialize any machine-specific state used in | 
|  | FP_TRAPPING_EXCEPTIONS or FP_HANDLE_EXCEPTIONS.  */ | 
|  | #ifndef FP_INIT_TRAPPING_EXCEPTIONS | 
|  | # define FP_INIT_TRAPPING_EXCEPTIONS FP_INIT_ROUNDMODE | 
|  | #endif | 
|  |  | 
|  | /* Initialize any machine-specific state used in | 
|  | FP_HANDLE_EXCEPTIONS.  */ | 
|  | #ifndef FP_INIT_EXCEPTIONS | 
|  | # define FP_INIT_EXCEPTIONS FP_INIT_TRAPPING_EXCEPTIONS | 
|  | #endif | 
|  |  | 
|  | #ifndef FP_HANDLE_EXCEPTIONS | 
|  | # define FP_HANDLE_EXCEPTIONS do {} while (0) | 
|  | #endif | 
|  |  | 
|  | /* Whether to flush subnormal inputs to zero with the same sign.  */ | 
|  | #ifndef FP_DENORM_ZERO | 
|  | # define FP_DENORM_ZERO 0 | 
|  | #endif | 
|  |  | 
|  | #ifndef FP_INHIBIT_RESULTS | 
|  | /* By default we write the results always. | 
|  | sfp-machine may override this and e.g. | 
|  | check if some exceptions are unmasked | 
|  | and inhibit it in such a case.  */ | 
|  | # define FP_INHIBIT_RESULTS 0 | 
|  | #endif | 
|  |  | 
|  | #define FP_SET_EXCEPTION(ex)				\ | 
|  | _fex |= (ex) | 
|  |  | 
|  | #define FP_CUR_EXCEPTIONS				\ | 
|  | (_fex) | 
|  |  | 
|  | #ifndef FP_TRAPPING_EXCEPTIONS | 
|  | # define FP_TRAPPING_EXCEPTIONS 0 | 
|  | #endif | 
|  |  | 
|  | /* A file using soft-fp may define FP_NO_EXCEPTIONS before including | 
|  | soft-fp.h to indicate that, although a macro used there could raise | 
|  | exceptions, or do rounding and potentially thereby raise | 
|  | exceptions, for some arguments, for the particular arguments used | 
|  | in that file no exceptions or rounding can occur.  Such a file | 
|  | should not itself use macros relating to handling exceptions and | 
|  | rounding modes; this is only for indirect uses (in particular, in | 
|  | _FP_FROM_INT and the macros it calls).  */ | 
|  | #ifdef FP_NO_EXCEPTIONS | 
|  |  | 
|  | # undef FP_SET_EXCEPTION | 
|  | # define FP_SET_EXCEPTION(ex) do {} while (0) | 
|  |  | 
|  | # undef FP_CUR_EXCEPTIONS | 
|  | # define FP_CUR_EXCEPTIONS 0 | 
|  |  | 
|  | # undef FP_TRAPPING_EXCEPTIONS | 
|  | # define FP_TRAPPING_EXCEPTIONS 0 | 
|  |  | 
|  | # undef FP_ROUNDMODE | 
|  | # define FP_ROUNDMODE FP_RND_ZERO | 
|  |  | 
|  | # undef _FP_TININESS_AFTER_ROUNDING | 
|  | # define _FP_TININESS_AFTER_ROUNDING 0 | 
|  |  | 
|  | #endif | 
|  |  | 
|  | /* A file using soft-fp may define FP_NO_EXACT_UNDERFLOW before | 
|  | including soft-fp.h to indicate that, although a macro used there | 
|  | could allow for the case of exact underflow requiring the underflow | 
|  | exception to be raised if traps are enabled, for the particular | 
|  | arguments used in that file no exact underflow can occur.  */ | 
|  | #ifdef FP_NO_EXACT_UNDERFLOW | 
|  | # undef FP_TRAPPING_EXCEPTIONS | 
|  | # define FP_TRAPPING_EXCEPTIONS 0 | 
|  | #endif | 
|  |  | 
|  | #define _FP_ROUND_NEAREST(wc, X)				\ | 
|  | do								\ | 
|  | {								\ | 
|  | if ((_FP_FRAC_LOW_##wc (X) & 15) != _FP_WORK_ROUND)	\ | 
|  | _FP_FRAC_ADDI_##wc (X, _FP_WORK_ROUND);			\ | 
|  | }								\ | 
|  | while (0) | 
|  |  | 
|  | #define _FP_ROUND_ZERO(wc, X)		(void) 0 | 
|  |  | 
|  | #define _FP_ROUND_PINF(wc, X)				\ | 
|  | do							\ | 
|  | {							\ | 
|  | if (!X##_s && (_FP_FRAC_LOW_##wc (X) & 7))	\ | 
|  | _FP_FRAC_ADDI_##wc (X, _FP_WORK_LSB);		\ | 
|  | }							\ | 
|  | while (0) | 
|  |  | 
|  | #define _FP_ROUND_MINF(wc, X)			\ | 
|  | do						\ | 
|  | {						\ | 
|  | if (X##_s && (_FP_FRAC_LOW_##wc (X) & 7))	\ | 
|  | _FP_FRAC_ADDI_##wc (X, _FP_WORK_LSB);	\ | 
|  | }						\ | 
|  | while (0) | 
|  |  | 
|  | #define _FP_ROUND(wc, X)			\ | 
|  | do						\ | 
|  | {						\ | 
|  | if (_FP_FRAC_LOW_##wc (X) & 7)		\ | 
|  | {					\ | 
|  | FP_SET_EXCEPTION (FP_EX_INEXACT);	\ | 
|  | switch (FP_ROUNDMODE)			\ | 
|  | {					\ | 
|  | case FP_RND_NEAREST:		\ | 
|  | _FP_ROUND_NEAREST (wc, X);	\ | 
|  | break;				\ | 
|  | case FP_RND_ZERO:			\ | 
|  | _FP_ROUND_ZERO (wc, X);		\ | 
|  | break;				\ | 
|  | case FP_RND_PINF:			\ | 
|  | _FP_ROUND_PINF (wc, X);		\ | 
|  | break;				\ | 
|  | case FP_RND_MINF:			\ | 
|  | _FP_ROUND_MINF (wc, X);		\ | 
|  | break;				\ | 
|  | }					\ | 
|  | }					\ | 
|  | }						\ | 
|  | while (0) | 
|  |  | 
|  | #define FP_CLS_NORMAL		0 | 
|  | #define FP_CLS_ZERO		1 | 
|  | #define FP_CLS_INF		2 | 
|  | #define FP_CLS_NAN		3 | 
|  |  | 
|  | #define _FP_CLS_COMBINE(x, y)	(((x) << 2) | (y)) | 
|  |  | 
|  | #include "op-1.h" | 
|  | #include "op-2.h" | 
|  | #include "op-4.h" | 
|  | #include "op-8.h" | 
|  | #include "op-common.h" | 
|  |  | 
|  | /* Sigh.  Silly things longlong.h needs.  */ | 
|  | #define UWtype		_FP_W_TYPE | 
|  | #define W_TYPE_SIZE	_FP_W_TYPE_SIZE | 
|  |  | 
|  | typedef int QItype __attribute__ ((mode (QI))); | 
|  | typedef int SItype __attribute__ ((mode (SI))); | 
|  | typedef int DItype __attribute__ ((mode (DI))); | 
|  | typedef unsigned int UQItype __attribute__ ((mode (QI))); | 
|  | typedef unsigned int USItype __attribute__ ((mode (SI))); | 
|  | typedef unsigned int UDItype __attribute__ ((mode (DI))); | 
|  | #if _FP_W_TYPE_SIZE == 32 | 
|  | typedef unsigned int UHWtype __attribute__ ((mode (HI))); | 
|  | #elif _FP_W_TYPE_SIZE == 64 | 
|  | typedef USItype UHWtype; | 
|  | #endif | 
|  |  | 
|  | #ifndef CMPtype | 
|  | # define CMPtype	int | 
|  | #endif | 
|  |  | 
|  | #define SI_BITS		(__CHAR_BIT__ * (int) sizeof (SItype)) | 
|  | #define DI_BITS		(__CHAR_BIT__ * (int) sizeof (DItype)) | 
|  |  | 
|  | #ifndef umul_ppmm | 
|  | # ifdef _LIBC | 
|  | #  include <stdlib/longlong.h> | 
|  | # else | 
|  | #  include "longlong.h" | 
|  | # endif | 
|  | #endif | 
|  |  | 
|  | #endif /* !SOFT_FP_H */ |