Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
145 halyavin 1
/* TCC runtime library.
2
   Parts of this code are (c) 2002 Fabrice Bellard
3
 
4
   Copyright (C) 1987, 1988, 1992, 1994, 1995 Free Software Foundation, Inc.
5
 
6
This file is free software; you can redistribute it and/or modify it
7
under the terms of the GNU General Public License as published by the
8
Free Software Foundation; either version 2, or (at your option) any
9
later version.
10
 
11
In addition to the permissions in the GNU General Public License, the
12
Free Software Foundation gives you unlimited permission to link the
13
compiled version of this file into combinations with other programs,
14
and to distribute those combinations without any restriction coming
15
from the use of this file.  (The General Public License restrictions
16
do apply in other respects; for example, they cover modification of
17
the file, and distribution when not linked into a combine
18
executable.)
19
 
20
This file is distributed in the hope that it will be useful, but
21
WITHOUT ANY WARRANTY; without even the implied warranty of
22
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23
General Public License for more details.
24
 
25
You should have received a copy of the GNU General Public License
26
along with this program; see the file COPYING.  If not, write to
27
the Free Software Foundation, 59 Temple Place - Suite 330,
28
Boston, MA 02111-1307, USA.
29
*/
30
 
31
#define W_TYPE_SIZE   32
32
#define BITS_PER_UNIT 8
33
 
34
typedef int Wtype;
35
typedef unsigned int UWtype;
36
typedef unsigned int USItype;
37
typedef long long DWtype;
38
typedef unsigned long long UDWtype;
39
 
40
struct DWstruct {
41
    Wtype low, high;
42
};
43
 
44
typedef union
45
{
46
  struct DWstruct s;
47
  DWtype ll;
48
} DWunion;
49
 
50
typedef long double XFtype;
51
#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
52
#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
53
 
54
/* the following deal with IEEE single-precision numbers */
55
#define EXCESS		126
56
#define SIGNBIT		0x80000000
57
#define HIDDEN		(1 << 23)
58
#define SIGN(fp)	((fp) & SIGNBIT)
59
#define EXP(fp)		(((fp) >> 23) & 0xFF)
60
#define MANT(fp)	(((fp) & 0x7FFFFF) | HIDDEN)
61
#define PACK(s,e,m)	((s) | ((e) << 23) | (m))
62
 
63
/* the following deal with IEEE double-precision numbers */
64
#define EXCESSD		1022
65
#define HIDDEND		(1 << 20)
66
#define EXPD(fp)	(((fp.l.upper) >> 20) & 0x7FF)
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 HIDDEND_LL	((long long)1 << 52)
71
#define MANTD_LL(fp)	((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL)
72
#define PACKD_LL(s,e,m)	(((long long)((s)+((e)<<20))<<32)|(m))
73
 
74
/* the following deal with x86 long double-precision numbers */
75
#define EXCESSLD	16382
76
#define EXPLD(fp)	(fp.l.upper & 0x7fff)
77
#define SIGNLD(fp)	((fp.l.upper) & 0x8000)
78
 
79
/* only for x86 */
80
union ldouble_long {
81
    long double ld;
82
    struct {
83
        unsigned long long lower;
84
        unsigned short upper;
85
    } l;
86
};
87
 
88
union double_long {
89
    double d;
90
#if 1
91
    struct {
92
        unsigned long lower;
93
        long upper;
94
    } l;
95
#else
96
    struct {
97
        long upper;
98
        unsigned long lower;
99
    } l;
100
#endif
101
    long long ll;
102
};
103
 
104
union float_long {
105
    float f;
106
    long l;
107
};
108
 
109
/* XXX: use gcc/tcc intrinsic ? */
110
#if defined(__i386__)
111
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
112
  __asm__ ("subl %5,%1\n\tsbbl %3,%0"					\
113
	   : "=r" ((USItype) (sh)),					\
114
	     "=&r" ((USItype) (sl))					\
115
	   : "0" ((USItype) (ah)),					\
116
	     "g" ((USItype) (bh)),					\
117
	     "1" ((USItype) (al)),					\
118
	     "g" ((USItype) (bl)))
119
#define umul_ppmm(w1, w0, u, v) \
120
  __asm__ ("mull %3"							\
121
	   : "=a" ((USItype) (w0)),					\
122
	     "=d" ((USItype) (w1))					\
123
	   : "%0" ((USItype) (u)),					\
124
	     "rm" ((USItype) (v)))
125
#define udiv_qrnnd(q, r, n1, n0, dv) \
126
  __asm__ ("divl %4"							\
127
	   : "=a" ((USItype) (q)),					\
128
	     "=d" ((USItype) (r))					\
129
	   : "0" ((USItype) (n0)),					\
130
	     "1" ((USItype) (n1)),					\
131
	     "rm" ((USItype) (dv)))
132
#define count_leading_zeros(count, x) \
133
  do {									\
134
    USItype __cbtmp;							\
135
    __asm__ ("bsrl %1,%0"						\
136
	     : "=r" (__cbtmp) : "rm" ((USItype) (x)));			\
137
    (count) = __cbtmp ^ 31;						\
138
  } while (0)
139
#else
140
#error unsupported CPU type
141
#endif
142
 
143
/* most of this code is taken from libgcc2.c from gcc */
144
 
145
static UDWtype __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
146
{
147
  DWunion ww;
148
  DWunion nn, dd;
149
  DWunion rr;
150
  UWtype d0, d1, n0, n1, n2;
151
  UWtype q0, q1;
152
  UWtype b, bm;
153
 
154
  nn.ll = n;
155
  dd.ll = d;
156
 
157
  d0 = dd.s.low;
158
  d1 = dd.s.high;
159
  n0 = nn.s.low;
160
  n1 = nn.s.high;
161
 
162
#if !UDIV_NEEDS_NORMALIZATION
163
  if (d1 == 0)
164
    {
165
      if (d0 > n1)
166
	{
167
	  /* 0q = nn / 0D */
168
 
169
	  udiv_qrnnd (q0, n0, n1, n0, d0);
170
	  q1 = 0;
171
 
172
	  /* Remainder in n0.  */
173
	}
174
      else
175
	{
176
	  /* qq = NN / 0d */
177
 
178
	  if (d0 == 0)
179
	    d0 = 1 / d0;	/* Divide intentionally by zero.  */
180
 
181
	  udiv_qrnnd (q1, n1, 0, n1, d0);
182
	  udiv_qrnnd (q0, n0, n1, n0, d0);
183
 
184
	  /* Remainder in n0.  */
185
	}
186
 
187
      if (rp != 0)
188
	{
189
	  rr.s.low = n0;
190
	  rr.s.high = 0;
191
	  *rp = rr.ll;
192
	}
193
    }
194
 
195
#else /* UDIV_NEEDS_NORMALIZATION */
196
 
197
  if (d1 == 0)
198
    {
199
      if (d0 > n1)
200
	{
201
	  /* 0q = nn / 0D */
202
 
203
	  count_leading_zeros (bm, d0);
204
 
205
	  if (bm != 0)
206
	    {
207
	      /* Normalize, i.e. make the most significant bit of the
208
		 denominator set.  */
209
 
210
	      d0 = d0 << bm;
211
	      n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
212
	      n0 = n0 << bm;
213
	    }
214
 
215
	  udiv_qrnnd (q0, n0, n1, n0, d0);
216
	  q1 = 0;
217
 
218
	  /* Remainder in n0 >> bm.  */
219
	}
220
      else
221
	{
222
	  /* qq = NN / 0d */
223
 
224
	  if (d0 == 0)
225
	    d0 = 1 / d0;	/* Divide intentionally by zero.  */
226
 
227
	  count_leading_zeros (bm, d0);
228
 
229
	  if (bm == 0)
230
	    {
231
	      /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
232
		 conclude (the most significant bit of n1 is set) /\ (the
233
		 leading quotient digit q1 = 1).
234
 
235
		 This special case is necessary, not an optimization.
236
		 (Shifts counts of W_TYPE_SIZE are undefined.)  */
237
 
238
	      n1 -= d0;
239
	      q1 = 1;
240
	    }
241
	  else
242
	    {
243
	      /* Normalize.  */
244
 
245
	      b = W_TYPE_SIZE - bm;
246
 
247
	      d0 = d0 << bm;
248
	      n2 = n1 >> b;
249
	      n1 = (n1 << bm) | (n0 >> b);
250
	      n0 = n0 << bm;
251
 
252
	      udiv_qrnnd (q1, n1, n2, n1, d0);
253
	    }
254
 
255
	  /* n1 != d0...  */
256
 
257
	  udiv_qrnnd (q0, n0, n1, n0, d0);
258
 
259
	  /* Remainder in n0 >> bm.  */
260
	}
261
 
262
      if (rp != 0)
263
	{
264
	  rr.s.low = n0 >> bm;
265
	  rr.s.high = 0;
266
	  *rp = rr.ll;
267
	}
268
    }
269
#endif /* UDIV_NEEDS_NORMALIZATION */
270
 
271
  else
272
    {
273
      if (d1 > n1)
274
	{
275
	  /* 00 = nn / DD */
276
 
277
	  q0 = 0;
278
	  q1 = 0;
279
 
280
	  /* Remainder in n1n0.  */
281
	  if (rp != 0)
282
	    {
283
	      rr.s.low = n0;
284
	      rr.s.high = n1;
285
	      *rp = rr.ll;
286
	    }
287
	}
288
      else
289
	{
290
	  /* 0q = NN / dd */
291
 
292
	  count_leading_zeros (bm, d1);
293
	  if (bm == 0)
294
	    {
295
	      /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
296
		 conclude (the most significant bit of n1 is set) /\ (the
297
		 quotient digit q0 = 0 or 1).
298
 
299
		 This special case is necessary, not an optimization.  */
300
 
301
	      /* The condition on the next line takes advantage of that
302
		 n1 >= d1 (true due to program flow).  */
303
	      if (n1 > d1 || n0 >= d0)
304
		{
305
		  q0 = 1;
306
		  sub_ddmmss (n1, n0, n1, n0, d1, d0);
307
		}
308
	      else
309
		q0 = 0;
310
 
311
	      q1 = 0;
312
 
313
	      if (rp != 0)
314
		{
315
		  rr.s.low = n0;
316
		  rr.s.high = n1;
317
		  *rp = rr.ll;
318
		}
319
	    }
320
	  else
321
	    {
322
	      UWtype m1, m0;
323
	      /* Normalize.  */
324
 
325
	      b = W_TYPE_SIZE - bm;
326
 
327
	      d1 = (d1 << bm) | (d0 >> b);
328
	      d0 = d0 << bm;
329
	      n2 = n1 >> b;
330
	      n1 = (n1 << bm) | (n0 >> b);
331
	      n0 = n0 << bm;
332
 
333
	      udiv_qrnnd (q0, n1, n2, n1, d1);
334
	      umul_ppmm (m1, m0, q0, d0);
335
 
336
	      if (m1 > n1 || (m1 == n1 && m0 > n0))
337
		{
338
		  q0--;
339
		  sub_ddmmss (m1, m0, m1, m0, d1, d0);
340
		}
341
 
342
	      q1 = 0;
343
 
344
	      /* Remainder in (n1n0 - m1m0) >> bm.  */
345
	      if (rp != 0)
346
		{
347
		  sub_ddmmss (n1, n0, n1, n0, m1, m0);
348
		  rr.s.low = (n1 << b) | (n0 >> bm);
349
		  rr.s.high = n1 >> bm;
350
		  *rp = rr.ll;
351
		}
352
	    }
353
	}
354
    }
355
 
356
  ww.s.low = q0;
357
  ww.s.high = q1;
358
  return ww.ll;
359
}
360
 
361
#define __negdi2(a) (-(a))
362
 
363
long long __divdi3(long long u, long long v)
364
{
365
    int c = 0;
366
    DWunion uu, vv;
367
    DWtype w;
368
 
369
    uu.ll = u;
370
    vv.ll = v;
371
 
372
    if (uu.s.high < 0) {
373
        c = ~c;
374
        uu.ll = __negdi2 (uu.ll);
375
    }
376
    if (vv.s.high < 0) {
377
        c = ~c;
378
        vv.ll = __negdi2 (vv.ll);
379
    }
380
    w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
381
    if (c)
382
        w = __negdi2 (w);
383
    return w;
384
}
385
 
386
long long __moddi3(long long u, long long v)
387
{
388
    int c = 0;
389
    DWunion uu, vv;
390
    DWtype w;
391
 
392
    uu.ll = u;
393
    vv.ll = v;
394
 
395
    if (uu.s.high < 0) {
396
        c = ~c;
397
        uu.ll = __negdi2 (uu.ll);
398
    }
399
    if (vv.s.high < 0)
400
        vv.ll = __negdi2 (vv.ll);
401
 
402
    __udivmoddi4 (uu.ll, vv.ll, &w);
403
    if (c)
404
        w = __negdi2 (w);
405
    return w;
406
}
407
 
408
unsigned long long __udivdi3(unsigned long long u, unsigned long long v)
409
{
410
    return __udivmoddi4 (u, v, (UDWtype *) 0);
411
}
412
 
413
unsigned long long __umoddi3(unsigned long long u, unsigned long long v)
414
{
415
    UDWtype w;
416
 
417
    __udivmoddi4 (u, v, &w);
418
    return w;
419
}
420
 
421
/* XXX: fix tcc's code generator to do this instead */
422
long long __sardi3(long long a, int b)
423
{
424
#ifdef __TINYC__
425
    DWunion u;
426
    u.ll = a;
427
    if (b >= 32) {
428
        u.s.low = u.s.high >> (b - 32);
429
        u.s.high = u.s.high >> 31;
430
    } else if (b != 0) {
431
        u.s.low = ((unsigned)u.s.low >> b) | (u.s.high << (32 - b));
432
        u.s.high = u.s.high >> b;
433
    }
434
    return u.ll;
435
#else
436
    return a >> b;
437
#endif
438
}
439
 
440
/* XXX: fix tcc's code generator to do this instead */
441
unsigned long long __shrdi3(unsigned long long a, int b)
442
{
443
#ifdef __TINYC__
444
    DWunion u;
445
    u.ll = a;
446
    if (b >= 32) {
447
        u.s.low = (unsigned)u.s.high >> (b - 32);
448
        u.s.high = 0;
449
    } else if (b != 0) {
450
        u.s.low = ((unsigned)u.s.low >> b) | (u.s.high << (32 - b));
451
        u.s.high = (unsigned)u.s.high >> b;
452
    }
453
    return u.ll;
454
#else
455
    return a >> b;
456
#endif
457
}
458
 
459
/* XXX: fix tcc's code generator to do this instead */
460
long long __shldi3(long long a, int b)
461
{
462
#ifdef __TINYC__
463
    DWunion u;
464
    u.ll = a;
465
    if (b >= 32) {
466
        u.s.high = (unsigned)u.s.low << (b - 32);
467
        u.s.low = 0;
468
    } else if (b != 0) {
469
        u.s.high = ((unsigned)u.s.high << b) | (u.s.low >> (32 - b));
470
        u.s.low = (unsigned)u.s.low << b;
471
    }
472
    return u.ll;
473
#else
474
    return a << b;
475
#endif
476
}
477
 
478
#if defined(__i386__)
479
/* FPU control word for rounding to nearest mode */
480
unsigned short __tcc_fpu_control = 0x137f;
481
/* FPU control word for round to zero mode for int conversion */
482
unsigned short __tcc_int_fpu_control = 0x137f | 0x0c00;
483
#endif
484
 
485
/* XXX: fix tcc's code generator to do this instead */
486
float __ulltof(unsigned long long a)
487
{
488
    DWunion uu;
489
    XFtype r;
490
 
491
    uu.ll = a;
492
    if (uu.s.high >= 0) {
493
        return (float)uu.ll;
494
    } else {
495
        r = (XFtype)uu.ll;
496
        r += 18446744073709551616.0;
497
        return (float)r;
498
    }
499
}
500
 
501
double __ulltod(unsigned long long a)
502
{
503
    DWunion uu;
504
    XFtype r;
505
 
506
    uu.ll = a;
507
    if (uu.s.high >= 0) {
508
        return (double)uu.ll;
509
    } else {
510
        r = (XFtype)uu.ll;
511
        r += 18446744073709551616.0;
512
        return (double)r;
513
    }
514
}
515
 
516
long double __ulltold(unsigned long long a)
517
{
518
    DWunion uu;
519
    XFtype r;
520
 
521
    uu.ll = a;
522
    if (uu.s.high >= 0) {
523
        return (long double)uu.ll;
524
    } else {
525
        r = (XFtype)uu.ll;
526
        r += 18446744073709551616.0;
527
        return (long double)r;
528
    }
529
}
530
 
531
unsigned long long __fixunssfdi (float a1)
532
{
533
    register union float_long fl1;
534
    register int exp;
535
    register unsigned long l;
536
 
537
    fl1.f = a1;
538
 
539
    if (fl1.l == 0)
540
	return (0);
541
 
542
    exp = EXP (fl1.l) - EXCESS - 24;
543
 
544
    l = MANT(fl1.l);
545
    if (exp >= 41)
546
	return (unsigned long long)-1;
547
    else if (exp >= 0)
548
        return (unsigned long long)l << exp;
549
    else if (exp >= -23)
550
        return l >> -exp;
551
    else
552
        return 0;
553
}
554
 
555
unsigned long long __fixunsdfdi (double a1)
556
{
557
    register union double_long dl1;
558
    register int exp;
559
    register unsigned long long l;
560
 
561
    dl1.d = a1;
562
 
563
    if (dl1.ll == 0)
564
	return (0);
565
 
566
    exp = EXPD (dl1) - EXCESSD - 53;
567
 
568
    l = MANTD_LL(dl1);
569
 
570
    if (exp >= 12)
571
	return (unsigned long long)-1;
572
    else if (exp >= 0)
573
        return l << exp;
574
    else if (exp >= -52)
575
        return l >> -exp;
576
    else
577
        return 0;
578
}
579
 
580
unsigned long long __fixunsxfdi (long double a1)
581
{
582
    register union ldouble_long dl1;
583
    register int exp;
584
    register unsigned long long l;
585
 
586
    dl1.ld = a1;
587
 
588
    if (dl1.l.lower == 0 && dl1.l.upper == 0)
589
	return (0);
590
 
591
    exp = EXPLD (dl1) - EXCESSLD - 64;
592
 
593
    l = dl1.l.lower;
594
 
595
    if (exp > 0)
596
	return (unsigned long long)-1;
597
    else if (exp >= -63)
598
        return l >> -exp;
599
    else
600
        return 0;
601
}
602