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

数学计算

开发平台:

Unix_Linux

  1. dnl  AMD K6 mpn_mul_1 -- mpn by limb multiply.
  2. dnl  Copyright 1999, 2000, 2002, 2005 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                           cycles/limb
  20. C P5:
  21. C P6 model 0-8,10-12)            5.5
  22. C P6 model 9  (Banias)
  23. C P6 model 13 (Dothan)           4.87
  24. C P4 model 0  (Willamette)
  25. C P4 model 1  (?)
  26. C P4 model 2  (Northwood)
  27. C P4 model 3  (Prescott)
  28. C P4 model 4  (Nocona)
  29. C K6:                            6.25
  30. C K7:
  31. C K8:
  32. C mp_limb_t mpn_mul_1 (mp_ptr dst, mp_srcptr src, mp_size_t size,
  33. C                      mp_limb_t multiplier);
  34. C mp_limb_t mpn_mul_1c (mp_ptr dst, mp_srcptr src, mp_size_t size,
  35. C                       mp_limb_t multiplier, mp_limb_t carry);
  36. C
  37. C Multiply src,size by mult and store the result in dst,size.
  38. C Return the carry limb from the top of the result.
  39. C
  40. C mpn_mul_1c() accepts an initial carry for the calculation, it's added into
  41. C the low limb of the result.
  42. defframe(PARAM_CARRY,     20)
  43. defframe(PARAM_MULTIPLIER,16)
  44. defframe(PARAM_SIZE,      12)
  45. defframe(PARAM_SRC,       8)
  46. defframe(PARAM_DST,       4)
  47. dnl  minimum 5 because the unrolled code can't handle less
  48. deflit(UNROLL_THRESHOLD, 5)
  49. TEXT
  50. ALIGN(32)
  51. PROLOGUE(mpn_mul_1c)
  52. pushl %esi
  53. deflit(`FRAME',4)
  54. movl PARAM_CARRY, %esi
  55. jmp L(start_nc)
  56. EPILOGUE()
  57. PROLOGUE(mpn_mul_1)
  58. push %esi
  59. deflit(`FRAME',4)
  60. xorl %esi, %esi C initial carry
  61. L(start_nc):
  62. mov PARAM_SIZE, %ecx
  63. push %ebx
  64. FRAME_pushl()
  65. movl PARAM_SRC, %ebx
  66. push %edi
  67. FRAME_pushl()
  68. movl PARAM_DST, %edi
  69. pushl %ebp
  70. FRAME_pushl()
  71. cmpl $UNROLL_THRESHOLD, %ecx
  72. movl PARAM_MULTIPLIER, %ebp
  73. jae L(unroll)
  74. C code offset 0x22 here, close enough to aligned
  75. L(simple):
  76. C eax scratch
  77. C ebx src
  78. C ecx counter
  79. C edx scratch
  80. C esi carry
  81. C edi dst
  82. C ebp multiplier
  83. C
  84. C this loop 8 cycles/limb
  85. movl (%ebx), %eax
  86. addl $4, %ebx
  87. mull %ebp
  88. addl %esi, %eax
  89. movl $0, %esi
  90. adcl %edx, %esi
  91. movl %eax, (%edi)
  92. addl $4, %edi
  93. loop L(simple)
  94. popl %ebp
  95. popl %edi
  96. popl %ebx
  97. movl %esi, %eax
  98. popl %esi
  99. ret
  100. C -----------------------------------------------------------------------------
  101. C The code for each limb is 6 cycles, with instruction decoding being the
  102. C limiting factor.  At 4 limbs/loop and 1 cycle/loop of overhead it's 6.25
  103. C cycles/limb in total.
  104. C
  105. C The secret ingredient to get 6.25 is to start the loop with the mul and
  106. C have the load/store pair at the end.  Rotating the load/store to the top
  107. C is an 0.5 c/l slowdown.  (Some address generation effect probably.)
  108. C
  109. C The whole unrolled loop fits nicely in exactly 80 bytes.
  110. ALIGN(16) C already aligned to 16 here actually
  111. L(unroll):
  112. movl (%ebx), %eax
  113. leal -16(%ebx,%ecx,4), %ebx
  114. leal -16(%edi,%ecx,4), %edi
  115. subl $4, %ecx
  116. negl %ecx
  117. ALIGN(16) C one byte nop for this alignment
  118. L(top):
  119. C eax scratch
  120. C ebx &src[size-4]
  121. C ecx counter
  122. C edx scratch
  123. C esi carry
  124. C edi &dst[size-4]
  125. C ebp multiplier
  126. mull %ebp
  127. addl %esi, %eax
  128. movl $0, %esi
  129. adcl %edx, %esi
  130. movl %eax, (%edi,%ecx,4)
  131. movl 4(%ebx,%ecx,4), %eax
  132. mull %ebp
  133. addl %esi, %eax
  134. movl $0, %esi
  135. adcl %edx, %esi
  136. movl %eax, 4(%edi,%ecx,4)
  137. movl 8(%ebx,%ecx,4), %eax
  138. mull %ebp
  139. addl %esi, %eax
  140. movl $0, %esi
  141. adcl %edx, %esi
  142. movl %eax, 8(%edi,%ecx,4)
  143. movl 12(%ebx,%ecx,4), %eax
  144. mull %ebp
  145. addl %esi, %eax
  146. movl $0, %esi
  147. adcl %edx, %esi
  148. movl %eax, 12(%edi,%ecx,4)
  149. movl 16(%ebx,%ecx,4), %eax
  150. addl $4, %ecx
  151. js L(top)
  152. C eax next src limb
  153. C ebx &src[size-4]
  154. C ecx 0 to 3 representing respectively 4 to 1 further limbs
  155. C edx
  156. C esi carry
  157. C edi &dst[size-4]
  158. testb $2, %cl
  159. jnz L(finish_not_two)
  160. mull %ebp
  161. addl %esi, %eax
  162. movl $0, %esi
  163. adcl %edx, %esi
  164. movl %eax, (%edi,%ecx,4)
  165. movl 4(%ebx,%ecx,4), %eax
  166. mull %ebp
  167. addl %esi, %eax
  168. movl $0, %esi
  169. adcl %edx, %esi
  170. movl %eax, 4(%edi,%ecx,4)
  171. movl 8(%ebx,%ecx,4), %eax
  172. addl $2, %ecx
  173. L(finish_not_two):
  174. testb $1, %cl
  175. jnz L(finish_not_one)
  176. mull %ebp
  177. addl %esi, %eax
  178. movl $0, %esi
  179. adcl %edx, %esi
  180. movl %eax, 8(%edi)
  181. movl 12(%ebx), %eax
  182. L(finish_not_one):
  183. mull %ebp
  184. addl %esi, %eax
  185. popl %ebp
  186. adcl $0, %edx
  187. movl %eax, 12(%edi)
  188. popl %edi
  189. popl %ebx
  190. movl %edx, %eax
  191. popl %esi
  192. ret
  193. EPILOGUE()