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 #ifndef _SOFT_FLOAT
111 #define FP_EX_INVALID		0x01
112 #define FP_EX_DENORM		0x02
113 #define FP_EX_DIVZERO		0x04
114 #define FP_EX_OVERFLOW		0x08
115 #define FP_EX_UNDERFLOW		0x10
116 #define FP_EX_INEXACT		0x20
117 
118 struct fenv
119 {
120   unsigned short int __control_word;
121   unsigned short int __unused1;
122   unsigned short int __status_word;
123   unsigned short int __unused2;
124   unsigned short int __tags;
125   unsigned short int __unused3;
126   unsigned int __eip;
127   unsigned short int __cs_selector;
128   unsigned int __opcode:11;
129   unsigned int __unused4:5;
130   unsigned int __data_offset;
131   unsigned short int __data_selector;
132   unsigned short int __unused5;
133 };
134 
135 #define FP_HANDLE_EXCEPTIONS						\
136   do {									\
137     if (_fex & FP_EX_INVALID)						\
138       {									\
139 	float f = 0.0;							\
140 	__asm__ __volatile__ ("fdiv {%y0, %0|%0, %y0}" : "+t" (f));	\
141 	__asm__ __volatile__ ("fwait");					\
142       }									\
143     if (_fex & FP_EX_DENORM)						\
144       {									\
145 	struct fenv temp;						\
146 	__asm__ __volatile__ ("fnstenv %0" : "=m" (temp));		\
147 	temp.__status_word |= FP_EX_DENORM;				\
148 	__asm__ __volatile__ ("fldenv %0" : : "m" (temp));		\
149 	__asm__ __volatile__ ("fwait");					\
150       }									\
151     if (_fex & FP_EX_DIVZERO)						\
152       {									\
153 	float f = 1.0, g = 0.0;						\
154 	__asm__ __volatile__ ("fdivp {%0, %y1|%y1, %0}"			\
155 				      : "+t" (f) : "u" (g)		\
156 				      : "st(1)");			\
157 	__asm__ __volatile__ ("fwait");					\
158       }									\
159     if (_fex & FP_EX_OVERFLOW)						\
160       {									\
161 	struct fenv temp;						\
162 	__asm__ __volatile__ ("fnstenv %0" : "=m" (temp));		\
163 	temp.__status_word |= FP_EX_OVERFLOW;				\
164 	__asm__ __volatile__ ("fldenv %0" : : "m" (temp));		\
165 	__asm__ __volatile__ ("fwait");					\
166       }									\
167     if (_fex & FP_EX_UNDERFLOW)						\
168       {									\
169 	struct fenv temp;						\
170 	__asm__ __volatile__ ("fnstenv %0" : "=m" (temp));		\
171 	temp.__status_word |= FP_EX_UNDERFLOW;				\
172 	__asm__ __volatile__ ("fldenv %0" : : "m" (temp));		\
173 	__asm__ __volatile__ ("fwait");					\
174       }									\
175     if (_fex & FP_EX_INEXACT)						\
176       {									\
177 	struct fenv temp;						\
178 	__asm__ __volatile__ ("fnstenv %0" : "=m" (temp));		\
179 	temp.__status_word |= FP_EX_INEXACT;				\
180 	__asm__ __volatile__ ("fldenv %0" : : "m" (temp));		\
181 	__asm__ __volatile__ ("fwait");					\
182       }									\
183   } while (0)
184 
185 #define FP_RND_NEAREST		0
186 #define FP_RND_ZERO		0xc00
187 #define FP_RND_PINF		0x800
188 #define FP_RND_MINF		0x400
189 
190 #define _FP_DECL_EX \
191   unsigned short _fcw __attribute__ ((unused)) = FP_RND_NEAREST
192 
193 #define FP_INIT_ROUNDMODE			\
194   do {						\
195     __asm__ ("fnstcw %0" : "=m" (_fcw));	\
196   } while (0)
197 
198 #define FP_ROUNDMODE		(_fcw & 0xc00)
199 #endif
200 
201 #define	__LITTLE_ENDIAN	1234
202 #define	__BIG_ENDIAN	4321
203 
204 #define __BYTE_ORDER __LITTLE_ENDIAN
205 
206 /* Define ALIASNAME as a strong alias for NAME.  */
207 #if defined __MACH__
208 /* Mach-O doesn't support aliasing.  If these functions ever return
209    anything but CMPtype we need to revisit this... */
210 #define strong_alias(name, aliasname) \
211   CMPtype aliasname (TFtype a, TFtype b) { return name(a, b); }
212 #else
213 # define strong_alias(name, aliasname) _strong_alias(name, aliasname)
214 # define _strong_alias(name, aliasname) \
215   extern __typeof (name) aliasname __attribute__ ((alias (#name)));
216 #endif
217