div64.h 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /*
  2. * Copyright (C) 2000, 2004 Maciej W. Rozycki
  3. * Copyright (C) 2003, 07 Ralf Baechle (ralf@linux-mips.org)
  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. #include <linux/types.h>
  12. #if (_MIPS_SZLONG == 32)
  13. #include <asm/compiler.h>
  14. /*
  15. * No traps on overflows for any of these...
  16. */
  17. #define do_div64_32(res, high, low, base) ({ \
  18. unsigned long __quot32, __mod32; \
  19. unsigned long __cf, __tmp, __tmp2, __i; \
  20. \
  21. __asm__(".set push\n\t" \
  22. ".set noat\n\t" \
  23. ".set noreorder\n\t" \
  24. "move %2, $0\n\t" \
  25. "move %3, $0\n\t" \
  26. "b 1f\n\t" \
  27. " li %4, 0x21\n" \
  28. "0:\n\t" \
  29. "sll $1, %0, 0x1\n\t" \
  30. "srl %3, %0, 0x1f\n\t" \
  31. "or %0, $1, %5\n\t" \
  32. "sll %1, %1, 0x1\n\t" \
  33. "sll %2, %2, 0x1\n" \
  34. "1:\n\t" \
  35. "bnez %3, 2f\n\t" \
  36. " sltu %5, %0, %z6\n\t" \
  37. "bnez %5, 3f\n" \
  38. "2:\n\t" \
  39. " addiu %4, %4, -1\n\t" \
  40. "subu %0, %0, %z6\n\t" \
  41. "addiu %2, %2, 1\n" \
  42. "3:\n\t" \
  43. "bnez %4, 0b\n\t" \
  44. " srl %5, %1, 0x1f\n\t" \
  45. ".set pop" \
  46. : "=&r" (__mod32), "=&r" (__tmp), \
  47. "=&r" (__quot32), "=&r" (__cf), \
  48. "=&r" (__i), "=&r" (__tmp2) \
  49. : "Jr" (base), "0" (high), "1" (low)); \
  50. \
  51. (res) = __quot32; \
  52. __mod32; })
  53. #define do_div(n, base) ({ \
  54. unsigned long long __quot; \
  55. unsigned long __mod; \
  56. unsigned long long __div; \
  57. unsigned long __upper, __low, __high, __base; \
  58. \
  59. __div = (n); \
  60. __base = (base); \
  61. \
  62. __high = __div >> 32; \
  63. __low = __div; \
  64. __upper = __high; \
  65. \
  66. if (__high) \
  67. __asm__("divu $0, %z2, %z3" \
  68. : "=h" (__upper), "=l" (__high) \
  69. : "Jr" (__high), "Jr" (__base) \
  70. : GCC_REG_ACCUM); \
  71. \
  72. __mod = do_div64_32(__low, __upper, __low, __base); \
  73. \
  74. __quot = __high; \
  75. __quot = __quot << 32 | __low; \
  76. (n) = __quot; \
  77. __mod; })
  78. #endif /* (_MIPS_SZLONG == 32) */
  79. #if (_MIPS_SZLONG == 64)
  80. /*
  81. * Hey, we're already 64-bit, no
  82. * need to play games..
  83. */
  84. #define do_div(n, base) ({ \
  85. unsigned long __quot; \
  86. unsigned int __mod; \
  87. unsigned long __div; \
  88. unsigned int __base; \
  89. \
  90. __div = (n); \
  91. __base = (base); \
  92. \
  93. __mod = __div % __base; \
  94. __quot = __div / __base; \
  95. \
  96. (n) = __quot; \
  97. __mod; })
  98. #endif /* (_MIPS_SZLONG == 64) */
  99. #endif /* _ASM_DIV64_H */