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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [config/] [m68k/] [fpgnulib.c] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/* 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.asm.
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
/* convert int to double */
109
double
110
__floatsidf (long a1)
111
{
112
  long sign = 0, exp = 31 + EXCESSD;
113
  union double_long dl;
114
 
115
  if (!a1)
116
    {
117
      dl.l.upper = dl.l.lower = 0;
118
      return dl.d;
119
    }
120
 
121
  if (a1 < 0)
122
    {
123
      sign = SIGNBIT;
124
      a1 = (long)-(unsigned long)a1;
125
      if (a1 < 0)
126
        {
127
          dl.l.upper = SIGNBIT | ((32 + EXCESSD) << 20L);
128
          dl.l.lower = 0;
129
          return dl.d;
130
        }
131
    }
132
 
133
  while (a1 < 0x1000000L)
134
    {
135
      a1 <<= 4;
136
      exp -= 4;
137
    }
138
 
139
  while (a1 < 0x40000000L)
140
    {
141
      a1 <<= 1;
142
      exp--;
143
    }
144
 
145
  /* pack up and go home */
146
  dl.l.upper = sign;
147
  dl.l.upper |= exp << 20L;
148
  dl.l.upper |= (a1 >> 10L) & ~HIDDEND;
149
  dl.l.lower = a1 << 22L;
150
 
151
  return dl.d;
152
}
153
 
154
/* convert int to float */
155
float
156
__floatsisf (long l)
157
{
158
  double foo = __floatsidf (l);
159
  return foo;
160
}
161
 
162
/* convert float to double */
163
double
164
__extendsfdf2 (float a1)
165
{
166
  register union float_long fl1;
167
  register union double_long dl;
168
  register long exp;
169
  register long mant;
170
 
171
  fl1.f = a1;
172
 
173
  if (!fl1.l)
174
    {
175
      dl.l.upper = dl.l.lower = 0;
176
      return dl.d;
177
    }
178
 
179
  dl.l.upper = SIGN (fl1.l);
180
  exp = EXP(fl1.l);
181
  mant = MANT (fl1.l) & ~HIDDEN;
182
  if (exp == 0)
183
    {
184
      /* Denormal.  */
185
      exp = 1;
186
      while (!(mant & HIDDEN))
187
        {
188
          mant <<= 1;
189
          exp--;
190
        }
191
      mant &= ~HIDDEN;
192
    }
193
  exp = exp - EXCESS + EXCESSD;
194
  dl.l.upper |= exp << 20;
195
  dl.l.upper |= mant >> 3;
196
  dl.l.lower = mant << 29;
197
 
198
  return dl.d;
199
}
200
 
201
/* convert double to float */
202
float
203
__truncdfsf2 (double a1)
204
{
205
  register long exp;
206
  register long mant;
207
  register union float_long fl;
208
  register union double_long dl1;
209
 
210
  dl1.d = a1;
211
 
212
  if (!dl1.l.upper && !dl1.l.lower)
213
    return 0;
214
 
215
  exp = EXPD (dl1) - EXCESSD + EXCESS;
216
 
217
  /* shift double mantissa 6 bits so we can round */
218
  mant = MANTD (dl1) >> 6;
219
 
220
  /* Check for underflow and denormals.  */
221
  if (exp <= 0)
222
    {
223
      if (exp < -24)
224
        mant = 0;
225
      else
226
        mant >>= 1 - exp;
227
      exp = 0;
228
    }
229
 
230
  /* now round and shift down */
231
  mant += 1;
232
  mant >>= 1;
233
 
234
  /* did the round overflow? */
235
  if (mant & 0xFF000000L)
236
    {
237
      mant >>= 1;
238
      exp++;
239
    }
240
 
241
  mant &= ~HIDDEN;
242
 
243
  /* pack up and go home */
244
  fl.l = PACK (SIGND (dl1), exp, mant);
245
  return (fl.f);
246
}
247
 
248
/* convert double to int */
249
long
250
__fixdfsi (double a1)
251
{
252
  register union double_long dl1;
253
  register long exp;
254
  register long l;
255
 
256
  dl1.d = a1;
257
 
258
  if (!dl1.l.upper && !dl1.l.lower)
259
    return 0;
260
 
261
  exp = EXPD (dl1) - EXCESSD - 31;
262
  l = MANTD (dl1);
263
 
264
  if (exp > 0)
265
    {
266
      /* Return largest integer.  */
267
      return SIGND (dl1) ? 0x80000000L : 0x7fffffffL;
268
    }
269
 
270
  if (exp <= -32)
271
    return 0;
272
 
273
  /* shift down until exp = 0 */
274
  if (exp < 0)
275
    l >>= -exp;
276
 
277
  return (SIGND (dl1) ? -l : l);
278
}
279
 
280
/* convert float to int */
281
long
282
__fixsfsi (float a1)
283
{
284
  double foo = a1;
285
  return __fixdfsi (foo);
286
}
287
 
288
#else /* EXTFLOAT */
289
 
290
/* Primitive extended precision floating point support.
291
 
292
   We assume all numbers are normalized, don't do any rounding, etc.  */
293
 
294
/* Prototypes for the above in case we use them.  */
295
double __floatsidf (long);
296
float __floatsisf (long);
297
double __extendsfdf2 (float);
298
float __truncdfsf2 (double);
299
long __fixdfsi (double);
300
long __fixsfsi (float);
301
 
302
/* convert double to long double */
303
long double
304
__extenddfxf2 (double d)
305
{
306
  register union double_long dl;
307
  register union long_double_long ldl;
308
  register long exp;
309
 
310
  dl.d = d;
311
  /*printf ("dfxf in: %g\n", d);*/
312
 
313
  if (!dl.l.upper && !dl.l.lower)
314
    return 0;
315
 
316
  ldl.l.upper = SIGND (dl);
317
  exp = EXPD (dl) - EXCESSD + EXCESSX;
318
  ldl.l.upper |= exp << 16;
319
  ldl.l.middle = HIDDENX;
320
  /* 31-20: # mantissa bits in ldl.l.middle - # mantissa bits in dl.l.upper */
321
  ldl.l.middle |= (dl.l.upper & MANTDMASK) << (31 - 20);
322
  /* 1+20: explicit-integer-bit + # mantissa bits in dl.l.upper */
323
  ldl.l.middle |= dl.l.lower >> (1 + 20);
324
  /* 32 - 21: # bits of dl.l.lower in ldl.l.middle */
325
  ldl.l.lower = dl.l.lower << (32 - 21);
326
 
327
  /*printf ("dfxf out: %s\n", dumpxf (ldl.ld));*/
328
  return ldl.ld;
329
}
330
 
331
/* convert long double to double */
332
double
333
__truncxfdf2 (long double ld)
334
{
335
  register long exp;
336
  register union double_long dl;
337
  register union long_double_long ldl;
338
 
339
  ldl.ld = ld;
340
  /*printf ("xfdf in: %s\n", dumpxf (ld));*/
341
 
342
  if (!ldl.l.upper && !ldl.l.middle && !ldl.l.lower)
343
    return 0;
344
 
345
  exp = EXPX (ldl) - EXCESSX + EXCESSD;
346
  /* ??? quick and dirty: keep `exp' sane */
347
  if (exp >= EXPDMASK)
348
    exp = EXPDMASK - 1;
349
  dl.l.upper = SIGNX (ldl);
350
  dl.l.upper |= exp << (32 - (EXPDBITS + 1));
351
  /* +1-1: add one for sign bit, but take one off for explicit-integer-bit */
352
  dl.l.upper |= (ldl.l.middle & MANTXMASK) >> (EXPDBITS + 1 - 1);
353
  dl.l.lower = (ldl.l.middle & MANTXMASK) << (32 - (EXPDBITS + 1 - 1));
354
  dl.l.lower |= ldl.l.lower >> (EXPDBITS + 1 - 1);
355
 
356
  /*printf ("xfdf out: %g\n", dl.d);*/
357
  return dl.d;
358
}
359
 
360
/* convert a float to a long double */
361
long double
362
__extendsfxf2 (float f)
363
{
364
  long double foo = __extenddfxf2 (__extendsfdf2 (f));
365
  return foo;
366
}
367
 
368
/* convert a long double to a float */
369
float
370
__truncxfsf2 (long double ld)
371
{
372
  float foo = __truncdfsf2 (__truncxfdf2 (ld));
373
  return foo;
374
}
375
 
376
/* convert an int to a long double */
377
long double
378
__floatsixf (long l)
379
{
380
  double foo = __floatsidf (l);
381
  return foo;
382
}
383
 
384
/* convert a long double to an int */
385
long
386
__fixxfsi (long double ld)
387
{
388
  long foo = __fixdfsi ((double) ld);
389
  return foo;
390
}
391
 
392
/* The remaining provide crude math support by working in double precision.  */
393
 
394
long double
395
__addxf3 (long double x1, long double x2)
396
{
397
  return (double) x1 + (double) x2;
398
}
399
 
400
long double
401
__subxf3 (long double x1, long double x2)
402
{
403
  return (double) x1 - (double) x2;
404
}
405
 
406
long double
407
__mulxf3 (long double x1, long double x2)
408
{
409
  return (double) x1 * (double) x2;
410
}
411
 
412
long double
413
__divxf3 (long double x1, long double x2)
414
{
415
  return (double) x1 / (double) x2;
416
}
417
 
418
long double
419
__negxf2 (long double x1)
420
{
421
  return - (double) x1;
422
}
423
 
424
long
425
__cmpxf2 (long double x1, long double x2)
426
{
427
  return __cmpdf2 ((double) x1, (double) x2);
428
}
429
 
430
long
431
__eqxf2 (long double x1, long double x2)
432
{
433
  return __cmpdf2 ((double) x1, (double) x2);
434
}
435
 
436
long
437
__nexf2 (long double x1, long double x2)
438
{
439
  return __cmpdf2 ((double) x1, (double) x2);
440
}
441
 
442
long
443
__ltxf2 (long double x1, long double x2)
444
{
445
  return __cmpdf2 ((double) x1, (double) x2);
446
}
447
 
448
long
449
__lexf2 (long double x1, long double x2)
450
{
451
  return __cmpdf2 ((double) x1, (double) x2);
452
}
453
 
454
long
455
__gtxf2 (long double x1, long double x2)
456
{
457
  return __cmpdf2 ((double) x1, (double) x2);
458
}
459
 
460
long
461
__gexf2 (long double x1, long double x2)
462
{
463
  return __cmpdf2 ((double) x1, (double) x2);
464
}
465
 
466
#endif /* EXTFLOAT */

powered by: WebSVN 2.1.0

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