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

数学计算

开发平台:

Unix_Linux

  1. dnl  AMD K7 mpn_gcd_1 -- mpn by 1 gcd.
  2. dnl  Copyright 2000, 2001, 2002, 2009 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 K7: 6.75 cycles/bit (approx)  1x1 gcd
  20. C     11.0 cycles/limb          Nx1 reduction (modexact_1_odd)
  21. dnl  Reduce using x%y if x is more than DIV_THRESHOLD bits bigger than y,
  22. dnl  where x is the larger of the two.  See tune/README for more.
  23. dnl
  24. dnl  divl at 40 cycles compared to the gcd at about 7 cycles/bitpair
  25. dnl  suggests 40/7*2=11.4 but 7 seems to be about right.
  26. deflit(DIV_THRESHOLD, 7)
  27. C table[n] is the number of trailing zeros on n, or MAXSHIFT if n==0.
  28. C
  29. C This is mixed in with the code, but as per the k7 optimization manual it's
  30. C a full cache line and suitably aligned so it won't get swapped between
  31. C code and data.  Having it in TEXT rather than RODATA saves needing a GOT
  32. C entry when PIC.
  33. C
  34. C Actually, there doesn't seem to be a measurable difference between this in
  35. C it's own cache line or plonked in the middle of the code.  Presumably
  36. C since TEXT is read-only there's no worries about coherency.
  37. deflit(MAXSHIFT, 6)
  38. deflit(MASK, eval((1<<MAXSHIFT)-1))
  39. TEXT
  40. ALIGN(64)
  41. L(table):
  42. .byte MAXSHIFT
  43. forloop(i,1,MASK,
  44. ` .byte m4_count_trailing_zeros(i)
  45. ')
  46. C mp_limb_t mpn_gcd_1 (mp_srcptr src, mp_size_t size, mp_limb_t limb);
  47. C
  48. defframe(PARAM_LIMB,   12)
  49. defframe(PARAM_SIZE,    8)
  50. defframe(PARAM_SRC,     4)
  51. defframe(SAVE_EBX,     -4)
  52. defframe(SAVE_ESI,     -8)
  53. defframe(SAVE_EDI,    -12)
  54. defframe(SAVE_EBP,    -16)
  55. defframe(CALL_DIVISOR,-20)
  56. defframe(CALL_SIZE,   -24)
  57. defframe(CALL_SRC,    -28)
  58. deflit(STACK_SPACE, 28)
  59. TEXT
  60. ALIGN(16)
  61. PROLOGUE(mpn_gcd_1)
  62. deflit(`FRAME',0)
  63. ASSERT(ne, `cmpl $0, PARAM_LIMB') C y!=0
  64. ASSERT(ae, `cmpl $1, PARAM_SIZE') C size>=1
  65. mov PARAM_SRC, %eax
  66. mov PARAM_LIMB, %edx
  67. sub $STACK_SPACE, %esp deflit(`FRAME',STACK_SPACE)
  68. mov %esi, SAVE_ESI
  69. mov %ebx, SAVE_EBX
  70. mov (%eax), %esi C src low limb
  71. ifdef(`PIC',`
  72. mov %edi, SAVE_EDI
  73. call L(movl_eip_to_edi)
  74. L(here):
  75. add $L(table)-L(here), %edi
  76. ')
  77. mov %esi, %ebx
  78. or %edx, %esi C x|y
  79. mov $-1, %ecx
  80. L(twos):
  81. inc %ecx
  82. shr %esi
  83. jnc L(twos) C 3/4 chance of x or y odd already
  84. shr %cl, %ebx
  85. shr %cl, %edx
  86. mov %ecx, %esi C common twos
  87. mov PARAM_SIZE, %ecx
  88. cmp $1, %ecx
  89. ja L(divide)
  90. C eax
  91. C ebx x
  92. C ecx
  93. C edx y
  94. C esi common twos
  95. C edi [PIC] L(table)
  96. C ebp
  97. mov %edx, %eax
  98. cmp %ebx, %edx
  99. cmovb( %ebx, %eax) C swap to make x bigger than y
  100. cmovb( %edx, %ebx)
  101. L(strip_y):
  102. C eax x
  103. C ebx y
  104. C ecx
  105. C edx
  106. C esi common twos
  107. C edi [PIC] L(table)
  108. C ebp
  109. ASSERT(nz,`orl %ebx,%ebx')
  110. shr %ebx
  111. jnc L(strip_y)
  112. rcl %ebx
  113. C eax x
  114. C ebx y (odd)
  115. C ecx
  116. C edx
  117. C esi common twos
  118. C edi [PIC] L(table)
  119. C ebp
  120. mov %eax, %ecx
  121. mov %ebx, %edx
  122. shr $DIV_THRESHOLD, %eax
  123. cmp %eax, %ebx
  124. mov %ecx, %eax
  125. ja L(strip_x_entry) C do x%y if x much bigger than y
  126. xor %edx, %edx
  127. div %ebx
  128. or %edx, %edx
  129. mov %edx, %ecx C remainder -> x
  130. mov %ebx, %edx C y
  131. jz L(done_ebx)
  132. jmp L(strip_x)
  133. C Offset 0x9D here for non-PIC.  About 0.4 cycles/bit is saved by
  134. C ensuring the end of the jnz at the end of this loop doesn't cross
  135. C into the next cache line at 0xC0.
  136. C
  137. C PIC on the other hand is offset 0xAC here and extends to 0xC9, so
  138. C it crosses but doesn't suffer any measurable slowdown.
  139. L(top):
  140. C eax x
  141. C ebx y-x
  142. C ecx x-y
  143. C edx y
  144. C esi twos, for use at end
  145. C edi [PIC] L(table)
  146. cmovc( %ebx, %ecx) C if x-y gave carry, use x and y-x
  147. cmovc( %eax, %edx)
  148. L(strip_x):
  149. mov %ecx, %eax
  150. L(strip_x_entry):
  151. and $MASK, %ecx
  152. ASSERT(nz, `orl %eax, %eax')
  153. ifdef(`PIC',`
  154. mov (%ecx,%edi), %cl
  155. ',`
  156. mov L(table) (%ecx), %cl
  157. ')
  158. shr %cl, %eax
  159. cmp $MAXSHIFT, %cl
  160. mov %eax, %ecx
  161. mov %edx, %ebx
  162. je L(strip_x)
  163. ASSERT(nz, `test $1, %eax') C both odd
  164. ASSERT(nz, `test $1, %edx')
  165. sub %eax, %ebx
  166. sub %edx, %ecx
  167. jnz L(top)
  168. L(done):
  169. mov %esi, %ecx
  170. mov SAVE_ESI, %esi
  171. ifdef(`PIC',`
  172. mov SAVE_EDI, %edi
  173. ')
  174. shl %cl, %eax
  175. mov SAVE_EBX, %ebx
  176. add $FRAME, %esp
  177. ret
  178. C -----------------------------------------------------------------------------
  179. C two or more limbs
  180. dnl  MODEXACT_THRESHOLD is the size at which it's better to call
  181. dnl  mpn_modexact_1_odd than do an inline loop.
  182. deflit(MODEXACT_THRESHOLD, ifdef(`PIC',6,5))
  183. L(divide):
  184. C eax src
  185. C ebx
  186. C ecx size
  187. C edx y
  188. C esi common twos
  189. C edi [PIC] L(table)
  190. C ebp
  191. L(divide_strip_y):
  192. ASSERT(nz,`or %edx,%edx')
  193. shr %edx
  194. jnc L(divide_strip_y)
  195. lea 1(%edx,%edx), %ebx C y now odd
  196. mov %ebp, SAVE_EBP
  197. mov %eax, %ebp
  198. mov -4(%eax,%ecx,4), %eax C src high limb
  199. cmp $MODEXACT_THRESHOLD, %ecx
  200. jae L(modexact)
  201. cmp %ebx, %eax C high cmp divisor
  202. mov $0, %edx
  203. cmovc( %eax, %edx) C skip a div if high<divisor
  204. sbb $0, %ecx
  205. L(divide_top):
  206. C eax scratch (quotient)
  207. C ebx y
  208. C ecx counter (size to 1, inclusive)
  209. C edx carry (remainder)
  210. C esi common twos
  211. C edi [PIC] L(table)
  212. C ebp src
  213. mov -4(%ebp,%ecx,4), %eax
  214. div %ebx
  215. dec %ecx
  216. jnz L(divide_top)
  217. C eax
  218. C ebx y (odd)
  219. C ecx
  220. C edx x
  221. C esi common twos
  222. C edi [PIC] L(table)
  223. C ebp
  224. or %edx, %edx
  225. mov SAVE_EBP, %ebp
  226. mov %edx, %eax
  227. mov %edx, %ecx
  228. mov %ebx, %edx
  229. jnz L(strip_x_entry)
  230. L(done_ebx):
  231. mov %ebx, %eax
  232. jmp L(done)
  233. L(modexact):
  234. C eax
  235. C ebx y
  236. C ecx size
  237. C edx
  238. C esi common twos
  239. C edi [PIC] L(table)
  240. C ebp src
  241. ifdef(`PIC',`
  242. mov %ebp, CALL_SRC
  243. mov %ebx, %ebp C y
  244. mov %edi, %ebx C L(table)
  245. add $_GLOBAL_OFFSET_TABLE_+[.-L(table)], %ebx
  246. mov %ebp, CALL_DIVISOR
  247. mov %ecx, CALL_SIZE
  248. call GSYM_PREFIX`'mpn_modexact_1_odd@PLT
  249. ',`
  250. dnl non-PIC
  251. mov %ebx, CALL_DIVISOR
  252. mov %ebp, CALL_SRC
  253. mov %ecx, CALL_SIZE
  254. call GSYM_PREFIX`'mpn_modexact_1_odd
  255. ')
  256. C eax x
  257. C ebx [non-PIC] y
  258. C ecx
  259. C edx
  260. C esi common twos
  261. C edi [PIC] L(table)
  262. C ebp [PIC] y
  263. or %eax, %eax
  264. mov ifdef(`PIC',`%ebp',`%ebx'), %edx
  265. mov SAVE_EBP, %ebp
  266. mov %eax, %ecx
  267. jnz L(strip_x_entry)
  268. mov %edx, %eax
  269. jmp L(done)
  270. ifdef(`PIC', `
  271. L(movl_eip_to_edi):
  272. mov (%esp), %edi
  273. ret_internal
  274. ')
  275. EPILOGUE()