1 #define _FP_W_TYPE_SIZE 64 2 3 #define _FP_W_TYPE unsigned long long 4 #define _FP_WS_TYPE signed long long 5 #define _FP_I_TYPE long long 6 7 typedef int TItype __attribute__ ((mode (TI))); 8 typedef unsigned int UTItype __attribute__ ((mode (TI))); 9 10 #define TI_BITS (__CHAR_BIT__ * (int)sizeof(TItype)) 11 12 /* The type of the result of a floating point comparison. This must 13 match `__libgcc_cmp_return__' in GCC for the target. */ 14 typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__))); 15 #define CMPtype __gcc_CMPtype 16 17 #define _FP_MUL_MEAT_Q(R,X,Y) \ 18 _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) 19 20 #define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y) 21 22 #define _FP_NANFRAC_S _FP_QNANBIT_S 23 #define _FP_NANFRAC_D _FP_QNANBIT_D 24 #define _FP_NANFRAC_E _FP_QNANBIT_E, 0 25 #define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0 26 #define _FP_NANSIGN_S 1 27 #define _FP_NANSIGN_D 1 28 #define _FP_NANSIGN_E 1 29 #define _FP_NANSIGN_Q 1 30 31 #define _FP_KEEPNANFRACP 1 32 33 /* Here is something Intel misdesigned: the specs don't define 34 the case where we have two NaNs with same mantissas, but 35 different sign. Different operations pick up different NaNs. */ 36 #define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ 37 do { \ 38 if (_FP_FRAC_GT_##wc(X, Y) \ 39 || (_FP_FRAC_EQ_##wc(X,Y) && (OP == '+' || OP == '*'))) \ 40 { \ 41 R##_s = X##_s; \ 42 _FP_FRAC_COPY_##wc(R,X); \ 43 } \ 44 else \ 45 { \ 46 R##_s = Y##_s; \ 47 _FP_FRAC_COPY_##wc(R,Y); \ 48 } \ 49 R##_c = FP_CLS_NAN; \ 50 } while (0) 51 52 #define FP_EX_INVALID 0x01 53 #define FP_EX_DENORM 0x02 54 #define FP_EX_DIVZERO 0x04 55 #define FP_EX_OVERFLOW 0x08 56 #define FP_EX_UNDERFLOW 0x10 57 #define FP_EX_INEXACT 0x20 58 59 struct fenv 60 { 61 unsigned short int __control_word; 62 unsigned short int __unused1; 63 unsigned short int __status_word; 64 unsigned short int __unused2; 65 unsigned short int __tags; 66 unsigned short int __unused3; 67 unsigned int __eip; 68 unsigned short int __cs_selector; 69 unsigned int __opcode:11; 70 unsigned int __unused4:5; 71 unsigned int __data_offset; 72 unsigned short int __data_selector; 73 unsigned short int __unused5; 74 }; 75 76 #ifdef __AVX__ 77 #define ASM_INVALID "vdivss %0, %0, %0" 78 #define ASM_DIVZERO "vdivss %1, %0, %0" 79 #else 80 #define ASM_INVALID "divss %0, %0" 81 #define ASM_DIVZERO "divss %1, %0" 82 #endif 83 84 #define FP_HANDLE_EXCEPTIONS \ 85 do { \ 86 if (_fex & FP_EX_INVALID) \ 87 { \ 88 float f = 0.0; \ 89 __asm__ __volatile__ (ASM_INVALID : : "x" (f)); \ 90 } \ 91 if (_fex & FP_EX_DIVZERO) \ 92 { \ 93 float f = 1.0, g = 0.0; \ 94 __asm__ __volatile__ (ASM_DIVZERO : : "x" (f), "x" (g)); \ 95 } \ 96 if (_fex & FP_EX_OVERFLOW) \ 97 { \ 98 struct fenv temp; \ 99 __asm__ __volatile__ ("fnstenv %0" : "=m" (temp)); \ 100 temp.__status_word |= FP_EX_OVERFLOW; \ 101 __asm__ __volatile__ ("fldenv %0" : : "m" (temp)); \ 102 __asm__ __volatile__ ("fwait"); \ 103 } \ 104 if (_fex & FP_EX_UNDERFLOW) \ 105 { \ 106 struct fenv temp; \ 107 __asm__ __volatile__ ("fnstenv %0" : "=m" (temp)); \ 108 temp.__status_word |= FP_EX_UNDERFLOW; \ 109 __asm__ __volatile__ ("fldenv %0" : : "m" (temp)); \ 110 __asm__ __volatile__ ("fwait"); \ 111 } \ 112 if (_fex & FP_EX_INEXACT) \ 113 { \ 114 struct fenv temp; \ 115 __asm__ __volatile__ ("fnstenv %0" : "=m" (temp)); \ 116 temp.__status_word |= FP_EX_INEXACT; \ 117 __asm__ __volatile__ ("fldenv %0" : : "m" (temp)); \ 118 __asm__ __volatile__ ("fwait"); \ 119 } \ 120 } while (0) 121 122 #define FP_RND_NEAREST 0 123 #define FP_RND_ZERO 0xc00 124 #define FP_RND_PINF 0x800 125 #define FP_RND_MINF 0x400 126 127 #define _FP_DECL_EX \ 128 unsigned short _fcw __attribute__ ((unused)) = FP_RND_NEAREST 129 130 #define FP_INIT_ROUNDMODE \ 131 do { \ 132 __asm__ ("fnstcw %0" : "=m" (_fcw)); \ 133 } while (0) 134 135 #define FP_ROUNDMODE (_fcw & 0xc00) 136 137 #define __LITTLE_ENDIAN 1234 138 #define __BIG_ENDIAN 4321 139 140 #define __BYTE_ORDER __LITTLE_ENDIAN 141 142 /* Define ALIASNAME as a strong alias for NAME. */ 143 #if defined __MACH__ 144 /* Mach-O doesn't support aliasing. If these functions ever return 145 anything but CMPtype we need to revisit this... */ 146 #define strong_alias(name, aliasname) \ 147 CMPtype aliasname (TFtype a, TFtype b) { return name(a, b); } 148 #else 149 # define strong_alias(name, aliasname) _strong_alias(name, aliasname) 150 # define _strong_alias(name, aliasname) \ 151 extern __typeof (name) aliasname __attribute__ ((alias (#name))); 152 #endif 153