1#!/usr/bin/env perl 2# Copyright 2017-2023 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 AVX2. 17# 18# July 2017. 19# 20# To paraphrase Gilles Van Assche, if you contemplate Fig. 2.3 on page 21# 20 of The Keccak reference [or Fig. 5 of FIPS PUB 202], and load data 22# other than A[0][0] in magic order into 6 [256-bit] registers, *each 23# dedicated to one axis*, Pi permutation is reduced to intra-register 24# shuffles... 25# 26# It makes other steps more intricate, but overall, is it a win? To be 27# more specific index permutations organized by quadruples are: 28# 29# [4][4] [3][3] [2][2] [1][1]<-+ 30# [0][4] [0][3] [0][2] [0][1]<-+ 31# [3][0] [1][0] [4][0] [2][0] | 32# [4][3] [3][1] [2][4] [1][2] | 33# [3][4] [1][3] [4][2] [2][1] | 34# [2][3] [4][1] [1][4] [3][2] | 35# [2][2] [4][4] [1][1] [3][3] -+ 36# 37# This however is highly impractical for Theta and Chi. What would help 38# Theta is if x indices were aligned column-wise, or in other words: 39# 40# [0][4] [0][3] [0][2] [0][1] 41# [3][0] [1][0] [4][0] [2][0] 42#vpermq([4][3] [3][1] [2][4] [1][2], 0b01110010) 43# [2][4] [4][3] [1][2] [3][1] 44#vpermq([4][2] [3][4] [2][1] [1][3], 0b10001101) 45# [3][4] [1][3] [4][2] [2][1] 46#vpermq([2][3] [4][1] [1][4] [3][2], 0b01110010) 47# [1][4] [2][3] [3][2] [4][1] 48#vpermq([1][1] [2][2] [3][3] [4][4], 0b00011011) 49# [4][4] [3][3] [2][2] [1][1] 50# 51# So here we have it, lines not marked with vpermq() represent the magic 52# order in which data is to be loaded and maintained. [And lines marked 53# with vpermq() represent Pi circular permutation in chosen layout. Note 54# that first step is permutation-free.] A[0][0] is loaded to register of 55# its own, to all lanes. [A[0][0] is not part of Pi permutation or Rho.] 56# Digits in variables' names denote right-most coordinates: 57 58my ($A00, # [0][0] [0][0] [0][0] [0][0] # %ymm0 59 $A01, # [0][4] [0][3] [0][2] [0][1] # %ymm1 60 $A20, # [3][0] [1][0] [4][0] [2][0] # %ymm2 61 $A31, # [2][4] [4][3] [1][2] [3][1] # %ymm3 62 $A21, # [3][4] [1][3] [4][2] [2][1] # %ymm4 63 $A41, # [1][4] [2][3] [3][2] [4][1] # %ymm5 64 $A11) = # [4][4] [3][3] [2][2] [1][1] # %ymm6 65 map("%ymm$_",(0..6)); 66 67# We also need to map the magic order into offsets within structure: 68 69my @A_jagged = ([0,0], [1,0], [1,1], [1,2], [1,3], # [0][0..4] 70 [2,2], [6,0], [3,1], [4,2], [5,3], # [1][0..4] 71 [2,0], [4,0], [6,1], [5,2], [3,3], # [2][0..4] 72 [2,3], [3,0], [5,1], [6,2], [4,3], # [3][0..4] 73 [2,1], [5,0], [4,1], [3,2], [6,3]); # [4][0..4] 74 @A_jagged = map(8*($$_[0]*4+$$_[1]), @A_jagged); # ... and now linear 75 76# But on the other hand Chi is much better off if y indices were aligned 77# column-wise, not x. For this reason we have to shuffle data prior 78# Chi and revert it afterwards. Prior shuffle is naturally merged with 79# Pi itself: 80# 81# [0][4] [0][3] [0][2] [0][1] 82# [3][0] [1][0] [4][0] [2][0] 83#vpermq([4][3] [3][1] [2][4] [1][2], 0b01110010) 84#vpermq([2][4] [4][3] [1][2] [3][1], 0b00011011) = 0b10001101 85# [3][1] [1][2] [4][3] [2][4] 86#vpermq([4][2] [3][4] [2][1] [1][3], 0b10001101) 87#vpermq([3][4] [1][3] [4][2] [2][1], 0b11100100) = 0b10001101 88# [3][4] [1][3] [4][2] [2][1] 89#vpermq([2][3] [4][1] [1][4] [3][2], 0b01110010) 90#vpermq([1][4] [2][3] [3][2] [4][1], 0b01110010) = 0b00011011 91# [3][2] [1][4] [4][1] [2][3] 92#vpermq([1][1] [2][2] [3][3] [4][4], 0b00011011) 93#vpermq([4][4] [3][3] [2][2] [1][1], 0b10001101) = 0b01110010 94# [3][3] [1][1] [4][4] [2][2] 95# 96# And reverse post-Chi permutation: 97# 98# [0][4] [0][3] [0][2] [0][1] 99# [3][0] [1][0] [4][0] [2][0] 100#vpermq([3][1] [1][2] [4][3] [2][4], 0b00011011) 101# [2][4] [4][3] [1][2] [3][1] 102#vpermq([3][4] [1][3] [4][2] [2][1], 0b11100100) = nop :-) 103# [3][4] [1][3] [4][2] [2][1] 104#vpermq([3][2] [1][4] [4][1] [2][3], 0b10001101) 105# [1][4] [2][3] [3][2] [4][1] 106#vpermq([3][3] [1][1] [4][4] [2][2], 0b01110010) 107# [4][4] [3][3] [2][2] [1][1] 108# 109######################################################################## 110# Numbers are cycles per processed byte out of large message. 111# 112# r=1088(*) 113# 114# Haswell 8.7/+10% 115# Skylake 7.8/+20% 116# Ryzen 17(**) 117# 118# (*) Corresponds to SHA3-256. Percentage after slash is improvement 119# coefficient in comparison to scalar keccak1600-x86_64.pl. 120# (**) It's expected that Ryzen performs poorly, because instruction 121# issue rate is limited to two AVX2 instructions per cycle and 122# in addition vpblendd is reportedly bound to specific port. 123# Obviously this code path should not be executed on Ryzen. 124 125my @T = map("%ymm$_",(7..15)); 126my ($C14,$C00,$D00,$D14) = @T[5..8]; 127 128$code.=<<___; 129.text 130 131.type __KeccakF1600,\@function 132.align 32 133__KeccakF1600: 134 lea rhotates_left+96(%rip),%r8 135 lea rhotates_right+96(%rip),%r9 136 lea iotas(%rip),%r10 137 mov \$24,%eax 138 jmp .Loop_avx2 139 140.align 32 141.Loop_avx2: 142 ######################################### Theta 143 vpshufd \$0b01001110,$A20,$C00 144 vpxor $A31,$A41,$C14 145 vpxor $A11,$A21,@T[2] 146 vpxor $A01,$C14,$C14 147 vpxor @T[2],$C14,$C14 # C[1..4] 148 149 vpermq \$0b10010011,$C14,@T[4] 150 vpxor $A20,$C00,$C00 151 vpermq \$0b01001110,$C00,@T[0] 152 153 vpsrlq \$63,$C14,@T[1] 154 vpaddq $C14,$C14,@T[2] 155 vpor @T[2],@T[1],@T[1] # ROL64(C[1..4],1) 156 157 vpermq \$0b00111001,@T[1],$D14 158 vpxor @T[4],@T[1],$D00 159 vpermq \$0b00000000,$D00,$D00 # D[0..0] = ROL64(C[1],1) ^ C[4] 160 161 vpxor $A00,$C00,$C00 162 vpxor @T[0],$C00,$C00 # C[0..0] 163 164 vpsrlq \$63,$C00,@T[0] 165 vpaddq $C00,$C00,@T[1] 166 vpor @T[0],@T[1],@T[1] # ROL64(C[0..0],1) 167 168 vpxor $D00,$A20,$A20 # ^= D[0..0] 169 vpxor $D00,$A00,$A00 # ^= D[0..0] 170 171 vpblendd \$0b11000000,@T[1],$D14,$D14 172 vpblendd \$0b00000011,$C00,@T[4],@T[4] 173 vpxor @T[4],$D14,$D14 # D[1..4] = ROL64(C[2..4,0),1) ^ C[0..3] 174 175 ######################################### Rho + Pi + pre-Chi shuffle 176 vpsllvq 0*32-96(%r8),$A20,@T[3] 177 vpsrlvq 0*32-96(%r9),$A20,$A20 178 vpor @T[3],$A20,$A20 179 180 vpxor $D14,$A31,$A31 # ^= D[1..4] from Theta 181 vpsllvq 2*32-96(%r8),$A31,@T[4] 182 vpsrlvq 2*32-96(%r9),$A31,$A31 183 vpor @T[4],$A31,$A31 184 185 vpxor $D14,$A21,$A21 # ^= D[1..4] from Theta 186 vpsllvq 3*32-96(%r8),$A21,@T[5] 187 vpsrlvq 3*32-96(%r9),$A21,$A21 188 vpor @T[5],$A21,$A21 189 190 vpxor $D14,$A41,$A41 # ^= D[1..4] from Theta 191 vpsllvq 4*32-96(%r8),$A41,@T[6] 192 vpsrlvq 4*32-96(%r9),$A41,$A41 193 vpor @T[6],$A41,$A41 194 195 vpxor $D14,$A11,$A11 # ^= D[1..4] from Theta 196 vpermq \$0b10001101,$A20,@T[3] # $A20 -> future $A31 197 vpermq \$0b10001101,$A31,@T[4] # $A31 -> future $A21 198 vpsllvq 5*32-96(%r8),$A11,@T[7] 199 vpsrlvq 5*32-96(%r9),$A11,@T[1] 200 vpor @T[7],@T[1],@T[1] # $A11 -> future $A01 201 202 vpxor $D14,$A01,$A01 # ^= D[1..4] from Theta 203 vpermq \$0b00011011,$A21,@T[5] # $A21 -> future $A41 204 vpermq \$0b01110010,$A41,@T[6] # $A41 -> future $A11 205 vpsllvq 1*32-96(%r8),$A01,@T[8] 206 vpsrlvq 1*32-96(%r9),$A01,@T[2] 207 vpor @T[8],@T[2],@T[2] # $A01 -> future $A20 208 209 ######################################### Chi 210 vpsrldq \$8,@T[1],@T[7] 211 vpandn @T[7],@T[1],@T[0] # tgting [0][0] [0][0] [0][0] [0][0] 212 213 vpblendd \$0b00001100,@T[6],@T[2],$A31 # [4][4] [2][0] 214 vpblendd \$0b00001100,@T[2],@T[4],@T[8] # [4][0] [2][1] 215 vpblendd \$0b00001100,@T[4],@T[3],$A41 # [4][2] [2][4] 216 vpblendd \$0b00001100,@T[3],@T[2],@T[7] # [4][3] [2][0] 217 vpblendd \$0b00110000,@T[4],$A31,$A31 # [1][3] [4][4] [2][0] 218 vpblendd \$0b00110000,@T[5],@T[8],@T[8] # [1][4] [4][0] [2][1] 219 vpblendd \$0b00110000,@T[2],$A41,$A41 # [1][0] [4][2] [2][4] 220 vpblendd \$0b00110000,@T[6],@T[7],@T[7] # [1][1] [4][3] [2][0] 221 vpblendd \$0b11000000,@T[5],$A31,$A31 # [3][2] [1][3] [4][4] [2][0] 222 vpblendd \$0b11000000,@T[6],@T[8],@T[8] # [3][3] [1][4] [4][0] [2][1] 223 vpblendd \$0b11000000,@T[6],$A41,$A41 # [3][3] [1][0] [4][2] [2][4] 224 vpblendd \$0b11000000,@T[4],@T[7],@T[7] # [3][4] [1][1] [4][3] [2][0] 225 vpandn @T[8],$A31,$A31 # tgting [3][1] [1][2] [4][3] [2][4] 226 vpandn @T[7],$A41,$A41 # tgting [3][2] [1][4] [4][1] [2][3] 227 228 vpblendd \$0b00001100,@T[2],@T[5],$A11 # [4][0] [2][3] 229 vpblendd \$0b00001100,@T[5],@T[3],@T[8] # [4][1] [2][4] 230 vpxor @T[3],$A31,$A31 231 vpblendd \$0b00110000,@T[3],$A11,$A11 # [1][2] [4][0] [2][3] 232 vpblendd \$0b00110000,@T[4],@T[8],@T[8] # [1][3] [4][1] [2][4] 233 vpxor @T[5],$A41,$A41 234 vpblendd \$0b11000000,@T[4],$A11,$A11 # [3][4] [1][2] [4][0] [2][3] 235 vpblendd \$0b11000000,@T[2],@T[8],@T[8] # [3][0] [1][3] [4][1] [2][4] 236 vpandn @T[8],$A11,$A11 # tgting [3][3] [1][1] [4][4] [2][2] 237 vpxor @T[6],$A11,$A11 238 239 vpermq \$0b00011110,@T[1],$A21 # [0][1] [0][2] [0][4] [0][3] 240 vpblendd \$0b00110000,$A00,$A21,@T[8] # [0][1] [0][0] [0][4] [0][3] 241 vpermq \$0b00111001,@T[1],$A01 # [0][1] [0][4] [0][3] [0][2] 242 vpblendd \$0b11000000,$A00,$A01,$A01 # [0][0] [0][4] [0][3] [0][2] 243 vpandn @T[8],$A01,$A01 # tgting [0][4] [0][3] [0][2] [0][1] 244 245 vpblendd \$0b00001100,@T[5],@T[4],$A20 # [4][1] [2][1] 246 vpblendd \$0b00001100,@T[4],@T[6],@T[7] # [4][2] [2][2] 247 vpblendd \$0b00110000,@T[6],$A20,$A20 # [1][1] [4][1] [2][1] 248 vpblendd \$0b00110000,@T[3],@T[7],@T[7] # [1][2] [4][2] [2][2] 249 vpblendd \$0b11000000,@T[3],$A20,$A20 # [3][1] [1][1] [4][1] [2][1] 250 vpblendd \$0b11000000,@T[5],@T[7],@T[7] # [3][2] [1][2] [4][2] [2][2] 251 vpandn @T[7],$A20,$A20 # tgting [3][0] [1][0] [4][0] [2][0] 252 vpxor @T[2],$A20,$A20 253 254 vpermq \$0b00000000,@T[0],@T[0] # [0][0] [0][0] [0][0] [0][0] 255 vpermq \$0b00011011,$A31,$A31 # post-Chi shuffle 256 vpermq \$0b10001101,$A41,$A41 257 vpermq \$0b01110010,$A11,$A11 258 259 vpblendd \$0b00001100,@T[3],@T[6],$A21 # [4][3] [2][2] 260 vpblendd \$0b00001100,@T[6],@T[5],@T[7] # [4][4] [2][3] 261 vpblendd \$0b00110000,@T[5],$A21,$A21 # [1][4] [4][3] [2][2] 262 vpblendd \$0b00110000,@T[2],@T[7],@T[7] # [1][0] [4][4] [2][3] 263 vpblendd \$0b11000000,@T[2],$A21,$A21 # [3][0] [1][4] [4][3] [2][2] 264 vpblendd \$0b11000000,@T[3],@T[7],@T[7] # [3][1] [1][0] [4][4] [2][3] 265 vpandn @T[7],$A21,$A21 # tgting [3][4] [1][3] [4][2] [2][1] 266 267 vpxor @T[0],$A00,$A00 268 vpxor @T[1],$A01,$A01 269 vpxor @T[4],$A21,$A21 270 271 ######################################### Iota 272 vpxor (%r10),$A00,$A00 273 lea 32(%r10),%r10 274 275 dec %eax 276 jnz .Loop_avx2 277 278 ret 279.size __KeccakF1600,.-__KeccakF1600 280___ 281my ($A_flat,$inp,$len,$bsz) = ("%rdi","%rsi","%rdx","%rcx"); 282my $out = $inp; # in squeeze 283 284$code.=<<___; 285.globl SHA3_absorb 286.type SHA3_absorb,\@function 287.align 32 288SHA3_absorb: 289 mov %rsp,%r11 290 291 lea -240(%rsp),%rsp 292 and \$-32,%rsp 293 294 lea 96($A_flat),$A_flat 295 lea 96($inp),$inp 296 lea 96(%rsp),%r10 297 298 vzeroupper 299 300 vpbroadcastq -96($A_flat),$A00 # load A[5][5] 301 vmovdqu 8+32*0-96($A_flat),$A01 302 vmovdqu 8+32*1-96($A_flat),$A20 303 vmovdqu 8+32*2-96($A_flat),$A31 304 vmovdqu 8+32*3-96($A_flat),$A21 305 vmovdqu 8+32*4-96($A_flat),$A41 306 vmovdqu 8+32*5-96($A_flat),$A11 307 308 vpxor @T[0],@T[0],@T[0] 309 vmovdqa @T[0],32*2-96(%r10) # zero transfer area on stack 310 vmovdqa @T[0],32*3-96(%r10) 311 vmovdqa @T[0],32*4-96(%r10) 312 vmovdqa @T[0],32*5-96(%r10) 313 vmovdqa @T[0],32*6-96(%r10) 314 315.Loop_absorb_avx2: 316 mov $bsz,%rax 317 sub $bsz,$len 318 jc .Ldone_absorb_avx2 319 320 shr \$3,%eax 321 vpbroadcastq 0-96($inp),@T[0] 322 vmovdqu 8-96($inp),@T[1] 323 sub \$4,%eax 324___ 325for(my $i=5; $i<25; $i++) { 326$code.=<<___ 327 dec %eax 328 jz .Labsorved_avx2 329 mov 8*$i-96($inp),%r8 330 mov %r8,$A_jagged[$i]-96(%r10) 331___ 332} 333$code.=<<___; 334.Labsorved_avx2: 335 lea ($inp,$bsz),$inp 336 337 vpxor @T[0],$A00,$A00 338 vpxor @T[1],$A01,$A01 339 vpxor 32*2-96(%r10),$A20,$A20 340 vpxor 32*3-96(%r10),$A31,$A31 341 vpxor 32*4-96(%r10),$A21,$A21 342 vpxor 32*5-96(%r10),$A41,$A41 343 vpxor 32*6-96(%r10),$A11,$A11 344 345 call __KeccakF1600 346 347 lea 96(%rsp),%r10 348 jmp .Loop_absorb_avx2 349 350.Ldone_absorb_avx2: 351 vmovq %xmm0,-96($A_flat) 352 vmovdqu $A01,8+32*0-96($A_flat) 353 vmovdqu $A20,8+32*1-96($A_flat) 354 vmovdqu $A31,8+32*2-96($A_flat) 355 vmovdqu $A21,8+32*3-96($A_flat) 356 vmovdqu $A41,8+32*4-96($A_flat) 357 vmovdqu $A11,8+32*5-96($A_flat) 358 359 vzeroupper 360 361 lea (%r11),%rsp 362 lea ($len,$bsz),%rax # return value 363 ret 364.size SHA3_absorb,.-SHA3_absorb 365 366.globl SHA3_squeeze 367.type SHA3_squeeze,\@function 368.align 32 369SHA3_squeeze: 370 mov %rsp,%r11 371 372 lea 96($A_flat),$A_flat 373 shr \$3,$bsz 374 375 vzeroupper 376 377 vpbroadcastq -96($A_flat),$A00 378 vpxor @T[0],@T[0],@T[0] 379 vmovdqu 8+32*0-96($A_flat),$A01 380 vmovdqu 8+32*1-96($A_flat),$A20 381 vmovdqu 8+32*2-96($A_flat),$A31 382 vmovdqu 8+32*3-96($A_flat),$A21 383 vmovdqu 8+32*4-96($A_flat),$A41 384 vmovdqu 8+32*5-96($A_flat),$A11 385 386 mov $bsz,%rax 387 388.Loop_squeeze_avx2: 389 mov @A_jagged[$i]-96($A_flat),%r8 390___ 391for (my $i=0; $i<25; $i++) { 392$code.=<<___; 393 sub \$8,$len 394 jc .Ltail_squeeze_avx2 395 mov %r8,($out) 396 lea 8($out),$out 397 je .Ldone_squeeze_avx2 398 dec %eax 399 je .Lextend_output_avx2 400 mov @A_jagged[$i+1]-120($A_flat),%r8 401___ 402} 403$code.=<<___; 404.Lextend_output_avx2: 405 call __KeccakF1600 406 407 vmovq %xmm0,-96($A_flat) 408 vmovdqu $A01,8+32*0-96($A_flat) 409 vmovdqu $A20,8+32*1-96($A_flat) 410 vmovdqu $A31,8+32*2-96($A_flat) 411 vmovdqu $A21,8+32*3-96($A_flat) 412 vmovdqu $A41,8+32*4-96($A_flat) 413 vmovdqu $A11,8+32*5-96($A_flat) 414 415 mov $bsz,%rax 416 jmp .Loop_squeeze_avx2 417 418 419.Ltail_squeeze_avx2: 420 add \$8,$len 421.Loop_tail_avx2: 422 mov %r8b,($out) 423 lea 1($out),$out 424 shr \$8,%r8 425 dec $len 426 jnz .Loop_tail_avx2 427 428.Ldone_squeeze_avx2: 429 vzeroupper 430 431 lea (%r11),%rsp 432 ret 433.size SHA3_squeeze,.-SHA3_squeeze 434 435.section .rodata 436.align 64 437rhotates_left: 438 .quad 3, 18, 36, 41 # [2][0] [4][0] [1][0] [3][0] 439 .quad 1, 62, 28, 27 # [0][1] [0][2] [0][3] [0][4] 440 .quad 45, 6, 56, 39 # [3][1] [1][2] [4][3] [2][4] 441 .quad 10, 61, 55, 8 # [2][1] [4][2] [1][3] [3][4] 442 .quad 2, 15, 25, 20 # [4][1] [3][2] [2][3] [1][4] 443 .quad 44, 43, 21, 14 # [1][1] [2][2] [3][3] [4][4] 444rhotates_right: 445 .quad 64-3, 64-18, 64-36, 64-41 446 .quad 64-1, 64-62, 64-28, 64-27 447 .quad 64-45, 64-6, 64-56, 64-39 448 .quad 64-10, 64-61, 64-55, 64-8 449 .quad 64-2, 64-15, 64-25, 64-20 450 .quad 64-44, 64-43, 64-21, 64-14 451iotas: 452 .quad 0x0000000000000001, 0x0000000000000001, 0x0000000000000001, 0x0000000000000001 453 .quad 0x0000000000008082, 0x0000000000008082, 0x0000000000008082, 0x0000000000008082 454 .quad 0x800000000000808a, 0x800000000000808a, 0x800000000000808a, 0x800000000000808a 455 .quad 0x8000000080008000, 0x8000000080008000, 0x8000000080008000, 0x8000000080008000 456 .quad 0x000000000000808b, 0x000000000000808b, 0x000000000000808b, 0x000000000000808b 457 .quad 0x0000000080000001, 0x0000000080000001, 0x0000000080000001, 0x0000000080000001 458 .quad 0x8000000080008081, 0x8000000080008081, 0x8000000080008081, 0x8000000080008081 459 .quad 0x8000000000008009, 0x8000000000008009, 0x8000000000008009, 0x8000000000008009 460 .quad 0x000000000000008a, 0x000000000000008a, 0x000000000000008a, 0x000000000000008a 461 .quad 0x0000000000000088, 0x0000000000000088, 0x0000000000000088, 0x0000000000000088 462 .quad 0x0000000080008009, 0x0000000080008009, 0x0000000080008009, 0x0000000080008009 463 .quad 0x000000008000000a, 0x000000008000000a, 0x000000008000000a, 0x000000008000000a 464 .quad 0x000000008000808b, 0x000000008000808b, 0x000000008000808b, 0x000000008000808b 465 .quad 0x800000000000008b, 0x800000000000008b, 0x800000000000008b, 0x800000000000008b 466 .quad 0x8000000000008089, 0x8000000000008089, 0x8000000000008089, 0x8000000000008089 467 .quad 0x8000000000008003, 0x8000000000008003, 0x8000000000008003, 0x8000000000008003 468 .quad 0x8000000000008002, 0x8000000000008002, 0x8000000000008002, 0x8000000000008002 469 .quad 0x8000000000000080, 0x8000000000000080, 0x8000000000000080, 0x8000000000000080 470 .quad 0x000000000000800a, 0x000000000000800a, 0x000000000000800a, 0x000000000000800a 471 .quad 0x800000008000000a, 0x800000008000000a, 0x800000008000000a, 0x800000008000000a 472 .quad 0x8000000080008081, 0x8000000080008081, 0x8000000080008081, 0x8000000080008081 473 .quad 0x8000000000008080, 0x8000000000008080, 0x8000000000008080, 0x8000000000008080 474 .quad 0x0000000080000001, 0x0000000080000001, 0x0000000080000001, 0x0000000080000001 475 .quad 0x8000000080008008, 0x8000000080008008, 0x8000000080008008, 0x8000000080008008 476 477.asciz "Keccak-1600 absorb and squeeze for AVX2, CRYPTOGAMS by <appro\@openssl.org>" 478___ 479 480$output=pop and open STDOUT,">$output"; 481print $code; 482close STDOUT or die "error closing STDOUT: $!"; 483