WGR-V
 
Lade ...
Suche ...
Keine Treffer
wgrlib.c
1#include "wgrtypes.h"
2
3//#define HARDWAREDIVISION
4
5typedef union
6{
7 float f;
8 uint32_t i;
10
11#define FLOAT_SIGN(x) ((x) >> 31)
12#define FLOAT_EXP(x) (((x) >> 23) & 0xFF)
13#define FLOAT_MANT(x) ((x) & 0x7FFFFF)
14#define FLOAT_BIAS 127
15#define FLOAT_RECONSTRUCT(sign, exp, mant) (((sign) << 31) | ((exp) << 23) | (mant))
16
17#ifdef HARDWAREDIVISION
18
19#ifndef HWREG32
20#define HWREG32(addr) (*((volatile uint32_t *)(addr)))
21#endif
22
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
29
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
36
37static inline uint64_t mult_calc_64(uint32_t multiplicand, uint32_t multiplier)
38{
39 HWREG32(MULT_BASE_ADDR + MUL1_OFFSET) = multiplicand;
40 HWREG32(MULT_BASE_ADDR + MUL2_OFFSET) = multiplier;
41
43
44 uint64_t high = (uint64_t)HWREG32(MULT_BASE_ADDR + RESH_OFFSET);
45 uint64_t low = (uint64_t)HWREG32(MULT_BASE_ADDR + RESL_OFFSET);
46 return (high << 32) | low;
47}
48
49static inline uint32_t mult_calc_32(uint32_t multiplicand, uint32_t multiplier)
50{
51 HWREG32(MULT_BASE_ADDR + MUL1_OFFSET) = multiplicand;
52 HWREG32(MULT_BASE_ADDR + MUL2_OFFSET) = multiplier;
53
55
57}
58
59static inline uint32_t div_calc_quotient(uint32_t dividend, uint32_t divisor)
60{
61 if (divisor == 0)
62 {
63 return 0xFFFFFFFF;
64 }
65
68
70
72}
73
74static inline uint32_t div_calc_remainder(uint32_t dividend, uint32_t divisor)
75{
76 if (divisor == 0)
77 {
78 return 0xFFFFFFFF;
79 }
80
83
85
87}
88
89static inline uint32_t div_get_quotient()
90{
92}
93
94static inline uint32_t div_get_remainder()
95{
97}
98
99#endif
100
101float __floatsisf(int32_t x)
102{
103 if (x == 0)
104 {
105 return 0.0f;
106 }
107 uint32_t sign = 0;
108 uint32_t abs_x;
109 if (x < 0)
110 {
111 sign = 1;
112
113 abs_x = (x == (-2147483647 - 1)) ? 0x80000000U : (uint32_t)(-x);
114 }
115 else
116 {
117 abs_x = (uint32_t)x;
118 }
119
120 int shift = 31;
121 while (!(abs_x & (1u << shift)))
122 shift--;
123
124 int exp = shift + FLOAT_BIAS;
125 uint32_t mantissa;
126 if (shift > 23)
127 {
128
129 int rshift = shift - 23;
130 uint32_t extra = abs_x & ((1u << rshift) - 1);
131 mantissa = abs_x >> rshift;
132
133 uint32_t halfway = 1u << (rshift - 1);
134 if (rshift > 0)
135 {
136 if ((extra > halfway) || ((extra == halfway) && (mantissa & 1)))
137 mantissa++;
138 }
139
140 if (mantissa & (1u << 24))
141 {
142 mantissa >>= 1;
143 exp++;
144 }
145 }
146 else
147 {
148
149 mantissa = abs_x << (23 - shift);
150 }
151
152 mantissa &= 0x7FFFFF;
153
154 float_union u;
155 u.i = FLOAT_RECONSTRUCT(sign, exp, mantissa);
156 return u.f;
157}
158
159int32_t __fixsfsi(float x)
160{
161 float_union u = {.f = x};
162 int32_t sign = FLOAT_SIGN(u.i);
163 int32_t exp = FLOAT_EXP(u.i) - FLOAT_BIAS;
164
165 if (exp < 0)
166 {
167 return 0;
168 }
169
170 if (exp > 31)
171 {
172 return sign ? -2147483648 : 2147483647;
173 }
174
175 uint32_t mant = FLOAT_MANT(u.i) | (1u << 23);
176 int32_t result;
177 if (exp > 23)
178 {
179 result = mant << (exp - 23);
180 }
181 else
182 {
183 result = mant >> (23 - exp);
184 }
185 return sign ? -result : result;
186}
187
188float __addsf3(float a, float b)
189{
190 float_union ua = {.f = a};
191 float_union ub = {.f = b};
192
193 if (FLOAT_EXP(ua.i) == 0xFF)
194 {
195 if (FLOAT_MANT(ua.i))
196 return a;
197
198 if ((FLOAT_EXP(ub.i) == 0xFF) && (FLOAT_MANT(ub.i) == 0) &&
199 (FLOAT_SIGN(ua.i) != FLOAT_SIGN(ub.i)))
200 {
201 float_union res;
202 res.i = 0xFFC00000;
203 return res.f;
204 }
205 return a;
206 }
207 if (FLOAT_EXP(ub.i) == 0xFF)
208 {
209 if (FLOAT_MANT(ub.i))
210 return b;
211 return b;
212 }
213
214 if ((ua.i & 0x7FFFFFFF) == 0)
215 return b;
216 if ((ub.i & 0x7FFFFFFF) == 0)
217 return a;
218
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);
223
224 if (exp_a == 0)
225 {
226 exp_a = 1 - FLOAT_BIAS;
227 }
228 else
229 {
230 mant_a |= (1u << 23);
231 }
232 if (exp_b == 0)
233 {
234 exp_b = 1 - FLOAT_BIAS;
235 }
236 else
237 {
238 mant_b |= (1u << 23);
239 }
240 int sign_a = FLOAT_SIGN(ua.i);
241 int sign_b = FLOAT_SIGN(ub.i);
242
243 int exp_diff = exp_a - exp_b;
244
245 uint32_t mant_a_ext = mant_a << 3;
246 uint32_t mant_b_ext = mant_b << 3;
247 int exp_result;
248 if (exp_diff > 0)
249 {
250 if (exp_diff < 32)
251 {
252 uint32_t lost = mant_b_ext & ((1u << exp_diff) - 1);
253 mant_b_ext = mant_b_ext >> exp_diff;
254 if (lost)
255 mant_b_ext |= 1;
256 }
257 else
258 {
259 mant_b_ext = 0;
260 }
261 exp_result = exp_a;
262 }
263 else if (exp_diff < 0)
264 {
265 int shift = -exp_diff;
266 if (shift < 32)
267 {
268 uint32_t lost = mant_a_ext & ((1u << shift) - 1);
269 mant_a_ext = mant_a_ext >> shift;
270 if (lost)
271 mant_a_ext |= 1;
272 }
273 else
274 {
275 mant_a_ext = 0;
276 }
277 exp_result = exp_b;
278 }
279 else
280 {
281 exp_result = exp_a;
282 }
283
284 uint32_t result_mant;
285 int result_sign;
286 if (sign_a == sign_b)
287 {
288 result_mant = mant_a_ext + mant_b_ext;
289 result_sign = sign_a;
290 }
291 else
292 {
293 if (mant_a_ext >= mant_b_ext)
294 {
295 result_mant = mant_a_ext - mant_b_ext;
296 result_sign = sign_a;
297 }
298 else
299 {
300 result_mant = mant_b_ext - mant_a_ext;
301 result_sign = sign_b;
302 }
303 }
304
305 if (result_mant == 0)
306 {
307 float_union res;
308 res.i = result_sign << 31;
309 return res.f;
310 }
311
312 if (result_mant & (1u << (24 + 3)))
313 {
314 uint32_t lsb = result_mant & 1;
315 result_mant = (result_mant >> 1) + lsb;
316 exp_result++;
317 }
318 else
319 {
320
321 while ((result_mant & (1u << (23 + 3))) == 0)
322 {
323 result_mant <<= 1;
324 exp_result--;
325 }
326 }
327
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;
332
333 if (round_bit && (sticky || (frac & 1)))
334 {
335 frac++;
336 if (frac & (1u << 24))
337 {
338 frac >>= 1;
339 exp_result++;
340 }
341 }
342 uint32_t final_mant = frac & 0x7FFFFF;
343
344 if (exp_result <= 0)
345 {
346 int shift = 1 - exp_result;
347 if (shift < 32)
348 final_mant = frac >> shift;
349 else
350 final_mant = 0;
351 exp_result = 0;
352 }
353 if (exp_result >= 255)
354 {
355
356 float_union res;
357 res.i = (result_sign << 31) | (0xFF << 23);
358 return res.f;
359 }
360
361 float_union res;
362 res.i = (result_sign << 31) | ((exp_result & 0xFF) << 23) | (final_mant & 0x7FFFFF);
363 return res.f;
364}
365
366float __subsf3(float a, float b)
367{
368 float_union ub = {.f = b};
369 ub.i ^= (1u << 31);
370 return __addsf3(a, ub.f);
371}
372
373float __mulsf3(float a, float b)
374{
375 float_union ua = {.f = a};
376 float_union ub = {.f = b};
377
378 if (FLOAT_EXP(ua.i) == 0xFF)
379 {
380 if (FLOAT_MANT(ua.i))
381 return a;
382 if ((ub.i & 0x7FFFFFFF) == 0)
383 {
384 float_union res;
385 res.i = 0xFFC00000;
386 return res.f;
387 }
388 return a;
389 }
390 if (FLOAT_EXP(ub.i) == 0xFF)
391 {
392 if (FLOAT_MANT(ub.i))
393 return b;
394 if ((ua.i & 0x7FFFFFFF) == 0)
395 {
396 float_union res;
397 res.i = 0xFFC00000;
398 return res.f;
399 }
400 return b;
401 }
402
403 if ((ua.i & 0x7FFFFFFF) == 0 || (ub.i & 0x7FFFFFFF) == 0)
404 {
405 float_union res;
406 res.i = (FLOAT_SIGN(ua.i) ^ FLOAT_SIGN(ub.i)) << 31;
407 return res.f;
408 }
409
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);
415 if (exp_a != 0)
416 mant_a |= (1u << 23);
417 else
418 exp_a = 1 - FLOAT_BIAS;
419 if (exp_b != 0)
420 mant_b |= (1u << 23);
421 else
422 exp_b = 1 - FLOAT_BIAS;
423
424 int exp_result = exp_a + exp_b - FLOAT_BIAS;
425
426 uint64_t product = (uint64_t)mant_a * (uint64_t)mant_b;
427
428 uint64_t shifted = product >> 23;
429 if (shifted & (1ULL << 24))
430 {
431 shifted >>= 1;
432 exp_result++;
433 }
434 uint32_t frac = shifted & ((1u << 23) - 1);
435
436 if (exp_result <= 0)
437 {
438
439 int shift = 1 - exp_result;
440 if (shift < 32)
441 frac = (uint32_t)shifted >> shift;
442 else
443 frac = 0;
444 exp_result = 0;
445 }
446 if (exp_result >= 255)
447 {
448 float_union res;
449 res.i = (sign << 31) | (0xFF << 23);
450 return res.f;
451 }
452 float_union res;
453 res.i = (sign << 31) | ((exp_result & 0xFF) << 23) | (frac & 0x7FFFFF);
454 return res.f;
455}
456
457float __divsf3(float a, float b)
458{
459 float_union ua = {.f = a};
460 float_union ub = {.f = b};
461
462 if (FLOAT_EXP(ua.i) == 0xFF)
463 {
464 if (FLOAT_MANT(ua.i))
465 return a;
466 if (FLOAT_EXP(ub.i) == 0xFF && (FLOAT_MANT(ub.i) == 0))
467 {
468 float_union res;
469 res.i = 0xFFC00000;
470 return res.f;
471 }
472 float_union res;
473 res.i = FLOAT_RECONSTRUCT(FLOAT_SIGN(ua.i) ^ FLOAT_SIGN(ub.i), 0xFF, 0);
474 return res.f;
475 }
476 if (FLOAT_EXP(ub.i) == 0xFF)
477 {
478 if (FLOAT_MANT(ub.i))
479 return b;
480 float_union res;
481 res.i = FLOAT_RECONSTRUCT(FLOAT_SIGN(ua.i) ^ FLOAT_SIGN(ub.i), 0, 0);
482 return res.f;
483 }
484
485 if ((ub.i & 0x7FFFFFFF) == 0)
486 {
487 if ((ua.i & 0x7FFFFFFF) == 0)
488 {
489 float_union res;
490 res.i = 0xFFC00000;
491 return res.f;
492 }
493 float_union res;
494 res.i = FLOAT_RECONSTRUCT(FLOAT_SIGN(ua.i) ^ FLOAT_SIGN(ub.i), 0xFF, 0);
495 return res.f;
496 }
497 if ((ua.i & 0x7FFFFFFF) == 0)
498 {
499 float_union res;
500 res.i = FLOAT_RECONSTRUCT(FLOAT_SIGN(ua.i) ^ FLOAT_SIGN(ub.i), 0, 0);
501 return res.f;
502 }
503
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)));
509
510 uint64_t dividend = (uint64_t)mant_a << 31;
511 uint32_t divisor = mant_b;
512 uint64_t quotient = dividend / divisor;
513
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)))
518 {
519 q++;
520 if (q == (1u << 24))
521 {
522 q >>= 1;
523 exp_a++;
524 }
525 }
526 int exp_result = exp_a - exp_b + FLOAT_BIAS;
527 if (q & (1u << 24))
528 {
529 q >>= 1;
530 exp_result++;
531 }
532 if (exp_result <= 0)
533 {
534 int shift = 1 - exp_result;
535 if (shift < 32)
536 q >>= shift;
537 else
538 q = 0;
539 exp_result = 0;
540 }
541 if (exp_result >= 255)
542 {
543 float_union res;
544 res.i = (sign << 31) | (0xFF << 23);
545 return res.f;
546 }
547 float_union res;
548 res.i = (sign << 31) | ((exp_result & 0xFF) << 23) | (q & 0x7FFFFF);
549 return res.f;
550}
551
552int32_t __gesf2(float a, float b)
553{
554 return (a >= b) ? 1 : 0;
555}
556
557int32_t __ltsf2(float a, float b)
558{
559 return (a < b) ? 1 : 0;
560}
561
562uint32_t __clzsi2(uint32_t x)
563{
564 uint32_t count = 0;
565 if (x == 0)
566 {
567 return 32;
568 }
569 while (!(x & 0x80000000))
570 {
571 count++;
572 x <<= 1;
573 }
574 return count;
575}
576
577uint32_t __ffssi2(uint32_t x)
578{
579 if (x == 0)
580 {
581 return 0;
582 }
583 return 32 - __clzsi2(x);
584}
585
586typedef struct
587{
588 uint32_t quotient;
589 uint32_t remainder;
591
592divmod_result __divmodsi4(uint32_t dividend, uint32_t divisor) {
593 divmod_result res = {0, 0};
594
595#ifdef HARDWAREDIVISION
596 if (divisor == 0) {
597 res.quotient = 0xFFFFFFFF;
598 res.remainder = 0xFFFFFFFF;
599 } else {
600 res.quotient = div_calc_quotient(dividend, divisor);
601 res.remainder = div_get_remainder();
602 }
603#else
604 if (divisor == 0) {
605 res.quotient = 0;
606 res.remainder = 0;
607 } else {
608 uint32_t temp = 0;
609 for (int32_t i = 31; i >= 0; i--) {
610 temp = (temp << 1) | ((dividend >> i) & 1);
611 if (temp >= divisor) {
612 temp -= divisor;
613 res.quotient |= (1U << i);
614 }
615 }
616 res.remainder = temp;
617 }
618#endif
619
620 return res;
621}
622
623int64_t __muldi3(int64_t a, int64_t b)
624{
625 uint64_t ua, ub, result = 0;
626 int negative = 0;
627
628 ua = (uint64_t)a;
629 if (a < 0)
630 {
631 negative = !negative;
632 ua = (~ua) + 1;
633 }
634
635 ub = (uint64_t)b;
636 if (b < 0)
637 {
638 negative = !negative;
639 ub = (~ub) + 1;
640 }
641
642 while (ub)
643 {
644 if (ub & 1)
645 result += ua;
646 ua <<= 1;
647 ub >>= 1;
648 }
649
650 if (negative)
651 result = (~result) + 1;
652
653 return (int64_t)result;
654}
655
656uint64_t __udivdi3(uint64_t dividend, uint64_t divisor)
657{
658 if (divisor == 0)
659 {
660 return ~((uint64_t)0);
661 }
662 uint64_t quotient = 0;
663 for (int32_t i = 63; i >= 0; i--)
664 {
665 if ((dividend >> i) >= divisor)
666 {
667 quotient |= ((uint64_t)1 << i);
668 dividend -= (divisor << i);
669 }
670 }
671 return quotient;
672}
673
674uint64_t __umoddi3(uint64_t dividend, uint64_t divisor)
675{
676 if (divisor == 0)
677 {
678 return 0;
679 }
680 for (int32_t i = 63; i >= 0; i--)
681 {
682 if ((dividend >> i) >= divisor)
683 {
684 dividend -= (divisor << i);
685 }
686 }
687 return dividend;
688}
689
690int64_t __divdi3(int64_t dividend, int64_t divisor)
691{
692 int negative = 0;
693 uint64_t udividend, udivisor, quotient;
694
695 udividend = (uint64_t)dividend;
696 if (dividend < 0)
697 {
698 negative = !negative;
699 udividend = (~udividend) + 1;
700 }
701
702 udivisor = (uint64_t)divisor;
703 if (divisor < 0)
704 {
705 negative = !negative;
706 udivisor = (~udivisor) + 1;
707 }
708
709 quotient = __udivdi3(udividend, udivisor);
710
711 if (negative)
712 quotient = (~quotient) + 1;
713
714 return (int64_t)quotient;
715}
716
717int64_t __moddi3(int64_t dividend, int64_t divisor)
718{
719 int negative = 0;
720 uint64_t udividend, udivisor, remainder;
721
722 udividend = (uint64_t)dividend;
723 if (dividend < 0)
724 {
725 negative = 1;
726 udividend = (~udividend) + 1;
727 }
728
729 udivisor = (uint64_t)divisor;
730 if (divisor < 0)
731 {
732 udivisor = (~udivisor) + 1;
733 }
734
735 remainder = __umoddi3(udividend, udivisor);
736
737 if (negative)
738 remainder = (~remainder) + 1;
739
740 return (int64_t)remainder;
741}
742
743uint64_t __ashldi3(uint64_t a, int32_t b)
744{
745 uint32_t lo = (uint32_t)a;
746 uint32_t hi = (uint32_t)(a >> 32);
747 if (b == 0)
748 return a;
749 if (b >= 64)
750 return 0ULL;
751 if (b < 32)
752 {
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;
756 }
757 else
758 {
759 uint32_t new_hi = lo << (b - 32);
760 return ((uint64_t)new_hi << 32);
761 }
762}
763
764int64_t __ashrdi3(int64_t a, int32_t b)
765{
766 if (b == 0)
767 return a;
768 if (b >= 64)
769 return a < 0 ? -1LL : 0LL;
770 int32_t hi = (int32_t)(a >> 32);
771 uint32_t lo = (uint32_t)a;
772 if (b < 32)
773 {
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;
777 }
778 else
779 {
780
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);
784 }
785}
786
787uint64_t __lshrdi3(uint64_t a, int32_t b)
788{
789 uint32_t lo = (uint32_t)a;
790 uint32_t hi = (uint32_t)(a >> 32);
791 if (b == 0)
792 return a;
793 if (b >= 64)
794 return 0ULL;
795 if (b < 32)
796 {
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;
800 }
801 else
802 {
803 uint32_t new_lo = hi >> (b - 32);
804 return new_lo;
805 }
806}
807
808uint32_t __mulsi3(uint32_t a, uint32_t b)
809{
810#ifdef HARDWAREDIVISION
811 return mult_calc_32(a, b);
812#else
813 uint32_t result = 0;
814 while (b)
815 {
816 if (b & 1)
817 {
818 result += a;
819 }
820 a <<= 1;
821 b >>= 1;
822 }
823 return result;
824#endif
825}
826
827uint32_t __udivsi3(uint32_t dividend, uint32_t divisor)
828{
829#ifdef HARDWAREDIVISION
830 return div_calc_quotient(dividend, divisor);
831#else
832 if (divisor == 0)
833 {
834 return 0;
835 }
836
837 uint32_t quotient = 0, temp = 0;
838 for (int32_t i = 31; i >= 0; i--)
839 {
840 temp = (temp << 1) | ((dividend >> i) & 1);
841 if (temp >= divisor) {
842 temp -= divisor;
843 quotient |= (1U << i);
844 }
845 }
846 return quotient;
847#endif
848}
849
850uint32_t __umodsi3(uint32_t dividend, uint32_t divisor)
851{
852#ifdef HARDWAREDIVISION
853 return div_calc_remainder(dividend, divisor);
854#else
855 if (divisor == 0)
856 {
857 return 0;
858 }
859
860 uint32_t temp = 0;
861 for (int32_t i = 31; i >= 0; i--)
862 {
863 temp = (temp << 1) | ((dividend >> i) & 1);
864 if (temp >= divisor)
865 {
866 temp -= divisor;
867 }
868 }
869 return temp;
870#endif
871}
872
873int32_t __divsi3(int32_t dividend, int32_t divisor)
874{
875#ifdef HARDWAREDIVISION
876 uint32_t abs_dividend = (dividend < 0) ? -dividend : dividend;
877 uint32_t abs_divisor = (divisor < 0) ? -divisor : divisor;
878 uint32_t result = div_calc_quotient(abs_dividend, abs_divisor);
879 return ((dividend < 0) ^ (divisor < 0)) ? -(int32_t)result : (int32_t)result;
880#else
881 if (divisor == 0)
882 {
883 return 0;
884 }
885
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;
889
890 for (int32_t i = 31; i >= 0; i--)
891 {
892 temp = (temp << 1) | ((abs_dividend >> i) & 1);
893 if (temp >= abs_divisor)
894 {
895 temp -= abs_divisor;
896 quotient |= (1U << i);
897 }
898 }
899
900 return ((dividend < 0) ^ (divisor < 0)) ? -(int32_t)quotient : (int32_t)quotient;
901#endif
902}
903
904int32_t __modsi3(int32_t dividend, int32_t divisor)
905{
906#ifdef HARDWAREDIVISION
907 uint32_t abs_dividend = (dividend < 0) ? -dividend : dividend;
908 uint32_t abs_divisor = (divisor < 0) ? -divisor : divisor;
909 uint32_t result = div_calc_remainder(abs_dividend, abs_divisor);
910 return (dividend < 0) ? -(int32_t)result : (int32_t)result;
911#else
912 if (divisor == 0)
913 {
914 return 0;
915 }
916
917 uint32_t abs_dividend = (dividend < 0) ? -dividend : dividend;
918 uint32_t abs_divisor = (divisor < 0) ? -divisor : divisor;
919 uint32_t temp = 0;
920
921 for (int32_t i = 31; i >= 0; i--)
922 {
923 temp = (temp << 1) | ((abs_dividend >> i) & 1);
924 if (temp >= abs_divisor)
925 {
926 temp -= abs_divisor;
927 }
928 }
929
930 return (dividend < 0) ? -(int32_t)temp : (int32_t)temp;
931#endif
932}
933
934float __negsf2(float a)
935{
936 float_union u = {.f = a};
937 u.i ^= (1U << 31);
938 return u.f;
939}
940
941float __floatunsisf(uint32_t x)
942{
943 if (x == 0)
944 {
945 return 0.0f;
946 }
947 int32_t shift = 31;
948 while (!(x & (1U << shift)))
949 {
950 shift--;
951 }
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;
955}
956
957uint32_t __fixunssfsi(float x)
958{
959 float_union u = {.f = x};
960 if (u.i & 0x80000000)
961 {
962 return 0;
963 }
964 int32_t exp = FLOAT_EXP(u.i) - FLOAT_BIAS;
965 if (exp < 0)
966 {
967 return 0;
968 }
969 if (exp > 31)
970 {
971 return ~0U;
972 }
973 uint32_t mant = FLOAT_MANT(u.i) | (1 << 23);
974 if (exp > 23)
975 {
976 return mant << (exp - 23);
977 }
978 else
979 {
980 return mant >> (23 - exp);
981 }
982}
983
984uint64_t __umuldi3(uint64_t a, uint64_t b)
985{
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);
991 uint64_t low_low = mult_calc_64(a_low, b_low);
992 uint64_t cross1 = mult_calc_64(a_low, b_high);
993 uint64_t cross2 = mult_calc_64(a_high, b_low);
994 uint64_t cross = cross1 + cross2;
995 return low_low + (cross << 32);
996#else
997 uint64_t result = 0;
998 while (b)
999 {
1000 if (b & 1)
1001 {
1002 result += a;
1003 }
1004 a <<= 1;
1005 b >>= 1;
1006 }
1007 return result;
1008#endif
1009}
#define HWREG32(addr)
Makro zur Adressierung von speicherabgebildeten Registern.
Definition wgrhal.h:27
uint32_t div_calc_quotient(uint32_t dividend, uint32_t divisor)
Berechnet den Quotienten einer Division.
Definition wgrhal_ext.c:71
uint32_t div_calc_remainder(uint32_t dividend, uint32_t divisor)
Berechnet den Rest einer Division.
Definition wgrhal_ext.c:87
uint64_t mult_calc_64(uint32_t multiplicand, uint32_t multiplier)
Berechnet das 64-Bit-Ergebnis einer Multiplikation.
Definition wgrhal_ext.c:27
#define RESL_OFFSET
Offset für die niederwertigen 32-Bit des 64-Bit-Ergebnisses.
Definition wgrhal_ext.h:42
#define DIV_INFO_OFFSET
Offset für das Informationsregister des Dividers.
Definition wgrhal_ext.h:51
#define DIV_SOR_OFFSET
Offset für den Divisor.
Definition wgrhal_ext.h:59
#define DIV_BASE_ADDR
Basisadresse für den Hardware-Divider.
Definition wgrhal_ext.h:47
#define MUL2_OFFSET
Offset für den zweiten Multiplikanden.
Definition wgrhal_ext.h:34
#define MUL1_OFFSET
Offset für den ersten Multiplikanden.
Definition wgrhal_ext.h:30
#define DIV_REM_OFFSET
Offset für den Rest.
Definition wgrhal_ext.h:67
#define MULT_INFO_OFFSET
Offset für das Informationsregister des Multiplikators.
Definition wgrhal_ext.h:26
#define DIV_QUO_OFFSET
Offset für den Quotienten.
Definition wgrhal_ext.h:63
#define RESH_OFFSET
Offset für die höheren 32-Bit des 64-Bit-Ergebnisses.
Definition wgrhal_ext.h:38
#define MULT_BASE_ADDR
Basisadresse für den Hardware-Multiplikator.
Definition wgrhal_ext.h:22
#define DIV_END_OFFSET
Offset für den Dividend.
Definition wgrhal_ext.h:55