1 #define _FP_W_TYPE_SIZE		32
2 #define _FP_W_TYPE		unsigned int
3 #define _FP_WS_TYPE		signed int
4 #define _FP_I_TYPE		int
5 
6 /* The type of the result of a floating point comparison.  This must
7    match `__libgcc_cmp_return__' in GCC for the target.  */
8 typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
9 #define CMPtype __gcc_CMPtype
10 
11 #define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)	\
12   __asm__ ("add{l} {%11,%3|%3,%11}\n\t"				\
13 	   "adc{l} {%9,%2|%2,%9}\n\t"				\
14 	   "adc{l} {%7,%1|%1,%7}\n\t"				\
15 	   "adc{l} {%5,%0|%0,%5}"				\
16 	   : "=r" ((USItype) (r3)),				\
17 	     "=&r" ((USItype) (r2)),				\
18 	     "=&r" ((USItype) (r1)),				\
19 	     "=&r" ((USItype) (r0))				\
20 	   : "%0" ((USItype) (x3)),				\
21 	     "g" ((USItype) (y3)),				\
22 	     "%1" ((USItype) (x2)),				\
23 	     "g" ((USItype) (y2)),				\
24 	     "%2" ((USItype) (x1)),				\
25 	     "g" ((USItype) (y1)),				\
26 	     "%3" ((USItype) (x0)),				\
27 	     "g" ((USItype) (y0)))
28 #define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)		\
29   __asm__ ("add{l} {%8,%2|%2,%8}\n\t"				\
30 	   "adc{l} {%6,%1|%1,%6}\n\t"				\
31 	   "adc{l} {%4,%0|%0,%4}"				\
32 	   : "=r" ((USItype) (r2)),				\
33 	     "=&r" ((USItype) (r1)),				\
34 	     "=&r" ((USItype) (r0))				\
35 	   : "%0" ((USItype) (x2)),				\
36 	     "g" ((USItype) (y2)),				\
37 	     "%1" ((USItype) (x1)),				\
38 	     "g" ((USItype) (y1)),				\
39 	     "%2" ((USItype) (x0)),				\
40 	     "g" ((USItype) (y0)))
41 #define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)	\
42   __asm__ ("sub{l} {%11,%3|%3,%11}\n\t"				\
43 	   "sbb{l} {%9,%2|%2,%9}\n\t"				\
44 	   "sbb{l} {%7,%1|%1,%7}\n\t"				\
45 	   "sbb{l} {%5,%0|%0,%5}"				\
46 	   : "=r" ((USItype) (r3)),				\
47 	     "=&r" ((USItype) (r2)),				\
48 	     "=&r" ((USItype) (r1)),				\
49 	     "=&r" ((USItype) (r0))				\
50 	   : "0" ((USItype) (x3)),				\
51 	     "g" ((USItype) (y3)),				\
52 	     "1" ((USItype) (x2)),				\
53 	     "g" ((USItype) (y2)),				\
54 	     "2" ((USItype) (x1)),				\
55 	     "g" ((USItype) (y1)),				\
56 	     "3" ((USItype) (x0)),				\
57 	     "g" ((USItype) (y0)))
58 #define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)		\
59   __asm__ ("sub{l} {%8,%2|%2,%8}\n\t"				\
60 	   "sbb{l} {%6,%1|%1,%6}\n\t"				\
61 	   "sbb{l} {%4,%0|%0,%4}"				\
62 	   : "=r" ((USItype) (r2)),				\
63 	     "=&r" ((USItype) (r1)),				\
64 	     "=&r" ((USItype) (r0))				\
65 	   : "0" ((USItype) (x2)),				\
66 	     "g" ((USItype) (y2)),				\
67 	     "1" ((USItype) (x1)),				\
68 	     "g" ((USItype) (y1)),				\
69 	     "2" ((USItype) (x0)),				\
70 	     "g" ((USItype) (y0)))
71 
72 
73 #define _FP_MUL_MEAT_Q(R,X,Y)					\
74   _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
75 
76 #define _FP_DIV_MEAT_Q(R,X,Y)   _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
77 
78 #define _FP_NANFRAC_S		_FP_QNANBIT_S
79 #define _FP_NANFRAC_D		_FP_QNANBIT_D, 0
80 /* Even if XFmode is 12byte,  we have to pad it to
81    16byte since soft-fp emulation is done in 16byte.  */
82 #define _FP_NANFRAC_E		_FP_QNANBIT_E, 0, 0, 0
83 #define _FP_NANFRAC_Q		_FP_QNANBIT_Q, 0, 0, 0
84 #define _FP_NANSIGN_S		1
85 #define _FP_NANSIGN_D		1
86 #define _FP_NANSIGN_E		1
87 #define _FP_NANSIGN_Q		1
88 
89 #define _FP_KEEPNANFRACP 1
90 
91 /* Here is something Intel misdesigned: the specs don't define
92    the case where we have two NaNs with same mantissas, but
93    different sign. Different operations pick up different NaNs.  */
94 #define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)			\
95   do {								\
96     if (_FP_FRAC_GT_##wc(X, Y)					\
97 	|| (_FP_FRAC_EQ_##wc(X,Y) && (OP == '+' || OP == '*')))	\
98       {								\
99 	R##_s = X##_s;						\
100         _FP_FRAC_COPY_##wc(R,X);				\
101       }								\
102     else							\
103       {								\
104 	R##_s = Y##_s;						\
105         _FP_FRAC_COPY_##wc(R,Y);				\
106       }								\
107     R##_c = FP_CLS_NAN;						\
108   } while (0)
109 
110 #define FP_EX_INVALID		0x01
111 #define FP_EX_DENORM		0x02
112 #define FP_EX_DIVZERO		0x04
113 #define FP_EX_OVERFLOW		0x08
114 #define FP_EX_UNDERFLOW		0x10
115 #define FP_EX_INEXACT		0x20
116 
117 struct fenv
118 {
119   unsigned short int __control_word;
120   unsigned short int __unused1;
121   unsigned short int __status_word;
122   unsigned short int __unused2;
123   unsigned short int __tags;
124   unsigned short int __unused3;
125   unsigned int __eip;
126   unsigned short int __cs_selector;
127   unsigned int __opcode:11;
128   unsigned int __unused4:5;
129   unsigned int __data_offset;
130   unsigned short int __data_selector;
131   unsigned short int __unused5;
132 };
133 
134 #define FP_HANDLE_EXCEPTIONS						\
135   do {									\
136     if (_fex & FP_EX_INVALID)						\
137       {									\
138 	float f = 0.0;							\
139 	__asm__ __volatile__ ("fdiv {%y0, %0|%0, %y0}" : "+t" (f));	\
140 	__asm__ __volatile__ ("fwait");					\
141       }									\
142     if (_fex & FP_EX_DIVZERO)						\
143       {									\
144 	float f = 1.0, g = 0.0;						\
145 	__asm__ __volatile__ ("fdivp {%0, %y1|%y1, %0}"			\
146 				      : "+t" (f) : "u" (g)		\
147 				      : "st(1)");			\
148 	__asm__ __volatile__ ("fwait");					\
149       }									\
150     if (_fex & FP_EX_OVERFLOW)						\
151       {									\
152 	struct fenv temp;						\
153 	__asm__ __volatile__ ("fnstenv %0" : "=m" (temp));		\
154 	temp.__status_word |= FP_EX_OVERFLOW;				\
155 	__asm__ __volatile__ ("fldenv %0" : : "m" (temp));		\
156 	__asm__ __volatile__ ("fwait");					\
157       }									\
158     if (_fex & FP_EX_UNDERFLOW)						\
159       {									\
160 	struct fenv temp;						\
161 	__asm__ __volatile__ ("fnstenv %0" : "=m" (temp));		\
162 	temp.__status_word |= FP_EX_UNDERFLOW;				\
163 	__asm__ __volatile__ ("fldenv %0" : : "m" (temp));		\
164 	__asm__ __volatile__ ("fwait");					\
165       }									\
166     if (_fex & FP_EX_INEXACT)						\
167       {									\
168 	struct fenv temp;						\
169 	__asm__ __volatile__ ("fnstenv %0" : "=m" (temp));		\
170 	temp.__status_word |= FP_EX_INEXACT;				\
171 	__asm__ __volatile__ ("fldenv %0" : : "m" (temp));		\
172 	__asm__ __volatile__ ("fwait");					\
173       }									\
174   } while (0)
175 
176 #define FP_RND_NEAREST		0
177 #define FP_RND_ZERO		0xc00
178 #define FP_RND_PINF		0x800
179 #define FP_RND_MINF		0x400
180 
181 #define _FP_DECL_EX \
182   unsigned short _fcw __attribute__ ((unused)) = FP_RND_NEAREST
183 
184 #define FP_INIT_ROUNDMODE			\
185   do {						\
186     __asm__ ("fnstcw %0" : "=m" (_fcw));	\
187   } while (0)
188 
189 #define FP_ROUNDMODE		(_fcw & 0xc00)
190 
191 #define	__LITTLE_ENDIAN	1234
192 #define	__BIG_ENDIAN	4321
193 
194 #define __BYTE_ORDER __LITTLE_ENDIAN
195 
196 /* Define ALIASNAME as a strong alias for NAME.  */
197 #if defined __MACH__
198 /* Mach-O doesn't support aliasing.  If these functions ever return
199    anything but CMPtype we need to revisit this... */
200 #define strong_alias(name, aliasname) \
201   CMPtype aliasname (TFtype a, TFtype b) { return name(a, b); }
202 #else
203 # define strong_alias(name, aliasname) _strong_alias(name, aliasname)
204 # define _strong_alias(name, aliasname) \
205   extern __typeof (name) aliasname __attribute__ ((alias (#name)));
206 #endif
207