divrem.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
  2. Contributed by David Mosberger (davidm@cs.arizona.edu).
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, write to the Free
  14. Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  15. 02111-1307 USA. */
  16. /* The current Alpha chips don't provide hardware for integer
  17. division. The C compiler expects the functions
  18. __divqu: 64-bit unsigned long divide
  19. __remqu: 64-bit unsigned long remainder
  20. __divqs/__remqs: signed 64-bit
  21. __divlu/__remlu: unsigned 32-bit
  22. __divls/__remls: signed 32-bit
  23. These are not normal C functions: instead of the normal calling
  24. sequence, these expect their arguments in registers t10 and t11, and
  25. return the result in t12 (aka pv). Register AT may be clobbered
  26. (assembly temporary), anything else must be saved. */
  27. #include <features.h>
  28. #ifdef __linux__
  29. # include <asm/gentrap.h>
  30. # include <asm/pal.h>
  31. #else
  32. # include <machine/pal.h>
  33. #endif
  34. #define mask v0
  35. #define divisor t0
  36. #define compare AT
  37. #define tmp1 t2
  38. #define tmp2 t3
  39. #define retaddr t9
  40. #define arg1 t10
  41. #define arg2 t11
  42. #define result t12
  43. #define v0 $0 /* function return value */
  44. #define t0 $1 /* temporary registers (caller-saved) */
  45. #define t1 $2
  46. #define t2 $3
  47. #define t3 $4
  48. #define t4 $5
  49. #define t5 $6
  50. #define t6 $7
  51. #define t7 $8
  52. #define s0 $9 /* saved-registers (callee-saved registers) */
  53. #define s1 $10
  54. #define s2 $11
  55. #define s3 $12
  56. #define s4 $13
  57. #define s5 $14
  58. #define s6 $15
  59. #define fp s6 /* frame-pointer (s6 in frame-less procedures) */
  60. #define a0 $16 /* argument registers (caller-saved) */
  61. #define a1 $17
  62. #define a2 $18
  63. #define a3 $19
  64. #define a4 $20
  65. #define a5 $21
  66. #define t8 $22 /* more temps (caller-saved) */
  67. #define t9 $23
  68. #define t10 $24
  69. #define t11 $25
  70. #define ra $26 /* return address register */
  71. #define t12 $27
  72. #define pv t12 /* procedure-variable register */
  73. #define AT $at /* assembler temporary */
  74. #define gp $29 /* global pointer */
  75. #define sp $30 /* stack pointer */
  76. #define zero $31 /* reads as zero, writes are noops */
  77. #if IS_REM
  78. # define DIV_ONLY(x,y...)
  79. # define REM_ONLY(x,y...) x,##y
  80. # define modulus result
  81. # define quotient t1
  82. # define GETSIGN(x) mov arg1, x
  83. # define STACK 32
  84. #else
  85. # define DIV_ONLY(x,y...) x,##y
  86. # define REM_ONLY(x,y...)
  87. # define modulus t1
  88. # define quotient result
  89. # define GETSIGN(x) xor arg1, arg2, x
  90. # define STACK 48
  91. #endif
  92. #if SIZE == 8
  93. # define LONGIFY(x,y) mov x,y
  94. # define SLONGIFY(x,y) mov x,y
  95. # define _SLONGIFY(x)
  96. # define NEG(x,y) negq x,y
  97. #else
  98. # define LONGIFY(x,y) zapnot x,15,y
  99. # define SLONGIFY(x,y) sextl x,y
  100. # define _SLONGIFY(x) sextl x,x
  101. # define NEG(x,y) negl x,y
  102. #endif
  103. .set noreorder
  104. .set noat
  105. .ent UFUNC_NAME
  106. .globl UFUNC_NAME
  107. .align 3
  108. UFUNC_NAME:
  109. lda sp, -STACK(sp)
  110. .frame sp, STACK, retaddr, 0
  111. #ifdef PROF
  112. stq ra, 0(sp)
  113. stq pv, 8(sp)
  114. stq gp, 16(sp)
  115. br AT, 1f
  116. 1: ldgp gp, 0(AT)
  117. mov retaddr, ra
  118. lda AT, _mcount
  119. jsr AT, (AT), _mcount
  120. ldq ra, 0(sp)
  121. ldq pv, 8(sp)
  122. ldq gp, 16(sp)
  123. #endif
  124. .prologue 0
  125. $udiv:
  126. stq t0, 0(sp)
  127. LONGIFY (arg2, divisor)
  128. stq t1, 8(sp)
  129. LONGIFY (arg1, modulus)
  130. stq v0, 16(sp)
  131. clr quotient
  132. stq tmp1, 24(sp)
  133. ldiq mask, 1
  134. DIV_ONLY(stq tmp2,32(sp))
  135. beq divisor, $divbyzero
  136. .align 3
  137. #if SIZE == 8
  138. /* Shift divisor left. */
  139. 1: cmpult divisor, modulus, compare
  140. blt divisor, 2f
  141. addq divisor, divisor, divisor
  142. addq mask, mask, mask
  143. bne compare, 1b
  144. unop
  145. 2:
  146. #else
  147. /* Shift divisor left using 3-bit shifts as we can't overflow.
  148. This results in looping three times less here, but up to
  149. two more times later. Thus using a large shift isn't worth it. */
  150. 1: cmpult divisor, modulus, compare
  151. s8addq divisor, zero, divisor
  152. s8addq mask, zero, mask
  153. bne compare, 1b
  154. #endif
  155. /* Now go back to the right. */
  156. 3: DIV_ONLY(addq quotient, mask, tmp2)
  157. srl mask, 1, mask
  158. cmpule divisor, modulus, compare
  159. subq modulus, divisor, tmp1
  160. DIV_ONLY(cmovne compare, tmp2, quotient)
  161. srl divisor, 1, divisor
  162. cmovne compare, tmp1, modulus
  163. bne mask, 3b
  164. $done: ldq t0, 0(sp)
  165. ldq t1, 8(sp)
  166. ldq v0, 16(sp)
  167. ldq tmp1, 24(sp)
  168. DIV_ONLY(ldq tmp2, 32(sp))
  169. lda sp, STACK(sp)
  170. ret zero, (retaddr), 1
  171. $divbyzero:
  172. mov a0, tmp1
  173. ldiq a0, GEN_INTDIV
  174. call_pal PAL_gentrap
  175. mov tmp1, a0
  176. clr result /* If trap returns, return zero. */
  177. br $done
  178. .end UFUNC_NAME
  179. .ent SFUNC_NAME
  180. .globl SFUNC_NAME
  181. .align 3
  182. SFUNC_NAME:
  183. lda sp, -STACK(sp)
  184. .frame sp, STACK, retaddr, 0
  185. #ifdef PROF
  186. stq ra, 0(sp)
  187. stq pv, 8(sp)
  188. stq gp, 16(sp)
  189. br AT, 1f
  190. 1: ldgp gp, 0(AT)
  191. mov retaddr, ra
  192. jsr AT, _mcount
  193. ldq ra, 0(sp)
  194. ldq pv, 8(sp)
  195. ldq gp, 16(sp)
  196. #endif
  197. .prologue 0
  198. or arg1, arg2, AT
  199. _SLONGIFY(AT)
  200. bge AT, $udiv /* don't need to mess with signs */
  201. /* Save originals and find absolute values. */
  202. stq arg1, 0(sp)
  203. NEG (arg1, AT)
  204. stq arg2, 8(sp)
  205. cmovge AT, AT, arg1
  206. stq retaddr, 16(sp)
  207. NEG (arg2, AT)
  208. stq tmp1, 24(sp)
  209. cmovge AT, AT, arg2
  210. /* Do the unsigned division. */
  211. bsr retaddr, UFUNC_NAME
  212. /* Restore originals and adjust the sign of the result. */
  213. ldq arg1, 0(sp)
  214. ldq arg2, 8(sp)
  215. GETSIGN (AT)
  216. NEG (result, tmp1)
  217. _SLONGIFY(AT)
  218. ldq retaddr, 16(sp)
  219. cmovlt AT, tmp1, result
  220. ldq tmp1, 24(sp)
  221. lda sp, STACK(sp)
  222. ret zero, (retaddr), 1
  223. .end SFUNC_NAME