1
0

math64.h 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __VDSO_MATH64_H
  3. #define __VDSO_MATH64_H
  4. static __always_inline u32
  5. __iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
  6. {
  7. u32 ret = 0;
  8. while (dividend >= divisor) {
  9. /* The following asm() prevents the compiler from
  10. optimising this loop into a modulo operation. */
  11. asm("" : "+rm"(dividend));
  12. dividend -= divisor;
  13. ret++;
  14. }
  15. *remainder = dividend;
  16. return ret;
  17. }
  18. #if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__)
  19. #ifndef mul_u64_u32_add_u64_shr
  20. static __always_inline u64 mul_u64_u32_add_u64_shr(u64 a, u32 mul, u64 b, unsigned int shift)
  21. {
  22. return (u64)((((unsigned __int128)a * mul) + b) >> shift);
  23. }
  24. #endif /* mul_u64_u32_add_u64_shr */
  25. #else
  26. #ifndef mul_u64_u32_add_u64_shr
  27. #ifndef mul_u32_u32
  28. static inline u64 mul_u32_u32(u32 a, u32 b)
  29. {
  30. return (u64)a * b;
  31. }
  32. #define mul_u32_u32 mul_u32_u32
  33. #endif
  34. static __always_inline u64 mul_u64_u32_add_u64_shr(u64 a, u32 mul, u64 b, unsigned int shift)
  35. {
  36. u32 ah = a >> 32, al = a;
  37. bool ovf;
  38. u64 ret;
  39. ovf = __builtin_add_overflow(mul_u32_u32(al, mul), b, &ret);
  40. ret >>= shift;
  41. if (ovf && shift)
  42. ret += 1ULL << (64 - shift);
  43. if (ah)
  44. ret += mul_u32_u32(ah, mul) << (32 - shift);
  45. return ret;
  46. }
  47. #endif /* mul_u64_u32_add_u64_shr */
  48. #endif
  49. #endif /* __VDSO_MATH64_H */