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
24 /* We rely on the little endianness and EABI calling convention for this to
27 typedef struct double_unsigned_struct
{
30 } double_unsigned_struct
;
32 typedef struct unsigned_int_struct
{
35 } unsigned_int_struct
;
37 #define REGS_RETURN(name, type) \
38 void name ## _return(type ret) {}
41 /* Float helper functions */
43 #define FLOAT_EXP_BITS 8
44 #define FLOAT_FRAC_BITS 23
46 #define DOUBLE_EXP_BITS 11
47 #define DOUBLE_FRAC_BITS 52
49 #define ONE_EXP(type) ((1 << (type ## _EXP_BITS - 1)) - 1)
51 REGS_RETURN(unsigned_int_struct
, unsigned_int_struct
)
52 REGS_RETURN(double_unsigned_struct
, double_unsigned_struct
)
54 /* float -> integer: (sign) 1.fraction x 2^(exponent - exp_for_one) */
57 /* float to [unsigned] long long conversion */
58 #define DEFINE__AEABI_F2XLZ(name, with_sign) \
59 void __aeabi_ ## name(unsigned val) \
61 int exp, high_shift, sign; \
62 double_unsigned_struct ret; \
67 /* compute real exponent */ \
68 exp = val >> FLOAT_FRAC_BITS; \
69 exp &= (1 << FLOAT_EXP_BITS) - 1; \
70 exp -= ONE_EXP(FLOAT); \
72 /* undefined behavior if truncated value cannot be represented */ \
74 if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
77 if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
81 val &= (1 << FLOAT_FRAC_BITS) - 1; \
83 ret.high = 1 << (exp - 32); \
84 if (exp - 32 >= FLOAT_FRAC_BITS) { \
85 ret.high |= val << (exp - 32 - FLOAT_FRAC_BITS); \
88 high_shift = FLOAT_FRAC_BITS - (exp - 32); \
89 ret.high |= val >> high_shift; \
90 ret.low = val << (32 - high_shift); \
95 if (exp > FLOAT_FRAC_BITS) \
96 ret.low |= val << (exp - FLOAT_FRAC_BITS); \
98 ret.low |= val >> (FLOAT_FRAC_BITS - exp); \
101 /* encode negative integer using 2's complement */ \
102 if (with_sign && sign) { \
103 ret.low = ~ret.low; \
104 ret.high = ~ret.high; \
105 if (ret.low == UINT_MAX) { \
112 double_unsigned_struct_return(ret); \
115 /* float to unsigned long long conversion */
116 DEFINE__AEABI_F2XLZ(f2ulz
, 0)
118 /* float to long long conversion */
119 DEFINE__AEABI_F2XLZ(f2lz
, 1)
121 /* double to [unsigned] long long conversion */
122 #define DEFINE__AEABI_D2XLZ(name, with_sign) \
123 void __aeabi_ ## name(double_unsigned_struct val) \
125 int exp, high_shift, sign; \
126 double_unsigned_struct ret; \
129 sign = val.high >> 31; \
131 /* compute real exponent */ \
132 exp = (val.high >> (DOUBLE_FRAC_BITS - 32)); \
133 exp &= (1 << DOUBLE_EXP_BITS) - 1; \
134 exp -= ONE_EXP(DOUBLE); \
136 /* undefined behavior if truncated value cannot be represented */ \
138 if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
141 if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
145 val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1; \
147 ret.high = 1 << (exp - 32); \
148 if (exp >= DOUBLE_FRAC_BITS) { \
149 high_shift = exp - DOUBLE_FRAC_BITS; \
150 ret.high |= val.high << high_shift; \
151 ret.high |= val.low >> (32 - high_shift); \
152 ret.low = val.low << high_shift; \
154 high_shift = DOUBLE_FRAC_BITS - exp; \
155 ret.high |= val.high >> high_shift; \
156 ret.low = val.high << (32 - high_shift); \
157 ret.low |= val.low >> high_shift; \
161 ret.low = 1 << exp; \
162 if (exp > DOUBLE_FRAC_BITS - 32) { \
163 high_shift = exp - DOUBLE_FRAC_BITS - 32; \
164 ret.low |= val.high << high_shift; \
165 ret.low |= val.low >> (32 - high_shift); \
167 ret.low |= val.high >> (DOUBLE_FRAC_BITS - 32 - exp); \
170 /* encode negative integer using 2's complement */ \
171 if (with_sign && sign) { \
172 ret.low = ~ret.low; \
173 ret.high = ~ret.high; \
174 if (ret.low == UINT_MAX) { \
181 double_unsigned_struct_return(ret); \
184 /* double to unsigned long long conversion */
185 DEFINE__AEABI_D2XLZ(d2ulz
, 0)
187 /* double to long long conversion */
188 DEFINE__AEABI_D2XLZ(d2lz
, 1)
190 /* long long to float conversion */
191 #define DEFINE__AEABI_XL2F(name, with_sign) \
192 unsigned __aeabi_ ## name(unsigned long long v) \
194 int s /* shift */, flb /* first lost bit */, sign = 0; \
195 unsigned p = 0 /* power */, ret; \
196 double_unsigned_struct val; \
198 /* fraction in negative float is encoded in 1's complement */ \
199 if (with_sign && (v & (1ULL << 63))) { \
204 val.high = v >> 32; \
205 /* fill fraction bits */ \
206 for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
208 ret = val.high & (p - 1); \
209 if (s < FLOAT_FRAC_BITS) { \
210 ret <<= FLOAT_FRAC_BITS - s; \
211 ret |= val.low >> (32 - (FLOAT_FRAC_BITS - s)); \
212 flb = (val.low >> (32 - (FLOAT_FRAC_BITS - s - 1))) & 1; \
214 flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
215 ret >>= s - FLOAT_FRAC_BITS; \
219 for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
221 ret = val.low & (p - 1); \
222 if (s <= FLOAT_FRAC_BITS) { \
223 ret <<= FLOAT_FRAC_BITS - s; \
226 flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
227 ret >>= s - FLOAT_FRAC_BITS; \
235 /* fill exponent bits */ \
236 ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \
238 /* fill sign bit */ \
244 /* unsigned long long to float conversion */
245 DEFINE__AEABI_XL2F(ul2f
, 0)
247 /* long long to float conversion */
248 DEFINE__AEABI_XL2F(l2f
, 1)
250 /* long long to double conversion */
251 #define __AEABI_XL2D(name, with_sign) \
252 void __aeabi_ ## name(unsigned long long v) \
254 int s /* shift */, high_shift, sign = 0; \
255 unsigned tmp, p = 0; \
256 double_unsigned_struct val, ret; \
258 /* fraction in negative float is encoded in 1's complement */ \
259 if (with_sign && (v & (1ULL << 63))) { \
264 val.high = v >> 32; \
266 /* fill fraction bits */ \
267 for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
269 tmp = val.high & (p - 1); \
270 if (s < DOUBLE_FRAC_BITS - 32) { \
271 high_shift = DOUBLE_FRAC_BITS - 32 - s; \
272 ret.high = tmp << high_shift; \
273 ret.high |= val.low >> (32 - high_shift); \
274 ret.low = val.low << high_shift; \
276 high_shift = s - (DOUBLE_FRAC_BITS - 32); \
277 ret.high = tmp >> high_shift; \
278 ret.low = tmp << (32 - high_shift); \
279 ret.low |= val.low >> high_shift; \
280 if ((val.low >> (high_shift - 1)) & 1) { \
281 if (ret.low == UINT_MAX) { \
290 for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
292 tmp = val.low & (p - 1); \
293 if (s <= DOUBLE_FRAC_BITS - 32) { \
294 high_shift = DOUBLE_FRAC_BITS - 32 - s; \
295 ret.high = tmp << high_shift; \
298 high_shift = s - (DOUBLE_FRAC_BITS - 32); \
299 ret.high = tmp >> high_shift; \
300 ret.low = tmp << (32 - high_shift); \
303 ret.high = ret.low = 0; \
304 double_unsigned_struct_return(ret); \
308 /* fill exponent bits */ \
309 ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32); \
311 /* fill sign bit */ \
312 ret.high |= sign << 31; \
314 double_unsigned_struct_return(ret); \
317 /* unsigned long long to double conversion */
318 __AEABI_XL2D(ul2d
, 0)
320 /* long long to double conversion */
324 /* Long long helper functions */
326 /* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */
328 #define define_aeabi_xdivmod_signed_type(basetype, type) \
329 typedef struct type { \
331 unsigned basetype rem; \
334 #define define_aeabi_xdivmod_unsigned_type(basetype, type) \
335 typedef struct type { \
340 #define AEABI_UXDIVMOD(name,type, rettype, typemacro) \
341 static inline rettype aeabi_ ## name (type num, type den) \
346 /* Increase quotient while it is less than numerator */ \
347 while (num >= den) { \
350 /* Find closest power of two */ \
351 while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
354 /* Compute difference between current quotient and numerator */ \
363 #define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \
364 void __aeabi_ ## name(type numerator, type denominator) \
366 unsigned type num, den; \
367 urettype uxdiv_ret; \
370 if (numerator >= 0) \
373 num = 0 - numerator; \
374 if (denominator >= 0) \
377 den = 0 - denominator; \
378 uxdiv_ret = aeabi_ ## uiname(num, den); \
380 if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \
381 ret.quot = 0 - uxdiv_ret.quot; \
383 ret.quot = uxdiv_ret.quot; \
385 ret.rem = 0 - uxdiv_ret.rem; \
387 ret.rem = uxdiv_ret.rem; \
389 rettype ## _return(ret); \
392 define_aeabi_xdivmod_signed_type(long long, lldiv_t
);
393 define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t
);
394 define_aeabi_xdivmod_signed_type(int, idiv_t
);
395 define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t
);
397 REGS_RETURN(lldiv_t
, lldiv_t
)
398 REGS_RETURN(ulldiv_t
, ulldiv_t
)
399 REGS_RETURN(idiv_t
, idiv_t
)
400 REGS_RETURN(uidiv_t
, uidiv_t
)
402 AEABI_UXDIVMOD(uldivmod
, unsigned long long, ulldiv_t
, ULONG
)
404 __AEABI_XDIVMOD(ldivmod
, long long, uldivmod
, lldiv_t
, ulldiv_t
, LLONG
)
406 void __aeabi_uldivmod(unsigned long long num
, unsigned long long den
)
408 ulldiv_t_return(aeabi_uldivmod(num
, den
));
411 void __aeabi_llsl(double_unsigned_struct val
, int shift
)
413 double_unsigned_struct ret
;
421 ret
.low
= val
.low
<< shift
;
422 ret
.high
= (val
.high
<< shift
) | (val
.low
>> (32 - shift
));
423 double_unsigned_struct_return(ret
);
426 double_unsigned_struct_return(val
);
429 #define aeabi_lsr(val, shift, fill, type) \
430 type ## _struct ret; \
433 val.low = val.high; \
438 ret.high = val.high >> shift; \
439 ret.low = (val.high << (32 - shift)) | (val.low >> shift); \
440 type ## _struct_return(ret); \
443 type ## _struct_return(val);
445 void __aeabi_llsr(double_unsigned_struct val
, int shift
)
447 aeabi_lsr(val
, shift
, 0, double_unsigned
);
450 void __aeabi_lasr(unsigned_int_struct val
, int shift
)
452 aeabi_lsr(val
, shift
, val
.high
>> 31, unsigned_int
);
456 /* Integer division functions */
458 AEABI_UXDIVMOD(uidivmod
, unsigned, uidiv_t
, UINT
)
460 int __aeabi_idiv(int numerator
, int denominator
)
469 if (denominator
>= 0)
472 den
= 0 - denominator
;
473 ret
= aeabi_uidivmod(num
, den
);
474 if ((numerator
& INT_MIN
) != (denominator
& INT_MIN
)) /* signs differ */
479 unsigned __aeabi_uidiv(unsigned num
, unsigned den
)
481 return aeabi_uidivmod(num
, den
).quot
;
484 __AEABI_XDIVMOD(idivmod
, int, uidivmod
, idiv_t
, uidiv_t
, INT
)
486 void __aeabi_uidivmod(unsigned num
, unsigned den
)
488 uidiv_t_return(aeabi_uidivmod(num
, den
));