keccak1600-ppc64.pl 19 KB

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