Specify license of lib/armeabi.c
[tinycc.git] / lib / armeabi.c
blob0d1217ba8f35a1729ae87c1593b703846d5804bb
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 #include <limits.h>
24 /* We rely on the little endianness and EABI calling convention for this to
25 work */
27 typedef struct double_unsigned_struct {
28 unsigned low;
29 unsigned high;
30 } double_unsigned_struct;
32 typedef struct unsigned_int_struct {
33 unsigned low;
34 int high;
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) \
60 { \
61 int exp, high_shift, sign; \
62 double_unsigned_struct ret; \
64 /* compute sign */ \
65 sign = val >> 31; \
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 */ \
73 if (with_sign) { \
74 if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
75 return; \
76 } else { \
77 if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
78 return; \
79 } \
81 val &= (1 << FLOAT_FRAC_BITS) - 1; \
82 if (exp >= 32) { \
83 ret.high = 1 << (exp - 32); \
84 if (exp - 32 >= FLOAT_FRAC_BITS) { \
85 ret.high |= val << (exp - 32 - FLOAT_FRAC_BITS); \
86 ret.low = 0; \
87 } else { \
88 high_shift = FLOAT_FRAC_BITS - (exp - 32); \
89 ret.high |= val >> high_shift; \
90 ret.low = val << (32 - high_shift); \
91 } \
92 } else { \
93 ret.high = 0; \
94 ret.low = 1 << exp; \
95 if (exp > FLOAT_FRAC_BITS) \
96 ret.low |= val << (exp - FLOAT_FRAC_BITS); \
97 else \
98 ret.low |= val >> (FLOAT_FRAC_BITS - exp); \
99 } \
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) { \
106 ret.low = 0; \
107 ret.high++; \
108 } else \
109 ret.low++; \
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; \
128 /* compute sign */ \
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 */ \
137 if (with_sign) { \
138 if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
139 return; \
140 } else { \
141 if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
142 return; \
145 val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1; \
146 if (exp >= 32) { \
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; \
153 } else { \
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; \
159 } else { \
160 ret.high = 0; \
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); \
166 } else \
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) { \
175 ret.low = 0; \
176 ret.high++; \
177 } else \
178 ret.low++; \
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))) { \
200 sign = 1; \
201 v = ~v + 1; \
203 val.low = v; \
204 val.high = v >> 32; \
205 /* fill fraction bits */ \
206 for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
207 if (p) { \
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; \
213 } else { \
214 flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
215 ret >>= s - FLOAT_FRAC_BITS; \
217 s += 32; \
218 } else { \
219 for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
220 if (p) { \
221 ret = val.low & (p - 1); \
222 if (s <= FLOAT_FRAC_BITS) { \
223 ret <<= FLOAT_FRAC_BITS - s; \
224 flb = 0; \
225 } else { \
226 flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
227 ret >>= s - FLOAT_FRAC_BITS; \
229 } else \
230 return 0; \
232 if (flb) \
233 ret++; \
235 /* fill exponent bits */ \
236 ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \
238 /* fill sign bit */ \
239 ret |= sign << 31; \
241 return ret; \
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))) { \
260 sign = 1; \
261 v = ~v + 1; \
263 val.low = v; \
264 val.high = v >> 32; \
266 /* fill fraction bits */ \
267 for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
268 if (p) { \
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; \
275 } else { \
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) { \
282 ret.high++; \
283 ret.low = 0; \
284 } else \
285 ret.low++; \
288 s += 32; \
289 } else { \
290 for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
291 if (p) { \
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; \
296 ret.low = 0; \
297 } else { \
298 high_shift = s - (DOUBLE_FRAC_BITS - 32); \
299 ret.high = tmp >> high_shift; \
300 ret.low = tmp << (32 - high_shift); \
302 } else { \
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 */
321 __AEABI_XL2D(l2d, 1)
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 { \
330 basetype quot; \
331 unsigned basetype rem; \
332 } type
334 #define define_aeabi_xdivmod_unsigned_type(basetype, type) \
335 typedef struct type { \
336 basetype quot; \
337 basetype rem; \
338 } type
340 #define AEABI_UXDIVMOD(name,type, rettype, typemacro) \
341 static inline rettype aeabi_ ## name (type num, type den) \
343 rettype ret; \
344 type quot = 0; \
346 /* Increase quotient while it is less than numerator */ \
347 while (num >= den) { \
348 type q = 1; \
350 /* Find closest power of two */ \
351 while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
352 q <<= 1; \
354 /* Compute difference between current quotient and numerator */ \
355 num -= q * den; \
356 quot += q; \
358 ret.quot = quot; \
359 ret.rem = num; \
360 return ret; \
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; \
368 rettype ret; \
370 if (numerator >= 0) \
371 num = numerator; \
372 else \
373 num = 0 - numerator; \
374 if (denominator >= 0) \
375 den = denominator; \
376 else \
377 den = 0 - denominator; \
378 uxdiv_ret = aeabi_ ## uiname(num, den); \
379 /* signs differ */ \
380 if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \
381 ret.quot = 0 - uxdiv_ret.quot; \
382 else \
383 ret.quot = uxdiv_ret.quot; \
384 if (numerator < 0) \
385 ret.rem = 0 - uxdiv_ret.rem; \
386 else \
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;
415 if (shift >= 32) {
416 val.high = val.low;
417 val.low = 0;
418 shift -= 32;
420 if (shift > 0) {
421 ret.low = val.low << shift;
422 ret.high = (val.high << shift) | (val.low >> (32 - shift));
423 double_unsigned_struct_return(ret);
424 return;
426 double_unsigned_struct_return(val);
429 #define aeabi_lsr(val, shift, fill, type) \
430 type ## _struct ret; \
432 if (shift >= 32) { \
433 val.low = val.high; \
434 val.high = fill; \
435 shift -= 32; \
437 if (shift > 0) { \
438 ret.high = val.high >> shift; \
439 ret.low = (val.high << (32 - shift)) | (val.low >> shift); \
440 type ## _struct_return(ret); \
441 return; \
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)
462 unsigned num, den;
463 uidiv_t ret;
465 if (numerator >= 0)
466 num = numerator;
467 else
468 num = 0 - numerator;
469 if (denominator >= 0)
470 den = denominator;
471 else
472 den = 0 - denominator;
473 ret = aeabi_uidivmod(num, den);
474 if ((numerator & INT_MIN) != (denominator & INT_MIN)) /* signs differ */
475 ret.quot *= -1;
476 return ret.quot;
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));