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

数学计算

开发平台:

Unix_Linux

  1. dnl  AMD64 mpn_mul_basecase.
  2. dnl  Contributed to the GNU project by Torbjorn Granlund and David Harvey.
  3. dnl  Copyright 2008 Free Software Foundation, Inc.
  4. dnl  This file is part of the GNU MP Library.
  5. dnl  The GNU MP Library is free software; you can redistribute it and/or modify
  6. dnl  it under the terms of the GNU Lesser General Public License as published
  7. dnl  by the Free Software Foundation; either version 3 of the License, or (at
  8. dnl  your option) any later version.
  9. dnl  The GNU MP Library is distributed in the hope that it will be useful, but
  10. dnl  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  11. dnl  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
  12. dnl  License for more details.
  13. dnl  You should have received a copy of the GNU Lesser General Public License
  14. dnl  along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.
  15. include(`../config.m4')
  16. C      cycles/limb
  17. C K8,K9:  2.375
  18. C K10:  2.375
  19. C P4:  ?
  20. C P6-15:  4.45
  21. C The inner loops of this code are the result of running a code generation and
  22. C optimization tool suite written by David Harvey and Torbjorn Granlund.
  23. C TODO
  24. C  * Use fewer registers.  (how??? I can't see it -- david)
  25. C  * Avoid some "mov $0,r" and instead use "xor r,r".
  26. C  * Can the top of each L(addmul_outer_n) prologue be folded into the
  27. C    mul_1/mul_2 prologues, saving a LEA (%rip)? It would slow down the
  28. C    case where vn = 1 or 2; is it worth it?
  29. C INPUT PARAMETERS
  30. define(`rp',      `%rdi')
  31. define(`up',      `%rsi')
  32. define(`un_param',`%rdx')
  33. define(`vp',      `%rcx')
  34. define(`vn',      `%r8')
  35. define(`v0', `%r12')
  36. define(`v1', `%r9')
  37. define(`w0', `%rbx')
  38. define(`w1', `%r15')
  39. define(`w2', `%rbp')
  40. define(`w3', `%r10')
  41. define(`n',  `%r11')
  42. define(`outer_addr', `%r14')
  43. define(`un',  `%r13')
  44. ASM_START()
  45. TEXT
  46. ALIGN(16)
  47. PROLOGUE(mpn_mul_basecase)
  48. push %rbx
  49. push %rbp
  50. push %r12
  51. push %r13
  52. push %r14
  53. push %r15
  54. xor R32(un), R32(un)
  55. mov (up), %rax
  56. mov (vp), v0
  57. sub un_param, un C rdx used by mul
  58. mov un, n
  59. mov R32(un_param), R32(w0)
  60. lea (rp,un_param,8), rp
  61. lea (up,un_param,8), up
  62. mul v0
  63. test $1, R8(vn)
  64. jz L(mul_2)
  65. C ===========================================================
  66. C     mul_1 for vp[0] if vn is odd
  67. L(mul_1):
  68. and $3, R32(w0)
  69. jz L(mul_1_prologue_0)
  70. cmp $2, R32(w0)
  71. jc L(mul_1_prologue_1)
  72. jz L(mul_1_prologue_2)
  73. jmp L(mul_1_prologue_3)
  74. L(mul_1_prologue_0):
  75. mov %rax, w2
  76. mov %rdx, w3 C note: already w0 == 0
  77. lea L(addmul_outer_0)(%rip), outer_addr
  78. jmp L(mul_1_entry_0)
  79. L(mul_1_prologue_1):
  80. cmp $-1, un
  81. jne 2f
  82. mov %rax, -8(rp)
  83. mov %rdx, (rp)
  84. jmp L(ret)
  85. 2: add $1, n
  86. lea L(addmul_outer_1)(%rip), outer_addr
  87. mov %rax, w1
  88. mov %rdx, w2
  89. xor R32(w3), R32(w3)
  90. mov (up,n,8), %rax
  91. jmp L(mul_1_entry_1)
  92. L(mul_1_prologue_2):
  93. add $-2, n
  94. lea L(addmul_outer_2)(%rip), outer_addr
  95. mov %rax, w0
  96. mov %rdx, w1
  97. mov 24(up,n,8), %rax
  98. xor R32(w2), R32(w2)
  99. xor R32(w3), R32(w3)
  100. jmp L(mul_1_entry_2)
  101. L(mul_1_prologue_3):
  102. add $-1, n
  103. lea L(addmul_outer_3)(%rip), outer_addr
  104. mov %rax, w3
  105. mov %rdx, w0
  106. jmp L(mul_1_entry_3)
  107. C this loop is 10 c/loop = 2.5 c/l on K8, for all up/rp alignments
  108. ALIGN(16)
  109. L(mul_1_top):
  110. mov w0, -16(rp,n,8)
  111. add %rax, w1
  112. mov (up,n,8), %rax
  113. adc %rdx, w2
  114. L(mul_1_entry_1):
  115. xor R32(w0), R32(w0)
  116. mul v0
  117. mov w1, -8(rp,n,8)
  118. add %rax, w2
  119. adc %rdx, w3
  120. L(mul_1_entry_0):
  121. mov 8(up,n,8), %rax
  122. mul v0
  123. mov w2, (rp,n,8)
  124. add %rax, w3
  125. adc %rdx, w0
  126. L(mul_1_entry_3):
  127. mov 16(up,n,8), %rax
  128. mul v0
  129. mov w3, 8(rp,n,8)
  130. xor R32(w2), R32(w2) C zero
  131. mov w2, w3 C zero
  132. add %rax, w0
  133. mov 24(up,n,8), %rax
  134. mov w2, w1 C zero
  135. adc %rdx, w1
  136. L(mul_1_entry_2):
  137. mul v0
  138. add $4, n
  139. js L(mul_1_top)
  140. mov w0, -16(rp)
  141. add %rax, w1
  142. mov w1, -8(rp)
  143. adc %rdx, w2
  144. mov w2, (rp)
  145. add $-1, vn C vn -= 1
  146. jz L(ret)
  147. mov 8(vp), v0
  148. mov 16(vp), v1
  149. lea 8(vp), vp C vp += 1
  150. lea 8(rp), rp C rp += 1
  151. jmp *outer_addr
  152. C ===========================================================
  153. C     mul_2 for vp[0], vp[1] if vn is even
  154. ALIGN(16)
  155. L(mul_2):
  156. mov 8(vp), v1
  157. and $3, R32(w0)
  158. jz L(mul_2_prologue_0)
  159. cmp $2, R32(w0)
  160. jz L(mul_2_prologue_2)
  161. jc L(mul_2_prologue_1)
  162. L(mul_2_prologue_3):
  163. lea L(addmul_outer_3)(%rip), outer_addr
  164. add $2, n
  165. mov %rax, -16(rp,n,8)
  166. mov %rdx, w2
  167. xor R32(w3), R32(w3)
  168. xor R32(w0), R32(w0)
  169. mov -16(up,n,8), %rax
  170. jmp L(mul_2_entry_3)
  171. ALIGN(16)
  172. L(mul_2_prologue_0):
  173. add $3, n
  174. mov %rax, w0
  175. mov %rdx, w1
  176. xor R32(w2), R32(w2)
  177. mov -24(up,n,8), %rax
  178. lea L(addmul_outer_0)(%rip), outer_addr
  179. jmp L(mul_2_entry_0)
  180. ALIGN(16)
  181. L(mul_2_prologue_1):
  182. mov %rax, w3
  183. mov %rdx, w0
  184. xor R32(w1), R32(w1)
  185. lea L(addmul_outer_1)(%rip), outer_addr
  186. jmp L(mul_2_entry_1)
  187. ALIGN(16)
  188. L(mul_2_prologue_2):
  189. add $1, n
  190. lea L(addmul_outer_2)(%rip), outer_addr
  191. mov $0, R32(w0)
  192. mov $0, R32(w1)
  193. mov %rax, w2
  194. mov -8(up,n,8), %rax
  195. mov %rdx, w3
  196. jmp L(mul_2_entry_2)
  197. C this loop is 18 c/loop = 2.25 c/l on K8, for all up/rp alignments
  198. ALIGN(16)
  199. L(mul_2_top):
  200. mov -32(up,n,8), %rax
  201. mul v1
  202. add %rax, w0
  203. adc %rdx, w1
  204. mov -24(up,n,8), %rax
  205. xor R32(w2), R32(w2)
  206. mul v0
  207. add %rax, w0
  208. mov -24(up,n,8), %rax
  209. adc %rdx, w1
  210. adc $0, R32(w2)
  211. L(mul_2_entry_0):
  212. mul v1
  213. add %rax, w1
  214. mov w0, -24(rp,n,8)
  215. adc %rdx, w2
  216. mov -16(up,n,8), %rax
  217. mul v0
  218. mov $0, R32(w3)
  219. add %rax, w1
  220. adc %rdx, w2
  221. mov -16(up,n,8), %rax
  222. adc $0, R32(w3)
  223. mov $0, R32(w0)
  224. mov w1, -16(rp,n,8)
  225. L(mul_2_entry_3):
  226. mul v1
  227. add %rax, w2
  228. mov -8(up,n,8), %rax
  229. adc %rdx, w3
  230. mov $0, R32(w1)
  231. mul v0
  232. add %rax, w2
  233. mov -8(up,n,8), %rax
  234. adc %rdx, w3
  235. adc R32(w1), R32(w0) C adc $0, w0
  236. L(mul_2_entry_2):
  237. mul v1
  238. add %rax, w3
  239. mov w2, -8(rp,n,8)
  240. adc %rdx, w0
  241. mov (up,n,8), %rax
  242. mul v0
  243. add %rax, w3
  244. adc %rdx, w0
  245. adc $0, R32(w1)
  246. L(mul_2_entry_1):
  247. add $4, n
  248. mov w3, -32(rp,n,8)
  249. js L(mul_2_top)
  250. mov -32(up,n,8), %rax
  251. mul v1
  252. add %rax, w0
  253. mov w0, (rp)
  254. adc %rdx, w1
  255. mov w1, 8(rp)
  256. add $-2, vn C vn -= 2
  257. jz L(ret)
  258. mov 16(vp), v0
  259. mov 24(vp), v1
  260. lea 16(vp), vp C vp += 2
  261. lea 16(rp), rp C rp += 2
  262. jmp *outer_addr
  263. C ===========================================================
  264. C     addmul_2 for remaining vp's
  265. C in the following prologues, we reuse un to store the
  266. C adjusted value of n that is reloaded on each iteration
  267. L(addmul_outer_0):
  268. add $3, un
  269. lea 0(%rip), outer_addr
  270. mov un, n
  271. mov -24(up,un,8), %rax
  272. mul v0
  273. mov %rax, w0
  274. mov -24(up,un,8), %rax
  275. mov %rdx, w1
  276. xor R32(w2), R32(w2)
  277. jmp L(addmul_entry_0)
  278. L(addmul_outer_1):
  279. mov un, n
  280. mov (up,un,8), %rax
  281. mul v0
  282. mov %rax, w3
  283. mov (up,un,8), %rax
  284. mov %rdx, w0
  285. xor R32(w1), R32(w1)
  286. jmp L(addmul_entry_1)
  287. L(addmul_outer_2):
  288. add $1, un
  289. lea 0(%rip), outer_addr
  290. mov un, n
  291. mov -8(up,un,8), %rax
  292. mul v0
  293. xor R32(w0), R32(w0)
  294. mov %rax, w2
  295. xor R32(w1), R32(w1)
  296. mov %rdx, w3
  297. mov -8(up,un,8), %rax
  298. jmp L(addmul_entry_2)
  299. L(addmul_outer_3):
  300. add $2, un
  301. lea 0(%rip), outer_addr
  302. mov un, n
  303. mov -16(up,un,8), %rax
  304. xor R32(w3), R32(w3)
  305. mul v0
  306. mov %rax, w1
  307. mov -16(up,un,8), %rax
  308. mov %rdx, w2
  309. jmp L(addmul_entry_3)
  310. C this loop is 19 c/loop = 2.375 c/l on K8, for all up/rp alignments
  311. ALIGN(16)
  312. L(addmul_top):
  313. add w3, -32(rp,n,8)
  314. adc %rax, w0
  315. mov -24(up,n,8), %rax
  316. adc %rdx, w1
  317. xor R32(w2), R32(w2)
  318. mul v0
  319. add %rax, w0
  320. mov -24(up,n,8), %rax
  321. adc %rdx, w1
  322. adc R32(w2), R32(w2) C adc $0, w2
  323. L(addmul_entry_0):
  324. mul v1
  325. xor R32(w3), R32(w3)
  326. add w0, -24(rp,n,8)
  327. adc %rax, w1
  328. mov -16(up,n,8), %rax
  329. adc %rdx, w2
  330. mul v0
  331. add %rax, w1
  332. mov -16(up,n,8), %rax
  333. adc %rdx, w2
  334. adc $0, R32(w3)
  335. L(addmul_entry_3):
  336. mul v1
  337. add w1, -16(rp,n,8)
  338. adc %rax, w2
  339. mov -8(up,n,8), %rax
  340. adc %rdx, w3
  341. mul v0
  342. xor R32(w0), R32(w0)
  343. add %rax, w2
  344. adc %rdx, w3
  345. mov $0, R32(w1)
  346. mov -8(up,n,8), %rax
  347. adc R32(w1), R32(w0) C adc $0, w0
  348. L(addmul_entry_2):
  349. mul v1
  350. add w2, -8(rp,n,8)
  351. adc %rax, w3
  352. adc %rdx, w0
  353. mov (up,n,8), %rax
  354. mul v0
  355. add %rax, w3
  356. mov (up,n,8), %rax
  357. adc %rdx, w0
  358. adc $0, R32(w1)
  359. L(addmul_entry_1):
  360. mul v1
  361. add $4, n
  362. js L(addmul_top)
  363. add w3, -8(rp)
  364. adc %rax, w0
  365. mov w0, (rp)
  366. adc %rdx, w1
  367. mov w1, 8(rp)
  368. add $-2, vn C vn -= 2
  369. jz L(ret)
  370. lea 16(rp), rp C rp += 2
  371. lea 16(vp), vp C vp += 2
  372. mov (vp), v0
  373. mov 8(vp), v1
  374. jmp *outer_addr
  375. ALIGN(16)
  376. L(ret): pop %r15
  377. pop %r14
  378. pop %r13
  379. pop %r12
  380. pop %rbp
  381. pop %rbx
  382. ret
  383. EPILOGUE()