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

数学计算

开发平台:

Unix_Linux

  1. dnl  AMD K6-2 mpn_lshift -- mpn left shift.
  2. dnl  Copyright 1999, 2000, 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 K6-2: 1.75 cycles/limb
  20. C mp_limb_t mpn_lshift (mp_ptr dst, mp_srcptr src, mp_size_t size,
  21. C                       unsigned shift);
  22. C
  23. defframe(PARAM_SHIFT,16)
  24. defframe(PARAM_SIZE, 12)
  25. defframe(PARAM_SRC,  8)
  26. defframe(PARAM_DST,  4)
  27. deflit(`FRAME',0)
  28. dnl  used after src has been fetched
  29. define(VAR_RETVAL,`PARAM_SRC')
  30. dnl  minimum 9, because unrolled loop can't handle less
  31. deflit(UNROLL_THRESHOLD, 9)
  32. TEXT
  33. ALIGN(32)
  34. PROLOGUE(mpn_lshift)
  35. deflit(`FRAME',0)
  36. C The 1 limb case can be done without the push %ebx, but it's then
  37. C still the same speed.  The push is left as a free helping hand for
  38. C the two_or_more code.
  39. movl PARAM_SIZE, %eax
  40. pushl %ebx FRAME_pushl()
  41. movl PARAM_SRC, %ebx
  42. decl %eax
  43. movl PARAM_SHIFT, %ecx
  44. jnz L(two_or_more)
  45. movl (%ebx), %edx C src limb
  46. movl PARAM_DST, %ebx
  47. shldl( %cl, %edx, %eax) C return value
  48. shll %cl, %edx
  49. movl %edx, (%ebx) C dst limb
  50. popl %ebx
  51. ret
  52. C -----------------------------------------------------------------------------
  53. ALIGN(16) C avoid offset 0x1f
  54. L(two_or_more):
  55. C eax size-1
  56. C ebx src
  57. C ecx shift
  58. C edx
  59. movl (%ebx,%eax,4), %edx C src high limb
  60. negl %ecx
  61. movd PARAM_SHIFT, %mm6
  62. addl $32, %ecx C 32-shift
  63. shrl %cl, %edx
  64. cmpl $UNROLL_THRESHOLD-1, %eax
  65. movl %edx, VAR_RETVAL
  66. jae L(unroll)
  67. movd %ecx, %mm7
  68. movl %eax, %ecx
  69. movl PARAM_DST, %eax
  70. L(simple):
  71. C eax dst
  72. C ebx src
  73. C ecx counter, size-1 to 1
  74. C edx retval
  75. C
  76. C mm0 scratch
  77. C mm6 shift
  78. C mm7 32-shift
  79. movq -4(%ebx,%ecx,4), %mm0
  80. psrlq %mm7, %mm0
  81. Zdisp( movd, %mm0, 0,(%eax,%ecx,4))
  82. loop L(simple)
  83. movd (%ebx), %mm0
  84. popl %ebx
  85. psllq %mm6, %mm0
  86. movd %mm0, (%eax)
  87. movl %edx, %eax
  88. femms
  89. ret
  90. C -----------------------------------------------------------------------------
  91. ALIGN(16)
  92. L(unroll):
  93. C eax size-1
  94. C ebx src
  95. C ecx 32-shift
  96. C edx retval (but instead VAR_RETVAL is used)
  97. C
  98. C mm6 shift
  99. addl $32, %ecx
  100. movl PARAM_DST, %edx
  101. movd %ecx, %mm7
  102. subl $7, %eax C size-8
  103. leal (%edx,%eax,4), %ecx C alignment of dst
  104. movq 32-8(%ebx,%eax,4), %mm2 C src high qword
  105. testb $4, %cl
  106. jz L(dst_aligned)
  107. psllq %mm6, %mm2
  108. psrlq $32, %mm2
  109. decl %eax
  110. movd %mm2, 32(%edx,%eax,4) C dst high limb
  111. movq 32-8(%ebx,%eax,4), %mm2 C new src high qword
  112. L(dst_aligned):
  113. movq 32-16(%ebx,%eax,4), %mm0 C src second highest qword
  114. C This loop is the important bit, the rest is just support for it.
  115. C Four src limbs are held at the start, and four more will be read.
  116. C Four dst limbs will be written.  This schedule seems necessary for
  117. C full speed.
  118. C
  119. C The use of size-8 lets the loop stop when %eax goes negative and
  120. C leaves -4 to -1 which can be tested with test $1 and $2.
  121. L(top):
  122. C eax counter, size-8 step by -4 until <0
  123. C ebx src
  124. C ecx
  125. C edx dst
  126. C
  127. C mm0 src next qword
  128. C mm1 scratch
  129. C mm2 src prev qword
  130. C mm6 shift
  131. C mm7 64-shift
  132. psllq %mm6, %mm2
  133. subl $4, %eax
  134. movq %mm0, %mm1
  135. psrlq %mm7, %mm0
  136. por %mm0, %mm2
  137. movq 24(%ebx,%eax,4), %mm0
  138. psllq %mm6, %mm1
  139. movq %mm2, 40(%edx,%eax,4)
  140. movq %mm0, %mm2
  141. psrlq %mm7, %mm0
  142. por %mm0, %mm1
  143. movq 16(%ebx,%eax,4), %mm0
  144. movq %mm1, 32(%edx,%eax,4)
  145. jnc L(top)
  146. C Now have four limbs in mm2 (prev) and mm0 (next), plus eax mod 4.
  147. C
  148. C 8(%ebx) is the next source, and 24(%edx) is the next destination.
  149. C %eax is between -4 and -1, representing respectively 0 to 3 extra
  150. C limbs that must be read.
  151. testl $2, %eax C testl to avoid bad cache line crossing
  152. jz L(finish_nottwo)
  153. C Two more limbs: lshift mm2, OR it with rshifted mm0, mm0 becomes
  154. C new mm2 and a new mm0 is loaded.
  155. psllq %mm6, %mm2
  156. movq %mm0, %mm1
  157. psrlq %mm7, %mm0
  158. subl $2, %eax
  159. por %mm0, %mm2
  160. movq 16(%ebx,%eax,4), %mm0
  161. movq %mm2, 32(%edx,%eax,4)
  162. movq %mm1, %mm2
  163. L(finish_nottwo):
  164. C lshift mm2, OR with rshifted mm0, mm1 becomes lshifted mm0
  165. testb $1, %al
  166. psllq %mm6, %mm2
  167. movq %mm0, %mm1
  168. psrlq %mm7, %mm0
  169. por %mm0, %mm2
  170. psllq %mm6, %mm1
  171. movq %mm2, 24(%edx,%eax,4)
  172. jz L(finish_even)
  173. C Size is odd, so mm1 and one extra limb to process.
  174. movd (%ebx), %mm0 C src[0]
  175. popl %ebx
  176. deflit(`FRAME',0)
  177. movq %mm0, %mm2
  178. psllq $32, %mm0
  179. psrlq %mm7, %mm0
  180. psllq %mm6, %mm2
  181. por %mm0, %mm1
  182. movq %mm1, 4(%edx) C dst[1,2]
  183. movd %mm2, (%edx) C dst[0]
  184. movl VAR_RETVAL, %eax
  185. femms
  186. ret
  187. nop C avoid bad cache line crossing
  188. L(finish_even):
  189. deflit(`FRAME',4)
  190. C Size is even, so only mm1 left to process.
  191. movq %mm1, (%edx) C dst[0,1]
  192. movl VAR_RETVAL, %eax
  193. popl %ebx
  194. femms
  195. ret
  196. EPILOGUE()