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

数学计算

开发平台:

Unix_Linux

  1. dnl  Intel Pentium-4 mpn_divexact_1 -- mpn by limb exact division.
  2. dnl  Copyright 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 P4: 19.0 cycles/limb
  20. C void mpn_divexact_1 (mp_ptr dst, mp_srcptr src, mp_size_t size,
  21. C                      mp_limb_t divisor);
  22. C
  23. C Pairs of movd's are used to avoid unaligned loads.  Despite the loads not
  24. C being on the dependent chain and there being plenty of cycles available,
  25. C using an unaligned movq on every second iteration measured about 23 c/l.
  26. C
  27. C Using divl for size==1 seems a touch quicker than mul-by-inverse.  The mul
  28. C will be about 9+2*4+2*2+10*4+19+12 = 92 cycles latency, though some of
  29. C that might be hidden by out-of-order execution, whereas divl is around 60.
  30. C At size==2 an extra 19 for the mul versus 60 for the divl will see the mul
  31. C faster.
  32. defframe(PARAM_DIVISOR,16)
  33. defframe(PARAM_SIZE,   12)
  34. defframe(PARAM_SRC,    8)
  35. defframe(PARAM_DST,    4)
  36. TEXT
  37. ALIGN(16)
  38. PROLOGUE(mpn_divexact_1)
  39. deflit(`FRAME',0)
  40. movl PARAM_SIZE, %edx
  41. movl PARAM_SRC, %eax
  42. movl PARAM_DIVISOR, %ecx
  43. subl $1, %edx
  44. jnz L(two_or_more)
  45. movl (%eax), %eax
  46. xorl %edx, %edx
  47. divl %ecx
  48. movl PARAM_DST, %ecx
  49. movl %eax, (%ecx)
  50. ret
  51. L(two_or_more):
  52. C eax src
  53. C ebx
  54. C ecx divisor
  55. C edx size-1
  56. movl %ecx, %eax
  57. bsfl %ecx, %ecx C trailing twos
  58. shrl %cl, %eax C d = divisor without twos
  59. movd %eax, %mm6
  60. movd %ecx, %mm7 C shift
  61. shrl %eax C d/2
  62. andl $127, %eax C d/2, 7 bits
  63. ifdef(`PIC',`
  64. LEA( binvert_limb_table, %ecx)
  65. movzbl (%eax,%ecx), %eax C inv 8 bits
  66. ',`
  67. movzbl binvert_limb_table(%eax), %eax C inv 8 bits
  68. ')
  69. C
  70. movd %eax, %mm5 C inv
  71. movd %eax, %mm0 C inv
  72. pmuludq %mm5, %mm5 C inv*inv
  73. C
  74. pmuludq %mm6, %mm5 C inv*inv*d
  75. paddd %mm0, %mm0 C 2*inv
  76. C
  77. psubd %mm5, %mm0 C inv = 2*inv - inv*inv*d
  78. pxor %mm5, %mm5
  79. paddd %mm0, %mm5
  80. pmuludq %mm0, %mm0 C inv*inv
  81. pcmpeqd %mm4, %mm4
  82. psrlq $32, %mm4 C 0x00000000FFFFFFFF
  83. C
  84. pmuludq %mm6, %mm0 C inv*inv*d
  85. paddd %mm5, %mm5 C 2*inv
  86. movl PARAM_SRC, %eax
  87. movl PARAM_DST, %ecx
  88. pxor %mm1, %mm1 C initial carry limb
  89. C
  90. psubd %mm0, %mm5 C inv = 2*inv - inv*inv*d
  91. ASSERT(e,` C expect d*inv == 1 mod 2^GMP_LIMB_BITS
  92. pushl %eax FRAME_pushl()
  93. movq %mm6, %mm0
  94. pmuludq %mm5, %mm0
  95. movd %mm0, %eax
  96. cmpl $1, %eax
  97. popl %eax FRAME_popl()')
  98. pxor %mm0, %mm0 C initial carry bit
  99. C The dependent chain here is as follows.
  100. C
  101. C         latency
  102. C psubq  s = (src-cbit) - climb    2
  103. C pmuludq  q = s*inverse             8
  104. C pmuludq  prod = q*divisor          8
  105. C psrlq  climb = high(prod)        2
  106. C                                   --
  107. C                                   20
  108. C
  109. C Yet the loop measures 19.0 c/l, so obviously there's something gained
  110. C there over a straight reading of the chip documentation.
  111. L(top):
  112. C eax src, incrementing
  113. C ebx
  114. C ecx dst, incrementing
  115. C edx counter, size-1 iterations
  116. C
  117. C mm0 carry bit
  118. C mm1 carry limb
  119. C mm4 0x00000000FFFFFFFF
  120. C mm5 inverse
  121. C mm6 divisor
  122. C mm7 shift
  123. movd (%eax), %mm2
  124. movd 4(%eax), %mm3
  125. addl $4, %eax
  126. punpckldq %mm3, %mm2
  127. psrlq %mm7, %mm2
  128. pand %mm4, %mm2 C src
  129. psubq %mm0, %mm2 C src - cbit
  130. psubq %mm1, %mm2 C src - cbit - climb
  131. movq %mm2, %mm0
  132. psrlq $63, %mm0 C new cbit
  133. pmuludq %mm5, %mm2 C s*inverse
  134. movd %mm2, (%ecx) C q
  135. addl $4, %ecx
  136. movq %mm6, %mm1
  137. pmuludq %mm2, %mm1 C q*divisor
  138. psrlq $32, %mm1 C new climb
  139. subl $1, %edx
  140. jnz L(top)
  141. L(done):
  142. movd (%eax), %mm2
  143. psrlq %mm7, %mm2 C src
  144. psubq %mm0, %mm2 C src - cbit
  145. psubq %mm1, %mm2 C src - cbit - climb
  146. pmuludq %mm5, %mm2 C s*inverse
  147. movd %mm2, (%ecx) C q
  148. emms
  149. ret
  150. EPILOGUE()