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

数学计算

开发平台:

Unix_Linux

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