| @@ -0,0 +1,441 @@ |
| | 1 | #include<limits.h> |
| | 2 | |
| | 3 | /* We rely on the little endianness and EABI calling convention for this to |
| | 4 | work */ |
| | 5 | |
| | 6 | typedef struct double_unsigned_struct { |
| | 7 | unsigned low; |
| | 8 | unsigned high; |
| | 9 | } double_unsigned_struct; |
| | 10 | |
| | 11 | typedef struct unsigned_int_struct { |
| | 12 | unsigned low; |
| | 13 | int high; |
| | 14 | } unsigned_int_struct; |
| | 15 | |
| | 16 | #define REGS_RETURN(name, type) \ |
| | 17 | void name ## _return(type ret) {} |
| | 18 | |
| | 19 | |
| | 20 | /* Float helper functions */ |
| | 21 | |
| | 22 | #define FLOAT_EXP_BITS 8 |
| | 23 | #define FLOAT_FRAC_BITS 23 |
| | 24 | |
| | 25 | #define DOUBLE_EXP_BITS 11 |
| | 26 | #define DOUBLE_FRAC_BITS 52 |
| | 27 | |
| | 28 | #define ONE_EXP(type) ((1 << (type ## _EXP_BITS - 1)) - 1) |
| | 29 | |
| | 30 | REGS_RETURN(unsigned_int_struct, unsigned_int_struct) |
| | 31 | REGS_RETURN(double_unsigned_struct, double_unsigned_struct) |
| | 32 | |
| | 33 | /* float -> integer: (sign) 1.fraction x 2^(exponent - exp_for_one) */ |
| | 34 | |
| | 35 | |
| | 36 | /* float to [unsigned] long long conversion */ |
| | 37 | #define DEFINE__AEABIT_F2XLZ(name, with_sign) \ |
| | 38 | void __aeabi_ ## name(unsigned val) \ |
| | 39 | { \ |
| | 40 | int exp, high_shift, sign; \ |
| | 41 | double_unsigned_struct ret; \ |
| | 42 | \ |
| | 43 | /* compute sign */ \ |
| | 44 | sign = val >> 31; \ |
| | 45 | \ |
| | 46 | /* compute real exponent */ \ |
| | 47 | exp = val >> FLOAT_FRAC_BITS; \ |
| | 48 | exp &= (1 << FLOAT_EXP_BITS) - 1; \ |
| | 49 | exp -= ONE_EXP(FLOAT); \ |
| | 50 | \ |
| | 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 | } \ |
| | 59 | \ |
| | 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 | } \ |
| | 79 | \ |
| | 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 | } \ |
| | 90 | \ |
| | 91 | double_unsigned_struct_return(ret); \ |
| | 92 | } |
| | 93 | |
| | 94 | /* float to unsigned long long conversion */ |
| | 95 | DEFINE__AEABIT_F2XLZ(f2ulz, 0) |
| | 96 | |
| | 97 | /* float to long long conversion */ |
| | 98 | DEFINE__AEABIT_F2XLZ(f2lz, 1) |
| | 99 | |
| | 100 | /* double to [unsigned] long long conversion */ |
| | 101 | #define DEFINE__AEABIT_D2XLZ(name, with_sign) \ |
| | 102 | void __aeabi_ ## name(double_unsigned_struct val) \ |
| | 103 | { \ |
| | 104 | int exp, high_shift, sign; \ |
| | 105 | double_unsigned_struct ret; \ |
| | 106 | \ |
| | 107 | /* compute sign */ \ |
| | 108 | sign = val.high >> 31; \ |
| | 109 | \ |
| | 110 | /* compute real exponent */ \ |
| | 111 | exp = (val.high >> (DOUBLE_FRAC_BITS - 32)); \ |
| | 112 | exp &= (1 << DOUBLE_EXP_BITS) - 1; \ |
| | 113 | exp -= ONE_EXP(DOUBLE); \ |
| | 114 | \ |
| | 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; \ |
| | 122 | } \ |
| | 123 | \ |
| | 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; \ |
| | 137 | } \ |
| | 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); \ |
| | 147 | } \ |
| | 148 | \ |
| | 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++; \ |
| | 158 | } \ |
| | 159 | \ |
| | 160 | double_unsigned_struct_return(ret); \ |
| | 161 | } |
| | 162 | |
| | 163 | /* double to unsigned long long conversion */ |
| | 164 | DEFINE__AEABIT_D2XLZ(d2ulz, 0) |
| | 165 | |
| | 166 | /* double to long long conversion */ |
| | 167 | DEFINE__AEABIT_D2XLZ(d2lz, 1) |
| | 168 | |
| | 169 | /* long long to float conversion */ |
| | 170 | #define DEFINE__AEABI_XL2F(name, with_sign) \ |
| | 171 | unsigned __aeabi_ ## name(unsigned long long v) \ |
| | 172 | { \ |
| | 173 | int s /* shift */, sign = 0; \ |
| | 174 | unsigned p = 0 /* power */, ret; \ |
| | 175 | double_unsigned_struct val; \ |
| | 176 | \ |
| | 177 | /* fraction in negative float is encoded in 1's complement */ \ |
| | 178 | if (with_sign && (v & (1 << 63))) { \ |
| | 179 | sign = 1; \ |
| | 180 | v = ~v + 1; \ |
| | 181 | } \ |
| | 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 | } else \ |
| | 192 | ret >>= s - FLOAT_FRAC_BITS; \ |
| | 193 | s += 32; \ |
| | 194 | } else { \ |
| | 195 | for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \ |
| | 196 | if (p) { \ |
| | 197 | ret = val.low & (p - 1); \ |
| | 198 | if (s <= FLOAT_FRAC_BITS) \ |
| | 199 | ret <<= FLOAT_FRAC_BITS - s; \ |
| | 200 | else \ |
| | 201 | ret >>= s - FLOAT_FRAC_BITS; \ |
| | 202 | } else \ |
| | 203 | return 0; \ |
| | 204 | } \ |
| | 205 | \ |
| | 206 | /* fill exponent bits */ \ |
| | 207 | ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \ |
| | 208 | \ |
| | 209 | /* fill sign bit */ \ |
| | 210 | ret |= sign << 31; \ |
| | 211 | \ |
| | 212 | return ret; \ |
| | 213 | } |
| | 214 | |
| | 215 | /* unsigned long long to float conversion */ |
| | 216 | DEFINE__AEABI_XL2F(ul2f, 0) |
| | 217 | |
| | 218 | /* long long to float conversion */ |
| | 219 | DEFINE__AEABI_XL2F(l2f, 0) |
| | 220 | |
| | 221 | /* long long to double conversion */ |
| | 222 | #define __AEABI_XL2D(name, with_sign) \ |
| | 223 | void __aeabi_ ## name(unsigned long long v) \ |
| | 224 | { \ |
| | 225 | int s, high_shift, sign = 0; \ |
| | 226 | unsigned tmp, p = 0; \ |
| | 227 | double_unsigned_struct val, ret; \ |
| | 228 | \ |
| | 229 | /* fraction in negative float is encoded in 1's complement */ \ |
| | 230 | if (with_sign && (v & (1ULL << 63))) { \ |
| | 231 | sign = 1; \ |
| | 232 | v = ~v + 1; \ |
| | 233 | } \ |
| | 234 | val.low = v; \ |
| | 235 | val.high = v >> 32; \ |
| | 236 | \ |
| | 237 | /* fill fraction bits */ \ |
| | 238 | for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \ |
| | 239 | if (p) { \ |
| | 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; \ |
| | 246 | } else { \ |
| | 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; \ |
| | 251 | } \ |
| | 252 | s += 32; \ |
| | 253 | } else { \ |
| | 254 | for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \ |
| | 255 | if (p) { \ |
| | 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; \ |
| | 260 | ret.low = 0; \ |
| | 261 | } else { \ |
| | 262 | high_shift = s - (DOUBLE_FRAC_BITS - 32); \ |
| | 263 | ret.high = tmp >> high_shift; \ |
| | 264 | ret.low = tmp << (32 - high_shift); \ |
| | 265 | } \ |
| | 266 | } else { \ |
| | 267 | ret.high = ret.low = 0; \ |
| | 268 | double_unsigned_struct_return(ret); \ |
| | 269 | } \ |
| | 270 | } \ |
| | 271 | \ |
| | 272 | /* fill exponent bits */ \ |
| | 273 | ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32); \ |
| | 274 | \ |
| | 275 | /* fill sign bit */ \ |
| | 276 | ret.high |= sign << 31; \ |
| | 277 | \ |
| | 278 | double_unsigned_struct_return(ret); \ |
| | 279 | } |
| | 280 | |
| | 281 | /* unsigned long long to double conversion */ |
| | 282 | __AEABI_XL2D(ul2d, 0) |
| | 283 | |
| | 284 | /* long long to double conversion */ |
| | 285 | __AEABI_XL2D(l2d, 1) |
| | 286 | |
| | 287 | |
| | 288 | /* Long long helper functions */ |
| | 289 | |
| | 290 | /* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */ |
| | 291 | |
| | 292 | #define define_aeabi_xdivmod_signed_type(basetype, type) \ |
| | 293 | typedef struct type { \ |
| | 294 | basetype quot; \ |
| | 295 | unsigned basetype rem; \ |
| | 296 | } type |
| | 297 | |
| | 298 | #define define_aeabi_xdivmod_unsigned_type(basetype, type) \ |
| | 299 | typedef struct type { \ |
| | 300 | basetype quot; \ |
| | 301 | basetype rem; \ |
| | 302 | } type |
| | 303 | |
| | 304 | #define AEABI_UXDIVMOD(name,type, rettype, typemacro) \ |
| | 305 | static inline rettype aeabi_ ## name (type num, type den) \ |
| | 306 | { \ |
| | 307 | rettype ret; \ |
| | 308 | type quot = 0; \ |
| | 309 | \ |
| | 310 | /* Increase quotient while it is less than numerator */ \ |
| | 311 | while (num >= den) { \ |
| | 312 | type q = 1; \ |
| | 313 | \ |
| | 314 | /* Find closest power of two */ \ |
| | 315 | while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \ |
| | 316 | q <<= 1; \ |
| | 317 | \ |
| | 318 | /* Compute difference between current quotient and numerator */ \ |
| | 319 | num -= q * den; \ |
| | 320 | quot += q; \ |
| | 321 | } \ |
| | 322 | ret.quot = quot; \ |
| | 323 | ret.rem = num; \ |
| | 324 | return ret; \ |
| | 325 | } |
| | 326 | |
| | 327 | #define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \ |
| | 328 | void __aeabi_ ## name(type numerator, type denominator) \ |
| | 329 | { \ |
| | 330 | unsigned type num, den; \ |
| | 331 | urettype uxdiv_ret; \ |
| | 332 | rettype ret; \ |
| | 333 | \ |
| | 334 | num = numerator & typemacro ## _MAX; \ |
| | 335 | den = denominator & typemacro ## _MAX; \ |
| | 336 | uxdiv_ret = aeabi_ ## uiname(num, den); \ |
| | 337 | /* signs differ */ \ |
| | 338 | if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \ |
| | 339 | ret.quot = uxdiv_ret.quot * -1; \ |
| | 340 | else \ |
| | 341 | ret.quot = uxdiv_ret.quot; \ |
| | 342 | if (numerator & typemacro ## _MIN) \ |
| | 343 | ret.rem = uxdiv_ret.rem * -1; \ |
| | 344 | else \ |
| | 345 | ret.rem = uxdiv_ret.rem; \ |
| | 346 | \ |
| | 347 | rettype ## _return(ret); \ |
| | 348 | } |
| | 349 | |
| | 350 | define_aeabi_xdivmod_signed_type(long long, lldiv_t); |
| | 351 | define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t); |
| | 352 | define_aeabi_xdivmod_signed_type(int, idiv_t); |
| | 353 | define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t); |
| | 354 | |
| | 355 | REGS_RETURN(lldiv_t, lldiv_t) |
| | 356 | REGS_RETURN(ulldiv_t, ulldiv_t) |
| | 357 | REGS_RETURN(idiv_t, idiv_t) |
| | 358 | REGS_RETURN(uidiv_t, uidiv_t) |
| | 359 | |
| | 360 | AEABI_UXDIVMOD(uldivmod, unsigned long long, ulldiv_t, ULONG) |
| | 361 | |
| | 362 | __AEABI_XDIVMOD(ldivmod, long long, uldivmod, lldiv_t, ulldiv_t, LLONG) |
| | 363 | |
| | 364 | void __aeabi_uldivmod(unsigned long long num, unsigned long long den) |
| | 365 | { |
| | 366 | ulldiv_t_return(aeabi_uldivmod(num, den)); |
| | 367 | } |
| | 368 | |
| | 369 | void __aeabi_llsl(double_unsigned_struct val, int shift) |
| | 370 | { |
| | 371 | double_unsigned_struct ret; |
| | 372 | |
| | 373 | if (shift >= 32) { |
| | 374 | val.high = val.low; |
| | 375 | val.low = 0; |
| | 376 | shift -= 32; |
| | 377 | } |
| | 378 | if (shift > 0) { |
| | 379 | ret.low = val.low << shift; |
| | 380 | ret.high = (val.high << shift) | (val.low >> (32 - shift)); |
| | 381 | double_unsigned_struct_return(ret); |
| | 382 | return; |
| | 383 | } |
| | 384 | double_unsigned_struct_return(val); |
| | 385 | } |
| | 386 | |
| | 387 | #define aeabi_lsr(val, shift, fill, type) \ |
| | 388 | type ## _struct ret; \ |
| | 389 | \ |
| | 390 | if (shift >= 32) { \ |
| | 391 | val.low = val.high; \ |
| | 392 | val.high = fill; \ |
| | 393 | shift -= 32; \ |
| | 394 | } \ |
| | 395 | if (shift > 0) { \ |
| | 396 | ret.high = val.high >> shift; \ |
| | 397 | ret.low = (val.high << (32 - shift)) | (val.low >> shift); \ |
| | 398 | type ## _struct_return(ret); \ |
| | 399 | return; \ |
| | 400 | } \ |
| | 401 | type ## _struct_return(val); |
| | 402 | |
| | 403 | void __aeabi_llsr(double_unsigned_struct val, int shift) |
| | 404 | { |
| | 405 | aeabi_lsr(val, shift, 0, double_unsigned); |
| | 406 | } |
| | 407 | |
| | 408 | void __aeabi_lasr(unsigned_int_struct val, int shift) |
| | 409 | { |
| | 410 | aeabi_lsr(val, shift, val.high >> 31, unsigned_int); |
| | 411 | } |
| | 412 | |
| | 413 | |
| | 414 | /* Integer division functions */ |
| | 415 | |
| | 416 | AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT) |
| | 417 | |
| | 418 | int __aeabi_idiv(int numerator, int denominator) |
| | 419 | { |
| | 420 | unsigned num, den; |
| | 421 | uidiv_t ret; |
| | 422 | |
| | 423 | num = numerator & INT_MAX; |
| | 424 | den = denominator & INT_MAX; |
| | 425 | ret = aeabi_uidivmod(num, den); |
| | 426 | if ((numerator & INT_MIN) != (denominator & INT_MIN)) /* signs differ */ |
| | 427 | ret.quot *= -1; |
| | 428 | return ret.quot; |
| | 429 | } |
| | 430 | |
| | 431 | unsigned __aeabi_uidiv(unsigned num, unsigned den) |
| | 432 | { |
| | 433 | return aeabi_uidivmod(num, den).quot; |
| | 434 | } |
| | 435 | |
| | 436 | __AEABI_XDIVMOD(idivmod, int, uidivmod, idiv_t, uidiv_t, INT) |
| | 437 | |
| | 438 | void __aeabi_uidivmod(unsigned num, unsigned den) |
| | 439 | { |
| | 440 | uidiv_t_return(aeabi_uidivmod(num, den)); |
| | 441 | } |