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

数学计算

开发平台:

Unix_Linux

  1. dnl  X86-32 and X86-64 mpn_popcount using SSE2.
  2. dnl  Copyright 2006, 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 modify
  7. dnl  it under the terms of the GNU Lesser General Public License as published
  8. dnl  by the Free Software Foundation; either version 3 of the License, or (at
  9. dnl  your option) any later version.
  10. dnl
  11. dnl  The GNU MP Library is distributed in the hope that it will be useful, but
  12. dnl  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  13. dnl  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
  14. dnl  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 32-bit                     popcount        hamdist
  20. C                           cycles/limb     cycles/limb
  21. C P5:                           -
  22. C P6 model 0-8,10-12)           -
  23. C P6 model 9  (Banias)          ?
  24. C P6 model 13 (Dothan)          4
  25. C P4 model 0  (Willamette)      ?
  26. C P4 model 1  (?)               ?
  27. C P4 model 2  (Northwood)       3.9
  28. C P4 model 3  (Prescott)        ?
  29. C P4 model 4  (Nocona)          ?
  30. C K6:                           -
  31. C K7:                           -
  32. C K8:                           ?
  33. C 64-bit                     popcount        hamdist
  34. C                           cycles/limb     cycles/limb
  35. C P4 model 4 (Nocona):          8
  36. C K8:                           7.5
  37. C K10: 3.5
  38. C P6 core2: 3.68
  39. C P6 corei7: 3.15
  40. C TODO
  41. C  * Make a mpn_hamdist based on this.  Alignment could either be handled by
  42. C    using movdqu for one operand and movdqa for the other, or by painfully
  43. C    shifting as we go.  Unfortunately, there seem to be no useable shift
  44. C    instruction, except for one that takes an immediate count.
  45. C  * It would probably be possible to cut a few cycles/limb using software
  46. C    pipelining.
  47. C  * There are 35 decode slots unused by the SSE2 instructions.  Loop control
  48. C    needs just 2 or 3 slots, leaving around 32 slots.  This allows a parallel
  49. C    integer based popcount.  Such a combined loop would handle 6 limbs in
  50. C    about 30 cycles on K8.
  51. C  * We could save a byte or two by using 32-bit operations on areg.
  52. C  * Check if using movdqa to a temp of and then register-based pand is faster.
  53. ifelse(GMP_LIMB_BITS,`32',
  54. ` define(`up',  `%edx')
  55. define(`n',   `%ecx')
  56. define(`areg',`%eax')
  57. define(`breg',`%ebx')
  58. define(`zero',`%xmm4')
  59. define(`LIMB32',` $1')
  60. define(`LIMB64',`dnl')
  61. ',`
  62. define(`up',  `%rdi')
  63. define(`n',   `%rsi')
  64. define(`areg',`%rax')
  65. define(`breg',`%rdx')
  66. define(`zero',`%xmm8')
  67. define(`LIMB32',`dnl')
  68. define(`LIMB64',` $1')
  69. ')
  70. define(`mm01010101',`%xmm6')
  71. define(`mm00110011',`%xmm7')
  72. define(`mm00001111',`%xmm2')
  73. define(`GMP_LIMB_BYTES', eval(GMP_LIMB_BITS/8))
  74. define(`LIMBS_PER_XMM',  eval(16/GMP_LIMB_BYTES))
  75. define(`LIMBS_PER_2XMM', eval(32/GMP_LIMB_BYTES))
  76. undefine(`psadbw') C override inherited m4 version
  77. ASM_START()
  78. C Make cnsts global to work around Apple relocation bug.
  79. ifdef(`DARWIN',`
  80. define(`cnsts', MPN(popccnsts))
  81. GLOBL cnsts')
  82. TEXT
  83. ALIGN(32)
  84. PROLOGUE(mpn_popcount)
  85. LIMB32(`mov 4(%esp), up ')
  86. LIMB32(`mov 8(%esp), n ')
  87. LIMB32(`push %ebx ')
  88. pxor %xmm3, %xmm3 C zero grand total count
  89. LIMB64(`pxor zero, zero ')
  90. ifdef(`PIC',`
  91. LEA( cnsts, breg)
  92. ',`
  93. LIMB32(`mov $cnsts, breg ')
  94. LIMB64(`movabs $cnsts, breg ')
  95. ')
  96. movdqa -48(breg), mm01010101
  97. movdqa -32(breg), mm00110011
  98. movdqa -16(breg), mm00001111
  99. mov up, areg
  100. and $-16, up C round `up' down to 128-bit boundary
  101. and $12, areg C 32:areg = 0, 4, 8, 12
  102. C 64:areg = 0, 8
  103. movdqa (up), %xmm0
  104. pand 64(breg,areg,4), %xmm0
  105. shr $m4_log2(GMP_LIMB_BYTES), %eax
  106. add areg, n C compensate n for rounded down `up'
  107. pxor %xmm4, %xmm4
  108. sub $LIMBS_PER_XMM, n
  109. jbe L(sum)
  110. sub $LIMBS_PER_XMM, n
  111. ja L(ent)
  112. jmp L(lsum)
  113. ALIGN(16)
  114. L(top): movdqa (up), %xmm0
  115. L(ent): movdqa 16(up), %xmm4
  116. movdqa %xmm0, %xmm1
  117. movdqa %xmm4, %xmm5
  118. psrld $1, %xmm0
  119. psrld $1, %xmm4
  120. pand mm01010101, %xmm0
  121. pand mm01010101, %xmm4
  122. psubd %xmm0, %xmm1
  123. psubd %xmm4, %xmm5
  124. movdqa %xmm1, %xmm0
  125. movdqa %xmm5, %xmm4
  126. psrlq $2, %xmm1
  127. psrlq $2, %xmm5
  128. pand mm00110011, %xmm0
  129. pand mm00110011, %xmm4
  130. pand mm00110011, %xmm1
  131. pand mm00110011, %xmm5
  132. paddq %xmm0, %xmm1
  133. paddq %xmm4, %xmm5
  134. LIMB32(`pxor zero, zero ')
  135. add $32, up
  136. sub $LIMBS_PER_2XMM, n
  137. paddq %xmm5, %xmm1
  138. movdqa %xmm1, %xmm0
  139. psrlq $4, %xmm1
  140. pand mm00001111, %xmm0
  141. pand mm00001111, %xmm1
  142. paddq %xmm0, %xmm1
  143. psadbw zero, %xmm1
  144. paddq %xmm1, %xmm3 C add to grand total
  145. jnc L(top)
  146. L(end):
  147. add $LIMBS_PER_2XMM, n
  148. jz L(rt)
  149. movdqa (up), %xmm0
  150. pxor %xmm4, %xmm4
  151. sub $LIMBS_PER_XMM, n
  152. jbe L(sum)
  153. L(lsum):
  154. movdqa %xmm0, %xmm4
  155. movdqa 16(up), %xmm0
  156. L(sum):
  157. shl $m4_log2(GMP_LIMB_BYTES), n
  158. and $12, n
  159. pand (breg,n,4), %xmm0
  160. movdqa %xmm0, %xmm1
  161. movdqa %xmm4, %xmm5
  162. psrld $1, %xmm0
  163. psrld $1, %xmm4
  164. pand mm01010101, %xmm0
  165. pand mm01010101, %xmm4
  166. psubd %xmm0, %xmm1
  167. psubd %xmm4, %xmm5
  168. movdqa %xmm1, %xmm0
  169. movdqa %xmm5, %xmm4
  170. psrlq $2, %xmm1
  171. psrlq $2, %xmm5
  172. pand mm00110011, %xmm0
  173. pand mm00110011, %xmm4
  174. pand mm00110011, %xmm1
  175. pand mm00110011, %xmm5
  176. paddq %xmm0, %xmm1
  177. paddq %xmm4, %xmm5
  178. LIMB32(`pxor zero, zero ')
  179. paddq %xmm5, %xmm1
  180. movdqa %xmm1, %xmm0
  181. psrlq $4, %xmm1
  182. pand mm00001111, %xmm0
  183. pand mm00001111, %xmm1
  184. paddq %xmm0, %xmm1
  185. psadbw zero, %xmm1
  186. paddq %xmm1, %xmm3 C add to grand total
  187. C Add the two 64-bit halves of the grand total counter
  188. L(rt): movdqa %xmm3, %xmm0
  189. psrldq $8, %xmm3
  190. paddq %xmm3, %xmm0
  191. movd %xmm0, areg C movq avoided due to gas bug
  192. LIMB32(`pop %ebx ')
  193. ret
  194. EPILOGUE()
  195. DEF_OBJECT(dummy,16)
  196. C Three magic constants used for masking out bits
  197. .byte 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55
  198. .byte 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55
  199. .byte 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33
  200. .byte 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33
  201. .byte 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f
  202. .byte 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f
  203. cnsts:
  204. C Masks for high end of number
  205. .byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
  206. .byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
  207. .byte 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00
  208. .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
  209. .byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
  210. .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
  211. .byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
  212. .byte 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00
  213. C Masks for low end of number
  214. .byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
  215. .byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
  216. .byte 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff
  217. .byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
  218. .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
  219. .byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
  220. .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
  221. .byte 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff
  222. END_OBJECT(dummy)