keccak1600-ppc64.pl 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. #!/usr/bin/env perl
  2. # Copyright 2017-2020 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 <[email protected]> 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. # Keccak-1600 for PPC64.
  17. #
  18. # June 2017.
  19. #
  20. # This is straightforward KECCAK_1X_ALT implementation that works on
  21. # *any* PPC64. Then PowerISA 2.07 adds 2x64-bit vector rotate, and
  22. # it's possible to achieve performance better than below, but that is
  23. # naturally option only for POWER8 and successors...
  24. #
  25. ######################################################################
  26. # Numbers are cycles per processed byte.
  27. #
  28. # r=1088(*)
  29. #
  30. # PPC970/G5 14.0/+130%
  31. # POWER7 9.7/+110%
  32. # POWER8 10.6/+100%
  33. # POWER9 8.2/+66%
  34. #
  35. # (*) Corresponds to SHA3-256. Percentage after slash is improvement
  36. # over gcc-4.x-generated KECCAK_1X_ALT code. Newer compilers do
  37. # much better (but watch out for them generating code specific
  38. # to processor they execute on).
  39. # $output is the last argument if it looks like a file (it has an extension)
  40. # $flavour is the first argument if it doesn't look like a file
  41. $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
  42. $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
  43. if ($flavour =~ /64/) {
  44. $SIZE_T =8;
  45. $LRSAVE =2*$SIZE_T;
  46. $UCMP ="cmpld";
  47. $STU ="stdu";
  48. $POP ="ld";
  49. $PUSH ="std";
  50. } else { die "nonsense $flavour"; }
  51. $LITTLE_ENDIAN = ($flavour=~/le$/) ? 1 : 0;
  52. if ($LITTLE_ENDIAN) {
  53. $DWORD_LE_LOAD = "ldu r0,8(r3)";
  54. $LE_LOAD_SIZE = "8";
  55. } else {
  56. $DWORD_LE_LOAD = "bl dword_le_load";
  57. $LE_LOAD_SIZE = "1";
  58. }
  59. $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
  60. ( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
  61. ( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
  62. die "can't locate ppc-xlate.pl";
  63. open STDOUT,"| $^X $xlate $flavour \"$output\""
  64. or die "can't call $xlate: $!";
  65. $FRAME=24*$SIZE_T+6*$SIZE_T+32;
  66. $LOCALS=6*$SIZE_T;
  67. $TEMP=$LOCALS+6*$SIZE_T;
  68. my $sp ="r1";
  69. my @A = map([ "r$_", "r".($_+1), "r".($_+2), "r".($_+3), "r".($_+4) ],
  70. (7, 12, 17, 22, 27));
  71. $A[1][1] = "r6"; # r13 is reserved
  72. my @C = map("r$_", (0,3,4,5));
  73. my @rhotates = ([ 0, 1, 62, 28, 27 ],
  74. [ 36, 44, 6, 55, 20 ],
  75. [ 3, 10, 43, 25, 39 ],
  76. [ 41, 45, 15, 21, 8 ],
  77. [ 18, 2, 61, 56, 14 ]);
  78. $code.=<<___;
  79. .text
  80. .type KeccakF1600_int,\@function
  81. .align 5
  82. KeccakF1600_int:
  83. li r0,24
  84. mtctr r0
  85. b .Loop
  86. .align 4
  87. .Loop:
  88. xor $C[0],$A[0][0],$A[1][0] ; Theta
  89. std $A[0][4],`$TEMP+0`($sp)
  90. xor $C[1],$A[0][1],$A[1][1]
  91. std $A[1][4],`$TEMP+8`($sp)
  92. xor $C[2],$A[0][2],$A[1][2]
  93. std $A[2][4],`$TEMP+16`($sp)
  94. xor $C[3],$A[0][3],$A[1][3]
  95. std $A[3][4],`$TEMP+24`($sp)
  96. ___
  97. $C[4]=$A[0][4];
  98. $C[5]=$A[1][4];
  99. $C[6]=$A[2][4];
  100. $C[7]=$A[3][4];
  101. $code.=<<___;
  102. xor $C[4],$A[0][4],$A[1][4]
  103. xor $C[0],$C[0],$A[2][0]
  104. xor $C[1],$C[1],$A[2][1]
  105. xor $C[2],$C[2],$A[2][2]
  106. xor $C[3],$C[3],$A[2][3]
  107. xor $C[4],$C[4],$A[2][4]
  108. xor $C[0],$C[0],$A[3][0]
  109. xor $C[1],$C[1],$A[3][1]
  110. xor $C[2],$C[2],$A[3][2]
  111. xor $C[3],$C[3],$A[3][3]
  112. xor $C[4],$C[4],$A[3][4]
  113. xor $C[0],$C[0],$A[4][0]
  114. xor $C[2],$C[2],$A[4][2]
  115. xor $C[1],$C[1],$A[4][1]
  116. xor $C[3],$C[3],$A[4][3]
  117. rotldi $C[5],$C[2],1
  118. xor $C[4],$C[4],$A[4][4]
  119. rotldi $C[6],$C[3],1
  120. xor $C[5],$C[5],$C[0]
  121. rotldi $C[7],$C[4],1
  122. xor $A[0][1],$A[0][1],$C[5]
  123. xor $A[1][1],$A[1][1],$C[5]
  124. xor $A[2][1],$A[2][1],$C[5]
  125. xor $A[3][1],$A[3][1],$C[5]
  126. xor $A[4][1],$A[4][1],$C[5]
  127. rotldi $C[5],$C[0],1
  128. xor $C[6],$C[6],$C[1]
  129. xor $C[2],$C[2],$C[7]
  130. rotldi $C[7],$C[1],1
  131. xor $C[3],$C[3],$C[5]
  132. xor $C[4],$C[4],$C[7]
  133. xor $C[1], $A[0][2],$C[6] ;mr $C[1],$A[0][2]
  134. xor $A[1][2],$A[1][2],$C[6]
  135. xor $A[2][2],$A[2][2],$C[6]
  136. xor $A[3][2],$A[3][2],$C[6]
  137. xor $A[4][2],$A[4][2],$C[6]
  138. xor $A[0][0],$A[0][0],$C[4]
  139. xor $A[1][0],$A[1][0],$C[4]
  140. xor $A[2][0],$A[2][0],$C[4]
  141. xor $A[3][0],$A[3][0],$C[4]
  142. xor $A[4][0],$A[4][0],$C[4]
  143. ___
  144. $C[4]=undef;
  145. $C[5]=undef;
  146. $C[6]=undef;
  147. $C[7]=undef;
  148. $code.=<<___;
  149. ld $A[0][4],`$TEMP+0`($sp)
  150. xor $C[0], $A[0][3],$C[2] ;mr $C[0],$A[0][3]
  151. ld $A[1][4],`$TEMP+8`($sp)
  152. xor $A[1][3],$A[1][3],$C[2]
  153. ld $A[2][4],`$TEMP+16`($sp)
  154. xor $A[2][3],$A[2][3],$C[2]
  155. ld $A[3][4],`$TEMP+24`($sp)
  156. xor $A[3][3],$A[3][3],$C[2]
  157. xor $A[4][3],$A[4][3],$C[2]
  158. xor $C[2], $A[0][4],$C[3] ;mr $C[2],$A[0][4]
  159. xor $A[1][4],$A[1][4],$C[3]
  160. xor $A[2][4],$A[2][4],$C[3]
  161. xor $A[3][4],$A[3][4],$C[3]
  162. xor $A[4][4],$A[4][4],$C[3]
  163. mr $C[3],$A[0][1] ; Rho+Pi
  164. rotldi $A[0][1],$A[1][1],$rhotates[1][1]
  165. ;mr $C[1],$A[0][2]
  166. rotldi $A[0][2],$A[2][2],$rhotates[2][2]
  167. ;mr $C[0],$A[0][3]
  168. rotldi $A[0][3],$A[3][3],$rhotates[3][3]
  169. ;mr $C[2],$A[0][4]
  170. rotldi $A[0][4],$A[4][4],$rhotates[4][4]
  171. rotldi $A[1][1],$A[1][4],$rhotates[1][4]
  172. rotldi $A[2][2],$A[2][3],$rhotates[2][3]
  173. rotldi $A[3][3],$A[3][2],$rhotates[3][2]
  174. rotldi $A[4][4],$A[4][1],$rhotates[4][1]
  175. rotldi $A[1][4],$A[4][2],$rhotates[4][2]
  176. rotldi $A[2][3],$A[3][4],$rhotates[3][4]
  177. rotldi $A[3][2],$A[2][1],$rhotates[2][1]
  178. rotldi $A[4][1],$A[1][3],$rhotates[1][3]
  179. rotldi $A[4][2],$A[2][4],$rhotates[2][4]
  180. rotldi $A[3][4],$A[4][3],$rhotates[4][3]
  181. rotldi $A[2][1],$A[1][2],$rhotates[1][2]
  182. rotldi $A[1][3],$A[3][1],$rhotates[3][1]
  183. rotldi $A[2][4],$A[4][0],$rhotates[4][0]
  184. rotldi $A[4][3],$A[3][0],$rhotates[3][0]
  185. rotldi $A[1][2],$A[2][0],$rhotates[2][0]
  186. rotldi $A[3][1],$A[1][0],$rhotates[1][0]
  187. rotldi $A[1][0],$C[0],$rhotates[0][3]
  188. rotldi $A[2][0],$C[3],$rhotates[0][1]
  189. rotldi $A[3][0],$C[2],$rhotates[0][4]
  190. rotldi $A[4][0],$C[1],$rhotates[0][2]
  191. andc $C[0],$A[0][2],$A[0][1] ; Chi+Iota
  192. andc $C[1],$A[0][3],$A[0][2]
  193. andc $C[2],$A[0][0],$A[0][4]
  194. andc $C[3],$A[0][1],$A[0][0]
  195. xor $A[0][0],$A[0][0],$C[0]
  196. andc $C[0],$A[0][4],$A[0][3]
  197. xor $A[0][1],$A[0][1],$C[1]
  198. ld $C[1],`$LOCALS+4*$SIZE_T`($sp)
  199. xor $A[0][3],$A[0][3],$C[2]
  200. xor $A[0][4],$A[0][4],$C[3]
  201. xor $A[0][2],$A[0][2],$C[0]
  202. ldu $C[3],8($C[1]) ; Iota[i++]
  203. andc $C[0],$A[1][2],$A[1][1]
  204. std $C[1],`$LOCALS+4*$SIZE_T`($sp)
  205. andc $C[1],$A[1][3],$A[1][2]
  206. andc $C[2],$A[1][0],$A[1][4]
  207. xor $A[0][0],$A[0][0],$C[3] ; A[0][0] ^= Iota
  208. andc $C[3],$A[1][1],$A[1][0]
  209. xor $A[1][0],$A[1][0],$C[0]
  210. andc $C[0],$A[1][4],$A[1][3]
  211. xor $A[1][1],$A[1][1],$C[1]
  212. xor $A[1][3],$A[1][3],$C[2]
  213. xor $A[1][4],$A[1][4],$C[3]
  214. xor $A[1][2],$A[1][2],$C[0]
  215. andc $C[0],$A[2][2],$A[2][1]
  216. andc $C[1],$A[2][3],$A[2][2]
  217. andc $C[2],$A[2][0],$A[2][4]
  218. andc $C[3],$A[2][1],$A[2][0]
  219. xor $A[2][0],$A[2][0],$C[0]
  220. andc $C[0],$A[2][4],$A[2][3]
  221. xor $A[2][1],$A[2][1],$C[1]
  222. xor $A[2][3],$A[2][3],$C[2]
  223. xor $A[2][4],$A[2][4],$C[3]
  224. xor $A[2][2],$A[2][2],$C[0]
  225. andc $C[0],$A[3][2],$A[3][1]
  226. andc $C[1],$A[3][3],$A[3][2]
  227. andc $C[2],$A[3][0],$A[3][4]
  228. andc $C[3],$A[3][1],$A[3][0]
  229. xor $A[3][0],$A[3][0],$C[0]
  230. andc $C[0],$A[3][4],$A[3][3]
  231. xor $A[3][1],$A[3][1],$C[1]
  232. xor $A[3][3],$A[3][3],$C[2]
  233. xor $A[3][4],$A[3][4],$C[3]
  234. xor $A[3][2],$A[3][2],$C[0]
  235. andc $C[0],$A[4][2],$A[4][1]
  236. andc $C[1],$A[4][3],$A[4][2]
  237. andc $C[2],$A[4][0],$A[4][4]
  238. andc $C[3],$A[4][1],$A[4][0]
  239. xor $A[4][0],$A[4][0],$C[0]
  240. andc $C[0],$A[4][4],$A[4][3]
  241. xor $A[4][1],$A[4][1],$C[1]
  242. xor $A[4][3],$A[4][3],$C[2]
  243. xor $A[4][4],$A[4][4],$C[3]
  244. xor $A[4][2],$A[4][2],$C[0]
  245. bdnz .Loop
  246. blr
  247. .long 0
  248. .byte 0,12,0x14,0,0,0,0,0
  249. .size KeccakF1600_int,.-KeccakF1600_int
  250. .type KeccakF1600,\@function
  251. .align 5
  252. KeccakF1600:
  253. $STU $sp,-$FRAME($sp)
  254. mflr r0
  255. $PUSH r14,`$FRAME-$SIZE_T*18`($sp)
  256. $PUSH r15,`$FRAME-$SIZE_T*17`($sp)
  257. $PUSH r16,`$FRAME-$SIZE_T*16`($sp)
  258. $PUSH r17,`$FRAME-$SIZE_T*15`($sp)
  259. $PUSH r18,`$FRAME-$SIZE_T*14`($sp)
  260. $PUSH r19,`$FRAME-$SIZE_T*13`($sp)
  261. $PUSH r20,`$FRAME-$SIZE_T*12`($sp)
  262. $PUSH r21,`$FRAME-$SIZE_T*11`($sp)
  263. $PUSH r22,`$FRAME-$SIZE_T*10`($sp)
  264. $PUSH r23,`$FRAME-$SIZE_T*9`($sp)
  265. $PUSH r24,`$FRAME-$SIZE_T*8`($sp)
  266. $PUSH r25,`$FRAME-$SIZE_T*7`($sp)
  267. $PUSH r26,`$FRAME-$SIZE_T*6`($sp)
  268. $PUSH r27,`$FRAME-$SIZE_T*5`($sp)
  269. $PUSH r28,`$FRAME-$SIZE_T*4`($sp)
  270. $PUSH r29,`$FRAME-$SIZE_T*3`($sp)
  271. $PUSH r30,`$FRAME-$SIZE_T*2`($sp)
  272. $PUSH r31,`$FRAME-$SIZE_T*1`($sp)
  273. $PUSH r0,`$FRAME+$LRSAVE`($sp)
  274. bl PICmeup
  275. subi r12,r12,8 ; prepare for ldu
  276. $PUSH r3,`$LOCALS+0*$SIZE_T`($sp)
  277. ;$PUSH r4,`$LOCALS+1*$SIZE_T`($sp)
  278. ;$PUSH r5,`$LOCALS+2*$SIZE_T`($sp)
  279. ;$PUSH r6,`$LOCALS+3*$SIZE_T`($sp)
  280. $PUSH r12,`$LOCALS+4*$SIZE_T`($sp)
  281. ld $A[0][0],`8*0`(r3) ; load A[5][5]
  282. ld $A[0][1],`8*1`(r3)
  283. ld $A[0][2],`8*2`(r3)
  284. ld $A[0][3],`8*3`(r3)
  285. ld $A[0][4],`8*4`(r3)
  286. ld $A[1][0],`8*5`(r3)
  287. ld $A[1][1],`8*6`(r3)
  288. ld $A[1][2],`8*7`(r3)
  289. ld $A[1][3],`8*8`(r3)
  290. ld $A[1][4],`8*9`(r3)
  291. ld $A[2][0],`8*10`(r3)
  292. ld $A[2][1],`8*11`(r3)
  293. ld $A[2][2],`8*12`(r3)
  294. ld $A[2][3],`8*13`(r3)
  295. ld $A[2][4],`8*14`(r3)
  296. ld $A[3][0],`8*15`(r3)
  297. ld $A[3][1],`8*16`(r3)
  298. ld $A[3][2],`8*17`(r3)
  299. ld $A[3][3],`8*18`(r3)
  300. ld $A[3][4],`8*19`(r3)
  301. ld $A[4][0],`8*20`(r3)
  302. ld $A[4][1],`8*21`(r3)
  303. ld $A[4][2],`8*22`(r3)
  304. ld $A[4][3],`8*23`(r3)
  305. ld $A[4][4],`8*24`(r3)
  306. bl KeccakF1600_int
  307. $POP r3,`$LOCALS+0*$SIZE_T`($sp)
  308. std $A[0][0],`8*0`(r3) ; return A[5][5]
  309. std $A[0][1],`8*1`(r3)
  310. std $A[0][2],`8*2`(r3)
  311. std $A[0][3],`8*3`(r3)
  312. std $A[0][4],`8*4`(r3)
  313. std $A[1][0],`8*5`(r3)
  314. std $A[1][1],`8*6`(r3)
  315. std $A[1][2],`8*7`(r3)
  316. std $A[1][3],`8*8`(r3)
  317. std $A[1][4],`8*9`(r3)
  318. std $A[2][0],`8*10`(r3)
  319. std $A[2][1],`8*11`(r3)
  320. std $A[2][2],`8*12`(r3)
  321. std $A[2][3],`8*13`(r3)
  322. std $A[2][4],`8*14`(r3)
  323. std $A[3][0],`8*15`(r3)
  324. std $A[3][1],`8*16`(r3)
  325. std $A[3][2],`8*17`(r3)
  326. std $A[3][3],`8*18`(r3)
  327. std $A[3][4],`8*19`(r3)
  328. std $A[4][0],`8*20`(r3)
  329. std $A[4][1],`8*21`(r3)
  330. std $A[4][2],`8*22`(r3)
  331. std $A[4][3],`8*23`(r3)
  332. std $A[4][4],`8*24`(r3)
  333. $POP r0,`$FRAME+$LRSAVE`($sp)
  334. $POP r14,`$FRAME-$SIZE_T*18`($sp)
  335. $POP r15,`$FRAME-$SIZE_T*17`($sp)
  336. $POP r16,`$FRAME-$SIZE_T*16`($sp)
  337. $POP r17,`$FRAME-$SIZE_T*15`($sp)
  338. $POP r18,`$FRAME-$SIZE_T*14`($sp)
  339. $POP r19,`$FRAME-$SIZE_T*13`($sp)
  340. $POP r20,`$FRAME-$SIZE_T*12`($sp)
  341. $POP r21,`$FRAME-$SIZE_T*11`($sp)
  342. $POP r22,`$FRAME-$SIZE_T*10`($sp)
  343. $POP r23,`$FRAME-$SIZE_T*9`($sp)
  344. $POP r24,`$FRAME-$SIZE_T*8`($sp)
  345. $POP r25,`$FRAME-$SIZE_T*7`($sp)
  346. $POP r26,`$FRAME-$SIZE_T*6`($sp)
  347. $POP r27,`$FRAME-$SIZE_T*5`($sp)
  348. $POP r28,`$FRAME-$SIZE_T*4`($sp)
  349. $POP r29,`$FRAME-$SIZE_T*3`($sp)
  350. $POP r30,`$FRAME-$SIZE_T*2`($sp)
  351. $POP r31,`$FRAME-$SIZE_T*1`($sp)
  352. mtlr r0
  353. addi $sp,$sp,$FRAME
  354. blr
  355. .long 0
  356. .byte 0,12,4,1,0x80,18,1,0
  357. .long 0
  358. .size KeccakF1600,.-KeccakF1600
  359. ___
  360. if (!$LITTLE_ENDIAN) {
  361. $code.=<<___;
  362. .type dword_le_load,\@function
  363. .align 5
  364. dword_le_load:
  365. lbz r0,1(r3)
  366. lbz r4,2(r3)
  367. lbz r5,3(r3)
  368. insrdi r0,r4,8,48
  369. lbz r4,4(r3)
  370. insrdi r0,r5,8,40
  371. lbz r5,5(r3)
  372. insrdi r0,r4,8,32
  373. lbz r4,6(r3)
  374. insrdi r0,r5,8,24
  375. lbz r5,7(r3)
  376. insrdi r0,r4,8,16
  377. lbzu r4,8(r3)
  378. insrdi r0,r5,8,8
  379. insrdi r0,r4,8,0
  380. blr
  381. .long 0
  382. .byte 0,12,0x14,0,0,0,1,0
  383. .long 0
  384. .size dword_le_load,.-dword_le_load
  385. ___
  386. }
  387. $code.=<<___;
  388. .globl SHA3_absorb
  389. .type SHA3_absorb,\@function
  390. .align 5
  391. SHA3_absorb:
  392. $STU $sp,-$FRAME($sp)
  393. mflr r0
  394. $PUSH r14,`$FRAME-$SIZE_T*18`($sp)
  395. $PUSH r15,`$FRAME-$SIZE_T*17`($sp)
  396. $PUSH r16,`$FRAME-$SIZE_T*16`($sp)
  397. $PUSH r17,`$FRAME-$SIZE_T*15`($sp)
  398. $PUSH r18,`$FRAME-$SIZE_T*14`($sp)
  399. $PUSH r19,`$FRAME-$SIZE_T*13`($sp)
  400. $PUSH r20,`$FRAME-$SIZE_T*12`($sp)
  401. $PUSH r21,`$FRAME-$SIZE_T*11`($sp)
  402. $PUSH r22,`$FRAME-$SIZE_T*10`($sp)
  403. $PUSH r23,`$FRAME-$SIZE_T*9`($sp)
  404. $PUSH r24,`$FRAME-$SIZE_T*8`($sp)
  405. $PUSH r25,`$FRAME-$SIZE_T*7`($sp)
  406. $PUSH r26,`$FRAME-$SIZE_T*6`($sp)
  407. $PUSH r27,`$FRAME-$SIZE_T*5`($sp)
  408. $PUSH r28,`$FRAME-$SIZE_T*4`($sp)
  409. $PUSH r29,`$FRAME-$SIZE_T*3`($sp)
  410. $PUSH r30,`$FRAME-$SIZE_T*2`($sp)
  411. $PUSH r31,`$FRAME-$SIZE_T*1`($sp)
  412. $PUSH r0,`$FRAME+$LRSAVE`($sp)
  413. bl PICmeup
  414. subi r4,r4,$LE_LOAD_SIZE ; prepare for ldu or lbzu
  415. subi r12,r12,8 ; prepare for ldu
  416. $PUSH r3,`$LOCALS+0*$SIZE_T`($sp) ; save A[][]
  417. $PUSH r4,`$LOCALS+1*$SIZE_T`($sp) ; save inp
  418. $PUSH r5,`$LOCALS+2*$SIZE_T`($sp) ; save len
  419. $PUSH r6,`$LOCALS+3*$SIZE_T`($sp) ; save bsz
  420. mr r0,r6
  421. $PUSH r12,`$LOCALS+4*$SIZE_T`($sp)
  422. ld $A[0][0],`8*0`(r3) ; load A[5][5]
  423. ld $A[0][1],`8*1`(r3)
  424. ld $A[0][2],`8*2`(r3)
  425. ld $A[0][3],`8*3`(r3)
  426. ld $A[0][4],`8*4`(r3)
  427. ld $A[1][0],`8*5`(r3)
  428. ld $A[1][1],`8*6`(r3)
  429. ld $A[1][2],`8*7`(r3)
  430. ld $A[1][3],`8*8`(r3)
  431. ld $A[1][4],`8*9`(r3)
  432. ld $A[2][0],`8*10`(r3)
  433. ld $A[2][1],`8*11`(r3)
  434. ld $A[2][2],`8*12`(r3)
  435. ld $A[2][3],`8*13`(r3)
  436. ld $A[2][4],`8*14`(r3)
  437. ld $A[3][0],`8*15`(r3)
  438. ld $A[3][1],`8*16`(r3)
  439. ld $A[3][2],`8*17`(r3)
  440. ld $A[3][3],`8*18`(r3)
  441. ld $A[3][4],`8*19`(r3)
  442. ld $A[4][0],`8*20`(r3)
  443. ld $A[4][1],`8*21`(r3)
  444. ld $A[4][2],`8*22`(r3)
  445. ld $A[4][3],`8*23`(r3)
  446. ld $A[4][4],`8*24`(r3)
  447. mr r3,r4
  448. mr r4,r5
  449. mr r5,r0
  450. b .Loop_absorb
  451. .align 4
  452. .Loop_absorb:
  453. $UCMP r4,r5 ; len < bsz?
  454. blt .Labsorbed
  455. sub r4,r4,r5 ; len -= bsz
  456. srwi r5,r5,3
  457. $PUSH r4,`$LOCALS+2*$SIZE_T`($sp) ; save len
  458. mtctr r5
  459. $DWORD_LE_LOAD ; *inp++
  460. xor $A[0][0],$A[0][0],r0
  461. bdz .Lprocess_block
  462. $DWORD_LE_LOAD ; *inp++
  463. xor $A[0][1],$A[0][1],r0
  464. bdz .Lprocess_block
  465. $DWORD_LE_LOAD ; *inp++
  466. xor $A[0][2],$A[0][2],r0
  467. bdz .Lprocess_block
  468. $DWORD_LE_LOAD ; *inp++
  469. xor $A[0][3],$A[0][3],r0
  470. bdz .Lprocess_block
  471. $DWORD_LE_LOAD ; *inp++
  472. xor $A[0][4],$A[0][4],r0
  473. bdz .Lprocess_block
  474. $DWORD_LE_LOAD ; *inp++
  475. xor $A[1][0],$A[1][0],r0
  476. bdz .Lprocess_block
  477. $DWORD_LE_LOAD ; *inp++
  478. xor $A[1][1],$A[1][1],r0
  479. bdz .Lprocess_block
  480. $DWORD_LE_LOAD ; *inp++
  481. xor $A[1][2],$A[1][2],r0
  482. bdz .Lprocess_block
  483. $DWORD_LE_LOAD ; *inp++
  484. xor $A[1][3],$A[1][3],r0
  485. bdz .Lprocess_block
  486. $DWORD_LE_LOAD ; *inp++
  487. xor $A[1][4],$A[1][4],r0
  488. bdz .Lprocess_block
  489. $DWORD_LE_LOAD ; *inp++
  490. xor $A[2][0],$A[2][0],r0
  491. bdz .Lprocess_block
  492. $DWORD_LE_LOAD ; *inp++
  493. xor $A[2][1],$A[2][1],r0
  494. bdz .Lprocess_block
  495. $DWORD_LE_LOAD ; *inp++
  496. xor $A[2][2],$A[2][2],r0
  497. bdz .Lprocess_block
  498. $DWORD_LE_LOAD ; *inp++
  499. xor $A[2][3],$A[2][3],r0
  500. bdz .Lprocess_block
  501. $DWORD_LE_LOAD ; *inp++
  502. xor $A[2][4],$A[2][4],r0
  503. bdz .Lprocess_block
  504. $DWORD_LE_LOAD ; *inp++
  505. xor $A[3][0],$A[3][0],r0
  506. bdz .Lprocess_block
  507. $DWORD_LE_LOAD ; *inp++
  508. xor $A[3][1],$A[3][1],r0
  509. bdz .Lprocess_block
  510. $DWORD_LE_LOAD ; *inp++
  511. xor $A[3][2],$A[3][2],r0
  512. bdz .Lprocess_block
  513. $DWORD_LE_LOAD ; *inp++
  514. xor $A[3][3],$A[3][3],r0
  515. bdz .Lprocess_block
  516. $DWORD_LE_LOAD ; *inp++
  517. xor $A[3][4],$A[3][4],r0
  518. bdz .Lprocess_block
  519. $DWORD_LE_LOAD ; *inp++
  520. xor $A[4][0],$A[4][0],r0
  521. bdz .Lprocess_block
  522. $DWORD_LE_LOAD ; *inp++
  523. xor $A[4][1],$A[4][1],r0
  524. bdz .Lprocess_block
  525. $DWORD_LE_LOAD ; *inp++
  526. xor $A[4][2],$A[4][2],r0
  527. bdz .Lprocess_block
  528. $DWORD_LE_LOAD ; *inp++
  529. xor $A[4][3],$A[4][3],r0
  530. bdz .Lprocess_block
  531. $DWORD_LE_LOAD ; *inp++
  532. xor $A[4][4],$A[4][4],r0
  533. .Lprocess_block:
  534. $PUSH r3,`$LOCALS+1*$SIZE_T`($sp) ; save inp
  535. bl KeccakF1600_int
  536. $POP r0,`$LOCALS+4*$SIZE_T`($sp) ; pull iotas[24]
  537. $POP r5,`$LOCALS+3*$SIZE_T`($sp) ; restore bsz
  538. $POP r4,`$LOCALS+2*$SIZE_T`($sp) ; restore len
  539. $POP r3,`$LOCALS+1*$SIZE_T`($sp) ; restore inp
  540. addic r0,r0,`-8*24` ; rewind iotas
  541. $PUSH r0,`$LOCALS+4*$SIZE_T`($sp)
  542. b .Loop_absorb
  543. .align 4
  544. .Labsorbed:
  545. $POP r3,`$LOCALS+0*$SIZE_T`($sp)
  546. std $A[0][0],`8*0`(r3) ; return A[5][5]
  547. std $A[0][1],`8*1`(r3)
  548. std $A[0][2],`8*2`(r3)
  549. std $A[0][3],`8*3`(r3)
  550. std $A[0][4],`8*4`(r3)
  551. std $A[1][0],`8*5`(r3)
  552. std $A[1][1],`8*6`(r3)
  553. std $A[1][2],`8*7`(r3)
  554. std $A[1][3],`8*8`(r3)
  555. std $A[1][4],`8*9`(r3)
  556. std $A[2][0],`8*10`(r3)
  557. std $A[2][1],`8*11`(r3)
  558. std $A[2][2],`8*12`(r3)
  559. std $A[2][3],`8*13`(r3)
  560. std $A[2][4],`8*14`(r3)
  561. std $A[3][0],`8*15`(r3)
  562. std $A[3][1],`8*16`(r3)
  563. std $A[3][2],`8*17`(r3)
  564. std $A[3][3],`8*18`(r3)
  565. std $A[3][4],`8*19`(r3)
  566. std $A[4][0],`8*20`(r3)
  567. std $A[4][1],`8*21`(r3)
  568. std $A[4][2],`8*22`(r3)
  569. std $A[4][3],`8*23`(r3)
  570. std $A[4][4],`8*24`(r3)
  571. mr r3,r4 ; return value
  572. $POP r0,`$FRAME+$LRSAVE`($sp)
  573. $POP r14,`$FRAME-$SIZE_T*18`($sp)
  574. $POP r15,`$FRAME-$SIZE_T*17`($sp)
  575. $POP r16,`$FRAME-$SIZE_T*16`($sp)
  576. $POP r17,`$FRAME-$SIZE_T*15`($sp)
  577. $POP r18,`$FRAME-$SIZE_T*14`($sp)
  578. $POP r19,`$FRAME-$SIZE_T*13`($sp)
  579. $POP r20,`$FRAME-$SIZE_T*12`($sp)
  580. $POP r21,`$FRAME-$SIZE_T*11`($sp)
  581. $POP r22,`$FRAME-$SIZE_T*10`($sp)
  582. $POP r23,`$FRAME-$SIZE_T*9`($sp)
  583. $POP r24,`$FRAME-$SIZE_T*8`($sp)
  584. $POP r25,`$FRAME-$SIZE_T*7`($sp)
  585. $POP r26,`$FRAME-$SIZE_T*6`($sp)
  586. $POP r27,`$FRAME-$SIZE_T*5`($sp)
  587. $POP r28,`$FRAME-$SIZE_T*4`($sp)
  588. $POP r29,`$FRAME-$SIZE_T*3`($sp)
  589. $POP r30,`$FRAME-$SIZE_T*2`($sp)
  590. $POP r31,`$FRAME-$SIZE_T*1`($sp)
  591. mtlr r0
  592. addi $sp,$sp,$FRAME
  593. blr
  594. .long 0
  595. .byte 0,12,4,1,0x80,18,4,0
  596. .long 0
  597. .size SHA3_absorb,.-SHA3_absorb
  598. ___
  599. {
  600. my ($A_flat,$out,$len,$bsz) = map("r$_",(28..31));
  601. $code.=<<___;
  602. .globl SHA3_squeeze
  603. .type SHA3_squeeze,\@function
  604. .align 5
  605. SHA3_squeeze:
  606. $STU $sp,`-10*$SIZE_T`($sp)
  607. mflr r0
  608. $PUSH r28,`6*$SIZE_T`($sp)
  609. $PUSH r29,`7*$SIZE_T`($sp)
  610. $PUSH r30,`8*$SIZE_T`($sp)
  611. $PUSH r31,`9*$SIZE_T`($sp)
  612. $PUSH r0,`10*$SIZE_T+$LRSAVE`($sp)
  613. mr $A_flat,r3
  614. subi r3,r3,8 ; prepare for ldu
  615. subi $out,r4,1 ; prepare for stbu
  616. mr $len,r5
  617. mr $bsz,r6
  618. cmplwi r7,0 ; r7 = 'next' argument
  619. bne .Lnext_block
  620. b .Loop_squeeze
  621. .align 4
  622. .Loop_squeeze:
  623. ldu r0,8(r3)
  624. ${UCMP}i $len,8
  625. blt .Lsqueeze_tail
  626. stb r0,1($out)
  627. srdi r0,r0,8
  628. stb r0,2($out)
  629. srdi r0,r0,8
  630. stb r0,3($out)
  631. srdi r0,r0,8
  632. stb r0,4($out)
  633. srdi r0,r0,8
  634. stb r0,5($out)
  635. srdi r0,r0,8
  636. stb r0,6($out)
  637. srdi r0,r0,8
  638. stb r0,7($out)
  639. srdi r0,r0,8
  640. stbu r0,8($out)
  641. subic. $len,$len,8
  642. beq .Lsqueeze_done
  643. subic. r6,r6,8
  644. bgt .Loop_squeeze
  645. .Lnext_block:
  646. mr r3,$A_flat
  647. bl KeccakF1600
  648. subi r3,$A_flat,8 ; prepare for ldu
  649. mr r6,$bsz
  650. b .Loop_squeeze
  651. .align 4
  652. .Lsqueeze_tail:
  653. mtctr $len
  654. .Loop_tail:
  655. stbu r0,1($out)
  656. srdi r0,r0,8
  657. bdnz .Loop_tail
  658. .Lsqueeze_done:
  659. $POP r0,`10*$SIZE_T+$LRSAVE`($sp)
  660. $POP r28,`6*$SIZE_T`($sp)
  661. $POP r29,`7*$SIZE_T`($sp)
  662. $POP r30,`8*$SIZE_T`($sp)
  663. $POP r31,`9*$SIZE_T`($sp)
  664. mtlr r0
  665. addi $sp,$sp,`10*$SIZE_T`
  666. blr
  667. .long 0
  668. .byte 0,12,4,1,0x80,4,4,0
  669. .long 0
  670. .size SHA3_squeeze,.-SHA3_squeeze
  671. ___
  672. }
  673. # Ugly hack here, because PPC assembler syntax seem to vary too
  674. # much from platforms to platform...
  675. $code.=<<___;
  676. .align 6
  677. PICmeup:
  678. mflr r0
  679. bcl 20,31,\$+4
  680. mflr r12 ; vvvvvv "distance" between . and 1st data entry
  681. addi r12,r12,`64-8`
  682. mtlr r0
  683. blr
  684. .long 0
  685. .byte 0,12,0x14,0,0,0,0,0
  686. .space `64-9*4`
  687. .type iotas,\@object
  688. iotas:
  689. .quad 0x0000000000000001
  690. .quad 0x0000000000008082
  691. .quad 0x800000000000808a
  692. .quad 0x8000000080008000
  693. .quad 0x000000000000808b
  694. .quad 0x0000000080000001
  695. .quad 0x8000000080008081
  696. .quad 0x8000000000008009
  697. .quad 0x000000000000008a
  698. .quad 0x0000000000000088
  699. .quad 0x0000000080008009
  700. .quad 0x000000008000000a
  701. .quad 0x000000008000808b
  702. .quad 0x800000000000008b
  703. .quad 0x8000000000008089
  704. .quad 0x8000000000008003
  705. .quad 0x8000000000008002
  706. .quad 0x8000000000000080
  707. .quad 0x000000000000800a
  708. .quad 0x800000008000000a
  709. .quad 0x8000000080008081
  710. .quad 0x8000000000008080
  711. .quad 0x0000000080000001
  712. .quad 0x8000000080008008
  713. .size iotas,.-iotas
  714. .asciz "Keccak-1600 absorb and squeeze for PPC64, CRYPTOGAMS by <appro\@openssl.org>"
  715. ___
  716. $code =~ s/\`([^\`]*)\`/eval $1/gem;
  717. print $code;
  718. close STDOUT or die "error closing STDOUT: $!";