BSD 4_4_Lite2 development
[unix-history] / usr / src / contrib / gcc-2.3.3 / floatlib.c
CommitLineData
9221ab2b
C
1/*
2** libgcc support for software floating point.
3** Copyright (C) 1991 by Pipeline Associates, Inc. All rights reserved.
4** Permission is granted to do *anything* you want with this file,
5** commercial or otherwise, provided this message remains intact. So there!
6** I would appreciate receiving any updates/patches/changes that anyone
7** makes, and am willing to be the repository for said changes (am I
8** making a big mistake?).
9
10Warning! Only single-precision is actually implemented. This file
11won't really be much use until double-precision is supported.
12
13However, once that is done, this file might eventually become a
14replacement for libgcc1.c. It might also make possible
15cross-compilation for an IEEE target machine from a non-IEEE
16host such as a VAX.
17
18If you'd like to work on completing this, please talk to rms@gnu.ai.mit.edu.
19
20
21**
22** Pat Wood
23** Pipeline Associates, Inc.
24** pipeline!phw@motown.com or
25** sun!pipeline!phw or
26** uunet!motown!pipeline!phw
27**
28** 05/01/91 -- V1.0 -- first release to gcc mailing lists
29** 05/04/91 -- V1.1 -- added float and double prototypes and return values
30** -- fixed problems with adding and subtracting zero
31** -- fixed rounding in truncdfsf2
32** -- fixed SWAP define and tested on 386
33*/
34
35/*
36** The following are routines that replace the libgcc soft floating point
37** routines that are called automatically when -msoft-float is selected.
38** The support single and double precision IEEE format, with provisions
39** for byte-swapped machines (tested on 386). Some of the double-precision
40** routines work at full precision, but most of the hard ones simply punt
41** and call the single precision routines, producing a loss of accuracy.
42** long long support is not assumed or included.
43** Overall accuracy is close to IEEE (actually 68882) for single-precision
44** arithmetic. I think there may still be a 1 in 1000 chance of a bit
45** being rounded the wrong way during a multiply. I'm not fussy enough to
46** bother with it, but if anyone is, knock yourself out.
47**
48** Efficiency has only been addressed where it was obvious that something
49** would make a big difference. Anyone who wants to do this right for
50** best speed should go in and rewrite in assembler.
51**
52** I have tested this only on a 68030 workstation and 386/ix integrated
53** in with -msoft-float.
54*/
55
56/* the following deal with IEEE single-precision numbers */
57#define EXCESS 126
58#define SIGNBIT 0x80000000
59#define HIDDEN (1 << 23)
60#define SIGN(fp) ((fp) & SIGNBIT)
61#define EXP(fp) (((fp) >> 23) & 0xFF)
62#define MANT(fp) (((fp) & 0x7FFFFF) | HIDDEN)
63#define PACK(s,e,m) ((s) | ((e) << 23) | (m))
64
65/* the following deal with IEEE double-precision numbers */
66#define EXCESSD 1022
67#define HIDDEND (1 << 20)
68#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
69#define SIGND(fp) ((fp.l.upper) & SIGNBIT)
70#define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \
71 (fp.l.lower >> 22))
72
73/* define SWAP for 386/960 reverse-byte-order brain-damaged CPUs */
74union double_long
75 {
76 double d;
77#ifdef SWAP
78 struct {
79 unsigned long lower;
80 long upper;
81 } l;
82#else
83 struct {
84 long upper;
85 unsigned long lower;
86 } l;
87#endif
88 };
89
90union float_long
91 {
92 float f;
93 long l;
94 };
95
96/* add two floats */
97float
98__addsf3 (float a1, float a2)
99{
100 register long mant1, mant2;
101 register union float_long fl1, fl2;
102 register int exp1, exp2;
103 int sign = 0;
104
105 fl1.f = a1;
106 fl2.f = a2;
107
108 /* check for zero args */
109 if (!fl1.l)
110 return (fl2.f);
111 if (!fl2.l)
112 return (fl1.f);
113
114 exp1 = EXP (fl1.l);
115 exp2 = EXP (fl2.l);
116
117 if (exp1 > exp2 + 25)
118 return (fl1.l);
119 if (exp2 > exp1 + 25)
120 return (fl2.l);
121
122 /* do everything in excess precision so's we can round later */
123 mant1 = MANT (fl1.l) << 6;
124 mant2 = MANT (fl2.l) << 6;
125
126 if (SIGN (fl1.l))
127 mant1 = -mant1;
128 if (SIGN (fl2.l))
129 mant2 = -mant2;
130
131 if (exp1 > exp2)
132 {
133 mant2 >>= exp1 - exp2;
134 }
135 else
136 {
137 mant1 >>= exp2 - exp1;
138 exp1 = exp2;
139 }
140 mant1 += mant2;
141
142 if (mant1 < 0)
143 {
144 mant1 = -mant1;
145 sign = SIGNBIT;
146 }
147 else if (!mant1)
148 return (0);
149
150 /* normalize up */
151 while (!(mant1 & 0xE0000000))
152 {
153 mant1 <<= 1;
154 exp1--;
155 }
156
157 /* normalize down? */
158 if (mant1 & (1 << 30))
159 {
160 mant1 >>= 1;
161 exp1++;
162 }
163
164 /* round to even */
165 mant1 += (mant1 & 0x40) ? 0x20 : 0x1F;
166
167 /* normalize down? */
168 if (mant1 & (1 << 30))
169 {
170 mant1 >>= 1;
171 exp1++;
172 }
173
174 /* lose extra precision */
175 mant1 >>= 6;
176
177 /* turn off hidden bit */
178 mant1 &= ~HIDDEN;
179
180 /* pack up and go home */
181 fl1.l = PACK (sign, exp1, mant1);
182 return (fl1.f);
183}
184
185/* subtract two floats */
186float
187__subsf3 (float a1, float a2)
188{
189 register union float_long fl1, fl2;
190
191 fl1.f = a1;
192 fl2.f = a2;
193
194 /* check for zero args */
195 if (!fl2.l)
196 return (fl1.f);
197 if (!fl1.l)
198 return (-fl2.f);
199
200 /* twiddle sign bit and add */
201 fl2.l ^= SIGNBIT;
202 return __addsf3 (a1, fl2.f);
203}
204
205/* compare two floats */
206long
207__cmpsf2 (float a1, float a2)
208{
209 register union float_long fl1, fl2;
210
211 fl1.f = a1;
212 fl2.f = a2;
213
214 if (SIGN (fl1.l) && SIGN (fl2.l))
215 {
216 fl1.l ^= SIGNBIT;
217 fl2.l ^= SIGNBIT;
218 }
219 if (fl1.l < fl2.l)
220 return (-1);
221 if (fl1.l > fl2.l)
222 return (1);
223 return (0);
224}
225
226/* multiply two floats */
227float
228__mulsf3 (float a1, float a2)
229{
230 register union float_long fl1, fl2;
231 register unsigned long result;
232 register int exp;
233 int sign;
234
235 fl1.f = a1;
236 fl2.f = a2;
237
238 if (!fl1.l || !fl2.l)
239 return (0);
240
241 /* compute sign and exponent */
242 sign = SIGN (fl1.l) ^ SIGN (fl2.l);
243 exp = EXP (fl1.l) - EXCESS;
244 exp += EXP (fl2.l);
245
246 fl1.l = MANT (fl1.l);
247 fl2.l = MANT (fl2.l);
248
249 /* the multiply is done as one 16x16 multiply and two 16x8 multiples */
250 result = (fl1.l >> 8) * (fl2.l >> 8);
251 result += ((fl1.l & 0xFF) * (fl2.l >> 8)) >> 8;
252 result += ((fl2.l & 0xFF) * (fl1.l >> 8)) >> 8;
253
254 if (result & 0x80000000)
255 {
256 /* round */
257 result += 0x80;
258 result >>= 8;
259 }
260 else
261 {
262 /* round */
263 result += 0x40;
264 result >>= 7;
265 exp--;
266 }
267
268 result &= ~HIDDEN;
269
270 /* pack up and go home */
271 fl1.l = PACK (sign, exp, result);
272 return (fl1.f);
273}
274
275/* divide two floats */
276float
277__divsf3 (float a1, float a2)
278{
279 register union float_long fl1, fl2;
280 register int result;
281 register int mask;
282 register int exp, sign;
283
284 fl1.f = a1;
285 fl2.f = a2;
286
287 /* subtract exponents */
288 exp = EXP (fl1.l) - EXP (fl2.l) + EXCESS;
289
290 /* compute sign */
291 sign = SIGN (fl1.l) ^ SIGN (fl2.l);
292
293 /* divide by zero??? */
294 if (!fl2.l)
295 /* return NaN or -NaN */
296 return (sign ? 0xFFFFFFFF : 0x7FFFFFFF);
297
298 /* numerator zero??? */
299 if (!fl1.l)
300 return (0);
301
302 /* now get mantissas */
303 fl1.l = MANT (fl1.l);
304 fl2.l = MANT (fl2.l);
305
306 /* this assures we have 25 bits of precision in the end */
307 if (fl1.l < fl2.l)
308 {
309 fl1.l <<= 1;
310 exp--;
311 }
312
313 /* now we perform repeated subtraction of fl2.l from fl1.l */
314 mask = 0x1000000;
315 result = 0;
316 while (mask)
317 {
318 if (fl1.l >= fl2.l)
319 {
320 result |= mask;
321 fl1.l -= fl2.l;
322 }
323 fl1.l <<= 1;
324 mask >>= 1;
325 }
326
327 /* round */
328 result += 1;
329
330 /* normalize down */
331 exp++;
332 result >>= 1;
333
334 result &= ~HIDDEN;
335
336 /* pack up and go home */
337 fl1.l = PACK (sign, exp, result);
338 return (fl1.f);
339}
340
341/* convert int to double */
342double
343__floatsidf (register long a1)
344{
345 register int sign = 0, exp = 31 + EXCESSD;
346 union double_long dl;
347
348 if (!a1)
349 {
350 dl.l.upper = dl.l.lower = 0;
351 return (dl.d);
352 }
353
354 if (a1 < 0)
355 {
356 sign = SIGNBIT;
357 a1 = -a1;
358 }
359
360 while (a1 < 0x1000000)
361 {
362 a1 <<= 4;
363 exp -= 4;
364 }
365
366 while (a1 < 0x40000000)
367 {
368 a1 <<= 1;
369 exp--;
370 }
371
372 /* pack up and go home */
373 dl.l.upper = sign;
374 dl.l.upper |= exp << 20;
375 dl.l.upper |= (a1 >> 10) & ~HIDDEND;
376 dl.l.lower = a1 << 22;
377
378 return (dl.d);
379}
380
381/* negate a float */
382float
383__negsf2 (float a1)
384{
385 register union float_long fl1;
386
387 fl1.f = a1;
388 if (!fl1.l)
389 return (0);
390
391 fl1.l ^= SIGNBIT;
392 return (fl1.f);
393}
394
395/* negate a double */
396double
397__negdf2 (double a1)
398{
399 register union double_long dl1;
400
401 dl1.d = a1;
402
403 if (!dl1.l.upper && !dl1.l.lower)
404 return (dl1.d);
405
406 dl1.l.upper ^= SIGNBIT;
407 return (dl1.d);
408}
409
410/* convert float to double */
411double
412__extendsfdf2 (float a1)
413{
414 register union float_long fl1;
415 register union double_long dl;
416 register int exp;
417
418 fl1.f = a1;
419
420 if (!fl1.l)
421 {
422 dl.l.upper = dl.l.lower = 0;
423 return (dl.d);
424 }
425
426 dl.l.upper = SIGN (fl1.l);
427 exp = EXP (fl1.l) - EXCESS + EXCESSD;
428 dl.l.upper |= exp << 20;
429 dl.l.upper |= (MANT (fl1.l) & ~HIDDEN) >> 3;
430 dl.l.lower = MANT (fl1.l) << 29;
431
432 return (dl.d);
433}
434
435/* convert double to float */
436float
437__truncdfsf2 (double a1)
438{
439 register int exp;
440 register long mant;
441 register union float_long fl;
442 register union double_long dl1;
443
444 dl1.d = a1;
445
446 if (!dl1.l.upper && !dl1.l.lower)
447 return (0);
448
449 exp = EXPD (dl1) - EXCESSD + EXCESS;
450
451 /* shift double mantissa 6 bits so we can round */
452 mant = MANTD (dl1) >> 6;
453
454 /* now round and shift down */
455 mant += 1;
456 mant >>= 1;
457
458 /* did the round overflow? */
459 if (mant & 0xFF000000)
460 {
461 mant >>= 1;
462 exp++;
463 }
464
465 mant &= ~HIDDEN;
466
467 /* pack up and go home */
468 fl.l = PACK (SIGND (dl1), exp, mant);
469 return (fl.f);
470}
471
472/* compare two doubles */
473long
474__cmpdf2 (double a1, double a2)
475{
476 register union double_long dl1, dl2;
477
478 dl1.d = a1;
479 dl2.d = a2;
480
481 if (SIGND (dl1) && SIGND (dl2))
482 {
483 dl1.l.upper ^= SIGNBIT;
484 dl2.l.upper ^= SIGNBIT;
485 }
486 if (dl1.l.upper < dl2.l.upper)
487 return (-1);
488 if (dl1.l.upper > dl2.l.upper)
489 return (1);
490 if (dl1.l.lower < dl2.l.lower)
491 return (-1);
492 if (dl1.l.lower > dl2.l.lower)
493 return (1);
494 return (0);
495}
496
497/* convert double to int */
498long
499__fixdfsi (double a1)
500{
501 register union double_long dl1;
502 register int exp;
503 register long l;
504
505 dl1.d = a1;
506
507 if (!dl1.l.upper && !dl1.l.lower)
508 return (0);
509
510 exp = EXPD (dl1) - EXCESSD - 31;
511 l = MANTD (dl1);
512
513 if (exp > 0)
514 return (0x7FFFFFFF | SIGND (dl1)); /* largest integer */
515
516 /* shift down until exp = 0 or l = 0 */
517 if (exp < 0 && exp > -32 && l)
518 l >>= -exp;
519 else
520 return (0);
521
522 return (SIGND (dl1) ? -l : l);
523}
524
525/* convert double to unsigned int */
526unsigned
527long __fixunsdfsi (double a1)
528{
529 register union double_long dl1;
530 register int exp;
531 register unsigned long l;
532
533 dl1.d = a1;
534
535 if (!dl1.l.upper && !dl1.l.lower)
536 return (0);
537
538 exp = EXPD (dl1) - EXCESSD - 32;
539 l = (((((dl1.l.upper) & 0xFFFFF) | HIDDEND) << 11) | (dl1.l.lower >> 21));
540
541 if (exp > 0)
542 return (0xFFFFFFFF); /* largest integer */
543
544 /* shift down until exp = 0 or l = 0 */
545 if (exp < 0 && exp > -32 && l)
546 l >>= -exp;
547 else
548 return (0);
549
550 return (l);
551}
552
553/* For now, the hard double-precision routines simply
554 punt and do it in single */
555/* addtwo doubles */
556double
557__adddf3 (double a1, double a2)
558{
559 return ((float) a1 + (float) a2);
560}
561
562/* subtract two doubles */
563double
564__subdf3 (double a1, double a2)
565{
566 return ((float) a1 - (float) a2);
567}
568
569/* multiply two doubles */
570double
571__muldf3 (double a1, double a2)
572{
573 return ((float) a1 * (float) a2);
574}
575
576/* divide two doubles */
577double
578__divdf3 (double a1, double a2)
579{
580 return ((float) a1 / (float) a2);
581}