Add implementation for float / integer conversion functions: __aeabi_d2lz, __aeabi_d2ulz, __aeabi_f2lz, __aeabi_f2ulz, __aeabi_l2d, __aeabi_l2f, __aeabi_ul2d, __aeabi_ul2f Add implementation for long long helper functions: __aeabi_ldivmod, __aeabi_uldivmod, __aeabi_llsl, __aeabi_llsr, __aeabi_lasr Add implementation for integer division functions: __aeabi_uidiv, __aeabi_uidivmod, __aeabi_idiv, __aeabi_idivmod,
Showing the changes to lib (2 of 3 files). Show all
Unified · Split
| @@ -45,7 +45,7 @@ cross : TCC = $(TOP)/$(TARGET)-tcc$(EXESUF) · 44 unmodified lines | |||
| 45 | 45 | ||
| 46 | I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O) | 46 | I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BCHECK_O) |
| 47 | X86_64_O = libtcc1.o alloca86_64.o | 47 | X86_64_O = libtcc1.o alloca86_64.o |
| 48 | ARM_O = libtcc1.o | 48 | ARM_O = libtcc1.o armeabi.o |
| 49 | WIN32_O = $(I386_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o | 49 | WIN32_O = $(I386_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o |
| 50 | WIN64_O = $(X86_64_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o | 50 | WIN64_O = $(X86_64_O) crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o |
| 51 | 51 | ||
| @@ -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 | } | ||