1 /* TCC ARM runtime EABI
2 Copyright (C) 2013 Thomas Preud'homme
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
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
36 /* We rely on the little endianness and EABI calling convention for this to
39 typedef struct double_unsigned_struct
{
42 } double_unsigned_struct
;
44 typedef struct unsigned_int_struct
{
47 } unsigned_int_struct
;
49 #define REGS_RETURN(name, type) \
50 void name ## _return(type ret) {}
53 /* Float helper functions */
55 #define FLOAT_EXP_BITS 8
56 #define FLOAT_FRAC_BITS 23
58 #define DOUBLE_EXP_BITS 11
59 #define DOUBLE_FRAC_BITS 52
61 #define ONE_EXP(type) ((1 << (type ## _EXP_BITS - 1)) - 1)
63 REGS_RETURN(unsigned_int_struct
, unsigned_int_struct
)
64 REGS_RETURN(double_unsigned_struct
, double_unsigned_struct
)
66 /* float -> integer: (sign) 1.fraction x 2^(exponent - exp_for_one) */
69 /* float to [unsigned] long long conversion */
70 #define DEFINE__AEABI_F2XLZ(name, with_sign) \
71 void __aeabi_ ## name(unsigned val) \
73 int exp, high_shift, sign; \
74 double_unsigned_struct ret; \
79 /* compute real exponent */ \
80 exp = val >> FLOAT_FRAC_BITS; \
81 exp &= (1 << FLOAT_EXP_BITS) - 1; \
82 exp -= ONE_EXP(FLOAT); \
84 /* undefined behavior if truncated value cannot be represented */ \
86 if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
89 if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
93 val &= (1 << FLOAT_FRAC_BITS) - 1; \
95 ret.high = 1 << (exp - 32); \
96 if (exp - 32 >= FLOAT_FRAC_BITS) { \
97 ret.high |= val << (exp - 32 - FLOAT_FRAC_BITS); \
100 high_shift = FLOAT_FRAC_BITS - (exp - 32); \
101 ret.high |= val >> high_shift; \
102 ret.low = val << (32 - high_shift); \
106 ret.low = 1 << exp; \
107 if (exp > FLOAT_FRAC_BITS) \
108 ret.low |= val << (exp - FLOAT_FRAC_BITS); \
110 ret.low |= val >> (FLOAT_FRAC_BITS - exp); \
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) { \
124 double_unsigned_struct_return(ret); \
127 /* float to unsigned long long conversion */
128 DEFINE__AEABI_F2XLZ(f2ulz
, 0)
130 /* float to long long conversion */
131 DEFINE__AEABI_F2XLZ(f2lz
, 1)
133 /* double to [unsigned] long long conversion */
134 #define DEFINE__AEABI_D2XLZ(name, with_sign) \
135 void __aeabi_ ## name(double_unsigned_struct val) \
137 int exp, high_shift, sign; \
138 double_unsigned_struct ret; \
140 if ((val.high & ~0x80000000) == 0 && val.low == 0) { \
141 ret.low = ret.high = 0; \
146 sign = val.high >> 31; \
148 /* compute real exponent */ \
149 exp = (val.high >> (DOUBLE_FRAC_BITS - 32)); \
150 exp &= (1 << DOUBLE_EXP_BITS) - 1; \
151 exp -= ONE_EXP(DOUBLE); \
153 /* undefined behavior if truncated value cannot be represented */ \
155 if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
158 if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
162 val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1; \
164 ret.high = 1 << (exp - 32); \
165 if (exp >= DOUBLE_FRAC_BITS) { \
166 high_shift = exp - DOUBLE_FRAC_BITS; \
167 ret.high |= val.high << high_shift; \
168 ret.high |= val.low >> (32 - high_shift); \
169 ret.low = val.low << high_shift; \
171 high_shift = DOUBLE_FRAC_BITS - exp; \
172 ret.high |= val.high >> high_shift; \
173 ret.low = val.high << (32 - high_shift); \
174 ret.low |= val.low >> high_shift; \
178 ret.low = 1 << exp; \
179 if (exp > DOUBLE_FRAC_BITS - 32) { \
180 high_shift = exp - DOUBLE_FRAC_BITS - 32; \
181 ret.low |= val.high << high_shift; \
182 ret.low |= val.low >> (32 - high_shift); \
184 ret.low |= val.high >> (DOUBLE_FRAC_BITS - 32 - exp); \
187 /* encode negative integer using 2's complement */ \
188 if (with_sign && sign) { \
189 ret.low = ~ret.low; \
190 ret.high = ~ret.high; \
191 if (ret.low == UINT_MAX) { \
199 double_unsigned_struct_return(ret); \
202 /* double to unsigned long long conversion */
203 DEFINE__AEABI_D2XLZ(d2ulz
, 0)
205 /* double to long long conversion */
206 DEFINE__AEABI_D2XLZ(d2lz
, 1)
208 /* long long to float conversion */
209 #define DEFINE__AEABI_XL2F(name, with_sign) \
210 unsigned __aeabi_ ## name(unsigned long long v) \
212 int s /* shift */, flb /* first lost bit */, sign = 0; \
213 unsigned p = 0 /* power */, ret; \
214 double_unsigned_struct val; \
216 /* fraction in negative float is encoded in 1's complement */ \
217 if (with_sign && (v & (1ULL << 63))) { \
222 val.high = v >> 32; \
223 /* fill fraction bits */ \
224 for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
226 ret = val.high & (p - 1); \
227 if (s < FLOAT_FRAC_BITS) { \
228 ret <<= FLOAT_FRAC_BITS - s; \
229 ret |= val.low >> (32 - (FLOAT_FRAC_BITS - s)); \
230 flb = (val.low >> (32 - (FLOAT_FRAC_BITS - s - 1))) & 1; \
232 flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
233 ret >>= s - FLOAT_FRAC_BITS; \
237 for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
239 ret = val.low & (p - 1); \
240 if (s <= FLOAT_FRAC_BITS) { \
241 ret <<= FLOAT_FRAC_BITS - s; \
244 flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
245 ret >>= s - FLOAT_FRAC_BITS; \
253 /* fill exponent bits */ \
254 ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \
256 /* fill sign bit */ \
262 /* unsigned long long to float conversion */
263 DEFINE__AEABI_XL2F(ul2f
, 0)
265 /* long long to float conversion */
266 DEFINE__AEABI_XL2F(l2f
, 1)
268 /* long long to double conversion */
269 #define __AEABI_XL2D(name, with_sign) \
270 void __aeabi_ ## name(unsigned long long v) \
272 int s /* shift */, high_shift, sign = 0; \
273 unsigned tmp, p = 0; \
274 double_unsigned_struct val, ret; \
276 /* fraction in negative float is encoded in 1's complement */ \
277 if (with_sign && (v & (1ULL << 63))) { \
282 val.high = v >> 32; \
284 /* fill fraction bits */ \
285 for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
287 tmp = val.high & (p - 1); \
288 if (s < DOUBLE_FRAC_BITS - 32) { \
289 high_shift = DOUBLE_FRAC_BITS - 32 - s; \
290 ret.high = tmp << high_shift; \
291 ret.high |= val.low >> (32 - high_shift); \
292 ret.low = val.low << high_shift; \
294 high_shift = s - (DOUBLE_FRAC_BITS - 32); \
295 ret.high = tmp >> high_shift; \
296 ret.low = tmp << (32 - high_shift); \
297 ret.low |= val.low >> high_shift; \
298 if ((val.low >> (high_shift - 1)) & 1) { \
299 if (ret.low == UINT_MAX) { \
308 for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
310 tmp = val.low & (p - 1); \
311 if (s <= DOUBLE_FRAC_BITS - 32) { \
312 high_shift = DOUBLE_FRAC_BITS - 32 - s; \
313 ret.high = tmp << high_shift; \
316 high_shift = s - (DOUBLE_FRAC_BITS - 32); \
317 ret.high = tmp >> high_shift; \
318 ret.low = tmp << (32 - high_shift); \
321 ret.high = ret.low = 0; \
326 /* fill exponent bits */ \
327 ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32); \
329 /* fill sign bit */ \
330 ret.high |= sign << 31; \
333 double_unsigned_struct_return(ret); \
336 /* unsigned long long to double conversion */
337 __AEABI_XL2D(ul2d
, 0)
339 /* long long to double conversion */
343 /* Long long helper functions */
345 /* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */
347 #define define_aeabi_xdivmod_signed_type(basetype, type) \
348 typedef struct type { \
350 unsigned basetype rem; \
353 #define define_aeabi_xdivmod_unsigned_type(basetype, type) \
354 typedef struct type { \
359 #define AEABI_UXDIVMOD(name,type, rettype, typemacro) \
360 static inline rettype aeabi_ ## name (type num, type den) \
365 /* Increase quotient while it is less than numerator */ \
366 while (num >= den) { \
369 /* Find closest power of two */ \
370 while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
373 /* Compute difference between current quotient and numerator */ \
382 #define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \
383 void __aeabi_ ## name(type numerator, type denominator) \
385 unsigned type num, den; \
386 urettype uxdiv_ret; \
389 if (numerator >= 0) \
392 num = 0 - numerator; \
393 if (denominator >= 0) \
396 den = 0 - denominator; \
397 uxdiv_ret = aeabi_ ## uiname(num, den); \
399 if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \
400 ret.quot = 0 - uxdiv_ret.quot; \
402 ret.quot = uxdiv_ret.quot; \
404 ret.rem = 0 - uxdiv_ret.rem; \
406 ret.rem = uxdiv_ret.rem; \
408 rettype ## _return(ret); \
411 define_aeabi_xdivmod_signed_type(long long, lldiv_t
);
412 define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t
);
413 define_aeabi_xdivmod_signed_type(int, idiv_t
);
414 define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t
);
416 REGS_RETURN(lldiv_t
, lldiv_t
)
417 REGS_RETURN(ulldiv_t
, ulldiv_t
)
418 REGS_RETURN(idiv_t
, idiv_t
)
419 REGS_RETURN(uidiv_t
, uidiv_t
)
421 AEABI_UXDIVMOD(uldivmod
, unsigned long long, ulldiv_t
, ULLONG
)
423 __AEABI_XDIVMOD(ldivmod
, long long, uldivmod
, lldiv_t
, ulldiv_t
, LLONG
)
425 void __aeabi_uldivmod(unsigned long long num
, unsigned long long den
)
427 ulldiv_t_return(aeabi_uldivmod(num
, den
));
430 void __aeabi_llsl(double_unsigned_struct val
, int shift
)
432 double_unsigned_struct ret
;
440 ret
.low
= val
.low
<< shift
;
441 ret
.high
= (val
.high
<< shift
) | (val
.low
>> (32 - shift
));
442 double_unsigned_struct_return(ret
);
445 double_unsigned_struct_return(val
);
448 #define aeabi_lsr(val, shift, fill, type) \
449 type ## _struct ret; \
452 val.low = val.high; \
457 ret.high = val.high >> shift; \
458 ret.low = (val.high << (32 - shift)) | (val.low >> shift); \
459 type ## _struct_return(ret); \
462 type ## _struct_return(val);
464 void __aeabi_llsr(double_unsigned_struct val
, int shift
)
466 aeabi_lsr(val
, shift
, 0, double_unsigned
);
469 void __aeabi_lasr(unsigned_int_struct val
, int shift
)
471 aeabi_lsr(val
, shift
, val
.high
>> 31, unsigned_int
);
475 /* Integer division functions */
477 AEABI_UXDIVMOD(uidivmod
, unsigned, uidiv_t
, UINT
)
479 int __aeabi_idiv(int numerator
, int denominator
)
488 if (denominator
>= 0)
491 den
= 0 - denominator
;
492 ret
= aeabi_uidivmod(num
, den
);
493 if ((numerator
& INT_MIN
) != (denominator
& INT_MIN
)) /* signs differ */
498 unsigned __aeabi_uidiv(unsigned num
, unsigned den
)
500 return aeabi_uidivmod(num
, den
).quot
;
503 __AEABI_XDIVMOD(idivmod
, int, uidivmod
, idiv_t
, uidiv_t
, INT
)
505 void __aeabi_uidivmod(unsigned num
, unsigned den
)
507 uidiv_t_return(aeabi_uidivmod(num
, den
));
510 /* Some targets do not have all eabi calls (OpenBSD) */
511 typedef __SIZE_TYPE__
size_t;
512 extern void *memcpy(void *dest
, const void *src
, size_t n
);
513 extern void *memmove(void *dest
, const void *src
, size_t n
);
514 extern void *memset(void *s
, int c
, size_t n
);
517 __aeabi_memcpy (void *dest
, const void *src
, size_t n
)
519 return memcpy (dest
, src
, n
);
523 __aeabi_memmove (void *dest
, const void *src
, size_t n
)
525 return memmove (dest
, src
, n
);
529 __aeabi_memmove4 (void *dest
, const void *src
, size_t n
)
531 return memmove (dest
, src
, n
);
535 __aeabi_memmove8 (void *dest
, const void *src
, size_t n
)
537 return memmove (dest
, src
, n
);
541 __aeabi_memset (void *s
, size_t n
, int c
)
543 return memset (s
, c
, n
);