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

数学计算

开发平台:

Unix_Linux

  1. dnl  AMD K6 mpn_gcd_1 -- mpn by 1 gcd.
  2. dnl  Copyright 2000, 2001, 2002, 2004 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 K6: 9.5 cycles/bit (approx)   1x1 gcd
  20. C     11.0 cycles/limb          Nx1 reduction (modexact_1_odd)
  21. C mp_limb_t mpn_gcd_1 (mp_srcptr src, mp_size_t size, mp_limb_t y);
  22. C
  23. C This code is nothing very special, but offers a speedup over what gcc 2.95
  24. C can do with mpn/generic/gcd_1.c.
  25. C
  26. C Future:
  27. C
  28. C Using a lookup table to count trailing zeros seems a touch quicker, but
  29. C after a slightly longer startup.  Might be worthwhile if an mpn_gcd_2 used
  30. C it too.
  31. dnl  If size==1 and x (the larger operand) is more than DIV_THRESHOLD bits
  32. dnl  bigger than y, then a division x%y is done to reduce it.
  33. dnl
  34. dnl  A divl is 20 cycles and the loop runs at about 9.5 cycles/bitpair so
  35. dnl  there should be an advantage in the divl at about 4 or 5 bits, which is
  36. dnl  what's found.
  37. deflit(DIV_THRESHOLD, 5)
  38. defframe(PARAM_LIMB, 12)
  39. defframe(PARAM_SIZE,  8)
  40. defframe(PARAM_SRC,   4)
  41. TEXT
  42. ALIGN(16)
  43. PROLOGUE(mpn_gcd_1)
  44. deflit(`FRAME',0)
  45. ASSERT(ne, `cmpl $0, PARAM_LIMB')
  46. ASSERT(ae, `cmpl $1, PARAM_SIZE')
  47. movl PARAM_SRC, %eax
  48. pushl %ebx FRAME_pushl()
  49. movl PARAM_LIMB, %edx
  50. movl $-1, %ecx
  51. movl (%eax), %ebx C src low limb
  52. movl %ebx, %eax C src low limb
  53. orl %edx, %ebx
  54. L(common_twos):
  55. shrl %ebx
  56. incl %ecx
  57. jnc L(common_twos) C 1/4 chance on random data
  58. shrl %cl, %edx C y
  59. cmpl $1, PARAM_SIZE
  60. ja L(size_two_or_more)
  61. ASSERT(nz, `orl %eax, %eax') C should have src limb != 0
  62. shrl %cl, %eax C x
  63. C Swap if necessary to make x>=y.  Measures a touch quicker as a
  64. C jump than a branch free calculation.
  65. C
  66. C eax x
  67. C ebx
  68. C ecx common twos
  69. C edx y
  70. movl %eax, %ebx
  71. cmpl %eax, %edx
  72. jb L(noswap)
  73. movl %edx, %eax
  74. movl %ebx, %edx
  75. movl %eax, %ebx
  76. L(noswap):
  77. C See if it's worth reducing x with a divl.
  78. C
  79. C eax x
  80. C ebx x
  81. C ecx common twos
  82. C edx y
  83. shrl $DIV_THRESHOLD, %ebx
  84. cmpl %ebx, %edx
  85. ja L(nodiv)
  86. C Reduce x to x%y.
  87. C
  88. C eax x
  89. C ebx
  90. C ecx common twos
  91. C edx y
  92. movl %edx, %ebx
  93. xorl %edx, %edx
  94. divl %ebx
  95. orl %edx, %edx C y
  96. nop C code alignment
  97. movl %ebx, %eax C x
  98. jz L(done_shll)
  99. L(nodiv):
  100. C eax x
  101. C ebx
  102. C ecx common twos
  103. C edx y
  104. C esi
  105. C edi
  106. C ebp
  107. L(strip_y):
  108. shrl %edx
  109. jnc L(strip_y)
  110. leal 1(%edx,%edx), %edx
  111. movl %ecx, %ebx C common twos
  112. leal 1(%eax), %ecx
  113. jmp L(strip_x_and)
  114. C Calculating a %cl shift based on the low bit 0 or 1 avoids doing a branch
  115. C on a 50/50 chance of 0 or 1.  The chance of the next bit also being 0 is
  116. C only 1/4.
  117. C
  118. C A second computed %cl shift was tried, but that measured a touch slower
  119. C than branching back.
  120. C
  121. C A branch-free abs(x-y) and min(x,y) calculation was tried, but that
  122. C measured about 1 cycle/bit slower.
  123. C eax x
  124. C ebx common twos
  125. C ecx scratch
  126. C edx y
  127. ALIGN(4)
  128. L(swap):
  129. addl %eax, %edx C x-y+y = x
  130. negl %eax C -(x-y) = y-x
  131. L(strip_x):
  132. shrl %eax C odd-odd = even, so always one to strip
  133. ASSERT(nz)
  134. L(strip_x_leal):
  135. leal 1(%eax), %ecx
  136. L(strip_x_and):
  137. andl $1, %ecx C (x^1)&1
  138. shrl %cl, %eax C shift if x even
  139. testb $1, %al
  140. jz L(strip_x)
  141. ASSERT(nz,`testl $1, %eax') C x, y odd
  142. ASSERT(nz,`testl $1, %edx')
  143. subl %edx, %eax
  144. jb L(swap)
  145. ja L(strip_x)
  146. movl %edx, %eax
  147. movl %ebx, %ecx
  148. L(done_shll):
  149. shll %cl, %eax
  150. popl %ebx
  151. ret
  152. C -----------------------------------------------------------------------------
  153. C Two or more limbs.
  154. C
  155. C x={src,size} is reduced modulo y using either a plain mod_1 style
  156. C remainder, or a modexact_1 style exact division.
  157. deflit(MODEXACT_THRESHOLD, ifdef(`PIC', 4, 4))
  158. ALIGN(8)
  159. L(size_two_or_more):
  160. C eax
  161. C ebx
  162. C ecx common twos
  163. C edx y, without common twos
  164. C esi
  165. C edi
  166. C ebp
  167. deflit(FRAME_TWO_OR_MORE, FRAME)
  168. pushl %edi defframe_pushl(SAVE_EDI)
  169. movl PARAM_SRC, %ebx
  170. L(y_twos):
  171. shrl %edx
  172. jnc L(y_twos)
  173. movl %ecx, %edi C common twos
  174. movl PARAM_SIZE, %ecx
  175. pushl %esi defframe_pushl(SAVE_ESI)
  176. leal 1(%edx,%edx), %esi C y (odd)
  177. movl -4(%ebx,%ecx,4), %eax C src high limb
  178. cmpl %edx, %eax C carry if high<divisor
  179. sbbl %edx, %edx C -1 if high<divisor
  180. addl %edx, %ecx C skip one limb if high<divisor
  181. andl %eax, %edx
  182. cmpl $MODEXACT_THRESHOLD, %ecx
  183. jae L(modexact)
  184. L(divide_top):
  185. C eax scratch (quotient)
  186. C ebx src
  187. C ecx counter, size-1 to 1
  188. C edx carry (remainder)
  189. C esi divisor (odd)
  190. C edi
  191. C ebp
  192. movl -4(%ebx,%ecx,4), %eax
  193. divl %esi
  194. loop L(divide_top)
  195. movl %edx, %eax C x
  196. movl %esi, %edx C y (odd)
  197. movl %edi, %ebx C common twos
  198. popl %esi
  199. popl %edi
  200. leal 1(%eax), %ecx
  201. orl %eax, %eax
  202. jnz L(strip_x_and)
  203. movl %ebx, %ecx
  204. movl %edx, %eax
  205. shll %cl, %eax
  206. popl %ebx
  207. ret
  208. ALIGN(8)
  209. L(modexact):
  210. C eax
  211. C ebx src ptr
  212. C ecx size or size-1
  213. C edx
  214. C esi y odd
  215. C edi common twos
  216. C ebp
  217. movl PARAM_SIZE, %eax
  218. pushl %esi FRAME_pushl()
  219. pushl %eax FRAME_pushl()
  220. pushl %ebx FRAME_pushl()
  221. ifdef(`PIC',`
  222. nop C code alignment
  223. call L(movl_eip_ebx)
  224. L(here):
  225. addl $_GLOBAL_OFFSET_TABLE_, %ebx
  226. call GSYM_PREFIX`'mpn_modexact_1_odd@PLT
  227. ',`
  228. call GSYM_PREFIX`'mpn_modexact_1_odd
  229. ')
  230. movl %esi, %edx C y odd
  231. movl SAVE_ESI, %esi
  232. movl %edi, %ebx C common twos
  233. movl SAVE_EDI, %edi
  234. addl $eval(FRAME - FRAME_TWO_OR_MORE), %esp
  235. orl %eax, %eax
  236. leal 1(%eax), %ecx
  237. jnz L(strip_x_and)
  238. movl %ebx, %ecx
  239. movl %edx, %eax
  240. shll %cl, %eax
  241. popl %ebx
  242. ret
  243. ifdef(`PIC',`
  244. L(movl_eip_ebx):
  245. movl (%esp), %ebx
  246. ret_internal
  247. ')
  248. EPILOGUE()