History

new subdirs: include, lib, tests

grischka committed 17 years ago

Commit ea5e81b1 parent e8a52a816 files · +0 −6Browse files

Showing the changes to lib/libtcc1.c (1 of 16 files). Show all

Unified · Split

lib/libtcc1.c+607−0
@@ -0,0 +1,607 @@
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 int lower;
93+ int upper;
94+ } l;
95+#else
96+ struct {
97+ int upper;
98+ unsigned int 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: we don't support several builtin supports for now */
110+#ifndef __x86_64__
111+
112+/* XXX: use gcc/tcc intrinsic ? */
113+#if defined(__i386__)
114+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
115+ __asm__ ("subl %5,%1\n\tsbbl %3,%0" \
116+ : "=r" ((USItype) (sh)), \
117+ "=&r" ((USItype) (sl)) \
118+ : "0" ((USItype) (ah)), \
119+ "g" ((USItype) (bh)), \
120+ "1" ((USItype) (al)), \
121+ "g" ((USItype) (bl)))
122+#define umul_ppmm(w1, w0, u, v) \
123+ __asm__ ("mull %3" \
124+ : "=a" ((USItype) (w0)), \
125+ "=d" ((USItype) (w1)) \
126+ : "%0" ((USItype) (u)), \
127+ "rm" ((USItype) (v)))
128+#define udiv_qrnnd(q, r, n1, n0, dv) \
129+ __asm__ ("divl %4" \
130+ : "=a" ((USItype) (q)), \
131+ "=d" ((USItype) (r)) \
132+ : "0" ((USItype) (n0)), \
133+ "1" ((USItype) (n1)), \
134+ "rm" ((USItype) (dv)))
135+#define count_leading_zeros(count, x) \
136+ do { \
137+ USItype __cbtmp; \
138+ __asm__ ("bsrl %1,%0" \
139+ : "=r" (__cbtmp) : "rm" ((USItype) (x))); \
140+ (count) = __cbtmp ^ 31; \
141+ } while (0)
142+#else
143+#error unsupported CPU type
144+#endif
145+
146+/* most of this code is taken from libgcc2.c from gcc */
147+
148+static UDWtype __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
149+{
150+ DWunion ww;
151+ DWunion nn, dd;
152+ DWunion rr;
153+ UWtype d0, d1, n0, n1, n2;
154+ UWtype q0, q1;
155+ UWtype b, bm;
156+
157+ nn.ll = n;
158+ dd.ll = d;
159+
160+ d0 = dd.s.low;
161+ d1 = dd.s.high;
162+ n0 = nn.s.low;
163+ n1 = nn.s.high;
164+
165+#if !UDIV_NEEDS_NORMALIZATION
166+ if (d1 == 0)
167+ {
168+ if (d0 > n1)
169+ {
170+ /* 0q = nn / 0D */
171+
172+ udiv_qrnnd (q0, n0, n1, n0, d0);
173+ q1 = 0;
174+
175+ /* Remainder in n0. */
176+ }
177+ else
178+ {
179+ /* qq = NN / 0d */
180+
181+ if (d0 == 0)
182+ d0 = 1 / d0; /* Divide intentionally by zero. */
183+
184+ udiv_qrnnd (q1, n1, 0, n1, d0);
185+ udiv_qrnnd (q0, n0, n1, n0, d0);
186+
187+ /* Remainder in n0. */
188+ }
189+
190+ if (rp != 0)
191+ {
192+ rr.s.low = n0;
193+ rr.s.high = 0;
194+ *rp = rr.ll;
195+ }
196+ }
197+
198+#else /* UDIV_NEEDS_NORMALIZATION */
199+
200+ if (d1 == 0)
201+ {
202+ if (d0 > n1)
203+ {
204+ /* 0q = nn / 0D */
205+
206+ count_leading_zeros (bm, d0);
207+
208+ if (bm != 0)
209+ {
210+ /* Normalize, i.e. make the most significant bit of the
211+ denominator set. */
212+
213+ d0 = d0 << bm;
214+ n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
215+ n0 = n0 << bm;
216+ }
217+
218+ udiv_qrnnd (q0, n0, n1, n0, d0);
219+ q1 = 0;
220+
221+ /* Remainder in n0 >> bm. */
222+ }
223+ else
224+ {
225+ /* qq = NN / 0d */
226+
227+ if (d0 == 0)
228+ d0 = 1 / d0; /* Divide intentionally by zero. */
229+
230+ count_leading_zeros (bm, d0);
231+
232+ if (bm == 0)
233+ {
234+ /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
235+ conclude (the most significant bit of n1 is set) /\ (the
236+ leading quotient digit q1 = 1).
237+
238+ This special case is necessary, not an optimization.
239+ (Shifts counts of W_TYPE_SIZE are undefined.) */
240+
241+ n1 -= d0;
242+ q1 = 1;
243+ }
244+ else
245+ {
246+ /* Normalize. */
247+
248+ b = W_TYPE_SIZE - bm;
249+
250+ d0 = d0 << bm;
251+ n2 = n1 >> b;
252+ n1 = (n1 << bm) | (n0 >> b);
253+ n0 = n0 << bm;
254+
255+ udiv_qrnnd (q1, n1, n2, n1, d0);
256+ }
257+
258+ /* n1 != d0... */
259+
260+ udiv_qrnnd (q0, n0, n1, n0, d0);
261+
262+ /* Remainder in n0 >> bm. */
263+ }
264+
265+ if (rp != 0)
266+ {
267+ rr.s.low = n0 >> bm;
268+ rr.s.high = 0;
269+ *rp = rr.ll;
270+ }
271+ }
272+#endif /* UDIV_NEEDS_NORMALIZATION */
273+
274+ else
275+ {
276+ if (d1 > n1)
277+ {
278+ /* 00 = nn / DD */
279+
280+ q0 = 0;
281+ q1 = 0;
282+
283+ /* Remainder in n1n0. */
284+ if (rp != 0)
285+ {
286+ rr.s.low = n0;
287+ rr.s.high = n1;
288+ *rp = rr.ll;
289+ }
290+ }
291+ else
292+ {
293+ /* 0q = NN / dd */
294+
295+ count_leading_zeros (bm, d1);
296+ if (bm == 0)
297+ {
298+ /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
299+ conclude (the most significant bit of n1 is set) /\ (the
300+ quotient digit q0 = 0 or 1).
301+
302+ This special case is necessary, not an optimization. */
303+
304+ /* The condition on the next line takes advantage of that
305+ n1 >= d1 (true due to program flow). */
306+ if (n1 > d1 || n0 >= d0)
307+ {
308+ q0 = 1;
309+ sub_ddmmss (n1, n0, n1, n0, d1, d0);
310+ }
311+ else
312+ q0 = 0;
313+
314+ q1 = 0;
315+
316+ if (rp != 0)
317+ {
318+ rr.s.low = n0;
319+ rr.s.high = n1;
320+ *rp = rr.ll;
321+ }
322+ }
323+ else
324+ {
325+ UWtype m1, m0;
326+ /* Normalize. */
327+
328+ b = W_TYPE_SIZE - bm;
329+
330+ d1 = (d1 << bm) | (d0 >> b);
331+ d0 = d0 << bm;
332+ n2 = n1 >> b;
333+ n1 = (n1 << bm) | (n0 >> b);
334+ n0 = n0 << bm;
335+
336+ udiv_qrnnd (q0, n1, n2, n1, d1);
337+ umul_ppmm (m1, m0, q0, d0);
338+
339+ if (m1 > n1 || (m1 == n1 && m0 > n0))
340+ {
341+ q0--;
342+ sub_ddmmss (m1, m0, m1, m0, d1, d0);
343+ }
344+
345+ q1 = 0;
346+
347+ /* Remainder in (n1n0 - m1m0) >> bm. */
348+ if (rp != 0)
349+ {
350+ sub_ddmmss (n1, n0, n1, n0, m1, m0);
351+ rr.s.low = (n1 << b) | (n0 >> bm);
352+ rr.s.high = n1 >> bm;
353+ *rp = rr.ll;
354+ }
355+ }
356+ }
357+ }
358+
359+ ww.s.low = q0;
360+ ww.s.high = q1;
361+ return ww.ll;
362+}
363+
364+#define __negdi2(a) (-(a))
365+
366+long long __divdi3(long long u, long long v)
367+{
368+ int c = 0;
369+ DWunion uu, vv;
370+ DWtype w;
371+
372+ uu.ll = u;
373+ vv.ll = v;
374+
375+ if (uu.s.high < 0) {
376+ c = ~c;
377+ uu.ll = __negdi2 (uu.ll);
378+ }
379+ if (vv.s.high < 0) {
380+ c = ~c;
381+ vv.ll = __negdi2 (vv.ll);
382+ }
383+ w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
384+ if (c)
385+ w = __negdi2 (w);
386+ return w;
387+}
388+
389+long long __moddi3(long long u, long long v)
390+{
391+ int c = 0;
392+ DWunion uu, vv;
393+ DWtype w;
394+
395+ uu.ll = u;
396+ vv.ll = v;
397+
398+ if (uu.s.high < 0) {
399+ c = ~c;
400+ uu.ll = __negdi2 (uu.ll);
401+ }
402+ if (vv.s.high < 0)
403+ vv.ll = __negdi2 (vv.ll);
404+
405+ __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) &w);
406+ if (c)
407+ w = __negdi2 (w);
408+ return w;
409+}
410+
411+unsigned long long __udivdi3(unsigned long long u, unsigned long long v)
412+{
413+ return __udivmoddi4 (u, v, (UDWtype *) 0);
414+}
415+
416+unsigned long long __umoddi3(unsigned long long u, unsigned long long v)
417+{
418+ UDWtype w;
419+
420+ __udivmoddi4 (u, v, &w);
421+ return w;
422+}
423+
424+/* XXX: fix tcc's code generator to do this instead */
425+long long __ashrdi3(long long a, int b)
426+{
427+#ifdef __TINYC__
428+ DWunion u;
429+ u.ll = a;
430+ if (b >= 32) {
431+ u.s.low = u.s.high >> (b - 32);
432+ u.s.high = u.s.high >> 31;
433+ } else if (b != 0) {
434+ u.s.low = ((unsigned)u.s.low >> b) | (u.s.high << (32 - b));
435+ u.s.high = u.s.high >> b;
436+ }
437+ return u.ll;
438+#else
439+ return a >> b;
440+#endif
441+}
442+
443+/* XXX: fix tcc's code generator to do this instead */
444+unsigned long long __lshrdi3(unsigned long long a, int b)
445+{
446+#ifdef __TINYC__
447+ DWunion u;
448+ u.ll = a;
449+ if (b >= 32) {
450+ u.s.low = (unsigned)u.s.high >> (b - 32);
451+ u.s.high = 0;
452+ } else if (b != 0) {
453+ u.s.low = ((unsigned)u.s.low >> b) | (u.s.high << (32 - b));
454+ u.s.high = (unsigned)u.s.high >> b;
455+ }
456+ return u.ll;
457+#else
458+ return a >> b;
459+#endif
460+}
461+
462+/* XXX: fix tcc's code generator to do this instead */
463+long long __ashldi3(long long a, int b)
464+{
465+#ifdef __TINYC__
466+ DWunion u;
467+ u.ll = a;
468+ if (b >= 32) {
469+ u.s.high = (unsigned)u.s.low << (b - 32);
470+ u.s.low = 0;
471+ } else if (b != 0) {
472+ u.s.high = ((unsigned)u.s.high << b) | ((unsigned)u.s.low >> (32 - b));
473+ u.s.low = (unsigned)u.s.low << b;
474+ }
475+ return u.ll;
476+#else
477+ return a << b;
478+#endif
479+}
480+
481+#if defined(__i386__)
482+/* FPU control word for rounding to nearest mode */
483+unsigned short __tcc_fpu_control = 0x137f;
484+/* FPU control word for round to zero mode for int conversion */
485+unsigned short __tcc_int_fpu_control = 0x137f | 0x0c00;
486+#endif
487+
488+#endif /* !__x86_64__ */
489+
490+/* XXX: fix tcc's code generator to do this instead */
491+float __floatundisf(unsigned long long a)
492+{
493+ DWunion uu;
494+ XFtype r;
495+
496+ uu.ll = a;
497+ if (uu.s.high >= 0) {
498+ return (float)uu.ll;
499+ } else {
500+ r = (XFtype)uu.ll;
501+ r += 18446744073709551616.0;
502+ return (float)r;
503+ }
504+}
505+
506+double __floatundidf(unsigned long long a)
507+{
508+ DWunion uu;
509+ XFtype r;
510+
511+ uu.ll = a;
512+ if (uu.s.high >= 0) {
513+ return (double)uu.ll;
514+ } else {
515+ r = (XFtype)uu.ll;
516+ r += 18446744073709551616.0;
517+ return (double)r;
518+ }
519+}
520+
521+long double __floatundixf(unsigned long long a)
522+{
523+ DWunion uu;
524+ XFtype r;
525+
526+ uu.ll = a;
527+ if (uu.s.high >= 0) {
528+ return (long double)uu.ll;
529+ } else {
530+ r = (XFtype)uu.ll;
531+ r += 18446744073709551616.0;
532+ return (long double)r;
533+ }
534+}
535+
536+unsigned long long __fixunssfdi (float a1)
537+{
538+ register union float_long fl1;
539+ register int exp;
540+ register unsigned long l;
541+
542+ fl1.f = a1;
543+
544+ if (fl1.l == 0)
545+ return (0);
546+
547+ exp = EXP (fl1.l) - EXCESS - 24;
548+
549+ l = MANT(fl1.l);
550+ if (exp >= 41)
551+ return (unsigned long long)-1;
552+ else if (exp >= 0)
553+ return (unsigned long long)l << exp;
554+ else if (exp >= -23)
555+ return l >> -exp;
556+ else
557+ return 0;
558+}
559+
560+unsigned long long __fixunsdfdi (double a1)
561+{
562+ register union double_long dl1;
563+ register int exp;
564+ register unsigned long long l;
565+
566+ dl1.d = a1;
567+
568+ if (dl1.ll == 0)
569+ return (0);
570+
571+ exp = EXPD (dl1) - EXCESSD - 53;
572+
573+ l = MANTD_LL(dl1);
574+
575+ if (exp >= 12)
576+ return (unsigned long long)-1;
577+ else if (exp >= 0)
578+ return l << exp;
579+ else if (exp >= -52)
580+ return l >> -exp;
581+ else
582+ return 0;
583+}
584+
585+unsigned long long __fixunsxfdi (long double a1)
586+{
587+ register union ldouble_long dl1;
588+ register int exp;
589+ register unsigned long long l;
590+
591+ dl1.ld = a1;
592+
593+ if (dl1.l.lower == 0 && dl1.l.upper == 0)
594+ return (0);
595+
596+ exp = EXPLD (dl1) - EXCESSLD - 64;
597+
598+ l = dl1.l.lower;
599+
600+ if (exp > 0)
601+ return (unsigned long long)-1;
602+ else if (exp >= -63)
603+ return l >> -exp;
604+ else
605+ return 0;
606+}
607+

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t