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

数学计算

开发平台:

Unix_Linux

  1. dnl  AMD K7 mpn_rshift -- mpn right shift.
  2. dnl  Copyright 1999, 2000, 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 K7: 1.21 cycles/limb (at 16 limbs/loop).
  20. dnl  K7: UNROLL_COUNT cycles/limb
  21. dnl           4           1.51
  22. dnl           8           1.26
  23. dnl          16           1.21
  24. dnl          32           1.2
  25. dnl  Maximum possible with the current code is 64.
  26. deflit(UNROLL_COUNT, 16)
  27. C mp_limb_t mpn_rshift (mp_ptr dst, mp_srcptr src, mp_size_t size,
  28. C                       unsigned shift);
  29. C
  30. C Shift src,size right by shift many bits and store the result in dst,size.
  31. C Zeros are shifted in at the left.  The bits shifted out at the right are
  32. C the return value.
  33. C
  34. C This code uses 64-bit MMX operations, which makes it possible to handle
  35. C two limbs at a time, for a theoretical 1.0 cycles/limb.  Plain integer
  36. C code, on the other hand, suffers from shrd being a vector path decode and
  37. C running at 3 cycles back-to-back.
  38. C
  39. C Full speed depends on source and destination being aligned, and some hairy
  40. C setups and finish-ups are done to arrange this for the loop.
  41. ifdef(`PIC',`
  42. deflit(UNROLL_THRESHOLD, 10)
  43. ',`
  44. deflit(UNROLL_THRESHOLD, 10)
  45. ')
  46. defframe(PARAM_SHIFT,16)
  47. defframe(PARAM_SIZE, 12)
  48. defframe(PARAM_SRC,  8)
  49. defframe(PARAM_DST,  4)
  50. defframe(SAVE_EDI, -4)
  51. defframe(SAVE_ESI, -8)
  52. defframe(SAVE_EBX, -12)
  53. deflit(SAVE_SIZE, 12)
  54. TEXT
  55. ALIGN(32)
  56. PROLOGUE(mpn_rshift)
  57. deflit(`FRAME',0)
  58. movl PARAM_SIZE, %eax
  59. movl PARAM_SRC, %edx
  60. subl $SAVE_SIZE, %esp
  61. deflit(`FRAME',SAVE_SIZE)
  62. movl PARAM_SHIFT, %ecx
  63. movl %edi, SAVE_EDI
  64. movl PARAM_DST, %edi
  65. decl %eax
  66. jnz L(more_than_one_limb)
  67. movl (%edx), %edx C src limb
  68. shrdl( %cl, %edx, %eax) C eax was decremented to zero
  69. shrl %cl, %edx
  70. movl %edx, (%edi) C dst limb
  71. movl SAVE_EDI, %edi
  72. addl $SAVE_SIZE, %esp
  73. ret
  74. C -----------------------------------------------------------------------------
  75. L(more_than_one_limb):
  76. C eax size-1
  77. C ebx
  78. C ecx shift
  79. C edx src
  80. C esi
  81. C edi dst
  82. C ebp
  83. movd PARAM_SHIFT, %mm6 C rshift
  84. movd (%edx), %mm5 C src low limb
  85. cmp $UNROLL_THRESHOLD-1, %eax
  86. jae L(unroll)
  87. leal (%edx,%eax,4), %edx C &src[size-1]
  88. leal -4(%edi,%eax,4), %edi C &dst[size-2]
  89. movd (%edx), %mm4 C src high limb
  90. negl %eax
  91. L(simple_top):
  92. C eax loop counter, limbs, negative
  93. C ebx
  94. C ecx shift
  95. C edx carry
  96. C edx &src[size-1]
  97. C edi &dst[size-2]
  98. C ebp
  99. C
  100. C mm0 scratch
  101. C mm4 src high limb
  102. C mm5 src low limb
  103. C mm6 shift
  104. movq (%edx,%eax,4), %mm0
  105. incl %eax
  106. psrlq %mm6, %mm0
  107. movd %mm0, (%edi,%eax,4)
  108. jnz L(simple_top)
  109. psllq $32, %mm5
  110. psrlq %mm6, %mm4
  111. psrlq %mm6, %mm5
  112. movd %mm4, 4(%edi) C dst high limb
  113. movd %mm5, %eax C return value
  114. movl SAVE_EDI, %edi
  115. addl $SAVE_SIZE, %esp
  116. emms
  117. ret
  118. C -----------------------------------------------------------------------------
  119. ALIGN(16)
  120. L(unroll):
  121. C eax size-1
  122. C ebx
  123. C ecx shift
  124. C edx src
  125. C esi
  126. C edi dst
  127. C ebp
  128. C
  129. C mm5 src low limb
  130. C mm6 rshift
  131. testb $4, %dl
  132. movl %esi, SAVE_ESI
  133. movl %ebx, SAVE_EBX
  134. psllq $32, %mm5
  135. jz L(start_src_aligned)
  136. C src isn't aligned, process low limb separately (marked xxx) and
  137. C step src and dst by one limb, making src aligned.
  138. C
  139. C source                  edx
  140. C --+-------+-------+-------+
  141. C           |          xxx  |
  142. C --+-------+-------+-------+
  143. C         4mod8   0mod8   4mod8
  144. C
  145. C         dest            edi
  146. C         --+-------+-------+
  147. C           |       |  xxx  |
  148. C         --+-------+-------+
  149. movq (%edx), %mm0 C src low two limbs
  150. addl $4, %edx
  151. movl %eax, PARAM_SIZE C size-1
  152. addl $4, %edi
  153. decl %eax C size-2 is new size-1
  154. psrlq %mm6, %mm0
  155. movl %edi, PARAM_DST C new dst
  156. movd %mm0, -4(%edi)
  157. L(start_src_aligned):
  158. movq (%edx), %mm1 C src low two limbs
  159. decl %eax C size-2, two last limbs handled at end
  160. testl $4, %edi
  161. psrlq %mm6, %mm5
  162. jz L(start_dst_aligned)
  163. C dst isn't aligned, add 4 to make it so, and pretend the shift is
  164. C 32 bits extra.  Low limb of dst (marked xxx) handled here separately.
  165. C
  166. C          source          edx
  167. C          --+-------+-------+
  168. C            |      mm1      |
  169. C          --+-------+-------+
  170. C                  4mod8   0mod8
  171. C
  172. C  dest                    edi
  173. C  --+-------+-------+-------+
  174. C                    |  xxx  |
  175. C  --+-------+-------+-------+
  176. C          4mod8   0mod8   4mod8
  177. movq %mm1, %mm0
  178. psrlq %mm6, %mm1
  179. addl $32, %ecx C shift+32
  180. movd %mm1, (%edi)
  181. movq %mm0, %mm1
  182. addl $4, %edi C new dst
  183. movd %ecx, %mm6
  184. L(start_dst_aligned):
  185. movq %mm1, %mm2 C copy of src low two limbs
  186. negl %ecx
  187. andl $-2, %eax C round size down to even
  188. movl %eax, %ebx
  189. negl %eax
  190. addl $64, %ecx
  191. andl $UNROLL_MASK, %eax
  192. decl %ebx
  193. shll %eax
  194. movd %ecx, %mm7 C lshift = 64-rshift
  195. ifdef(`PIC',`
  196. call L(pic_calc)
  197. L(here):
  198. ',`
  199. leal L(entry) (%eax,%eax,4), %esi
  200. negl %eax
  201. ')
  202. shrl $UNROLL_LOG2, %ebx C loop counter
  203. leal ifelse(UNROLL_BYTES,256,128+) 8(%edx,%eax,2), %edx
  204. leal ifelse(UNROLL_BYTES,256,128) (%edi,%eax,2), %edi
  205. movl PARAM_SIZE, %eax C for use at end
  206. jmp *%esi
  207. ifdef(`PIC',`
  208. L(pic_calc):
  209. C See mpn/x86/README about old gas bugs
  210. leal (%eax,%eax,4), %esi
  211. addl $L(entry)-L(here), %esi
  212. addl (%esp), %esi
  213. negl %eax
  214. ret_internal
  215. ')
  216. C -----------------------------------------------------------------------------
  217. ALIGN(64)
  218. L(top):
  219. C eax size, for use at end
  220. C ebx loop counter
  221. C ecx lshift
  222. C edx src
  223. C esi was computed jump
  224. C edi dst
  225. C ebp
  226. C
  227. C mm0 scratch
  228. C mm1  carry (alternating)
  229. C mm2 /
  230. C mm6 rshift
  231. C mm7 lshift
  232. C
  233. C 10 code bytes/limb
  234. C
  235. C The two chunks differ in whether mm1 or mm2 hold the carry.
  236. C The computed jump puts the initial carry in both mm1 and mm2.
  237. L(entry):
  238. deflit(CHUNK_COUNT, 4)
  239. forloop(i, 0, UNROLL_COUNT/CHUNK_COUNT-1, `
  240. deflit(`disp0', eval(i*CHUNK_COUNT*4 ifelse(UNROLL_BYTES,256,-128)))
  241. deflit(`disp1', eval(disp0 + 8))
  242. Zdisp( movq, disp0,(%edx), %mm0)
  243. psrlq %mm6, %mm2
  244. movq %mm0, %mm1
  245. psllq %mm7, %mm0
  246. por %mm2, %mm0
  247. Zdisp( movq, %mm0, disp0,(%edi))
  248. Zdisp( movq, disp1,(%edx), %mm0)
  249. psrlq %mm6, %mm1
  250. movq %mm0, %mm2
  251. psllq %mm7, %mm0
  252. por %mm1, %mm0
  253. Zdisp( movq, %mm0, disp1,(%edi))
  254. ')
  255. addl $UNROLL_BYTES, %edx
  256. addl $UNROLL_BYTES, %edi
  257. decl %ebx
  258. jns L(top)
  259. deflit(`disp0', ifelse(UNROLL_BYTES,256,-128))
  260. deflit(`disp1', eval(disp0-0 + 8))
  261. testb $1, %al
  262. psrlq %mm6, %mm2 C wanted rshifted in all cases below
  263. movl SAVE_ESI, %esi
  264. movd %mm5, %eax C return value
  265. movl SAVE_EBX, %ebx
  266. jz L(end_even)
  267. C Size odd, destination was aligned.
  268. C
  269. C source
  270. C       edx
  271. C +-------+---------------+--
  272. C |       |      mm2      |
  273. C +-------+---------------+--
  274. C
  275. C dest                  edi
  276. C +-------+---------------+---------------+--
  277. C |       |               |    written    |
  278. C +-------+---------------+---------------+--
  279. C
  280. C mm6 = shift
  281. C mm7 = ecx = 64-shift
  282. C Size odd, destination was unaligned.
  283. C
  284. C source
  285. C       edx
  286. C +-------+---------------+--
  287. C |       |      mm2      |
  288. C +-------+---------------+--
  289. C
  290. C dest          edi
  291. C +---------------+---------------+--
  292. C |               |    written    |
  293. C +---------------+---------------+--
  294. C
  295. C mm6 = shift+32
  296. C mm7 = ecx = 64-(shift+32)
  297. C In both cases there's one extra limb of src to fetch and combine
  298. C with mm2 to make a qword to store, and in the aligned case there's
  299. C a further extra limb of dst to be formed.
  300. movd disp0(%edx), %mm0
  301. movq %mm0, %mm1
  302. psllq %mm7, %mm0
  303. testb $32, %cl
  304. por %mm2, %mm0
  305. psrlq %mm6, %mm1
  306. movq %mm0, disp0(%edi)
  307. jz L(finish_odd_unaligned)
  308. movd %mm1, disp1(%edi)
  309. L(finish_odd_unaligned):
  310. movl SAVE_EDI, %edi
  311. addl $SAVE_SIZE, %esp
  312. emms
  313. ret
  314. L(end_even):
  315. C Size even, destination was aligned.
  316. C
  317. C source
  318. C +---------------+--
  319. C |      mm2      |
  320. C +---------------+--
  321. C
  322. C dest          edi
  323. C +---------------+---------------+--
  324. C |               |      mm3      |
  325. C +---------------+---------------+--
  326. C
  327. C mm6 = shift
  328. C mm7 = ecx = 64-shift
  329. C Size even, destination was unaligned.
  330. C
  331. C source
  332. C +---------------+--
  333. C |      mm2      |
  334. C +---------------+--
  335. C
  336. C dest  edi
  337. C +-------+---------------+--
  338. C |       |      mm3      |
  339. C +-------+---------------+--
  340. C
  341. C mm6 = shift+32
  342. C mm7 = 64-(shift+32)
  343. C The movd for the unaligned case is the same data as the movq for
  344. C the aligned case, it's just a choice between whether one or two
  345. C limbs should be written.
  346. testb $32, %cl
  347. movd %mm2, disp0(%edi)
  348. jz L(end_even_unaligned)
  349. movq %mm2, disp0(%edi)
  350. L(end_even_unaligned):
  351. movl SAVE_EDI, %edi
  352. addl $SAVE_SIZE, %esp
  353. emms
  354. ret
  355. EPILOGUE()