1 #include <linux/module.h> 2 3 #include "libgcc.h" 4 5 #define DWtype long long 6 #define UWtype unsigned long 7 #define UHWtype unsigned short 8 9 #define W_TYPE_SIZE 32 10 11 #define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) 12 #define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) 13 #define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) 14 15 /* If we still don't have umul_ppmm, define it using plain C. */ 16 #if !defined(umul_ppmm) 17 #define umul_ppmm(w1, w0, u, v) \ 18 do { \ 19 UWtype __x0, __x1, __x2, __x3; \ 20 UHWtype __ul, __vl, __uh, __vh; \ 21 \ 22 __ul = __ll_lowpart(u); \ 23 __uh = __ll_highpart(u); \ 24 __vl = __ll_lowpart(v); \ 25 __vh = __ll_highpart(v); \ 26 \ 27 __x0 = (UWtype) __ul * __vl; \ 28 __x1 = (UWtype) __ul * __vh; \ 29 __x2 = (UWtype) __uh * __vl; \ 30 __x3 = (UWtype) __uh * __vh; \ 31 \ 32 __x1 += __ll_highpart(__x0); /* this can't give carry */\ 33 __x1 += __x2; /* but this indeed can */ \ 34 if (__x1 < __x2) /* did we get it? */ \ 35 __x3 += __ll_B; /* yes, add it in the proper pos */ \ 36 \ 37 (w1) = __x3 + __ll_highpart(__x1); \ 38 (w0) = __ll_lowpart(__x1) * __ll_B + __ll_lowpart(__x0);\ 39 } while (0) 40 #endif 41 42 #if !defined(__umulsidi3) 43 #define __umulsidi3(u, v) ({ \ 44 DWunion __w; \ 45 umul_ppmm(__w.s.high, __w.s.low, u, v); \ 46 __w.ll; \ 47 }) 48 #endif 49 50 DWtype __muldi3(DWtype u, DWtype v) 51 { 52 const DWunion uu = {.ll = u}; 53 const DWunion vv = {.ll = v}; 54 DWunion w = {.ll = __umulsidi3(uu.s.low, vv.s.low)}; 55 56 w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high 57 + (UWtype) uu.s.high * (UWtype) vv.s.low); 58 59 return w.ll; 60 } 61