dive_1.asm
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:5k
源码类别:

数学计算

开发平台:

Unix_Linux

  1. dnl  AMD K6 mpn_divexact_1 -- mpn by limb exact division.
  2. dnl  Copyright 2000, 2001, 2002, 2007 Free Software Foundation, Inc.
  3. dnl
  4. dnl  This file is part of the GNU MP Library.
  5. dnl
  6. dnl  The GNU MP Library is free software; you can redistribute it and/or
  7. dnl  modify it under the terms of the GNU Lesser General Public License as
  8. dnl  published by the Free Software Foundation; either version 3 of the
  9. dnl  License, or (at your option) any later version.
  10. dnl
  11. dnl  The GNU MP Library is distributed in the hope that it will be useful,
  12. dnl  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14. dnl  Lesser General Public License for more details.
  15. dnl
  16. dnl  You should have received a copy of the GNU Lesser General Public License
  17. dnl  along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.
  18. include(`../config.m4')
  19. C         divisor
  20. C       odd   even
  21. C K6:   10.0  12.0  cycles/limb
  22. C K6-2: 10.0  11.5
  23. C void mpn_divexact_1 (mp_ptr dst, mp_srcptr src, mp_size_t size,
  24. C                      mp_limb_t divisor);
  25. C
  26. C A simple divl is used for size==1.  This is about 10 cycles faster for an
  27. C odd divisor or 20 cycles for an even divisor.
  28. C
  29. C The loops are quite sensitive to code alignment, speeds should be
  30. C rechecked (odd and even divisor, pic and non-pic) if contemplating
  31. C changing anything.
  32. defframe(PARAM_DIVISOR,16)
  33. defframe(PARAM_SIZE,   12)
  34. defframe(PARAM_SRC,    8)
  35. defframe(PARAM_DST,    4)
  36. dnl  re-use parameter space
  37. define(VAR_INVERSE,`PARAM_DST')
  38. TEXT
  39. ALIGN(32)
  40. PROLOGUE(mpn_divexact_1)
  41. deflit(`FRAME',0)
  42. movl PARAM_SIZE, %ecx
  43. movl PARAM_SRC, %eax
  44. xorl %edx, %edx
  45. cmpl $1, %ecx
  46. jnz L(two_or_more)
  47. movl (%eax), %eax
  48. divl PARAM_DIVISOR
  49. movl PARAM_DST, %ecx
  50. movl %eax, (%ecx)
  51. ret
  52. L(two_or_more):
  53. movl PARAM_DIVISOR, %eax
  54. pushl %ebx FRAME_pushl()
  55. movl PARAM_SRC, %ebx
  56. pushl %ebp FRAME_pushl()
  57. L(strip_twos):
  58. shrl %eax
  59. incl %edx C will get shift+1
  60. jnc L(strip_twos)
  61. pushl %esi FRAME_pushl()
  62. leal 1(%eax,%eax), %esi C d without twos
  63. andl $127, %eax C d/2, 7 bits
  64. ifdef(`PIC',`
  65. LEA( binvert_limb_table, %ebp)
  66. Zdisp( movzbl, 0,(%eax,%ebp), %eax)
  67. ',`
  68. movzbl binvert_limb_table(%eax), %eax C inv 8 bits
  69. ')
  70. pushl %edi FRAME_pushl()
  71. leal (%eax,%eax), %ebp C 2*inv
  72. imull %eax, %eax C inv*inv
  73. movl PARAM_DST, %edi
  74. imull %esi, %eax C inv*inv*d
  75. subl %eax, %ebp C inv = 2*inv - inv*inv*d
  76. leal (%ebp,%ebp), %eax C 2*inv
  77. imull %ebp, %ebp C inv*inv
  78. movl %esi, PARAM_DIVISOR C d without twos
  79. leal (%ebx,%ecx,4), %ebx C src end
  80. imull %esi, %ebp C inv*inv*d
  81. leal (%edi,%ecx,4), %edi C dst end
  82. negl %ecx C -size
  83. subl %ebp, %eax C inv = 2*inv - inv*inv*d
  84. subl $1, %edx C shift amount, and clear carry
  85. ASSERT(e,` C expect d*inv == 1 mod 2^GMP_LIMB_BITS
  86. pushl %eax FRAME_pushl()
  87. imull PARAM_DIVISOR, %eax
  88. cmpl $1, %eax
  89. popl %eax FRAME_popl()')
  90. movl %eax, VAR_INVERSE
  91. jnz L(even)
  92. movl (%ebx,%ecx,4), %esi C src low limb
  93. jmp L(odd_entry)
  94. ALIGN(16)
  95. nop C code alignment
  96. L(odd_top):
  97. C eax scratch
  98. C ebx src end
  99. C ecx counter, limbs, negative
  100. C edx inverse
  101. C esi next limb, adjusted for carry
  102. C edi dst end
  103. C ebp carry bit, 0 or -1
  104. imull %edx, %esi
  105. movl PARAM_DIVISOR, %eax
  106. movl %esi, -4(%edi,%ecx,4)
  107. mull %esi C carry limb in edx
  108. subl %ebp, %edx C apply carry bit
  109. movl (%ebx,%ecx,4), %esi
  110. L(odd_entry):
  111. subl %edx, %esi C apply carry limb
  112. movl VAR_INVERSE, %edx
  113. sbbl %ebp, %ebp C 0 or -1
  114. incl %ecx
  115. jnz L(odd_top)
  116. imull %edx, %esi
  117. movl %esi, -4(%edi,%ecx,4)
  118. popl %edi
  119. popl %esi
  120. popl %ebp
  121. popl %ebx
  122. ret
  123. L(even):
  124. C eax
  125. C ebx src end
  126. C ecx -size
  127. C edx twos
  128. C esi
  129. C edi dst end
  130. C ebp
  131. xorl %ebp, %ebp
  132. Zdisp( movq, 0,(%ebx,%ecx,4), %mm0) C src[0,1]
  133. movd %edx, %mm7
  134. movl VAR_INVERSE, %edx
  135. addl $2, %ecx
  136. psrlq %mm7, %mm0
  137. movd %mm0, %esi
  138. jz L(even_two) C if only two limbs
  139. C Out-of-order execution is good enough to hide the load/rshift/movd
  140. C latency.  Having imul at the top of the loop gives 11.5 c/l instead of 12,
  141. C on K6-2.  In fact there's only 11 of decode, but nothing running at 11 has
  142. C been found.  Maybe the fact every second movq is unaligned costs the extra
  143. C 0.5.
  144. L(even_top):
  145. C eax scratch
  146. C ebx src end
  147. C ecx counter, limbs, negative
  148. C edx inverse
  149. C esi next limb, adjusted for carry
  150. C edi dst end
  151. C ebp carry bit, 0 or -1
  152. C
  153. C mm0 scratch, source limbs
  154. C mm7 twos
  155. imull %edx, %esi
  156. movl %esi, -8(%edi,%ecx,4)
  157. movl PARAM_DIVISOR, %eax
  158. mull %esi C carry limb in edx
  159. movq -4(%ebx,%ecx,4), %mm0
  160. psrlq %mm7, %mm0
  161. movd %mm0, %esi
  162. subl %ebp, %edx C apply carry bit
  163. subl %edx, %esi C apply carry limb
  164. movl VAR_INVERSE, %edx
  165. sbbl %ebp, %ebp C 0 or -1
  166. incl %ecx
  167. jnz L(even_top)
  168. L(even_two):
  169. movd -4(%ebx), %mm0 C src high limb
  170. psrlq %mm7, %mm0
  171. imull %edx, %esi
  172. movl %esi, -8(%edi)
  173. movl PARAM_DIVISOR, %eax
  174. mull %esi C carry limb in edx
  175. movd %mm0, %esi
  176. subl %ebp, %edx C apply carry bit
  177. movl VAR_INVERSE, %eax
  178. subl %edx, %esi C apply carry limb
  179. imull %eax, %esi
  180. movl %esi, -4(%edi)
  181. popl %edi
  182. popl %esi
  183. popl %ebp
  184. popl %ebx
  185. emms_or_femms
  186. ret
  187. EPILOGUE()