2
0

chacha-c64xplus.pl 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926
  1. #! /usr/bin/env perl
  2. # Copyright 2016-2020 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. # ====================================================================
  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. #
  16. # ChaCha20 for C64x+.
  17. #
  18. # October 2015
  19. #
  20. # Performance is 3.54 cycles per processed byte, which is ~4.3 times
  21. # faster than code generated by TI compiler. Compiler also disables
  22. # interrupts for some reason, thus making interrupt response time
  23. # dependent on input length. This module on the other hand is free
  24. # from such limitation.
  25. $output=pop;
  26. open STDOUT,">$output";
  27. ($OUT,$INP,$LEN,$KEYB,$COUNTERA)=("A4","B4","A6","B6","A8");
  28. ($KEYA,$COUNTERB,$STEP)=("A7","B7","A3");
  29. @X= ("A16","B16","A17","B17","A18","B18","A19","B19",
  30. "A20","B20","A21","B21","A22","B22","A23","B23");
  31. @Y= ("A24","B24","A25","B25","A26","B26","A27","B27",
  32. "A28","B28","A29","B29","A30","B30","A31","B31");
  33. @DAT=("A6", "A7", "B6", "B7", "A8", "A9", "B8", "B9",
  34. "A10","A11","B10","B11","A12","A13","B12","B13");
  35. # yes, overlaps with @DAT, used only in 2x interleave code path...
  36. @K2x=("A6", "B6", "A7", "B7", "A8", "B8", "A9", "B9",
  37. "A10","B10","A11","B11","A2", "B2", "A13","B13");
  38. $code.=<<___;
  39. .text
  40. .if .ASSEMBLER_VERSION<7000000
  41. .asg 0,__TI_EABI__
  42. .endif
  43. .if __TI_EABI__
  44. .asg ChaCha20_ctr32,_ChaCha20_ctr32
  45. .endif
  46. .asg B3,RA
  47. .asg A15,FP
  48. .asg B15,SP
  49. .global _ChaCha20_ctr32
  50. .align 32
  51. _ChaCha20_ctr32:
  52. .asmfunc stack_usage(40+64)
  53. MV $LEN,A0 ; reassign
  54. [!A0] BNOP RA ; no data
  55. || [A0] STW FP,*SP--(40+64) ; save frame pointer and alloca(40+64)
  56. || [A0] MV SP,FP
  57. [A0] STDW B13:B12,*SP[4+8] ; ABI says so
  58. || [A0] MV $KEYB,$KEYA
  59. || [A0] MV $COUNTERA,$COUNTERB
  60. [A0] STDW B11:B10,*SP[3+8]
  61. || [A0] STDW A13:A12,*FP[-3]
  62. [A0] STDW A11:A10,*FP[-4]
  63. || [A0] MVK 128,$STEP ; 2 * input block size
  64. [A0] LDW *${KEYA}[0],@Y[4] ; load key
  65. || [A0] LDW *${KEYB}[1],@Y[5]
  66. || [A0] MVK 0x00007865,@Y[0] ; synthesize sigma
  67. || [A0] MVK 0x0000646e,@Y[1]
  68. [A0] LDW *${KEYA}[2],@Y[6]
  69. || [A0] LDW *${KEYB}[3],@Y[7]
  70. || [A0] MVKH 0x61700000,@Y[0]
  71. || [A0] MVKH 0x33200000,@Y[1]
  72. LDW *${KEYA}[4],@Y[8]
  73. || LDW *${KEYB}[5],@Y[9]
  74. || MVK 0x00002d32,@Y[2]
  75. || MVK 0x00006574,@Y[3]
  76. LDW *${KEYA}[6],@Y[10]
  77. || LDW *${KEYB}[7],@Y[11]
  78. || MVKH 0x79620000,@Y[2]
  79. || MVKH 0x6b200000,@Y[3]
  80. LDW *${COUNTERA}[0],@Y[12] ; load counter||nonce
  81. || LDW *${COUNTERB}[1],@Y[13]
  82. || CMPLTU A0,$STEP,A1 ; is length < 2*blocks?
  83. LDW *${COUNTERA}[2],@Y[14]
  84. || LDW *${COUNTERB}[3],@Y[15]
  85. || [A1] BNOP top1x?
  86. [A1] MVK 64,$STEP ; input block size
  87. || MVK 10,B0 ; inner loop counter
  88. DMV @Y[2],@Y[0],@X[2]:@X[0] ; copy block
  89. || DMV @Y[3],@Y[1],@X[3]:@X[1]
  90. ||[!A1] STDW @Y[2]:@Y[0],*FP[-12] ; offload key material to stack
  91. ||[!A1] STDW @Y[3]:@Y[1],*SP[2]
  92. DMV @Y[6],@Y[4],@X[6]:@X[4]
  93. || DMV @Y[7],@Y[5],@X[7]:@X[5]
  94. ||[!A1] STDW @Y[6]:@Y[4],*FP[-10]
  95. ||[!A1] STDW @Y[7]:@Y[5],*SP[4]
  96. DMV @Y[10],@Y[8],@X[10]:@X[8]
  97. || DMV @Y[11],@Y[9],@X[11]:@X[9]
  98. ||[!A1] STDW @Y[10]:@Y[8],*FP[-8]
  99. ||[!A1] STDW @Y[11]:@Y[9],*SP[6]
  100. DMV @Y[14],@Y[12],@X[14]:@X[12]
  101. || DMV @Y[15],@Y[13],@X[15]:@X[13]
  102. ||[!A1] MV @Y[12],@K2x[12] ; counter
  103. ||[!A1] MV @Y[13],@K2x[13]
  104. ||[!A1] STW @Y[14],*FP[-6*2]
  105. ||[!A1] STW @Y[15],*SP[8*2]
  106. ___
  107. { ################################################################
  108. # 2x interleave gives 50% performance improvement
  109. #
  110. my ($a0,$a1,$a2,$a3) = (0..3);
  111. my ($b0,$b1,$b2,$b3) = (4..7);
  112. my ($c0,$c1,$c2,$c3) = (8..11);
  113. my ($d0,$d1,$d2,$d3) = (12..15);
  114. $code.=<<___;
  115. outer2x?:
  116. ADD @X[$b1],@X[$a1],@X[$a1]
  117. || ADD @X[$b2],@X[$a2],@X[$a2]
  118. || ADD @X[$b0],@X[$a0],@X[$a0]
  119. || ADD @X[$b3],@X[$a3],@X[$a3]
  120. || DMV @Y[2],@Y[0],@K2x[2]:@K2x[0]
  121. || DMV @Y[3],@Y[1],@K2x[3]:@K2x[1]
  122. XOR @X[$a1],@X[$d1],@X[$d1]
  123. || XOR @X[$a2],@X[$d2],@X[$d2]
  124. || XOR @X[$a0],@X[$d0],@X[$d0]
  125. || XOR @X[$a3],@X[$d3],@X[$d3]
  126. || DMV @Y[6],@Y[4],@K2x[6]:@K2x[4]
  127. || DMV @Y[7],@Y[5],@K2x[7]:@K2x[5]
  128. SWAP2 @X[$d1],@X[$d1] ; rotate by 16
  129. || SWAP2 @X[$d2],@X[$d2]
  130. || SWAP2 @X[$d0],@X[$d0]
  131. || SWAP2 @X[$d3],@X[$d3]
  132. ADD @X[$d1],@X[$c1],@X[$c1]
  133. || ADD @X[$d2],@X[$c2],@X[$c2]
  134. || ADD @X[$d0],@X[$c0],@X[$c0]
  135. || ADD @X[$d3],@X[$c3],@X[$c3]
  136. || DMV @Y[10],@Y[8],@K2x[10]:@K2x[8]
  137. || DMV @Y[11],@Y[9],@K2x[11]:@K2x[9]
  138. XOR @X[$c1],@X[$b1],@X[$b1]
  139. || XOR @X[$c2],@X[$b2],@X[$b2]
  140. || XOR @X[$c0],@X[$b0],@X[$b0]
  141. || XOR @X[$c3],@X[$b3],@X[$b3]
  142. || ADD 1,@Y[12],@Y[12] ; adjust counter for 2nd block
  143. ROTL @X[$b1],12,@X[$b1]
  144. || ROTL @X[$b2],12,@X[$b2]
  145. || MV @Y[14],@K2x[14]
  146. || MV @Y[15],@K2x[15]
  147. top2x?:
  148. ROTL @X[$b0],12,@X[$b0]
  149. || ROTL @X[$b3],12,@X[$b3]
  150. || ADD @Y[$b1],@Y[$a1],@Y[$a1]
  151. || ADD @Y[$b2],@Y[$a2],@Y[$a2]
  152. ADD @Y[$b0],@Y[$a0],@Y[$a0]
  153. || ADD @Y[$b3],@Y[$a3],@Y[$a3]
  154. || ADD @X[$b1],@X[$a1],@X[$a1]
  155. || ADD @X[$b2],@X[$a2],@X[$a2]
  156. || XOR @Y[$a1],@Y[$d1],@Y[$d1]
  157. || XOR @Y[$a2],@Y[$d2],@Y[$d2]
  158. XOR @Y[$a0],@Y[$d0],@Y[$d0]
  159. || XOR @Y[$a3],@Y[$d3],@Y[$d3]
  160. || ADD @X[$b0],@X[$a0],@X[$a0]
  161. || ADD @X[$b3],@X[$a3],@X[$a3]
  162. || XOR @X[$a1],@X[$d1],@X[$d1]
  163. || XOR @X[$a2],@X[$d2],@X[$d2]
  164. XOR @X[$a0],@X[$d0],@X[$d0]
  165. || XOR @X[$a3],@X[$d3],@X[$d3]
  166. || ROTL @X[$d1],8,@X[$d1]
  167. || ROTL @X[$d2],8,@X[$d2]
  168. || SWAP2 @Y[$d1],@Y[$d1] ; rotate by 16
  169. || SWAP2 @Y[$d2],@Y[$d2]
  170. || SWAP2 @Y[$d0],@Y[$d0]
  171. || SWAP2 @Y[$d3],@Y[$d3]
  172. ROTL @X[$d0],8,@X[$d0]
  173. || ROTL @X[$d3],8,@X[$d3]
  174. || ADD @Y[$d1],@Y[$c1],@Y[$c1]
  175. || ADD @Y[$d2],@Y[$c2],@Y[$c2]
  176. || ADD @Y[$d0],@Y[$c0],@Y[$c0]
  177. || ADD @Y[$d3],@Y[$c3],@Y[$c3]
  178. || BNOP middle2x1? ; protect from interrupt
  179. ADD @X[$d1],@X[$c1],@X[$c1]
  180. || ADD @X[$d2],@X[$c2],@X[$c2]
  181. || XOR @Y[$c1],@Y[$b1],@Y[$b1]
  182. || XOR @Y[$c2],@Y[$b2],@Y[$b2]
  183. || XOR @Y[$c0],@Y[$b0],@Y[$b0]
  184. || XOR @Y[$c3],@Y[$b3],@Y[$b3]
  185. ADD @X[$d0],@X[$c0],@X[$c0]
  186. || ADD @X[$d3],@X[$c3],@X[$c3]
  187. || XOR @X[$c1],@X[$b1],@X[$b1]
  188. || XOR @X[$c2],@X[$b2],@X[$b2]
  189. || ROTL @X[$d1],0,@X[$d2] ; moved to avoid cross-path stall
  190. || ROTL @X[$d2],0,@X[$d3]
  191. XOR @X[$c0],@X[$b0],@X[$b0]
  192. || XOR @X[$c3],@X[$b3],@X[$b3]
  193. || MV @X[$d0],@X[$d1]
  194. || MV @X[$d3],@X[$d0]
  195. || ROTL @Y[$b1],12,@Y[$b1]
  196. || ROTL @Y[$b2],12,@Y[$b2]
  197. ROTL @X[$b1],7,@X[$b0] ; avoided cross-path stall
  198. || ROTL @X[$b2],7,@X[$b1]
  199. ROTL @X[$b0],7,@X[$b3]
  200. || ROTL @X[$b3],7,@X[$b2]
  201. middle2x1?:
  202. ROTL @Y[$b0],12,@Y[$b0]
  203. || ROTL @Y[$b3],12,@Y[$b3]
  204. || ADD @X[$b0],@X[$a0],@X[$a0]
  205. || ADD @X[$b1],@X[$a1],@X[$a1]
  206. ADD @X[$b2],@X[$a2],@X[$a2]
  207. || ADD @X[$b3],@X[$a3],@X[$a3]
  208. || ADD @Y[$b1],@Y[$a1],@Y[$a1]
  209. || ADD @Y[$b2],@Y[$a2],@Y[$a2]
  210. || XOR @X[$a0],@X[$d0],@X[$d0]
  211. || XOR @X[$a1],@X[$d1],@X[$d1]
  212. XOR @X[$a2],@X[$d2],@X[$d2]
  213. || XOR @X[$a3],@X[$d3],@X[$d3]
  214. || ADD @Y[$b0],@Y[$a0],@Y[$a0]
  215. || ADD @Y[$b3],@Y[$a3],@Y[$a3]
  216. || XOR @Y[$a1],@Y[$d1],@Y[$d1]
  217. || XOR @Y[$a2],@Y[$d2],@Y[$d2]
  218. XOR @Y[$a0],@Y[$d0],@Y[$d0]
  219. || XOR @Y[$a3],@Y[$d3],@Y[$d3]
  220. || ROTL @Y[$d1],8,@Y[$d1]
  221. || ROTL @Y[$d2],8,@Y[$d2]
  222. || SWAP2 @X[$d0],@X[$d0] ; rotate by 16
  223. || SWAP2 @X[$d1],@X[$d1]
  224. || SWAP2 @X[$d2],@X[$d2]
  225. || SWAP2 @X[$d3],@X[$d3]
  226. ROTL @Y[$d0],8,@Y[$d0]
  227. || ROTL @Y[$d3],8,@Y[$d3]
  228. || ADD @X[$d0],@X[$c2],@X[$c2]
  229. || ADD @X[$d1],@X[$c3],@X[$c3]
  230. || ADD @X[$d2],@X[$c0],@X[$c0]
  231. || ADD @X[$d3],@X[$c1],@X[$c1]
  232. || BNOP middle2x2? ; protect from interrupt
  233. ADD @Y[$d1],@Y[$c1],@Y[$c1]
  234. || ADD @Y[$d2],@Y[$c2],@Y[$c2]
  235. || XOR @X[$c2],@X[$b0],@X[$b0]
  236. || XOR @X[$c3],@X[$b1],@X[$b1]
  237. || XOR @X[$c0],@X[$b2],@X[$b2]
  238. || XOR @X[$c1],@X[$b3],@X[$b3]
  239. ADD @Y[$d0],@Y[$c0],@Y[$c0]
  240. || ADD @Y[$d3],@Y[$c3],@Y[$c3]
  241. || XOR @Y[$c1],@Y[$b1],@Y[$b1]
  242. || XOR @Y[$c2],@Y[$b2],@Y[$b2]
  243. || ROTL @Y[$d1],0,@Y[$d2] ; moved to avoid cross-path stall
  244. || ROTL @Y[$d2],0,@Y[$d3]
  245. XOR @Y[$c0],@Y[$b0],@Y[$b0]
  246. || XOR @Y[$c3],@Y[$b3],@Y[$b3]
  247. || MV @Y[$d0],@Y[$d1]
  248. || MV @Y[$d3],@Y[$d0]
  249. || ROTL @X[$b0],12,@X[$b0]
  250. || ROTL @X[$b1],12,@X[$b1]
  251. ROTL @Y[$b1],7,@Y[$b0] ; avoided cross-path stall
  252. || ROTL @Y[$b2],7,@Y[$b1]
  253. ROTL @Y[$b0],7,@Y[$b3]
  254. || ROTL @Y[$b3],7,@Y[$b2]
  255. middle2x2?:
  256. ROTL @X[$b2],12,@X[$b2]
  257. || ROTL @X[$b3],12,@X[$b3]
  258. || ADD @Y[$b0],@Y[$a0],@Y[$a0]
  259. || ADD @Y[$b1],@Y[$a1],@Y[$a1]
  260. ADD @Y[$b2],@Y[$a2],@Y[$a2]
  261. || ADD @Y[$b3],@Y[$a3],@Y[$a3]
  262. || ADD @X[$b0],@X[$a0],@X[$a0]
  263. || ADD @X[$b1],@X[$a1],@X[$a1]
  264. || XOR @Y[$a0],@Y[$d0],@Y[$d0]
  265. || XOR @Y[$a1],@Y[$d1],@Y[$d1]
  266. XOR @Y[$a2],@Y[$d2],@Y[$d2]
  267. || XOR @Y[$a3],@Y[$d3],@Y[$d3]
  268. || ADD @X[$b2],@X[$a2],@X[$a2]
  269. || ADD @X[$b3],@X[$a3],@X[$a3]
  270. || XOR @X[$a0],@X[$d0],@X[$d0]
  271. || XOR @X[$a1],@X[$d1],@X[$d1]
  272. XOR @X[$a2],@X[$d2],@X[$d2]
  273. || XOR @X[$a3],@X[$d3],@X[$d3]
  274. || ROTL @X[$d0],8,@X[$d0]
  275. || ROTL @X[$d1],8,@X[$d1]
  276. || SWAP2 @Y[$d0],@Y[$d0] ; rotate by 16
  277. || SWAP2 @Y[$d1],@Y[$d1]
  278. || SWAP2 @Y[$d2],@Y[$d2]
  279. || SWAP2 @Y[$d3],@Y[$d3]
  280. ROTL @X[$d2],8,@X[$d2]
  281. || ROTL @X[$d3],8,@X[$d3]
  282. || ADD @Y[$d0],@Y[$c2],@Y[$c2]
  283. || ADD @Y[$d1],@Y[$c3],@Y[$c3]
  284. || ADD @Y[$d2],@Y[$c0],@Y[$c0]
  285. || ADD @Y[$d3],@Y[$c1],@Y[$c1]
  286. || BNOP bottom2x1? ; protect from interrupt
  287. ADD @X[$d0],@X[$c2],@X[$c2]
  288. || ADD @X[$d1],@X[$c3],@X[$c3]
  289. || XOR @Y[$c2],@Y[$b0],@Y[$b0]
  290. || XOR @Y[$c3],@Y[$b1],@Y[$b1]
  291. || XOR @Y[$c0],@Y[$b2],@Y[$b2]
  292. || XOR @Y[$c1],@Y[$b3],@Y[$b3]
  293. ADD @X[$d2],@X[$c0],@X[$c0]
  294. || ADD @X[$d3],@X[$c1],@X[$c1]
  295. || XOR @X[$c2],@X[$b0],@X[$b0]
  296. || XOR @X[$c3],@X[$b1],@X[$b1]
  297. || ROTL @X[$d0],0,@X[$d3] ; moved to avoid cross-path stall
  298. || ROTL @X[$d1],0,@X[$d0]
  299. XOR @X[$c0],@X[$b2],@X[$b2]
  300. || XOR @X[$c1],@X[$b3],@X[$b3]
  301. || MV @X[$d2],@X[$d1]
  302. || MV @X[$d3],@X[$d2]
  303. || ROTL @Y[$b0],12,@Y[$b0]
  304. || ROTL @Y[$b1],12,@Y[$b1]
  305. ROTL @X[$b0],7,@X[$b1] ; avoided cross-path stall
  306. || ROTL @X[$b1],7,@X[$b2]
  307. ROTL @X[$b2],7,@X[$b3]
  308. || ROTL @X[$b3],7,@X[$b0]
  309. || [B0] SUB B0,1,B0 ; decrement inner loop counter
  310. bottom2x1?:
  311. ROTL @Y[$b2],12,@Y[$b2]
  312. || ROTL @Y[$b3],12,@Y[$b3]
  313. || [B0] ADD @X[$b1],@X[$a1],@X[$a1] ; modulo-scheduled
  314. || [B0] ADD @X[$b2],@X[$a2],@X[$a2]
  315. [B0] ADD @X[$b0],@X[$a0],@X[$a0]
  316. || [B0] ADD @X[$b3],@X[$a3],@X[$a3]
  317. || ADD @Y[$b0],@Y[$a0],@Y[$a0]
  318. || ADD @Y[$b1],@Y[$a1],@Y[$a1]
  319. || [B0] XOR @X[$a1],@X[$d1],@X[$d1]
  320. || [B0] XOR @X[$a2],@X[$d2],@X[$d2]
  321. [B0] XOR @X[$a0],@X[$d0],@X[$d0]
  322. || [B0] XOR @X[$a3],@X[$d3],@X[$d3]
  323. || ADD @Y[$b2],@Y[$a2],@Y[$a2]
  324. || ADD @Y[$b3],@Y[$a3],@Y[$a3]
  325. || XOR @Y[$a0],@Y[$d0],@Y[$d0]
  326. || XOR @Y[$a1],@Y[$d1],@Y[$d1]
  327. XOR @Y[$a2],@Y[$d2],@Y[$d2]
  328. || XOR @Y[$a3],@Y[$d3],@Y[$d3]
  329. || ROTL @Y[$d0],8,@Y[$d0]
  330. || ROTL @Y[$d1],8,@Y[$d1]
  331. || [B0] SWAP2 @X[$d1],@X[$d1] ; rotate by 16
  332. || [B0] SWAP2 @X[$d2],@X[$d2]
  333. || [B0] SWAP2 @X[$d0],@X[$d0]
  334. || [B0] SWAP2 @X[$d3],@X[$d3]
  335. ROTL @Y[$d2],8,@Y[$d2]
  336. || ROTL @Y[$d3],8,@Y[$d3]
  337. || [B0] ADD @X[$d1],@X[$c1],@X[$c1]
  338. || [B0] ADD @X[$d2],@X[$c2],@X[$c2]
  339. || [B0] ADD @X[$d0],@X[$c0],@X[$c0]
  340. || [B0] ADD @X[$d3],@X[$c3],@X[$c3]
  341. || [B0] BNOP top2x? ; even protects from interrupt
  342. ADD @Y[$d0],@Y[$c2],@Y[$c2]
  343. || ADD @Y[$d1],@Y[$c3],@Y[$c3]
  344. || [B0] XOR @X[$c1],@X[$b1],@X[$b1]
  345. || [B0] XOR @X[$c2],@X[$b2],@X[$b2]
  346. || [B0] XOR @X[$c0],@X[$b0],@X[$b0]
  347. || [B0] XOR @X[$c3],@X[$b3],@X[$b3]
  348. ADD @Y[$d2],@Y[$c0],@Y[$c0]
  349. || ADD @Y[$d3],@Y[$c1],@Y[$c1]
  350. || XOR @Y[$c2],@Y[$b0],@Y[$b0]
  351. || XOR @Y[$c3],@Y[$b1],@Y[$b1]
  352. || ROTL @Y[$d0],0,@Y[$d3] ; moved to avoid cross-path stall
  353. || ROTL @Y[$d1],0,@Y[$d0]
  354. XOR @Y[$c0],@Y[$b2],@Y[$b2]
  355. || XOR @Y[$c1],@Y[$b3],@Y[$b3]
  356. || MV @Y[$d2],@Y[$d1]
  357. || MV @Y[$d3],@Y[$d2]
  358. || [B0] ROTL @X[$b1],12,@X[$b1]
  359. || [B0] ROTL @X[$b2],12,@X[$b2]
  360. ROTL @Y[$b0],7,@Y[$b1] ; avoided cross-path stall
  361. || ROTL @Y[$b1],7,@Y[$b2]
  362. ROTL @Y[$b2],7,@Y[$b3]
  363. || ROTL @Y[$b3],7,@Y[$b0]
  364. bottom2x2?:
  365. ___
  366. }
  367. $code.=<<___;
  368. ADD @K2x[0],@X[0],@X[0] ; accumulate key material
  369. || ADD @K2x[1],@X[1],@X[1]
  370. || ADD @K2x[2],@X[2],@X[2]
  371. || ADD @K2x[3],@X[3],@X[3]
  372. ADD @K2x[0],@Y[0],@Y[0]
  373. || ADD @K2x[1],@Y[1],@Y[1]
  374. || ADD @K2x[2],@Y[2],@Y[2]
  375. || ADD @K2x[3],@Y[3],@Y[3]
  376. || LDNDW *${INP}++[8],@DAT[1]:@DAT[0]
  377. ADD @K2x[4],@X[4],@X[4]
  378. || ADD @K2x[5],@X[5],@X[5]
  379. || ADD @K2x[6],@X[6],@X[6]
  380. || ADD @K2x[7],@X[7],@X[7]
  381. || LDNDW *${INP}[-7],@DAT[3]:@DAT[2]
  382. ADD @K2x[4],@Y[4],@Y[4]
  383. || ADD @K2x[5],@Y[5],@Y[5]
  384. || ADD @K2x[6],@Y[6],@Y[6]
  385. || ADD @K2x[7],@Y[7],@Y[7]
  386. || LDNDW *${INP}[-6],@DAT[5]:@DAT[4]
  387. ADD @K2x[8],@X[8],@X[8]
  388. || ADD @K2x[9],@X[9],@X[9]
  389. || ADD @K2x[10],@X[10],@X[10]
  390. || ADD @K2x[11],@X[11],@X[11]
  391. || LDNDW *${INP}[-5],@DAT[7]:@DAT[6]
  392. ADD @K2x[8],@Y[8],@Y[8]
  393. || ADD @K2x[9],@Y[9],@Y[9]
  394. || ADD @K2x[10],@Y[10],@Y[10]
  395. || ADD @K2x[11],@Y[11],@Y[11]
  396. || LDNDW *${INP}[-4],@DAT[9]:@DAT[8]
  397. ADD @K2x[12],@X[12],@X[12]
  398. || ADD @K2x[13],@X[13],@X[13]
  399. || ADD @K2x[14],@X[14],@X[14]
  400. || ADD @K2x[15],@X[15],@X[15]
  401. || LDNDW *${INP}[-3],@DAT[11]:@DAT[10]
  402. ADD @K2x[12],@Y[12],@Y[12]
  403. || ADD @K2x[13],@Y[13],@Y[13]
  404. || ADD @K2x[14],@Y[14],@Y[14]
  405. || ADD @K2x[15],@Y[15],@Y[15]
  406. || LDNDW *${INP}[-2],@DAT[13]:@DAT[12]
  407. ADD 1,@Y[12],@Y[12] ; adjust counter for 2nd block
  408. || ADD 2,@K2x[12],@K2x[12] ; increment counter
  409. || LDNDW *${INP}[-1],@DAT[15]:@DAT[14]
  410. .if .BIG_ENDIAN
  411. SWAP2 @X[0],@X[0]
  412. || SWAP2 @X[1],@X[1]
  413. || SWAP2 @X[2],@X[2]
  414. || SWAP2 @X[3],@X[3]
  415. SWAP2 @X[4],@X[4]
  416. || SWAP2 @X[5],@X[5]
  417. || SWAP2 @X[6],@X[6]
  418. || SWAP2 @X[7],@X[7]
  419. SWAP2 @X[8],@X[8]
  420. || SWAP2 @X[9],@X[9]
  421. || SWAP4 @X[0],@X[1]
  422. || SWAP4 @X[1],@X[0]
  423. SWAP2 @X[10],@X[10]
  424. || SWAP2 @X[11],@X[11]
  425. || SWAP4 @X[2],@X[3]
  426. || SWAP4 @X[3],@X[2]
  427. SWAP2 @X[12],@X[12]
  428. || SWAP2 @X[13],@X[13]
  429. || SWAP4 @X[4],@X[5]
  430. || SWAP4 @X[5],@X[4]
  431. SWAP2 @X[14],@X[14]
  432. || SWAP2 @X[15],@X[15]
  433. || SWAP4 @X[6],@X[7]
  434. || SWAP4 @X[7],@X[6]
  435. SWAP4 @X[8],@X[9]
  436. || SWAP4 @X[9],@X[8]
  437. || SWAP2 @Y[0],@Y[0]
  438. || SWAP2 @Y[1],@Y[1]
  439. SWAP4 @X[10],@X[11]
  440. || SWAP4 @X[11],@X[10]
  441. || SWAP2 @Y[2],@Y[2]
  442. || SWAP2 @Y[3],@Y[3]
  443. SWAP4 @X[12],@X[13]
  444. || SWAP4 @X[13],@X[12]
  445. || SWAP2 @Y[4],@Y[4]
  446. || SWAP2 @Y[5],@Y[5]
  447. SWAP4 @X[14],@X[15]
  448. || SWAP4 @X[15],@X[14]
  449. || SWAP2 @Y[6],@Y[6]
  450. || SWAP2 @Y[7],@Y[7]
  451. SWAP2 @Y[8],@Y[8]
  452. || SWAP2 @Y[9],@Y[9]
  453. || SWAP4 @Y[0],@Y[1]
  454. || SWAP4 @Y[1],@Y[0]
  455. SWAP2 @Y[10],@Y[10]
  456. || SWAP2 @Y[11],@Y[11]
  457. || SWAP4 @Y[2],@Y[3]
  458. || SWAP4 @Y[3],@Y[2]
  459. SWAP2 @Y[12],@Y[12]
  460. || SWAP2 @Y[13],@Y[13]
  461. || SWAP4 @Y[4],@Y[5]
  462. || SWAP4 @Y[5],@Y[4]
  463. SWAP2 @Y[14],@Y[14]
  464. || SWAP2 @Y[15],@Y[15]
  465. || SWAP4 @Y[6],@Y[7]
  466. || SWAP4 @Y[7],@Y[6]
  467. SWAP4 @Y[8],@Y[9]
  468. || SWAP4 @Y[9],@Y[8]
  469. SWAP4 @Y[10],@Y[11]
  470. || SWAP4 @Y[11],@Y[10]
  471. SWAP4 @Y[12],@Y[13]
  472. || SWAP4 @Y[13],@Y[12]
  473. SWAP4 @Y[14],@Y[15]
  474. || SWAP4 @Y[15],@Y[14]
  475. .endif
  476. XOR @DAT[0],@X[0],@X[0] ; xor 1st block
  477. || XOR @DAT[3],@X[3],@X[3]
  478. || XOR @DAT[2],@X[2],@X[1]
  479. || XOR @DAT[1],@X[1],@X[2]
  480. || LDNDW *${INP}++[8],@DAT[1]:@DAT[0]
  481. XOR @DAT[4],@X[4],@X[4]
  482. || XOR @DAT[7],@X[7],@X[7]
  483. || LDNDW *${INP}[-7],@DAT[3]:@DAT[2]
  484. XOR @DAT[6],@X[6],@X[5]
  485. || XOR @DAT[5],@X[5],@X[6]
  486. || LDNDW *${INP}[-6],@DAT[5]:@DAT[4]
  487. XOR @DAT[8],@X[8],@X[8]
  488. || XOR @DAT[11],@X[11],@X[11]
  489. || LDNDW *${INP}[-5],@DAT[7]:@DAT[6]
  490. XOR @DAT[10],@X[10],@X[9]
  491. || XOR @DAT[9],@X[9],@X[10]
  492. || LDNDW *${INP}[-4],@DAT[9]:@DAT[8]
  493. XOR @DAT[12],@X[12],@X[12]
  494. || XOR @DAT[15],@X[15],@X[15]
  495. || LDNDW *${INP}[-3],@DAT[11]:@DAT[10]
  496. XOR @DAT[14],@X[14],@X[13]
  497. || XOR @DAT[13],@X[13],@X[14]
  498. || LDNDW *${INP}[-2],@DAT[13]:@DAT[12]
  499. [A0] SUB A0,$STEP,A0 ; SUB A0,128,A0
  500. || LDNDW *${INP}[-1],@DAT[15]:@DAT[14]
  501. XOR @Y[0],@DAT[0],@DAT[0] ; xor 2nd block
  502. || XOR @Y[1],@DAT[1],@DAT[1]
  503. || STNDW @X[2]:@X[0],*${OUT}++[8]
  504. XOR @Y[2],@DAT[2],@DAT[2]
  505. || XOR @Y[3],@DAT[3],@DAT[3]
  506. || STNDW @X[3]:@X[1],*${OUT}[-7]
  507. XOR @Y[4],@DAT[4],@DAT[4]
  508. || [A0] LDDW *FP[-12],@X[2]:@X[0] ; re-load key material from stack
  509. || [A0] LDDW *SP[2], @X[3]:@X[1]
  510. XOR @Y[5],@DAT[5],@DAT[5]
  511. || STNDW @X[6]:@X[4],*${OUT}[-6]
  512. XOR @Y[6],@DAT[6],@DAT[6]
  513. || XOR @Y[7],@DAT[7],@DAT[7]
  514. || STNDW @X[7]:@X[5],*${OUT}[-5]
  515. XOR @Y[8],@DAT[8],@DAT[8]
  516. || [A0] LDDW *FP[-10],@X[6]:@X[4]
  517. || [A0] LDDW *SP[4], @X[7]:@X[5]
  518. XOR @Y[9],@DAT[9],@DAT[9]
  519. || STNDW @X[10]:@X[8],*${OUT}[-4]
  520. XOR @Y[10],@DAT[10],@DAT[10]
  521. || XOR @Y[11],@DAT[11],@DAT[11]
  522. || STNDW @X[11]:@X[9],*${OUT}[-3]
  523. XOR @Y[12],@DAT[12],@DAT[12]
  524. || [A0] LDDW *FP[-8], @X[10]:@X[8]
  525. || [A0] LDDW *SP[6], @X[11]:@X[9]
  526. XOR @Y[13],@DAT[13],@DAT[13]
  527. || STNDW @X[14]:@X[12],*${OUT}[-2]
  528. XOR @Y[14],@DAT[14],@DAT[14]
  529. || XOR @Y[15],@DAT[15],@DAT[15]
  530. || STNDW @X[15]:@X[13],*${OUT}[-1]
  531. [A0] MV @K2x[12],@X[12]
  532. || [A0] MV @K2x[13],@X[13]
  533. || [A0] LDW *FP[-6*2], @X[14]
  534. || [A0] LDW *SP[8*2], @X[15]
  535. [A0] DMV @X[2],@X[0],@Y[2]:@Y[0] ; duplicate key material
  536. || STNDW @DAT[1]:@DAT[0],*${OUT}++[8]
  537. [A0] DMV @X[3],@X[1],@Y[3]:@Y[1]
  538. || STNDW @DAT[3]:@DAT[2],*${OUT}[-7]
  539. [A0] DMV @X[6],@X[4],@Y[6]:@Y[4]
  540. || STNDW @DAT[5]:@DAT[4],*${OUT}[-6]
  541. || CMPLTU A0,$STEP,A1 ; is remaining length < 2*blocks?
  542. ||[!A0] BNOP epilogue?
  543. [A0] DMV @X[7],@X[5],@Y[7]:@Y[5]
  544. || STNDW @DAT[7]:@DAT[6],*${OUT}[-5]
  545. ||[!A1] BNOP outer2x?
  546. [A0] DMV @X[10],@X[8],@Y[10]:@Y[8]
  547. || STNDW @DAT[9]:@DAT[8],*${OUT}[-4]
  548. [A0] DMV @X[11],@X[9],@Y[11]:@Y[9]
  549. || STNDW @DAT[11]:@DAT[10],*${OUT}[-3]
  550. [A0] DMV @X[14],@X[12],@Y[14]:@Y[12]
  551. || STNDW @DAT[13]:@DAT[12],*${OUT}[-2]
  552. [A0] DMV @X[15],@X[13],@Y[15]:@Y[13]
  553. || STNDW @DAT[15]:@DAT[14],*${OUT}[-1]
  554. ;;===== branch to epilogue? is taken here
  555. [A1] MVK 64,$STEP
  556. || [A0] MVK 10,B0 ; inner loop counter
  557. ;;===== branch to outer2x? is taken here
  558. ___
  559. {
  560. my ($a0,$a1,$a2,$a3) = (0..3);
  561. my ($b0,$b1,$b2,$b3) = (4..7);
  562. my ($c0,$c1,$c2,$c3) = (8..11);
  563. my ($d0,$d1,$d2,$d3) = (12..15);
  564. $code.=<<___;
  565. top1x?:
  566. ADD @X[$b1],@X[$a1],@X[$a1]
  567. || ADD @X[$b2],@X[$a2],@X[$a2]
  568. ADD @X[$b0],@X[$a0],@X[$a0]
  569. || ADD @X[$b3],@X[$a3],@X[$a3]
  570. || XOR @X[$a1],@X[$d1],@X[$d1]
  571. || XOR @X[$a2],@X[$d2],@X[$d2]
  572. XOR @X[$a0],@X[$d0],@X[$d0]
  573. || XOR @X[$a3],@X[$d3],@X[$d3]
  574. || SWAP2 @X[$d1],@X[$d1] ; rotate by 16
  575. || SWAP2 @X[$d2],@X[$d2]
  576. SWAP2 @X[$d0],@X[$d0]
  577. || SWAP2 @X[$d3],@X[$d3]
  578. || ADD @X[$d1],@X[$c1],@X[$c1]
  579. || ADD @X[$d2],@X[$c2],@X[$c2]
  580. ADD @X[$d0],@X[$c0],@X[$c0]
  581. || ADD @X[$d3],@X[$c3],@X[$c3]
  582. || XOR @X[$c1],@X[$b1],@X[$b1]
  583. || XOR @X[$c2],@X[$b2],@X[$b2]
  584. XOR @X[$c0],@X[$b0],@X[$b0]
  585. || XOR @X[$c3],@X[$b3],@X[$b3]
  586. || ROTL @X[$b1],12,@X[$b1]
  587. || ROTL @X[$b2],12,@X[$b2]
  588. ROTL @X[$b0],12,@X[$b0]
  589. || ROTL @X[$b3],12,@X[$b3]
  590. ADD @X[$b1],@X[$a1],@X[$a1]
  591. || ADD @X[$b2],@X[$a2],@X[$a2]
  592. ADD @X[$b0],@X[$a0],@X[$a0]
  593. || ADD @X[$b3],@X[$a3],@X[$a3]
  594. || XOR @X[$a1],@X[$d1],@X[$d1]
  595. || XOR @X[$a2],@X[$d2],@X[$d2]
  596. XOR @X[$a0],@X[$d0],@X[$d0]
  597. || XOR @X[$a3],@X[$d3],@X[$d3]
  598. || ROTL @X[$d1],8,@X[$d1]
  599. || ROTL @X[$d2],8,@X[$d2]
  600. ROTL @X[$d0],8,@X[$d0]
  601. || ROTL @X[$d3],8,@X[$d3]
  602. || BNOP middle1x? ; protect from interrupt
  603. ADD @X[$d1],@X[$c1],@X[$c1]
  604. || ADD @X[$d2],@X[$c2],@X[$c2]
  605. ADD @X[$d0],@X[$c0],@X[$c0]
  606. || ADD @X[$d3],@X[$c3],@X[$c3]
  607. || XOR @X[$c1],@X[$b1],@X[$b1]
  608. || XOR @X[$c2],@X[$b2],@X[$b2]
  609. || ROTL @X[$d1],0,@X[$d2] ; moved to avoid cross-path stall
  610. || ROTL @X[$d2],0,@X[$d3]
  611. XOR @X[$c0],@X[$b0],@X[$b0]
  612. || XOR @X[$c3],@X[$b3],@X[$b3]
  613. || ROTL @X[$d0],0,@X[$d1]
  614. || ROTL @X[$d3],0,@X[$d0]
  615. ROTL @X[$b1],7,@X[$b0] ; avoided cross-path stall
  616. || ROTL @X[$b2],7,@X[$b1]
  617. ROTL @X[$b0],7,@X[$b3]
  618. || ROTL @X[$b3],7,@X[$b2]
  619. middle1x?:
  620. ADD @X[$b0],@X[$a0],@X[$a0]
  621. || ADD @X[$b1],@X[$a1],@X[$a1]
  622. ADD @X[$b2],@X[$a2],@X[$a2]
  623. || ADD @X[$b3],@X[$a3],@X[$a3]
  624. || XOR @X[$a0],@X[$d0],@X[$d0]
  625. || XOR @X[$a1],@X[$d1],@X[$d1]
  626. XOR @X[$a2],@X[$d2],@X[$d2]
  627. || XOR @X[$a3],@X[$d3],@X[$d3]
  628. || SWAP2 @X[$d0],@X[$d0] ; rotate by 16
  629. || SWAP2 @X[$d1],@X[$d1]
  630. SWAP2 @X[$d2],@X[$d2]
  631. || SWAP2 @X[$d3],@X[$d3]
  632. || ADD @X[$d0],@X[$c2],@X[$c2]
  633. || ADD @X[$d1],@X[$c3],@X[$c3]
  634. ADD @X[$d2],@X[$c0],@X[$c0]
  635. || ADD @X[$d3],@X[$c1],@X[$c1]
  636. || XOR @X[$c2],@X[$b0],@X[$b0]
  637. || XOR @X[$c3],@X[$b1],@X[$b1]
  638. XOR @X[$c0],@X[$b2],@X[$b2]
  639. || XOR @X[$c1],@X[$b3],@X[$b3]
  640. || ROTL @X[$b0],12,@X[$b0]
  641. || ROTL @X[$b1],12,@X[$b1]
  642. ROTL @X[$b2],12,@X[$b2]
  643. || ROTL @X[$b3],12,@X[$b3]
  644. ADD @X[$b0],@X[$a0],@X[$a0]
  645. || ADD @X[$b1],@X[$a1],@X[$a1]
  646. || [B0] SUB B0,1,B0 ; decrement inner loop counter
  647. ADD @X[$b2],@X[$a2],@X[$a2]
  648. || ADD @X[$b3],@X[$a3],@X[$a3]
  649. || XOR @X[$a0],@X[$d0],@X[$d0]
  650. || XOR @X[$a1],@X[$d1],@X[$d1]
  651. XOR @X[$a2],@X[$d2],@X[$d2]
  652. || XOR @X[$a3],@X[$d3],@X[$d3]
  653. || ROTL @X[$d0],8,@X[$d0]
  654. || ROTL @X[$d1],8,@X[$d1]
  655. ROTL @X[$d2],8,@X[$d2]
  656. || ROTL @X[$d3],8,@X[$d3]
  657. || [B0] BNOP top1x? ; even protects from interrupt
  658. ADD @X[$d0],@X[$c2],@X[$c2]
  659. || ADD @X[$d1],@X[$c3],@X[$c3]
  660. ADD @X[$d2],@X[$c0],@X[$c0]
  661. || ADD @X[$d3],@X[$c1],@X[$c1]
  662. || XOR @X[$c2],@X[$b0],@X[$b0]
  663. || XOR @X[$c3],@X[$b1],@X[$b1]
  664. || ROTL @X[$d0],0,@X[$d3] ; moved to avoid cross-path stall
  665. || ROTL @X[$d1],0,@X[$d0]
  666. XOR @X[$c0],@X[$b2],@X[$b2]
  667. || XOR @X[$c1],@X[$b3],@X[$b3]
  668. || ROTL @X[$d2],0,@X[$d1]
  669. || ROTL @X[$d3],0,@X[$d2]
  670. ROTL @X[$b0],7,@X[$b1] ; avoided cross-path stall
  671. || ROTL @X[$b1],7,@X[$b2]
  672. ROTL @X[$b2],7,@X[$b3]
  673. || ROTL @X[$b3],7,@X[$b0]
  674. ||[!B0] CMPLTU A0,$STEP,A1 ; less than 64 bytes left?
  675. bottom1x?:
  676. ___
  677. }
  678. $code.=<<___;
  679. ADD @Y[0],@X[0],@X[0] ; accumulate key material
  680. || ADD @Y[1],@X[1],@X[1]
  681. || ADD @Y[2],@X[2],@X[2]
  682. || ADD @Y[3],@X[3],@X[3]
  683. ||[!A1] LDNDW *${INP}++[8],@DAT[1]:@DAT[0]
  684. || [A1] BNOP tail?
  685. ADD @Y[4],@X[4],@X[4]
  686. || ADD @Y[5],@X[5],@X[5]
  687. || ADD @Y[6],@X[6],@X[6]
  688. || ADD @Y[7],@X[7],@X[7]
  689. ||[!A1] LDNDW *${INP}[-7],@DAT[3]:@DAT[2]
  690. ADD @Y[8],@X[8],@X[8]
  691. || ADD @Y[9],@X[9],@X[9]
  692. || ADD @Y[10],@X[10],@X[10]
  693. || ADD @Y[11],@X[11],@X[11]
  694. ||[!A1] LDNDW *${INP}[-6],@DAT[5]:@DAT[4]
  695. ADD @Y[12],@X[12],@X[12]
  696. || ADD @Y[13],@X[13],@X[13]
  697. || ADD @Y[14],@X[14],@X[14]
  698. || ADD @Y[15],@X[15],@X[15]
  699. ||[!A1] LDNDW *${INP}[-5],@DAT[7]:@DAT[6]
  700. [!A1] LDNDW *${INP}[-4],@DAT[9]:@DAT[8]
  701. [!A1] LDNDW *${INP}[-3],@DAT[11]:@DAT[10]
  702. LDNDW *${INP}[-2],@DAT[13]:@DAT[12]
  703. LDNDW *${INP}[-1],@DAT[15]:@DAT[14]
  704. .if .BIG_ENDIAN
  705. SWAP2 @X[0],@X[0]
  706. || SWAP2 @X[1],@X[1]
  707. || SWAP2 @X[2],@X[2]
  708. || SWAP2 @X[3],@X[3]
  709. SWAP2 @X[4],@X[4]
  710. || SWAP2 @X[5],@X[5]
  711. || SWAP2 @X[6],@X[6]
  712. || SWAP2 @X[7],@X[7]
  713. SWAP2 @X[8],@X[8]
  714. || SWAP2 @X[9],@X[9]
  715. || SWAP4 @X[0],@X[1]
  716. || SWAP4 @X[1],@X[0]
  717. SWAP2 @X[10],@X[10]
  718. || SWAP2 @X[11],@X[11]
  719. || SWAP4 @X[2],@X[3]
  720. || SWAP4 @X[3],@X[2]
  721. SWAP2 @X[12],@X[12]
  722. || SWAP2 @X[13],@X[13]
  723. || SWAP4 @X[4],@X[5]
  724. || SWAP4 @X[5],@X[4]
  725. SWAP2 @X[14],@X[14]
  726. || SWAP2 @X[15],@X[15]
  727. || SWAP4 @X[6],@X[7]
  728. || SWAP4 @X[7],@X[6]
  729. SWAP4 @X[8],@X[9]
  730. || SWAP4 @X[9],@X[8]
  731. SWAP4 @X[10],@X[11]
  732. || SWAP4 @X[11],@X[10]
  733. SWAP4 @X[12],@X[13]
  734. || SWAP4 @X[13],@X[12]
  735. SWAP4 @X[14],@X[15]
  736. || SWAP4 @X[15],@X[14]
  737. .else
  738. NOP 1
  739. .endif
  740. XOR @X[0],@DAT[0],@DAT[0] ; xor with input
  741. || XOR @X[1],@DAT[1],@DAT[1]
  742. || XOR @X[2],@DAT[2],@DAT[2]
  743. || XOR @X[3],@DAT[3],@DAT[3]
  744. || [A0] SUB A0,$STEP,A0 ; SUB A0,64,A0
  745. XOR @X[4],@DAT[4],@DAT[4]
  746. || XOR @X[5],@DAT[5],@DAT[5]
  747. || XOR @X[6],@DAT[6],@DAT[6]
  748. || XOR @X[7],@DAT[7],@DAT[7]
  749. || STNDW @DAT[1]:@DAT[0],*${OUT}++[8]
  750. XOR @X[8],@DAT[8],@DAT[8]
  751. || XOR @X[9],@DAT[9],@DAT[9]
  752. || XOR @X[10],@DAT[10],@DAT[10]
  753. || XOR @X[11],@DAT[11],@DAT[11]
  754. || STNDW @DAT[3]:@DAT[2],*${OUT}[-7]
  755. XOR @X[12],@DAT[12],@DAT[12]
  756. || XOR @X[13],@DAT[13],@DAT[13]
  757. || XOR @X[14],@DAT[14],@DAT[14]
  758. || XOR @X[15],@DAT[15],@DAT[15]
  759. || STNDW @DAT[5]:@DAT[4],*${OUT}[-6]
  760. || [A0] BNOP top1x?
  761. [A0] DMV @Y[2],@Y[0],@X[2]:@X[0] ; duplicate key material
  762. || [A0] DMV @Y[3],@Y[1],@X[3]:@X[1]
  763. || STNDW @DAT[7]:@DAT[6],*${OUT}[-5]
  764. [A0] DMV @Y[6],@Y[4],@X[6]:@X[4]
  765. || [A0] DMV @Y[7],@Y[5],@X[7]:@X[5]
  766. || STNDW @DAT[9]:@DAT[8],*${OUT}[-4]
  767. [A0] DMV @Y[10],@Y[8],@X[10]:@X[8]
  768. || [A0] DMV @Y[11],@Y[9],@X[11]:@X[9]
  769. || [A0] ADD 1,@Y[12],@Y[12] ; increment counter
  770. || STNDW @DAT[11]:@DAT[10],*${OUT}[-3]
  771. [A0] DMV @Y[14],@Y[12],@X[14]:@X[12]
  772. || [A0] DMV @Y[15],@Y[13],@X[15]:@X[13]
  773. || STNDW @DAT[13]:@DAT[12],*${OUT}[-2]
  774. [A0] MVK 10,B0 ; inner loop counter
  775. || STNDW @DAT[15]:@DAT[14],*${OUT}[-1]
  776. ;;===== branch to top1x? is taken here
  777. epilogue?:
  778. LDDW *FP[-4],A11:A10 ; ABI says so
  779. LDDW *FP[-3],A13:A12
  780. || LDDW *SP[3+8],B11:B10
  781. LDDW *SP[4+8],B13:B12
  782. || BNOP RA
  783. LDW *++SP(40+64),FP ; restore frame pointer
  784. NOP 4
  785. tail?:
  786. LDBU *${INP}++[1],B24 ; load byte by byte
  787. || SUB A0,1,A0
  788. || SUB A0,1,B1
  789. [!B1] BNOP epilogue? ; interrupts are disabled for whole time
  790. || [A0] LDBU *${INP}++[1],B24
  791. || [A0] SUB A0,1,A0
  792. || SUB B1,1,B1
  793. [!B1] BNOP epilogue?
  794. || [A0] LDBU *${INP}++[1],B24
  795. || [A0] SUB A0,1,A0
  796. || SUB B1,1,B1
  797. [!B1] BNOP epilogue?
  798. || ROTL @X[0],0,A24
  799. || [A0] LDBU *${INP}++[1],B24
  800. || [A0] SUB A0,1,A0
  801. || SUB B1,1,B1
  802. [!B1] BNOP epilogue?
  803. || ROTL @X[0],24,A24
  804. || [A0] LDBU *${INP}++[1],A24
  805. || [A0] SUB A0,1,A0
  806. || SUB B1,1,B1
  807. [!B1] BNOP epilogue?
  808. || ROTL @X[0],16,A24
  809. || [A0] LDBU *${INP}++[1],A24
  810. || [A0] SUB A0,1,A0
  811. || SUB B1,1,B1
  812. || XOR A24,B24,B25
  813. STB B25,*${OUT}++[1] ; store byte by byte
  814. ||[!B1] BNOP epilogue?
  815. || ROTL @X[0],8,A24
  816. || [A0] LDBU *${INP}++[1],A24
  817. || [A0] SUB A0,1,A0
  818. || SUB B1,1,B1
  819. || XOR A24,B24,B25
  820. STB B25,*${OUT}++[1]
  821. ___
  822. sub TAIL_STEP {
  823. my $Xi= shift;
  824. my $T = ($Xi=~/^B/?"B24":"A24"); # match @X[i] to avoid cross path
  825. my $D = $T; $D=~tr/AB/BA/;
  826. my $O = $D; $O=~s/24/25/;
  827. $code.=<<___;
  828. ||[!B1] BNOP epilogue?
  829. || ROTL $Xi,0,$T
  830. || [A0] LDBU *${INP}++[1],$D
  831. || [A0] SUB A0,1,A0
  832. || SUB B1,1,B1
  833. || XOR A24,B24,$O
  834. STB $O,*${OUT}++[1]
  835. ||[!B1] BNOP epilogue?
  836. || ROTL $Xi,24,$T
  837. || [A0] LDBU *${INP}++[1],$T
  838. || [A0] SUB A0,1,A0
  839. || SUB B1,1,B1
  840. || XOR A24,B24,$O
  841. STB $O,*${OUT}++[1]
  842. ||[!B1] BNOP epilogue?
  843. || ROTL $Xi,16,$T
  844. || [A0] LDBU *${INP}++[1],$T
  845. || [A0] SUB A0,1,A0
  846. || SUB B1,1,B1
  847. || XOR A24,B24,$O
  848. STB $O,*${OUT}++[1]
  849. ||[!B1] BNOP epilogue?
  850. || ROTL $Xi,8,$T
  851. || [A0] LDBU *${INP}++[1],$T
  852. || [A0] SUB A0,1,A0
  853. || SUB B1,1,B1
  854. || XOR A24,B24,$O
  855. STB $O,*${OUT}++[1]
  856. ___
  857. }
  858. foreach (1..14) { TAIL_STEP(@X[$_]); }
  859. $code.=<<___;
  860. ||[!B1] BNOP epilogue?
  861. || ROTL @X[15],0,B24
  862. || XOR A24,B24,A25
  863. STB A25,*${OUT}++[1]
  864. || ROTL @X[15],24,B24
  865. || XOR A24,B24,A25
  866. STB A25,*${OUT}++[1]
  867. || ROTL @X[15],16,B24
  868. || XOR A24,B24,A25
  869. STB A25,*${OUT}++[1]
  870. || XOR A24,B24,A25
  871. STB A25,*${OUT}++[1]
  872. || XOR A24,B24,B25
  873. STB B25,*${OUT}++[1]
  874. .endasmfunc
  875. .sect .const
  876. .cstring "ChaCha20 for C64x+, CRYPTOGAMS by <appro\@openssl.org>"
  877. .align 4
  878. ___
  879. print $code;
  880. close STDOUT or die "error closing STDOUT: $!";