pkgconfig: Fix libgcrypt.pc.
[libgcrypt.git] / cipher / blake2b-amd64-avx2.S
1 /* blake2b-amd64-avx2.S  -  AVX2 implementation of BLAKE2b
2  *
3  * Copyright (C) 2018 Jussi Kivilinna <jussi.kivilinna@iki.fi>
4  *
5  * This file is part of Libgcrypt.
6  *
7  * Libgcrypt is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * Libgcrypt is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /* The code is based on public-domain/CC0 BLAKE2 reference implementation
22  * by Samual Neves, at https://github.com/BLAKE2/BLAKE2/tree/master/sse
23  * Copyright 2012, Samuel Neves <sneves@dei.uc.pt>
24  */
25
26 #ifdef __x86_64
27 #include <config.h>
28 #if defined(HAVE_GCC_INLINE_ASM_AVX2) && \
29    (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
30     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
31
32 #include "asm-common-amd64.h"
33
34 .text
35
36 /* register macros */
37 #define RSTATE  %rdi
38 #define RINBLKS %rsi
39 #define RNBLKS  %rdx
40 #define RIV     %rcx
41
42 /* state structure */
43 #define STATE_H 0
44 #define STATE_T (STATE_H + 8 * 8)
45 #define STATE_F (STATE_T + 2 * 8)
46
47 /* vector registers */
48 #define ROW1  %ymm0
49 #define ROW2  %ymm1
50 #define ROW3  %ymm2
51 #define ROW4  %ymm3
52 #define TMP1  %ymm4
53 #define TMP1x %xmm4
54 #define R16   %ymm5
55 #define R24   %ymm6
56
57 #define MA1   %ymm8
58 #define MA2   %ymm9
59 #define MA3   %ymm10
60 #define MA4   %ymm11
61 #define MA1x  %xmm8
62 #define MA2x  %xmm9
63 #define MA3x  %xmm10
64 #define MA4x  %xmm11
65
66 #define MB1   %ymm12
67 #define MB2   %ymm13
68 #define MB3   %ymm14
69 #define MB4   %ymm15
70 #define MB1x  %xmm12
71 #define MB2x  %xmm13
72 #define MB3x  %xmm14
73 #define MB4x  %xmm15
74
75 /**********************************************************************
76   blake2b/AVX2
77  **********************************************************************/
78
79 #define GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
80                    s0, s1, s2, s3, s4, s5, s6, s7, s8, \
81                    s9, s10, s11, s12, s13, s14, s15) \
82         vmovq (s0)*8(RINBLKS), m1x; \
83         vmovq (s4)*8(RINBLKS), TMP1x; \
84         vpinsrq $1, (s2)*8(RINBLKS), m1x, m1x; \
85         vpinsrq $1, (s6)*8(RINBLKS), TMP1x, TMP1x; \
86         vinserti128 $1, TMP1x, m1, m1; \
87           vmovq (s1)*8(RINBLKS), m2x; \
88           vmovq (s5)*8(RINBLKS), TMP1x; \
89           vpinsrq $1, (s3)*8(RINBLKS), m2x, m2x; \
90           vpinsrq $1, (s7)*8(RINBLKS), TMP1x, TMP1x; \
91           vinserti128 $1, TMP1x, m2, m2; \
92             vmovq (s8)*8(RINBLKS), m3x; \
93             vmovq (s12)*8(RINBLKS), TMP1x; \
94             vpinsrq $1, (s10)*8(RINBLKS), m3x, m3x; \
95             vpinsrq $1, (s14)*8(RINBLKS), TMP1x, TMP1x; \
96             vinserti128 $1, TMP1x, m3, m3; \
97               vmovq (s9)*8(RINBLKS), m4x; \
98               vmovq (s13)*8(RINBLKS), TMP1x; \
99               vpinsrq $1, (s11)*8(RINBLKS), m4x, m4x; \
100               vpinsrq $1, (s15)*8(RINBLKS), TMP1x, TMP1x; \
101               vinserti128 $1, TMP1x, m4, m4;
102
103 #define LOAD_MSG_0(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
104         GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
105                     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15)
106 #define LOAD_MSG_1(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
107         GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
108                    14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3)
109 #define LOAD_MSG_2(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
110         GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
111                    11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4)
112 #define LOAD_MSG_3(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
113         GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
114                     7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8)
115 #define LOAD_MSG_4(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
116         GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
117                     9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13)
118 #define LOAD_MSG_5(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
119         GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
120                     2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9)
121 #define LOAD_MSG_6(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
122         GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
123                    12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11)
124 #define LOAD_MSG_7(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
125         GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
126                    13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10)
127 #define LOAD_MSG_8(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
128         GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
129                     6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5)
130 #define LOAD_MSG_9(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
131         GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
132                    10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 , 0)
133 #define LOAD_MSG_10(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
134         LOAD_MSG_0(m1, m2, m3, m4, m1x, m2x, m3x, m4x)
135 #define LOAD_MSG_11(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
136         LOAD_MSG_1(m1, m2, m3, m4, m1x, m2x, m3x, m4x)
137
138 #define LOAD_MSG(r, m1, m2, m3, m4) \
139         LOAD_MSG_##r(m1, m2, m3, m4, m1##x, m2##x, m3##x, m4##x)
140
141 #define ROR_32(in, out) vpshufd $0xb1, in, out;
142
143 #define ROR_24(in, out) vpshufb R24, in, out;
144
145 #define ROR_16(in, out) vpshufb R16, in, out;
146
147 #define ROR_63(in, out) \
148         vpsrlq $63, in, TMP1; \
149         vpaddq in, in, out; \
150         vpxor  TMP1, out, out;
151
152 #define G(r1, r2, r3, r4, m, ROR_A, ROR_B) \
153         vpaddq m, r1, r1; \
154         vpaddq r2, r1, r1; \
155         vpxor r1, r4, r4; \
156         ROR_A(r4, r4); \
157         vpaddq r4, r3, r3; \
158         vpxor r3, r2, r2; \
159         ROR_B(r2, r2);
160
161 #define G1(r1, r2, r3, r4, m) \
162         G(r1, r2, r3, r4, m, ROR_32, ROR_24);
163
164 #define G2(r1, r2, r3, r4, m) \
165         G(r1, r2, r3, r4, m, ROR_16, ROR_63);
166
167 #define MM_SHUFFLE(z,y,x,w) \
168         (((z) << 6) | ((y) << 4) | ((x) << 2) | (w))
169
170 #define DIAGONALIZE(r1, r2, r3, r4) \
171         vpermq $MM_SHUFFLE(0,3,2,1), r2, r2; \
172         vpermq $MM_SHUFFLE(1,0,3,2), r3, r3; \
173         vpermq $MM_SHUFFLE(2,1,0,3), r4, r4;
174
175 #define UNDIAGONALIZE(r1, r2, r3, r4) \
176         vpermq $MM_SHUFFLE(2,1,0,3), r2, r2; \
177         vpermq $MM_SHUFFLE(1,0,3,2), r3, r3; \
178         vpermq $MM_SHUFFLE(0,3,2,1), r4, r4;
179
180 #define ROUND(r, m1, m2, m3, m4) \
181         G1(ROW1, ROW2, ROW3, ROW4, m1); \
182         G2(ROW1, ROW2, ROW3, ROW4, m2); \
183         DIAGONALIZE(ROW1, ROW2, ROW3, ROW4); \
184         G1(ROW1, ROW2, ROW3, ROW4, m3); \
185         G2(ROW1, ROW2, ROW3, ROW4, m4); \
186         UNDIAGONALIZE(ROW1, ROW2, ROW3, ROW4);
187
188 blake2b_data:
189 .align 32
190 .Liv:
191         .quad 0x6a09e667f3bcc908, 0xbb67ae8584caa73b
192         .quad 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1
193         .quad 0x510e527fade682d1, 0x9b05688c2b3e6c1f
194         .quad 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179
195 .Lshuf_ror16:
196         .byte 2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9
197 .Lshuf_ror24:
198         .byte 3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10
199
200 .align 64
201 .globl _gcry_blake2b_transform_amd64_avx2
202 ELF(.type _gcry_blake2b_transform_amd64_avx2,@function;)
203
204 _gcry_blake2b_transform_amd64_avx2:
205         /* input:
206          *      %rdi: state
207          *      %rsi: blks
208          *      %rdx: num_blks
209          */
210         CFI_STARTPROC();
211
212         vzeroupper;
213
214         addq $128, (STATE_T + 0)(RSTATE);
215         adcq $0, (STATE_T + 8)(RSTATE);
216
217         vbroadcasti128 .Lshuf_ror16 (RIP), R16;
218         vbroadcasti128 .Lshuf_ror24 (RIP), R24;
219
220         vmovdqa .Liv+(0 * 8) (RIP), ROW3;
221         vmovdqa .Liv+(4 * 8) (RIP), ROW4;
222
223         vmovdqu (STATE_H + 0 * 8)(RSTATE), ROW1;
224         vmovdqu (STATE_H + 4 * 8)(RSTATE), ROW2;
225
226         vpxor (STATE_T)(RSTATE), ROW4, ROW4;
227
228         LOAD_MSG(0, MA1, MA2, MA3, MA4);
229         LOAD_MSG(1, MB1, MB2, MB3, MB4);
230
231 .Loop:
232         ROUND(0, MA1, MA2, MA3, MA4);
233                                       LOAD_MSG(2, MA1, MA2, MA3, MA4);
234         ROUND(1, MB1, MB2, MB3, MB4);
235                                       LOAD_MSG(3, MB1, MB2, MB3, MB4);
236         ROUND(2, MA1, MA2, MA3, MA4);
237                                       LOAD_MSG(4, MA1, MA2, MA3, MA4);
238         ROUND(3, MB1, MB2, MB3, MB4);
239                                       LOAD_MSG(5, MB1, MB2, MB3, MB4);
240         ROUND(4, MA1, MA2, MA3, MA4);
241                                       LOAD_MSG(6, MA1, MA2, MA3, MA4);
242         ROUND(5, MB1, MB2, MB3, MB4);
243                                       LOAD_MSG(7, MB1, MB2, MB3, MB4);
244         ROUND(6, MA1, MA2, MA3, MA4);
245                                       LOAD_MSG(8, MA1, MA2, MA3, MA4);
246         ROUND(7, MB1, MB2, MB3, MB4);
247                                       LOAD_MSG(9, MB1, MB2, MB3, MB4);
248         ROUND(8, MA1, MA2, MA3, MA4);
249                                       LOAD_MSG(10, MA1, MA2, MA3, MA4);
250         ROUND(9, MB1, MB2, MB3, MB4);
251                                       LOAD_MSG(11, MB1, MB2, MB3, MB4);
252         sub $1, RNBLKS;
253         jz .Loop_end;
254
255         lea 128(RINBLKS), RINBLKS;
256         addq $128, (STATE_T + 0)(RSTATE);
257         adcq $0, (STATE_T + 8)(RSTATE);
258
259         ROUND(10, MA1, MA2, MA3, MA4);
260                                       LOAD_MSG(0, MA1, MA2, MA3, MA4);
261         ROUND(11, MB1, MB2, MB3, MB4);
262                                       LOAD_MSG(1, MB1, MB2, MB3, MB4);
263
264         vpxor ROW3, ROW1, ROW1;
265         vpxor ROW4, ROW2, ROW2;
266
267         vmovdqa .Liv+(0 * 8) (RIP), ROW3;
268         vmovdqa .Liv+(4 * 8) (RIP), ROW4;
269
270         vpxor (STATE_H + 0 * 8)(RSTATE), ROW1, ROW1;
271         vpxor (STATE_H + 4 * 8)(RSTATE), ROW2, ROW2;
272
273         vmovdqu ROW1, (STATE_H + 0 * 8)(RSTATE);
274         vmovdqu ROW2, (STATE_H + 4 * 8)(RSTATE);
275
276         vpxor (STATE_T)(RSTATE), ROW4, ROW4;
277
278         jmp .Loop;
279
280 .Loop_end:
281         ROUND(10, MA1, MA2, MA3, MA4);
282         ROUND(11, MB1, MB2, MB3, MB4);
283
284         vpxor ROW3, ROW1, ROW1;
285         vpxor ROW4, ROW2, ROW2;
286         vpxor (STATE_H + 0 * 8)(RSTATE), ROW1, ROW1;
287         vpxor (STATE_H + 4 * 8)(RSTATE), ROW2, ROW2;
288
289         vmovdqu ROW1, (STATE_H + 0 * 8)(RSTATE);
290         vmovdqu ROW2, (STATE_H + 4 * 8)(RSTATE);
291
292         xor %eax, %eax;
293         vzeroall;
294         ret;
295         CFI_ENDPROC();
296 ELF(.size _gcry_blake2b_transform_amd64_avx2,
297     .-_gcry_blake2b_transform_amd64_avx2;)
298
299 #endif /*defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS)*/
300 #endif /*__x86_64*/