x86_64-mont.pl 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. #!/usr/bin/env perl
  2. # ====================================================================
  3. # Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
  4. # project. Rights for redistribution and usage in source and binary
  5. # forms are granted according to the OpenSSL license.
  6. # ====================================================================
  7. # October 2005.
  8. #
  9. # Montgomery multiplication routine for x86_64. While it gives modest
  10. # 9% improvement of rsa4096 sign on Opteron, rsa512 sign runs more
  11. # than twice, >2x, as fast. Most common rsa1024 sign is improved by
  12. # respectful 50%. It remains to be seen if loop unrolling and
  13. # dedicated squaring routine can provide further improvement...
  14. $output=shift;
  15. open STDOUT,"| $^X ../perlasm/x86_64-xlate.pl $output";
  16. # int bn_mul_mont(
  17. $rp="%rdi"; # BN_ULONG *rp,
  18. $ap="%rsi"; # const BN_ULONG *ap,
  19. $bp="%rdx"; # const BN_ULONG *bp,
  20. $np="%rcx"; # const BN_ULONG *np,
  21. $n0="%r8"; # const BN_ULONG *n0,
  22. $num="%r9"; # int num);
  23. $lo0="%r10";
  24. $hi0="%r11";
  25. $bp="%r12"; # reassign $bp
  26. $hi1="%r13";
  27. $i="%r14";
  28. $j="%r15";
  29. $m0="%rbx";
  30. $m1="%rbp";
  31. $code=<<___;
  32. .text
  33. .globl bn_mul_mont
  34. .type bn_mul_mont,\@function,6
  35. .align 16
  36. bn_mul_mont:
  37. push %rbx
  38. push %rbp
  39. push %r12
  40. push %r13
  41. push %r14
  42. push %r15
  43. lea 2($num),%rax
  44. mov %rsp,%rbp
  45. neg %rax
  46. lea (%rsp,%rax,8),%rsp # tp=alloca(8*(num+2))
  47. and \$-1024,%rsp # minimize TLB usage
  48. mov %rbp,8(%rsp,$num,8) # tp[num+1]=%rsp
  49. mov %rdx,$bp # $bp reassigned, remember?
  50. mov ($n0),$n0 # pull n0[0] value
  51. xor $i,$i # i=0
  52. xor $j,$j # j=0
  53. mov ($bp),$m0 # m0=bp[0]
  54. mov ($ap),%rax
  55. mulq $m0 # ap[0]*bp[0]
  56. mov %rax,$lo0
  57. mov %rdx,$hi0
  58. imulq $n0,%rax # "tp[0]"*n0
  59. mov %rax,$m1
  60. mulq ($np) # np[0]*m1
  61. add $lo0,%rax # discarded
  62. adc \$0,%rdx
  63. mov %rdx,$hi1
  64. lea 1($j),$j # j++
  65. .L1st:
  66. mov ($ap,$j,8),%rax
  67. mulq $m0 # ap[j]*bp[0]
  68. add $hi0,%rax
  69. adc \$0,%rdx
  70. mov %rax,$lo0
  71. mov %rdx,$hi0
  72. mov ($np,$j,8),%rax
  73. mulq $m1 # np[j]*m1
  74. add $hi1,%rax
  75. adc \$0,%rdx
  76. add $lo0,%rax # np[j]*m1+ap[j]*bp[0]
  77. adc \$0,%rdx
  78. mov %rax,-8(%rsp,$j,8) # tp[j-1]
  79. mov %rdx,$hi1
  80. lea 1($j),$j # j++
  81. cmp $num,$j
  82. jl .L1st
  83. xor %rdx,%rdx
  84. add $hi0,$hi1
  85. adc \$0,%rdx
  86. mov $hi1,-8(%rsp,$num,8)
  87. mov %rdx,(%rsp,$num,8) # store upmost overflow bit
  88. lea 1($i),$i # i++
  89. .align 4
  90. .Louter:
  91. xor $j,$j # j=0
  92. mov ($bp,$i,8),$m0 # m0=bp[i]
  93. mov ($ap),%rax # ap[0]
  94. mulq $m0 # ap[0]*bp[i]
  95. add (%rsp),%rax # ap[0]*bp[i]+tp[0]
  96. adc \$0,%rdx
  97. mov %rax,$lo0
  98. mov %rdx,$hi0
  99. imulq $n0,%rax # tp[0]*n0
  100. mov %rax,$m1
  101. mulq ($np,$j,8) # np[0]*m1
  102. add $lo0,%rax # discarded
  103. adc \$0,%rdx
  104. mov %rdx,$hi1
  105. lea 1($j),$j # j++
  106. .align 4
  107. .Linner:
  108. mov ($ap,$j,8),%rax
  109. mulq $m0 # ap[j]*bp[i]
  110. add $hi0,%rax
  111. adc \$0,%rdx
  112. add (%rsp,$j,8),%rax # ap[j]*bp[i]+tp[j]
  113. adc \$0,%rdx
  114. mov %rax,$lo0
  115. mov %rdx,$hi0
  116. mov ($np,$j,8),%rax
  117. mulq $m1 # np[j]*m1
  118. add $hi1,%rax
  119. adc \$0,%rdx
  120. add $lo0,%rax # np[j]*m1+ap[j]*bp[i]+tp[j]
  121. adc \$0,%rdx
  122. mov %rax,-8(%rsp,$j,8) # tp[j-1]
  123. mov %rdx,$hi1
  124. lea 1($j),$j # j++
  125. cmp $num,$j
  126. jl .Linner
  127. xor %rdx,%rdx
  128. add $hi0,$hi1
  129. adc \$0,%rdx
  130. add (%rsp,$num,8),$hi1 # pull upmost overflow bit
  131. adc \$0,%rdx
  132. mov $hi1,-8(%rsp,$num,8)
  133. mov %rdx,(%rsp,$num,8) # store upmost overflow bit
  134. lea 1($i),$i # i++
  135. cmp $num,$i
  136. jl .Louter
  137. xor $i,$i # i=0
  138. lea -1($num),$j # j=num-1
  139. cmp \$0,%rdx # %rdx still holds upmost overflow bit
  140. jnz .Lsub # CF is cleared by compare with 0
  141. mov (%rsp,$j,8),%rax
  142. cmp ($np,$j,8),%rax # tp[num-1]-np[num-1]
  143. jae .Lsub # if taken CF was cleared by above cmp
  144. .align 4
  145. .Lcopy:
  146. mov (%rsp,$j,8),%rax
  147. mov %rax,($rp,$j,8) # rp[i]=tp[i]
  148. mov $i,(%rsp,$j,8) # zap temporary vector
  149. dec $j
  150. jge .Lcopy
  151. .align 4
  152. .Lexit:
  153. mov 8(%rsp,$num,8),%rsp # restore %rsp
  154. mov \$1,%rax
  155. pop %r15
  156. pop %r14
  157. pop %r13
  158. pop %r12
  159. pop %rbp
  160. pop %rbx
  161. ret
  162. .align 16
  163. .Lsub: mov (%rsp,$i,8),%rax
  164. sbb ($np,$i,8),%rax
  165. mov %rax,($rp,$i,8) # rp[i]=tp[i]-np[j]
  166. lea 1($i),$i # i++
  167. dec $j # doesn't affect CF!
  168. jge .Lsub
  169. lea -1($num),$j # j=num-1
  170. sbb \$0,%rdx
  171. jc .Lcopy # tp was less than np
  172. .align 4
  173. .Lzap: mov $i,(%rsp,$j,8) # zap temporary vector
  174. dec $j
  175. jge .Lzap
  176. jmp .Lexit
  177. .size bn_mul_mont,.-bn_mul_mont
  178. ___
  179. print $code;
  180. close STDOUT;