Add clang target pragma for mixed C/assembly x86-64 implementations
[libgcrypt.git] / cipher / cipher-gcm-intel-pclmul.c
1 /* cipher-gcm-intel-pclmul.c  -  Intel PCLMUL accelerated Galois Counter Mode
2  *                               implementation
3  * Copyright (C) 2013-2014 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 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26
27 #include "g10lib.h"
28 #include "cipher.h"
29 #include "bufhelp.h"
30 #include "./cipher-internal.h"
31
32
33 #ifdef GCM_USE_INTEL_PCLMUL
34
35
36 #if _GCRY_GCC_VERSION >= 40400 /* 4.4 */
37 /* Prevent compiler from issuing SSE instructions between asm blocks. */
38 #  pragma GCC target("no-sse")
39 #endif
40 #if __clang__
41 #  pragma clang attribute push (__attribute__((target("no-sse"))), apply_to = function)
42 #endif
43
44
45 /*
46  Intel PCLMUL ghash based on white paper:
47   "Intel® Carry-Less Multiplication Instruction and its Usage for Computing the
48    GCM Mode - Rev 2.01"; Shay Gueron, Michael E. Kounavis.
49  */
50 static inline void gfmul_pclmul(void)
51 {
52   /* Input: XMM0 and XMM1, Output: XMM1. Input XMM0 stays unmodified.
53      Input must be converted to little-endian.
54    */
55   asm volatile (/* gfmul, xmm0 has operator a and xmm1 has operator b. */
56                 "pshufd $78, %%xmm0, %%xmm2\n\t"
57                 "pshufd $78, %%xmm1, %%xmm4\n\t"
58                 "pxor %%xmm0, %%xmm2\n\t" /* xmm2 holds a0+a1 */
59                 "pxor %%xmm1, %%xmm4\n\t" /* xmm4 holds b0+b1 */
60
61                 "movdqa %%xmm0, %%xmm3\n\t"
62                 "pclmulqdq $0, %%xmm1, %%xmm3\n\t"  /* xmm3 holds a0*b0 */
63                 "movdqa %%xmm0, %%xmm6\n\t"
64                 "pclmulqdq $17, %%xmm1, %%xmm6\n\t" /* xmm6 holds a1*b1 */
65                 "movdqa %%xmm3, %%xmm5\n\t"
66                 "pclmulqdq $0, %%xmm2, %%xmm4\n\t"  /* xmm4 holds (a0+a1)*(b0+b1) */
67
68                 "pxor %%xmm6, %%xmm5\n\t" /* xmm5 holds a0*b0+a1*b1 */
69                 "pxor %%xmm5, %%xmm4\n\t" /* xmm4 holds a0*b0+a1*b1+(a0+a1)*(b0+b1) */
70                 "movdqa %%xmm4, %%xmm5\n\t"
71                 "psrldq $8, %%xmm4\n\t"
72                 "pslldq $8, %%xmm5\n\t"
73                 "pxor %%xmm5, %%xmm3\n\t"
74                 "pxor %%xmm4, %%xmm6\n\t" /* <xmm6:xmm3> holds the result of the
75                                              carry-less multiplication of xmm0
76                                              by xmm1 */
77
78                 /* shift the result by one bit position to the left cope for
79                    the fact that bits are reversed */
80                 "movdqa %%xmm3, %%xmm4\n\t"
81                 "movdqa %%xmm6, %%xmm5\n\t"
82                 "pslld $1, %%xmm3\n\t"
83                 "pslld $1, %%xmm6\n\t"
84                 "psrld $31, %%xmm4\n\t"
85                 "psrld $31, %%xmm5\n\t"
86                 "movdqa %%xmm4, %%xmm1\n\t"
87                 "pslldq $4, %%xmm5\n\t"
88                 "pslldq $4, %%xmm4\n\t"
89                 "psrldq $12, %%xmm1\n\t"
90                 "por %%xmm4, %%xmm3\n\t"
91                 "por %%xmm5, %%xmm6\n\t"
92                 "por %%xmm6, %%xmm1\n\t"
93
94                 /* first phase of the reduction */
95                 "movdqa %%xmm3, %%xmm6\n\t"
96                 "movdqa %%xmm3, %%xmm7\n\t"
97                 "pslld $31, %%xmm6\n\t"  /* packed right shifting << 31 */
98                 "movdqa %%xmm3, %%xmm5\n\t"
99                 "pslld $30, %%xmm7\n\t"  /* packed right shifting shift << 30 */
100                 "pslld $25, %%xmm5\n\t"  /* packed right shifting shift << 25 */
101                 "pxor %%xmm7, %%xmm6\n\t" /* xor the shifted versions */
102                 "pxor %%xmm5, %%xmm6\n\t"
103                 "movdqa %%xmm6, %%xmm7\n\t"
104                 "pslldq $12, %%xmm6\n\t"
105                 "psrldq $4, %%xmm7\n\t"
106                 "pxor %%xmm6, %%xmm3\n\t" /* first phase of the reduction
107                                              complete */
108
109                 /* second phase of the reduction */
110                 "movdqa %%xmm3, %%xmm2\n\t"
111                 "movdqa %%xmm3, %%xmm4\n\t"
112                 "psrld $1, %%xmm2\n\t"    /* packed left shifting >> 1 */
113                 "movdqa %%xmm3, %%xmm5\n\t"
114                 "psrld $2, %%xmm4\n\t"    /* packed left shifting >> 2 */
115                 "psrld $7, %%xmm5\n\t"    /* packed left shifting >> 7 */
116                 "pxor %%xmm4, %%xmm2\n\t" /* xor the shifted versions */
117                 "pxor %%xmm5, %%xmm2\n\t"
118                 "pxor %%xmm7, %%xmm2\n\t"
119                 "pxor %%xmm2, %%xmm3\n\t"
120                 "pxor %%xmm3, %%xmm1\n\t" /* the result is in xmm1 */
121                 ::: "cc" );
122 }
123
124
125 #ifdef __x86_64__
126 static inline void gfmul_pclmul_aggr4(void)
127 {
128   /* Input:
129       H¹: XMM0          X_i            : XMM6
130       H²: XMM8          X_(i-1)        : XMM3
131       H³: XMM9          X_(i-2)        : XMM2
132       H⁴: XMM10         X_(i-3)⊕Y_(i-4): XMM1
133      Output:
134       Y_i: XMM1
135      Inputs XMM0 stays unmodified.
136      Input must be converted to little-endian.
137    */
138   asm volatile (/* perform clmul and merge results... */
139                 "pshufd $78, %%xmm10, %%xmm11\n\t"
140                 "pshufd $78, %%xmm1, %%xmm12\n\t"
141                 "pxor %%xmm10, %%xmm11\n\t" /* xmm11 holds 4:a0+a1 */
142                 "pxor %%xmm1, %%xmm12\n\t" /* xmm12 holds 4:b0+b1 */
143
144                 "pshufd $78, %%xmm9, %%xmm13\n\t"
145                 "pshufd $78, %%xmm2, %%xmm14\n\t"
146                 "pxor %%xmm9, %%xmm13\n\t" /* xmm13 holds 3:a0+a1 */
147                 "pxor %%xmm2, %%xmm14\n\t" /* xmm14 holds 3:b0+b1 */
148
149                 "pshufd $78, %%xmm8, %%xmm5\n\t"
150                 "pshufd $78, %%xmm3, %%xmm15\n\t"
151                 "pxor %%xmm8, %%xmm5\n\t" /* xmm1 holds 2:a0+a1 */
152                 "pxor %%xmm3, %%xmm15\n\t" /* xmm2 holds 2:b0+b1 */
153
154                 "movdqa %%xmm10, %%xmm4\n\t"
155                 "movdqa %%xmm9, %%xmm7\n\t"
156                 "pclmulqdq $0, %%xmm1, %%xmm4\n\t"   /* xmm4 holds 4:a0*b0 */
157                 "pclmulqdq $0, %%xmm2, %%xmm7\n\t"   /* xmm7 holds 3:a0*b0 */
158                 "pclmulqdq $17, %%xmm10, %%xmm1\n\t" /* xmm1 holds 4:a1*b1 */
159                 "pclmulqdq $17, %%xmm9, %%xmm2\n\t"  /* xmm9 holds 3:a1*b1 */
160                 "pclmulqdq $0, %%xmm11, %%xmm12\n\t" /* xmm12 holds 4:(a0+a1)*(b0+b1) */
161                 "pclmulqdq $0, %%xmm13, %%xmm14\n\t" /* xmm14 holds 3:(a0+a1)*(b0+b1) */
162
163                 "pshufd $78, %%xmm0, %%xmm10\n\t"
164                 "pshufd $78, %%xmm6, %%xmm11\n\t"
165                 "pxor %%xmm0, %%xmm10\n\t" /* xmm10 holds 1:a0+a1 */
166                 "pxor %%xmm6, %%xmm11\n\t" /* xmm11 holds 1:b0+b1 */
167
168                 "pxor %%xmm4, %%xmm7\n\t"   /* xmm7 holds 3+4:a0*b0 */
169                 "pxor %%xmm2, %%xmm1\n\t"   /* xmm1 holds 3+4:a1*b1 */
170                 "pxor %%xmm14, %%xmm12\n\t" /* xmm12 holds 3+4:(a0+a1)*(b0+b1) */
171
172                 "movdqa %%xmm8, %%xmm13\n\t"
173                 "pclmulqdq $0, %%xmm3, %%xmm13\n\t"  /* xmm13 holds 2:a0*b0 */
174                 "pclmulqdq $17, %%xmm8, %%xmm3\n\t"  /* xmm3 holds 2:a1*b1 */
175                 "pclmulqdq $0, %%xmm5, %%xmm15\n\t" /* xmm15 holds 2:(a0+a1)*(b0+b1) */
176
177                 "pxor %%xmm13, %%xmm7\n\t" /* xmm7 holds 2+3+4:a0*b0 */
178                 "pxor %%xmm3, %%xmm1\n\t"  /* xmm1 holds 2+3+4:a1*b1 */
179                 "pxor %%xmm15, %%xmm12\n\t" /* xmm12 holds 2+3+4:(a0+a1)*(b0+b1) */
180
181                 "movdqa %%xmm0, %%xmm3\n\t"
182                 "pclmulqdq $0, %%xmm6, %%xmm3\n\t"  /* xmm3 holds 1:a0*b0 */
183                 "pclmulqdq $17, %%xmm0, %%xmm6\n\t" /* xmm6 holds 1:a1*b1 */
184                 "movdqa %%xmm11, %%xmm4\n\t"
185                 "pclmulqdq $0, %%xmm10, %%xmm4\n\t" /* xmm4 holds 1:(a0+a1)*(b0+b1) */
186
187                 "pxor %%xmm7, %%xmm3\n\t"  /* xmm3 holds 1+2+3+4:a0*b0 */
188                 "pxor %%xmm1, %%xmm6\n\t"  /* xmm6 holds 1+2+3+4:a1*b1 */
189                 "pxor %%xmm12, %%xmm4\n\t" /* xmm4 holds 1+2+3+4:(a0+a1)*(b0+b1) */
190
191                 /* aggregated reduction... */
192                 "movdqa %%xmm3, %%xmm5\n\t"
193                 "pxor %%xmm6, %%xmm5\n\t" /* xmm5 holds a0*b0+a1*b1 */
194                 "pxor %%xmm5, %%xmm4\n\t" /* xmm4 holds a0*b0+a1*b1+(a0+a1)*(b0+b1) */
195                 "movdqa %%xmm4, %%xmm5\n\t"
196                 "psrldq $8, %%xmm4\n\t"
197                 "pslldq $8, %%xmm5\n\t"
198                 "pxor %%xmm5, %%xmm3\n\t"
199                 "pxor %%xmm4, %%xmm6\n\t" /* <xmm6:xmm3> holds the result of the
200                                              carry-less multiplication of xmm0
201                                              by xmm1 */
202
203                 /* shift the result by one bit position to the left cope for
204                    the fact that bits are reversed */
205                 "movdqa %%xmm3, %%xmm4\n\t"
206                 "movdqa %%xmm6, %%xmm5\n\t"
207                 "pslld $1, %%xmm3\n\t"
208                 "pslld $1, %%xmm6\n\t"
209                 "psrld $31, %%xmm4\n\t"
210                 "psrld $31, %%xmm5\n\t"
211                 "movdqa %%xmm4, %%xmm1\n\t"
212                 "pslldq $4, %%xmm5\n\t"
213                 "pslldq $4, %%xmm4\n\t"
214                 "psrldq $12, %%xmm1\n\t"
215                 "por %%xmm4, %%xmm3\n\t"
216                 "por %%xmm5, %%xmm6\n\t"
217                 "por %%xmm6, %%xmm1\n\t"
218
219                 /* first phase of the reduction */
220                 "movdqa %%xmm3, %%xmm6\n\t"
221                 "movdqa %%xmm3, %%xmm7\n\t"
222                 "pslld $31, %%xmm6\n\t"  /* packed right shifting << 31 */
223                 "movdqa %%xmm3, %%xmm5\n\t"
224                 "pslld $30, %%xmm7\n\t"  /* packed right shifting shift << 30 */
225                 "pslld $25, %%xmm5\n\t"  /* packed right shifting shift << 25 */
226                 "pxor %%xmm7, %%xmm6\n\t" /* xor the shifted versions */
227                 "pxor %%xmm5, %%xmm6\n\t"
228                 "movdqa %%xmm6, %%xmm7\n\t"
229                 "pslldq $12, %%xmm6\n\t"
230                 "psrldq $4, %%xmm7\n\t"
231                 "pxor %%xmm6, %%xmm3\n\t" /* first phase of the reduction
232                                              complete */
233
234                 /* second phase of the reduction */
235                 "movdqa %%xmm3, %%xmm2\n\t"
236                 "movdqa %%xmm3, %%xmm4\n\t"
237                 "psrld $1, %%xmm2\n\t"    /* packed left shifting >> 1 */
238                 "movdqa %%xmm3, %%xmm5\n\t"
239                 "psrld $2, %%xmm4\n\t"    /* packed left shifting >> 2 */
240                 "psrld $7, %%xmm5\n\t"    /* packed left shifting >> 7 */
241                 "pxor %%xmm4, %%xmm2\n\t" /* xor the shifted versions */
242                 "pxor %%xmm5, %%xmm2\n\t"
243                 "pxor %%xmm7, %%xmm2\n\t"
244                 "pxor %%xmm2, %%xmm3\n\t"
245                 "pxor %%xmm3, %%xmm1\n\t" /* the result is in xmm1 */
246                 :::"cc");
247 }
248 #endif
249
250
251 void
252 _gcry_ghash_setup_intel_pclmul (gcry_cipher_hd_t c)
253 {
254   static const unsigned char be_mask[16] __attribute__ ((aligned (16))) =
255     { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
256 #if defined(__x86_64__) && defined(__WIN64__)
257   char win64tmp[3 * 16];
258
259   /* XMM6-XMM8 need to be restored after use. */
260   asm volatile ("movdqu %%xmm6, 0*16(%0)\n\t"
261                 "movdqu %%xmm7, 1*16(%0)\n\t"
262                 "movdqu %%xmm8, 2*16(%0)\n\t"
263                 :
264                 : "r" (win64tmp)
265                 : "memory");
266 #endif
267
268   /* Swap endianness of hsub. */
269   asm volatile ("movdqu (%[key]), %%xmm0\n\t"
270                 "pshufb %[be_mask], %%xmm0\n\t"
271                 "movdqu %%xmm0, (%[key])\n\t"
272                 :
273                 : [key] "r" (c->u_mode.gcm.u_ghash_key.key),
274                   [be_mask] "m" (*be_mask)
275                 : "memory");
276
277 #ifdef __x86_64__
278   asm volatile ("movdqa %%xmm0, %%xmm1\n\t"
279                 :
280                 :
281                 : "memory");
282
283   gfmul_pclmul (); /* H•H => H² */
284
285   asm volatile ("movdqu %%xmm1, 0*16(%[h_234])\n\t"
286                 "movdqa %%xmm1, %%xmm8\n\t"
287                 :
288                 : [h_234] "r" (c->u_mode.gcm.gcm_table)
289                 : "memory");
290
291   gfmul_pclmul (); /* H•H² => H³ */
292
293   asm volatile ("movdqa %%xmm8, %%xmm0\n\t"
294                 "movdqu %%xmm1, 1*16(%[h_234])\n\t"
295                 "movdqa %%xmm8, %%xmm1\n\t"
296                 :
297                 : [h_234] "r" (c->u_mode.gcm.gcm_table)
298                 : "memory");
299
300   gfmul_pclmul (); /* H²•H² => H⁴ */
301
302   asm volatile ("movdqu %%xmm1, 2*16(%[h_234])\n\t"
303                 :
304                 : [h_234] "r" (c->u_mode.gcm.gcm_table)
305                 : "memory");
306
307 #ifdef __WIN64__
308   /* Clear/restore used registers. */
309   asm volatile( "pxor %%xmm0, %%xmm0\n\t"
310                 "pxor %%xmm1, %%xmm1\n\t"
311                 "pxor %%xmm2, %%xmm2\n\t"
312                 "pxor %%xmm3, %%xmm3\n\t"
313                 "pxor %%xmm4, %%xmm4\n\t"
314                 "pxor %%xmm5, %%xmm5\n\t"
315                 "movdqu 0*16(%0), %%xmm6\n\t"
316                 "movdqu 1*16(%0), %%xmm7\n\t"
317                 "movdqu 2*16(%0), %%xmm8\n\t"
318                 :
319                 : "r" (win64tmp)
320                 : "memory");
321 #else
322   /* Clear used registers. */
323   asm volatile( "pxor %%xmm0, %%xmm0\n\t"
324                 "pxor %%xmm1, %%xmm1\n\t"
325                 "pxor %%xmm2, %%xmm2\n\t"
326                 "pxor %%xmm3, %%xmm3\n\t"
327                 "pxor %%xmm4, %%xmm4\n\t"
328                 "pxor %%xmm5, %%xmm5\n\t"
329                 "pxor %%xmm6, %%xmm6\n\t"
330                 "pxor %%xmm7, %%xmm7\n\t"
331                 "pxor %%xmm8, %%xmm8\n\t"
332                 ::: "cc" );
333 #endif
334 #endif
335 }
336
337
338 unsigned int
339 _gcry_ghash_intel_pclmul (gcry_cipher_hd_t c, byte *result, const byte *buf,
340                           size_t nblocks)
341 {
342   static const unsigned char be_mask[16] __attribute__ ((aligned (16))) =
343     { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
344   const unsigned int blocksize = GCRY_GCM_BLOCK_LEN;
345 #ifdef __WIN64__
346   char win64tmp[10 * 16];
347 #endif
348
349   if (nblocks == 0)
350     return 0;
351
352 #ifdef __WIN64__
353   /* XMM8-XMM15 need to be restored after use. */
354   asm volatile ("movdqu %%xmm6,  0*16(%0)\n\t"
355                 "movdqu %%xmm7,  1*16(%0)\n\t"
356                 "movdqu %%xmm8,  2*16(%0)\n\t"
357                 "movdqu %%xmm9,  3*16(%0)\n\t"
358                 "movdqu %%xmm10, 4*16(%0)\n\t"
359                 "movdqu %%xmm11, 5*16(%0)\n\t"
360                 "movdqu %%xmm12, 6*16(%0)\n\t"
361                 "movdqu %%xmm13, 7*16(%0)\n\t"
362                 "movdqu %%xmm14, 8*16(%0)\n\t"
363                 "movdqu %%xmm15, 9*16(%0)\n\t"
364                 :
365                 : "r" (win64tmp)
366                 : "memory" );
367 #endif
368
369   /* Preload hash and H1. */
370   asm volatile ("movdqu %[hash], %%xmm1\n\t"
371                 "movdqa %[hsub], %%xmm0\n\t"
372                 "pshufb %[be_mask], %%xmm1\n\t" /* be => le */
373                 :
374                 : [hash] "m" (*result), [be_mask] "m" (*be_mask),
375                   [hsub] "m" (*c->u_mode.gcm.u_ghash_key.key));
376
377 #ifdef __x86_64__
378   if (nblocks >= 4)
379     {
380       do
381         {
382           asm volatile ("movdqa %[be_mask], %%xmm4\n\t"
383                         "movdqu 0*16(%[buf]), %%xmm5\n\t"
384                         "movdqu 1*16(%[buf]), %%xmm2\n\t"
385                         "movdqu 2*16(%[buf]), %%xmm3\n\t"
386                         "movdqu 3*16(%[buf]), %%xmm6\n\t"
387                         "pshufb %%xmm4, %%xmm5\n\t" /* be => le */
388
389                         /* Load H2, H3, H4. */
390                         "movdqu 2*16(%[h_234]), %%xmm10\n\t"
391                         "movdqu 1*16(%[h_234]), %%xmm9\n\t"
392                         "movdqu 0*16(%[h_234]), %%xmm8\n\t"
393
394                         "pxor %%xmm5, %%xmm1\n\t"
395                         "pshufb %%xmm4, %%xmm2\n\t" /* be => le */
396                         "pshufb %%xmm4, %%xmm3\n\t" /* be => le */
397                         "pshufb %%xmm4, %%xmm6\n\t" /* be => le */
398                         :
399                         : [buf] "r" (buf), [be_mask] "m" (*be_mask),
400                           [h_234] "r" (c->u_mode.gcm.gcm_table));
401
402           gfmul_pclmul_aggr4 ();
403
404           buf += 4 * blocksize;
405           nblocks -= 4;
406         }
407       while (nblocks >= 4);
408
409 #ifndef __WIN64__
410       /* Clear used x86-64/XMM registers. */
411       asm volatile( "pxor %%xmm8, %%xmm8\n\t"
412                     "pxor %%xmm9, %%xmm9\n\t"
413                     "pxor %%xmm10, %%xmm10\n\t"
414                     "pxor %%xmm11, %%xmm11\n\t"
415                     "pxor %%xmm12, %%xmm12\n\t"
416                     "pxor %%xmm13, %%xmm13\n\t"
417                     "pxor %%xmm14, %%xmm14\n\t"
418                     "pxor %%xmm15, %%xmm15\n\t"
419                     ::: "cc" );
420 #endif
421     }
422 #endif
423
424   while (nblocks--)
425     {
426       asm volatile ("movdqu %[buf], %%xmm2\n\t"
427                     "pshufb %[be_mask], %%xmm2\n\t" /* be => le */
428                     "pxor %%xmm2, %%xmm1\n\t"
429                     :
430                     : [buf] "m" (*buf), [be_mask] "m" (*be_mask));
431
432       gfmul_pclmul ();
433
434       buf += blocksize;
435     }
436
437   /* Store hash. */
438   asm volatile ("pshufb %[be_mask], %%xmm1\n\t" /* be => le */
439                 "movdqu %%xmm1, %[hash]\n\t"
440                 : [hash] "=m" (*result)
441                 : [be_mask] "m" (*be_mask));
442
443 #ifdef __WIN64__
444   /* Clear/restore used registers. */
445   asm volatile( "pxor %%xmm0, %%xmm0\n\t"
446                 "pxor %%xmm1, %%xmm1\n\t"
447                 "pxor %%xmm2, %%xmm2\n\t"
448                 "pxor %%xmm3, %%xmm3\n\t"
449                 "pxor %%xmm4, %%xmm4\n\t"
450                 "pxor %%xmm5, %%xmm5\n\t"
451                 "movdqu 0*16(%0), %%xmm6\n\t"
452                 "movdqu 1*16(%0), %%xmm7\n\t"
453                 "movdqu 2*16(%0), %%xmm8\n\t"
454                 "movdqu 3*16(%0), %%xmm9\n\t"
455                 "movdqu 4*16(%0), %%xmm10\n\t"
456                 "movdqu 5*16(%0), %%xmm11\n\t"
457                 "movdqu 6*16(%0), %%xmm12\n\t"
458                 "movdqu 7*16(%0), %%xmm13\n\t"
459                 "movdqu 8*16(%0), %%xmm14\n\t"
460                 "movdqu 9*16(%0), %%xmm15\n\t"
461                 :
462                 : "r" (win64tmp)
463                 : "memory" );
464 #else
465   /* Clear used registers. */
466   asm volatile( "pxor %%xmm0, %%xmm0\n\t"
467                 "pxor %%xmm1, %%xmm1\n\t"
468                 "pxor %%xmm2, %%xmm2\n\t"
469                 "pxor %%xmm3, %%xmm3\n\t"
470                 "pxor %%xmm4, %%xmm4\n\t"
471                 "pxor %%xmm5, %%xmm5\n\t"
472                 "pxor %%xmm6, %%xmm6\n\t"
473                 "pxor %%xmm7, %%xmm7\n\t"
474                 ::: "cc" );
475 #endif
476
477   return 0;
478 }
479
480 #if __clang__
481 #  pragma clang attribute pop
482 #endif
483
484 #endif /* GCM_USE_INTEL_PCLMUL */