armv4-mont.pl 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #!/usr/bin/env perl
  2. # ====================================================================
  3. # Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
  4. # project. The module is, however, dual licensed under OpenSSL and
  5. # CRYPTOGAMS licenses depending on where you obtain it. For further
  6. # details see http://www.openssl.org/~appro/cryptogams/.
  7. # ====================================================================
  8. # January 2007.
  9. # Montgomery multiplication for ARMv4.
  10. #
  11. # Performance improvement naturally varies among CPU implementations
  12. # and compilers. The code was observed to provide +65-35% improvement
  13. # [depending on key length, less for longer keys] on ARM920T, and
  14. # +115-80% on Intel IXP425. This is compared to pre-bn_mul_mont code
  15. # base and compiler generated code with in-lined umull and even umlal
  16. # instructions. The latter means that this code didn't really have an
  17. # "advantage" of utilizing some "secret" instruction.
  18. #
  19. # The code is interoperable with Thumb ISA and is rather compact, less
  20. # than 1/2KB. Windows CE port would be trivial, as it's exclusively
  21. # about decorations, ABI and instruction syntax are identical.
  22. while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
  23. open STDOUT,">$output";
  24. $num="r0"; # starts as num argument, but holds &tp[num-1]
  25. $ap="r1";
  26. $bp="r2"; $bi="r2"; $rp="r2";
  27. $np="r3";
  28. $tp="r4";
  29. $aj="r5";
  30. $nj="r6";
  31. $tj="r7";
  32. $n0="r8";
  33. ########### # r9 is reserved by ELF as platform specific, e.g. TLS pointer
  34. $alo="r10"; # sl, gcc uses it to keep @GOT
  35. $ahi="r11"; # fp
  36. $nlo="r12"; # ip
  37. ########### # r13 is stack pointer
  38. $nhi="r14"; # lr
  39. ########### # r15 is program counter
  40. #### argument block layout relative to &tp[num-1], a.k.a. $num
  41. $_rp="$num,#12*4";
  42. # ap permanently resides in r1
  43. $_bp="$num,#13*4";
  44. # np permanently resides in r3
  45. $_n0="$num,#14*4";
  46. $_num="$num,#15*4"; $_bpend=$_num;
  47. $code=<<___;
  48. .text
  49. .global bn_mul_mont
  50. .type bn_mul_mont,%function
  51. .align 2
  52. bn_mul_mont:
  53. stmdb sp!,{r0,r2} @ sp points at argument block
  54. ldr $num,[sp,#3*4] @ load num
  55. cmp $num,#2
  56. movlt r0,#0
  57. addlt sp,sp,#2*4
  58. blt .Labrt
  59. stmdb sp!,{r4-r12,lr} @ save 10 registers
  60. mov $num,$num,lsl#2 @ rescale $num for byte count
  61. sub sp,sp,$num @ alloca(4*num)
  62. sub sp,sp,#4 @ +extra dword
  63. sub $num,$num,#4 @ "num=num-1"
  64. add $tp,$bp,$num @ &bp[num-1]
  65. add $num,sp,$num @ $num to point at &tp[num-1]
  66. ldr $n0,[$_n0] @ &n0
  67. ldr $bi,[$bp] @ bp[0]
  68. ldr $aj,[$ap],#4 @ ap[0],ap++
  69. ldr $nj,[$np],#4 @ np[0],np++
  70. ldr $n0,[$n0] @ *n0
  71. str $tp,[$_bpend] @ save &bp[num]
  72. umull $alo,$ahi,$aj,$bi @ ap[0]*bp[0]
  73. str $n0,[$_n0] @ save n0 value
  74. mul $n0,$alo,$n0 @ "tp[0]"*n0
  75. mov $nlo,#0
  76. umlal $alo,$nlo,$nj,$n0 @ np[0]*n0+"t[0]"
  77. mov $tp,sp
  78. .L1st:
  79. ldr $aj,[$ap],#4 @ ap[j],ap++
  80. mov $alo,$ahi
  81. ldr $nj,[$np],#4 @ np[j],np++
  82. mov $ahi,#0
  83. umlal $alo,$ahi,$aj,$bi @ ap[j]*bp[0]
  84. mov $nhi,#0
  85. umlal $nlo,$nhi,$nj,$n0 @ np[j]*n0
  86. adds $nlo,$nlo,$alo
  87. str $nlo,[$tp],#4 @ tp[j-1]=,tp++
  88. adc $nlo,$nhi,#0
  89. cmp $tp,$num
  90. bne .L1st
  91. adds $nlo,$nlo,$ahi
  92. ldr $tp,[$_bp] @ restore bp
  93. mov $nhi,#0
  94. ldr $n0,[$_n0] @ restore n0
  95. adc $nhi,$nhi,#0
  96. str $nlo,[$num] @ tp[num-1]=
  97. str $nhi,[$num,#4] @ tp[num]=
  98. .Louter:
  99. sub $tj,$num,sp @ "original" $num-1 value
  100. sub $ap,$ap,$tj @ "rewind" ap to &ap[1]
  101. ldr $bi,[$tp,#4]! @ *(++bp)
  102. sub $np,$np,$tj @ "rewind" np to &np[1]
  103. ldr $aj,[$ap,#-4] @ ap[0]
  104. ldr $alo,[sp] @ tp[0]
  105. ldr $nj,[$np,#-4] @ np[0]
  106. ldr $tj,[sp,#4] @ tp[1]
  107. mov $ahi,#0
  108. umlal $alo,$ahi,$aj,$bi @ ap[0]*bp[i]+tp[0]
  109. str $tp,[$_bp] @ save bp
  110. mul $n0,$alo,$n0
  111. mov $nlo,#0
  112. umlal $alo,$nlo,$nj,$n0 @ np[0]*n0+"tp[0]"
  113. mov $tp,sp
  114. .Linner:
  115. ldr $aj,[$ap],#4 @ ap[j],ap++
  116. adds $alo,$ahi,$tj @ +=tp[j]
  117. ldr $nj,[$np],#4 @ np[j],np++
  118. mov $ahi,#0
  119. umlal $alo,$ahi,$aj,$bi @ ap[j]*bp[i]
  120. mov $nhi,#0
  121. umlal $nlo,$nhi,$nj,$n0 @ np[j]*n0
  122. adc $ahi,$ahi,#0
  123. ldr $tj,[$tp,#8] @ tp[j+1]
  124. adds $nlo,$nlo,$alo
  125. str $nlo,[$tp],#4 @ tp[j-1]=,tp++
  126. adc $nlo,$nhi,#0
  127. cmp $tp,$num
  128. bne .Linner
  129. adds $nlo,$nlo,$ahi
  130. mov $nhi,#0
  131. ldr $tp,[$_bp] @ restore bp
  132. adc $nhi,$nhi,#0
  133. ldr $n0,[$_n0] @ restore n0
  134. adds $nlo,$nlo,$tj
  135. ldr $tj,[$_bpend] @ restore &bp[num]
  136. adc $nhi,$nhi,#0
  137. str $nlo,[$num] @ tp[num-1]=
  138. str $nhi,[$num,#4] @ tp[num]=
  139. cmp $tp,$tj
  140. bne .Louter
  141. ldr $rp,[$_rp] @ pull rp
  142. add $num,$num,#4 @ $num to point at &tp[num]
  143. sub $aj,$num,sp @ "original" num value
  144. mov $tp,sp @ "rewind" $tp
  145. mov $ap,$tp @ "borrow" $ap
  146. sub $np,$np,$aj @ "rewind" $np to &np[0]
  147. subs $tj,$tj,$tj @ "clear" carry flag
  148. .Lsub: ldr $tj,[$tp],#4
  149. ldr $nj,[$np],#4
  150. sbcs $tj,$tj,$nj @ tp[j]-np[j]
  151. str $tj,[$rp],#4 @ rp[j]=
  152. teq $tp,$num @ preserve carry
  153. bne .Lsub
  154. sbcs $nhi,$nhi,#0 @ upmost carry
  155. mov $tp,sp @ "rewind" $tp
  156. sub $rp,$rp,$aj @ "rewind" $rp
  157. and $ap,$tp,$nhi
  158. bic $np,$rp,$nhi
  159. orr $ap,$ap,$np @ ap=borrow?tp:rp
  160. .Lcopy: ldr $tj,[$ap],#4 @ copy or in-place refresh
  161. str sp,[$tp],#4 @ zap tp
  162. str $tj,[$rp],#4
  163. cmp $tp,$num
  164. bne .Lcopy
  165. add sp,$num,#4 @ skip over tp[num+1]
  166. ldmia sp!,{r4-r12,lr} @ restore registers
  167. add sp,sp,#2*4 @ skip over {r0,r2}
  168. mov r0,#1
  169. .Labrt: tst lr,#1
  170. moveq pc,lr @ be binary compatible with V4, yet
  171. bx lr @ interoperable with Thumb ISA:-)
  172. .size bn_mul_mont,.-bn_mul_mont
  173. .asciz "Montgomery multiplication for ARMv4, CRYPTOGAMS by <appro\@openssl.org>"
  174. .align 2
  175. ___
  176. $code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4
  177. print $code;
  178. close STDOUT;