3 /* We rely on the little endianness and EABI calling convention for this to
6 typedef struct double_unsigned_struct
{
9 } double_unsigned_struct
;
11 typedef struct unsigned_int_struct
{
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__AEABIT_F2XLZ(name, with_sign) \
38 void __aeabi_ ## name(unsigned val) \
40 int exp, high_shift, sign; \
41 double_unsigned_struct ret; \
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 */ \
53 if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
56 if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
60 val &= (1 << FLOAT_FRAC_BITS) - 1; \
62 ret.high = 1 << (exp - 32); \
63 if (exp - 32 >= FLOAT_FRAC_BITS) { \
64 ret.high |= val << (exp - 32 - FLOAT_FRAC_BITS); \
67 high_shift = FLOAT_FRAC_BITS - (exp - 32); \
68 ret.high |= val >> high_shift; \
69 ret.low = val << (32 - high_shift); \
74 if (exp > FLOAT_FRAC_BITS) \
75 ret.low |= val << (exp - FLOAT_FRAC_BITS); \
77 ret.low = val >> (FLOAT_FRAC_BITS - exp); \
80 /* encode negative integer using 2's complement */ \
81 if (with_sign && sign) { \
83 ret.high = ~ret.high; \
84 if (ret.low == UINT_MAX) { \
91 double_unsigned_struct_return(ret); \
94 /* float to unsigned long long conversion */
95 DEFINE__AEABIT_F2XLZ(f2ulz
, 0)
97 /* float to long long conversion */
98 DEFINE__AEABIT_F2XLZ(f2lz
, 1)
100 /* double to [unsigned] long long conversion */
101 #define DEFINE__AEABIT_D2XLZ(name, with_sign) \
102 void __aeabi_ ## name(double_unsigned_struct val) \
104 int exp, high_shift, sign; \
105 double_unsigned_struct ret; \
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 */ \
117 if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
120 if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
124 val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1; \
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; \
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; \
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); \
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) { \
160 double_unsigned_struct_return(ret); \
163 /* double to unsigned long long conversion */
164 DEFINE__AEABIT_D2XLZ(d2ulz
, 0)
166 /* double to long long conversion */
167 DEFINE__AEABIT_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 */, 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 & (1 << 63))) { \
183 val.high = v >> 32; \
184 /* fill fraction bits */ \
185 for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
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)); \
192 ret >>= s - FLOAT_FRAC_BITS; \
195 for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
197 ret = val.low & (p - 1); \
198 if (s <= FLOAT_FRAC_BITS) \
199 ret <<= FLOAT_FRAC_BITS - s; \
201 ret >>= s - FLOAT_FRAC_BITS; \
206 /* fill exponent bits */ \
207 ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \
209 /* fill sign bit */ \
215 /* unsigned long long to float conversion */
216 DEFINE__AEABI_XL2F(ul2f
, 0)
218 /* long long to float conversion */
219 DEFINE__AEABI_XL2F(l2f
, 0)
221 /* long long to double conversion */
222 #define __AEABI_XL2D(name, with_sign) \
223 void __aeabi_ ## name(unsigned long long v) \
225 int s, high_shift, sign = 0; \
226 unsigned tmp, p = 0; \
227 double_unsigned_struct val, ret; \
229 /* fraction in negative float is encoded in 1's complement */ \
230 if (with_sign && (v & (1ULL << 63))) { \
235 val.high = v >> 32; \
237 /* fill fraction bits */ \
238 for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
240 tmp = val.high & (p - 1); \
241 if (s < DOUBLE_FRAC_BITS - 32) { \
242 high_shift = DOUBLE_FRAC_BITS - 32 - s; \
243 ret.high = tmp << high_shift; \
244 ret.high |= val.low >> (32 - high_shift); \
245 ret.low = val.low << high_shift; \
247 high_shift = s - (DOUBLE_FRAC_BITS - 32); \
248 ret.high = tmp >> high_shift; \
249 ret.low = tmp << (32 - high_shift); \
250 ret.low |= val.low >> high_shift; \
254 for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
256 tmp = val.low & (p - 1); \
257 if (s <= DOUBLE_FRAC_BITS - 32) { \
258 high_shift = DOUBLE_FRAC_BITS - 32 - s; \
259 ret.high = tmp << high_shift; \
262 high_shift = s - (DOUBLE_FRAC_BITS - 32); \
263 ret.high = tmp >> high_shift; \
264 ret.low = tmp << (32 - high_shift); \
267 ret.high = ret.low = 0; \
268 double_unsigned_struct_return(ret); \
272 /* fill exponent bits */ \
273 ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32); \
275 /* fill sign bit */ \
276 ret.high |= sign << 31; \
278 double_unsigned_struct_return(ret); \
281 /* unsigned long long to double conversion */
282 __AEABI_XL2D(ul2d
, 0)
284 /* long long to double conversion */
288 /* Long long helper functions */
290 /* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */
292 #define define_aeabi_xdivmod_signed_type(basetype, type) \
293 typedef struct type { \
295 unsigned basetype rem; \
298 #define define_aeabi_xdivmod_unsigned_type(basetype, type) \
299 typedef struct type { \
304 #define AEABI_UXDIVMOD(name,type, rettype, typemacro) \
305 static inline rettype aeabi_ ## name (type num, type den) \
310 /* Increase quotient while it is less than numerator */ \
311 while (num >= den) { \
314 /* Find closest power of two */ \
315 while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
318 /* Compute difference between current quotient and numerator */ \
327 #define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \
328 void __aeabi_ ## name(type numerator, type denominator) \
330 unsigned type num, den; \
331 urettype uxdiv_ret; \
334 if (numerator >= 0) \
337 num = 0 - numerator; \
338 if (denominator >= 0) \
341 den = 0 - denominator; \
342 uxdiv_ret = aeabi_ ## uiname(num, den); \
344 if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \
345 ret.quot = 0 - uxdiv_ret.quot; \
347 ret.quot = uxdiv_ret.quot; \
349 ret.rem = 0 - uxdiv_ret.rem; \
351 ret.rem = uxdiv_ret.rem; \
353 rettype ## _return(ret); \
356 define_aeabi_xdivmod_signed_type(long long, lldiv_t
);
357 define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t
);
358 define_aeabi_xdivmod_signed_type(int, idiv_t
);
359 define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t
);
361 REGS_RETURN(lldiv_t
, lldiv_t
)
362 REGS_RETURN(ulldiv_t
, ulldiv_t
)
363 REGS_RETURN(idiv_t
, idiv_t
)
364 REGS_RETURN(uidiv_t
, uidiv_t
)
366 AEABI_UXDIVMOD(uldivmod
, unsigned long long, ulldiv_t
, ULONG
)
368 __AEABI_XDIVMOD(ldivmod
, long long, uldivmod
, lldiv_t
, ulldiv_t
, LLONG
)
370 void __aeabi_uldivmod(unsigned long long num
, unsigned long long den
)
372 ulldiv_t_return(aeabi_uldivmod(num
, den
));
375 void __aeabi_llsl(double_unsigned_struct val
, int shift
)
377 double_unsigned_struct ret
;
385 ret
.low
= val
.low
<< shift
;
386 ret
.high
= (val
.high
<< shift
) | (val
.low
>> (32 - shift
));
387 double_unsigned_struct_return(ret
);
390 double_unsigned_struct_return(val
);
393 #define aeabi_lsr(val, shift, fill, type) \
394 type ## _struct ret; \
397 val.low = val.high; \
402 ret.high = val.high >> shift; \
403 ret.low = (val.high << (32 - shift)) | (val.low >> shift); \
404 type ## _struct_return(ret); \
407 type ## _struct_return(val);
409 void __aeabi_llsr(double_unsigned_struct val
, int shift
)
411 aeabi_lsr(val
, shift
, 0, double_unsigned
);
414 void __aeabi_lasr(unsigned_int_struct val
, int shift
)
416 aeabi_lsr(val
, shift
, val
.high
>> 31, unsigned_int
);
420 /* Integer division functions */
422 AEABI_UXDIVMOD(uidivmod
, unsigned, uidiv_t
, UINT
)
424 int __aeabi_idiv(int numerator
, int denominator
)
433 if (denominator
>= 0)
436 den
= 0 - denominator
;
437 ret
= aeabi_uidivmod(num
, den
);
438 if ((numerator
& INT_MIN
) != (denominator
& INT_MIN
)) /* signs differ */
443 unsigned __aeabi_uidiv(unsigned num
, unsigned den
)
445 return aeabi_uidivmod(num
, den
).quot
;
448 __AEABI_XDIVMOD(idivmod
, int, uidivmod
, idiv_t
, uidiv_t
, INT
)
450 void __aeabi_uidivmod(unsigned num
, unsigned den
)
452 uidiv_t_return(aeabi_uidivmod(num
, den
));