sparcv9-mont.pl 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. #! /usr/bin/env perl
  2. # Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
  3. #
  4. # Licensed under the OpenSSL license (the "License"). You may not use
  5. # this file except in compliance with the License. You can obtain a copy
  6. # in the file LICENSE in the source distribution or at
  7. # https://www.openssl.org/source/license.html
  8. # ====================================================================
  9. # Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
  10. # project. The module is, however, dual licensed under OpenSSL and
  11. # CRYPTOGAMS licenses depending on where you obtain it. For further
  12. # details see http://www.openssl.org/~appro/cryptogams/.
  13. # ====================================================================
  14. # December 2005
  15. #
  16. # Pure SPARCv9/8+ and IALU-only bn_mul_mont implementation. The reasons
  17. # for undertaken effort are multiple. First of all, UltraSPARC is not
  18. # the whole SPARCv9 universe and other VIS-free implementations deserve
  19. # optimized code as much. Secondly, newly introduced UltraSPARC T1,
  20. # a.k.a. Niagara, has shared FPU and concurrent FPU-intensive paths,
  21. # such as sparcv9a-mont, will simply sink it. Yes, T1 is equipped with
  22. # several integrated RSA/DSA accelerator circuits accessible through
  23. # kernel driver [only(*)], but having decent user-land software
  24. # implementation is important too. Finally, reasons like desire to
  25. # experiment with dedicated squaring procedure. Yes, this module
  26. # implements one, because it was easiest to draft it in SPARCv9
  27. # instructions...
  28. # (*) Engine accessing the driver in question is on my TODO list.
  29. # For reference, acceleator is estimated to give 6 to 10 times
  30. # improvement on single-threaded RSA sign. It should be noted
  31. # that 6-10x improvement coefficient does not actually mean
  32. # something extraordinary in terms of absolute [single-threaded]
  33. # performance, as SPARCv9 instruction set is by all means least
  34. # suitable for high performance crypto among other 64 bit
  35. # platforms. 6-10x factor simply places T1 in same performance
  36. # domain as say AMD64 and IA-64. Improvement of RSA verify don't
  37. # appear impressive at all, but it's the sign operation which is
  38. # far more critical/interesting.
  39. # You might notice that inner loops are modulo-scheduled:-) This has
  40. # essentially negligible impact on UltraSPARC performance, it's
  41. # Fujitsu SPARC64 V users who should notice and hopefully appreciate
  42. # the advantage... Currently this module surpasses sparcv9a-mont.pl
  43. # by ~20% on UltraSPARC-III and later cores, but recall that sparcv9a
  44. # module still have hidden potential [see TODO list there], which is
  45. # estimated to be larger than 20%...
  46. $output = pop;
  47. open STDOUT,">$output";
  48. # int bn_mul_mont(
  49. $rp="%i0"; # BN_ULONG *rp,
  50. $ap="%i1"; # const BN_ULONG *ap,
  51. $bp="%i2"; # const BN_ULONG *bp,
  52. $np="%i3"; # const BN_ULONG *np,
  53. $n0="%i4"; # const BN_ULONG *n0,
  54. $num="%i5"; # int num);
  55. $frame="STACK_FRAME";
  56. $bias="STACK_BIAS";
  57. $car0="%o0";
  58. $car1="%o1";
  59. $car2="%o2"; # 1 bit
  60. $acc0="%o3";
  61. $acc1="%o4";
  62. $mask="%g1"; # 32 bits, what a waste...
  63. $tmp0="%g4";
  64. $tmp1="%g5";
  65. $i="%l0";
  66. $j="%l1";
  67. $mul0="%l2";
  68. $mul1="%l3";
  69. $tp="%l4";
  70. $apj="%l5";
  71. $npj="%l6";
  72. $tpj="%l7";
  73. $fname="bn_mul_mont_int";
  74. $code=<<___;
  75. #include "sparc_arch.h"
  76. .section ".text",#alloc,#execinstr
  77. .global $fname
  78. .align 32
  79. $fname:
  80. cmp %o5,4 ! 128 bits minimum
  81. bge,pt %icc,.Lenter
  82. sethi %hi(0xffffffff),$mask
  83. retl
  84. clr %o0
  85. .align 32
  86. .Lenter:
  87. save %sp,-$frame,%sp
  88. sll $num,2,$num ! num*=4
  89. or $mask,%lo(0xffffffff),$mask
  90. ld [$n0],$n0
  91. cmp $ap,$bp
  92. and $num,$mask,$num
  93. ld [$bp],$mul0 ! bp[0]
  94. nop
  95. add %sp,$bias,%o7 ! real top of stack
  96. ld [$ap],$car0 ! ap[0] ! redundant in squaring context
  97. sub %o7,$num,%o7
  98. ld [$ap+4],$apj ! ap[1]
  99. and %o7,-1024,%o7
  100. ld [$np],$car1 ! np[0]
  101. sub %o7,$bias,%sp ! alloca
  102. ld [$np+4],$npj ! np[1]
  103. be,pt SIZE_T_CC,.Lbn_sqr_mont
  104. mov 12,$j
  105. mulx $car0,$mul0,$car0 ! ap[0]*bp[0]
  106. mulx $apj,$mul0,$tmp0 !prologue! ap[1]*bp[0]
  107. and $car0,$mask,$acc0
  108. add %sp,$bias+$frame,$tp
  109. ld [$ap+8],$apj !prologue!
  110. mulx $n0,$acc0,$mul1 ! "t[0]"*n0
  111. and $mul1,$mask,$mul1
  112. mulx $car1,$mul1,$car1 ! np[0]*"t[0]"*n0
  113. mulx $npj,$mul1,$acc1 !prologue! np[1]*"t[0]"*n0
  114. srlx $car0,32,$car0
  115. add $acc0,$car1,$car1
  116. ld [$np+8],$npj !prologue!
  117. srlx $car1,32,$car1
  118. mov $tmp0,$acc0 !prologue!
  119. .L1st:
  120. mulx $apj,$mul0,$tmp0
  121. mulx $npj,$mul1,$tmp1
  122. add $acc0,$car0,$car0
  123. ld [$ap+$j],$apj ! ap[j]
  124. and $car0,$mask,$acc0
  125. add $acc1,$car1,$car1
  126. ld [$np+$j],$npj ! np[j]
  127. srlx $car0,32,$car0
  128. add $acc0,$car1,$car1
  129. add $j,4,$j ! j++
  130. mov $tmp0,$acc0
  131. st $car1,[$tp]
  132. cmp $j,$num
  133. mov $tmp1,$acc1
  134. srlx $car1,32,$car1
  135. bl %icc,.L1st
  136. add $tp,4,$tp ! tp++
  137. !.L1st
  138. mulx $apj,$mul0,$tmp0 !epilogue!
  139. mulx $npj,$mul1,$tmp1
  140. add $acc0,$car0,$car0
  141. and $car0,$mask,$acc0
  142. add $acc1,$car1,$car1
  143. srlx $car0,32,$car0
  144. add $acc0,$car1,$car1
  145. st $car1,[$tp]
  146. srlx $car1,32,$car1
  147. add $tmp0,$car0,$car0
  148. and $car0,$mask,$acc0
  149. add $tmp1,$car1,$car1
  150. srlx $car0,32,$car0
  151. add $acc0,$car1,$car1
  152. st $car1,[$tp+4]
  153. srlx $car1,32,$car1
  154. add $car0,$car1,$car1
  155. st $car1,[$tp+8]
  156. srlx $car1,32,$car2
  157. mov 4,$i ! i++
  158. ld [$bp+4],$mul0 ! bp[1]
  159. .Louter:
  160. add %sp,$bias+$frame,$tp
  161. ld [$ap],$car0 ! ap[0]
  162. ld [$ap+4],$apj ! ap[1]
  163. ld [$np],$car1 ! np[0]
  164. ld [$np+4],$npj ! np[1]
  165. ld [$tp],$tmp1 ! tp[0]
  166. ld [$tp+4],$tpj ! tp[1]
  167. mov 12,$j
  168. mulx $car0,$mul0,$car0
  169. mulx $apj,$mul0,$tmp0 !prologue!
  170. add $tmp1,$car0,$car0
  171. ld [$ap+8],$apj !prologue!
  172. and $car0,$mask,$acc0
  173. mulx $n0,$acc0,$mul1
  174. and $mul1,$mask,$mul1
  175. mulx $car1,$mul1,$car1
  176. mulx $npj,$mul1,$acc1 !prologue!
  177. srlx $car0,32,$car0
  178. add $acc0,$car1,$car1
  179. ld [$np+8],$npj !prologue!
  180. srlx $car1,32,$car1
  181. mov $tmp0,$acc0 !prologue!
  182. .Linner:
  183. mulx $apj,$mul0,$tmp0
  184. mulx $npj,$mul1,$tmp1
  185. add $tpj,$car0,$car0
  186. ld [$ap+$j],$apj ! ap[j]
  187. add $acc0,$car0,$car0
  188. add $acc1,$car1,$car1
  189. ld [$np+$j],$npj ! np[j]
  190. and $car0,$mask,$acc0
  191. ld [$tp+8],$tpj ! tp[j]
  192. srlx $car0,32,$car0
  193. add $acc0,$car1,$car1
  194. add $j,4,$j ! j++
  195. mov $tmp0,$acc0
  196. st $car1,[$tp] ! tp[j-1]
  197. srlx $car1,32,$car1
  198. mov $tmp1,$acc1
  199. cmp $j,$num
  200. bl %icc,.Linner
  201. add $tp,4,$tp ! tp++
  202. !.Linner
  203. mulx $apj,$mul0,$tmp0 !epilogue!
  204. mulx $npj,$mul1,$tmp1
  205. add $tpj,$car0,$car0
  206. add $acc0,$car0,$car0
  207. ld [$tp+8],$tpj ! tp[j]
  208. and $car0,$mask,$acc0
  209. add $acc1,$car1,$car1
  210. srlx $car0,32,$car0
  211. add $acc0,$car1,$car1
  212. st $car1,[$tp] ! tp[j-1]
  213. srlx $car1,32,$car1
  214. add $tpj,$car0,$car0
  215. add $tmp0,$car0,$car0
  216. and $car0,$mask,$acc0
  217. add $tmp1,$car1,$car1
  218. add $acc0,$car1,$car1
  219. st $car1,[$tp+4] ! tp[j-1]
  220. srlx $car0,32,$car0
  221. add $i,4,$i ! i++
  222. srlx $car1,32,$car1
  223. add $car0,$car1,$car1
  224. cmp $i,$num
  225. add $car2,$car1,$car1
  226. st $car1,[$tp+8]
  227. srlx $car1,32,$car2
  228. bl,a %icc,.Louter
  229. ld [$bp+$i],$mul0 ! bp[i]
  230. !.Louter
  231. add $tp,12,$tp
  232. .Ltail:
  233. add $np,$num,$np
  234. add $rp,$num,$rp
  235. mov $tp,$ap
  236. sub %g0,$num,%o7 ! k=-num
  237. ba .Lsub
  238. subcc %g0,%g0,%g0 ! clear %icc.c
  239. .align 16
  240. .Lsub:
  241. ld [$tp+%o7],%o0
  242. ld [$np+%o7],%o1
  243. subccc %o0,%o1,%o1 ! tp[j]-np[j]
  244. add $rp,%o7,$i
  245. add %o7,4,%o7
  246. brnz %o7,.Lsub
  247. st %o1,[$i]
  248. subc $car2,0,$car2 ! handle upmost overflow bit
  249. and $tp,$car2,$ap
  250. andn $rp,$car2,$np
  251. or $ap,$np,$ap
  252. sub %g0,$num,%o7
  253. .Lcopy:
  254. ld [$ap+%o7],%o0 ! copy or in-place refresh
  255. st %g0,[$tp+%o7] ! zap tp
  256. st %o0,[$rp+%o7]
  257. add %o7,4,%o7
  258. brnz %o7,.Lcopy
  259. nop
  260. mov 1,%i0
  261. ret
  262. restore
  263. ___
  264. ########
  265. ######## .Lbn_sqr_mont gives up to 20% *overall* improvement over
  266. ######## code without following dedicated squaring procedure.
  267. ########
  268. $sbit="%i2"; # re-use $bp!
  269. $code.=<<___;
  270. .align 32
  271. .Lbn_sqr_mont:
  272. mulx $mul0,$mul0,$car0 ! ap[0]*ap[0]
  273. mulx $apj,$mul0,$tmp0 !prologue!
  274. and $car0,$mask,$acc0
  275. add %sp,$bias+$frame,$tp
  276. ld [$ap+8],$apj !prologue!
  277. mulx $n0,$acc0,$mul1 ! "t[0]"*n0
  278. srlx $car0,32,$car0
  279. and $mul1,$mask,$mul1
  280. mulx $car1,$mul1,$car1 ! np[0]*"t[0]"*n0
  281. mulx $npj,$mul1,$acc1 !prologue!
  282. and $car0,1,$sbit
  283. ld [$np+8],$npj !prologue!
  284. srlx $car0,1,$car0
  285. add $acc0,$car1,$car1
  286. srlx $car1,32,$car1
  287. mov $tmp0,$acc0 !prologue!
  288. .Lsqr_1st:
  289. mulx $apj,$mul0,$tmp0
  290. mulx $npj,$mul1,$tmp1
  291. add $acc0,$car0,$car0 ! ap[j]*a0+c0
  292. add $acc1,$car1,$car1
  293. ld [$ap+$j],$apj ! ap[j]
  294. and $car0,$mask,$acc0
  295. ld [$np+$j],$npj ! np[j]
  296. srlx $car0,32,$car0
  297. add $acc0,$acc0,$acc0
  298. or $sbit,$acc0,$acc0
  299. mov $tmp1,$acc1
  300. srlx $acc0,32,$sbit
  301. add $j,4,$j ! j++
  302. and $acc0,$mask,$acc0
  303. cmp $j,$num
  304. add $acc0,$car1,$car1
  305. st $car1,[$tp]
  306. mov $tmp0,$acc0
  307. srlx $car1,32,$car1
  308. bl %icc,.Lsqr_1st
  309. add $tp,4,$tp ! tp++
  310. !.Lsqr_1st
  311. mulx $apj,$mul0,$tmp0 ! epilogue
  312. mulx $npj,$mul1,$tmp1
  313. add $acc0,$car0,$car0 ! ap[j]*a0+c0
  314. add $acc1,$car1,$car1
  315. and $car0,$mask,$acc0
  316. srlx $car0,32,$car0
  317. add $acc0,$acc0,$acc0
  318. or $sbit,$acc0,$acc0
  319. srlx $acc0,32,$sbit
  320. and $acc0,$mask,$acc0
  321. add $acc0,$car1,$car1
  322. st $car1,[$tp]
  323. srlx $car1,32,$car1
  324. add $tmp0,$car0,$car0 ! ap[j]*a0+c0
  325. add $tmp1,$car1,$car1
  326. and $car0,$mask,$acc0
  327. srlx $car0,32,$car0
  328. add $acc0,$acc0,$acc0
  329. or $sbit,$acc0,$acc0
  330. srlx $acc0,32,$sbit
  331. and $acc0,$mask,$acc0
  332. add $acc0,$car1,$car1
  333. st $car1,[$tp+4]
  334. srlx $car1,32,$car1
  335. add $car0,$car0,$car0
  336. or $sbit,$car0,$car0
  337. add $car0,$car1,$car1
  338. st $car1,[$tp+8]
  339. srlx $car1,32,$car2
  340. ld [%sp+$bias+$frame],$tmp0 ! tp[0]
  341. ld [%sp+$bias+$frame+4],$tmp1 ! tp[1]
  342. ld [%sp+$bias+$frame+8],$tpj ! tp[2]
  343. ld [$ap+4],$mul0 ! ap[1]
  344. ld [$ap+8],$apj ! ap[2]
  345. ld [$np],$car1 ! np[0]
  346. ld [$np+4],$npj ! np[1]
  347. mulx $n0,$tmp0,$mul1
  348. mulx $mul0,$mul0,$car0
  349. and $mul1,$mask,$mul1
  350. mulx $car1,$mul1,$car1
  351. mulx $npj,$mul1,$acc1
  352. add $tmp0,$car1,$car1
  353. and $car0,$mask,$acc0
  354. ld [$np+8],$npj ! np[2]
  355. srlx $car1,32,$car1
  356. add $tmp1,$car1,$car1
  357. srlx $car0,32,$car0
  358. add $acc0,$car1,$car1
  359. and $car0,1,$sbit
  360. add $acc1,$car1,$car1
  361. srlx $car0,1,$car0
  362. mov 12,$j
  363. st $car1,[%sp+$bias+$frame] ! tp[0]=
  364. srlx $car1,32,$car1
  365. add %sp,$bias+$frame+4,$tp
  366. .Lsqr_2nd:
  367. mulx $apj,$mul0,$acc0
  368. mulx $npj,$mul1,$acc1
  369. add $acc0,$car0,$car0
  370. add $tpj,$car1,$car1
  371. ld [$ap+$j],$apj ! ap[j]
  372. and $car0,$mask,$acc0
  373. ld [$np+$j],$npj ! np[j]
  374. srlx $car0,32,$car0
  375. add $acc1,$car1,$car1
  376. ld [$tp+8],$tpj ! tp[j]
  377. add $acc0,$acc0,$acc0
  378. add $j,4,$j ! j++
  379. or $sbit,$acc0,$acc0
  380. srlx $acc0,32,$sbit
  381. and $acc0,$mask,$acc0
  382. cmp $j,$num
  383. add $acc0,$car1,$car1
  384. st $car1,[$tp] ! tp[j-1]
  385. srlx $car1,32,$car1
  386. bl %icc,.Lsqr_2nd
  387. add $tp,4,$tp ! tp++
  388. !.Lsqr_2nd
  389. mulx $apj,$mul0,$acc0
  390. mulx $npj,$mul1,$acc1
  391. add $acc0,$car0,$car0
  392. add $tpj,$car1,$car1
  393. and $car0,$mask,$acc0
  394. srlx $car0,32,$car0
  395. add $acc1,$car1,$car1
  396. add $acc0,$acc0,$acc0
  397. or $sbit,$acc0,$acc0
  398. srlx $acc0,32,$sbit
  399. and $acc0,$mask,$acc0
  400. add $acc0,$car1,$car1
  401. st $car1,[$tp] ! tp[j-1]
  402. srlx $car1,32,$car1
  403. add $car0,$car0,$car0
  404. or $sbit,$car0,$car0
  405. add $car0,$car1,$car1
  406. add $car2,$car1,$car1
  407. st $car1,[$tp+4]
  408. srlx $car1,32,$car2
  409. ld [%sp+$bias+$frame],$tmp1 ! tp[0]
  410. ld [%sp+$bias+$frame+4],$tpj ! tp[1]
  411. ld [$ap+8],$mul0 ! ap[2]
  412. ld [$np],$car1 ! np[0]
  413. ld [$np+4],$npj ! np[1]
  414. mulx $n0,$tmp1,$mul1
  415. and $mul1,$mask,$mul1
  416. mov 8,$i
  417. mulx $mul0,$mul0,$car0
  418. mulx $car1,$mul1,$car1
  419. and $car0,$mask,$acc0
  420. add $tmp1,$car1,$car1
  421. srlx $car0,32,$car0
  422. add %sp,$bias+$frame,$tp
  423. srlx $car1,32,$car1
  424. and $car0,1,$sbit
  425. srlx $car0,1,$car0
  426. mov 4,$j
  427. .Lsqr_outer:
  428. .Lsqr_inner1:
  429. mulx $npj,$mul1,$acc1
  430. add $tpj,$car1,$car1
  431. add $j,4,$j
  432. ld [$tp+8],$tpj
  433. cmp $j,$i
  434. add $acc1,$car1,$car1
  435. ld [$np+$j],$npj
  436. st $car1,[$tp]
  437. srlx $car1,32,$car1
  438. bl %icc,.Lsqr_inner1
  439. add $tp,4,$tp
  440. !.Lsqr_inner1
  441. add $j,4,$j
  442. ld [$ap+$j],$apj ! ap[j]
  443. mulx $npj,$mul1,$acc1
  444. add $tpj,$car1,$car1
  445. ld [$np+$j],$npj ! np[j]
  446. add $acc0,$car1,$car1
  447. ld [$tp+8],$tpj ! tp[j]
  448. add $acc1,$car1,$car1
  449. st $car1,[$tp]
  450. srlx $car1,32,$car1
  451. add $j,4,$j
  452. cmp $j,$num
  453. be,pn %icc,.Lsqr_no_inner2
  454. add $tp,4,$tp
  455. .Lsqr_inner2:
  456. mulx $apj,$mul0,$acc0
  457. mulx $npj,$mul1,$acc1
  458. add $tpj,$car1,$car1
  459. add $acc0,$car0,$car0
  460. ld [$ap+$j],$apj ! ap[j]
  461. and $car0,$mask,$acc0
  462. ld [$np+$j],$npj ! np[j]
  463. srlx $car0,32,$car0
  464. add $acc0,$acc0,$acc0
  465. ld [$tp+8],$tpj ! tp[j]
  466. or $sbit,$acc0,$acc0
  467. add $j,4,$j ! j++
  468. srlx $acc0,32,$sbit
  469. and $acc0,$mask,$acc0
  470. cmp $j,$num
  471. add $acc0,$car1,$car1
  472. add $acc1,$car1,$car1
  473. st $car1,[$tp] ! tp[j-1]
  474. srlx $car1,32,$car1
  475. bl %icc,.Lsqr_inner2
  476. add $tp,4,$tp ! tp++
  477. .Lsqr_no_inner2:
  478. mulx $apj,$mul0,$acc0
  479. mulx $npj,$mul1,$acc1
  480. add $tpj,$car1,$car1
  481. add $acc0,$car0,$car0
  482. and $car0,$mask,$acc0
  483. srlx $car0,32,$car0
  484. add $acc0,$acc0,$acc0
  485. or $sbit,$acc0,$acc0
  486. srlx $acc0,32,$sbit
  487. and $acc0,$mask,$acc0
  488. add $acc0,$car1,$car1
  489. add $acc1,$car1,$car1
  490. st $car1,[$tp] ! tp[j-1]
  491. srlx $car1,32,$car1
  492. add $car0,$car0,$car0
  493. or $sbit,$car0,$car0
  494. add $car0,$car1,$car1
  495. add $car2,$car1,$car1
  496. st $car1,[$tp+4]
  497. srlx $car1,32,$car2
  498. add $i,4,$i ! i++
  499. ld [%sp+$bias+$frame],$tmp1 ! tp[0]
  500. ld [%sp+$bias+$frame+4],$tpj ! tp[1]
  501. ld [$ap+$i],$mul0 ! ap[j]
  502. ld [$np],$car1 ! np[0]
  503. ld [$np+4],$npj ! np[1]
  504. mulx $n0,$tmp1,$mul1
  505. and $mul1,$mask,$mul1
  506. add $i,4,$tmp0
  507. mulx $mul0,$mul0,$car0
  508. mulx $car1,$mul1,$car1
  509. and $car0,$mask,$acc0
  510. add $tmp1,$car1,$car1
  511. srlx $car0,32,$car0
  512. add %sp,$bias+$frame,$tp
  513. srlx $car1,32,$car1
  514. and $car0,1,$sbit
  515. srlx $car0,1,$car0
  516. cmp $tmp0,$num ! i<num-1
  517. bl %icc,.Lsqr_outer
  518. mov 4,$j
  519. .Lsqr_last:
  520. mulx $npj,$mul1,$acc1
  521. add $tpj,$car1,$car1
  522. add $j,4,$j
  523. ld [$tp+8],$tpj
  524. cmp $j,$i
  525. add $acc1,$car1,$car1
  526. ld [$np+$j],$npj
  527. st $car1,[$tp]
  528. srlx $car1,32,$car1
  529. bl %icc,.Lsqr_last
  530. add $tp,4,$tp
  531. !.Lsqr_last
  532. mulx $npj,$mul1,$acc1
  533. add $tpj,$car1,$car1
  534. add $acc0,$car1,$car1
  535. add $acc1,$car1,$car1
  536. st $car1,[$tp]
  537. srlx $car1,32,$car1
  538. add $car0,$car0,$car0 ! recover $car0
  539. or $sbit,$car0,$car0
  540. add $car0,$car1,$car1
  541. add $car2,$car1,$car1
  542. st $car1,[$tp+4]
  543. srlx $car1,32,$car2
  544. ba .Ltail
  545. add $tp,8,$tp
  546. .type $fname,#function
  547. .size $fname,(.-$fname)
  548. .asciz "Montgomery Multipltication for SPARCv9, CRYPTOGAMS by <appro\@openssl.org>"
  549. .align 32
  550. ___
  551. $code =~ s/\`([^\`]*)\`/eval($1)/gem;
  552. print $code;
  553. close STDOUT;