1e1051a39Sopenharmony_ci#!/usr/bin/env perl
2e1051a39Sopenharmony_ci# Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci#
4e1051a39Sopenharmony_ci# Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci# this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci# in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci# https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci#
9e1051a39Sopenharmony_ci# ====================================================================
10e1051a39Sopenharmony_ci# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
11e1051a39Sopenharmony_ci# project. The module is, however, dual licensed under OpenSSL and
12e1051a39Sopenharmony_ci# CRYPTOGAMS licenses depending on where you obtain it. For further
13e1051a39Sopenharmony_ci# details see http://www.openssl.org/~appro/cryptogams/.
14e1051a39Sopenharmony_ci# ====================================================================
15e1051a39Sopenharmony_ci#
16e1051a39Sopenharmony_ci# Keccak-1600 for AVX512VL.
17e1051a39Sopenharmony_ci#
18e1051a39Sopenharmony_ci# December 2017.
19e1051a39Sopenharmony_ci#
20e1051a39Sopenharmony_ci# This is an adaptation of AVX2 module that reuses register data
21e1051a39Sopenharmony_ci# layout, but utilizes new 256-bit AVX512VL instructions. See AVX2
22e1051a39Sopenharmony_ci# module for further information on layout.
23e1051a39Sopenharmony_ci#
24e1051a39Sopenharmony_ci########################################################################
25e1051a39Sopenharmony_ci# Numbers are cycles per processed byte out of large message.
26e1051a39Sopenharmony_ci#
27e1051a39Sopenharmony_ci#			r=1088(*)
28e1051a39Sopenharmony_ci#
29e1051a39Sopenharmony_ci# Skylake-X		6.4/+47%
30e1051a39Sopenharmony_ci#
31e1051a39Sopenharmony_ci# (*)	Corresponds to SHA3-256. Percentage after slash is improvement
32e1051a39Sopenharmony_ci#	coefficient in comparison to scalar keccak1600-x86_64.pl.
33e1051a39Sopenharmony_ci
34e1051a39Sopenharmony_ci# Digits in variables' names denote right-most coordinates:
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_cimy ($A00,	# [0][0] [0][0] [0][0] [0][0]		# %ymm0
37e1051a39Sopenharmony_ci    $A01,	# [0][4] [0][3] [0][2] [0][1]		# %ymm1
38e1051a39Sopenharmony_ci    $A20,	# [3][0] [1][0] [4][0] [2][0]		# %ymm2
39e1051a39Sopenharmony_ci    $A31,	# [2][4] [4][3] [1][2] [3][1]		# %ymm3
40e1051a39Sopenharmony_ci    $A21,	# [3][4] [1][3] [4][2] [2][1]		# %ymm4
41e1051a39Sopenharmony_ci    $A41,	# [1][4] [2][3] [3][2] [4][1]		# %ymm5
42e1051a39Sopenharmony_ci    $A11) =	# [4][4] [3][3] [2][2] [1][1]		# %ymm6
43e1051a39Sopenharmony_ci    map("%ymm$_",(0..6));
44e1051a39Sopenharmony_ci
45e1051a39Sopenharmony_ci# We also need to map the magic order into offsets within structure:
46e1051a39Sopenharmony_ci
47e1051a39Sopenharmony_cimy @A_jagged = ([0,0], [1,0], [1,1], [1,2], [1,3],	# [0][0..4]
48e1051a39Sopenharmony_ci		[2,2], [6,0], [3,1], [4,2], [5,3],	# [1][0..4]
49e1051a39Sopenharmony_ci		[2,0], [4,0], [6,1], [5,2], [3,3],	# [2][0..4]
50e1051a39Sopenharmony_ci		[2,3], [3,0], [5,1], [6,2], [4,3],	# [3][0..4]
51e1051a39Sopenharmony_ci		[2,1], [5,0], [4,1], [3,2], [6,3]);	# [4][0..4]
52e1051a39Sopenharmony_ci   @A_jagged = map(8*($$_[0]*4+$$_[1]), @A_jagged);	# ... and now linear
53e1051a39Sopenharmony_ci
54e1051a39Sopenharmony_cimy @T = map("%ymm$_",(7..15));
55e1051a39Sopenharmony_cimy ($C14,$C00,$D00,$D14) = @T[5..8];
56e1051a39Sopenharmony_cimy ($R20,$R01,$R31,$R21,$R41,$R11) = map("%ymm$_",(16..21));
57e1051a39Sopenharmony_ci
58e1051a39Sopenharmony_ci$code.=<<___;
59e1051a39Sopenharmony_ci.text
60e1051a39Sopenharmony_ci
61e1051a39Sopenharmony_ci.type	__KeccakF1600,\@function
62e1051a39Sopenharmony_ci.align	32
63e1051a39Sopenharmony_ci__KeccakF1600:
64e1051a39Sopenharmony_ci	lea		iotas(%rip),%r10
65e1051a39Sopenharmony_ci	mov		\$24,%eax
66e1051a39Sopenharmony_ci	jmp		.Loop_avx512vl
67e1051a39Sopenharmony_ci
68e1051a39Sopenharmony_ci.align	32
69e1051a39Sopenharmony_ci.Loop_avx512vl:
70e1051a39Sopenharmony_ci	######################################### Theta
71e1051a39Sopenharmony_ci	vpshufd		\$0b01001110,$A20,$C00
72e1051a39Sopenharmony_ci	vpxor		$A31,$A41,$C14
73e1051a39Sopenharmony_ci	vpxor		$A11,$A21,@T[2]
74e1051a39Sopenharmony_ci	vpternlogq	\$0x96,$A01,$T[2],$C14	# C[1..4]
75e1051a39Sopenharmony_ci
76e1051a39Sopenharmony_ci	vpxor		$A20,$C00,$C00
77e1051a39Sopenharmony_ci	vpermq		\$0b01001110,$C00,@T[0]
78e1051a39Sopenharmony_ci
79e1051a39Sopenharmony_ci	vpermq		\$0b10010011,$C14,@T[4]
80e1051a39Sopenharmony_ci	vprolq		\$1,$C14,@T[1]		# ROL64(C[1..4],1)
81e1051a39Sopenharmony_ci
82e1051a39Sopenharmony_ci	vpermq		\$0b00111001,@T[1],$D14
83e1051a39Sopenharmony_ci	vpxor		@T[4],@T[1],$D00
84e1051a39Sopenharmony_ci	vpermq		\$0b00000000,$D00,$D00	# D[0..0] = ROL64(C[1],1) ^ C[4]
85e1051a39Sopenharmony_ci
86e1051a39Sopenharmony_ci	vpternlogq	\$0x96,@T[0],$A00,$C00	# C[0..0]
87e1051a39Sopenharmony_ci	vprolq		\$1,$C00,@T[1]		# ROL64(C[0..0],1)
88e1051a39Sopenharmony_ci
89e1051a39Sopenharmony_ci	vpxor		$D00,$A00,$A00		# ^= D[0..0]
90e1051a39Sopenharmony_ci
91e1051a39Sopenharmony_ci	vpblendd	\$0b11000000,@T[1],$D14,$D14
92e1051a39Sopenharmony_ci	vpblendd	\$0b00000011,$C00,@T[4],@T[0]
93e1051a39Sopenharmony_ci
94e1051a39Sopenharmony_ci	######################################### Rho + Pi + pre-Chi shuffle
95e1051a39Sopenharmony_ci	 vpxor		$D00,$A20,$A20		# ^= D[0..0] from Theta
96e1051a39Sopenharmony_ci	vprolvq		$R20,$A20,$A20
97e1051a39Sopenharmony_ci
98e1051a39Sopenharmony_ci	 vpternlogq	\$0x96,@T[0],$D14,$A31	# ^= D[1..4] from Theta
99e1051a39Sopenharmony_ci	vprolvq		$R31,$A31,$A31
100e1051a39Sopenharmony_ci
101e1051a39Sopenharmony_ci	 vpternlogq	\$0x96,@T[0],$D14,$A21	# ^= D[1..4] from Theta
102e1051a39Sopenharmony_ci	vprolvq		$R21,$A21,$A21
103e1051a39Sopenharmony_ci
104e1051a39Sopenharmony_ci	 vpternlogq	\$0x96,@T[0],$D14,$A41	# ^= D[1..4] from Theta
105e1051a39Sopenharmony_ci	vprolvq		$R41,$A41,$A41
106e1051a39Sopenharmony_ci
107e1051a39Sopenharmony_ci	 vpermq		\$0b10001101,$A20,@T[3]	# $A20 -> future $A31
108e1051a39Sopenharmony_ci	 vpermq		\$0b10001101,$A31,@T[4]	# $A31 -> future $A21
109e1051a39Sopenharmony_ci	 vpternlogq	\$0x96,@T[0],$D14,$A11	# ^= D[1..4] from Theta
110e1051a39Sopenharmony_ci	vprolvq		$R11,$A11,@T[1]		# $A11 -> future $A01
111e1051a39Sopenharmony_ci
112e1051a39Sopenharmony_ci	 vpermq		\$0b00011011,$A21,@T[5]	# $A21 -> future $A41
113e1051a39Sopenharmony_ci	 vpermq		\$0b01110010,$A41,@T[6]	# $A41 -> future $A11
114e1051a39Sopenharmony_ci	 vpternlogq	\$0x96,@T[0],$D14,$A01	# ^= D[1..4] from Theta
115e1051a39Sopenharmony_ci	vprolvq		$R01,$A01,@T[2]		# $A01 -> future $A20
116e1051a39Sopenharmony_ci
117e1051a39Sopenharmony_ci	######################################### Chi
118e1051a39Sopenharmony_ci	vpblendd	\$0b00001100,@T[6],@T[2],$A31	#               [4][4] [2][0]
119e1051a39Sopenharmony_ci	vpblendd	\$0b00001100,@T[2],@T[4],@T[8]	#               [4][0] [2][1]
120e1051a39Sopenharmony_ci	 vpblendd	\$0b00001100,@T[4],@T[3],$A41	#               [4][2] [2][4]
121e1051a39Sopenharmony_ci	 vpblendd	\$0b00001100,@T[3],@T[2],@T[7]	#               [4][3] [2][0]
122e1051a39Sopenharmony_ci	vpblendd	\$0b00110000,@T[4],$A31,$A31	#        [1][3] [4][4] [2][0]
123e1051a39Sopenharmony_ci	vpblendd	\$0b00110000,@T[5],@T[8],@T[8]	#        [1][4] [4][0] [2][1]
124e1051a39Sopenharmony_ci	 vpblendd	\$0b00110000,@T[2],$A41,$A41	#        [1][0] [4][2] [2][4]
125e1051a39Sopenharmony_ci	 vpblendd	\$0b00110000,@T[6],@T[7],@T[7]	#        [1][1] [4][3] [2][0]
126e1051a39Sopenharmony_ci	vpblendd	\$0b11000000,@T[5],$A31,$A31	# [3][2] [1][3] [4][4] [2][0]
127e1051a39Sopenharmony_ci	vpblendd	\$0b11000000,@T[6],@T[8],@T[8]	# [3][3] [1][4] [4][0] [2][1]
128e1051a39Sopenharmony_ci	 vpblendd	\$0b11000000,@T[6],$A41,$A41	# [3][3] [1][0] [4][2] [2][4]
129e1051a39Sopenharmony_ci	 vpblendd	\$0b11000000,@T[4],@T[7],@T[7]	# [3][4] [1][1] [4][3] [2][0]
130e1051a39Sopenharmony_ci	vpternlogq	\$0xC6,@T[8],@T[3],$A31		# [3][1] [1][2] [4][3] [2][4]
131e1051a39Sopenharmony_ci	 vpternlogq	\$0xC6,@T[7],@T[5],$A41		# [3][2] [1][4] [4][1] [2][3]
132e1051a39Sopenharmony_ci
133e1051a39Sopenharmony_ci	vpsrldq		\$8,@T[1],@T[0]
134e1051a39Sopenharmony_ci	vpandn		@T[0],@T[1],@T[0]	# tgting  [0][0] [0][0] [0][0] [0][0]
135e1051a39Sopenharmony_ci
136e1051a39Sopenharmony_ci	vpblendd	\$0b00001100,@T[2],@T[5],$A11	#               [4][0] [2][3]
137e1051a39Sopenharmony_ci	vpblendd	\$0b00001100,@T[5],@T[3],@T[8]	#               [4][1] [2][4]
138e1051a39Sopenharmony_ci	vpblendd	\$0b00110000,@T[3],$A11,$A11	#        [1][2] [4][0] [2][3]
139e1051a39Sopenharmony_ci	vpblendd	\$0b00110000,@T[4],@T[8],@T[8]	#        [1][3] [4][1] [2][4]
140e1051a39Sopenharmony_ci	vpblendd	\$0b11000000,@T[4],$A11,$A11	# [3][4] [1][2] [4][0] [2][3]
141e1051a39Sopenharmony_ci	vpblendd	\$0b11000000,@T[2],@T[8],@T[8]	# [3][0] [1][3] [4][1] [2][4]
142e1051a39Sopenharmony_ci	vpternlogq	\$0xC6,@T[8],@T[6],$A11		# [3][3] [1][1] [4][4] [2][2]
143e1051a39Sopenharmony_ci
144e1051a39Sopenharmony_ci	  vpermq	\$0b00011110,@T[1],$A21		# [0][1] [0][2] [0][4] [0][3]
145e1051a39Sopenharmony_ci	  vpblendd	\$0b00110000,$A00,$A21,@T[8]	# [0][1] [0][0] [0][4] [0][3]
146e1051a39Sopenharmony_ci	  vpermq	\$0b00111001,@T[1],$A01		# [0][1] [0][4] [0][3] [0][2]
147e1051a39Sopenharmony_ci	  vpblendd	\$0b11000000,$A00,$A01,$A01	# [0][0] [0][4] [0][3] [0][2]
148e1051a39Sopenharmony_ci
149e1051a39Sopenharmony_ci	vpblendd	\$0b00001100,@T[5],@T[4],$A20	#               [4][1] [2][1]
150e1051a39Sopenharmony_ci	vpblendd	\$0b00001100,@T[4],@T[6],@T[7]	#               [4][2] [2][2]
151e1051a39Sopenharmony_ci	vpblendd	\$0b00110000,@T[6],$A20,$A20	#        [1][1] [4][1] [2][1]
152e1051a39Sopenharmony_ci	vpblendd	\$0b00110000,@T[3],@T[7],@T[7]	#        [1][2] [4][2] [2][2]
153e1051a39Sopenharmony_ci	vpblendd	\$0b11000000,@T[3],$A20,$A20	# [3][1] [1][1] [4][1] [2][1]
154e1051a39Sopenharmony_ci	vpblendd	\$0b11000000,@T[5],@T[7],@T[7]	# [3][2] [1][2] [4][2] [2][2]
155e1051a39Sopenharmony_ci	vpternlogq	\$0xC6,@T[7],@T[2],$A20		# [3][0] [1][0] [4][0] [2][0]
156e1051a39Sopenharmony_ci
157e1051a39Sopenharmony_ci	 vpermq		\$0b00000000,@T[0],@T[0]	# [0][0] [0][0] [0][0] [0][0]
158e1051a39Sopenharmony_ci	 vpermq		\$0b00011011,$A31,$A31		# post-Chi shuffle
159e1051a39Sopenharmony_ci	 vpermq		\$0b10001101,$A41,$A41
160e1051a39Sopenharmony_ci	 vpermq		\$0b01110010,$A11,$A11
161e1051a39Sopenharmony_ci
162e1051a39Sopenharmony_ci	vpblendd	\$0b00001100,@T[3],@T[6],$A21	#               [4][3] [2][2]
163e1051a39Sopenharmony_ci	vpblendd	\$0b00001100,@T[6],@T[5],@T[7]	#               [4][4] [2][3]
164e1051a39Sopenharmony_ci	vpblendd	\$0b00110000,@T[5],$A21,$A21	#        [1][4] [4][3] [2][2]
165e1051a39Sopenharmony_ci	vpblendd	\$0b00110000,@T[2],@T[7],@T[7]	#        [1][0] [4][4] [2][3]
166e1051a39Sopenharmony_ci	vpblendd	\$0b11000000,@T[2],$A21,$A21	# [3][0] [1][4] [4][3] [2][2]
167e1051a39Sopenharmony_ci	vpblendd	\$0b11000000,@T[3],@T[7],@T[7]	# [3][1] [1][0] [4][4] [2][3]
168e1051a39Sopenharmony_ci
169e1051a39Sopenharmony_ci	vpternlogq	\$0xC6,@T[8],@T[1],$A01		# [0][4] [0][3] [0][2] [0][1]
170e1051a39Sopenharmony_ci	vpternlogq	\$0xC6,@T[7],@T[4],$A21		# [3][4] [1][3] [4][2] [2][1]
171e1051a39Sopenharmony_ci
172e1051a39Sopenharmony_ci	######################################### Iota
173e1051a39Sopenharmony_ci	vpternlogq	\$0x96,(%r10),@T[0],$A00
174e1051a39Sopenharmony_ci	lea		32(%r10),%r10
175e1051a39Sopenharmony_ci
176e1051a39Sopenharmony_ci	dec		%eax
177e1051a39Sopenharmony_ci	jnz		.Loop_avx512vl
178e1051a39Sopenharmony_ci
179e1051a39Sopenharmony_ci	ret
180e1051a39Sopenharmony_ci.size	__KeccakF1600,.-__KeccakF1600
181e1051a39Sopenharmony_ci___
182e1051a39Sopenharmony_cimy ($A_flat,$inp,$len,$bsz) = ("%rdi","%rsi","%rdx","%rcx");
183e1051a39Sopenharmony_cimy  $out = $inp;	# in squeeze
184e1051a39Sopenharmony_ci
185e1051a39Sopenharmony_ci$code.=<<___;
186e1051a39Sopenharmony_ci.globl	SHA3_absorb
187e1051a39Sopenharmony_ci.type	SHA3_absorb,\@function
188e1051a39Sopenharmony_ci.align	32
189e1051a39Sopenharmony_ciSHA3_absorb:
190e1051a39Sopenharmony_ci	mov	%rsp,%r11
191e1051a39Sopenharmony_ci
192e1051a39Sopenharmony_ci	lea	-240(%rsp),%rsp
193e1051a39Sopenharmony_ci	and	\$-32,%rsp
194e1051a39Sopenharmony_ci
195e1051a39Sopenharmony_ci	lea	96($A_flat),$A_flat
196e1051a39Sopenharmony_ci	lea	96($inp),$inp
197e1051a39Sopenharmony_ci	lea	96(%rsp),%r10
198e1051a39Sopenharmony_ci	lea	rhotates_left(%rip),%r8
199e1051a39Sopenharmony_ci
200e1051a39Sopenharmony_ci	vzeroupper
201e1051a39Sopenharmony_ci
202e1051a39Sopenharmony_ci	vpbroadcastq	-96($A_flat),$A00	# load A[5][5]
203e1051a39Sopenharmony_ci	vmovdqu		8+32*0-96($A_flat),$A01
204e1051a39Sopenharmony_ci	vmovdqu		8+32*1-96($A_flat),$A20
205e1051a39Sopenharmony_ci	vmovdqu		8+32*2-96($A_flat),$A31
206e1051a39Sopenharmony_ci	vmovdqu		8+32*3-96($A_flat),$A21
207e1051a39Sopenharmony_ci	vmovdqu		8+32*4-96($A_flat),$A41
208e1051a39Sopenharmony_ci	vmovdqu		8+32*5-96($A_flat),$A11
209e1051a39Sopenharmony_ci
210e1051a39Sopenharmony_ci	vmovdqa64	0*32(%r8),$R20		# load "rhotate" indices
211e1051a39Sopenharmony_ci	vmovdqa64	1*32(%r8),$R01
212e1051a39Sopenharmony_ci	vmovdqa64	2*32(%r8),$R31
213e1051a39Sopenharmony_ci	vmovdqa64	3*32(%r8),$R21
214e1051a39Sopenharmony_ci	vmovdqa64	4*32(%r8),$R41
215e1051a39Sopenharmony_ci	vmovdqa64	5*32(%r8),$R11
216e1051a39Sopenharmony_ci
217e1051a39Sopenharmony_ci	vpxor		@T[0],@T[0],@T[0]
218e1051a39Sopenharmony_ci	vmovdqa		@T[0],32*2-96(%r10)	# zero transfer area on stack
219e1051a39Sopenharmony_ci	vmovdqa		@T[0],32*3-96(%r10)
220e1051a39Sopenharmony_ci	vmovdqa		@T[0],32*4-96(%r10)
221e1051a39Sopenharmony_ci	vmovdqa		@T[0],32*5-96(%r10)
222e1051a39Sopenharmony_ci	vmovdqa		@T[0],32*6-96(%r10)
223e1051a39Sopenharmony_ci
224e1051a39Sopenharmony_ci.Loop_absorb_avx512vl:
225e1051a39Sopenharmony_ci	mov		$bsz,%rax
226e1051a39Sopenharmony_ci	sub		$bsz,$len
227e1051a39Sopenharmony_ci	jc		.Ldone_absorb_avx512vl
228e1051a39Sopenharmony_ci
229e1051a39Sopenharmony_ci	shr		\$3,%eax
230e1051a39Sopenharmony_ci	vpbroadcastq	0-96($inp),@T[0]
231e1051a39Sopenharmony_ci	vmovdqu		8-96($inp),@T[1]
232e1051a39Sopenharmony_ci	sub		\$4,%eax
233e1051a39Sopenharmony_ci___
234e1051a39Sopenharmony_cifor(my $i=5; $i<25; $i++) {
235e1051a39Sopenharmony_ci$code.=<<___
236e1051a39Sopenharmony_ci	dec	%eax
237e1051a39Sopenharmony_ci	jz	.Labsorved_avx512vl
238e1051a39Sopenharmony_ci	mov	8*$i-96($inp),%r8
239e1051a39Sopenharmony_ci	mov	%r8,$A_jagged[$i]-96(%r10)
240e1051a39Sopenharmony_ci___
241e1051a39Sopenharmony_ci}
242e1051a39Sopenharmony_ci$code.=<<___;
243e1051a39Sopenharmony_ci.Labsorved_avx512vl:
244e1051a39Sopenharmony_ci	lea	($inp,$bsz),$inp
245e1051a39Sopenharmony_ci
246e1051a39Sopenharmony_ci	vpxor	@T[0],$A00,$A00
247e1051a39Sopenharmony_ci	vpxor	@T[1],$A01,$A01
248e1051a39Sopenharmony_ci	vpxor	32*2-96(%r10),$A20,$A20
249e1051a39Sopenharmony_ci	vpxor	32*3-96(%r10),$A31,$A31
250e1051a39Sopenharmony_ci	vpxor	32*4-96(%r10),$A21,$A21
251e1051a39Sopenharmony_ci	vpxor	32*5-96(%r10),$A41,$A41
252e1051a39Sopenharmony_ci	vpxor	32*6-96(%r10),$A11,$A11
253e1051a39Sopenharmony_ci
254e1051a39Sopenharmony_ci	call	__KeccakF1600
255e1051a39Sopenharmony_ci
256e1051a39Sopenharmony_ci	lea	96(%rsp),%r10
257e1051a39Sopenharmony_ci	jmp	.Loop_absorb_avx512vl
258e1051a39Sopenharmony_ci
259e1051a39Sopenharmony_ci.Ldone_absorb_avx512vl:
260e1051a39Sopenharmony_ci	vmovq	%xmm0,-96($A_flat)
261e1051a39Sopenharmony_ci	vmovdqu	$A01,8+32*0-96($A_flat)
262e1051a39Sopenharmony_ci	vmovdqu	$A20,8+32*1-96($A_flat)
263e1051a39Sopenharmony_ci	vmovdqu	$A31,8+32*2-96($A_flat)
264e1051a39Sopenharmony_ci	vmovdqu	$A21,8+32*3-96($A_flat)
265e1051a39Sopenharmony_ci	vmovdqu	$A41,8+32*4-96($A_flat)
266e1051a39Sopenharmony_ci	vmovdqu	$A11,8+32*5-96($A_flat)
267e1051a39Sopenharmony_ci
268e1051a39Sopenharmony_ci	vzeroupper
269e1051a39Sopenharmony_ci
270e1051a39Sopenharmony_ci	lea	(%r11),%rsp
271e1051a39Sopenharmony_ci	lea	($len,$bsz),%rax		# return value
272e1051a39Sopenharmony_ci	ret
273e1051a39Sopenharmony_ci.size	SHA3_absorb,.-SHA3_absorb
274e1051a39Sopenharmony_ci
275e1051a39Sopenharmony_ci.globl	SHA3_squeeze
276e1051a39Sopenharmony_ci.type	SHA3_squeeze,\@function
277e1051a39Sopenharmony_ci.align	32
278e1051a39Sopenharmony_ciSHA3_squeeze:
279e1051a39Sopenharmony_ci	mov	%rsp,%r11
280e1051a39Sopenharmony_ci
281e1051a39Sopenharmony_ci	lea	96($A_flat),$A_flat
282e1051a39Sopenharmony_ci	lea	rhotates_left(%rip),%r8
283e1051a39Sopenharmony_ci	shr	\$3,$bsz
284e1051a39Sopenharmony_ci
285e1051a39Sopenharmony_ci	vzeroupper
286e1051a39Sopenharmony_ci
287e1051a39Sopenharmony_ci	vpbroadcastq	-96($A_flat),$A00
288e1051a39Sopenharmony_ci	vpxor		@T[0],@T[0],@T[0]
289e1051a39Sopenharmony_ci	vmovdqu		8+32*0-96($A_flat),$A01
290e1051a39Sopenharmony_ci	vmovdqu		8+32*1-96($A_flat),$A20
291e1051a39Sopenharmony_ci	vmovdqu		8+32*2-96($A_flat),$A31
292e1051a39Sopenharmony_ci	vmovdqu		8+32*3-96($A_flat),$A21
293e1051a39Sopenharmony_ci	vmovdqu		8+32*4-96($A_flat),$A41
294e1051a39Sopenharmony_ci	vmovdqu		8+32*5-96($A_flat),$A11
295e1051a39Sopenharmony_ci
296e1051a39Sopenharmony_ci	vmovdqa64	0*32(%r8),$R20		# load "rhotate" indices
297e1051a39Sopenharmony_ci	vmovdqa64	1*32(%r8),$R01
298e1051a39Sopenharmony_ci	vmovdqa64	2*32(%r8),$R31
299e1051a39Sopenharmony_ci	vmovdqa64	3*32(%r8),$R21
300e1051a39Sopenharmony_ci	vmovdqa64	4*32(%r8),$R41
301e1051a39Sopenharmony_ci	vmovdqa64	5*32(%r8),$R11
302e1051a39Sopenharmony_ci
303e1051a39Sopenharmony_ci	mov	$bsz,%rax
304e1051a39Sopenharmony_ci
305e1051a39Sopenharmony_ci.Loop_squeeze_avx512vl:
306e1051a39Sopenharmony_ci	mov	@A_jagged[$i]-96($A_flat),%r8
307e1051a39Sopenharmony_ci___
308e1051a39Sopenharmony_cifor (my $i=0; $i<25; $i++) {
309e1051a39Sopenharmony_ci$code.=<<___;
310e1051a39Sopenharmony_ci	sub	\$8,$len
311e1051a39Sopenharmony_ci	jc	.Ltail_squeeze_avx512vl
312e1051a39Sopenharmony_ci	mov	%r8,($out)
313e1051a39Sopenharmony_ci	lea	8($out),$out
314e1051a39Sopenharmony_ci	je	.Ldone_squeeze_avx512vl
315e1051a39Sopenharmony_ci	dec	%eax
316e1051a39Sopenharmony_ci	je	.Lextend_output_avx512vl
317e1051a39Sopenharmony_ci	mov	@A_jagged[$i+1]-120($A_flat),%r8
318e1051a39Sopenharmony_ci___
319e1051a39Sopenharmony_ci}
320e1051a39Sopenharmony_ci$code.=<<___;
321e1051a39Sopenharmony_ci.Lextend_output_avx512vl:
322e1051a39Sopenharmony_ci	call	__KeccakF1600
323e1051a39Sopenharmony_ci
324e1051a39Sopenharmony_ci	vmovq	%xmm0,-96($A_flat)
325e1051a39Sopenharmony_ci	vmovdqu	$A01,8+32*0-96($A_flat)
326e1051a39Sopenharmony_ci	vmovdqu	$A20,8+32*1-96($A_flat)
327e1051a39Sopenharmony_ci	vmovdqu	$A31,8+32*2-96($A_flat)
328e1051a39Sopenharmony_ci	vmovdqu	$A21,8+32*3-96($A_flat)
329e1051a39Sopenharmony_ci	vmovdqu	$A41,8+32*4-96($A_flat)
330e1051a39Sopenharmony_ci	vmovdqu	$A11,8+32*5-96($A_flat)
331e1051a39Sopenharmony_ci
332e1051a39Sopenharmony_ci	mov	$bsz,%rax
333e1051a39Sopenharmony_ci	jmp	.Loop_squeeze_avx512vl
334e1051a39Sopenharmony_ci
335e1051a39Sopenharmony_ci
336e1051a39Sopenharmony_ci.Ltail_squeeze_avx512vl:
337e1051a39Sopenharmony_ci	add	\$8,$len
338e1051a39Sopenharmony_ci.Loop_tail_avx512vl:
339e1051a39Sopenharmony_ci	mov	%r8b,($out)
340e1051a39Sopenharmony_ci	lea	1($out),$out
341e1051a39Sopenharmony_ci	shr	\$8,%r8
342e1051a39Sopenharmony_ci	dec	$len
343e1051a39Sopenharmony_ci	jnz	.Loop_tail_avx512vl
344e1051a39Sopenharmony_ci
345e1051a39Sopenharmony_ci.Ldone_squeeze_avx512vl:
346e1051a39Sopenharmony_ci	vzeroupper
347e1051a39Sopenharmony_ci
348e1051a39Sopenharmony_ci	lea	(%r11),%rsp
349e1051a39Sopenharmony_ci	ret
350e1051a39Sopenharmony_ci.size	SHA3_squeeze,.-SHA3_squeeze
351e1051a39Sopenharmony_ci
352e1051a39Sopenharmony_ci.align	64
353e1051a39Sopenharmony_cirhotates_left:
354e1051a39Sopenharmony_ci	.quad	3,	18,	36,	41	# [2][0] [4][0] [1][0] [3][0]
355e1051a39Sopenharmony_ci	.quad	1,	62,	28,	27	# [0][1] [0][2] [0][3] [0][4]
356e1051a39Sopenharmony_ci	.quad	45,	6,	56,	39	# [3][1] [1][2] [4][3] [2][4]
357e1051a39Sopenharmony_ci	.quad	10,	61,	55,	8	# [2][1] [4][2] [1][3] [3][4]
358e1051a39Sopenharmony_ci	.quad	2,	15,	25,	20	# [4][1] [3][2] [2][3] [1][4]
359e1051a39Sopenharmony_ci	.quad	44,	43,	21,	14	# [1][1] [2][2] [3][3] [4][4]
360e1051a39Sopenharmony_ciiotas:
361e1051a39Sopenharmony_ci	.quad	0x0000000000000001, 0x0000000000000001, 0x0000000000000001, 0x0000000000000001
362e1051a39Sopenharmony_ci	.quad	0x0000000000008082, 0x0000000000008082, 0x0000000000008082, 0x0000000000008082
363e1051a39Sopenharmony_ci	.quad	0x800000000000808a, 0x800000000000808a, 0x800000000000808a, 0x800000000000808a
364e1051a39Sopenharmony_ci	.quad	0x8000000080008000, 0x8000000080008000, 0x8000000080008000, 0x8000000080008000
365e1051a39Sopenharmony_ci	.quad	0x000000000000808b, 0x000000000000808b, 0x000000000000808b, 0x000000000000808b
366e1051a39Sopenharmony_ci	.quad	0x0000000080000001, 0x0000000080000001, 0x0000000080000001, 0x0000000080000001
367e1051a39Sopenharmony_ci	.quad	0x8000000080008081, 0x8000000080008081, 0x8000000080008081, 0x8000000080008081
368e1051a39Sopenharmony_ci	.quad	0x8000000000008009, 0x8000000000008009, 0x8000000000008009, 0x8000000000008009
369e1051a39Sopenharmony_ci	.quad	0x000000000000008a, 0x000000000000008a, 0x000000000000008a, 0x000000000000008a
370e1051a39Sopenharmony_ci	.quad	0x0000000000000088, 0x0000000000000088, 0x0000000000000088, 0x0000000000000088
371e1051a39Sopenharmony_ci	.quad	0x0000000080008009, 0x0000000080008009, 0x0000000080008009, 0x0000000080008009
372e1051a39Sopenharmony_ci	.quad	0x000000008000000a, 0x000000008000000a, 0x000000008000000a, 0x000000008000000a
373e1051a39Sopenharmony_ci	.quad	0x000000008000808b, 0x000000008000808b, 0x000000008000808b, 0x000000008000808b
374e1051a39Sopenharmony_ci	.quad	0x800000000000008b, 0x800000000000008b, 0x800000000000008b, 0x800000000000008b
375e1051a39Sopenharmony_ci	.quad	0x8000000000008089, 0x8000000000008089, 0x8000000000008089, 0x8000000000008089
376e1051a39Sopenharmony_ci	.quad	0x8000000000008003, 0x8000000000008003, 0x8000000000008003, 0x8000000000008003
377e1051a39Sopenharmony_ci	.quad	0x8000000000008002, 0x8000000000008002, 0x8000000000008002, 0x8000000000008002
378e1051a39Sopenharmony_ci	.quad	0x8000000000000080, 0x8000000000000080, 0x8000000000000080, 0x8000000000000080
379e1051a39Sopenharmony_ci	.quad	0x000000000000800a, 0x000000000000800a, 0x000000000000800a, 0x000000000000800a
380e1051a39Sopenharmony_ci	.quad	0x800000008000000a, 0x800000008000000a, 0x800000008000000a, 0x800000008000000a
381e1051a39Sopenharmony_ci	.quad	0x8000000080008081, 0x8000000080008081, 0x8000000080008081, 0x8000000080008081
382e1051a39Sopenharmony_ci	.quad	0x8000000000008080, 0x8000000000008080, 0x8000000000008080, 0x8000000000008080
383e1051a39Sopenharmony_ci	.quad	0x0000000080000001, 0x0000000080000001, 0x0000000080000001, 0x0000000080000001
384e1051a39Sopenharmony_ci	.quad	0x8000000080008008, 0x8000000080008008, 0x8000000080008008, 0x8000000080008008
385e1051a39Sopenharmony_ci
386e1051a39Sopenharmony_ci.asciz	"Keccak-1600 absorb and squeeze for AVX512VL, CRYPTOGAMS by <appro\@openssl.org>"
387e1051a39Sopenharmony_ci___
388e1051a39Sopenharmony_ci
389e1051a39Sopenharmony_ci$output=pop and open STDOUT,">$output";
390e1051a39Sopenharmony_ciprint $code;
391e1051a39Sopenharmony_ciclose STDOUT or die "error closing STDOUT: $!";
392