OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgcc/] [config/] [m68k/] [fpgnulib.c] - Blame information for rev 734

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 734 jeremybenn
/* This is a stripped down version of floatlib.c.  It supplies only those
2
   functions which exist in libgcc, but for which there is not assembly
3
   language versions in m68k/lb1sf68.S.
4
 
5
   It also includes simplistic support for extended floats (by working in
6
   double precision).  You must compile this file again with -DEXTFLOAT
7
   to get this support.  */
8
 
9
/*
10
** gnulib support for software floating point.
11
** Copyright (C) 1991 by Pipeline Associates, Inc.  All rights reserved.
12
** Permission is granted to do *anything* you want with this file,
13
** commercial or otherwise, provided this message remains intact.  So there!
14
** I would appreciate receiving any updates/patches/changes that anyone
15
** makes, and am willing to be the repository for said changes (am I
16
** making a big mistake?).
17
**
18
** Pat Wood
19
** Pipeline Associates, Inc.
20
** pipeline!phw@motown.com or
21
** sun!pipeline!phw or
22
** uunet!motown!pipeline!phw
23
**
24
** 05/01/91 -- V1.0 -- first release to gcc mailing lists
25
** 05/04/91 -- V1.1 -- added float and double prototypes and return values
26
**                  -- fixed problems with adding and subtracting zero
27
**                  -- fixed rounding in truncdfsf2
28
**                  -- fixed SWAP define and tested on 386
29
*/
30
 
31
/*
32
** The following are routines that replace the gnulib soft floating point
33
** routines that are called automatically when -msoft-float is selected.
34
** The support single and double precision IEEE format, with provisions
35
** for byte-swapped machines (tested on 386).  Some of the double-precision
36
** routines work at full precision, but most of the hard ones simply punt
37
** and call the single precision routines, producing a loss of accuracy.
38
** long long support is not assumed or included.
39
** Overall accuracy is close to IEEE (actually 68882) for single-precision
40
** arithmetic.  I think there may still be a 1 in 1000 chance of a bit
41
** being rounded the wrong way during a multiply.  I'm not fussy enough to
42
** bother with it, but if anyone is, knock yourself out.
43
**
44
** Efficiency has only been addressed where it was obvious that something
45
** would make a big difference.  Anyone who wants to do this right for
46
** best speed should go in and rewrite in assembler.
47
**
48
** I have tested this only on a 68030 workstation and 386/ix integrated
49
** in with -msoft-float.
50
*/
51
 
52
/* the following deal with IEEE single-precision numbers */
53
#define EXCESS          126L
54
#define SIGNBIT         0x80000000L
55
#define HIDDEN          (1L << 23L)
56
#define SIGN(fp)        ((fp) & SIGNBIT)
57
#define EXP(fp)         (((fp) >> 23L) & 0xFF)
58
#define MANT(fp)        (((fp) & 0x7FFFFFL) | HIDDEN)
59
#define PACK(s,e,m)     ((s) | ((e) << 23L) | (m))
60
 
61
/* the following deal with IEEE double-precision numbers */
62
#define EXCESSD         1022L
63
#define HIDDEND         (1L << 20L)
64
#define EXPDBITS        11
65
#define EXPDMASK        0x7FFL
66
#define EXPD(fp)        (((fp.l.upper) >> 20L) & 0x7FFL)
67
#define SIGND(fp)       ((fp.l.upper) & SIGNBIT)
68
#define MANTD(fp)       (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \
69
                                (fp.l.lower >> 22))
70
#define MANTDMASK       0xFFFFFL /* mask of upper part */
71
 
72
/* the following deal with IEEE extended-precision numbers */
73
#define EXCESSX         16382L
74
#define HIDDENX         (1L << 31L)
75
#define EXPXBITS        15
76
#define EXPXMASK        0x7FFF
77
#define EXPX(fp)        (((fp.l.upper) >> 16) & EXPXMASK)
78
#define SIGNX(fp)       ((fp.l.upper) & SIGNBIT)
79
#define MANTXMASK       0x7FFFFFFFL /* mask of upper part */
80
 
81
union double_long
82
{
83
  double d;
84
  struct {
85
      long upper;
86
      unsigned long lower;
87
    } l;
88
};
89
 
90
union float_long {
91
  float f;
92
  long l;
93
};
94
 
95
union long_double_long
96
{
97
  long double ld;
98
  struct
99
    {
100
      long upper;
101
      unsigned long middle;
102
      unsigned long lower;
103
    } l;
104
};
105
 
106
#ifndef EXTFLOAT
107
 
108
int
109
__unordsf2(float a, float b)
110
{
111
  union float_long fl;
112
 
113
  fl.f = a;
114
  if (EXP(fl.l) == EXP(~0u) && (MANT(fl.l) & ~HIDDEN) != 0)
115
    return 1;
116
  fl.f = b;
117
  if (EXP(fl.l) == EXP(~0u) && (MANT(fl.l) & ~HIDDEN) != 0)
118
    return 1;
119
  return 0;
120
}
121
 
122
int
123
__unorddf2(double a, double b)
124
{
125
  union double_long dl;
126
 
127
  dl.d = a;
128
  if (EXPD(dl) == EXPDMASK
129
      && ((dl.l.upper & MANTDMASK) != 0 || dl.l.lower != 0))
130
    return 1;
131
  dl.d = b;
132
  if (EXPD(dl) == EXPDMASK
133
      && ((dl.l.upper & MANTDMASK) != 0 || dl.l.lower != 0))
134
    return 1;
135
  return 0;
136
}
137
 
138
/* convert unsigned int to double */
139
double
140
__floatunsidf (unsigned long a1)
141
{
142
  long exp = 32 + EXCESSD;
143
  union double_long dl;
144
 
145
  if (!a1)
146
    {
147
      dl.l.upper = dl.l.lower = 0;
148
      return dl.d;
149
    }
150
 
151
  while (a1 < 0x2000000L)
152
    {
153
      a1 <<= 4;
154
      exp -= 4;
155
    }
156
 
157
  while (a1 < 0x80000000L)
158
    {
159
      a1 <<= 1;
160
      exp--;
161
    }
162
 
163
  /* pack up and go home */
164
  dl.l.upper = exp << 20L;
165
  dl.l.upper |= (a1 >> 11L) & ~HIDDEND;
166
  dl.l.lower = a1 << 21L;
167
 
168
  return dl.d;
169
}
170
 
171
/* convert int to double */
172
double
173
__floatsidf (long a1)
174
{
175
  long sign = 0, exp = 31 + EXCESSD;
176
  union double_long dl;
177
 
178
  if (!a1)
179
    {
180
      dl.l.upper = dl.l.lower = 0;
181
      return dl.d;
182
    }
183
 
184
  if (a1 < 0)
185
    {
186
      sign = SIGNBIT;
187
      a1 = (long)-(unsigned long)a1;
188
      if (a1 < 0)
189
        {
190
          dl.l.upper = SIGNBIT | ((32 + EXCESSD) << 20L);
191
          dl.l.lower = 0;
192
          return dl.d;
193
        }
194
    }
195
 
196
  while (a1 < 0x1000000L)
197
    {
198
      a1 <<= 4;
199
      exp -= 4;
200
    }
201
 
202
  while (a1 < 0x40000000L)
203
    {
204
      a1 <<= 1;
205
      exp--;
206
    }
207
 
208
  /* pack up and go home */
209
  dl.l.upper = sign;
210
  dl.l.upper |= exp << 20L;
211
  dl.l.upper |= (a1 >> 10L) & ~HIDDEND;
212
  dl.l.lower = a1 << 22L;
213
 
214
  return dl.d;
215
}
216
 
217
/* convert unsigned int to float */
218
float
219
__floatunsisf (unsigned long l)
220
{
221
  double foo = __floatunsidf (l);
222
  return foo;
223
}
224
 
225
/* convert int to float */
226
float
227
__floatsisf (long l)
228
{
229
  double foo = __floatsidf (l);
230
  return foo;
231
}
232
 
233
/* convert float to double */
234
double
235
__extendsfdf2 (float a1)
236
{
237
  register union float_long fl1;
238
  register union double_long dl;
239
  register long exp;
240
  register long mant;
241
 
242
  fl1.f = a1;
243
 
244
  dl.l.upper = SIGN (fl1.l);
245
  if ((fl1.l & ~SIGNBIT) == 0)
246
    {
247
      dl.l.lower = 0;
248
      return dl.d;
249
    }
250
 
251
  exp = EXP(fl1.l);
252
  mant = MANT (fl1.l) & ~HIDDEN;
253
  if (exp == 0)
254
    {
255
      /* Denormal.  */
256
      exp = 1;
257
      while (!(mant & HIDDEN))
258
        {
259
          mant <<= 1;
260
          exp--;
261
        }
262
      mant &= ~HIDDEN;
263
    }
264
  exp = exp - EXCESS + EXCESSD;
265
  dl.l.upper |= exp << 20;
266
  dl.l.upper |= mant >> 3;
267
  dl.l.lower = mant << 29;
268
 
269
  return dl.d;
270
}
271
 
272
/* convert double to float */
273
float
274
__truncdfsf2 (double a1)
275
{
276
  register long exp;
277
  register long mant;
278
  register union float_long fl;
279
  register union double_long dl1;
280
  int sticky;
281
  int shift;
282
 
283
  dl1.d = a1;
284
 
285
  if ((dl1.l.upper & ~SIGNBIT) == 0 && !dl1.l.lower)
286
    {
287
      fl.l = SIGND(dl1);
288
      return fl.f;
289
    }
290
 
291
  exp = EXPD (dl1) - EXCESSD + EXCESS;
292
 
293
  sticky = dl1.l.lower & ((1 << 22) - 1);
294
  mant = MANTD (dl1);
295
  /* shift double mantissa 6 bits so we can round */
296
  sticky |= mant & ((1 << 6) - 1);
297
  mant >>= 6;
298
 
299
  /* Check for underflow and denormals.  */
300
  if (exp <= 0)
301
    {
302
      if (exp < -24)
303
        {
304
          sticky |= mant;
305
          mant = 0;
306
        }
307
      else
308
        {
309
          sticky |= mant & ((1 << (1 - exp)) - 1);
310
          mant >>= 1 - exp;
311
        }
312
      exp = 0;
313
    }
314
 
315
  /* now round */
316
  shift = 1;
317
  if ((mant & 1) && (sticky || (mant & 2)))
318
    {
319
      int rounding = exp ? 2 : 1;
320
 
321
      mant += 1;
322
 
323
      /* did the round overflow? */
324
      if (mant >= (HIDDEN << rounding))
325
        {
326
          exp++;
327
          shift = rounding;
328
        }
329
    }
330
  /* shift down */
331
  mant >>= shift;
332
 
333
  mant &= ~HIDDEN;
334
 
335
  /* pack up and go home */
336
  fl.l = PACK (SIGND (dl1), exp, mant);
337
  return (fl.f);
338
}
339
 
340
/* convert double to int */
341
long
342
__fixdfsi (double a1)
343
{
344
  register union double_long dl1;
345
  register long exp;
346
  register long l;
347
 
348
  dl1.d = a1;
349
 
350
  if (!dl1.l.upper && !dl1.l.lower)
351
    return 0;
352
 
353
  exp = EXPD (dl1) - EXCESSD - 31;
354
  l = MANTD (dl1);
355
 
356
  if (exp > 0)
357
    {
358
      /* Return largest integer.  */
359
      return SIGND (dl1) ? 0x80000000L : 0x7fffffffL;
360
    }
361
 
362
  if (exp <= -32)
363
    return 0;
364
 
365
  /* shift down until exp = 0 */
366
  if (exp < 0)
367
    l >>= -exp;
368
 
369
  return (SIGND (dl1) ? -l : l);
370
}
371
 
372
/* convert float to int */
373
long
374
__fixsfsi (float a1)
375
{
376
  double foo = a1;
377
  return __fixdfsi (foo);
378
}
379
 
380
#else /* EXTFLOAT */
381
 
382
/* We do not need these routines for coldfire, as it has no extended
383
   float format. */
384
#if !defined (__mcoldfire__)
385
 
386
/* Primitive extended precision floating point support.
387
 
388
   We assume all numbers are normalized, don't do any rounding, etc.  */
389
 
390
/* Prototypes for the above in case we use them.  */
391
double __floatunsidf (unsigned long);
392
double __floatsidf (long);
393
float __floatsisf (long);
394
double __extendsfdf2 (float);
395
float __truncdfsf2 (double);
396
long __fixdfsi (double);
397
long __fixsfsi (float);
398
 
399
int
400
__unordxf2(long double a, long double b)
401
{
402
  union long_double_long ldl;
403
 
404
  ldl.ld = a;
405
  if (EXPX(ldl) == EXPXMASK
406
      && ((ldl.l.middle & MANTXMASK) != 0 || ldl.l.lower != 0))
407
    return 1;
408
  ldl.ld = b;
409
  if (EXPX(ldl) == EXPXMASK
410
      && ((ldl.l.middle & MANTXMASK) != 0 || ldl.l.lower != 0))
411
    return 1;
412
  return 0;
413
}
414
 
415
/* convert double to long double */
416
long double
417
__extenddfxf2 (double d)
418
{
419
  register union double_long dl;
420
  register union long_double_long ldl;
421
  register long exp;
422
 
423
  dl.d = d;
424
  /*printf ("dfxf in: %g\n", d);*/
425
 
426
  ldl.l.upper = SIGND (dl);
427
  if ((dl.l.upper & ~SIGNBIT) == 0 && !dl.l.lower)
428
    {
429
      ldl.l.middle = 0;
430
      ldl.l.lower = 0;
431
      return ldl.ld;
432
    }
433
 
434
  exp = EXPD (dl) - EXCESSD + EXCESSX;
435
  ldl.l.upper |= exp << 16;
436
  ldl.l.middle = HIDDENX;
437
  /* 31-20: # mantissa bits in ldl.l.middle - # mantissa bits in dl.l.upper */
438
  ldl.l.middle |= (dl.l.upper & MANTDMASK) << (31 - 20);
439
  /* 1+20: explicit-integer-bit + # mantissa bits in dl.l.upper */
440
  ldl.l.middle |= dl.l.lower >> (1 + 20);
441
  /* 32 - 21: # bits of dl.l.lower in ldl.l.middle */
442
  ldl.l.lower = dl.l.lower << (32 - 21);
443
 
444
  /*printf ("dfxf out: %s\n", dumpxf (ldl.ld));*/
445
  return ldl.ld;
446
}
447
 
448
/* convert long double to double */
449
double
450
__truncxfdf2 (long double ld)
451
{
452
  register long exp;
453
  register union double_long dl;
454
  register union long_double_long ldl;
455
 
456
  ldl.ld = ld;
457
  /*printf ("xfdf in: %s\n", dumpxf (ld));*/
458
 
459
  dl.l.upper = SIGNX (ldl);
460
  if ((ldl.l.upper & ~SIGNBIT) == 0 && !ldl.l.middle && !ldl.l.lower)
461
    {
462
      dl.l.lower = 0;
463
      return dl.d;
464
    }
465
 
466
  exp = EXPX (ldl) - EXCESSX + EXCESSD;
467
  /* ??? quick and dirty: keep `exp' sane */
468
  if (exp >= EXPDMASK)
469
    exp = EXPDMASK - 1;
470
  dl.l.upper |= exp << (32 - (EXPDBITS + 1));
471
  /* +1-1: add one for sign bit, but take one off for explicit-integer-bit */
472
  dl.l.upper |= (ldl.l.middle & MANTXMASK) >> (EXPDBITS + 1 - 1);
473
  dl.l.lower = (ldl.l.middle & MANTXMASK) << (32 - (EXPDBITS + 1 - 1));
474
  dl.l.lower |= ldl.l.lower >> (EXPDBITS + 1 - 1);
475
 
476
  /*printf ("xfdf out: %g\n", dl.d);*/
477
  return dl.d;
478
}
479
 
480
/* convert a float to a long double */
481
long double
482
__extendsfxf2 (float f)
483
{
484
  long double foo = __extenddfxf2 (__extendsfdf2 (f));
485
  return foo;
486
}
487
 
488
/* convert a long double to a float */
489
float
490
__truncxfsf2 (long double ld)
491
{
492
  float foo = __truncdfsf2 (__truncxfdf2 (ld));
493
  return foo;
494
}
495
 
496
/* convert an int to a long double */
497
long double
498
__floatsixf (long l)
499
{
500
  double foo = __floatsidf (l);
501
  return foo;
502
}
503
 
504
/* convert an unsigned int to a long double */
505
long double
506
__floatunsixf (unsigned long l)
507
{
508
  double foo = __floatunsidf (l);
509
  return foo;
510
}
511
 
512
/* convert a long double to an int */
513
long
514
__fixxfsi (long double ld)
515
{
516
  long foo = __fixdfsi ((double) ld);
517
  return foo;
518
}
519
 
520
/* The remaining provide crude math support by working in double precision.  */
521
 
522
long double
523
__addxf3 (long double x1, long double x2)
524
{
525
  return (double) x1 + (double) x2;
526
}
527
 
528
long double
529
__subxf3 (long double x1, long double x2)
530
{
531
  return (double) x1 - (double) x2;
532
}
533
 
534
long double
535
__mulxf3 (long double x1, long double x2)
536
{
537
  return (double) x1 * (double) x2;
538
}
539
 
540
long double
541
__divxf3 (long double x1, long double x2)
542
{
543
  return (double) x1 / (double) x2;
544
}
545
 
546
long double
547
__negxf2 (long double x1)
548
{
549
  return - (double) x1;
550
}
551
 
552
long
553
__cmpxf2 (long double x1, long double x2)
554
{
555
  return __cmpdf2 ((double) x1, (double) x2);
556
}
557
 
558
long
559
__eqxf2 (long double x1, long double x2)
560
{
561
  return __cmpdf2 ((double) x1, (double) x2);
562
}
563
 
564
long
565
__nexf2 (long double x1, long double x2)
566
{
567
  return __cmpdf2 ((double) x1, (double) x2);
568
}
569
 
570
long
571
__ltxf2 (long double x1, long double x2)
572
{
573
  return __cmpdf2 ((double) x1, (double) x2);
574
}
575
 
576
long
577
__lexf2 (long double x1, long double x2)
578
{
579
  return __cmpdf2 ((double) x1, (double) x2);
580
}
581
 
582
long
583
__gtxf2 (long double x1, long double x2)
584
{
585
  return __cmpdf2 ((double) x1, (double) x2);
586
}
587
 
588
long
589
__gexf2 (long double x1, long double x2)
590
{
591
  return __cmpdf2 ((double) x1, (double) x2);
592
}
593
 
594
#endif /* !__mcoldfire__ */
595
#endif /* EXTFLOAT */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.