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; \
141 sign = val.high >> 31; \
143 /* compute real exponent */ \
144 exp = (val.high >> (DOUBLE_FRAC_BITS - 32)); \
145 exp &= (1 << DOUBLE_EXP_BITS) - 1; \
146 exp -= ONE_EXP(DOUBLE); \
148 /* undefined behavior if truncated value cannot be represented */ \
150 if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
153 if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
157 val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1; \
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; \
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; \
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); \
179 ret.low |= val.high >> (DOUBLE_FRAC_BITS - 32 - exp); \
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) { \
193 double_unsigned_struct_return(ret); \
196 /* double to unsigned long long conversion */
197 DEFINE__AEABI_D2XLZ(d2ulz
, 0)
199 /* double to long long conversion */
200 DEFINE__AEABI_D2XLZ(d2lz
, 1)
202 /* long long to float conversion */
203 #define DEFINE__AEABI_XL2F(name, with_sign) \
204 unsigned __aeabi_ ## name(unsigned long long v) \
206 int s /* shift */, flb /* first lost bit */, sign = 0; \
207 unsigned p = 0 /* power */, ret; \
208 double_unsigned_struct val; \
210 /* fraction in negative float is encoded in 1's complement */ \
211 if (with_sign && (v & (1ULL << 63))) { \
216 val.high = v >> 32; \
217 /* fill fraction bits */ \
218 for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
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; \
226 flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
227 ret >>= s - FLOAT_FRAC_BITS; \
231 for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
233 ret = val.low & (p - 1); \
234 if (s <= FLOAT_FRAC_BITS) { \
235 ret <<= FLOAT_FRAC_BITS - s; \
238 flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
239 ret >>= s - FLOAT_FRAC_BITS; \
247 /* fill exponent bits */ \
248 ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \
250 /* fill sign bit */ \
256 /* unsigned long long to float conversion */
257 DEFINE__AEABI_XL2F(ul2f
, 0)
259 /* long long to float conversion */
260 DEFINE__AEABI_XL2F(l2f
, 1)
262 /* long long to double conversion */
263 #define __AEABI_XL2D(name, with_sign) \
264 void __aeabi_ ## name(unsigned long long v) \
266 int s /* shift */, high_shift, sign = 0; \
267 unsigned tmp, p = 0; \
268 double_unsigned_struct val, ret; \
270 /* fraction in negative float is encoded in 1's complement */ \
271 if (with_sign && (v & (1ULL << 63))) { \
276 val.high = v >> 32; \
278 /* fill fraction bits */ \
279 for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
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; \
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) { \
302 for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
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; \
310 high_shift = s - (DOUBLE_FRAC_BITS - 32); \
311 ret.high = tmp >> high_shift; \
312 ret.low = tmp << (32 - high_shift); \
315 ret.high = ret.low = 0; \
316 double_unsigned_struct_return(ret); \
320 /* fill exponent bits */ \
321 ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32); \
323 /* fill sign bit */ \
324 ret.high |= sign << 31; \
326 double_unsigned_struct_return(ret); \
329 /* unsigned long long to double conversion */
330 __AEABI_XL2D(ul2d
, 0)
332 /* long long to double conversion */
336 /* Long long helper functions */
338 /* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */
340 #define define_aeabi_xdivmod_signed_type(basetype, type) \
341 typedef struct type { \
343 unsigned basetype rem; \
346 #define define_aeabi_xdivmod_unsigned_type(basetype, type) \
347 typedef struct type { \
352 #define AEABI_UXDIVMOD(name,type, rettype, typemacro) \
353 static inline rettype aeabi_ ## name (type num, type den) \
358 /* Increase quotient while it is less than numerator */ \
359 while (num >= den) { \
362 /* Find closest power of two */ \
363 while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
366 /* Compute difference between current quotient and numerator */ \
375 #define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \
376 void __aeabi_ ## name(type numerator, type denominator) \
378 unsigned type num, den; \
379 urettype uxdiv_ret; \
382 if (numerator >= 0) \
385 num = 0 - numerator; \
386 if (denominator >= 0) \
389 den = 0 - denominator; \
390 uxdiv_ret = aeabi_ ## uiname(num, den); \
392 if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \
393 ret.quot = 0 - uxdiv_ret.quot; \
395 ret.quot = uxdiv_ret.quot; \
397 ret.rem = 0 - uxdiv_ret.rem; \
399 ret.rem = uxdiv_ret.rem; \
401 rettype ## _return(ret); \
404 define_aeabi_xdivmod_signed_type(long long, lldiv_t
);
405 define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t
);
406 define_aeabi_xdivmod_signed_type(int, idiv_t
);
407 define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t
);
409 REGS_RETURN(lldiv_t
, lldiv_t
)
410 REGS_RETURN(ulldiv_t
, ulldiv_t
)
411 REGS_RETURN(idiv_t
, idiv_t
)
412 REGS_RETURN(uidiv_t
, uidiv_t
)
414 AEABI_UXDIVMOD(uldivmod
, unsigned long long, ulldiv_t
, ULLONG
)
416 __AEABI_XDIVMOD(ldivmod
, long long, uldivmod
, lldiv_t
, ulldiv_t
, LLONG
)
418 void __aeabi_uldivmod(unsigned long long num
, unsigned long long den
)
420 ulldiv_t_return(aeabi_uldivmod(num
, den
));
423 void __aeabi_llsl(double_unsigned_struct val
, int shift
)
425 double_unsigned_struct ret
;
433 ret
.low
= val
.low
<< shift
;
434 ret
.high
= (val
.high
<< shift
) | (val
.low
>> (32 - shift
));
435 double_unsigned_struct_return(ret
);
438 double_unsigned_struct_return(val
);
441 #define aeabi_lsr(val, shift, fill, type) \
442 type ## _struct ret; \
445 val.low = val.high; \
450 ret.high = val.high >> shift; \
451 ret.low = (val.high << (32 - shift)) | (val.low >> shift); \
452 type ## _struct_return(ret); \
455 type ## _struct_return(val);
457 void __aeabi_llsr(double_unsigned_struct val
, int shift
)
459 aeabi_lsr(val
, shift
, 0, double_unsigned
);
462 void __aeabi_lasr(unsigned_int_struct val
, int shift
)
464 aeabi_lsr(val
, shift
, val
.high
>> 31, unsigned_int
);
468 /* Integer division functions */
470 AEABI_UXDIVMOD(uidivmod
, unsigned, uidiv_t
, UINT
)
472 int __aeabi_idiv(int numerator
, int denominator
)
481 if (denominator
>= 0)
484 den
= 0 - denominator
;
485 ret
= aeabi_uidivmod(num
, den
);
486 if ((numerator
& INT_MIN
) != (denominator
& INT_MIN
)) /* signs differ */
491 unsigned __aeabi_uidiv(unsigned num
, unsigned den
)
493 return aeabi_uidivmod(num
, den
).quot
;
496 __AEABI_XDIVMOD(idivmod
, int, uidivmod
, idiv_t
, uidiv_t
, INT
)
498 void __aeabi_uidivmod(unsigned num
, unsigned den
)
500 uidiv_t_return(aeabi_uidivmod(num
, den
));