divide.S 3.4 KB

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