div64.h 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * Copyright (C) 2000, 2004 Maciej W. Rozycki
  3. * Copyright (C) 2003 Ralf Baechle
  4. *
  5. * This file is subject to the terms and conditions of the GNU General Public
  6. * License. See the file "COPYING" in the main directory of this archive
  7. * for more details.
  8. */
  9. #ifndef _ASM_DIV64_H
  10. #define _ASM_DIV64_H
  11. #if (_MIPS_SZLONG == 32)
  12. #include <asm/compiler.h>
  13. /*
  14. * No traps on overflows for any of these...
  15. */
  16. #define do_div64_32(res, high, low, base) ({ \
  17. unsigned long __quot, __mod; \
  18. unsigned long __cf, __tmp, __tmp2, __i; \
  19. \
  20. __asm__(".set push\n\t" \
  21. ".set noat\n\t" \
  22. ".set noreorder\n\t" \
  23. "move %2, $0\n\t" \
  24. "move %3, $0\n\t" \
  25. "b 1f\n\t" \
  26. " li %4, 0x21\n" \
  27. "0:\n\t" \
  28. "sll $1, %0, 0x1\n\t" \
  29. "srl %3, %0, 0x1f\n\t" \
  30. "or %0, $1, %5\n\t" \
  31. "sll %1, %1, 0x1\n\t" \
  32. "sll %2, %2, 0x1\n" \
  33. "1:\n\t" \
  34. "bnez %3, 2f\n\t" \
  35. " sltu %5, %0, %z6\n\t" \
  36. "bnez %5, 3f\n" \
  37. "2:\n\t" \
  38. " addiu %4, %4, -1\n\t" \
  39. "subu %0, %0, %z6\n\t" \
  40. "addiu %2, %2, 1\n" \
  41. "3:\n\t" \
  42. "bnez %4, 0b\n\t" \
  43. " srl %5, %1, 0x1f\n\t" \
  44. ".set pop" \
  45. : "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \
  46. "=&r" (__i), "=&r" (__tmp2) \
  47. : "Jr" (base), "0" (high), "1" (low)); \
  48. \
  49. (res) = __quot; \
  50. __mod; })
  51. #define do_div(n, base) ({ \
  52. unsigned long long __quot; \
  53. unsigned long __mod; \
  54. unsigned long long __div; \
  55. unsigned long __upper, __low, __high, __base; \
  56. \
  57. __div = (n); \
  58. __base = (base); \
  59. \
  60. __high = __div >> 32; \
  61. __low = __div; \
  62. __upper = __high; \
  63. \
  64. if (__high) \
  65. __asm__("divu $0, %z2, %z3" \
  66. : "=h" (__upper), "=l" (__high) \
  67. : "Jr" (__high), "Jr" (__base) \
  68. : GCC_REG_ACCUM); \
  69. \
  70. __mod = do_div64_32(__low, __upper, __low, __base); \
  71. \
  72. __quot = __high; \
  73. __quot = __quot << 32 | __low; \
  74. (n) = __quot; \
  75. __mod; })
  76. #endif /* (_MIPS_SZLONG == 32) */
  77. #if (_MIPS_SZLONG == 64)
  78. /*
  79. * Don't use this one in new code
  80. */
  81. #define do_div64_32(res, high, low, base) ({ \
  82. unsigned int __quot, __mod; \
  83. unsigned long __div; \
  84. unsigned int __low, __high, __base; \
  85. \
  86. __high = (high); \
  87. __low = (low); \
  88. __div = __high; \
  89. __div = __div << 32 | __low; \
  90. __base = (base); \
  91. \
  92. __mod = __div % __base; \
  93. __div = __div / __base; \
  94. \
  95. __quot = __div; \
  96. (res) = __quot; \
  97. __mod; })
  98. /*
  99. * Hey, we're already 64-bit, no
  100. * need to play games..
  101. */
  102. #define do_div(n, base) ({ \
  103. unsigned long __quot; \
  104. unsigned int __mod; \
  105. unsigned long __div; \
  106. unsigned int __base; \
  107. \
  108. __div = (n); \
  109. __base = (base); \
  110. \
  111. __mod = __div % __base; \
  112. __quot = __div / __base; \
  113. \
  114. (n) = __quot; \
  115. __mod; })
  116. #endif /* (_MIPS_SZLONG == 64) */
  117. #endif /* _ASM_DIV64_H */