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

数学计算

开发平台:

Unix_Linux

  1. dnl  Intel Pentium mpn_divexact_1 -- mpn by limb exact division.
  2. dnl  Copyright 2001, 2002 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 P54:  24.5  30.5   cycles/limb
  22. C P55:  23.0  28.0
  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 Plain divl is used for small sizes, since the inverse takes a while to
  27. C setup.  Multiplying works out faster for size>=3 when the divisor is odd,
  28. C or size>=4 when the divisor is even.  Actually on P55 size==2 for odd or
  29. C size==3 for even are about the same speed for both divl or mul, but the
  30. C former is used since it will use up less code cache.
  31. C
  32. C The P55 speeds noted above, 23 cycles odd or 28 cycles even, are as
  33. C expected.  On P54 in the even case the shrdl pairing nonsense (see
  34. C mpn/x86/pentium/README) costs 1 cycle, but it's not clear why there's a
  35. C further 1.5 slowdown for both odd and even.
  36. defframe(PARAM_DIVISOR,16)
  37. defframe(PARAM_SIZE,   12)
  38. defframe(PARAM_SRC,    8)
  39. defframe(PARAM_DST,    4)
  40. dnl  re-use parameter space
  41. define(VAR_INVERSE,`PARAM_DST')
  42. TEXT
  43. ALIGN(32)
  44. PROLOGUE(mpn_divexact_1)
  45. deflit(`FRAME',0)
  46. movl PARAM_DIVISOR, %eax
  47. movl PARAM_SIZE, %ecx
  48. pushl %esi FRAME_pushl()
  49. push %edi FRAME_pushl()
  50. movl PARAM_SRC, %esi
  51. andl $1, %eax
  52. movl PARAM_DST, %edi
  53. addl %ecx, %eax C size if even, size+1 if odd
  54. cmpl $4, %eax
  55. jae L(mul_by_inverse)
  56. xorl %edx, %edx
  57. L(div_top):
  58. movl -4(%esi,%ecx,4), %eax
  59. divl PARAM_DIVISOR
  60. movl %eax, -4(%edi,%ecx,4)
  61. decl %ecx
  62. jnz L(div_top)
  63. popl %edi
  64. popl %esi
  65. ret
  66. L(mul_by_inverse):
  67. movl PARAM_DIVISOR, %eax
  68. movl $-1, %ecx
  69. L(strip_twos):
  70. ASSERT(nz, `orl %eax, %eax')
  71. shrl %eax
  72. incl %ecx C shift count
  73. jnc L(strip_twos)
  74. leal 1(%eax,%eax), %edx C d
  75. andl $127, %eax C d/2, 7 bits
  76. pushl %ebx FRAME_pushl()
  77. pushl %ebp FRAME_pushl()
  78. ifdef(`PIC',`
  79. call L(here)
  80. L(here):
  81. popl %ebp C eip
  82. addl $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebp
  83. C AGI
  84. movl binvert_limb_table@GOT(%ebp), %ebp
  85. C AGI
  86. movzbl (%eax,%ebp), %eax
  87. ',`
  88. dnl non-PIC
  89. movzbl binvert_limb_table(%eax), %eax C inv 8 bits
  90. ')
  91. movl %eax, %ebp C inv
  92. addl %eax, %eax C 2*inv
  93. imull %ebp, %ebp C inv*inv
  94. imull %edx, %ebp C inv*inv*d
  95. subl %ebp, %eax C inv = 2*inv - inv*inv*d
  96. movl PARAM_SIZE, %ebx
  97. movl %eax, %ebp
  98. addl %eax, %eax C 2*inv
  99. imull %ebp, %ebp C inv*inv
  100. imull %edx, %ebp C inv*inv*d
  101. subl %ebp, %eax C inv = 2*inv - inv*inv*d
  102. movl %edx, PARAM_DIVISOR C d without twos
  103. leal (%esi,%ebx,4), %esi C src end
  104. leal (%edi,%ebx,4), %edi C dst end
  105. negl %ebx C -size
  106. ASSERT(e,` C expect d*inv == 1 mod 2^GMP_LIMB_BITS
  107. pushl %eax FRAME_pushl()
  108. imull PARAM_DIVISOR, %eax
  109. cmpl $1, %eax
  110. popl %eax FRAME_popl()')
  111. movl %eax, VAR_INVERSE
  112. xorl %ebp, %ebp C initial carry bit
  113. movl (%esi,%ebx,4), %eax C src low limb
  114. orl %ecx, %ecx C shift
  115. movl 4(%esi,%ebx,4), %edx C src second limb (for even)
  116. jz L(odd_entry)
  117. shrdl( %cl, %edx, %eax)
  118. incl %ebx
  119. jmp L(even_entry)
  120. ALIGN(8)
  121. L(odd_top):
  122. C eax scratch
  123. C ebx counter, limbs, negative
  124. C ecx
  125. C edx
  126. C esi src end
  127. C edi dst end
  128. C ebp carry bit, 0 or -1
  129. mull PARAM_DIVISOR
  130. movl (%esi,%ebx,4), %eax
  131. subl %ebp, %edx
  132. subl %edx, %eax
  133. sbbl %ebp, %ebp
  134. L(odd_entry):
  135. imull VAR_INVERSE, %eax
  136. movl %eax, (%edi,%ebx,4)
  137. incl %ebx
  138. jnz L(odd_top)
  139. popl %ebp
  140. popl %ebx
  141. popl %edi
  142. popl %esi
  143. ret
  144. L(even_top):
  145. C eax scratch
  146. C ebx counter, limbs, negative
  147. C ecx twos
  148. C edx
  149. C esi src end
  150. C edi dst end
  151. C ebp carry bit, 0 or -1
  152. mull PARAM_DIVISOR
  153. subl %ebp, %edx C carry bit
  154. movl -4(%esi,%ebx,4), %eax C src limb
  155. movl (%esi,%ebx,4), %ebp C and one above it
  156. shrdl( %cl, %ebp, %eax)
  157. subl %edx, %eax C carry limb
  158. sbbl %ebp, %ebp
  159. L(even_entry):
  160. imull VAR_INVERSE, %eax
  161. movl %eax, -4(%edi,%ebx,4)
  162. incl %ebx
  163. jnz L(even_top)
  164. mull PARAM_DIVISOR
  165. movl -4(%esi), %eax C src high limb
  166. subl %ebp, %edx
  167. shrl %cl, %eax
  168. subl %edx, %eax C no carry if division is exact
  169. imull VAR_INVERSE, %eax
  170. movl %eax, -4(%edi) C dst high limb
  171. nop C protect against cache bank clash
  172. popl %ebp
  173. popl %ebx
  174. popl %edi
  175. popl %esi
  176. ret
  177. EPILOGUE()