sparcv9-mont.pl 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. #! /usr/bin/env perl
  2. # Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
  3. #
  4. # Licensed under the Apache License 2.0 (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@openssl.org> 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, accelerator 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 and open STDOUT,">$output";
  47. # int bn_mul_mont(
  48. $rp="%i0"; # BN_ULONG *rp,
  49. $ap="%i1"; # const BN_ULONG *ap,
  50. $bp="%i2"; # const BN_ULONG *bp,
  51. $np="%i3"; # const BN_ULONG *np,
  52. $n0="%i4"; # const BN_ULONG *n0,
  53. $num="%i5"; # int num);
  54. $frame="STACK_FRAME";
  55. $bias="STACK_BIAS";
  56. $car0="%o0";
  57. $car1="%o1";
  58. $car2="%o2"; # 1 bit
  59. $acc0="%o3";
  60. $acc1="%o4";
  61. $mask="%g1"; # 32 bits, what a waste...
  62. $tmp0="%g4";
  63. $tmp1="%g5";
  64. $i="%l0";
  65. $j="%l1";
  66. $mul0="%l2";
  67. $mul1="%l3";
  68. $tp="%l4";
  69. $apj="%l5";
  70. $npj="%l6";
  71. $tpj="%l7";
  72. $fname="bn_mul_mont_int";
  73. $code=<<___;
  74. #ifndef __ASSEMBLER__
  75. # define __ASSEMBLER__ 1
  76. #endif
  77. #include "crypto/sparc_arch.h"
  78. .section ".text",#alloc,#execinstr
  79. .global $fname
  80. .align 32
  81. $fname:
  82. cmp %o5,4 ! 128 bits minimum
  83. bge,pt %icc,.Lenter
  84. sethi %hi(0xffffffff),$mask
  85. retl
  86. clr %o0
  87. .align 32
  88. .Lenter:
  89. save %sp,-$frame,%sp
  90. sll $num,2,$num ! num*=4
  91. or $mask,%lo(0xffffffff),$mask
  92. ld [$n0],$n0
  93. cmp $ap,$bp
  94. and $num,$mask,$num
  95. ld [$bp],$mul0 ! bp[0]
  96. nop
  97. add %sp,$bias,%o7 ! real top of stack
  98. ld [$ap],$car0 ! ap[0] ! redundant in squaring context
  99. sub %o7,$num,%o7
  100. ld [$ap+4],$apj ! ap[1]
  101. and %o7,-1024,%o7
  102. ld [$np],$car1 ! np[0]
  103. sub %o7,$bias,%sp ! alloca
  104. ld [$np+4],$npj ! np[1]
  105. be,pt SIZE_T_CC,.Lbn_sqr_mont
  106. mov 12,$j
  107. mulx $car0,$mul0,$car0 ! ap[0]*bp[0]
  108. mulx $apj,$mul0,$tmp0 !prologue! ap[1]*bp[0]
  109. and $car0,$mask,$acc0
  110. add %sp,$bias+$frame,$tp
  111. ld [$ap+8],$apj !prologue!
  112. mulx $n0,$acc0,$mul1 ! "t[0]"*n0
  113. and $mul1,$mask,$mul1
  114. mulx $car1,$mul1,$car1 ! np[0]*"t[0]"*n0
  115. mulx $npj,$mul1,$acc1 !prologue! np[1]*"t[0]"*n0
  116. srlx $car0,32,$car0
  117. add $acc0,$car1,$car1
  118. ld [$np+8],$npj !prologue!
  119. srlx $car1,32,$car1
  120. mov $tmp0,$acc0 !prologue!
  121. .L1st:
  122. mulx $apj,$mul0,$tmp0
  123. mulx $npj,$mul1,$tmp1
  124. add $acc0,$car0,$car0
  125. ld [$ap+$j],$apj ! ap[j]
  126. and $car0,$mask,$acc0
  127. add $acc1,$car1,$car1
  128. ld [$np+$j],$npj ! np[j]
  129. srlx $car0,32,$car0
  130. add $acc0,$car1,$car1
  131. add $j,4,$j ! j++
  132. mov $tmp0,$acc0
  133. st $car1,[$tp]
  134. cmp $j,$num
  135. mov $tmp1,$acc1
  136. srlx $car1,32,$car1
  137. bl %icc,.L1st
  138. add $tp,4,$tp ! tp++
  139. !.L1st
  140. mulx $apj,$mul0,$tmp0 !epilogue!
  141. mulx $npj,$mul1,$tmp1
  142. add $acc0,$car0,$car0
  143. and $car0,$mask,$acc0
  144. add $acc1,$car1,$car1
  145. srlx $car0,32,$car0
  146. add $acc0,$car1,$car1
  147. st $car1,[$tp]
  148. srlx $car1,32,$car1
  149. add $tmp0,$car0,$car0
  150. and $car0,$mask,$acc0
  151. add $tmp1,$car1,$car1
  152. srlx $car0,32,$car0
  153. add $acc0,$car1,$car1
  154. st $car1,[$tp+4]
  155. srlx $car1,32,$car1
  156. add $car0,$car1,$car1
  157. st $car1,[$tp+8]
  158. srlx $car1,32,$car2
  159. mov 4,$i ! i++
  160. ld [$bp+4],$mul0 ! bp[1]
  161. .Louter:
  162. add %sp,$bias+$frame,$tp
  163. ld [$ap],$car0 ! ap[0]
  164. ld [$ap+4],$apj ! ap[1]
  165. ld [$np],$car1 ! np[0]
  166. ld [$np+4],$npj ! np[1]
  167. ld [$tp],$tmp1 ! tp[0]
  168. ld [$tp+4],$tpj ! tp[1]
  169. mov 12,$j
  170. mulx $car0,$mul0,$car0
  171. mulx $apj,$mul0,$tmp0 !prologue!
  172. add $tmp1,$car0,$car0
  173. ld [$ap+8],$apj !prologue!
  174. and $car0,$mask,$acc0
  175. mulx $n0,$acc0,$mul1
  176. and $mul1,$mask,$mul1
  177. mulx $car1,$mul1,$car1
  178. mulx $npj,$mul1,$acc1 !prologue!
  179. srlx $car0,32,$car0
  180. add $acc0,$car1,$car1
  181. ld [$np+8],$npj !prologue!
  182. srlx $car1,32,$car1
  183. mov $tmp0,$acc0 !prologue!
  184. .Linner:
  185. mulx $apj,$mul0,$tmp0
  186. mulx $npj,$mul1,$tmp1
  187. add $tpj,$car0,$car0
  188. ld [$ap+$j],$apj ! ap[j]
  189. add $acc0,$car0,$car0
  190. add $acc1,$car1,$car1
  191. ld [$np+$j],$npj ! np[j]
  192. and $car0,$mask,$acc0
  193. ld [$tp+8],$tpj ! tp[j]
  194. srlx $car0,32,$car0
  195. add $acc0,$car1,$car1
  196. add $j,4,$j ! j++
  197. mov $tmp0,$acc0
  198. st $car1,[$tp] ! tp[j-1]
  199. srlx $car1,32,$car1
  200. mov $tmp1,$acc1
  201. cmp $j,$num
  202. bl %icc,.Linner
  203. add $tp,4,$tp ! tp++
  204. !.Linner
  205. mulx $apj,$mul0,$tmp0 !epilogue!
  206. mulx $npj,$mul1,$tmp1
  207. add $tpj,$car0,$car0
  208. add $acc0,$car0,$car0
  209. ld [$tp+8],$tpj ! tp[j]
  210. and $car0,$mask,$acc0
  211. add $acc1,$car1,$car1
  212. srlx $car0,32,$car0
  213. add $acc0,$car1,$car1
  214. st $car1,[$tp] ! tp[j-1]
  215. srlx $car1,32,$car1
  216. add $tpj,$car0,$car0
  217. add $tmp0,$car0,$car0
  218. and $car0,$mask,$acc0
  219. add $tmp1,$car1,$car1
  220. add $acc0,$car1,$car1
  221. st $car1,[$tp+4] ! tp[j-1]
  222. srlx $car0,32,$car0
  223. add $i,4,$i ! i++
  224. srlx $car1,32,$car1
  225. add $car0,$car1,$car1
  226. cmp $i,$num
  227. add $car2,$car1,$car1
  228. st $car1,[$tp+8]
  229. srlx $car1,32,$car2
  230. bl,a %icc,.Louter
  231. ld [$bp+$i],$mul0 ! bp[i]
  232. !.Louter
  233. add $tp,12,$tp
  234. .Ltail:
  235. add $np,$num,$np
  236. add $rp,$num,$rp
  237. sub %g0,$num,%o7 ! k=-num
  238. ba .Lsub
  239. subcc %g0,%g0,%g0 ! clear %icc.c
  240. .align 16
  241. .Lsub:
  242. ld [$tp+%o7],%o0
  243. ld [$np+%o7],%o1
  244. subccc %o0,%o1,%o1 ! tp[j]-np[j]
  245. add $rp,%o7,$i
  246. add %o7,4,%o7
  247. brnz %o7,.Lsub
  248. st %o1,[$i]
  249. subccc $car2,0,$car2 ! handle upmost overflow bit
  250. sub %g0,$num,%o7
  251. .Lcopy:
  252. ld [$tp+%o7],%o1 ! conditional copy
  253. ld [$rp+%o7],%o0
  254. st %g0,[$tp+%o7] ! zap tp
  255. movcs %icc,%o1,%o0
  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="%o5";
  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,$sbit,$sbit
  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. add $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,$sbit,$sbit
  393. and $car0,$mask,$acc0
  394. srlx $car0,32,$car0
  395. add $acc1,$car1,$car1
  396. add $acc0,$acc0,$acc0
  397. add $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. add $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. srlx $car1,32,$tmp0
  447. and $car1,$mask,$car1
  448. add $tmp0,$sbit,$sbit
  449. add $acc0,$car1,$car1
  450. ld [$tp+8],$tpj ! tp[j]
  451. add $acc1,$car1,$car1
  452. st $car1,[$tp]
  453. srlx $car1,32,$car1
  454. add $j,4,$j
  455. cmp $j,$num
  456. be,pn %icc,.Lsqr_no_inner2
  457. add $tp,4,$tp
  458. .Lsqr_inner2:
  459. mulx $apj,$mul0,$acc0
  460. mulx $npj,$mul1,$acc1
  461. add $tpj,$sbit,$sbit
  462. add $acc0,$car0,$car0
  463. ld [$ap+$j],$apj ! ap[j]
  464. and $car0,$mask,$acc0
  465. ld [$np+$j],$npj ! np[j]
  466. srlx $car0,32,$car0
  467. add $acc0,$acc0,$acc0
  468. ld [$tp+8],$tpj ! tp[j]
  469. add $sbit,$acc0,$acc0
  470. add $j,4,$j ! j++
  471. srlx $acc0,32,$sbit
  472. and $acc0,$mask,$acc0
  473. cmp $j,$num
  474. add $acc0,$car1,$car1
  475. add $acc1,$car1,$car1
  476. st $car1,[$tp] ! tp[j-1]
  477. srlx $car1,32,$car1
  478. bl %icc,.Lsqr_inner2
  479. add $tp,4,$tp ! tp++
  480. .Lsqr_no_inner2:
  481. mulx $apj,$mul0,$acc0
  482. mulx $npj,$mul1,$acc1
  483. add $tpj,$sbit,$sbit
  484. add $acc0,$car0,$car0
  485. and $car0,$mask,$acc0
  486. srlx $car0,32,$car0
  487. add $acc0,$acc0,$acc0
  488. add $sbit,$acc0,$acc0
  489. srlx $acc0,32,$sbit
  490. and $acc0,$mask,$acc0
  491. add $acc0,$car1,$car1
  492. add $acc1,$car1,$car1
  493. st $car1,[$tp] ! tp[j-1]
  494. srlx $car1,32,$car1
  495. add $car0,$car0,$car0
  496. add $sbit,$car0,$car0
  497. add $car0,$car1,$car1
  498. add $car2,$car1,$car1
  499. st $car1,[$tp+4]
  500. srlx $car1,32,$car2
  501. add $i,4,$i ! i++
  502. ld [%sp+$bias+$frame],$tmp1 ! tp[0]
  503. ld [%sp+$bias+$frame+4],$tpj ! tp[1]
  504. ld [$ap+$i],$mul0 ! ap[j]
  505. ld [$np],$car1 ! np[0]
  506. ld [$np+4],$npj ! np[1]
  507. mulx $n0,$tmp1,$mul1
  508. and $mul1,$mask,$mul1
  509. add $i,4,$tmp0
  510. mulx $mul0,$mul0,$car0
  511. mulx $car1,$mul1,$car1
  512. and $car0,$mask,$acc0
  513. add $tmp1,$car1,$car1
  514. srlx $car0,32,$car0
  515. add %sp,$bias+$frame,$tp
  516. srlx $car1,32,$car1
  517. and $car0,1,$sbit
  518. srlx $car0,1,$car0
  519. cmp $tmp0,$num ! i<num-1
  520. bl %icc,.Lsqr_outer
  521. mov 4,$j
  522. .Lsqr_last:
  523. mulx $npj,$mul1,$acc1
  524. add $tpj,$car1,$car1
  525. add $j,4,$j
  526. ld [$tp+8],$tpj
  527. cmp $j,$i
  528. add $acc1,$car1,$car1
  529. ld [$np+$j],$npj
  530. st $car1,[$tp]
  531. srlx $car1,32,$car1
  532. bl %icc,.Lsqr_last
  533. add $tp,4,$tp
  534. !.Lsqr_last
  535. mulx $npj,$mul1,$acc1
  536. add $tpj,$acc0,$acc0
  537. srlx $acc0,32,$tmp0
  538. and $acc0,$mask,$acc0
  539. add $tmp0,$sbit,$sbit
  540. add $acc0,$car1,$car1
  541. add $acc1,$car1,$car1
  542. st $car1,[$tp]
  543. srlx $car1,32,$car1
  544. add $car0,$car0,$car0 ! recover $car0
  545. add $sbit,$car0,$car0
  546. add $car0,$car1,$car1
  547. add $car2,$car1,$car1
  548. st $car1,[$tp+4]
  549. srlx $car1,32,$car2
  550. ba .Ltail
  551. add $tp,8,$tp
  552. .type $fname,#function
  553. .size $fname,(.-$fname)
  554. .asciz "Montgomery Multiplication for SPARCv9, CRYPTOGAMS by <appro\@openssl.org>"
  555. .align 32
  556. ___
  557. $code =~ s/\`([^\`]*)\`/eval($1)/gem;
  558. print $code;
  559. close STDOUT or die "error closing STDOUT: $!";