2
0

ia64-mont.pl 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861
  1. #! /usr/bin/env perl
  2. # Copyright 2010-2018 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. # ====================================================================
  10. # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
  11. # project. The module is, however, dual licensed under OpenSSL and
  12. # CRYPTOGAMS licenses depending on where you obtain it. For further
  13. # details see http://www.openssl.org/~appro/cryptogams/.
  14. # ====================================================================
  15. # January 2010
  16. #
  17. # "Teaser" Montgomery multiplication module for IA-64. There are
  18. # several possibilities for improvement:
  19. #
  20. # - modulo-scheduling outer loop would eliminate quite a number of
  21. # stalls after ldf8, xma and getf.sig outside inner loop and
  22. # improve shorter key performance;
  23. # - shorter vector support [with input vectors being fetched only
  24. # once] should be added;
  25. # - 2x unroll with help of n0[1] would make the code scalable on
  26. # "wider" IA-64, "wider" than Itanium 2 that is, which is not of
  27. # acute interest, because upcoming Tukwila's individual cores are
  28. # reportedly based on Itanium 2 design;
  29. # - dedicated squaring procedure(?);
  30. #
  31. # January 2010
  32. #
  33. # Shorter vector support is implemented by zero-padding ap and np
  34. # vectors up to 8 elements, or 512 bits. This means that 256-bit
  35. # inputs will be processed only 2 times faster than 512-bit inputs,
  36. # not 4 [as one would expect, because algorithm complexity is n^2].
  37. # The reason for padding is that inputs shorter than 512 bits won't
  38. # be processed faster anyway, because minimal critical path of the
  39. # core loop happens to match 512-bit timing. Either way, it resulted
  40. # in >100% improvement of 512-bit RSA sign benchmark and 50% - of
  41. # 1024-bit one [in comparison to original version of *this* module].
  42. #
  43. # So far 'openssl speed rsa dsa' output on 900MHz Itanium 2 *with*
  44. # this module is:
  45. # sign verify sign/s verify/s
  46. # rsa 512 bits 0.000290s 0.000024s 3452.8 42031.4
  47. # rsa 1024 bits 0.000793s 0.000058s 1261.7 17172.0
  48. # rsa 2048 bits 0.005908s 0.000148s 169.3 6754.0
  49. # rsa 4096 bits 0.033456s 0.000469s 29.9 2133.6
  50. # dsa 512 bits 0.000253s 0.000198s 3949.9 5057.0
  51. # dsa 1024 bits 0.000585s 0.000607s 1708.4 1647.4
  52. # dsa 2048 bits 0.001453s 0.001703s 688.1 587.4
  53. #
  54. # ... and *without* (but still with ia64.S):
  55. #
  56. # rsa 512 bits 0.000670s 0.000041s 1491.8 24145.5
  57. # rsa 1024 bits 0.001988s 0.000080s 502.9 12499.3
  58. # rsa 2048 bits 0.008702s 0.000189s 114.9 5293.9
  59. # rsa 4096 bits 0.043860s 0.000533s 22.8 1875.9
  60. # dsa 512 bits 0.000441s 0.000427s 2265.3 2340.6
  61. # dsa 1024 bits 0.000823s 0.000867s 1215.6 1153.2
  62. # dsa 2048 bits 0.001894s 0.002179s 528.1 458.9
  63. #
  64. # As it can be seen, RSA sign performance improves by 130-30%,
  65. # hereafter less for longer keys, while verify - by 74-13%.
  66. # DSA performance improves by 115-30%.
  67. # $output is the last argument if it looks like a file (it has an extension)
  68. $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
  69. if ($^O eq "hpux") {
  70. $ADDP="addp4";
  71. for (@ARGV) { $ADDP="add" if (/[\+DD|\-mlp]64/); }
  72. } else { $ADDP="add"; }
  73. $code=<<___;
  74. .explicit
  75. .text
  76. // int bn_mul_mont (BN_ULONG *rp,const BN_ULONG *ap,
  77. // const BN_ULONG *bp,const BN_ULONG *np,
  78. // const BN_ULONG *n0p,int num);
  79. .align 64
  80. .global bn_mul_mont#
  81. .proc bn_mul_mont#
  82. bn_mul_mont:
  83. .prologue
  84. .body
  85. { .mmi; cmp4.le p6,p7=2,r37;;
  86. (p6) cmp4.lt.unc p8,p9=8,r37
  87. mov ret0=r0 };;
  88. { .bbb;
  89. (p9) br.cond.dptk.many bn_mul_mont_8
  90. (p8) br.cond.dpnt.many bn_mul_mont_general
  91. (p7) br.ret.spnt.many b0 };;
  92. .endp bn_mul_mont#
  93. prevfs=r2; prevpr=r3; prevlc=r10; prevsp=r11;
  94. rptr=r8; aptr=r9; bptr=r14; nptr=r15;
  95. tptr=r16; // &tp[0]
  96. tp_1=r17; // &tp[-1]
  97. num=r18; len=r19; lc=r20;
  98. topbit=r21; // carry bit from tmp[num]
  99. n0=f6;
  100. m0=f7;
  101. bi=f8;
  102. .align 64
  103. .local bn_mul_mont_general#
  104. .proc bn_mul_mont_general#
  105. bn_mul_mont_general:
  106. .prologue
  107. { .mmi; .save ar.pfs,prevfs
  108. alloc prevfs=ar.pfs,6,2,0,8
  109. $ADDP aptr=0,in1
  110. .save ar.lc,prevlc
  111. mov prevlc=ar.lc }
  112. { .mmi; .vframe prevsp
  113. mov prevsp=sp
  114. $ADDP bptr=0,in2
  115. .save pr,prevpr
  116. mov prevpr=pr };;
  117. .body
  118. .rotf alo[6],nlo[4],ahi[8],nhi[6]
  119. .rotr a[3],n[3],t[2]
  120. { .mmi; ldf8 bi=[bptr],8 // (*bp++)
  121. ldf8 alo[4]=[aptr],16 // ap[0]
  122. $ADDP r30=8,in1 };;
  123. { .mmi; ldf8 alo[3]=[r30],16 // ap[1]
  124. ldf8 alo[2]=[aptr],16 // ap[2]
  125. $ADDP in4=0,in4 };;
  126. { .mmi; ldf8 alo[1]=[r30] // ap[3]
  127. ldf8 n0=[in4] // n0
  128. $ADDP rptr=0,in0 }
  129. { .mmi; $ADDP nptr=0,in3
  130. mov r31=16
  131. zxt4 num=in5 };;
  132. { .mmi; ldf8 nlo[2]=[nptr],8 // np[0]
  133. shladd len=num,3,r0
  134. shladd r31=num,3,r31 };;
  135. { .mmi; ldf8 nlo[1]=[nptr],8 // np[1]
  136. add lc=-5,num
  137. sub r31=sp,r31 };;
  138. { .mfb; and sp=-16,r31 // alloca
  139. xmpy.hu ahi[2]=alo[4],bi // ap[0]*bp[0]
  140. nop.b 0 }
  141. { .mfb; nop.m 0
  142. xmpy.lu alo[4]=alo[4],bi
  143. brp.loop.imp .L1st_ctop,.L1st_cend-16
  144. };;
  145. { .mfi; nop.m 0
  146. xma.hu ahi[1]=alo[3],bi,ahi[2] // ap[1]*bp[0]
  147. add tp_1=8,sp }
  148. { .mfi; nop.m 0
  149. xma.lu alo[3]=alo[3],bi,ahi[2]
  150. mov pr.rot=0x20001f<<16
  151. // ------^----- (p40) at first (p23)
  152. // ----------^^ p[16:20]=1
  153. };;
  154. { .mfi; nop.m 0
  155. xmpy.lu m0=alo[4],n0 // (ap[0]*bp[0])*n0
  156. mov ar.lc=lc }
  157. { .mfi; nop.m 0
  158. fcvt.fxu.s1 nhi[1]=f0
  159. mov ar.ec=8 };;
  160. .align 32
  161. .L1st_ctop:
  162. .pred.rel "mutex",p40,p42
  163. { .mfi; (p16) ldf8 alo[0]=[aptr],8 // *(aptr++)
  164. (p18) xma.hu ahi[0]=alo[2],bi,ahi[1]
  165. (p40) add n[2]=n[2],a[2] } // (p23) }
  166. { .mfi; (p18) ldf8 nlo[0]=[nptr],8 // *(nptr++)(p16)
  167. (p18) xma.lu alo[2]=alo[2],bi,ahi[1]
  168. (p42) add n[2]=n[2],a[2],1 };; // (p23)
  169. { .mfi; (p21) getf.sig a[0]=alo[5]
  170. (p20) xma.hu nhi[0]=nlo[2],m0,nhi[1]
  171. (p42) cmp.leu p41,p39=n[2],a[2] } // (p23)
  172. { .mfi; (p23) st8 [tp_1]=n[2],8
  173. (p20) xma.lu nlo[2]=nlo[2],m0,nhi[1]
  174. (p40) cmp.ltu p41,p39=n[2],a[2] } // (p23)
  175. { .mmb; (p21) getf.sig n[0]=nlo[3]
  176. (p16) nop.m 0
  177. br.ctop.sptk .L1st_ctop };;
  178. .L1st_cend:
  179. { .mmi; getf.sig a[0]=ahi[6] // (p24)
  180. getf.sig n[0]=nhi[4]
  181. add num=-1,num };; // num--
  182. { .mmi; .pred.rel "mutex",p40,p42
  183. (p40) add n[0]=n[0],a[0]
  184. (p42) add n[0]=n[0],a[0],1
  185. sub aptr=aptr,len };; // rewind
  186. { .mmi; .pred.rel "mutex",p40,p42
  187. (p40) cmp.ltu p41,p39=n[0],a[0]
  188. (p42) cmp.leu p41,p39=n[0],a[0]
  189. sub nptr=nptr,len };;
  190. { .mmi; .pred.rel "mutex",p39,p41
  191. (p39) add topbit=r0,r0
  192. (p41) add topbit=r0,r0,1
  193. nop.i 0 }
  194. { .mmi; st8 [tp_1]=n[0]
  195. add tptr=16,sp
  196. add tp_1=8,sp };;
  197. .Louter:
  198. { .mmi; ldf8 bi=[bptr],8 // (*bp++)
  199. ldf8 ahi[3]=[tptr] // tp[0]
  200. add r30=8,aptr };;
  201. { .mmi; ldf8 alo[4]=[aptr],16 // ap[0]
  202. ldf8 alo[3]=[r30],16 // ap[1]
  203. add r31=8,nptr };;
  204. { .mfb; ldf8 alo[2]=[aptr],16 // ap[2]
  205. xma.hu ahi[2]=alo[4],bi,ahi[3] // ap[0]*bp[i]+tp[0]
  206. brp.loop.imp .Linner_ctop,.Linner_cend-16
  207. }
  208. { .mfb; ldf8 alo[1]=[r30] // ap[3]
  209. xma.lu alo[4]=alo[4],bi,ahi[3]
  210. clrrrb.pr };;
  211. { .mfi; ldf8 nlo[2]=[nptr],16 // np[0]
  212. xma.hu ahi[1]=alo[3],bi,ahi[2] // ap[1]*bp[i]
  213. nop.i 0 }
  214. { .mfi; ldf8 nlo[1]=[r31] // np[1]
  215. xma.lu alo[3]=alo[3],bi,ahi[2]
  216. mov pr.rot=0x20101f<<16
  217. // ------^----- (p40) at first (p23)
  218. // --------^--- (p30) at first (p22)
  219. // ----------^^ p[16:20]=1
  220. };;
  221. { .mfi; st8 [tptr]=r0 // tp[0] is already accounted
  222. xmpy.lu m0=alo[4],n0 // (ap[0]*bp[i]+tp[0])*n0
  223. mov ar.lc=lc }
  224. { .mfi;
  225. fcvt.fxu.s1 nhi[1]=f0
  226. mov ar.ec=8 };;
  227. // This loop spins in 4*(n+7) ticks on Itanium 2 and should spin in
  228. // 7*(n+7) ticks on Itanium (the one codenamed Merced). Factor of 7
  229. // in latter case accounts for two-tick pipeline stall, which means
  230. // that its performance would be ~20% lower than optimal one. No
  231. // attempt was made to address this, because original Itanium is
  232. // hardly represented out in the wild...
  233. .align 32
  234. .Linner_ctop:
  235. .pred.rel "mutex",p40,p42
  236. .pred.rel "mutex",p30,p32
  237. { .mfi; (p16) ldf8 alo[0]=[aptr],8 // *(aptr++)
  238. (p18) xma.hu ahi[0]=alo[2],bi,ahi[1]
  239. (p40) add n[2]=n[2],a[2] } // (p23)
  240. { .mfi; (p16) nop.m 0
  241. (p18) xma.lu alo[2]=alo[2],bi,ahi[1]
  242. (p42) add n[2]=n[2],a[2],1 };; // (p23)
  243. { .mfi; (p21) getf.sig a[0]=alo[5]
  244. (p16) nop.f 0
  245. (p40) cmp.ltu p41,p39=n[2],a[2] } // (p23)
  246. { .mfi; (p21) ld8 t[0]=[tptr],8
  247. (p16) nop.f 0
  248. (p42) cmp.leu p41,p39=n[2],a[2] };; // (p23)
  249. { .mfi; (p18) ldf8 nlo[0]=[nptr],8 // *(nptr++)
  250. (p20) xma.hu nhi[0]=nlo[2],m0,nhi[1]
  251. (p30) add a[1]=a[1],t[1] } // (p22)
  252. { .mfi; (p16) nop.m 0
  253. (p20) xma.lu nlo[2]=nlo[2],m0,nhi[1]
  254. (p32) add a[1]=a[1],t[1],1 };; // (p22)
  255. { .mmi; (p21) getf.sig n[0]=nlo[3]
  256. (p16) nop.m 0
  257. (p30) cmp.ltu p31,p29=a[1],t[1] } // (p22)
  258. { .mmb; (p23) st8 [tp_1]=n[2],8
  259. (p32) cmp.leu p31,p29=a[1],t[1] // (p22)
  260. br.ctop.sptk .Linner_ctop };;
  261. .Linner_cend:
  262. { .mmi; getf.sig a[0]=ahi[6] // (p24)
  263. getf.sig n[0]=nhi[4]
  264. nop.i 0 };;
  265. { .mmi; .pred.rel "mutex",p31,p33
  266. (p31) add a[0]=a[0],topbit
  267. (p33) add a[0]=a[0],topbit,1
  268. mov topbit=r0 };;
  269. { .mfi; .pred.rel "mutex",p31,p33
  270. (p31) cmp.ltu p32,p30=a[0],topbit
  271. (p33) cmp.leu p32,p30=a[0],topbit
  272. }
  273. { .mfi; .pred.rel "mutex",p40,p42
  274. (p40) add n[0]=n[0],a[0]
  275. (p42) add n[0]=n[0],a[0],1
  276. };;
  277. { .mmi; .pred.rel "mutex",p44,p46
  278. (p40) cmp.ltu p41,p39=n[0],a[0]
  279. (p42) cmp.leu p41,p39=n[0],a[0]
  280. (p32) add topbit=r0,r0,1 }
  281. { .mmi; st8 [tp_1]=n[0],8
  282. cmp4.ne p6,p0=1,num
  283. sub aptr=aptr,len };; // rewind
  284. { .mmi; sub nptr=nptr,len
  285. (p41) add topbit=r0,r0,1
  286. add tptr=16,sp }
  287. { .mmb; add tp_1=8,sp
  288. add num=-1,num // num--
  289. (p6) br.cond.sptk.many .Louter };;
  290. { .mbb; add lc=4,lc
  291. brp.loop.imp .Lsub_ctop,.Lsub_cend-16
  292. clrrrb.pr };;
  293. { .mii; nop.m 0
  294. mov pr.rot=0x10001<<16
  295. // ------^---- (p33) at first (p17)
  296. mov ar.lc=lc }
  297. { .mii; nop.m 0
  298. mov ar.ec=3
  299. nop.i 0 };;
  300. .Lsub_ctop:
  301. .pred.rel "mutex",p33,p35
  302. { .mfi; (p16) ld8 t[0]=[tptr],8 // t=*(tp++)
  303. (p16) nop.f 0
  304. (p33) sub n[1]=t[1],n[1] } // (p17)
  305. { .mfi; (p16) ld8 n[0]=[nptr],8 // n=*(np++)
  306. (p16) nop.f 0
  307. (p35) sub n[1]=t[1],n[1],1 };; // (p17)
  308. { .mib; (p18) st8 [rptr]=n[2],8 // *(rp++)=r
  309. (p33) cmp.gtu p34,p32=n[1],t[1] // (p17)
  310. (p18) nop.b 0 }
  311. { .mib; (p18) nop.m 0
  312. (p35) cmp.geu p34,p32=n[1],t[1] // (p17)
  313. br.ctop.sptk .Lsub_ctop };;
  314. .Lsub_cend:
  315. { .mmb; .pred.rel "mutex",p34,p36
  316. (p34) sub topbit=topbit,r0 // (p19)
  317. (p36) sub topbit=topbit,r0,1
  318. brp.loop.imp .Lcopy_ctop,.Lcopy_cend-16
  319. }
  320. { .mmb; sub rptr=rptr,len // rewind
  321. sub tptr=tptr,len
  322. clrrrb.pr };;
  323. { .mmi; mov aptr=rptr
  324. mov bptr=tptr
  325. mov pr.rot=1<<16 };;
  326. { .mii; cmp.eq p0,p6=topbit,r0
  327. mov ar.lc=lc
  328. mov ar.ec=2 };;
  329. .Lcopy_ctop:
  330. { .mmi; (p16) ld8 a[0]=[aptr],8
  331. (p16) ld8 t[0]=[bptr],8
  332. (p6) mov a[1]=t[1] };; // (p17)
  333. { .mmb; (p17) st8 [rptr]=a[1],8
  334. (p17) st8 [tptr]=r0,8
  335. br.ctop.sptk .Lcopy_ctop };;
  336. .Lcopy_cend:
  337. { .mmi; mov ret0=1 // signal "handled"
  338. rum 1<<5 // clear um.mfh
  339. mov ar.lc=prevlc }
  340. { .mib; .restore sp
  341. mov sp=prevsp
  342. mov pr=prevpr,0x1ffff
  343. br.ret.sptk.many b0 };;
  344. .endp bn_mul_mont_general#
  345. a1=r16; a2=r17; a3=r18; a4=r19; a5=r20; a6=r21; a7=r22; a8=r23;
  346. n1=r24; n2=r25; n3=r26; n4=r27; n5=r28; n6=r29; n7=r30; n8=r31;
  347. t0=r15;
  348. ai0=f8; ai1=f9; ai2=f10; ai3=f11; ai4=f12; ai5=f13; ai6=f14; ai7=f15;
  349. ni0=f16; ni1=f17; ni2=f18; ni3=f19; ni4=f20; ni5=f21; ni6=f22; ni7=f23;
  350. .align 64
  351. .skip 48 // aligns loop body
  352. .local bn_mul_mont_8#
  353. .proc bn_mul_mont_8#
  354. bn_mul_mont_8:
  355. .prologue
  356. { .mmi; .save ar.pfs,prevfs
  357. alloc prevfs=ar.pfs,6,2,0,8
  358. .vframe prevsp
  359. mov prevsp=sp
  360. .save ar.lc,prevlc
  361. mov prevlc=ar.lc }
  362. { .mmi; add r17=-6*16,sp
  363. add sp=-7*16,sp
  364. .save pr,prevpr
  365. mov prevpr=pr };;
  366. { .mmi; .save.gf 0,0x10
  367. stf.spill [sp]=f16,-16
  368. .save.gf 0,0x20
  369. stf.spill [r17]=f17,32
  370. add r16=-5*16,prevsp};;
  371. { .mmi; .save.gf 0,0x40
  372. stf.spill [r16]=f18,32
  373. .save.gf 0,0x80
  374. stf.spill [r17]=f19,32
  375. $ADDP aptr=0,in1 };;
  376. { .mmi; .save.gf 0,0x100
  377. stf.spill [r16]=f20,32
  378. .save.gf 0,0x200
  379. stf.spill [r17]=f21,32
  380. $ADDP r29=8,in1 };;
  381. { .mmi; .save.gf 0,0x400
  382. stf.spill [r16]=f22
  383. .save.gf 0,0x800
  384. stf.spill [r17]=f23
  385. $ADDP rptr=0,in0 };;
  386. .body
  387. .rotf bj[8],mj[2],tf[2],alo[10],ahi[10],nlo[10],nhi[10]
  388. .rotr t[8]
  389. // load input vectors padding them to 8 elements
  390. { .mmi; ldf8 ai0=[aptr],16 // ap[0]
  391. ldf8 ai1=[r29],16 // ap[1]
  392. $ADDP bptr=0,in2 }
  393. { .mmi; $ADDP r30=8,in2
  394. $ADDP nptr=0,in3
  395. $ADDP r31=8,in3 };;
  396. { .mmi; ldf8 bj[7]=[bptr],16 // bp[0]
  397. ldf8 bj[6]=[r30],16 // bp[1]
  398. cmp4.le p4,p5=3,in5 }
  399. { .mmi; ldf8 ni0=[nptr],16 // np[0]
  400. ldf8 ni1=[r31],16 // np[1]
  401. cmp4.le p6,p7=4,in5 };;
  402. { .mfi; (p4)ldf8 ai2=[aptr],16 // ap[2]
  403. (p5)fcvt.fxu ai2=f0
  404. cmp4.le p8,p9=5,in5 }
  405. { .mfi; (p6)ldf8 ai3=[r29],16 // ap[3]
  406. (p7)fcvt.fxu ai3=f0
  407. cmp4.le p10,p11=6,in5 }
  408. { .mfi; (p4)ldf8 bj[5]=[bptr],16 // bp[2]
  409. (p5)fcvt.fxu bj[5]=f0
  410. cmp4.le p12,p13=7,in5 }
  411. { .mfi; (p6)ldf8 bj[4]=[r30],16 // bp[3]
  412. (p7)fcvt.fxu bj[4]=f0
  413. cmp4.le p14,p15=8,in5 }
  414. { .mfi; (p4)ldf8 ni2=[nptr],16 // np[2]
  415. (p5)fcvt.fxu ni2=f0
  416. addp4 r28=-1,in5 }
  417. { .mfi; (p6)ldf8 ni3=[r31],16 // np[3]
  418. (p7)fcvt.fxu ni3=f0
  419. $ADDP in4=0,in4 };;
  420. { .mfi; ldf8 n0=[in4]
  421. fcvt.fxu tf[1]=f0
  422. nop.i 0 }
  423. { .mfi; (p8)ldf8 ai4=[aptr],16 // ap[4]
  424. (p9)fcvt.fxu ai4=f0
  425. mov t[0]=r0 }
  426. { .mfi; (p10)ldf8 ai5=[r29],16 // ap[5]
  427. (p11)fcvt.fxu ai5=f0
  428. mov t[1]=r0 }
  429. { .mfi; (p8)ldf8 bj[3]=[bptr],16 // bp[4]
  430. (p9)fcvt.fxu bj[3]=f0
  431. mov t[2]=r0 }
  432. { .mfi; (p10)ldf8 bj[2]=[r30],16 // bp[5]
  433. (p11)fcvt.fxu bj[2]=f0
  434. mov t[3]=r0 }
  435. { .mfi; (p8)ldf8 ni4=[nptr],16 // np[4]
  436. (p9)fcvt.fxu ni4=f0
  437. mov t[4]=r0 }
  438. { .mfi; (p10)ldf8 ni5=[r31],16 // np[5]
  439. (p11)fcvt.fxu ni5=f0
  440. mov t[5]=r0 };;
  441. { .mfi; (p12)ldf8 ai6=[aptr],16 // ap[6]
  442. (p13)fcvt.fxu ai6=f0
  443. mov t[6]=r0 }
  444. { .mfi; (p14)ldf8 ai7=[r29],16 // ap[7]
  445. (p15)fcvt.fxu ai7=f0
  446. mov t[7]=r0 }
  447. { .mfi; (p12)ldf8 bj[1]=[bptr],16 // bp[6]
  448. (p13)fcvt.fxu bj[1]=f0
  449. mov ar.lc=r28 }
  450. { .mfi; (p14)ldf8 bj[0]=[r30],16 // bp[7]
  451. (p15)fcvt.fxu bj[0]=f0
  452. mov ar.ec=1 }
  453. { .mfi; (p12)ldf8 ni6=[nptr],16 // np[6]
  454. (p13)fcvt.fxu ni6=f0
  455. mov pr.rot=1<<16 }
  456. { .mfb; (p14)ldf8 ni7=[r31],16 // np[7]
  457. (p15)fcvt.fxu ni7=f0
  458. brp.loop.imp .Louter_8_ctop,.Louter_8_cend-16
  459. };;
  460. // The loop is scheduled for 32*n ticks on Itanium 2. Actual attempt
  461. // to measure with help of Interval Time Counter indicated that the
  462. // factor is a tad higher: 33 or 34, if not 35. Exact measurement and
  463. // addressing the issue is problematic, because I don't have access
  464. // to platform-specific instruction-level profiler. On Itanium it
  465. // should run in 56*n ticks, because of higher xma latency...
  466. .Louter_8_ctop:
  467. .pred.rel "mutex",p40,p42
  468. .pred.rel "mutex",p48,p50
  469. { .mfi; (p16) nop.m 0 // 0:
  470. (p16) xma.hu ahi[0]=ai0,bj[7],tf[1] // ap[0]*b[i]+t[0]
  471. (p40) add a3=a3,n3 } // (p17) a3+=n3
  472. { .mfi; (p42) add a3=a3,n3,1
  473. (p16) xma.lu alo[0]=ai0,bj[7],tf[1]
  474. (p16) nop.i 0 };;
  475. { .mii; (p17) getf.sig a7=alo[8] // 1:
  476. (p48) add t[6]=t[6],a3 // (p17) t[6]+=a3
  477. (p50) add t[6]=t[6],a3,1 };;
  478. { .mfi; (p17) getf.sig a8=ahi[8] // 2:
  479. (p17) xma.hu nhi[7]=ni6,mj[1],nhi[6] // np[6]*m0
  480. (p40) cmp.ltu p43,p41=a3,n3 }
  481. { .mfi; (p42) cmp.leu p43,p41=a3,n3
  482. (p17) xma.lu nlo[7]=ni6,mj[1],nhi[6]
  483. (p16) nop.i 0 };;
  484. { .mii; (p17) getf.sig n5=nlo[6] // 3:
  485. (p48) cmp.ltu p51,p49=t[6],a3
  486. (p50) cmp.leu p51,p49=t[6],a3 };;
  487. .pred.rel "mutex",p41,p43
  488. .pred.rel "mutex",p49,p51
  489. { .mfi; (p16) nop.m 0 // 4:
  490. (p16) xma.hu ahi[1]=ai1,bj[7],ahi[0] // ap[1]*b[i]
  491. (p41) add a4=a4,n4 } // (p17) a4+=n4
  492. { .mfi; (p43) add a4=a4,n4,1
  493. (p16) xma.lu alo[1]=ai1,bj[7],ahi[0]
  494. (p16) nop.i 0 };;
  495. { .mfi; (p49) add t[5]=t[5],a4 // 5: (p17) t[5]+=a4
  496. (p16) xmpy.lu mj[0]=alo[0],n0 // (ap[0]*b[i]+t[0])*n0
  497. (p51) add t[5]=t[5],a4,1 };;
  498. { .mfi; (p16) nop.m 0 // 6:
  499. (p17) xma.hu nhi[8]=ni7,mj[1],nhi[7] // np[7]*m0
  500. (p41) cmp.ltu p42,p40=a4,n4 }
  501. { .mfi; (p43) cmp.leu p42,p40=a4,n4
  502. (p17) xma.lu nlo[8]=ni7,mj[1],nhi[7]
  503. (p16) nop.i 0 };;
  504. { .mii; (p17) getf.sig n6=nlo[7] // 7:
  505. (p49) cmp.ltu p50,p48=t[5],a4
  506. (p51) cmp.leu p50,p48=t[5],a4 };;
  507. .pred.rel "mutex",p40,p42
  508. .pred.rel "mutex",p48,p50
  509. { .mfi; (p16) nop.m 0 // 8:
  510. (p16) xma.hu ahi[2]=ai2,bj[7],ahi[1] // ap[2]*b[i]
  511. (p40) add a5=a5,n5 } // (p17) a5+=n5
  512. { .mfi; (p42) add a5=a5,n5,1
  513. (p16) xma.lu alo[2]=ai2,bj[7],ahi[1]
  514. (p16) nop.i 0 };;
  515. { .mii; (p16) getf.sig a1=alo[1] // 9:
  516. (p48) add t[4]=t[4],a5 // p(17) t[4]+=a5
  517. (p50) add t[4]=t[4],a5,1 };;
  518. { .mfi; (p16) nop.m 0 // 10:
  519. (p16) xma.hu nhi[0]=ni0,mj[0],alo[0] // np[0]*m0
  520. (p40) cmp.ltu p43,p41=a5,n5 }
  521. { .mfi; (p42) cmp.leu p43,p41=a5,n5
  522. (p16) xma.lu nlo[0]=ni0,mj[0],alo[0]
  523. (p16) nop.i 0 };;
  524. { .mii; (p17) getf.sig n7=nlo[8] // 11:
  525. (p48) cmp.ltu p51,p49=t[4],a5
  526. (p50) cmp.leu p51,p49=t[4],a5 };;
  527. .pred.rel "mutex",p41,p43
  528. .pred.rel "mutex",p49,p51
  529. { .mfi; (p17) getf.sig n8=nhi[8] // 12:
  530. (p16) xma.hu ahi[3]=ai3,bj[7],ahi[2] // ap[3]*b[i]
  531. (p41) add a6=a6,n6 } // (p17) a6+=n6
  532. { .mfi; (p43) add a6=a6,n6,1
  533. (p16) xma.lu alo[3]=ai3,bj[7],ahi[2]
  534. (p16) nop.i 0 };;
  535. { .mii; (p16) getf.sig a2=alo[2] // 13:
  536. (p49) add t[3]=t[3],a6 // (p17) t[3]+=a6
  537. (p51) add t[3]=t[3],a6,1 };;
  538. { .mfi; (p16) nop.m 0 // 14:
  539. (p16) xma.hu nhi[1]=ni1,mj[0],nhi[0] // np[1]*m0
  540. (p41) cmp.ltu p42,p40=a6,n6 }
  541. { .mfi; (p43) cmp.leu p42,p40=a6,n6
  542. (p16) xma.lu nlo[1]=ni1,mj[0],nhi[0]
  543. (p16) nop.i 0 };;
  544. { .mii; (p16) nop.m 0 // 15:
  545. (p49) cmp.ltu p50,p48=t[3],a6
  546. (p51) cmp.leu p50,p48=t[3],a6 };;
  547. .pred.rel "mutex",p40,p42
  548. .pred.rel "mutex",p48,p50
  549. { .mfi; (p16) nop.m 0 // 16:
  550. (p16) xma.hu ahi[4]=ai4,bj[7],ahi[3] // ap[4]*b[i]
  551. (p40) add a7=a7,n7 } // (p17) a7+=n7
  552. { .mfi; (p42) add a7=a7,n7,1
  553. (p16) xma.lu alo[4]=ai4,bj[7],ahi[3]
  554. (p16) nop.i 0 };;
  555. { .mii; (p16) getf.sig a3=alo[3] // 17:
  556. (p48) add t[2]=t[2],a7 // (p17) t[2]+=a7
  557. (p50) add t[2]=t[2],a7,1 };;
  558. { .mfi; (p16) nop.m 0 // 18:
  559. (p16) xma.hu nhi[2]=ni2,mj[0],nhi[1] // np[2]*m0
  560. (p40) cmp.ltu p43,p41=a7,n7 }
  561. { .mfi; (p42) cmp.leu p43,p41=a7,n7
  562. (p16) xma.lu nlo[2]=ni2,mj[0],nhi[1]
  563. (p16) nop.i 0 };;
  564. { .mii; (p16) getf.sig n1=nlo[1] // 19:
  565. (p48) cmp.ltu p51,p49=t[2],a7
  566. (p50) cmp.leu p51,p49=t[2],a7 };;
  567. .pred.rel "mutex",p41,p43
  568. .pred.rel "mutex",p49,p51
  569. { .mfi; (p16) nop.m 0 // 20:
  570. (p16) xma.hu ahi[5]=ai5,bj[7],ahi[4] // ap[5]*b[i]
  571. (p41) add a8=a8,n8 } // (p17) a8+=n8
  572. { .mfi; (p43) add a8=a8,n8,1
  573. (p16) xma.lu alo[5]=ai5,bj[7],ahi[4]
  574. (p16) nop.i 0 };;
  575. { .mii; (p16) getf.sig a4=alo[4] // 21:
  576. (p49) add t[1]=t[1],a8 // (p17) t[1]+=a8
  577. (p51) add t[1]=t[1],a8,1 };;
  578. { .mfi; (p16) nop.m 0 // 22:
  579. (p16) xma.hu nhi[3]=ni3,mj[0],nhi[2] // np[3]*m0
  580. (p41) cmp.ltu p42,p40=a8,n8 }
  581. { .mfi; (p43) cmp.leu p42,p40=a8,n8
  582. (p16) xma.lu nlo[3]=ni3,mj[0],nhi[2]
  583. (p16) nop.i 0 };;
  584. { .mii; (p16) getf.sig n2=nlo[2] // 23:
  585. (p49) cmp.ltu p50,p48=t[1],a8
  586. (p51) cmp.leu p50,p48=t[1],a8 };;
  587. { .mfi; (p16) nop.m 0 // 24:
  588. (p16) xma.hu ahi[6]=ai6,bj[7],ahi[5] // ap[6]*b[i]
  589. (p16) add a1=a1,n1 } // (p16) a1+=n1
  590. { .mfi; (p16) nop.m 0
  591. (p16) xma.lu alo[6]=ai6,bj[7],ahi[5]
  592. (p17) mov t[0]=r0 };;
  593. { .mii; (p16) getf.sig a5=alo[5] // 25:
  594. (p16) add t0=t[7],a1 // (p16) t[7]+=a1
  595. (p42) add t[0]=t[0],r0,1 };;
  596. { .mfi; (p16) setf.sig tf[0]=t0 // 26:
  597. (p16) xma.hu nhi[4]=ni4,mj[0],nhi[3] // np[4]*m0
  598. (p50) add t[0]=t[0],r0,1 }
  599. { .mfi; (p16) cmp.ltu.unc p42,p40=a1,n1
  600. (p16) xma.lu nlo[4]=ni4,mj[0],nhi[3]
  601. (p16) nop.i 0 };;
  602. { .mii; (p16) getf.sig n3=nlo[3] // 27:
  603. (p16) cmp.ltu.unc p50,p48=t0,a1
  604. (p16) nop.i 0 };;
  605. .pred.rel "mutex",p40,p42
  606. .pred.rel "mutex",p48,p50
  607. { .mfi; (p16) nop.m 0 // 28:
  608. (p16) xma.hu ahi[7]=ai7,bj[7],ahi[6] // ap[7]*b[i]
  609. (p40) add a2=a2,n2 } // (p16) a2+=n2
  610. { .mfi; (p42) add a2=a2,n2,1
  611. (p16) xma.lu alo[7]=ai7,bj[7],ahi[6]
  612. (p16) nop.i 0 };;
  613. { .mii; (p16) getf.sig a6=alo[6] // 29:
  614. (p48) add t[6]=t[6],a2 // (p16) t[6]+=a2
  615. (p50) add t[6]=t[6],a2,1 };;
  616. { .mfi; (p16) nop.m 0 // 30:
  617. (p16) xma.hu nhi[5]=ni5,mj[0],nhi[4] // np[5]*m0
  618. (p40) cmp.ltu p41,p39=a2,n2 }
  619. { .mfi; (p42) cmp.leu p41,p39=a2,n2
  620. (p16) xma.lu nlo[5]=ni5,mj[0],nhi[4]
  621. (p16) nop.i 0 };;
  622. { .mfi; (p16) getf.sig n4=nlo[4] // 31:
  623. (p16) nop.f 0
  624. (p48) cmp.ltu p49,p47=t[6],a2 }
  625. { .mfb; (p50) cmp.leu p49,p47=t[6],a2
  626. (p16) nop.f 0
  627. br.ctop.sptk.many .Louter_8_ctop };;
  628. .Louter_8_cend:
  629. // above loop has to execute one more time, without (p16), which is
  630. // replaced with merged move of np[8] to GPR bank
  631. .pred.rel "mutex",p40,p42
  632. .pred.rel "mutex",p48,p50
  633. { .mmi; (p0) getf.sig n1=ni0 // 0:
  634. (p40) add a3=a3,n3 // (p17) a3+=n3
  635. (p42) add a3=a3,n3,1 };;
  636. { .mii; (p17) getf.sig a7=alo[8] // 1:
  637. (p48) add t[6]=t[6],a3 // (p17) t[6]+=a3
  638. (p50) add t[6]=t[6],a3,1 };;
  639. { .mfi; (p17) getf.sig a8=ahi[8] // 2:
  640. (p17) xma.hu nhi[7]=ni6,mj[1],nhi[6] // np[6]*m0
  641. (p40) cmp.ltu p43,p41=a3,n3 }
  642. { .mfi; (p42) cmp.leu p43,p41=a3,n3
  643. (p17) xma.lu nlo[7]=ni6,mj[1],nhi[6]
  644. (p0) nop.i 0 };;
  645. { .mii; (p17) getf.sig n5=nlo[6] // 3:
  646. (p48) cmp.ltu p51,p49=t[6],a3
  647. (p50) cmp.leu p51,p49=t[6],a3 };;
  648. .pred.rel "mutex",p41,p43
  649. .pred.rel "mutex",p49,p51
  650. { .mmi; (p0) getf.sig n2=ni1 // 4:
  651. (p41) add a4=a4,n4 // (p17) a4+=n4
  652. (p43) add a4=a4,n4,1 };;
  653. { .mfi; (p49) add t[5]=t[5],a4 // 5: (p17) t[5]+=a4
  654. (p0) nop.f 0
  655. (p51) add t[5]=t[5],a4,1 };;
  656. { .mfi; (p0) getf.sig n3=ni2 // 6:
  657. (p17) xma.hu nhi[8]=ni7,mj[1],nhi[7] // np[7]*m0
  658. (p41) cmp.ltu p42,p40=a4,n4 }
  659. { .mfi; (p43) cmp.leu p42,p40=a4,n4
  660. (p17) xma.lu nlo[8]=ni7,mj[1],nhi[7]
  661. (p0) nop.i 0 };;
  662. { .mii; (p17) getf.sig n6=nlo[7] // 7:
  663. (p49) cmp.ltu p50,p48=t[5],a4
  664. (p51) cmp.leu p50,p48=t[5],a4 };;
  665. .pred.rel "mutex",p40,p42
  666. .pred.rel "mutex",p48,p50
  667. { .mii; (p0) getf.sig n4=ni3 // 8:
  668. (p40) add a5=a5,n5 // (p17) a5+=n5
  669. (p42) add a5=a5,n5,1 };;
  670. { .mii; (p0) nop.m 0 // 9:
  671. (p48) add t[4]=t[4],a5 // p(17) t[4]+=a5
  672. (p50) add t[4]=t[4],a5,1 };;
  673. { .mii; (p0) nop.m 0 // 10:
  674. (p40) cmp.ltu p43,p41=a5,n5
  675. (p42) cmp.leu p43,p41=a5,n5 };;
  676. { .mii; (p17) getf.sig n7=nlo[8] // 11:
  677. (p48) cmp.ltu p51,p49=t[4],a5
  678. (p50) cmp.leu p51,p49=t[4],a5 };;
  679. .pred.rel "mutex",p41,p43
  680. .pred.rel "mutex",p49,p51
  681. { .mii; (p17) getf.sig n8=nhi[8] // 12:
  682. (p41) add a6=a6,n6 // (p17) a6+=n6
  683. (p43) add a6=a6,n6,1 };;
  684. { .mii; (p0) getf.sig n5=ni4 // 13:
  685. (p49) add t[3]=t[3],a6 // (p17) t[3]+=a6
  686. (p51) add t[3]=t[3],a6,1 };;
  687. { .mii; (p0) nop.m 0 // 14:
  688. (p41) cmp.ltu p42,p40=a6,n6
  689. (p43) cmp.leu p42,p40=a6,n6 };;
  690. { .mii; (p0) getf.sig n6=ni5 // 15:
  691. (p49) cmp.ltu p50,p48=t[3],a6
  692. (p51) cmp.leu p50,p48=t[3],a6 };;
  693. .pred.rel "mutex",p40,p42
  694. .pred.rel "mutex",p48,p50
  695. { .mii; (p0) nop.m 0 // 16:
  696. (p40) add a7=a7,n7 // (p17) a7+=n7
  697. (p42) add a7=a7,n7,1 };;
  698. { .mii; (p0) nop.m 0 // 17:
  699. (p48) add t[2]=t[2],a7 // (p17) t[2]+=a7
  700. (p50) add t[2]=t[2],a7,1 };;
  701. { .mii; (p0) nop.m 0 // 18:
  702. (p40) cmp.ltu p43,p41=a7,n7
  703. (p42) cmp.leu p43,p41=a7,n7 };;
  704. { .mii; (p0) getf.sig n7=ni6 // 19:
  705. (p48) cmp.ltu p51,p49=t[2],a7
  706. (p50) cmp.leu p51,p49=t[2],a7 };;
  707. .pred.rel "mutex",p41,p43
  708. .pred.rel "mutex",p49,p51
  709. { .mii; (p0) nop.m 0 // 20:
  710. (p41) add a8=a8,n8 // (p17) a8+=n8
  711. (p43) add a8=a8,n8,1 };;
  712. { .mmi; (p0) nop.m 0 // 21:
  713. (p49) add t[1]=t[1],a8 // (p17) t[1]+=a8
  714. (p51) add t[1]=t[1],a8,1 }
  715. { .mmi; (p17) mov t[0]=r0
  716. (p41) cmp.ltu p42,p40=a8,n8
  717. (p43) cmp.leu p42,p40=a8,n8 };;
  718. { .mmi; (p0) getf.sig n8=ni7 // 22:
  719. (p49) cmp.ltu p50,p48=t[1],a8
  720. (p51) cmp.leu p50,p48=t[1],a8 }
  721. { .mmi; (p42) add t[0]=t[0],r0,1
  722. (p0) add r16=-7*16,prevsp
  723. (p0) add r17=-6*16,prevsp };;
  724. // subtract np[8] from carrybit|tmp[8]
  725. // carrybit|tmp[8] layout upon exit from above loop is:
  726. // t[0]|t[1]|t[2]|t[3]|t[4]|t[5]|t[6]|t[7]|t0 (least significant)
  727. { .mmi; (p50)add t[0]=t[0],r0,1
  728. add r18=-5*16,prevsp
  729. sub n1=t0,n1 };;
  730. { .mmi; cmp.gtu p34,p32=n1,t0;;
  731. .pred.rel "mutex",p32,p34
  732. (p32)sub n2=t[7],n2
  733. (p34)sub n2=t[7],n2,1 };;
  734. { .mii; (p32)cmp.gtu p35,p33=n2,t[7]
  735. (p34)cmp.geu p35,p33=n2,t[7];;
  736. .pred.rel "mutex",p33,p35
  737. (p33)sub n3=t[6],n3 }
  738. { .mmi; (p35)sub n3=t[6],n3,1;;
  739. (p33)cmp.gtu p34,p32=n3,t[6]
  740. (p35)cmp.geu p34,p32=n3,t[6] };;
  741. .pred.rel "mutex",p32,p34
  742. { .mii; (p32)sub n4=t[5],n4
  743. (p34)sub n4=t[5],n4,1;;
  744. (p32)cmp.gtu p35,p33=n4,t[5] }
  745. { .mmi; (p34)cmp.geu p35,p33=n4,t[5];;
  746. .pred.rel "mutex",p33,p35
  747. (p33)sub n5=t[4],n5
  748. (p35)sub n5=t[4],n5,1 };;
  749. { .mii; (p33)cmp.gtu p34,p32=n5,t[4]
  750. (p35)cmp.geu p34,p32=n5,t[4];;
  751. .pred.rel "mutex",p32,p34
  752. (p32)sub n6=t[3],n6 }
  753. { .mmi; (p34)sub n6=t[3],n6,1;;
  754. (p32)cmp.gtu p35,p33=n6,t[3]
  755. (p34)cmp.geu p35,p33=n6,t[3] };;
  756. .pred.rel "mutex",p33,p35
  757. { .mii; (p33)sub n7=t[2],n7
  758. (p35)sub n7=t[2],n7,1;;
  759. (p33)cmp.gtu p34,p32=n7,t[2] }
  760. { .mmi; (p35)cmp.geu p34,p32=n7,t[2];;
  761. .pred.rel "mutex",p32,p34
  762. (p32)sub n8=t[1],n8
  763. (p34)sub n8=t[1],n8,1 };;
  764. { .mii; (p32)cmp.gtu p35,p33=n8,t[1]
  765. (p34)cmp.geu p35,p33=n8,t[1];;
  766. .pred.rel "mutex",p33,p35
  767. (p33)sub a8=t[0],r0 }
  768. { .mmi; (p35)sub a8=t[0],r0,1;;
  769. (p33)cmp.gtu p34,p32=a8,t[0]
  770. (p35)cmp.geu p34,p32=a8,t[0] };;
  771. // save the result, either tmp[num] or tmp[num]-np[num]
  772. .pred.rel "mutex",p32,p34
  773. { .mmi; (p32)st8 [rptr]=n1,8
  774. (p34)st8 [rptr]=t0,8
  775. add r19=-4*16,prevsp};;
  776. { .mmb; (p32)st8 [rptr]=n2,8
  777. (p34)st8 [rptr]=t[7],8
  778. (p5)br.cond.dpnt.few .Ldone };;
  779. { .mmb; (p32)st8 [rptr]=n3,8
  780. (p34)st8 [rptr]=t[6],8
  781. (p7)br.cond.dpnt.few .Ldone };;
  782. { .mmb; (p32)st8 [rptr]=n4,8
  783. (p34)st8 [rptr]=t[5],8
  784. (p9)br.cond.dpnt.few .Ldone };;
  785. { .mmb; (p32)st8 [rptr]=n5,8
  786. (p34)st8 [rptr]=t[4],8
  787. (p11)br.cond.dpnt.few .Ldone };;
  788. { .mmb; (p32)st8 [rptr]=n6,8
  789. (p34)st8 [rptr]=t[3],8
  790. (p13)br.cond.dpnt.few .Ldone };;
  791. { .mmb; (p32)st8 [rptr]=n7,8
  792. (p34)st8 [rptr]=t[2],8
  793. (p15)br.cond.dpnt.few .Ldone };;
  794. { .mmb; (p32)st8 [rptr]=n8,8
  795. (p34)st8 [rptr]=t[1],8
  796. nop.b 0 };;
  797. .Ldone: // epilogue
  798. { .mmi; ldf.fill f16=[r16],64
  799. ldf.fill f17=[r17],64
  800. nop.i 0 }
  801. { .mmi; ldf.fill f18=[r18],64
  802. ldf.fill f19=[r19],64
  803. mov pr=prevpr,0x1ffff };;
  804. { .mmi; ldf.fill f20=[r16]
  805. ldf.fill f21=[r17]
  806. mov ar.lc=prevlc }
  807. { .mmi; ldf.fill f22=[r18]
  808. ldf.fill f23=[r19]
  809. mov ret0=1 } // signal "handled"
  810. { .mib; rum 1<<5
  811. .restore sp
  812. mov sp=prevsp
  813. br.ret.sptk.many b0 };;
  814. .endp bn_mul_mont_8#
  815. .type copyright#,\@object
  816. copyright:
  817. stringz "Montgomery multiplication for IA-64, CRYPTOGAMS by <appro\@openssl.org>"
  818. ___
  819. open STDOUT,">$output" if $output;
  820. print $code;
  821. close STDOUT or die "error closing STDOUT";