source: EcnlProtoTool/trunk/tcc-0.9.27/lib/armeabi.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
File size: 27.2 KB
Line 
1/* TCC ARM runtime EABI
2 Copyright (C) 2013 Thomas Preud'homme
3
4Permission is hereby granted, free of charge, to any person obtaining a copy
5of this software and associated documentation files (the "Software"), to deal
6in the Software without restriction, including without limitation the rights
7to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8copies of the Software, and to permit persons to whom the Software is
9furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20THE SOFTWARE.*/
21
22#ifdef __TINYC__
23#define INT_MIN (-2147483647 - 1)
24#define INT_MAX 2147483647
25#define UINT_MAX 0xffffffff
26#define LONG_MIN (-2147483647L - 1)
27#define LONG_MAX 2147483647L
28#define ULONG_MAX 0xffffffffUL
29#define LLONG_MAX 9223372036854775807LL
30#define LLONG_MIN (-9223372036854775807LL - 1)
31#define ULLONG_MAX 0xffffffffffffffffULL
32#else
33#include <limits.h>
34#endif
35
36/* We rely on the little endianness and EABI calling convention for this to
37 work */
38
39typedef struct double_unsigned_struct {
40 unsigned low;
41 unsigned high;
42} double_unsigned_struct;
43
44typedef struct unsigned_int_struct {
45 unsigned low;
46 int high;
47} unsigned_int_struct;
48
49#define REGS_RETURN(name, type) \
50 void name ## _return(type ret) {}
51
52
53/* Float helper functions */
54
55#define FLOAT_EXP_BITS 8
56#define FLOAT_FRAC_BITS 23
57
58#define DOUBLE_EXP_BITS 11
59#define DOUBLE_FRAC_BITS 52
60
61#define ONE_EXP(type) ((1 << (type ## _EXP_BITS - 1)) - 1)
62
63REGS_RETURN(unsigned_int_struct, unsigned_int_struct)
64REGS_RETURN(double_unsigned_struct, double_unsigned_struct)
65
66/* float -> integer: (sign) 1.fraction x 2^(exponent - exp_for_one) */
67
68
69/* float to [unsigned] long long conversion */
70#define DEFINE__AEABI_F2XLZ(name, with_sign) \
71void __aeabi_ ## name(unsigned val) \
72{ \
73 int exp, high_shift, sign; \
74 double_unsigned_struct ret; \
75 \
76 /* compute sign */ \
77 sign = val >> 31; \
78 \
79 /* compute real exponent */ \
80 exp = val >> FLOAT_FRAC_BITS; \
81 exp &= (1 << FLOAT_EXP_BITS) - 1; \
82 exp -= ONE_EXP(FLOAT); \
83 \
84 /* undefined behavior if truncated value cannot be represented */ \
85 if (with_sign) { \
86 if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
87 return; \
88 } else { \
89 if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
90 return; \
91 } \
92 \
93 val &= (1 << FLOAT_FRAC_BITS) - 1; \
94 if (exp >= 32) { \
95 ret.high = 1 << (exp - 32); \
96 if (exp - 32 >= FLOAT_FRAC_BITS) { \
97 ret.high |= val << (exp - 32 - FLOAT_FRAC_BITS); \
98 ret.low = 0; \
99 } else { \
100 high_shift = FLOAT_FRAC_BITS - (exp - 32); \
101 ret.high |= val >> high_shift; \
102 ret.low = val << (32 - high_shift); \
103 } \
104 } else { \
105 ret.high = 0; \
106 ret.low = 1 << exp; \
107 if (exp > FLOAT_FRAC_BITS) \
108 ret.low |= val << (exp - FLOAT_FRAC_BITS); \
109 else \
110 ret.low |= val >> (FLOAT_FRAC_BITS - exp); \
111 } \
112 \
113 /* encode negative integer using 2's complement */ \
114 if (with_sign && sign) { \
115 ret.low = ~ret.low; \
116 ret.high = ~ret.high; \
117 if (ret.low == UINT_MAX) { \
118 ret.low = 0; \
119 ret.high++; \
120 } else \
121 ret.low++; \
122 } \
123 \
124 double_unsigned_struct_return(ret); \
125}
126
127/* float to unsigned long long conversion */
128DEFINE__AEABI_F2XLZ(f2ulz, 0)
129
130/* float to long long conversion */
131DEFINE__AEABI_F2XLZ(f2lz, 1)
132
133/* double to [unsigned] long long conversion */
134#define DEFINE__AEABI_D2XLZ(name, with_sign) \
135void __aeabi_ ## name(double_unsigned_struct val) \
136{ \
137 int exp, high_shift, sign; \
138 double_unsigned_struct ret; \
139 \
140 /* compute sign */ \
141 sign = val.high >> 31; \
142 \
143 /* compute real exponent */ \
144 exp = (val.high >> (DOUBLE_FRAC_BITS - 32)); \
145 exp &= (1 << DOUBLE_EXP_BITS) - 1; \
146 exp -= ONE_EXP(DOUBLE); \
147 \
148 /* undefined behavior if truncated value cannot be represented */ \
149 if (with_sign) { \
150 if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
151 return; \
152 } else { \
153 if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
154 return; \
155 } \
156 \
157 val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1; \
158 if (exp >= 32) { \
159 ret.high = 1 << (exp - 32); \
160 if (exp >= DOUBLE_FRAC_BITS) { \
161 high_shift = exp - DOUBLE_FRAC_BITS; \
162 ret.high |= val.high << high_shift; \
163 ret.high |= val.low >> (32 - high_shift); \
164 ret.low = val.low << high_shift; \
165 } else { \
166 high_shift = DOUBLE_FRAC_BITS - exp; \
167 ret.high |= val.high >> high_shift; \
168 ret.low = val.high << (32 - high_shift); \
169 ret.low |= val.low >> high_shift; \
170 } \
171 } else { \
172 ret.high = 0; \
173 ret.low = 1 << exp; \
174 if (exp > DOUBLE_FRAC_BITS - 32) { \
175 high_shift = exp - DOUBLE_FRAC_BITS - 32; \
176 ret.low |= val.high << high_shift; \
177 ret.low |= val.low >> (32 - high_shift); \
178 } else \
179 ret.low |= val.high >> (DOUBLE_FRAC_BITS - 32 - exp); \
180 } \
181 \
182 /* encode negative integer using 2's complement */ \
183 if (with_sign && sign) { \
184 ret.low = ~ret.low; \
185 ret.high = ~ret.high; \
186 if (ret.low == UINT_MAX) { \
187 ret.low = 0; \
188 ret.high++; \
189 } else \
190 ret.low++; \
191 } \
192 \
193 double_unsigned_struct_return(ret); \
194}
195
196/* double to unsigned long long conversion */
197DEFINE__AEABI_D2XLZ(d2ulz, 0)
198
199/* double to long long conversion */
200DEFINE__AEABI_D2XLZ(d2lz, 1)
201
202/* long long to float conversion */
203#define DEFINE__AEABI_XL2F(name, with_sign) \
204unsigned __aeabi_ ## name(unsigned long long v) \
205{ \
206 int s /* shift */, flb /* first lost bit */, sign = 0; \
207 unsigned p = 0 /* power */, ret; \
208 double_unsigned_struct val; \
209 \
210 /* fraction in negative float is encoded in 1's complement */ \
211 if (with_sign && (v & (1ULL << 63))) { \
212 sign = 1; \
213 v = ~v + 1; \
214 } \
215 val.low = v; \
216 val.high = v >> 32; \
217 /* fill fraction bits */ \
218 for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
219 if (p) { \
220 ret = val.high & (p - 1); \
221 if (s < FLOAT_FRAC_BITS) { \
222 ret <<= FLOAT_FRAC_BITS - s; \
223 ret |= val.low >> (32 - (FLOAT_FRAC_BITS - s)); \
224 flb = (val.low >> (32 - (FLOAT_FRAC_BITS - s - 1))) & 1; \
225 } else { \
226 flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
227 ret >>= s - FLOAT_FRAC_BITS; \
228 } \
229 s += 32; \
230 } else { \
231 for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
232 if (p) { \
233 ret = val.low & (p - 1); \
234 if (s <= FLOAT_FRAC_BITS) { \
235 ret <<= FLOAT_FRAC_BITS - s; \
236 flb = 0; \
237 } else { \
238 flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
239 ret >>= s - FLOAT_FRAC_BITS; \
240 } \
241 } else \
242 return 0; \
243 } \
244 if (flb) \
245 ret++; \
246 \
247 /* fill exponent bits */ \
248 ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \
249 \
250 /* fill sign bit */ \
251 ret |= sign << 31; \
252 \
253 return ret; \
254}
255
256/* unsigned long long to float conversion */
257DEFINE__AEABI_XL2F(ul2f, 0)
258
259/* long long to float conversion */
260DEFINE__AEABI_XL2F(l2f, 1)
261
262/* long long to double conversion */
263#define __AEABI_XL2D(name, with_sign) \
264void __aeabi_ ## name(unsigned long long v) \
265{ \
266 int s /* shift */, high_shift, sign = 0; \
267 unsigned tmp, p = 0; \
268 double_unsigned_struct val, ret; \
269 \
270 /* fraction in negative float is encoded in 1's complement */ \
271 if (with_sign && (v & (1ULL << 63))) { \
272 sign = 1; \
273 v = ~v + 1; \
274 } \
275 val.low = v; \
276 val.high = v >> 32; \
277 \
278 /* fill fraction bits */ \
279 for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
280 if (p) { \
281 tmp = val.high & (p - 1); \
282 if (s < DOUBLE_FRAC_BITS - 32) { \
283 high_shift = DOUBLE_FRAC_BITS - 32 - s; \
284 ret.high = tmp << high_shift; \
285 ret.high |= val.low >> (32 - high_shift); \
286 ret.low = val.low << high_shift; \
287 } else { \
288 high_shift = s - (DOUBLE_FRAC_BITS - 32); \
289 ret.high = tmp >> high_shift; \
290 ret.low = tmp << (32 - high_shift); \
291 ret.low |= val.low >> high_shift; \
292 if ((val.low >> (high_shift - 1)) & 1) { \
293 if (ret.low == UINT_MAX) { \
294 ret.high++; \
295 ret.low = 0; \
296 } else \
297 ret.low++; \
298 } \
299 } \
300 s += 32; \
301 } else { \
302 for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
303 if (p) { \
304 tmp = val.low & (p - 1); \
305 if (s <= DOUBLE_FRAC_BITS - 32) { \
306 high_shift = DOUBLE_FRAC_BITS - 32 - s; \
307 ret.high = tmp << high_shift; \
308 ret.low = 0; \
309 } else { \
310 high_shift = s - (DOUBLE_FRAC_BITS - 32); \
311 ret.high = tmp >> high_shift; \
312 ret.low = tmp << (32 - high_shift); \
313 } \
314 } else { \
315 ret.high = ret.low = 0; \
316 double_unsigned_struct_return(ret); \
317 } \
318 } \
319 \
320 /* fill exponent bits */ \
321 ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32); \
322 \
323 /* fill sign bit */ \
324 ret.high |= sign << 31; \
325 \
326 double_unsigned_struct_return(ret); \
327}
328
329/* unsigned long long to double conversion */
330__AEABI_XL2D(ul2d, 0)
331
332/* long long to double conversion */
333__AEABI_XL2D(l2d, 1)
334
335
336/* Long long helper functions */
337
338/* TODO: add error in case of den == 0 (see 則4.3.1 and 則4.3.2) */
339
340#define define_aeabi_xdivmod_signed_type(basetype, type) \
341typedef struct type { \
342 basetype quot; \
343 unsigned basetype rem; \
344} type
345
346#define define_aeabi_xdivmod_unsigned_type(basetype, type) \
347typedef struct type { \
348 basetype quot; \
349 basetype rem; \
350} type
351
352#define AEABI_UXDIVMOD(name,type, rettype, typemacro) \
353static inline rettype aeabi_ ## name (type num, type den) \
354{ \
355 rettype ret; \
356 type quot = 0; \
357 \
358 /* Increase quotient while it is less than numerator */ \
359 while (num >= den) { \
360 type q = 1; \
361 \
362 /* Find closest power of two */ \
363 while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
364 q <<= 1; \
365 \
366 /* Compute difference between current quotient and numerator */ \
367 num -= q * den; \
368 quot += q; \
369 } \
370 ret.quot = quot; \
371 ret.rem = num; \
372 return ret; \
373}
374
375#define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \
376void __aeabi_ ## name(type numerator, type denominator) \
377{ \
378 unsigned type num, den; \
379 urettype uxdiv_ret; \
380 rettype ret; \
381 \
382 if (numerator >= 0) \
383 num = numerator; \
384 else \
385 num = 0 - numerator; \
386 if (denominator >= 0) \
387 den = denominator; \
388 else \
389 den = 0 - denominator; \
390 uxdiv_ret = aeabi_ ## uiname(num, den); \
391 /* signs differ */ \
392 if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \
393 ret.quot = 0 - uxdiv_ret.quot; \
394 else \
395 ret.quot = uxdiv_ret.quot; \
396 if (numerator < 0) \
397 ret.rem = 0 - uxdiv_ret.rem; \
398 else \
399 ret.rem = uxdiv_ret.rem; \
400 \
401 rettype ## _return(ret); \
402}
403
404define_aeabi_xdivmod_signed_type(long long, lldiv_t);
405define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t);
406define_aeabi_xdivmod_signed_type(int, idiv_t);
407define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t);
408
409REGS_RETURN(lldiv_t, lldiv_t)
410REGS_RETURN(ulldiv_t, ulldiv_t)
411REGS_RETURN(idiv_t, idiv_t)
412REGS_RETURN(uidiv_t, uidiv_t)
413
414AEABI_UXDIVMOD(uldivmod, unsigned long long, ulldiv_t, ULLONG)
415
416__AEABI_XDIVMOD(ldivmod, long long, uldivmod, lldiv_t, ulldiv_t, LLONG)
417
418void __aeabi_uldivmod(unsigned long long num, unsigned long long den)
419{
420 ulldiv_t_return(aeabi_uldivmod(num, den));
421}
422
423void __aeabi_llsl(double_unsigned_struct val, int shift)
424{
425 double_unsigned_struct ret;
426
427 if (shift >= 32) {
428 val.high = val.low;
429 val.low = 0;
430 shift -= 32;
431 }
432 if (shift > 0) {
433 ret.low = val.low << shift;
434 ret.high = (val.high << shift) | (val.low >> (32 - shift));
435 double_unsigned_struct_return(ret);
436 return;
437 }
438 double_unsigned_struct_return(val);
439}
440
441#define aeabi_lsr(val, shift, fill, type) \
442 type ## _struct ret; \
443 \
444 if (shift >= 32) { \
445 val.low = val.high; \
446 val.high = fill; \
447 shift -= 32; \
448 } \
449 if (shift > 0) { \
450 ret.high = val.high >> shift; \
451 ret.low = (val.high << (32 - shift)) | (val.low >> shift); \
452 type ## _struct_return(ret); \
453 return; \
454 } \
455 type ## _struct_return(val);
456
457void __aeabi_llsr(double_unsigned_struct val, int shift)
458{
459 aeabi_lsr(val, shift, 0, double_unsigned);
460}
461
462void __aeabi_lasr(unsigned_int_struct val, int shift)
463{
464 aeabi_lsr(val, shift, val.high >> 31, unsigned_int);
465}
466
467
468/* Integer division functions */
469
470AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT)
471
472int __aeabi_idiv(int numerator, int denominator)
473{
474 unsigned num, den;
475 uidiv_t ret;
476
477 if (numerator >= 0)
478 num = numerator;
479 else
480 num = 0 - numerator;
481 if (denominator >= 0)
482 den = denominator;
483 else
484 den = 0 - denominator;
485 ret = aeabi_uidivmod(num, den);
486 if ((numerator & INT_MIN) != (denominator & INT_MIN)) /* signs differ */
487 ret.quot *= -1;
488 return ret.quot;
489}
490
491unsigned __aeabi_uidiv(unsigned num, unsigned den)
492{
493 return aeabi_uidivmod(num, den).quot;
494}
495
496__AEABI_XDIVMOD(idivmod, int, uidivmod, idiv_t, uidiv_t, INT)
497
498void __aeabi_uidivmod(unsigned num, unsigned den)
499{
500 uidiv_t_return(aeabi_uidivmod(num, den));
501}
Note: See TracBrowser for help on using the repository browser.