divide.S 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * arch/alpha/lib/divide.S
  4. *
  5. * (C) 1995 Linus Torvalds
  6. *
  7. * Alpha division..
  8. */
  9. /*
  10. * The alpha chip doesn't provide hardware division, so we have to do it
  11. * by hand. The compiler expects the functions
  12. *
  13. * __divqu: 64-bit unsigned long divide
  14. * __remqu: 64-bit unsigned long remainder
  15. * __divqs/__remqs: signed 64-bit
  16. * __divlu/__remlu: unsigned 32-bit
  17. * __divls/__remls: signed 32-bit
  18. *
  19. * These are not normal C functions: instead of the normal
  20. * calling sequence, these expect their arguments in registers
  21. * $24 and $25, and return the result in $27. Register $28 may
  22. * be clobbered (assembly temporary), anything else must be saved.
  23. *
  24. * In short: painful.
  25. *
  26. * This is a rather simple bit-at-a-time algorithm: it's very good
  27. * at dividing random 64-bit numbers, but the more usual case where
  28. * the divisor is small is handled better by the DEC algorithm
  29. * using lookup tables. This uses much less memory, though, and is
  30. * nicer on the cache.. Besides, I don't know the copyright status
  31. * of the DEC code.
  32. */
  33. /*
  34. * My temporaries:
  35. * $0 - current bit
  36. * $1 - shifted divisor
  37. * $2 - modulus/quotient
  38. *
  39. * $23 - return address
  40. * $24 - dividend
  41. * $25 - divisor
  42. *
  43. * $27 - quotient/modulus
  44. * $28 - compare status
  45. */
  46. #include <asm/export.h>
  47. #define halt .long 0
  48. /*
  49. * Select function type and registers
  50. */
  51. #define mask $0
  52. #define divisor $1
  53. #define compare $28
  54. #define tmp1 $3
  55. #define tmp2 $4
  56. #ifdef DIV
  57. #define DIV_ONLY(x,y...) x,##y
  58. #define MOD_ONLY(x,y...)
  59. #define func(x) __div##x
  60. #define modulus $2
  61. #define quotient $27
  62. #define GETSIGN(x) xor $24,$25,x
  63. #define STACK 48
  64. #else
  65. #define DIV_ONLY(x,y...)
  66. #define MOD_ONLY(x,y...) x,##y
  67. #define func(x) __rem##x
  68. #define modulus $27
  69. #define quotient $2
  70. #define GETSIGN(x) bis $24,$24,x
  71. #define STACK 32
  72. #endif
  73. /*
  74. * For 32-bit operations, we need to extend to 64-bit
  75. */
  76. #ifdef INTSIZE
  77. #define ufunction func(lu)
  78. #define sfunction func(l)
  79. #define LONGIFY(x) zapnot x,15,x
  80. #define SLONGIFY(x) addl x,0,x
  81. #else
  82. #define ufunction func(qu)
  83. #define sfunction func(q)
  84. #define LONGIFY(x)
  85. #define SLONGIFY(x)
  86. #endif
  87. .set noat
  88. .align 3
  89. .globl ufunction
  90. .ent ufunction
  91. ufunction:
  92. subq $30,STACK,$30
  93. .frame $30,STACK,$23
  94. .prologue 0
  95. 7: stq $1, 0($30)
  96. bis $25,$25,divisor
  97. stq $2, 8($30)
  98. bis $24,$24,modulus
  99. stq $0,16($30)
  100. bis $31,$31,quotient
  101. LONGIFY(divisor)
  102. stq tmp1,24($30)
  103. LONGIFY(modulus)
  104. bis $31,1,mask
  105. DIV_ONLY(stq tmp2,32($30))
  106. beq divisor, 9f /* div by zero */
  107. #ifdef INTSIZE
  108. /*
  109. * shift divisor left, using 3-bit shifts for
  110. * 32-bit divides as we can't overflow. Three-bit
  111. * shifts will result in looping three times less
  112. * here, but can result in two loops more later.
  113. * Thus using a large shift isn't worth it (and
  114. * s8add pairs better than a sll..)
  115. */
  116. 1: cmpult divisor,modulus,compare
  117. s8addq divisor,$31,divisor
  118. s8addq mask,$31,mask
  119. bne compare,1b
  120. #else
  121. 1: cmpult divisor,modulus,compare
  122. blt divisor, 2f
  123. addq divisor,divisor,divisor
  124. addq mask,mask,mask
  125. bne compare,1b
  126. unop
  127. #endif
  128. /* ok, start to go right again.. */
  129. 2: DIV_ONLY(addq quotient,mask,tmp2)
  130. srl mask,1,mask
  131. cmpule divisor,modulus,compare
  132. subq modulus,divisor,tmp1
  133. DIV_ONLY(cmovne compare,tmp2,quotient)
  134. srl divisor,1,divisor
  135. cmovne compare,tmp1,modulus
  136. bne mask,2b
  137. 9: ldq $1, 0($30)
  138. ldq $2, 8($30)
  139. ldq $0,16($30)
  140. ldq tmp1,24($30)
  141. DIV_ONLY(ldq tmp2,32($30))
  142. addq $30,STACK,$30
  143. ret $31,($23),1
  144. .end ufunction
  145. EXPORT_SYMBOL(ufunction)
  146. /*
  147. * Uhh.. Ugly signed division. I'd rather not have it at all, but
  148. * it's needed in some circumstances. There are different ways to
  149. * handle this, really. This does:
  150. * -a / b = a / -b = -(a / b)
  151. * -a % b = -(a % b)
  152. * a % -b = a % b
  153. * which is probably not the best solution, but at least should
  154. * have the property that (x/y)*y + (x%y) = x.
  155. */
  156. .align 3
  157. .globl sfunction
  158. .ent sfunction
  159. sfunction:
  160. subq $30,STACK,$30
  161. .frame $30,STACK,$23
  162. .prologue 0
  163. bis $24,$25,$28
  164. SLONGIFY($28)
  165. bge $28,7b
  166. stq $24,0($30)
  167. subq $31,$24,$28
  168. stq $25,8($30)
  169. cmovlt $24,$28,$24 /* abs($24) */
  170. stq $23,16($30)
  171. subq $31,$25,$28
  172. stq tmp1,24($30)
  173. cmovlt $25,$28,$25 /* abs($25) */
  174. unop
  175. bsr $23,ufunction
  176. ldq $24,0($30)
  177. ldq $25,8($30)
  178. GETSIGN($28)
  179. subq $31,$27,tmp1
  180. SLONGIFY($28)
  181. ldq $23,16($30)
  182. cmovlt $28,tmp1,$27
  183. ldq tmp1,24($30)
  184. addq $30,STACK,$30
  185. ret $31,($23),1
  186. .end sfunction
  187. EXPORT_SYMBOL(sfunction)