Add linker's --export-dynamic flag alias
[tinycc.git] / lib / armeabi.c
bloba59640dd076051a86804b016fe3c62f15bf4f3f9
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
20 THE SOFTWARE.*/
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
36 /* We rely on the little endianness and EABI calling convention for this to
37 work */
39 typedef struct double_unsigned_struct {
40 unsigned low;
41 unsigned high;
42 } double_unsigned_struct;
44 typedef struct unsigned_int_struct {
45 unsigned low;
46 int high;
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) \
72 { \
73 int exp, high_shift, sign; \
74 double_unsigned_struct ret; \
76 /* compute sign */ \
77 sign = val >> 31; \
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 */ \
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 } \
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); \
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); \
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++; \
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 /* compute sign */ \
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 */ \
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; \
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; \
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); \
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++; \
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))) { \
212 sign = 1; \
213 v = ~v + 1; \
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; \
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; \
241 } else \
242 return 0; \
244 if (flb) \
245 ret++; \
247 /* fill exponent bits */ \
248 ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \
250 /* fill sign bit */ \
251 ret |= sign << 31; \
253 return ret; \
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))) { \
272 sign = 1; \
273 v = ~v + 1; \
275 val.low = v; \
276 val.high = v >> 32; \
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++; \
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); \
314 } else { \
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 */
333 __AEABI_XL2D(l2d, 1)
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 { \
342 basetype quot; \
343 unsigned basetype rem; \
344 } type
346 #define define_aeabi_xdivmod_unsigned_type(basetype, type) \
347 typedef struct type { \
348 basetype quot; \
349 basetype rem; \
350 } type
352 #define AEABI_UXDIVMOD(name,type, rettype, typemacro) \
353 static inline rettype aeabi_ ## name (type num, type den) \
355 rettype ret; \
356 type quot = 0; \
358 /* Increase quotient while it is less than numerator */ \
359 while (num >= den) { \
360 type q = 1; \
362 /* Find closest power of two */ \
363 while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
364 q <<= 1; \
366 /* Compute difference between current quotient and numerator */ \
367 num -= q * den; \
368 quot += q; \
370 ret.quot = quot; \
371 ret.rem = num; \
372 return ret; \
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; \
380 rettype ret; \
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; \
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;
427 if (shift >= 32) {
428 val.high = val.low;
429 val.low = 0;
430 shift -= 32;
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;
438 double_unsigned_struct_return(val);
441 #define aeabi_lsr(val, shift, fill, type) \
442 type ## _struct ret; \
444 if (shift >= 32) { \
445 val.low = val.high; \
446 val.high = fill; \
447 shift -= 32; \
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; \
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)
474 unsigned num, den;
475 uidiv_t ret;
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;
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));