11#define FLOAT_SIGN(x) ((x) >> 31)
12#define FLOAT_EXP(x) (((x) >> 23) & 0xFF)
13#define FLOAT_MANT(x) ((x) & 0x7FFFFF)
15#define FLOAT_RECONSTRUCT(sign, exp, mant) (((sign) << 31) | ((exp) << 23) | (mant))
17#ifdef HARDWAREDIVISION
20#define HWREG32(addr) (*((volatile uint32_t *)(addr)))
23#define MULT_BASE_ADDR 0x00000500
24#define MULT_INFO_OFFSET 0x0000
25#define MUL1_OFFSET 0x0004
26#define MUL2_OFFSET 0x0008
27#define RESH_OFFSET 0x000C
28#define RESL_OFFSET 0x0010
30#define DIV_BASE_ADDR 0x00000600
31#define DIV_INFO_OFFSET 0x00
32#define DIV_END_OFFSET 0x04
33#define DIV_SOR_OFFSET 0x08
34#define DIV_QUO_OFFSET 0x0C
35#define DIV_REM_OFFSET 0x10
37static inline uint64_t
mult_calc_64(uint32_t multiplicand, uint32_t multiplier)
46 return (high << 32) | low;
49static inline uint32_t mult_calc_32(uint32_t multiplicand, uint32_t multiplier)
89static inline uint32_t div_get_quotient()
94static inline uint32_t div_get_remainder()
101float __floatsisf(int32_t x)
113 abs_x = (x == (-2147483647 - 1)) ? 0x80000000U : (uint32_t)(-x);
121 while (!(abs_x & (1u << shift)))
124 int exp = shift + FLOAT_BIAS;
129 int rshift = shift - 23;
130 uint32_t extra = abs_x & ((1u << rshift) - 1);
131 mantissa = abs_x >> rshift;
133 uint32_t halfway = 1u << (rshift - 1);
136 if ((extra > halfway) || ((extra == halfway) && (mantissa & 1)))
140 if (mantissa & (1u << 24))
149 mantissa = abs_x << (23 - shift);
152 mantissa &= 0x7FFFFF;
155 u.i = FLOAT_RECONSTRUCT(sign, exp, mantissa);
159int32_t __fixsfsi(
float x)
162 int32_t sign = FLOAT_SIGN(u.i);
163 int32_t exp = FLOAT_EXP(u.i) - FLOAT_BIAS;
172 return sign ? -2147483648 : 2147483647;
175 uint32_t mant = FLOAT_MANT(u.i) | (1u << 23);
179 result = mant << (exp - 23);
183 result = mant >> (23 - exp);
185 return sign ? -result : result;
188float __addsf3(
float a,
float b)
193 if (FLOAT_EXP(ua.i) == 0xFF)
195 if (FLOAT_MANT(ua.i))
198 if ((FLOAT_EXP(ub.i) == 0xFF) && (FLOAT_MANT(ub.i) == 0) &&
199 (FLOAT_SIGN(ua.i) != FLOAT_SIGN(ub.i)))
207 if (FLOAT_EXP(ub.i) == 0xFF)
209 if (FLOAT_MANT(ub.i))
214 if ((ua.i & 0x7FFFFFFF) == 0)
216 if ((ub.i & 0x7FFFFFFF) == 0)
219 int exp_a = FLOAT_EXP(ua.i);
220 int exp_b = FLOAT_EXP(ub.i);
221 uint32_t mant_a = FLOAT_MANT(ua.i);
222 uint32_t mant_b = FLOAT_MANT(ub.i);
226 exp_a = 1 - FLOAT_BIAS;
230 mant_a |= (1u << 23);
234 exp_b = 1 - FLOAT_BIAS;
238 mant_b |= (1u << 23);
240 int sign_a = FLOAT_SIGN(ua.i);
241 int sign_b = FLOAT_SIGN(ub.i);
243 int exp_diff = exp_a - exp_b;
245 uint32_t mant_a_ext = mant_a << 3;
246 uint32_t mant_b_ext = mant_b << 3;
252 uint32_t lost = mant_b_ext & ((1u << exp_diff) - 1);
253 mant_b_ext = mant_b_ext >> exp_diff;
263 else if (exp_diff < 0)
265 int shift = -exp_diff;
268 uint32_t lost = mant_a_ext & ((1u << shift) - 1);
269 mant_a_ext = mant_a_ext >> shift;
284 uint32_t result_mant;
286 if (sign_a == sign_b)
288 result_mant = mant_a_ext + mant_b_ext;
289 result_sign = sign_a;
293 if (mant_a_ext >= mant_b_ext)
295 result_mant = mant_a_ext - mant_b_ext;
296 result_sign = sign_a;
300 result_mant = mant_b_ext - mant_a_ext;
301 result_sign = sign_b;
305 if (result_mant == 0)
308 res.i = result_sign << 31;
312 if (result_mant & (1u << (24 + 3)))
314 uint32_t lsb = result_mant & 1;
315 result_mant = (result_mant >> 1) + lsb;
321 while ((result_mant & (1u << (23 + 3))) == 0)
328 uint32_t guard = (result_mant >> 2) & 1;
329 uint32_t round_bit = (result_mant >> 1) & 1;
330 uint32_t sticky = (result_mant & 1);
331 uint32_t frac = result_mant >> 3;
333 if (round_bit && (sticky || (frac & 1)))
336 if (frac & (1u << 24))
342 uint32_t final_mant = frac & 0x7FFFFF;
346 int shift = 1 - exp_result;
348 final_mant = frac >> shift;
353 if (exp_result >= 255)
357 res.i = (result_sign << 31) | (0xFF << 23);
362 res.i = (result_sign << 31) | ((exp_result & 0xFF) << 23) | (final_mant & 0x7FFFFF);
366float __subsf3(
float a,
float b)
370 return __addsf3(a, ub.f);
373float __mulsf3(
float a,
float b)
378 if (FLOAT_EXP(ua.i) == 0xFF)
380 if (FLOAT_MANT(ua.i))
382 if ((ub.i & 0x7FFFFFFF) == 0)
390 if (FLOAT_EXP(ub.i) == 0xFF)
392 if (FLOAT_MANT(ub.i))
394 if ((ua.i & 0x7FFFFFFF) == 0)
403 if ((ua.i & 0x7FFFFFFF) == 0 || (ub.i & 0x7FFFFFFF) == 0)
406 res.i = (FLOAT_SIGN(ua.i) ^ FLOAT_SIGN(ub.i)) << 31;
410 int sign = FLOAT_SIGN(ua.i) ^ FLOAT_SIGN(ub.i);
411 int exp_a = FLOAT_EXP(ua.i);
412 int exp_b = FLOAT_EXP(ub.i);
413 uint32_t mant_a = FLOAT_MANT(ua.i);
414 uint32_t mant_b = FLOAT_MANT(ub.i);
416 mant_a |= (1u << 23);
418 exp_a = 1 - FLOAT_BIAS;
420 mant_b |= (1u << 23);
422 exp_b = 1 - FLOAT_BIAS;
424 int exp_result = exp_a + exp_b - FLOAT_BIAS;
426 uint64_t product = (uint64_t)mant_a * (uint64_t)mant_b;
428 uint64_t shifted = product >> 23;
429 if (shifted & (1ULL << 24))
434 uint32_t frac = shifted & ((1u << 23) - 1);
439 int shift = 1 - exp_result;
441 frac = (uint32_t)shifted >> shift;
446 if (exp_result >= 255)
449 res.i = (sign << 31) | (0xFF << 23);
453 res.i = (sign << 31) | ((exp_result & 0xFF) << 23) | (frac & 0x7FFFFF);
457float __divsf3(
float a,
float b)
462 if (FLOAT_EXP(ua.i) == 0xFF)
464 if (FLOAT_MANT(ua.i))
466 if (FLOAT_EXP(ub.i) == 0xFF && (FLOAT_MANT(ub.i) == 0))
473 res.i = FLOAT_RECONSTRUCT(FLOAT_SIGN(ua.i) ^ FLOAT_SIGN(ub.i), 0xFF, 0);
476 if (FLOAT_EXP(ub.i) == 0xFF)
478 if (FLOAT_MANT(ub.i))
481 res.i = FLOAT_RECONSTRUCT(FLOAT_SIGN(ua.i) ^ FLOAT_SIGN(ub.i), 0, 0);
485 if ((ub.i & 0x7FFFFFFF) == 0)
487 if ((ua.i & 0x7FFFFFFF) == 0)
494 res.i = FLOAT_RECONSTRUCT(FLOAT_SIGN(ua.i) ^ FLOAT_SIGN(ub.i), 0xFF, 0);
497 if ((ua.i & 0x7FFFFFFF) == 0)
500 res.i = FLOAT_RECONSTRUCT(FLOAT_SIGN(ua.i) ^ FLOAT_SIGN(ub.i), 0, 0);
504 int sign = FLOAT_SIGN(ua.i) ^ FLOAT_SIGN(ub.i);
505 int exp_a = (FLOAT_EXP(ua.i) == 0 ? 1 - FLOAT_BIAS : FLOAT_EXP(ua.i));
506 int exp_b = (FLOAT_EXP(ub.i) == 0 ? 1 - FLOAT_BIAS : FLOAT_EXP(ub.i));
507 uint32_t mant_a = (FLOAT_EXP(ua.i) == 0 ? FLOAT_MANT(ua.i) : (FLOAT_MANT(ua.i) | (1u << 23)));
508 uint32_t mant_b = (FLOAT_EXP(ub.i) == 0 ? FLOAT_MANT(ub.i) : (FLOAT_MANT(ub.i) | (1u << 23)));
510 uint64_t dividend = (uint64_t)mant_a << 31;
511 uint32_t divisor = mant_b;
512 uint64_t quotient = dividend / divisor;
514 uint32_t q = quotient >> 8;
515 uint32_t round_bit = (quotient >> 7) & 1;
516 uint32_t sticky = ((quotient & 0x7F) != 0);
517 if (round_bit && (sticky || (q & 1)))
526 int exp_result = exp_a - exp_b + FLOAT_BIAS;
534 int shift = 1 - exp_result;
541 if (exp_result >= 255)
544 res.i = (sign << 31) | (0xFF << 23);
548 res.i = (sign << 31) | ((exp_result & 0xFF) << 23) | (q & 0x7FFFFF);
552int32_t __gesf2(
float a,
float b)
554 return (a >= b) ? 1 : 0;
557int32_t __ltsf2(
float a,
float b)
559 return (a < b) ? 1 : 0;
562uint32_t __clzsi2(uint32_t x)
569 while (!(x & 0x80000000))
577uint32_t __ffssi2(uint32_t x)
583 return 32 - __clzsi2(x);
592divmod_result __divmodsi4(uint32_t dividend, uint32_t divisor) {
595#ifdef HARDWAREDIVISION
597 res.quotient = 0xFFFFFFFF;
598 res.remainder = 0xFFFFFFFF;
601 res.remainder = div_get_remainder();
609 for (int32_t i = 31; i >= 0; i--) {
610 temp = (temp << 1) | ((dividend >> i) & 1);
611 if (temp >= divisor) {
613 res.quotient |= (1U << i);
616 res.remainder = temp;
623int64_t __muldi3(int64_t a, int64_t b)
625 uint64_t ua, ub, result = 0;
631 negative = !negative;
638 negative = !negative;
651 result = (~result) + 1;
653 return (int64_t)result;
656uint64_t __udivdi3(uint64_t dividend, uint64_t divisor)
660 return ~((uint64_t)0);
662 uint64_t quotient = 0;
663 for (int32_t i = 63; i >= 0; i--)
665 if ((dividend >> i) >= divisor)
667 quotient |= ((uint64_t)1 << i);
668 dividend -= (divisor << i);
674uint64_t __umoddi3(uint64_t dividend, uint64_t divisor)
680 for (int32_t i = 63; i >= 0; i--)
682 if ((dividend >> i) >= divisor)
684 dividend -= (divisor << i);
690int64_t __divdi3(int64_t dividend, int64_t divisor)
693 uint64_t udividend, udivisor, quotient;
695 udividend = (uint64_t)dividend;
698 negative = !negative;
699 udividend = (~udividend) + 1;
702 udivisor = (uint64_t)divisor;
705 negative = !negative;
706 udivisor = (~udivisor) + 1;
709 quotient = __udivdi3(udividend, udivisor);
712 quotient = (~quotient) + 1;
714 return (int64_t)quotient;
717int64_t __moddi3(int64_t dividend, int64_t divisor)
720 uint64_t udividend, udivisor, remainder;
722 udividend = (uint64_t)dividend;
726 udividend = (~udividend) + 1;
729 udivisor = (uint64_t)divisor;
732 udivisor = (~udivisor) + 1;
735 remainder = __umoddi3(udividend, udivisor);
738 remainder = (~remainder) + 1;
740 return (int64_t)remainder;
743uint64_t __ashldi3(uint64_t a, int32_t b)
745 uint32_t lo = (uint32_t)a;
746 uint32_t hi = (uint32_t)(a >> 32);
753 uint32_t new_hi = (hi << b) | (lo >> (32 - b));
754 uint32_t new_lo = lo << b;
755 return ((uint64_t)new_hi << 32) | new_lo;
759 uint32_t new_hi = lo << (b - 32);
760 return ((uint64_t)new_hi << 32);
764int64_t __ashrdi3(int64_t a, int32_t b)
769 return a < 0 ? -1LL : 0LL;
770 int32_t hi = (int32_t)(a >> 32);
771 uint32_t lo = (uint32_t)a;
774 uint32_t new_lo = (lo >> b) | (((uint32_t)hi) << (32 - b));
775 int32_t new_hi = hi >> b;
776 return ((uint64_t)(uint32_t)new_hi << 32) | new_lo;
781 int32_t new_hi = hi < 0 ? -1 : 0;
782 int32_t new_lo = hi >> (b - 32);
783 return ((uint64_t)(uint32_t)new_hi << 32) | ((uint32_t)new_lo);
787uint64_t __lshrdi3(uint64_t a, int32_t b)
789 uint32_t lo = (uint32_t)a;
790 uint32_t hi = (uint32_t)(a >> 32);
797 uint32_t new_lo = (lo >> b) | (hi << (32 - b));
798 uint32_t new_hi = hi >> b;
799 return ((uint64_t)new_hi << 32) | new_lo;
803 uint32_t new_lo = hi >> (b - 32);
808uint32_t __mulsi3(uint32_t a, uint32_t b)
810#ifdef HARDWAREDIVISION
811 return mult_calc_32(a, b);
827uint32_t __udivsi3(uint32_t dividend, uint32_t divisor)
829#ifdef HARDWAREDIVISION
837 uint32_t quotient = 0, temp = 0;
838 for (int32_t i = 31; i >= 0; i--)
840 temp = (temp << 1) | ((dividend >> i) & 1);
841 if (temp >= divisor) {
843 quotient |= (1U << i);
850uint32_t __umodsi3(uint32_t dividend, uint32_t divisor)
852#ifdef HARDWAREDIVISION
861 for (int32_t i = 31; i >= 0; i--)
863 temp = (temp << 1) | ((dividend >> i) & 1);
873int32_t __divsi3(int32_t dividend, int32_t divisor)
875#ifdef HARDWAREDIVISION
876 uint32_t abs_dividend = (dividend < 0) ? -dividend : dividend;
877 uint32_t abs_divisor = (divisor < 0) ? -divisor : divisor;
879 return ((dividend < 0) ^ (divisor < 0)) ? -(int32_t)result : (int32_t)result;
886 uint32_t abs_dividend = (dividend < 0) ? -dividend : dividend;
887 uint32_t abs_divisor = (divisor < 0) ? -divisor : divisor;
888 uint32_t quotient = 0, temp = 0;
890 for (int32_t i = 31; i >= 0; i--)
892 temp = (temp << 1) | ((abs_dividend >> i) & 1);
893 if (temp >= abs_divisor)
896 quotient |= (1U << i);
900 return ((dividend < 0) ^ (divisor < 0)) ? -(int32_t)quotient : (int32_t)quotient;
904int32_t __modsi3(int32_t dividend, int32_t divisor)
906#ifdef HARDWAREDIVISION
907 uint32_t abs_dividend = (dividend < 0) ? -dividend : dividend;
908 uint32_t abs_divisor = (divisor < 0) ? -divisor : divisor;
910 return (dividend < 0) ? -(int32_t)result : (int32_t)result;
917 uint32_t abs_dividend = (dividend < 0) ? -dividend : dividend;
918 uint32_t abs_divisor = (divisor < 0) ? -divisor : divisor;
921 for (int32_t i = 31; i >= 0; i--)
923 temp = (temp << 1) | ((abs_dividend >> i) & 1);
924 if (temp >= abs_divisor)
930 return (dividend < 0) ? -(int32_t)temp : (int32_t)temp;
934float __negsf2(
float a)
941float __floatunsisf(uint32_t x)
948 while (!(x & (1U << shift)))
952 int32_t exp = shift + FLOAT_BIAS;
953 uint32_t mant = (x << (23 - shift)) & 0x7FFFFF;
954 return ((
float_union){.i = FLOAT_RECONSTRUCT(0, exp, mant)}).f;
957uint32_t __fixunssfsi(
float x)
960 if (u.i & 0x80000000)
964 int32_t exp = FLOAT_EXP(u.i) - FLOAT_BIAS;
973 uint32_t mant = FLOAT_MANT(u.i) | (1 << 23);
976 return mant << (exp - 23);
980 return mant >> (23 - exp);
984uint64_t __umuldi3(uint64_t a, uint64_t b)
986#ifdef HARDWAREDIVISION
987 uint32_t a_low = (uint32_t)(a & 0xFFFFFFFF);
988 uint32_t a_high = (uint32_t)(a >> 32);
989 uint32_t b_low = (uint32_t)(b & 0xFFFFFFFF);
990 uint32_t b_high = (uint32_t)(b >> 32);
994 uint64_t cross = cross1 + cross2;
995 return low_low + (cross << 32);
#define HWREG32(addr)
Makro zur Adressierung von speicherabgebildeten Registern.
uint32_t div_calc_quotient(uint32_t dividend, uint32_t divisor)
Berechnet den Quotienten einer Division.
uint32_t div_calc_remainder(uint32_t dividend, uint32_t divisor)
Berechnet den Rest einer Division.
uint64_t mult_calc_64(uint32_t multiplicand, uint32_t multiplier)
Berechnet das 64-Bit-Ergebnis einer Multiplikation.
#define RESL_OFFSET
Offset für die niederwertigen 32-Bit des 64-Bit-Ergebnisses.
#define DIV_INFO_OFFSET
Offset für das Informationsregister des Dividers.
#define DIV_SOR_OFFSET
Offset für den Divisor.
#define DIV_BASE_ADDR
Basisadresse für den Hardware-Divider.
#define MUL2_OFFSET
Offset für den zweiten Multiplikanden.
#define MUL1_OFFSET
Offset für den ersten Multiplikanden.
#define DIV_REM_OFFSET
Offset für den Rest.
#define MULT_INFO_OFFSET
Offset für das Informationsregister des Multiplikators.
#define DIV_QUO_OFFSET
Offset für den Quotienten.
#define RESH_OFFSET
Offset für die höheren 32-Bit des 64-Bit-Ergebnisses.
#define MULT_BASE_ADDR
Basisadresse für den Hardware-Multiplikator.
#define DIV_END_OFFSET
Offset für den Dividend.