Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6429 | siemargl | 1 | /* TCC ARM runtime EABI |
2 | Copyright (C) 2013 Thomas Preud'homme |
||
3 | |||
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: |
||
10 | |||
11 | The above copyright notice and this permission notice shall be included in |
||
12 | all copies or substantial portions of the software. |
||
13 | |||
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.*/ |
||
21 | |||
22 | #include |
||
23 | |||
24 | /* We rely on the little endianness and EABI calling convention for this to |
||
25 | work */ |
||
26 | |||
27 | typedef struct double_unsigned_struct { |
||
28 | unsigned low; |
||
29 | unsigned high; |
||
30 | } double_unsigned_struct; |
||
31 | |||
32 | typedef struct unsigned_int_struct { |
||
33 | unsigned low; |
||
34 | int high; |
||
35 | } unsigned_int_struct; |
||
36 | |||
37 | #define REGS_RETURN(name, type) \ |
||
38 | void name ## _return(type ret) {} |
||
39 | |||
40 | |||
41 | /* Float helper functions */ |
||
42 | |||
43 | #define FLOAT_EXP_BITS 8 |
||
44 | #define FLOAT_FRAC_BITS 23 |
||
45 | |||
46 | #define DOUBLE_EXP_BITS 11 |
||
47 | #define DOUBLE_FRAC_BITS 52 |
||
48 | |||
49 | #define ONE_EXP(type) ((1 << (type ## _EXP_BITS - 1)) - 1) |
||
50 | |||
51 | REGS_RETURN(unsigned_int_struct, unsigned_int_struct) |
||
52 | REGS_RETURN(double_unsigned_struct, double_unsigned_struct) |
||
53 | |||
54 | /* float -> integer: (sign) 1.fraction x 2^(exponent - exp_for_one) */ |
||
55 | |||
56 | |||
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; \ |
||
63 | \ |
||
64 | /* compute sign */ \ |
||
65 | sign = val >> 31; \ |
||
66 | \ |
||
67 | /* compute real exponent */ \ |
||
68 | exp = val >> FLOAT_FRAC_BITS; \ |
||
69 | exp &= (1 << FLOAT_EXP_BITS) - 1; \ |
||
70 | exp -= ONE_EXP(FLOAT); \ |
||
71 | \ |
||
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 | } \ |
||
80 | \ |
||
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 | } \ |
||
100 | \ |
||
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++; \ |
||
110 | } \ |
||
111 | \ |
||
112 | double_unsigned_struct_return(ret); \ |
||
113 | } |
||
114 | |||
115 | /* float to unsigned long long conversion */ |
||
116 | DEFINE__AEABI_F2XLZ(f2ulz, 0) |
||
117 | |||
118 | /* float to long long conversion */ |
||
119 | DEFINE__AEABI_F2XLZ(f2lz, 1) |
||
120 | |||
121 | /* double to [unsigned] long long conversion */ |
||
122 | #define DEFINE__AEABI_D2XLZ(name, with_sign) \ |
||
123 | void __aeabi_ ## name(double_unsigned_struct val) \ |
||
124 | { \ |
||
125 | int exp, high_shift, sign; \ |
||
126 | double_unsigned_struct ret; \ |
||
127 | \ |
||
128 | /* compute sign */ \ |
||
129 | sign = val.high >> 31; \ |
||
130 | \ |
||
131 | /* compute real exponent */ \ |
||
132 | exp = (val.high >> (DOUBLE_FRAC_BITS - 32)); \ |
||
133 | exp &= (1 << DOUBLE_EXP_BITS) - 1; \ |
||
134 | exp -= ONE_EXP(DOUBLE); \ |
||
135 | \ |
||
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; \ |
||
143 | } \ |
||
144 | \ |
||
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; \ |
||
158 | } \ |
||
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); \ |
||
168 | } \ |
||
169 | \ |
||
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++; \ |
||
179 | } \ |
||
180 | \ |
||
181 | double_unsigned_struct_return(ret); \ |
||
182 | } |
||
183 | |||
184 | /* double to unsigned long long conversion */ |
||
185 | DEFINE__AEABI_D2XLZ(d2ulz, 0) |
||
186 | |||
187 | /* double to long long conversion */ |
||
188 | DEFINE__AEABI_D2XLZ(d2lz, 1) |
||
189 | |||
190 | /* long long to float conversion */ |
||
191 | #define DEFINE__AEABI_XL2F(name, with_sign) \ |
||
192 | unsigned __aeabi_ ## name(unsigned long long v) \ |
||
193 | { \ |
||
194 | int s /* shift */, flb /* first lost bit */, sign = 0; \ |
||
195 | unsigned p = 0 /* power */, ret; \ |
||
196 | double_unsigned_struct val; \ |
||
197 | \ |
||
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; \ |
||
202 | } \ |
||
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; \ |
||
216 | } \ |
||
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; \ |
||
228 | } \ |
||
229 | } else \ |
||
230 | return 0; \ |
||
231 | } \ |
||
232 | if (flb) \ |
||
233 | ret++; \ |
||
234 | \ |
||
235 | /* fill exponent bits */ \ |
||
236 | ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \ |
||
237 | \ |
||
238 | /* fill sign bit */ \ |
||
239 | ret |= sign << 31; \ |
||
240 | \ |
||
241 | return ret; \ |
||
242 | } |
||
243 | |||
244 | /* unsigned long long to float conversion */ |
||
245 | DEFINE__AEABI_XL2F(ul2f, 0) |
||
246 | |||
247 | /* long long to float conversion */ |
||
248 | DEFINE__AEABI_XL2F(l2f, 1) |
||
249 | |||
250 | /* long long to double conversion */ |
||
251 | #define __AEABI_XL2D(name, with_sign) \ |
||
252 | void __aeabi_ ## name(unsigned long long v) \ |
||
253 | { \ |
||
254 | int s /* shift */, high_shift, sign = 0; \ |
||
255 | unsigned tmp, p = 0; \ |
||
256 | double_unsigned_struct val, ret; \ |
||
257 | \ |
||
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; \ |
||
262 | } \ |
||
263 | val.low = v; \ |
||
264 | val.high = v >> 32; \ |
||
265 | \ |
||
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++; \ |
||
286 | } \ |
||
287 | } \ |
||
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); \ |
||
301 | } \ |
||
302 | } else { \ |
||
303 | ret.high = ret.low = 0; \ |
||
304 | double_unsigned_struct_return(ret); \ |
||
305 | } \ |
||
306 | } \ |
||
307 | \ |
||
308 | /* fill exponent bits */ \ |
||
309 | ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32); \ |
||
310 | \ |
||
311 | /* fill sign bit */ \ |
||
312 | ret.high |= sign << 31; \ |
||
313 | \ |
||
314 | double_unsigned_struct_return(ret); \ |
||
315 | } |
||
316 | |||
317 | /* unsigned long long to double conversion */ |
||
318 | __AEABI_XL2D(ul2d, 0) |
||
319 | |||
320 | /* long long to double conversion */ |
||
321 | __AEABI_XL2D(l2d, 1) |
||
322 | |||
323 | |||
324 | /* Long long helper functions */ |
||
325 | |||
326 | /* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */ |
||
327 | |||
328 | #define define_aeabi_xdivmod_signed_type(basetype, type) \ |
||
329 | typedef struct type { \ |
||
330 | basetype quot; \ |
||
331 | unsigned basetype rem; \ |
||
332 | } type |
||
333 | |||
334 | #define define_aeabi_xdivmod_unsigned_type(basetype, type) \ |
||
335 | typedef struct type { \ |
||
336 | basetype quot; \ |
||
337 | basetype rem; \ |
||
338 | } type |
||
339 | |||
340 | #define AEABI_UXDIVMOD(name,type, rettype, typemacro) \ |
||
341 | static inline rettype aeabi_ ## name (type num, type den) \ |
||
342 | { \ |
||
343 | rettype ret; \ |
||
344 | type quot = 0; \ |
||
345 | \ |
||
346 | /* Increase quotient while it is less than numerator */ \ |
||
347 | while (num >= den) { \ |
||
348 | type q = 1; \ |
||
349 | \ |
||
350 | /* Find closest power of two */ \ |
||
351 | while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \ |
||
352 | q <<= 1; \ |
||
353 | \ |
||
354 | /* Compute difference between current quotient and numerator */ \ |
||
355 | num -= q * den; \ |
||
356 | quot += q; \ |
||
357 | } \ |
||
358 | ret.quot = quot; \ |
||
359 | ret.rem = num; \ |
||
360 | return ret; \ |
||
361 | } |
||
362 | |||
363 | #define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \ |
||
364 | void __aeabi_ ## name(type numerator, type denominator) \ |
||
365 | { \ |
||
366 | unsigned type num, den; \ |
||
367 | urettype uxdiv_ret; \ |
||
368 | rettype ret; \ |
||
369 | \ |
||
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; \ |
||
388 | \ |
||
389 | rettype ## _return(ret); \ |
||
390 | } |
||
391 | |||
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); |
||
396 | |||
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) |
||
401 | |||
402 | AEABI_UXDIVMOD(uldivmod, unsigned long long, ulldiv_t, ULONG) |
||
403 | |||
404 | __AEABI_XDIVMOD(ldivmod, long long, uldivmod, lldiv_t, ulldiv_t, LLONG) |
||
405 | |||
406 | void __aeabi_uldivmod(unsigned long long num, unsigned long long den) |
||
407 | { |
||
408 | ulldiv_t_return(aeabi_uldivmod(num, den)); |
||
409 | } |
||
410 | |||
411 | void __aeabi_llsl(double_unsigned_struct val, int shift) |
||
412 | { |
||
413 | double_unsigned_struct ret; |
||
414 | |||
415 | if (shift >= 32) { |
||
416 | val.high = val.low; |
||
417 | val.low = 0; |
||
418 | shift -= 32; |
||
419 | } |
||
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; |
||
425 | } |
||
426 | double_unsigned_struct_return(val); |
||
427 | } |
||
428 | |||
429 | #define aeabi_lsr(val, shift, fill, type) \ |
||
430 | type ## _struct ret; \ |
||
431 | \ |
||
432 | if (shift >= 32) { \ |
||
433 | val.low = val.high; \ |
||
434 | val.high = fill; \ |
||
435 | shift -= 32; \ |
||
436 | } \ |
||
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; \ |
||
442 | } \ |
||
443 | type ## _struct_return(val); |
||
444 | |||
445 | void __aeabi_llsr(double_unsigned_struct val, int shift) |
||
446 | { |
||
447 | aeabi_lsr(val, shift, 0, double_unsigned); |
||
448 | } |
||
449 | |||
450 | void __aeabi_lasr(unsigned_int_struct val, int shift) |
||
451 | { |
||
452 | aeabi_lsr(val, shift, val.high >> 31, unsigned_int); |
||
453 | } |
||
454 | |||
455 | |||
456 | /* Integer division functions */ |
||
457 | |||
458 | AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT) |
||
459 | |||
460 | int __aeabi_idiv(int numerator, int denominator) |
||
461 | { |
||
462 | unsigned num, den; |
||
463 | uidiv_t ret; |
||
464 | |||
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; |
||
477 | } |
||
478 | |||
479 | unsigned __aeabi_uidiv(unsigned num, unsigned den) |
||
480 | { |
||
481 | return aeabi_uidivmod(num, den).quot; |
||
482 | } |
||
483 | |||
484 | __AEABI_XDIVMOD(idivmod, int, uidivmod, idiv_t, uidiv_t, INT) |
||
485 | |||
486 | void __aeabi_uidivmod(unsigned num, unsigned den) |
||
487 | { |
||
488 | uidiv_t_return(aeabi_uidivmod(num, den)); |
||
489 | }><>><>><>>=><=>=>=>><>><>><>><>><>=>><>><>><>><>>><>><>><>><>=><=>=>><>=><=>>><>><>><>><>><>><>><>><>><>>><>><>><>><>><>><>><>>><>><> |