Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6515 serge 1
/* Software floating-point emulation.
2
   Basic one-word fraction declaration and manipulation.
3
   Copyright (C) 1997-2014 Free Software Foundation, Inc.
4
   This file is part of the GNU C Library.
5
   Contributed by Richard Henderson (rth@cygnus.com),
6
		  Jakub Jelinek (jj@ultra.linux.cz),
7
		  David S. Miller (davem@redhat.com) and
8
		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
9
 
10
   The GNU C Library is free software; you can redistribute it and/or
11
   modify it under the terms of the GNU Lesser General Public
12
   License as published by the Free Software Foundation; either
13
   version 2.1 of the License, or (at your option) any later version.
14
 
15
   In addition to the permissions in the GNU Lesser General Public
16
   License, the Free Software Foundation gives you unlimited
17
   permission to link the compiled version of this file into
18
   combinations with other programs, and to distribute those
19
   combinations without any restriction coming from the use of this
20
   file.  (The Lesser General Public License restrictions do apply in
21
   other respects; for example, they cover modification of the file,
22
   and distribution when not linked into a combine executable.)
23
 
24
   The GNU C Library is distributed in the hope that it will be useful,
25
   but WITHOUT ANY WARRANTY; without even the implied warranty of
26
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
27
   Lesser General Public License for more details.
28
 
29
   You should have received a copy of the GNU Lesser General Public
30
   License along with the GNU C Library; if not, see
31
   .  */
32
 
33
#define _FP_FRAC_DECL_1(X)	_FP_W_TYPE X##_f
34
#define _FP_FRAC_COPY_1(D, S)	(D##_f = S##_f)
35
#define _FP_FRAC_SET_1(X, I)	(X##_f = I)
36
#define _FP_FRAC_HIGH_1(X)	(X##_f)
37
#define _FP_FRAC_LOW_1(X)	(X##_f)
38
#define _FP_FRAC_WORD_1(X, w)	(X##_f)
39
 
40
#define _FP_FRAC_ADDI_1(X, I)	(X##_f += I)
41
#define _FP_FRAC_SLL_1(X, N)			\
42
  do						\
43
    {						\
44
      if (__builtin_constant_p (N) && (N) == 1)	\
45
	X##_f += X##_f;				\
46
      else					\
47
	X##_f <<= (N);				\
48
    }						\
49
  while (0)
50
#define _FP_FRAC_SRL_1(X, N)	(X##_f >>= N)
51
 
52
/* Right shift with sticky-lsb.  */
53
#define _FP_FRAC_SRST_1(X, S, N, sz)	__FP_FRAC_SRST_1 (X##_f, S, (N), (sz))
54
#define _FP_FRAC_SRS_1(X, N, sz)	__FP_FRAC_SRS_1 (X##_f, (N), (sz))
55
 
56
#define __FP_FRAC_SRST_1(X, S, N, sz)			\
57
  do							\
58
    {							\
59
      S = (__builtin_constant_p (N) && (N) == 1		\
60
	   ? X & 1					\
61
	   : (X << (_FP_W_TYPE_SIZE - (N))) != 0);	\
62
      X = X >> (N);					\
63
    }							\
64
  while (0)
65
 
66
#define __FP_FRAC_SRS_1(X, N, sz)				\
67
  (X = (X >> (N) | (__builtin_constant_p (N) && (N) == 1	\
68
		    ? X & 1					\
69
		    : (X << (_FP_W_TYPE_SIZE - (N))) != 0)))
70
 
71
#define _FP_FRAC_ADD_1(R, X, Y)	(R##_f = X##_f + Y##_f)
72
#define _FP_FRAC_SUB_1(R, X, Y)	(R##_f = X##_f - Y##_f)
73
#define _FP_FRAC_DEC_1(X, Y)	(X##_f -= Y##_f)
74
#define _FP_FRAC_CLZ_1(z, X)	__FP_CLZ ((z), X##_f)
75
 
76
/* Predicates.  */
77
#define _FP_FRAC_NEGP_1(X)	((_FP_WS_TYPE) X##_f < 0)
78
#define _FP_FRAC_ZEROP_1(X)	(X##_f == 0)
79
#define _FP_FRAC_OVERP_1(fs, X)	(X##_f & _FP_OVERFLOW_##fs)
80
#define _FP_FRAC_CLEAR_OVERP_1(fs, X)	(X##_f &= ~_FP_OVERFLOW_##fs)
81
#define _FP_FRAC_HIGHBIT_DW_1(fs, X)	(X##_f & _FP_HIGHBIT_DW_##fs)
82
#define _FP_FRAC_EQ_1(X, Y)	(X##_f == Y##_f)
83
#define _FP_FRAC_GE_1(X, Y)	(X##_f >= Y##_f)
84
#define _FP_FRAC_GT_1(X, Y)	(X##_f > Y##_f)
85
 
86
#define _FP_ZEROFRAC_1		0
87
#define _FP_MINFRAC_1		1
88
#define _FP_MAXFRAC_1		(~(_FP_WS_TYPE) 0)
89
 
90
/* Unpack the raw bits of a native fp value.  Do not classify or
91
   normalize the data.  */
92
 
93
#define _FP_UNPACK_RAW_1(fs, X, val)			\
94
  do							\
95
    {							\
96
      union _FP_UNION_##fs _FP_UNPACK_RAW_1_flo;	\
97
      _FP_UNPACK_RAW_1_flo.flt = (val);			\
98
							\
99
      X##_f = _FP_UNPACK_RAW_1_flo.bits.frac;		\
100
      X##_e = _FP_UNPACK_RAW_1_flo.bits.exp;		\
101
      X##_s = _FP_UNPACK_RAW_1_flo.bits.sign;		\
102
    }							\
103
  while (0)
104
 
105
#define _FP_UNPACK_RAW_1_P(fs, X, val)			\
106
  do							\
107
    {							\
108
      union _FP_UNION_##fs *_FP_UNPACK_RAW_1_P_flo	\
109
	= (union _FP_UNION_##fs *) (val);		\
110
							\
111
      X##_f = _FP_UNPACK_RAW_1_P_flo->bits.frac;	\
112
      X##_e = _FP_UNPACK_RAW_1_P_flo->bits.exp;		\
113
      X##_s = _FP_UNPACK_RAW_1_P_flo->bits.sign;	\
114
    }							\
115
  while (0)
116
 
117
/* Repack the raw bits of a native fp value.  */
118
 
119
#define _FP_PACK_RAW_1(fs, val, X)		\
120
  do						\
121
    {						\
122
      union _FP_UNION_##fs _FP_PACK_RAW_1_flo;	\
123
						\
124
      _FP_PACK_RAW_1_flo.bits.frac = X##_f;	\
125
      _FP_PACK_RAW_1_flo.bits.exp  = X##_e;	\
126
      _FP_PACK_RAW_1_flo.bits.sign = X##_s;	\
127
						\
128
      (val) = _FP_PACK_RAW_1_flo.flt;		\
129
    }						\
130
  while (0)
131
 
132
#define _FP_PACK_RAW_1_P(fs, val, X)			\
133
  do							\
134
    {							\
135
      union _FP_UNION_##fs *_FP_PACK_RAW_1_P_flo	\
136
	= (union _FP_UNION_##fs *) (val);		\
137
							\
138
      _FP_PACK_RAW_1_P_flo->bits.frac = X##_f;		\
139
      _FP_PACK_RAW_1_P_flo->bits.exp  = X##_e;		\
140
      _FP_PACK_RAW_1_P_flo->bits.sign = X##_s;		\
141
    }							\
142
  while (0)
143
 
144
 
145
/* Multiplication algorithms: */
146
 
147
/* Basic.  Assuming the host word size is >= 2*FRACBITS, we can do the
148
   multiplication immediately.  */
149
 
150
#define _FP_MUL_MEAT_DW_1_imm(wfracbits, R, X, Y)	\
151
  do							\
152
    {							\
153
      R##_f = X##_f * Y##_f;				\
154
    }							\
155
  while (0)
156
 
157
#define _FP_MUL_MEAT_1_imm(wfracbits, R, X, Y)				\
158
  do									\
159
    {									\
160
      _FP_MUL_MEAT_DW_1_imm ((wfracbits), R, X, Y);			\
161
      /* Normalize since we know where the msb of the multiplicands	\
162
	 were (bit B), we know that the msb of the of the product is	\
163
	 at either 2B or 2B-1.  */					\
164
      _FP_FRAC_SRS_1 (R, (wfracbits)-1, 2*(wfracbits));			\
165
    }									\
166
  while (0)
167
 
168
/* Given a 1W * 1W => 2W primitive, do the extended multiplication.  */
169
 
170
#define _FP_MUL_MEAT_DW_1_wide(wfracbits, R, X, Y, doit)	\
171
  do								\
172
    {								\
173
      doit (R##_f1, R##_f0, X##_f, Y##_f);			\
174
    }								\
175
  while (0)
176
 
177
#define _FP_MUL_MEAT_1_wide(wfracbits, R, X, Y, doit)			\
178
  do									\
179
    {									\
180
      _FP_FRAC_DECL_2 (_FP_MUL_MEAT_1_wide_Z);				\
181
      _FP_MUL_MEAT_DW_1_wide ((wfracbits), _FP_MUL_MEAT_1_wide_Z,	\
182
			      X, Y, doit);				\
183
      /* Normalize since we know where the msb of the multiplicands	\
184
	 were (bit B), we know that the msb of the of the product is	\
185
	 at either 2B or 2B-1.  */					\
186
      _FP_FRAC_SRS_2 (_FP_MUL_MEAT_1_wide_Z, (wfracbits)-1,		\
187
		      2*(wfracbits));					\
188
      R##_f = _FP_MUL_MEAT_1_wide_Z_f0;					\
189
    }									\
190
  while (0)
191
 
192
/* Finally, a simple widening multiply algorithm.  What fun!  */
193
 
194
#define _FP_MUL_MEAT_DW_1_hard(wfracbits, R, X, Y)			\
195
  do									\
196
    {									\
197
      _FP_W_TYPE _FP_MUL_MEAT_DW_1_hard_xh, _FP_MUL_MEAT_DW_1_hard_xl;	\
198
      _FP_W_TYPE _FP_MUL_MEAT_DW_1_hard_yh, _FP_MUL_MEAT_DW_1_hard_yl;	\
199
      _FP_FRAC_DECL_2 (_FP_MUL_MEAT_DW_1_hard_a);			\
200
									\
201
      /* Split the words in half.  */					\
202
      _FP_MUL_MEAT_DW_1_hard_xh = X##_f >> (_FP_W_TYPE_SIZE/2);		\
203
      _FP_MUL_MEAT_DW_1_hard_xl						\
204
	= X##_f & (((_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE/2)) - 1);	\
205
      _FP_MUL_MEAT_DW_1_hard_yh = Y##_f >> (_FP_W_TYPE_SIZE/2);		\
206
      _FP_MUL_MEAT_DW_1_hard_yl						\
207
	= Y##_f & (((_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE/2)) - 1);	\
208
									\
209
      /* Multiply the pieces.  */					\
210
      R##_f0 = _FP_MUL_MEAT_DW_1_hard_xl * _FP_MUL_MEAT_DW_1_hard_yl;	\
211
      _FP_MUL_MEAT_DW_1_hard_a_f0					\
212
	= _FP_MUL_MEAT_DW_1_hard_xh * _FP_MUL_MEAT_DW_1_hard_yl;	\
213
      _FP_MUL_MEAT_DW_1_hard_a_f1					\
214
	= _FP_MUL_MEAT_DW_1_hard_xl * _FP_MUL_MEAT_DW_1_hard_yh;	\
215
      R##_f1 = _FP_MUL_MEAT_DW_1_hard_xh * _FP_MUL_MEAT_DW_1_hard_yh;	\
216
									\
217
      /* Reassemble into two full words.  */				\
218
      if ((_FP_MUL_MEAT_DW_1_hard_a_f0 += _FP_MUL_MEAT_DW_1_hard_a_f1)	\
219
	  < _FP_MUL_MEAT_DW_1_hard_a_f1)				\
220
	R##_f1 += (_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE/2);		\
221
      _FP_MUL_MEAT_DW_1_hard_a_f1					\
222
	= _FP_MUL_MEAT_DW_1_hard_a_f0 >> (_FP_W_TYPE_SIZE/2);		\
223
      _FP_MUL_MEAT_DW_1_hard_a_f0					\
224
	= _FP_MUL_MEAT_DW_1_hard_a_f0 << (_FP_W_TYPE_SIZE/2);		\
225
      _FP_FRAC_ADD_2 (R, R, _FP_MUL_MEAT_DW_1_hard_a);			\
226
    }									\
227
  while (0)
228
 
229
#define _FP_MUL_MEAT_1_hard(wfracbits, R, X, Y)			\
230
  do								\
231
    {								\
232
      _FP_FRAC_DECL_2 (_FP_MUL_MEAT_1_hard_z);			\
233
      _FP_MUL_MEAT_DW_1_hard ((wfracbits),			\
234
			      _FP_MUL_MEAT_1_hard_z, X, Y);	\
235
								\
236
      /* Normalize.  */						\
237
      _FP_FRAC_SRS_2 (_FP_MUL_MEAT_1_hard_z,			\
238
		      (wfracbits) - 1, 2*(wfracbits));		\
239
      R##_f = _FP_MUL_MEAT_1_hard_z_f0;				\
240
    }								\
241
  while (0)
242
 
243
 
244
/* Division algorithms: */
245
 
246
/* Basic.  Assuming the host word size is >= 2*FRACBITS, we can do the
247
   division immediately.  Give this macro either _FP_DIV_HELP_imm for
248
   C primitives or _FP_DIV_HELP_ldiv for the ISO function.  Which you
249
   choose will depend on what the compiler does with divrem4.  */
250
 
251
#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit)				\
252
  do									\
253
    {									\
254
      _FP_W_TYPE _FP_DIV_MEAT_1_imm_q, _FP_DIV_MEAT_1_imm_r;		\
255
      X##_f <<= (X##_f < Y##_f						\
256
		 ? R##_e--, _FP_WFRACBITS_##fs				\
257
		 : _FP_WFRACBITS_##fs - 1);				\
258
      doit (_FP_DIV_MEAT_1_imm_q, _FP_DIV_MEAT_1_imm_r, X##_f, Y##_f);	\
259
      R##_f = _FP_DIV_MEAT_1_imm_q | (_FP_DIV_MEAT_1_imm_r != 0);	\
260
    }									\
261
  while (0)
262
 
263
/* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd
264
   that may be useful in this situation.  This first is for a primitive
265
   that requires normalization, the second for one that does not.  Look
266
   for UDIV_NEEDS_NORMALIZATION to tell which your machine needs.  */
267
 
268
#define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y)				\
269
  do									\
270
    {									\
271
      _FP_W_TYPE _FP_DIV_MEAT_1_udiv_norm_nh;				\
272
      _FP_W_TYPE _FP_DIV_MEAT_1_udiv_norm_nl;				\
273
      _FP_W_TYPE _FP_DIV_MEAT_1_udiv_norm_q;				\
274
      _FP_W_TYPE _FP_DIV_MEAT_1_udiv_norm_r;				\
275
      _FP_W_TYPE _FP_DIV_MEAT_1_udiv_norm_y;				\
276
									\
277
      /* Normalize Y -- i.e. make the most significant bit set.  */	\
278
      _FP_DIV_MEAT_1_udiv_norm_y = Y##_f << _FP_WFRACXBITS_##fs;	\
279
									\
280
      /* Shift X op correspondingly high, that is, up one full word.  */ \
281
      if (X##_f < Y##_f)						\
282
	{								\
283
	  R##_e--;							\
284
	  _FP_DIV_MEAT_1_udiv_norm_nl = 0;				\
285
	  _FP_DIV_MEAT_1_udiv_norm_nh = X##_f;				\
286
	}								\
287
      else								\
288
	{								\
289
	  _FP_DIV_MEAT_1_udiv_norm_nl = X##_f << (_FP_W_TYPE_SIZE - 1);	\
290
	  _FP_DIV_MEAT_1_udiv_norm_nh = X##_f >> 1;			\
291
	}								\
292
									\
293
      udiv_qrnnd (_FP_DIV_MEAT_1_udiv_norm_q,				\
294
		  _FP_DIV_MEAT_1_udiv_norm_r,				\
295
		  _FP_DIV_MEAT_1_udiv_norm_nh,				\
296
		  _FP_DIV_MEAT_1_udiv_norm_nl,				\
297
		  _FP_DIV_MEAT_1_udiv_norm_y);				\
298
      R##_f = (_FP_DIV_MEAT_1_udiv_norm_q				\
299
	       | (_FP_DIV_MEAT_1_udiv_norm_r != 0));			\
300
    }									\
301
  while (0)
302
 
303
#define _FP_DIV_MEAT_1_udiv(fs, R, X, Y)				\
304
  do									\
305
    {									\
306
      _FP_W_TYPE _FP_DIV_MEAT_1_udiv_nh, _FP_DIV_MEAT_1_udiv_nl;	\
307
      _FP_W_TYPE _FP_DIV_MEAT_1_udiv_q, _FP_DIV_MEAT_1_udiv_r;		\
308
      if (X##_f < Y##_f)						\
309
	{								\
310
	  R##_e--;							\
311
	  _FP_DIV_MEAT_1_udiv_nl = X##_f << _FP_WFRACBITS_##fs;		\
312
	  _FP_DIV_MEAT_1_udiv_nh = X##_f >> _FP_WFRACXBITS_##fs;	\
313
	}								\
314
      else								\
315
	{								\
316
	  _FP_DIV_MEAT_1_udiv_nl = X##_f << (_FP_WFRACBITS_##fs - 1);	\
317
	  _FP_DIV_MEAT_1_udiv_nh = X##_f >> (_FP_WFRACXBITS_##fs + 1);	\
318
	}								\
319
      udiv_qrnnd (_FP_DIV_MEAT_1_udiv_q, _FP_DIV_MEAT_1_udiv_r,		\
320
		  _FP_DIV_MEAT_1_udiv_nh, _FP_DIV_MEAT_1_udiv_nl,	\
321
		  Y##_f);						\
322
      R##_f = _FP_DIV_MEAT_1_udiv_q | (_FP_DIV_MEAT_1_udiv_r != 0);	\
323
    }									\
324
  while (0)
325
 
326
 
327
/* Square root algorithms:
328
   We have just one right now, maybe Newton approximation
329
   should be added for those machines where division is fast.  */
330
 
331
#define _FP_SQRT_MEAT_1(R, S, T, X, q)		\
332
  do						\
333
    {						\
334
      while ((q) != _FP_WORK_ROUND)		\
335
	{					\
336
	  T##_f = S##_f + (q);			\
337
	  if (T##_f <= X##_f)			\
338
	    {					\
339
	      S##_f = T##_f + (q);		\
340
	      X##_f -= T##_f;			\
341
	      R##_f += (q);			\
342
	    }					\
343
	  _FP_FRAC_SLL_1 (X, 1);		\
344
	  (q) >>= 1;				\
345
	}					\
346
      if (X##_f)				\
347
	{					\
348
	  if (S##_f < X##_f)			\
349
	    R##_f |= _FP_WORK_ROUND;		\
350
	  R##_f |= _FP_WORK_STICKY;		\
351
	}					\
352
    }						\
353
  while (0)
354
 
355
/* Assembly/disassembly for converting to/from integral types.
356
   No shifting or overflow handled here.  */
357
 
358
#define _FP_FRAC_ASSEMBLE_1(r, X, rsize)	((r) = X##_f)
359
#define _FP_FRAC_DISASSEMBLE_1(X, r, rsize)	(X##_f = (r))
360
 
361
 
362
/* Convert FP values between word sizes.  */
363
 
364
#define _FP_FRAC_COPY_1_1(D, S)		(D##_f = S##_f)