math64.h 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _LINUX_MATH64_H
  3. #define _LINUX_MATH64_H
  4. #include <linux/types.h>
  5. #ifdef __x86_64__
  6. static inline u64 mul_u64_u64_div64(u64 a, u64 b, u64 c)
  7. {
  8. u64 q;
  9. asm ("mulq %2; divq %3" : "=a" (q)
  10. : "a" (a), "rm" (b), "rm" (c)
  11. : "rdx");
  12. return q;
  13. }
  14. #define mul_u64_u64_div64 mul_u64_u64_div64
  15. #endif
  16. #ifdef __SIZEOF_INT128__
  17. static inline u64 mul_u64_u32_shr(u64 a, u32 b, unsigned int shift)
  18. {
  19. return (u64)(((unsigned __int128)a * b) >> shift);
  20. }
  21. #else
  22. #ifdef __i386__
  23. static inline u64 mul_u32_u32(u32 a, u32 b)
  24. {
  25. u32 high, low;
  26. asm ("mull %[b]" : "=a" (low), "=d" (high)
  27. : [a] "a" (a), [b] "rm" (b) );
  28. return low | ((u64)high) << 32;
  29. }
  30. #else
  31. static inline u64 mul_u32_u32(u32 a, u32 b)
  32. {
  33. return (u64)a * b;
  34. }
  35. #endif
  36. static inline u64 mul_u64_u32_shr(u64 a, u32 b, unsigned int shift)
  37. {
  38. u32 ah, al;
  39. u64 ret;
  40. al = a;
  41. ah = a >> 32;
  42. ret = mul_u32_u32(al, b) >> shift;
  43. if (ah)
  44. ret += mul_u32_u32(ah, b) << (32 - shift);
  45. return ret;
  46. }
  47. #endif /* __SIZEOF_INT128__ */
  48. #ifndef mul_u64_u64_div64
  49. static inline u64 mul_u64_u64_div64(u64 a, u64 b, u64 c)
  50. {
  51. u64 quot, rem;
  52. quot = a / c;
  53. rem = a % c;
  54. return quot * b + (rem * b) / c;
  55. }
  56. #endif
  57. static inline u64 div_u64(u64 dividend, u32 divisor)
  58. {
  59. return dividend / divisor;
  60. }
  61. #endif /* _LINUX_MATH64_H */