| /* Header file for fp-bit.c. */ |
| /* Copyright (C) 2000-2023 Free Software Foundation, Inc. |
| |
| This file is part of GCC. |
| |
| GCC is free software; you can redistribute it and/or modify it under |
| the terms of the GNU General Public License as published by the Free |
| Software Foundation; either version 3, or (at your option) any later |
| version. |
| |
| GCC 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 General Public License |
| for more details. |
| |
| Under Section 7 of GPL version 3, you are granted additional |
| permissions described in the GCC Runtime Library Exception, version |
| 3.1, as published by the Free Software Foundation. |
| |
| You should have received a copy of the GNU General Public License and |
| a copy of the GCC Runtime Library Exception along with this program; |
| see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #ifndef GCC_FP_BIT_H |
| #define GCC_FP_BIT_H |
| |
| /* Defining FINE_GRAINED_LIBRARIES allows one to select which routines |
| from this file are compiled via additional -D options. |
| |
| This avoids the need to pull in the entire fp emulation library |
| when only a small number of functions are needed. |
| |
| If FINE_GRAINED_LIBRARIES is not defined, then compile every |
| suitable routine. */ |
| #ifndef FINE_GRAINED_LIBRARIES |
| #define L_pack_df |
| #define L_unpack_df |
| #define L_pack_sf |
| #define L_unpack_sf |
| #define L_addsub_sf |
| #define L_addsub_df |
| #define L_mul_sf |
| #define L_mul_df |
| #define L_div_sf |
| #define L_div_df |
| #define L_fpcmp_parts_sf |
| #define L_fpcmp_parts_df |
| #define L_compare_sf |
| #define L_compare_df |
| #define L_eq_sf |
| #define L_eq_df |
| #define L_ne_sf |
| #define L_ne_df |
| #define L_gt_sf |
| #define L_gt_df |
| #define L_ge_sf |
| #define L_ge_df |
| #define L_lt_sf |
| #define L_lt_df |
| #define L_le_sf |
| #define L_le_df |
| #define L_unord_sf |
| #define L_unord_df |
| #define L_usi_to_sf |
| #define L_usi_to_df |
| #define L_si_to_sf |
| #define L_si_to_df |
| #define L_sf_to_si |
| #define L_df_to_si |
| #define L_f_to_usi |
| #define L_df_to_usi |
| #define L_negate_sf |
| #define L_negate_df |
| #define L_make_sf |
| #define L_make_df |
| #define L_sf_to_df |
| #define L_df_to_sf |
| #ifdef FLOAT |
| #define L_thenan_sf |
| #else |
| #define L_thenan_df |
| #endif |
| #endif /* ! FINE_GRAINED_LIBRARIES */ |
| |
| #if __LDBL_MANT_DIG__ == 113 || __LDBL_MANT_DIG__ == 106 |
| # if defined(TFLOAT) || defined(L_sf_to_tf) || defined(L_df_to_tf) |
| # define TMODES |
| # endif |
| #endif |
| |
| typedef float SFtype __attribute__ ((mode (SF))); |
| typedef float DFtype __attribute__ ((mode (DF))); |
| #ifdef TMODES |
| typedef float TFtype __attribute__ ((mode (TF))); |
| #endif |
| |
| typedef int HItype __attribute__ ((mode (HI))); |
| typedef int SItype __attribute__ ((mode (SI))); |
| typedef int DItype __attribute__ ((mode (DI))); |
| #ifdef TMODES |
| typedef int TItype __attribute__ ((mode (TI))); |
| #endif |
| |
| /* The type of the result of a floating point comparison. This must |
| match `__libgcc_cmp_return__' in GCC for the target. */ |
| #ifndef CMPtype |
| typedef int CMPtype __attribute__ ((mode (__libgcc_cmp_return__))); |
| #endif |
| |
| typedef unsigned int UHItype __attribute__ ((mode (HI))); |
| typedef unsigned int USItype __attribute__ ((mode (SI))); |
| typedef unsigned int UDItype __attribute__ ((mode (DI))); |
| #ifdef TMODES |
| typedef unsigned int UTItype __attribute__ ((mode (TI))); |
| #endif |
| |
| #define MAX_USI_INT (~(USItype)0) |
| #define MAX_SI_INT ((SItype) (MAX_USI_INT >> 1)) |
| #define BITS_PER_SI (4 * __CHAR_BIT__) |
| #ifdef TMODES |
| #define MAX_UDI_INT (~(UDItype)0) |
| #define MAX_DI_INT ((DItype) (MAX_UDI_INT >> 1)) |
| #define BITS_PER_DI (8 * __CHAR_BIT__) |
| #endif |
| |
| #ifdef FLOAT_ONLY |
| #define NO_DI_MODE |
| #endif |
| |
| #if __BYTE_ORDER__ != __FLOAT_WORD_ORDER__ |
| #define FLOAT_WORD_ORDER_MISMATCH |
| #endif |
| |
| #ifdef TFLOAT |
| # ifndef TMODES |
| # error "TFLOAT requires long double to have 113 bits of mantissa" |
| # endif |
| |
| # define PREFIXFPDP tp |
| # define PREFIXSFDF tf |
| # define NGARDS 10L /* Is this right? */ |
| # define GARDROUND 0x1ff |
| # define GARDMASK 0x3ff |
| # define GARDMSB 0x200 |
| # define FRAC_NBITS 128 |
| |
| # if __LDBL_MANT_DIG__ == 113 /* IEEE quad */ |
| # define EXPBITS 15 |
| # define EXPBIAS 16383 |
| # define EXPMAX (0x7fff) |
| # define QUIET_NAN ((TItype)0x8 << 108) |
| # define FRACHIGH ((TItype)0x8 << 124) |
| # define FRACHIGH2 ((TItype)0xc << 124) |
| # define FRACBITS 112 |
| # endif |
| |
| # if __LDBL_MANT_DIG__ == 106 /* IBM extended (double+double) */ |
| # define EXPBITS 11 |
| # define EXPBIAS 1023 |
| # define EXPMAX (0x7ff) |
| # define QUIET_NAN ((TItype)0x8 << (48 + 64)) |
| # define FRACHIGH ((TItype)0x8 << 124) |
| # define FRACHIGH2 ((TItype)0xc << 124) |
| # define FRACBITS 105 |
| # define HALFFRACBITS 52 |
| # define HALFSHIFT 64 |
| # endif |
| |
| # define pack_d __pack_t |
| # define unpack_d __unpack_t |
| # define __fpcmp_parts __fpcmp_parts_t |
| typedef UTItype fractype; |
| typedef UDItype halffractype; |
| typedef USItype qrtrfractype; |
| #define qrtrfractype qrtrfractype |
| typedef TFtype FLO_type; |
| typedef TItype intfrac; |
| #elif defined FLOAT |
| # define NGARDS 7L |
| # define GARDROUND 0x3f |
| # define GARDMASK 0x7f |
| # define GARDMSB 0x40 |
| # define EXPBITS 8 |
| # define EXPBIAS 127 |
| # define FRACBITS 23 |
| # define EXPMAX (0xff) |
| # define QUIET_NAN 0x400000L |
| # define FRAC_NBITS 32 |
| # define FRACHIGH 0x80000000L |
| # define FRACHIGH2 0xc0000000L |
| # define pack_d __pack_f |
| # define unpack_d __unpack_f |
| # define __fpcmp_parts __fpcmp_parts_f |
| typedef USItype fractype; |
| typedef UHItype halffractype; |
| typedef SFtype FLO_type; |
| typedef SItype intfrac; |
| |
| #else |
| # define PREFIXFPDP dp |
| # define PREFIXSFDF df |
| # define NGARDS 8L |
| # define GARDROUND 0x7f |
| # define GARDMASK 0xff |
| # define GARDMSB 0x80 |
| # define EXPBITS 11 |
| # define EXPBIAS 1023 |
| # define FRACBITS 52 |
| # define EXPMAX (0x7ff) |
| # define QUIET_NAN 0x8000000000000LL |
| # define FRAC_NBITS 64 |
| # define FRACHIGH 0x8000000000000000LL |
| # define FRACHIGH2 0xc000000000000000LL |
| # define pack_d __pack_d |
| # define unpack_d __unpack_d |
| # define __fpcmp_parts __fpcmp_parts_d |
| typedef UDItype fractype; |
| typedef USItype halffractype; |
| typedef DFtype FLO_type; |
| typedef DItype intfrac; |
| #endif /* FLOAT */ |
| |
| #ifdef TFLOAT |
| # define add __addtf3 |
| # define sub __subtf3 |
| # define multiply __multf3 |
| # define divide __divtf3 |
| # define compare __cmptf2 |
| # define _eq_f2 __eqtf2 |
| # define _ne_f2 __netf2 |
| # define _gt_f2 __gttf2 |
| # define _ge_f2 __getf2 |
| # define _lt_f2 __lttf2 |
| # define _le_f2 __letf2 |
| # define _unord_f2 __unordtf2 |
| # define usi_to_float __floatunsitf |
| # define si_to_float __floatsitf |
| # define float_to_si __fixtfsi |
| # define float_to_usi __fixunstfsi |
| # define negate __negtf2 |
| # define tf_to_sf __trunctfsf2 |
| # define tf_to_df __trunctfdf2 |
| #elif defined FLOAT |
| # define add __addsf3 |
| # define sub __subsf3 |
| # define multiply __mulsf3 |
| # define divide __divsf3 |
| # define compare __cmpsf2 |
| # define _eq_f2 __eqsf2 |
| # define _ne_f2 __nesf2 |
| # define _gt_f2 __gtsf2 |
| # define _ge_f2 __gesf2 |
| # define _lt_f2 __ltsf2 |
| # define _le_f2 __lesf2 |
| # define _unord_f2 __unordsf2 |
| # define usi_to_float __floatunsisf |
| # define si_to_float __floatsisf |
| # define float_to_si __fixsfsi |
| # define float_to_usi __fixunssfsi |
| # define negate __negsf2 |
| # define sf_to_df __extendsfdf2 |
| # define sf_to_tf __extendsftf2 |
| #else |
| # define add __adddf3 |
| # define sub __subdf3 |
| # define multiply __muldf3 |
| # define divide __divdf3 |
| # define compare __cmpdf2 |
| # define _eq_f2 __eqdf2 |
| # define _ne_f2 __nedf2 |
| # define _gt_f2 __gtdf2 |
| # define _ge_f2 __gedf2 |
| # define _lt_f2 __ltdf2 |
| # define _le_f2 __ledf2 |
| # define _unord_f2 __unorddf2 |
| # define usi_to_float __floatunsidf |
| # define si_to_float __floatsidf |
| # define float_to_si __fixdfsi |
| # define float_to_usi __fixunsdfsi |
| # define negate __negdf2 |
| # define df_to_sf __truncdfsf2 |
| # define df_to_tf __extenddftf2 |
| #endif /* FLOAT */ |
| |
| #ifndef INLINE |
| #define INLINE __inline__ |
| #endif |
| |
| /* Preserve the sticky-bit when shifting fractions to the right. */ |
| #define LSHIFT(a, s) { a = (a >> s) | !!(a & (((fractype) 1 << s) - 1)); } |
| |
| /* numeric parameters */ |
| /* F_D_BITOFF is the number of bits offset between the MSB of the mantissa |
| of a float and of a double. Assumes there are only two float types. |
| (double::FRAC_BITS+double::NGARDS-(float::FRAC_BITS+float::NGARDS)) |
| */ |
| #define F_D_BITOFF (52+8-(23+7)) |
| |
| #ifdef TMODES |
| # define F_T_BITOFF (__LDBL_MANT_DIG__-1+10-(23+7)) |
| # define D_T_BITOFF (__LDBL_MANT_DIG__-1+10-(52+8)) |
| #endif |
| |
| |
| #define NORMAL_EXPMIN (-(EXPBIAS)+1) |
| #define IMPLICIT_1 ((fractype)1<<(FRACBITS+NGARDS)) |
| #define IMPLICIT_2 ((fractype)1<<(FRACBITS+1+NGARDS)) |
| |
| /* common types */ |
| |
| typedef enum |
| { |
| CLASS_SNAN, |
| CLASS_QNAN, |
| CLASS_ZERO, |
| CLASS_NUMBER, |
| CLASS_INFINITY |
| } fp_class_type; |
| |
| typedef struct |
| { |
| #ifdef SMALL_MACHINE |
| char class; |
| unsigned char sign; |
| short normal_exp; |
| #else |
| fp_class_type class; |
| unsigned int sign; |
| int normal_exp; |
| #endif |
| |
| union |
| { |
| fractype ll; |
| halffractype l[2]; |
| } fraction; |
| } fp_number_type; |
| |
| typedef union |
| { |
| FLO_type value; |
| fractype value_raw; |
| |
| #ifndef FLOAT |
| # ifdef qrtrfractype |
| qrtrfractype qwords[4]; |
| # else |
| halffractype words[2]; |
| # endif |
| #endif |
| |
| #ifdef _DEBUG_BITFLOAT |
| struct |
| { |
| unsigned int sign:1 __attribute__ ((packed)); |
| unsigned int exp:EXPBITS __attribute__ ((packed)); |
| fractype fraction:FRACBITS __attribute__ ((packed)); |
| } |
| bits_big_endian; |
| |
| struct |
| { |
| fractype fraction:FRACBITS __attribute__ ((packed)); |
| unsigned int exp:EXPBITS __attribute__ ((packed)); |
| unsigned int sign:1 __attribute__ ((packed)); |
| } |
| bits_little_endian; |
| #endif |
| } |
| FLO_union_type; |
| |
| /* Prototypes. */ |
| |
| #if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf) |
| extern FLO_type pack_d (const fp_number_type *); |
| #endif |
| |
| extern void unpack_d (FLO_union_type *, fp_number_type *); |
| |
| #if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf) |
| extern FLO_type add (FLO_type, FLO_type); |
| extern FLO_type sub (FLO_type, FLO_type); |
| #endif |
| |
| #if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf) |
| extern FLO_type multiply (FLO_type, FLO_type); |
| #endif |
| |
| #if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf) |
| extern FLO_type divide (FLO_type, FLO_type); |
| #endif |
| |
| extern int __fpcmp_parts (fp_number_type *, fp_number_type *); |
| |
| #if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compare_tf) |
| extern CMPtype compare (FLO_type, FLO_type); |
| #endif |
| |
| #if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf) |
| extern CMPtype _eq_f2 (FLO_type, FLO_type); |
| #endif |
| |
| #if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf) |
| extern CMPtype _ne_f2 (FLO_type, FLO_type); |
| #endif |
| |
| #if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf) |
| extern CMPtype _gt_f2 (FLO_type, FLO_type); |
| #endif |
| |
| #if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf) |
| extern CMPtype _ge_f2 (FLO_type, FLO_type); |
| #endif |
| |
| #if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf) |
| extern CMPtype _lt_f2 (FLO_type, FLO_type); |
| #endif |
| |
| #if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf) |
| extern CMPtype _le_f2 (FLO_type, FLO_type); |
| #endif |
| |
| #if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf) |
| extern CMPtype _unord_f2 (FLO_type, FLO_type); |
| #endif |
| |
| #if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf) |
| extern FLO_type si_to_float (SItype); |
| #endif |
| |
| #if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si) |
| extern SItype float_to_si (FLO_type); |
| #endif |
| |
| #if defined(L_tf_to_usi) |
| extern USItype float_to_usi (FLO_type); |
| #endif |
| |
| #if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf) |
| extern FLO_type usi_to_float (USItype); |
| #endif |
| |
| #if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf) |
| extern FLO_type negate (FLO_type); |
| #endif |
| |
| #ifdef FLOAT |
| #if defined(L_make_sf) |
| extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype); |
| #endif |
| #ifndef FLOAT_ONLY |
| extern DFtype __make_dp (fp_class_type, unsigned int, int, UDItype); |
| #if defined(L_sf_to_df) |
| extern DFtype sf_to_df (SFtype); |
| #endif |
| #if defined(L_sf_to_tf) && defined(TMODES) |
| extern TFtype sf_to_tf (SFtype); |
| #endif |
| #endif /* ! FLOAT_ONLY */ |
| #endif /* FLOAT */ |
| |
| #ifndef FLOAT |
| extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype); |
| #if defined(L_make_df) |
| extern DFtype __make_dp (fp_class_type, unsigned int, int, UDItype); |
| #endif |
| #if defined(L_df_to_sf) |
| extern SFtype df_to_sf (DFtype); |
| #endif |
| #if defined(L_df_to_tf) && defined(TMODES) |
| extern TFtype df_to_tf (DFtype); |
| #endif |
| #endif /* ! FLOAT */ |
| |
| #ifdef TMODES |
| extern DFtype __make_dp (fp_class_type, unsigned int, int, UDItype); |
| extern TFtype __make_tp (fp_class_type, unsigned int, int, UTItype); |
| #ifdef TFLOAT |
| #if defined(L_tf_to_sf) |
| extern SFtype tf_to_sf (TFtype); |
| #endif |
| #if defined(L_tf_to_df) |
| extern DFtype tf_to_df (TFtype); |
| #endif |
| #if defined(L_di_to_tf) |
| extern TFtype di_to_df (DItype); |
| #endif |
| #endif /* TFLOAT */ |
| #endif /* TMODES */ |
| |
| #endif /* ! GCC_FP_BIT_H */ |