divide.S
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:4k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  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. #define tmp1 $3
  53. #define tmp2 $4
  54. #ifdef DIV
  55. #define DIV_ONLY(x,y...) x,##y
  56. #define MOD_ONLY(x,y...)
  57. #define func(x) __div##x
  58. #define modulus $2
  59. #define quotient $27
  60. #define GETSIGN(x) xor $24,$25,x
  61. #define STACK 48
  62. #else
  63. #define DIV_ONLY(x,y...)
  64. #define MOD_ONLY(x,y...) x,##y
  65. #define func(x) __rem##x
  66. #define modulus $27
  67. #define quotient $2
  68. #define GETSIGN(x) bis $24,$24,x
  69. #define STACK 32
  70. #endif
  71. /*
  72.  * For 32-bit operations, we need to extend to 64-bit
  73.  */
  74. #ifdef INTSIZE
  75. #define ufunction func(lu)
  76. #define sfunction func(l)
  77. #define LONGIFY(x) zapnot x,15,x
  78. #define SLONGIFY(x) addl x,0,x
  79. #else
  80. #define ufunction func(qu)
  81. #define sfunction func(q)
  82. #define LONGIFY(x)
  83. #define SLONGIFY(x)
  84. #endif
  85. .set noat
  86. .align 3
  87. .globl ufunction
  88. .ent ufunction
  89. ufunction:
  90. subq $30,STACK,$30
  91. .frame $30,STACK,$23
  92. .prologue 0
  93. 7: stq $1, 0($30)
  94. bis $25,$25,divisor
  95. stq $2, 8($30)
  96. bis $24,$24,modulus
  97. stq $0,16($30)
  98. bis $31,$31,quotient
  99. LONGIFY(divisor)
  100. stq tmp1,24($30)
  101. LONGIFY(modulus)
  102. bis $31,1,mask
  103. DIV_ONLY(stq tmp2,32($30))
  104. beq divisor, 9f /* div by zero */
  105. #ifdef INTSIZE
  106. /*
  107.  * shift divisor left, using 3-bit shifts for
  108.  * 32-bit divides as we can't overflow. Three-bit
  109.  * shifts will result in looping three times less
  110.  * here, but can result in two loops more later.
  111.  * Thus using a large shift isn't worth it (and
  112.  * s8add pairs better than a sll..)
  113.  */
  114. 1: cmpult divisor,modulus,compare
  115. s8addq divisor,$31,divisor
  116. s8addq mask,$31,mask
  117. bne compare,1b
  118. #else
  119. 1: cmpult divisor,modulus,compare
  120. blt     divisor, 2f
  121. addq divisor,divisor,divisor
  122. addq mask,mask,mask
  123. bne compare,1b
  124. unop
  125. #endif
  126. /* ok, start to go right again.. */
  127. 2: DIV_ONLY(addq quotient,mask,tmp2)
  128. srl mask,1,mask
  129. cmpule divisor,modulus,compare
  130. subq modulus,divisor,tmp1
  131. DIV_ONLY(cmovne compare,tmp2,quotient)
  132. srl divisor,1,divisor
  133. cmovne compare,tmp1,modulus
  134. bne mask,2b
  135. 9: ldq $1, 0($30)
  136. ldq $2, 8($30)
  137. ldq $0,16($30)
  138. ldq tmp1,24($30)
  139. DIV_ONLY(ldq tmp2,32($30))
  140. addq $30,STACK,$30
  141. ret $31,($23),1
  142. .end ufunction
  143. /*
  144.  * Uhh.. Ugly signed division. I'd rather not have it at all, but
  145.  * it's needed in some circumstances. There are different ways to
  146.  * handle this, really. This does:
  147.  *  -a / b = a / -b = -(a / b)
  148.  * -a % b = -(a % b)
  149.  * a % -b = a % b
  150.  * which is probably not the best solution, but at least should
  151.  * have the property that (x/y)*y + (x%y) = x.
  152.  */
  153. .align 3
  154. .globl sfunction
  155. .ent sfunction
  156. sfunction:
  157. subq $30,STACK,$30
  158. .frame $30,STACK,$23
  159. .prologue 0
  160. bis $24,$25,$28
  161. SLONGIFY($28)
  162. bge $28,7b
  163. stq $24,0($30)
  164. subq $31,$24,$28
  165. stq $25,8($30)
  166. cmovlt $24,$28,$24 /* abs($24) */
  167. stq $23,16($30)
  168. subq $31,$25,$28
  169. stq tmp1,24($30)
  170. cmovlt $25,$28,$25 /* abs($25) */
  171. unop
  172. bsr $23,ufunction
  173. ldq $24,0($30)
  174. ldq $25,8($30)
  175. GETSIGN($28)
  176. subq $31,$27,tmp1
  177. SLONGIFY($28)
  178. ldq $23,16($30)
  179. cmovlt $28,tmp1,$27
  180. ldq tmp1,24($30)
  181. addq $30,STACK,$30
  182. ret $31,($23),1
  183. .end sfunction