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

数学计算

开发平台:

Unix_Linux

  1. dnl  Intel P6 mpn_addmul_1/mpn_submul_1 -- add or subtract mpn multiple.
  2. dnl  Copyright 1999, 2000, 2001, 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)            6.44
  22. C P6 model 9  (Banias)
  23. C P6 model 13 (Dothan)           6.11
  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:
  30. C K7:
  31. C K8:
  32. dnl  P6 UNROLL_COUNT cycles/limb
  33. dnl          8           6.7
  34. dnl         16           6.35
  35. dnl         32           6.3
  36. dnl         64           6.3
  37. dnl  Maximum possible with the current code is 64.
  38. deflit(UNROLL_COUNT, 16)
  39. ifdef(`OPERATION_addmul_1', `
  40. define(M4_inst,        addl)
  41. define(M4_function_1,  mpn_addmul_1)
  42. define(M4_function_1c, mpn_addmul_1c)
  43. define(M4_description, add it to)
  44. define(M4_desc_retval, carry)
  45. ',`ifdef(`OPERATION_submul_1', `
  46. define(M4_inst,        subl)
  47. define(M4_function_1,  mpn_submul_1)
  48. define(M4_function_1c, mpn_submul_1c)
  49. define(M4_description, subtract it from)
  50. define(M4_desc_retval, borrow)
  51. ',`m4_error(`Need OPERATION_addmul_1 or OPERATION_submul_1
  52. ')')')
  53. MULFUNC_PROLOGUE(mpn_addmul_1 mpn_addmul_1c mpn_submul_1 mpn_submul_1c)
  54. C mp_limb_t M4_function_1 (mp_ptr dst, mp_srcptr src, mp_size_t size,
  55. C                            mp_limb_t mult);
  56. C mp_limb_t M4_function_1c (mp_ptr dst, mp_srcptr src, mp_size_t size,
  57. C                             mp_limb_t mult, mp_limb_t carry);
  58. C
  59. C Calculate src,size multiplied by mult and M4_description dst,size.
  60. C Return the M4_desc_retval limb from the top of the result.
  61. C
  62. C This code is pretty much the same as the K6 code.  The unrolled loop is
  63. C the same, but there's just a few scheduling tweaks in the setups and the
  64. C simple loop.
  65. C
  66. C A number of variations have been tried for the unrolled loop, with one or
  67. C two carries, and with loads scheduled earlier, but nothing faster than 6
  68. C cycles/limb has been found.
  69. ifdef(`PIC',`
  70. deflit(UNROLL_THRESHOLD, 5)
  71. ',`
  72. deflit(UNROLL_THRESHOLD, 5)
  73. ')
  74. defframe(PARAM_CARRY,     20)
  75. defframe(PARAM_MULTIPLIER,16)
  76. defframe(PARAM_SIZE,      12)
  77. defframe(PARAM_SRC,       8)
  78. defframe(PARAM_DST,       4)
  79. TEXT
  80. ALIGN(32)
  81. PROLOGUE(M4_function_1c)
  82. pushl %ebx
  83. deflit(`FRAME',4)
  84. movl PARAM_CARRY, %ebx
  85. jmp L(start_nc)
  86. EPILOGUE()
  87. PROLOGUE(M4_function_1)
  88. push %ebx
  89. deflit(`FRAME',4)
  90. xorl %ebx, %ebx C initial carry
  91. L(start_nc):
  92. movl PARAM_SIZE, %ecx
  93. pushl %esi
  94. deflit(`FRAME',8)
  95. movl PARAM_SRC, %esi
  96. pushl %edi
  97. deflit(`FRAME',12)
  98. movl PARAM_DST, %edi
  99. pushl %ebp
  100. deflit(`FRAME',16)
  101. cmpl $UNROLL_THRESHOLD, %ecx
  102. movl PARAM_MULTIPLIER, %ebp
  103. jae L(unroll)
  104. C simple loop
  105. C this is offset 0x22, so close enough to aligned
  106. L(simple):
  107. C eax scratch
  108. C ebx carry
  109. C ecx counter
  110. C edx scratch
  111. C esi src
  112. C edi dst
  113. C ebp multiplier
  114. movl (%esi), %eax
  115. addl $4, %edi
  116. mull %ebp
  117. addl %ebx, %eax
  118. adcl $0, %edx
  119. M4_inst %eax, -4(%edi)
  120. movl %edx, %ebx
  121. adcl $0, %ebx
  122. decl %ecx
  123. leal 4(%esi), %esi
  124. jnz L(simple)
  125. popl %ebp
  126. popl %edi
  127. popl %esi
  128. movl %ebx, %eax
  129. popl %ebx
  130. ret
  131. C------------------------------------------------------------------------------
  132. C VAR_JUMP holds the computed jump temporarily because there's not enough
  133. C registers when doing the mul for the initial two carry limbs.
  134. C
  135. C The add/adc for the initial carry in %ebx is necessary only for the
  136. C mpn_add/submul_1c entry points.  Duplicating the startup code to
  137. C eliminate this for the plain mpn_add/submul_1 doesn't seem like a good
  138. C idea.
  139. dnl  overlapping with parameters already fetched
  140. define(VAR_COUNTER,`PARAM_SIZE')
  141. define(VAR_JUMP,   `PARAM_DST')
  142. C this is offset 0x43, so close enough to aligned
  143. L(unroll):
  144. C eax
  145. C ebx initial carry
  146. C ecx size
  147. C edx
  148. C esi src
  149. C edi dst
  150. C ebp
  151. movl %ecx, %edx
  152. decl %ecx
  153. subl $2, %edx
  154. negl %ecx
  155. shrl $UNROLL_LOG2, %edx
  156. andl $UNROLL_MASK, %ecx
  157. movl %edx, VAR_COUNTER
  158. movl %ecx, %edx
  159. C 15 code bytes per limb
  160. ifdef(`PIC',`
  161. call L(pic_calc)
  162. L(here):
  163. ',`
  164. shll $4, %edx
  165. negl %ecx
  166. leal L(entry) (%edx,%ecx,1), %edx
  167. ')
  168. movl (%esi), %eax C src low limb
  169. movl %edx, VAR_JUMP
  170. leal ifelse(UNROLL_BYTES,256,128+) 4(%esi,%ecx,4), %esi
  171. mull %ebp
  172. addl %ebx, %eax C initial carry (from _1c)
  173. adcl $0, %edx
  174. movl %edx, %ebx C high carry
  175. leal ifelse(UNROLL_BYTES,256,128) (%edi,%ecx,4), %edi
  176. movl VAR_JUMP, %edx
  177. testl $1, %ecx
  178. movl %eax, %ecx C low carry
  179. cmovnz( %ebx, %ecx) C high,low carry other way around
  180. cmovnz( %eax, %ebx)
  181. jmp *%edx
  182. ifdef(`PIC',`
  183. L(pic_calc):
  184. shll $4, %edx
  185. negl %ecx
  186. C See mpn/x86/README about old gas bugs
  187. leal (%edx,%ecx,1), %edx
  188. addl $L(entry)-L(here), %edx
  189. addl (%esp), %edx
  190. ret_internal
  191. ')
  192. C -----------------------------------------------------------
  193. ALIGN(32)
  194. L(top):
  195. deflit(`FRAME',16)
  196. C eax scratch
  197. C ebx carry hi
  198. C ecx carry lo
  199. C edx scratch
  200. C esi src
  201. C edi dst
  202. C ebp multiplier
  203. C
  204. C VAR_COUNTER loop counter
  205. C
  206. C 15 code bytes per limb
  207. addl $UNROLL_BYTES, %edi
  208. L(entry):
  209. deflit(CHUNK_COUNT,2)
  210. forloop(`i', 0, UNROLL_COUNT/CHUNK_COUNT-1, `
  211. deflit(`disp0', eval(i*4*CHUNK_COUNT ifelse(UNROLL_BYTES,256,-128)))
  212. deflit(`disp1', eval(disp0 + 4))
  213. Zdisp( movl, disp0,(%esi), %eax)
  214. mull %ebp
  215. Zdisp( M4_inst,%ecx, disp0,(%edi))
  216. adcl %eax, %ebx
  217. movl %edx, %ecx
  218. adcl $0, %ecx
  219. movl disp1(%esi), %eax
  220. mull %ebp
  221. M4_inst %ebx, disp1(%edi)
  222. adcl %eax, %ecx
  223. movl %edx, %ebx
  224. adcl $0, %ebx
  225. ')
  226. decl VAR_COUNTER
  227. leal UNROLL_BYTES(%esi), %esi
  228. jns L(top)
  229. deflit(`disp0', eval(UNROLL_BYTES ifelse(UNROLL_BYTES,256,-128)))
  230. M4_inst %ecx, disp0(%edi)
  231. movl %ebx, %eax
  232. popl %ebp
  233. popl %edi
  234. popl %esi
  235. popl %ebx
  236. adcl $0, %eax
  237. ret
  238. EPILOGUE()