source: EcnlProtoTool/trunk/tcc-0.9.27/lib/libtcc1.c@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 12.7 KB
Line 
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
6This file is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11In addition to the permissions in the GNU General Public License, the
12Free Software Foundation gives you unlimited permission to link the
13compiled version of this file into combinations with other programs,
14and to distribute those combinations without any restriction coming
15from the use of this file. (The General Public License restrictions
16do apply in other respects; for example, they cover modification of
17the file, and distribution when not linked into a combine
18executable.)
19
20This file is distributed in the hope that it will be useful, but
21WITHOUT ANY WARRANTY; without even the implied warranty of
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23General Public License for more details.
24
25You should have received a copy of the GNU General Public License
26along with this program; see the file COPYING. If not, write to
27the Free Software Foundation, 59 Temple Place - Suite 330,
28Boston, MA 02111-1307, USA.
29*/
30
31#define W_TYPE_SIZE 32
32#define BITS_PER_UNIT 8
33
34typedef int Wtype;
35typedef unsigned int UWtype;
36typedef unsigned int USItype;
37typedef long long DWtype;
38typedef unsigned long long UDWtype;
39
40struct DWstruct {
41 Wtype low, high;
42};
43
44typedef union
45{
46 struct DWstruct s;
47 DWtype ll;
48} DWunion;
49
50typedef 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 */
80union ldouble_long {
81 long double ld;
82 struct {
83 unsigned long long lower;
84 unsigned short upper;
85 } l;
86};
87
88union 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
104union float_long {
105 float f;
106 unsigned int l;
107};
108
109/* XXX: we don't support several builtin supports for now */
110#if !defined __x86_64__ && !defined __arm__
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
148static 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 !defined(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
366long 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
389long 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
411unsigned long long __udivdi3(unsigned long long u, unsigned long long v)
412{
413 return __udivmoddi4 (u, v, (UDWtype *) 0);
414}
415
416unsigned 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 */
425long 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 */
444unsigned 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 */
463long 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#endif /* !__x86_64__ */
482
483/* XXX: fix tcc's code generator to do this instead */
484float __floatundisf(unsigned long long a)
485{
486 DWunion uu;
487 XFtype r;
488
489 uu.ll = a;
490 if (uu.s.high >= 0) {
491 return (float)uu.ll;
492 } else {
493 r = (XFtype)uu.ll;
494 r += 18446744073709551616.0;
495 return (float)r;
496 }
497}
498
499double __floatundidf(unsigned long long a)
500{
501 DWunion uu;
502 XFtype r;
503
504 uu.ll = a;
505 if (uu.s.high >= 0) {
506 return (double)uu.ll;
507 } else {
508 r = (XFtype)uu.ll;
509 r += 18446744073709551616.0;
510 return (double)r;
511 }
512}
513
514long double __floatundixf(unsigned long long a)
515{
516 DWunion uu;
517 XFtype r;
518
519 uu.ll = a;
520 if (uu.s.high >= 0) {
521 return (long double)uu.ll;
522 } else {
523 r = (XFtype)uu.ll;
524 r += 18446744073709551616.0;
525 return (long double)r;
526 }
527}
528
529unsigned long long __fixunssfdi (float a1)
530{
531 register union float_long fl1;
532 register int exp;
533 register unsigned long l;
534
535 fl1.f = a1;
536
537 if (fl1.l == 0)
538 return (0);
539
540 exp = EXP (fl1.l) - EXCESS - 24;
541
542 l = MANT(fl1.l);
543 if (exp >= 41)
544 return (unsigned long long)-1;
545 else if (exp >= 0)
546 return (unsigned long long)l << exp;
547 else if (exp >= -23)
548 return l >> -exp;
549 else
550 return 0;
551}
552
553long long __fixsfdi (float a1)
554{
555 long long ret; int s;
556 ret = __fixunssfdi((s = a1 >= 0) ? a1 : -a1);
557 return s ? ret : -ret;
558}
559
560unsigned 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
585long long __fixdfdi (double a1)
586{
587 long long ret; int s;
588 ret = __fixunsdfdi((s = a1 >= 0) ? a1 : -a1);
589 return s ? ret : -ret;
590}
591
592#ifndef __arm__
593unsigned long long __fixunsxfdi (long double a1)
594{
595 register union ldouble_long dl1;
596 register int exp;
597 register unsigned long long l;
598
599 dl1.ld = a1;
600
601 if (dl1.l.lower == 0 && dl1.l.upper == 0)
602 return (0);
603
604 exp = EXPLD (dl1) - EXCESSLD - 64;
605
606 l = dl1.l.lower;
607
608 if (exp > 0)
609 return (unsigned long long)-1;
610 else if (exp >= -63)
611 return l >> -exp;
612 else
613 return 0;
614}
615
616long long __fixxfdi (long double a1)
617{
618 long long ret; int s;
619 ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1);
620 return s ? ret : -ret;
621}
622#endif /* !ARM */
Note: See TracBrowser for help on using the repository browser.