171abb752SPaolo Bonzini #include <stdint.h>
20b2d3dafSPaolo Bonzini
30b2d3dafSPaolo Bonzini extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *p_rem);
4a8a79dacSPaolo Bonzini extern int64_t __divmoddi4(int64_t num, int64_t den, int64_t *p_rem);
50b2d3dafSPaolo Bonzini extern int64_t __moddi3(int64_t num, int64_t den);
60b2d3dafSPaolo Bonzini extern int64_t __divdi3(int64_t num, int64_t den);
70b2d3dafSPaolo Bonzini extern uint64_t __udivdi3(uint64_t num, uint64_t den);
80b2d3dafSPaolo Bonzini extern uint64_t __umoddi3(uint64_t num, uint64_t den);
9*3b10c7e2SAndrew Jones #if __riscv
10*3b10c7e2SAndrew Jones extern int __clzsi2(uint32_t num);
11*3b10c7e2SAndrew Jones extern int __clzdi2(uint64_t num);
12*3b10c7e2SAndrew Jones
__clzsi2(uint32_t num)13*3b10c7e2SAndrew Jones int __clzsi2(uint32_t num)
14*3b10c7e2SAndrew Jones {
15*3b10c7e2SAndrew Jones int n = 0;
16*3b10c7e2SAndrew Jones
17*3b10c7e2SAndrew Jones while (num) {
18*3b10c7e2SAndrew Jones ++n;
19*3b10c7e2SAndrew Jones num >>= 1;
20*3b10c7e2SAndrew Jones }
21*3b10c7e2SAndrew Jones
22*3b10c7e2SAndrew Jones return 32 - n;
23*3b10c7e2SAndrew Jones }
24*3b10c7e2SAndrew Jones
__clzdi2(uint64_t num)25*3b10c7e2SAndrew Jones int __clzdi2(uint64_t num)
26*3b10c7e2SAndrew Jones {
27*3b10c7e2SAndrew Jones return num >> 32 ? __clzsi2(num >> 32) : __clzsi2(num) + 32;
28*3b10c7e2SAndrew Jones }
29*3b10c7e2SAndrew Jones #endif
300b2d3dafSPaolo Bonzini
__udivmoddi4(uint64_t num,uint64_t den,uint64_t * p_rem)310b2d3dafSPaolo Bonzini uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *p_rem)
320b2d3dafSPaolo Bonzini {
330b2d3dafSPaolo Bonzini uint64_t quot = 0;
340b2d3dafSPaolo Bonzini
350b2d3dafSPaolo Bonzini /* Trigger a division by zero at run time (trick taken from iPXE). */
36a8a79dacSPaolo Bonzini if (den == 0) {
37a8a79dacSPaolo Bonzini if (p_rem)
38a8a79dacSPaolo Bonzini *p_rem = 0;
390b2d3dafSPaolo Bonzini return 1/((unsigned)den);
40a8a79dacSPaolo Bonzini }
410b2d3dafSPaolo Bonzini
420b2d3dafSPaolo Bonzini if (num >= den) {
430b2d3dafSPaolo Bonzini /* Align den to num to avoid wasting time on leftmost zero bits. */
440b2d3dafSPaolo Bonzini int n = __builtin_clzll(den) - __builtin_clzll(num);
450b2d3dafSPaolo Bonzini den <<= n;
460b2d3dafSPaolo Bonzini
470b2d3dafSPaolo Bonzini do {
480b2d3dafSPaolo Bonzini quot <<= 1;
490b2d3dafSPaolo Bonzini if (num >= den) {
500b2d3dafSPaolo Bonzini num -= den;
510b2d3dafSPaolo Bonzini quot |= 1;
520b2d3dafSPaolo Bonzini }
530b2d3dafSPaolo Bonzini den >>= 1;
540b2d3dafSPaolo Bonzini } while (n--);
550b2d3dafSPaolo Bonzini }
560b2d3dafSPaolo Bonzini
570b2d3dafSPaolo Bonzini if (p_rem)
580b2d3dafSPaolo Bonzini *p_rem = num;
590b2d3dafSPaolo Bonzini
600b2d3dafSPaolo Bonzini return quot;
610b2d3dafSPaolo Bonzini }
620b2d3dafSPaolo Bonzini
__divmoddi4(int64_t num,int64_t den,int64_t * p_rem)63a8a79dacSPaolo Bonzini int64_t __divmoddi4(int64_t num, int64_t den, int64_t *p_rem)
640b2d3dafSPaolo Bonzini {
65a8a79dacSPaolo Bonzini int32_t nmask = num < 0 ? -1 : 0;
66a8a79dacSPaolo Bonzini int32_t qmask = (num ^ den) < 0 ? -1 : 0;
67a8a79dacSPaolo Bonzini uint64_t quot;
680b2d3dafSPaolo Bonzini
690b2d3dafSPaolo Bonzini /* Compute absolute values and do an unsigned division. */
70a8a79dacSPaolo Bonzini num = (num + nmask) ^ nmask;
710b2d3dafSPaolo Bonzini if (den < 0)
720b2d3dafSPaolo Bonzini den = -den;
730b2d3dafSPaolo Bonzini
74a8a79dacSPaolo Bonzini /* Copy sign of num^den into quotient, sign of num into remainder. */
75a8a79dacSPaolo Bonzini quot = (__udivmoddi4(num, den, (uint64_t *)p_rem) + qmask) ^ qmask;
76a8a79dacSPaolo Bonzini if (p_rem)
77a8a79dacSPaolo Bonzini *p_rem = (*p_rem + nmask) ^ nmask;
78a8a79dacSPaolo Bonzini return quot;
79a8a79dacSPaolo Bonzini }
80a8a79dacSPaolo Bonzini
__moddi3(int64_t num,int64_t den)81a8a79dacSPaolo Bonzini int64_t __moddi3(int64_t num, int64_t den)
82a8a79dacSPaolo Bonzini {
83a8a79dacSPaolo Bonzini int64_t rem;
84a8a79dacSPaolo Bonzini __divmoddi4(num, den, &rem);
85a8a79dacSPaolo Bonzini return rem;
860b2d3dafSPaolo Bonzini }
870b2d3dafSPaolo Bonzini
__divdi3(int64_t num,int64_t den)880b2d3dafSPaolo Bonzini int64_t __divdi3(int64_t num, int64_t den)
890b2d3dafSPaolo Bonzini {
90a8a79dacSPaolo Bonzini int64_t rem;
91a8a79dacSPaolo Bonzini return __divmoddi4(num, den, &rem);
920b2d3dafSPaolo Bonzini }
930b2d3dafSPaolo Bonzini
__udivdi3(uint64_t num,uint64_t den)940b2d3dafSPaolo Bonzini uint64_t __udivdi3(uint64_t num, uint64_t den)
950b2d3dafSPaolo Bonzini {
960b2d3dafSPaolo Bonzini uint64_t rem;
970b2d3dafSPaolo Bonzini return __udivmoddi4(num, den, &rem);
980b2d3dafSPaolo Bonzini }
990b2d3dafSPaolo Bonzini
__umoddi3(uint64_t num,uint64_t den)1000b2d3dafSPaolo Bonzini uint64_t __umoddi3(uint64_t num, uint64_t den)
1010b2d3dafSPaolo Bonzini {
1020b2d3dafSPaolo Bonzini uint64_t rem;
1030b2d3dafSPaolo Bonzini __udivmoddi4(num, den, &rem);
1040b2d3dafSPaolo Bonzini return rem;
1050b2d3dafSPaolo Bonzini }
1060b2d3dafSPaolo Bonzini
1070b2d3dafSPaolo Bonzini #ifdef TEST
1080b2d3dafSPaolo Bonzini #include <assert.h>
1090b2d3dafSPaolo Bonzini #define UTEST(a, b, q, r) assert(__udivdi3(a, b) == q && __umoddi3(a, b) == r)
1100b2d3dafSPaolo Bonzini #define STEST(a, b, q, r) assert(__divdi3(a, b) == q && __moddi3(a, b) == r)
main()1110b2d3dafSPaolo Bonzini int main()
1120b2d3dafSPaolo Bonzini {
1130b2d3dafSPaolo Bonzini UTEST(1, 1, 1, 0);
1140b2d3dafSPaolo Bonzini UTEST(2, 2, 1, 0);
1150b2d3dafSPaolo Bonzini UTEST(5, 3, 1, 2);
1160b2d3dafSPaolo Bonzini UTEST(10, 3, 3, 1);
1170b2d3dafSPaolo Bonzini UTEST(120, 3, 40, 0);
1180b2d3dafSPaolo Bonzini UTEST(120, 1, 120, 0);
1190b2d3dafSPaolo Bonzini UTEST(0x7FFFFFFFFFFFFFFFULL, 17, 0x787878787878787, 8);
1200b2d3dafSPaolo Bonzini UTEST(0x7FFFFFFFFFFFFFFFULL, 0x787878787878787, 17, 8);
1210b2d3dafSPaolo Bonzini UTEST(0x8000000000000001ULL, 17, 0x787878787878787, 10);
1220b2d3dafSPaolo Bonzini UTEST(0x8000000000000001ULL, 0x787878787878787, 17, 10);
1230b2d3dafSPaolo Bonzini UTEST(0, 5, 0, 0);
1240b2d3dafSPaolo Bonzini
1250b2d3dafSPaolo Bonzini STEST(0x7FFFFFFFFFFFFFFFULL, 17, 0x787878787878787, 8);
1260b2d3dafSPaolo Bonzini STEST(0x7FFFFFFFFFFFFFFFULL, -17, -0x787878787878787, 8);
1270b2d3dafSPaolo Bonzini STEST(-0x7FFFFFFFFFFFFFFFULL, 17, -0x787878787878787, -8);
1280b2d3dafSPaolo Bonzini STEST(-0x7FFFFFFFFFFFFFFFULL, -17, 0x787878787878787, -8);
1290b2d3dafSPaolo Bonzini STEST(33, 5, 6, 3);
1300b2d3dafSPaolo Bonzini STEST(33, -5, -6, 3);
1310b2d3dafSPaolo Bonzini STEST(-33, 5, -6, -3);
1320b2d3dafSPaolo Bonzini STEST(-33, -5, 6, -3);
1330b2d3dafSPaolo Bonzini }
1340b2d3dafSPaolo Bonzini #endif
135