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

数学计算

开发平台:

Unix_Linux

  1. dnl  x86 generic mpn_sqr_basecase -- square an mpn number.
  2. dnl  Copyright 1999, 2000, 2002, 2003 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 modify
  7. dnl  it under the terms of the GNU Lesser General Public License as published
  8. dnl  by the Free Software Foundation; either version 3 of the License, or (at
  9. dnl  your option) any later version.
  10. dnl
  11. dnl  The GNU MP Library is distributed in the hope that it will be useful, but
  12. dnl  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  13. dnl  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
  14. dnl  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     cycles/crossproduct  cycles/triangleproduct
  20. C P5:
  21. C P6:
  22. C K6:
  23. C K7:
  24. C P4:
  25. C void mpn_sqr_basecase (mp_ptr dst, mp_srcptr src, mp_size_t size);
  26. C
  27. C The algorithm is basically the same as mpn/generic/sqr_basecase.c, but a
  28. C lot of function call overheads are avoided, especially when the size is
  29. C small.
  30. C
  31. C The mul1 loop is not unrolled like mul_1.asm, it doesn't seem worth the
  32. C code size to do so here.
  33. C
  34. C Enhancements:
  35. C
  36. C The addmul loop here is also not unrolled like aorsmul_1.asm and
  37. C mul_basecase.asm are.  Perhaps it should be done.  It'd add to the
  38. C complexity, but if it's worth doing in the other places then it should be
  39. C worthwhile here.
  40. C
  41. C A fully-unrolled style like other sqr_basecase.asm versions (k6, k7, p6)
  42. C might be worth considering.  That'd add quite a bit to the code size, but
  43. C only as much as is used would be dragged into L1 cache.
  44. defframe(PARAM_SIZE,12)
  45. defframe(PARAM_SRC, 8)
  46. defframe(PARAM_DST, 4)
  47. TEXT
  48. ALIGN(8)
  49. PROLOGUE(mpn_sqr_basecase)
  50. deflit(`FRAME',0)
  51. movl PARAM_SIZE, %edx
  52. movl PARAM_SRC, %eax
  53. cmpl $2, %edx
  54. movl PARAM_DST, %ecx
  55. je L(two_limbs)
  56. ja L(three_or_more)
  57. C -----------------------------------------------------------------------------
  58. C one limb only
  59. C eax src
  60. C ebx
  61. C ecx dst
  62. C edx
  63. movl (%eax), %eax
  64. mull %eax
  65. movl %eax, (%ecx)
  66. movl %edx, 4(%ecx)
  67. ret
  68. C -----------------------------------------------------------------------------
  69. ALIGN(8)
  70. L(two_limbs):
  71. C eax src
  72. C ebx
  73. C ecx dst
  74. C edx
  75. pushl %ebx
  76. pushl %ebp
  77. movl %eax, %ebx
  78. movl (%eax), %eax
  79. mull %eax C src[0]^2
  80. pushl %esi
  81. pushl %edi
  82. movl %edx, %esi C dst[1]
  83. movl %eax, (%ecx) C dst[0]
  84. movl 4(%ebx), %eax
  85. mull %eax C src[1]^2
  86. movl %eax, %edi C dst[2]
  87. movl %edx, %ebp C dst[3]
  88. movl (%ebx), %eax
  89. mull 4(%ebx) C src[0]*src[1]
  90. addl %eax, %esi
  91. adcl %edx, %edi
  92. adcl $0, %ebp
  93. addl %esi, %eax
  94. adcl %edi, %edx
  95. movl %eax, 4(%ecx)
  96. adcl $0, %ebp
  97. movl %edx, 8(%ecx)
  98. movl %ebp, 12(%ecx)
  99. popl %edi
  100. popl %esi
  101. popl %ebp
  102. popl %ebx
  103. ret
  104. C -----------------------------------------------------------------------------
  105. ALIGN(8)
  106. L(three_or_more):
  107. deflit(`FRAME',0)
  108. C eax src
  109. C ebx
  110. C ecx dst
  111. C edx size
  112. pushl %ebx FRAME_pushl()
  113. pushl %edi FRAME_pushl()
  114. pushl %esi FRAME_pushl()
  115. pushl %ebp FRAME_pushl()
  116. leal (%ecx,%edx,4), %edi C &dst[size], end of this mul1
  117. leal (%eax,%edx,4), %esi C &src[size]
  118. C First multiply src[0]*src[1..size-1] and store at dst[1..size].
  119. movl (%eax), %ebp C src[0], multiplier
  120. movl %edx, %ecx
  121. negl %ecx C -size
  122. xorl %ebx, %ebx C clear carry limb
  123. incl %ecx C -(size-1)
  124. L(mul1):
  125. C eax scratch
  126. C ebx carry
  127. C ecx counter, limbs, negative
  128. C edx scratch
  129. C esi &src[size]
  130. C edi &dst[size]
  131. C ebp multiplier
  132. movl (%esi,%ecx,4), %eax
  133. mull %ebp
  134. addl %eax, %ebx
  135. adcl $0, %edx
  136. movl %ebx, (%edi,%ecx,4)
  137. movl %edx, %ebx
  138. incl %ecx
  139. jnz L(mul1)
  140. movl %ebx, (%edi)
  141. C Add products src[n]*src[n+1..size-1] at dst[2*n-1...], for
  142. C n=1..size-2.
  143. C
  144. C The last products src[size-2]*src[size-1], which is the end corner
  145. C of the product triangle, is handled separately at the end to save
  146. C looping overhead.  If size is 3 then it's only this that needs to
  147. C be done.
  148. C
  149. C In the outer loop %esi is a constant, and %edi just advances by 1
  150. C limb each time.  The size of the operation decreases by 1 limb
  151. C each time.
  152. C eax
  153. C ebx carry (needing carry flag added)
  154. C ecx
  155. C edx
  156. C esi &src[size]
  157. C edi &dst[size]
  158. C ebp
  159. movl PARAM_SIZE, %ecx
  160. subl $3, %ecx
  161. jz L(corner)
  162. negl %ecx
  163. dnl  re-use parameter space
  164. define(VAR_OUTER,`PARAM_DST')
  165. L(outer):
  166. C eax
  167. C ebx
  168. C ecx
  169. C edx outer loop counter, -(size-3) to -1
  170. C esi &src[size]
  171. C edi dst, pointing at stored carry limb of previous loop
  172. C ebp
  173. movl %ecx, VAR_OUTER
  174. addl $4, %edi C advance dst end
  175. movl -8(%esi,%ecx,4), %ebp C next multiplier
  176. subl $1, %ecx
  177. xorl %ebx, %ebx C initial carry limb
  178. L(inner):
  179. C eax scratch
  180. C ebx carry (needing carry flag added)
  181. C ecx counter, -n-1 to -1
  182. C edx scratch
  183. C esi &src[size]
  184. C edi dst end of this addmul
  185. C ebp multiplier
  186. movl (%esi,%ecx,4), %eax
  187. mull %ebp
  188. addl %ebx, %eax
  189. adcl $0, %edx
  190. addl %eax, (%edi,%ecx,4)
  191. adcl $0, %edx
  192. movl %edx, %ebx
  193. addl $1, %ecx
  194. jl L(inner)
  195. movl %ebx, (%edi)
  196. movl VAR_OUTER, %ecx
  197. incl %ecx
  198. jnz L(outer)
  199. L(corner):
  200. C esi &src[size]
  201. C edi &dst[2*size-3]
  202. movl -4(%esi), %eax
  203. mull -8(%esi) C src[size-1]*src[size-2]
  204. addl %eax, 0(%edi)
  205. adcl $0, %edx
  206. movl %edx, 4(%edi) C dst high limb
  207. C -----------------------------------------------------------------------------
  208. C Left shift of dst[1..2*size-2], high bit shifted out becomes dst[2*size-1].
  209. movl PARAM_SIZE, %eax
  210. negl %eax
  211. addl $1, %eax C -(size-1) and clear carry
  212. L(lshift):
  213. C eax counter, negative
  214. C ebx next limb
  215. C ecx
  216. C edx
  217. C esi
  218. C edi &dst[2*size-4]
  219. C ebp
  220. rcll 8(%edi,%eax,8)
  221. rcll 12(%edi,%eax,8)
  222. incl %eax
  223. jnz L(lshift)
  224. adcl %eax, %eax C high bit out
  225. movl %eax, 8(%edi) C dst most significant limb
  226. C Now add in the squares on the diagonal, namely src[0]^2, src[1]^2, ...,
  227. C src[size-1]^2.  dst[0] hasn't yet been set at all yet, and just gets the
  228. C low limb of src[0]^2.
  229. movl PARAM_SRC, %esi
  230. movl (%esi), %eax C src[0]
  231. mull %eax C src[0]^2
  232. movl PARAM_SIZE, %ecx
  233. leal (%esi,%ecx,4), %esi C src end
  234. negl %ecx C -size
  235. movl %edx, %ebx C initial carry
  236. movl %eax, 12(%edi,%ecx,8) C dst[0]
  237. incl %ecx C -(size-1)
  238. L(diag):
  239. C eax scratch (low product)
  240. C ebx carry limb
  241. C ecx counter, -(size-1) to -1
  242. C edx scratch (high product)
  243. C esi &src[size]
  244. C edi &dst[2*size-3]
  245. C ebp scratch (fetched dst limbs)
  246. movl (%esi,%ecx,4), %eax
  247. mull %eax
  248. addl %ebx, 8(%edi,%ecx,8)
  249. movl %edx, %ebx
  250. adcl %eax, 12(%edi,%ecx,8)
  251. adcl $0, %ebx
  252. incl %ecx
  253. jnz L(diag)
  254. addl %ebx, 8(%edi) C dst most significant limb
  255. popl %ebp
  256. popl %esi
  257. popl %edi
  258. popl %ebx
  259. ret
  260. EPILOGUE()