Create bcheck region for argv and arge argument
[tinycc.git] / lib / armeabi.c
blobce5e232b66c62e6cae6a5d82c067d0bd0ea462b3
1 #include <limits.h>
3 /* We rely on the little endianness and EABI calling convention for this to
4 work */
6 typedef struct double_unsigned_struct {
7 unsigned low;
8 unsigned high;
9 } double_unsigned_struct;
11 typedef struct unsigned_int_struct {
12 unsigned low;
13 int high;
14 } unsigned_int_struct;
16 #define REGS_RETURN(name, type) \
17 void name ## _return(type ret) {}
20 /* Float helper functions */
22 #define FLOAT_EXP_BITS 8
23 #define FLOAT_FRAC_BITS 23
25 #define DOUBLE_EXP_BITS 11
26 #define DOUBLE_FRAC_BITS 52
28 #define ONE_EXP(type) ((1 << (type ## _EXP_BITS - 1)) - 1)
30 REGS_RETURN(unsigned_int_struct, unsigned_int_struct)
31 REGS_RETURN(double_unsigned_struct, double_unsigned_struct)
33 /* float -> integer: (sign) 1.fraction x 2^(exponent - exp_for_one) */
36 /* float to [unsigned] long long conversion */
37 #define DEFINE__AEABI_F2XLZ(name, with_sign) \
38 void __aeabi_ ## name(unsigned val) \
39 { \
40 int exp, high_shift, sign; \
41 double_unsigned_struct ret; \
43 /* compute sign */ \
44 sign = val >> 31; \
46 /* compute real exponent */ \
47 exp = val >> FLOAT_FRAC_BITS; \
48 exp &= (1 << FLOAT_EXP_BITS) - 1; \
49 exp -= ONE_EXP(FLOAT); \
51 /* undefined behavior if truncated value cannot be represented */ \
52 if (with_sign) { \
53 if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
54 return; \
55 } else { \
56 if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
57 return; \
58 } \
60 val &= (1 << FLOAT_FRAC_BITS) - 1; \
61 if (exp >= 32) { \
62 ret.high = 1 << (exp - 32); \
63 if (exp - 32 >= FLOAT_FRAC_BITS) { \
64 ret.high |= val << (exp - 32 - FLOAT_FRAC_BITS); \
65 ret.low = 0; \
66 } else { \
67 high_shift = FLOAT_FRAC_BITS - (exp - 32); \
68 ret.high |= val >> high_shift; \
69 ret.low = val << (32 - high_shift); \
70 } \
71 } else { \
72 ret.high = 0; \
73 ret.low = 1 << exp; \
74 if (exp > FLOAT_FRAC_BITS) \
75 ret.low |= val << (exp - FLOAT_FRAC_BITS); \
76 else \
77 ret.low |= val >> (FLOAT_FRAC_BITS - exp); \
78 } \
80 /* encode negative integer using 2's complement */ \
81 if (with_sign && sign) { \
82 ret.low = ~ret.low; \
83 ret.high = ~ret.high; \
84 if (ret.low == UINT_MAX) { \
85 ret.low = 0; \
86 ret.high++; \
87 } else \
88 ret.low++; \
89 } \
91 double_unsigned_struct_return(ret); \
94 /* float to unsigned long long conversion */
95 DEFINE__AEABI_F2XLZ(f2ulz, 0)
97 /* float to long long conversion */
98 DEFINE__AEABI_F2XLZ(f2lz, 1)
100 /* double to [unsigned] long long conversion */
101 #define DEFINE__AEABI_D2XLZ(name, with_sign) \
102 void __aeabi_ ## name(double_unsigned_struct val) \
104 int exp, high_shift, sign; \
105 double_unsigned_struct ret; \
107 /* compute sign */ \
108 sign = val.high >> 31; \
110 /* compute real exponent */ \
111 exp = (val.high >> (DOUBLE_FRAC_BITS - 32)); \
112 exp &= (1 << DOUBLE_EXP_BITS) - 1; \
113 exp -= ONE_EXP(DOUBLE); \
115 /* undefined behavior if truncated value cannot be represented */ \
116 if (with_sign) { \
117 if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
118 return; \
119 } else { \
120 if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
121 return; \
124 val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1; \
125 if (exp >= 32) { \
126 ret.high = 1 << (exp - 32); \
127 if (exp >= DOUBLE_FRAC_BITS) { \
128 high_shift = exp - DOUBLE_FRAC_BITS; \
129 ret.high |= val.high << high_shift; \
130 ret.high |= val.low >> (32 - high_shift); \
131 ret.low = val.low << high_shift; \
132 } else { \
133 high_shift = DOUBLE_FRAC_BITS - exp; \
134 ret.high |= val.high >> high_shift; \
135 ret.low = val.high << (32 - high_shift); \
136 ret.low |= val.low >> high_shift; \
138 } else { \
139 ret.high = 0; \
140 ret.low = 1 << exp; \
141 if (exp > DOUBLE_FRAC_BITS - 32) { \
142 high_shift = exp - DOUBLE_FRAC_BITS - 32; \
143 ret.low |= val.high << high_shift; \
144 ret.low |= val.low >> (32 - high_shift); \
145 } else \
146 ret.low |= val.high >> (DOUBLE_FRAC_BITS - 32 - exp); \
149 /* encode negative integer using 2's complement */ \
150 if (with_sign && sign) { \
151 ret.low = ~ret.low; \
152 ret.high = ~ret.high; \
153 if (ret.low == UINT_MAX) { \
154 ret.low = 0; \
155 ret.high++; \
156 } else \
157 ret.low++; \
160 double_unsigned_struct_return(ret); \
163 /* double to unsigned long long conversion */
164 DEFINE__AEABI_D2XLZ(d2ulz, 0)
166 /* double to long long conversion */
167 DEFINE__AEABI_D2XLZ(d2lz, 1)
169 /* long long to float conversion */
170 #define DEFINE__AEABI_XL2F(name, with_sign) \
171 unsigned __aeabi_ ## name(unsigned long long v) \
173 int s /* shift */, flb /* first lost bit */, sign = 0; \
174 unsigned p = 0 /* power */, ret; \
175 double_unsigned_struct val; \
177 /* fraction in negative float is encoded in 1's complement */ \
178 if (with_sign && (v & (1ULL << 63))) { \
179 sign = 1; \
180 v = ~v + 1; \
182 val.low = v; \
183 val.high = v >> 32; \
184 /* fill fraction bits */ \
185 for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
186 if (p) { \
187 ret = val.high & (p - 1); \
188 if (s < FLOAT_FRAC_BITS) { \
189 ret <<= FLOAT_FRAC_BITS - s; \
190 ret |= val.low >> (32 - (FLOAT_FRAC_BITS - s)); \
191 flb = (val.low >> (32 - (FLOAT_FRAC_BITS - s - 1))) & 1; \
192 } else { \
193 flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
194 ret >>= s - FLOAT_FRAC_BITS; \
196 s += 32; \
197 } else { \
198 for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
199 if (p) { \
200 ret = val.low & (p - 1); \
201 if (s <= FLOAT_FRAC_BITS) { \
202 ret <<= FLOAT_FRAC_BITS - s; \
203 flb = 0; \
204 } else { \
205 flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
206 ret >>= s - FLOAT_FRAC_BITS; \
208 } else \
209 return 0; \
211 if (flb) \
212 ret++; \
214 /* fill exponent bits */ \
215 ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \
217 /* fill sign bit */ \
218 ret |= sign << 31; \
220 return ret; \
223 /* unsigned long long to float conversion */
224 DEFINE__AEABI_XL2F(ul2f, 0)
226 /* long long to float conversion */
227 DEFINE__AEABI_XL2F(l2f, 1)
229 /* long long to double conversion */
230 #define __AEABI_XL2D(name, with_sign) \
231 void __aeabi_ ## name(unsigned long long v) \
233 int s /* shift */, high_shift, sign = 0; \
234 unsigned tmp, p = 0; \
235 double_unsigned_struct val, ret; \
237 /* fraction in negative float is encoded in 1's complement */ \
238 if (with_sign && (v & (1ULL << 63))) { \
239 sign = 1; \
240 v = ~v + 1; \
242 val.low = v; \
243 val.high = v >> 32; \
245 /* fill fraction bits */ \
246 for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
247 if (p) { \
248 tmp = val.high & (p - 1); \
249 if (s < DOUBLE_FRAC_BITS - 32) { \
250 high_shift = DOUBLE_FRAC_BITS - 32 - s; \
251 ret.high = tmp << high_shift; \
252 ret.high |= val.low >> (32 - high_shift); \
253 ret.low = val.low << high_shift; \
254 } else { \
255 high_shift = s - (DOUBLE_FRAC_BITS - 32); \
256 ret.high = tmp >> high_shift; \
257 ret.low = tmp << (32 - high_shift); \
258 ret.low |= val.low >> high_shift; \
259 if ((val.low >> (high_shift - 1)) & 1) { \
260 if (ret.low == UINT_MAX) { \
261 ret.high++; \
262 ret.low = 0; \
263 } else \
264 ret.low++; \
267 s += 32; \
268 } else { \
269 for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
270 if (p) { \
271 tmp = val.low & (p - 1); \
272 if (s <= DOUBLE_FRAC_BITS - 32) { \
273 high_shift = DOUBLE_FRAC_BITS - 32 - s; \
274 ret.high = tmp << high_shift; \
275 ret.low = 0; \
276 } else { \
277 high_shift = s - (DOUBLE_FRAC_BITS - 32); \
278 ret.high = tmp >> high_shift; \
279 ret.low = tmp << (32 - high_shift); \
281 } else { \
282 ret.high = ret.low = 0; \
283 double_unsigned_struct_return(ret); \
287 /* fill exponent bits */ \
288 ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32); \
290 /* fill sign bit */ \
291 ret.high |= sign << 31; \
293 double_unsigned_struct_return(ret); \
296 /* unsigned long long to double conversion */
297 __AEABI_XL2D(ul2d, 0)
299 /* long long to double conversion */
300 __AEABI_XL2D(l2d, 1)
303 /* Long long helper functions */
305 /* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */
307 #define define_aeabi_xdivmod_signed_type(basetype, type) \
308 typedef struct type { \
309 basetype quot; \
310 unsigned basetype rem; \
311 } type
313 #define define_aeabi_xdivmod_unsigned_type(basetype, type) \
314 typedef struct type { \
315 basetype quot; \
316 basetype rem; \
317 } type
319 #define AEABI_UXDIVMOD(name,type, rettype, typemacro) \
320 static inline rettype aeabi_ ## name (type num, type den) \
322 rettype ret; \
323 type quot = 0; \
325 /* Increase quotient while it is less than numerator */ \
326 while (num >= den) { \
327 type q = 1; \
329 /* Find closest power of two */ \
330 while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
331 q <<= 1; \
333 /* Compute difference between current quotient and numerator */ \
334 num -= q * den; \
335 quot += q; \
337 ret.quot = quot; \
338 ret.rem = num; \
339 return ret; \
342 #define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \
343 void __aeabi_ ## name(type numerator, type denominator) \
345 unsigned type num, den; \
346 urettype uxdiv_ret; \
347 rettype ret; \
349 if (numerator >= 0) \
350 num = numerator; \
351 else \
352 num = 0 - numerator; \
353 if (denominator >= 0) \
354 den = denominator; \
355 else \
356 den = 0 - denominator; \
357 uxdiv_ret = aeabi_ ## uiname(num, den); \
358 /* signs differ */ \
359 if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \
360 ret.quot = 0 - uxdiv_ret.quot; \
361 else \
362 ret.quot = uxdiv_ret.quot; \
363 if (numerator < 0) \
364 ret.rem = 0 - uxdiv_ret.rem; \
365 else \
366 ret.rem = uxdiv_ret.rem; \
368 rettype ## _return(ret); \
371 define_aeabi_xdivmod_signed_type(long long, lldiv_t);
372 define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t);
373 define_aeabi_xdivmod_signed_type(int, idiv_t);
374 define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t);
376 REGS_RETURN(lldiv_t, lldiv_t)
377 REGS_RETURN(ulldiv_t, ulldiv_t)
378 REGS_RETURN(idiv_t, idiv_t)
379 REGS_RETURN(uidiv_t, uidiv_t)
381 AEABI_UXDIVMOD(uldivmod, unsigned long long, ulldiv_t, ULONG)
383 __AEABI_XDIVMOD(ldivmod, long long, uldivmod, lldiv_t, ulldiv_t, LLONG)
385 void __aeabi_uldivmod(unsigned long long num, unsigned long long den)
387 ulldiv_t_return(aeabi_uldivmod(num, den));
390 void __aeabi_llsl(double_unsigned_struct val, int shift)
392 double_unsigned_struct ret;
394 if (shift >= 32) {
395 val.high = val.low;
396 val.low = 0;
397 shift -= 32;
399 if (shift > 0) {
400 ret.low = val.low << shift;
401 ret.high = (val.high << shift) | (val.low >> (32 - shift));
402 double_unsigned_struct_return(ret);
403 return;
405 double_unsigned_struct_return(val);
408 #define aeabi_lsr(val, shift, fill, type) \
409 type ## _struct ret; \
411 if (shift >= 32) { \
412 val.low = val.high; \
413 val.high = fill; \
414 shift -= 32; \
416 if (shift > 0) { \
417 ret.high = val.high >> shift; \
418 ret.low = (val.high << (32 - shift)) | (val.low >> shift); \
419 type ## _struct_return(ret); \
420 return; \
422 type ## _struct_return(val);
424 void __aeabi_llsr(double_unsigned_struct val, int shift)
426 aeabi_lsr(val, shift, 0, double_unsigned);
429 void __aeabi_lasr(unsigned_int_struct val, int shift)
431 aeabi_lsr(val, shift, val.high >> 31, unsigned_int);
435 /* Integer division functions */
437 AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT)
439 int __aeabi_idiv(int numerator, int denominator)
441 unsigned num, den;
442 uidiv_t ret;
444 if (numerator >= 0)
445 num = numerator;
446 else
447 num = 0 - numerator;
448 if (denominator >= 0)
449 den = denominator;
450 else
451 den = 0 - denominator;
452 ret = aeabi_uidivmod(num, den);
453 if ((numerator & INT_MIN) != (denominator & INT_MIN)) /* signs differ */
454 ret.quot *= -1;
455 return ret.quot;
458 unsigned __aeabi_uidiv(unsigned num, unsigned den)
460 return aeabi_uidivmod(num, den).quot;
463 __AEABI_XDIVMOD(idivmod, int, uidivmod, idiv_t, uidiv_t, INT)
465 void __aeabi_uidivmod(unsigned num, unsigned den)
467 uidiv_t_return(aeabi_uidivmod(num, den));