LCOV - code coverage report
Current view: top level - cipher - crc-intel-pclmul.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 157 157 100.0 %
Date: 2017-03-02 16:44:37 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /* crc-intel-pclmul.c - Intel PCLMUL accelerated CRC implementation
       2             :  * Copyright (C) 2016 Jussi Kivilinna <jussi.kivilinna@iki.fi>
       3             :  *
       4             :  * This file is part of Libgcrypt.
       5             :  *
       6             :  * Libgcrypt is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU Lesser General Public License as
       8             :  * published by the Free Software Foundation; either version 2.1 of
       9             :  * the License, or (at your option) any later version.
      10             :  *
      11             :  * Libgcrypt is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public
      17             :  * License along with this program; if not, write to the Free Software
      18             :  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
      19             :  *
      20             :  */
      21             : 
      22             : #include <config.h>
      23             : #include <stdio.h>
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : 
      27             : #include "g10lib.h"
      28             : 
      29             : #include "bithelp.h"
      30             : #include "bufhelp.h"
      31             : 
      32             : 
      33             : #if defined(ENABLE_PCLMUL_SUPPORT) && defined(ENABLE_SSE41_SUPPORT) && \
      34             :     __GNUC__ >= 4 &&                                                   \
      35             :     ((defined(__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__))
      36             : 
      37             : 
      38             : #if _GCRY_GCC_VERSION >= 40400 /* 4.4 */
      39             : /* Prevent compiler from issuing SSE instructions between asm blocks. */
      40             : #  pragma GCC target("no-sse")
      41             : #endif
      42             : 
      43             : 
      44             : #define ALIGNED_16 __attribute__ ((aligned (16)))
      45             : 
      46             : 
      47             : struct u16_unaligned_s
      48             : {
      49             :   u16 a;
      50             : } __attribute__((packed, aligned (1), may_alias));
      51             : 
      52             : 
      53             : /* Constants structure for generic reflected/non-reflected CRC32 CLMUL
      54             :  * functions. */
      55             : struct crc32_consts_s
      56             : {
      57             :   /* k: { x^(32*17), x^(32*15), x^(32*5), x^(32*3), x^(32*2), 0 } mod P(x) */
      58             :   u64 k[6];
      59             :   /* my_p: { floor(x^64 / P(x)), P(x) } */
      60             :   u64 my_p[2];
      61             : };
      62             : 
      63             : 
      64             : /* CLMUL constants for CRC32 and CRC32RFC1510. */
      65             : static const struct crc32_consts_s crc32_consts ALIGNED_16 =
      66             : {
      67             :   { /* k[6] = reverse_33bits( x^(32*y) mod P(x) ) */
      68             :     U64_C(0x154442bd4), U64_C(0x1c6e41596), /* y = { 17, 15 } */
      69             :     U64_C(0x1751997d0), U64_C(0x0ccaa009e), /* y = { 5, 3 } */
      70             :     U64_C(0x163cd6124), 0                   /* y = 2 */
      71             :   },
      72             :   { /* my_p[2] = reverse_33bits ( { floor(x^64 / P(x)), P(x) } ) */
      73             :     U64_C(0x1f7011641), U64_C(0x1db710641)
      74             :   }
      75             : };
      76             : 
      77             : /* CLMUL constants for CRC24RFC2440 (polynomial multiplied with x⁸). */
      78             : static const struct crc32_consts_s crc24rfc2440_consts ALIGNED_16 =
      79             : {
      80             :   { /* k[6] = x^(32*y) mod P(x) << 32*/
      81             :     U64_C(0x08289a00) << 32, U64_C(0x74b44a00) << 32, /* y = { 17, 15 } */
      82             :     U64_C(0xc4b14d00) << 32, U64_C(0xfd7e0c00) << 32, /* y = { 5, 3 } */
      83             :     U64_C(0xd9fe8c00) << 32, 0                        /* y = 2 */
      84             :   },
      85             :   { /* my_p[2] = { floor(x^64 / P(x)), P(x) } */
      86             :     U64_C(0x1f845fe24), U64_C(0x1864cfb00)
      87             :   }
      88             : };
      89             : 
      90             : /* Common constants for CRC32 algorithms. */
      91             : static const byte crc32_refl_shuf_shift[3 * 16] ALIGNED_16 =
      92             :   {
      93             :     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      94             :     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      95             :     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
      96             :     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
      97             :     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      98             :     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      99             :   };
     100             : static const byte crc32_shuf_shift[3 * 16] ALIGNED_16 =
     101             :   {
     102             :     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     103             :     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     104             :     0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
     105             :     0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
     106             :     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     107             :     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     108             :   };
     109             : static const byte *crc32_bswap_shuf = &crc32_shuf_shift[16];
     110             : static const byte crc32_partial_fold_input_mask[16 + 16] ALIGNED_16 =
     111             :   {
     112             :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     113             :     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     114             :     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     115             :     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     116             :   };
     117             : static const u64 crc32_merge9to15_shuf[15 - 9 + 1][2] ALIGNED_16 =
     118             :   {
     119             :     { U64_C(0x0706050403020100), U64_C(0xffffffffffffff0f) }, /* 9 */
     120             :     { U64_C(0x0706050403020100), U64_C(0xffffffffffff0f0e) },
     121             :     { U64_C(0x0706050403020100), U64_C(0xffffffffff0f0e0d) },
     122             :     { U64_C(0x0706050403020100), U64_C(0xffffffff0f0e0d0c) },
     123             :     { U64_C(0x0706050403020100), U64_C(0xffffff0f0e0d0c0b) },
     124             :     { U64_C(0x0706050403020100), U64_C(0xffff0f0e0d0c0b0a) },
     125             :     { U64_C(0x0706050403020100), U64_C(0xff0f0e0d0c0b0a09) }, /* 15 */
     126             :   };
     127             : static const u64 crc32_merge5to7_shuf[7 - 5 + 1][2] ALIGNED_16 =
     128             :   {
     129             :     { U64_C(0xffffff0703020100), U64_C(0xffffffffffffffff) }, /* 5 */
     130             :     { U64_C(0xffff070603020100), U64_C(0xffffffffffffffff) },
     131             :     { U64_C(0xff07060503020100), U64_C(0xffffffffffffffff) }, /* 7 */
     132             :   };
     133             : 
     134             : /* PCLMUL functions for reflected CRC32. */
     135             : static inline void
     136       35948 : crc32_reflected_bulk (u32 *pcrc, const byte *inbuf, size_t inlen,
     137             :                       const struct crc32_consts_s *consts)
     138             : {
     139       35948 :   if (inlen >= 8 * 16)
     140             :     {
     141       14086 :       asm volatile ("movd %[crc], %%xmm4\n\t"
     142             :                     "movdqu %[inbuf_0], %%xmm0\n\t"
     143             :                     "movdqu %[inbuf_1], %%xmm1\n\t"
     144             :                     "movdqu %[inbuf_2], %%xmm2\n\t"
     145             :                     "movdqu %[inbuf_3], %%xmm3\n\t"
     146             :                     "pxor %%xmm4, %%xmm0\n\t"
     147             :                     :
     148             :                     : [inbuf_0] "m" (inbuf[0 * 16]),
     149       14086 :                       [inbuf_1] "m" (inbuf[1 * 16]),
     150       14086 :                       [inbuf_2] "m" (inbuf[2 * 16]),
     151       14086 :                       [inbuf_3] "m" (inbuf[3 * 16]),
     152             :                       [crc] "m" (*pcrc)
     153             :                     );
     154             : 
     155       14086 :       inbuf += 4 * 16;
     156       14086 :       inlen -= 4 * 16;
     157             : 
     158       14086 :       asm volatile ("movdqa %[k1k2], %%xmm4\n\t"
     159             :                     :
     160             :                     : [k1k2] "m" (consts->k[1 - 1])
     161             :                     );
     162             : 
     163             :       /* Fold by 4. */
     164      259514 :       while (inlen >= 4 * 16)
     165             :         {
     166      231342 :           asm volatile ("movdqu %[inbuf_0], %%xmm5\n\t"
     167             :                         "movdqa %%xmm0, %%xmm6\n\t"
     168             :                         "pclmulqdq $0x00, %%xmm4, %%xmm0\n\t"
     169             :                         "pclmulqdq $0x11, %%xmm4, %%xmm6\n\t"
     170             :                         "pxor %%xmm5, %%xmm0\n\t"
     171             :                         "pxor %%xmm6, %%xmm0\n\t"
     172             : 
     173             :                         "movdqu %[inbuf_1], %%xmm5\n\t"
     174             :                         "movdqa %%xmm1, %%xmm6\n\t"
     175             :                         "pclmulqdq $0x00, %%xmm4, %%xmm1\n\t"
     176             :                         "pclmulqdq $0x11, %%xmm4, %%xmm6\n\t"
     177             :                         "pxor %%xmm5, %%xmm1\n\t"
     178             :                         "pxor %%xmm6, %%xmm1\n\t"
     179             : 
     180             :                         "movdqu %[inbuf_2], %%xmm5\n\t"
     181             :                         "movdqa %%xmm2, %%xmm6\n\t"
     182             :                         "pclmulqdq $0x00, %%xmm4, %%xmm2\n\t"
     183             :                         "pclmulqdq $0x11, %%xmm4, %%xmm6\n\t"
     184             :                         "pxor %%xmm5, %%xmm2\n\t"
     185             :                         "pxor %%xmm6, %%xmm2\n\t"
     186             : 
     187             :                         "movdqu %[inbuf_3], %%xmm5\n\t"
     188             :                         "movdqa %%xmm3, %%xmm6\n\t"
     189             :                         "pclmulqdq $0x00, %%xmm4, %%xmm3\n\t"
     190             :                         "pclmulqdq $0x11, %%xmm4, %%xmm6\n\t"
     191             :                         "pxor %%xmm5, %%xmm3\n\t"
     192             :                         "pxor %%xmm6, %%xmm3\n\t"
     193             :                         :
     194             :                         : [inbuf_0] "m" (inbuf[0 * 16]),
     195      231342 :                           [inbuf_1] "m" (inbuf[1 * 16]),
     196      231342 :                           [inbuf_2] "m" (inbuf[2 * 16]),
     197      231342 :                           [inbuf_3] "m" (inbuf[3 * 16])
     198             :                         );
     199             : 
     200      231342 :           inbuf += 4 * 16;
     201      231342 :           inlen -= 4 * 16;
     202             :         }
     203             : 
     204       14086 :       asm volatile ("movdqa %[k3k4], %%xmm6\n\t"
     205             :                     "movdqa %[my_p], %%xmm5\n\t"
     206             :                     :
     207             :                     : [k3k4] "m" (consts->k[3 - 1]),
     208             :                       [my_p] "m" (consts->my_p[0])
     209             :                     );
     210             : 
     211             :       /* Fold 4 to 1. */
     212             : 
     213       14086 :       asm volatile ("movdqa %%xmm0, %%xmm4\n\t"
     214             :                     "pclmulqdq $0x00, %%xmm6, %%xmm0\n\t"
     215             :                     "pclmulqdq $0x11, %%xmm6, %%xmm4\n\t"
     216             :                     "pxor %%xmm1, %%xmm0\n\t"
     217             :                     "pxor %%xmm4, %%xmm0\n\t"
     218             : 
     219             :                     "movdqa %%xmm0, %%xmm4\n\t"
     220             :                     "pclmulqdq $0x00, %%xmm6, %%xmm0\n\t"
     221             :                     "pclmulqdq $0x11, %%xmm6, %%xmm4\n\t"
     222             :                     "pxor %%xmm2, %%xmm0\n\t"
     223             :                     "pxor %%xmm4, %%xmm0\n\t"
     224             : 
     225             :                     "movdqa %%xmm0, %%xmm4\n\t"
     226             :                     "pclmulqdq $0x00, %%xmm6, %%xmm0\n\t"
     227             :                     "pclmulqdq $0x11, %%xmm6, %%xmm4\n\t"
     228             :                     "pxor %%xmm3, %%xmm0\n\t"
     229             :                     "pxor %%xmm4, %%xmm0\n\t"
     230             :                     :
     231             :                     :
     232             :                     );
     233             :     }
     234             :   else
     235             :     {
     236       21862 :       asm volatile ("movd %[crc], %%xmm1\n\t"
     237             :                     "movdqu %[inbuf], %%xmm0\n\t"
     238             :                     "movdqa %[k3k4], %%xmm6\n\t"
     239             :                     "pxor %%xmm1, %%xmm0\n\t"
     240             :                     "movdqa %[my_p], %%xmm5\n\t"
     241             :                     :
     242             :                     : [inbuf] "m" (*inbuf),
     243             :                       [crc] "m" (*pcrc),
     244             :                       [k3k4] "m" (consts->k[3 - 1]),
     245             :                       [my_p] "m" (consts->my_p[0])
     246             :                     );
     247             : 
     248       21862 :       inbuf += 16;
     249       21862 :       inlen -= 16;
     250             :     }
     251             : 
     252             :   /* Fold by 1. */
     253       35948 :   if (inlen >= 16)
     254             :     {
     255      185803 :       while (inlen >= 16)
     256             :         {
     257             :           /* Load next block to XMM2. Fold XMM0 to XMM0:XMM1. */
     258      122283 :           asm volatile ("movdqu %[inbuf], %%xmm2\n\t"
     259             :                         "movdqa %%xmm0, %%xmm1\n\t"
     260             :                         "pclmulqdq $0x00, %%xmm6, %%xmm0\n\t"
     261             :                         "pclmulqdq $0x11, %%xmm6, %%xmm1\n\t"
     262             :                         "pxor %%xmm2, %%xmm0\n\t"
     263             :                         "pxor %%xmm1, %%xmm0\n\t"
     264             :                         :
     265             :                         : [inbuf] "m" (*inbuf)
     266             :                         );
     267             : 
     268      122283 :           inbuf += 16;
     269      122283 :           inlen -= 16;
     270             :         }
     271             :     }
     272             : 
     273             :   /* Partial fold. */
     274       35948 :   if (inlen)
     275             :     {
     276             :       /* Load last input and add padding zeros. */
     277       31917 :       asm volatile ("movdqu %[shr_shuf], %%xmm3\n\t"
     278             :                     "movdqu %[shl_shuf], %%xmm4\n\t"
     279             :                     "movdqu %[mask], %%xmm2\n\t"
     280             : 
     281             :                     "movdqa %%xmm0, %%xmm1\n\t"
     282             :                     "pshufb %%xmm4, %%xmm0\n\t"
     283             :                     "movdqu %[inbuf], %%xmm4\n\t"
     284             :                     "pshufb %%xmm3, %%xmm1\n\t"
     285             :                     "pand %%xmm4, %%xmm2\n\t"
     286             :                     "por %%xmm1, %%xmm2\n\t"
     287             : 
     288             :                     "movdqa %%xmm0, %%xmm1\n\t"
     289             :                     "pclmulqdq $0x00, %%xmm6, %%xmm0\n\t"
     290             :                     "pclmulqdq $0x11, %%xmm6, %%xmm1\n\t"
     291             :                     "pxor %%xmm2, %%xmm0\n\t"
     292             :                     "pxor %%xmm1, %%xmm0\n\t"
     293             :                     :
     294       31917 :                     : [inbuf] "m" (*(inbuf - 16 + inlen)),
     295             :                       [mask] "m" (crc32_partial_fold_input_mask[inlen]),
     296             :                       [shl_shuf] "m" (crc32_refl_shuf_shift[inlen]),
     297       31917 :                       [shr_shuf] "m" (crc32_refl_shuf_shift[inlen + 16])
     298             :                     );
     299             : 
     300       31917 :       inbuf += inlen;
     301       31917 :       inlen -= inlen;
     302             :     }
     303             : 
     304             :   /* Final fold. */
     305       35948 :   asm volatile (/* reduce 128-bits to 96-bits */
     306             :                 "movdqa %%xmm0, %%xmm1\n\t"
     307             :                 "pclmulqdq $0x10, %%xmm6, %%xmm0\n\t"
     308             :                 "psrldq $8, %%xmm1\n\t"
     309             :                 "pxor %%xmm1, %%xmm0\n\t"
     310             : 
     311             :                 /* reduce 96-bits to 64-bits */
     312             :                 "pshufd $0xfc, %%xmm0, %%xmm1\n\t" /* [00][00][00][x] */
     313             :                 "pshufd $0xf9, %%xmm0, %%xmm0\n\t" /* [00][00][x>>64][x>>32] */
     314             :                 "pclmulqdq $0x00, %[k5], %%xmm1\n\t" /* [00][00][xx][xx] */
     315             :                 "pxor %%xmm1, %%xmm0\n\t" /* top 64-bit are zero */
     316             : 
     317             :                 /* barrett reduction */
     318             :                 "pshufd $0xf3, %%xmm0, %%xmm1\n\t" /* [00][00][x>>32][00] */
     319             :                 "pslldq $4, %%xmm0\n\t" /* [??][x>>32][??][??] */
     320             :                 "pclmulqdq $0x00, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */
     321             :                 "pclmulqdq $0x10, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */
     322             :                 "pxor %%xmm1, %%xmm0\n\t"
     323             : 
     324             :                 /* store CRC */
     325             :                 "pextrd $2, %%xmm0, %[out]\n\t"
     326             :                 : [out] "=m" (*pcrc)
     327             :                 : [k5] "m" (consts->k[5 - 1])
     328             :                 );
     329       35948 : }
     330             : 
     331             : static inline void
     332     2000203 : crc32_reflected_less_than_16 (u32 *pcrc, const byte *inbuf, size_t inlen,
     333             :                               const struct crc32_consts_s *consts)
     334             : {
     335     2000203 :   if (inlen < 4)
     336             :     {
     337     2000046 :       u32 crc = *pcrc;
     338             :       u32 data;
     339             : 
     340     2000046 :       asm volatile ("movdqa %[my_p], %%xmm5\n\t"
     341             :                     :
     342             :                     : [my_p] "m" (consts->my_p[0])
     343             :                     );
     344             : 
     345     2000046 :       if (inlen == 1)
     346             :         {
     347     2000021 :           data = inbuf[0];
     348     2000021 :           data ^= crc;
     349     2000021 :           data <<= 24;
     350     2000021 :           crc >>= 8;
     351             :         }
     352          25 :       else if (inlen == 2)
     353             :         {
     354          13 :           data = ((const struct u16_unaligned_s *)inbuf)->a;
     355          13 :           data ^= crc;
     356          13 :           data <<= 16;
     357          13 :           crc >>= 16;
     358             :         }
     359             :       else
     360             :         {
     361          12 :           data = ((const struct u16_unaligned_s *)inbuf)->a;
     362          12 :           data |= inbuf[2] << 16;
     363          12 :           data ^= crc;
     364          12 :           data <<= 8;
     365          12 :           crc >>= 24;
     366             :         }
     367             : 
     368             :       /* Barrett reduction */
     369     2000046 :       asm volatile ("movd %[in], %%xmm0\n\t"
     370             :                     "movd %[crc], %%xmm1\n\t"
     371             : 
     372             :                     "pclmulqdq $0x00, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */
     373             :                     "psllq $32, %%xmm1\n\t"
     374             :                     "pshufd $0xfc, %%xmm0, %%xmm0\n\t" /* [00][00][00][x] */
     375             :                     "pclmulqdq $0x10, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */
     376             :                     "pxor %%xmm1, %%xmm0\n\t"
     377             : 
     378             :                     "pextrd $1, %%xmm0, %[out]\n\t"
     379             :                     : [out] "=m" (*pcrc)
     380             :                     : [in] "rm" (data),
     381             :                       [crc] "rm" (crc)
     382             :                     );
     383             :     }
     384         157 :   else if (inlen == 4)
     385             :     {
     386             :       /* Barrett reduction */
     387          21 :       asm volatile ("movd %[crc], %%xmm1\n\t"
     388             :                     "movd %[in], %%xmm0\n\t"
     389             :                     "movdqa %[my_p], %%xmm5\n\t"
     390             :                     "pxor %%xmm1, %%xmm0\n\t"
     391             : 
     392             :                     "pclmulqdq $0x00, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */
     393             :                     "pshufd $0xfc, %%xmm0, %%xmm0\n\t" /* [00][00][00][x] */
     394             :                     "pclmulqdq $0x10, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */
     395             : 
     396             :                     "pextrd $1, %%xmm0, %[out]\n\t"
     397             :                     : [out] "=m" (*pcrc)
     398             :                     : [in] "m" (*inbuf),
     399             :                       [crc] "m" (*pcrc),
     400             :                       [my_p] "m" (consts->my_p[0])
     401             :                     );
     402             :     }
     403             :   else
     404             :     {
     405         136 :       asm volatile ("movdqu %[shuf], %%xmm4\n\t"
     406             :                     "movd %[crc], %%xmm1\n\t"
     407             :                     "movdqa %[my_p], %%xmm5\n\t"
     408             :                     "movdqa %[k3k4], %%xmm6\n\t"
     409             :                     :
     410             :                     : [shuf] "m" (crc32_refl_shuf_shift[inlen]),
     411             :                       [crc] "m" (*pcrc),
     412             :                       [my_p] "m" (consts->my_p[0]),
     413             :                       [k3k4] "m" (consts->k[3 - 1])
     414             :                     );
     415             : 
     416         136 :       if (inlen >= 8)
     417             :         {
     418         104 :           asm volatile ("movq %[inbuf], %%xmm0\n\t"
     419             :                         :
     420             :                         : [inbuf] "m" (*inbuf)
     421             :                         );
     422         104 :           if (inlen > 8)
     423             :             {
     424          92 :               asm volatile (/*"pinsrq $1, %[inbuf_tail], %%xmm0\n\t"*/
     425             :                             "movq %[inbuf_tail], %%xmm2\n\t"
     426             :                             "punpcklqdq %%xmm2, %%xmm0\n\t"
     427             :                             "pshufb %[merge_shuf], %%xmm0\n\t"
     428             :                             :
     429          92 :                             : [inbuf_tail] "m" (inbuf[inlen - 8]),
     430             :                               [merge_shuf] "m"
     431          92 :                                 (*crc32_merge9to15_shuf[inlen - 9])
     432             :                             );
     433             :             }
     434             :         }
     435             :       else
     436             :         {
     437          32 :           asm volatile ("movd %[inbuf], %%xmm0\n\t"
     438             :                         "pinsrd $1, %[inbuf_tail], %%xmm0\n\t"
     439             :                         "pshufb %[merge_shuf], %%xmm0\n\t"
     440             :                         :
     441             :                         : [inbuf] "m" (*inbuf),
     442          32 :                           [inbuf_tail] "m" (inbuf[inlen - 4]),
     443             :                           [merge_shuf] "m"
     444          32 :                             (*crc32_merge5to7_shuf[inlen - 5])
     445             :                         );
     446             :         }
     447             : 
     448             :       /* Final fold. */
     449         136 :       asm volatile ("pxor %%xmm1, %%xmm0\n\t"
     450             :                     "pshufb %%xmm4, %%xmm0\n\t"
     451             : 
     452             :                     /* reduce 128-bits to 96-bits */
     453             :                     "movdqa %%xmm0, %%xmm1\n\t"
     454             :                     "pclmulqdq $0x10, %%xmm6, %%xmm0\n\t"
     455             :                     "psrldq $8, %%xmm1\n\t"
     456             :                     "pxor %%xmm1, %%xmm0\n\t" /* top 32-bit are zero */
     457             : 
     458             :                     /* reduce 96-bits to 64-bits */
     459             :                     "pshufd $0xfc, %%xmm0, %%xmm1\n\t" /* [00][00][00][x] */
     460             :                     "pshufd $0xf9, %%xmm0, %%xmm0\n\t" /* [00][00][x>>64][x>>32] */
     461             :                     "pclmulqdq $0x00, %[k5], %%xmm1\n\t" /* [00][00][xx][xx] */
     462             :                     "pxor %%xmm1, %%xmm0\n\t" /* top 64-bit are zero */
     463             : 
     464             :                     /* barrett reduction */
     465             :                     "pshufd $0xf3, %%xmm0, %%xmm1\n\t" /* [00][00][x>>32][00] */
     466             :                     "pslldq $4, %%xmm0\n\t" /* [??][x>>32][??][??] */
     467             :                     "pclmulqdq $0x00, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */
     468             :                     "pclmulqdq $0x10, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */
     469             :                     "pxor %%xmm1, %%xmm0\n\t"
     470             : 
     471             :                     /* store CRC */
     472             :                     "pextrd $2, %%xmm0, %[out]\n\t"
     473             :                     : [out] "=m" (*pcrc)
     474             :                     : [k5] "m" (consts->k[5 - 1])
     475             :                     );
     476             :     }
     477     2000203 : }
     478             : 
     479             : /* PCLMUL functions for non-reflected CRC32. */
     480             : static inline void
     481       17425 : crc32_bulk (u32 *pcrc, const byte *inbuf, size_t inlen,
     482             :             const struct crc32_consts_s *consts)
     483             : {
     484       17425 :   asm volatile ("movdqa %[bswap], %%xmm7\n\t"
     485             :                 :
     486       17425 :                 : [bswap] "m" (*crc32_bswap_shuf)
     487             :                 );
     488             : 
     489       17425 :   if (inlen >= 8 * 16)
     490             :     {
     491        6601 :       asm volatile ("movd %[crc], %%xmm4\n\t"
     492             :                     "movdqu %[inbuf_0], %%xmm0\n\t"
     493             :                     "movdqu %[inbuf_1], %%xmm1\n\t"
     494             :                     "movdqu %[inbuf_2], %%xmm2\n\t"
     495             :                     "pxor %%xmm4, %%xmm0\n\t"
     496             :                     "movdqu %[inbuf_3], %%xmm3\n\t"
     497             :                     "pshufb %%xmm7, %%xmm0\n\t"
     498             :                     "pshufb %%xmm7, %%xmm1\n\t"
     499             :                     "pshufb %%xmm7, %%xmm2\n\t"
     500             :                     "pshufb %%xmm7, %%xmm3\n\t"
     501             :                     :
     502             :                     : [inbuf_0] "m" (inbuf[0 * 16]),
     503        6601 :                       [inbuf_1] "m" (inbuf[1 * 16]),
     504        6601 :                       [inbuf_2] "m" (inbuf[2 * 16]),
     505        6601 :                       [inbuf_3] "m" (inbuf[3 * 16]),
     506             :                       [crc] "m" (*pcrc)
     507             :                     );
     508             : 
     509        6601 :       inbuf += 4 * 16;
     510        6601 :       inlen -= 4 * 16;
     511             : 
     512        6601 :       asm volatile ("movdqa %[k1k2], %%xmm4\n\t"
     513             :                     :
     514             :                     : [k1k2] "m" (consts->k[1 - 1])
     515             :                     );
     516             : 
     517             :       /* Fold by 4. */
     518      114755 :       while (inlen >= 4 * 16)
     519             :         {
     520      101553 :           asm volatile ("movdqu %[inbuf_0], %%xmm5\n\t"
     521             :                         "movdqa %%xmm0, %%xmm6\n\t"
     522             :                         "pshufb %%xmm7, %%xmm5\n\t"
     523             :                         "pclmulqdq $0x01, %%xmm4, %%xmm0\n\t"
     524             :                         "pclmulqdq $0x10, %%xmm4, %%xmm6\n\t"
     525             :                         "pxor %%xmm5, %%xmm0\n\t"
     526             :                         "pxor %%xmm6, %%xmm0\n\t"
     527             : 
     528             :                         "movdqu %[inbuf_1], %%xmm5\n\t"
     529             :                         "movdqa %%xmm1, %%xmm6\n\t"
     530             :                         "pshufb %%xmm7, %%xmm5\n\t"
     531             :                         "pclmulqdq $0x01, %%xmm4, %%xmm1\n\t"
     532             :                         "pclmulqdq $0x10, %%xmm4, %%xmm6\n\t"
     533             :                         "pxor %%xmm5, %%xmm1\n\t"
     534             :                         "pxor %%xmm6, %%xmm1\n\t"
     535             : 
     536             :                         "movdqu %[inbuf_2], %%xmm5\n\t"
     537             :                         "movdqa %%xmm2, %%xmm6\n\t"
     538             :                         "pshufb %%xmm7, %%xmm5\n\t"
     539             :                         "pclmulqdq $0x01, %%xmm4, %%xmm2\n\t"
     540             :                         "pclmulqdq $0x10, %%xmm4, %%xmm6\n\t"
     541             :                         "pxor %%xmm5, %%xmm2\n\t"
     542             :                         "pxor %%xmm6, %%xmm2\n\t"
     543             : 
     544             :                         "movdqu %[inbuf_3], %%xmm5\n\t"
     545             :                         "movdqa %%xmm3, %%xmm6\n\t"
     546             :                         "pshufb %%xmm7, %%xmm5\n\t"
     547             :                         "pclmulqdq $0x01, %%xmm4, %%xmm3\n\t"
     548             :                         "pclmulqdq $0x10, %%xmm4, %%xmm6\n\t"
     549             :                         "pxor %%xmm5, %%xmm3\n\t"
     550             :                         "pxor %%xmm6, %%xmm3\n\t"
     551             :                         :
     552             :                         : [inbuf_0] "m" (inbuf[0 * 16]),
     553      101553 :                           [inbuf_1] "m" (inbuf[1 * 16]),
     554      101553 :                           [inbuf_2] "m" (inbuf[2 * 16]),
     555      101553 :                           [inbuf_3] "m" (inbuf[3 * 16])
     556             :                         );
     557             : 
     558      101553 :           inbuf += 4 * 16;
     559      101553 :           inlen -= 4 * 16;
     560             :         }
     561             : 
     562        6601 :       asm volatile ("movdqa %[k3k4], %%xmm6\n\t"
     563             :                     "movdqa %[my_p], %%xmm5\n\t"
     564             :                     :
     565             :                     : [k3k4] "m" (consts->k[3 - 1]),
     566             :                       [my_p] "m" (consts->my_p[0])
     567             :                     );
     568             : 
     569             :       /* Fold 4 to 1. */
     570             : 
     571        6601 :       asm volatile ("movdqa %%xmm0, %%xmm4\n\t"
     572             :                     "pclmulqdq $0x01, %%xmm6, %%xmm0\n\t"
     573             :                     "pclmulqdq $0x10, %%xmm6, %%xmm4\n\t"
     574             :                     "pxor %%xmm1, %%xmm0\n\t"
     575             :                     "pxor %%xmm4, %%xmm0\n\t"
     576             : 
     577             :                     "movdqa %%xmm0, %%xmm4\n\t"
     578             :                     "pclmulqdq $0x01, %%xmm6, %%xmm0\n\t"
     579             :                     "pclmulqdq $0x10, %%xmm6, %%xmm4\n\t"
     580             :                     "pxor %%xmm2, %%xmm0\n\t"
     581             :                     "pxor %%xmm4, %%xmm0\n\t"
     582             : 
     583             :                     "movdqa %%xmm0, %%xmm4\n\t"
     584             :                     "pclmulqdq $0x01, %%xmm6, %%xmm0\n\t"
     585             :                     "pclmulqdq $0x10, %%xmm6, %%xmm4\n\t"
     586             :                     "pxor %%xmm3, %%xmm0\n\t"
     587             :                     "pxor %%xmm4, %%xmm0\n\t"
     588             :                     :
     589             :                     :
     590             :                     );
     591             :     }
     592             :   else
     593             :     {
     594       10824 :       asm volatile ("movd %[crc], %%xmm1\n\t"
     595             :                     "movdqu %[inbuf], %%xmm0\n\t"
     596             :                     "movdqa %[k3k4], %%xmm6\n\t"
     597             :                     "pxor %%xmm1, %%xmm0\n\t"
     598             :                     "movdqa %[my_p], %%xmm5\n\t"
     599             :                     "pshufb %%xmm7, %%xmm0\n\t"
     600             :                     :
     601             :                     : [inbuf] "m" (*inbuf),
     602             :                       [crc] "m" (*pcrc),
     603             :                       [k3k4] "m" (consts->k[3 - 1]),
     604             :                       [my_p] "m" (consts->my_p[0])
     605             :                     );
     606             : 
     607       10824 :       inbuf += 16;
     608       10824 :       inlen -= 16;
     609             :     }
     610             : 
     611             :   /* Fold by 1. */
     612       17425 :   if (inlen >= 16)
     613             :     {
     614       91530 :       while (inlen >= 16)
     615             :         {
     616             :           /* Load next block to XMM2. Fold XMM0 to XMM0:XMM1. */
     617       60670 :           asm volatile ("movdqu %[inbuf], %%xmm2\n\t"
     618             :                         "movdqa %%xmm0, %%xmm1\n\t"
     619             :                         "pclmulqdq $0x01, %%xmm6, %%xmm0\n\t"
     620             :                         "pshufb %%xmm7, %%xmm2\n\t"
     621             :                         "pclmulqdq $0x10, %%xmm6, %%xmm1\n\t"
     622             :                         "pxor %%xmm2, %%xmm0\n\t"
     623             :                         "pxor %%xmm1, %%xmm0\n\t"
     624             :                         :
     625             :                         : [inbuf] "m" (*inbuf)
     626             :                         );
     627             : 
     628       60670 :           inbuf += 16;
     629       60670 :           inlen -= 16;
     630             :         }
     631             :     }
     632             : 
     633             :   /* Partial fold. */
     634       17425 :   if (inlen)
     635             :     {
     636             :       /* Load last input and add padding zeros. */
     637       15957 :       asm volatile ("movdqu %[shl_shuf], %%xmm4\n\t"
     638             :                     "movdqu %[shr_shuf], %%xmm3\n\t"
     639             :                     "movdqu %[mask], %%xmm2\n\t"
     640             : 
     641             :                     "movdqa %%xmm0, %%xmm1\n\t"
     642             :                     "pshufb %%xmm4, %%xmm0\n\t"
     643             :                     "movdqu %[inbuf], %%xmm4\n\t"
     644             :                     "pshufb %%xmm3, %%xmm1\n\t"
     645             :                     "pand %%xmm4, %%xmm2\n\t"
     646             :                     "por %%xmm1, %%xmm2\n\t"
     647             : 
     648             :                     "pshufb %%xmm7, %%xmm2\n\t"
     649             : 
     650             :                     "movdqa %%xmm0, %%xmm1\n\t"
     651             :                     "pclmulqdq $0x01, %%xmm6, %%xmm0\n\t"
     652             :                     "pclmulqdq $0x10, %%xmm6, %%xmm1\n\t"
     653             :                     "pxor %%xmm2, %%xmm0\n\t"
     654             :                     "pxor %%xmm1, %%xmm0\n\t"
     655             :                     :
     656       15957 :                     : [inbuf] "m" (*(inbuf - 16 + inlen)),
     657             :                       [mask] "m" (crc32_partial_fold_input_mask[inlen]),
     658       15957 :                       [shl_shuf] "m" (crc32_refl_shuf_shift[32 - inlen]),
     659       15957 :                       [shr_shuf] "m" (crc32_shuf_shift[inlen + 16])
     660             :                     );
     661             : 
     662       15957 :       inbuf += inlen;
     663       15957 :       inlen -= inlen;
     664             :     }
     665             : 
     666             :   /* Final fold. */
     667       17425 :   asm volatile (/* reduce 128-bits to 96-bits */
     668             :                 "movdqa %%xmm0, %%xmm1\n\t"
     669             :                 "pclmulqdq $0x11, %%xmm6, %%xmm0\n\t"
     670             :                 "pslldq $8, %%xmm1\n\t"
     671             :                 "pxor %%xmm1, %%xmm0\n\t" /* bottom 32-bit are zero */
     672             : 
     673             :                 /* reduce 96-bits to 64-bits */
     674             :                 "pshufd $0x30, %%xmm0, %%xmm1\n\t" /* [00][x>>96][00][00] */
     675             :                 "pshufd $0x24, %%xmm0, %%xmm0\n\t" /* [00][xx][xx][00] */
     676             :                 "pclmulqdq $0x01, %[k5], %%xmm1\n\t" /* [00][xx][xx][00] */
     677             :                 "pxor %%xmm1, %%xmm0\n\t" /* top and bottom 32-bit are zero */
     678             : 
     679             :                 /* barrett reduction */
     680             :                 "pshufd $0x01, %%xmm0, %%xmm1\n\t" /* [00][00][00][x>>32] */
     681             :                 "pclmulqdq $0x01, %%xmm5, %%xmm0\n\t" /* [00][xx][xx][xx] */
     682             :                 "psrldq $4, %%xmm0\n\t" /* [00][00][xx][xx] */
     683             :                 "pclmulqdq $0x10, %%xmm5, %%xmm0\n\t"
     684             :                 "pxor %%xmm1, %%xmm0\n\t"
     685             : 
     686             :                 /* store CRC in input endian */
     687             :                 "movd %%xmm0, %%eax\n\t"
     688             :                 "bswapl %%eax\n\t"
     689             :                 "movl %%eax, %[out]\n\t"
     690             :                 : [out] "=m" (*pcrc)
     691             :                 : [k5] "m" (consts->k[5 - 1])
     692             :                 : "eax" );
     693       17425 : }
     694             : 
     695             : static inline void
     696     1000089 : crc32_less_than_16 (u32 *pcrc, const byte *inbuf, size_t inlen,
     697             :                     const struct crc32_consts_s *consts)
     698             : {
     699     1000089 :   if (inlen < 4)
     700             :     {
     701     1000014 :       u32 crc = *pcrc;
     702             :       u32 data;
     703             : 
     704     1000014 :       asm volatile ("movdqa %[my_p], %%xmm5\n\t"
     705             :                     :
     706             :                     : [my_p] "m" (consts->my_p[0])
     707             :                     );
     708             : 
     709     1000014 :       if (inlen == 1)
     710             :         {
     711     1000004 :           data = inbuf[0];
     712     1000004 :           data ^= crc;
     713     1000004 :           data = _gcry_bswap32(data << 24);
     714     1000004 :           crc = _gcry_bswap32(crc >> 8);
     715             :         }
     716          10 :       else if (inlen == 2)
     717             :         {
     718           5 :           data = ((const struct u16_unaligned_s *)inbuf)->a;
     719           5 :           data ^= crc;
     720           5 :           data = _gcry_bswap32(data << 16);
     721           5 :           crc = _gcry_bswap32(crc >> 16);
     722             :         }
     723             :       else
     724             :         {
     725           5 :           data = ((const struct u16_unaligned_s *)inbuf)->a;
     726           5 :           data |= inbuf[2] << 16;
     727           5 :           data ^= crc;
     728           5 :           data = _gcry_bswap32(data << 8);
     729           5 :           crc = _gcry_bswap32(crc >> 24);
     730             :         }
     731             : 
     732             :       /* Barrett reduction */
     733     1000014 :       asm volatile ("movd %[in], %%xmm0\n\t"
     734             :                     "psllq $32, %%xmm0\n\t" /* [00][00][xx][00] */
     735             :                     "movd %[crc], %%xmm1\n\t"
     736             : 
     737             :                     "pclmulqdq $0x00, %%xmm5, %%xmm0\n\t" /* [00][xx][xx][00] */
     738             :                     "pclmulqdq $0x11, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */
     739             :                     "pxor %%xmm1, %%xmm0\n\t"
     740             : 
     741             :                     /* store CRC in input endian */
     742             :                     "movd %%xmm0, %%eax\n\t"
     743             :                     "bswapl %%eax\n\t"
     744             :                     "movl %%eax, %[out]\n\t"
     745             :                     : [out] "=m" (*pcrc)
     746             :                     : [in] "r" (data),
     747             :                       [crc] "r" (crc)
     748             :                     : "eax" );
     749             :     }
     750          75 :   else if (inlen == 4)
     751             :     {
     752             :       /* Barrett reduction */
     753           8 :       asm volatile ("movd %[crc], %%xmm0\n\t"
     754             :                     "movd %[in], %%xmm1\n\t"
     755             :                     "movdqa %[my_p], %%xmm5\n\t"
     756             :                     :
     757             :                     : [in] "m" (*inbuf),
     758             :                       [crc] "m" (*pcrc),
     759             :                       [my_p] "m" (consts->my_p[0])
     760             :                     : "cc" );
     761             : 
     762           8 :       asm volatile ("pxor %%xmm1, %%xmm0\n\t"
     763             :                     "pshufb %[bswap], %%xmm0\n\t" /* [xx][00][00][00] */
     764             : 
     765             :                     "pclmulqdq $0x01, %%xmm5, %%xmm0\n\t" /* [00][xx][xx][00] */
     766             :                     "pclmulqdq $0x11, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */
     767             :                     :
     768           8 :                     : [bswap] "m" (*crc32_bswap_shuf)
     769             :                     : "cc" );
     770             : 
     771           8 :       asm volatile (/* store CRC in input endian */
     772             :                     "movd %%xmm0, %%eax\n\t"
     773             :                     "bswapl %%eax\n\t"
     774             :                     "movl %%eax, %[out]\n\t"
     775             :                     : [out] "=m" (*pcrc)
     776             :                     :
     777             :                     : "eax", "cc" );
     778             :     }
     779             :   else
     780             :     {
     781          67 :       asm volatile ("movdqu %[shuf], %%xmm7\n\t"
     782             :                     "movd %[crc], %%xmm1\n\t"
     783             :                     "movdqa %[my_p], %%xmm5\n\t"
     784             :                     "movdqa %[k3k4], %%xmm6\n\t"
     785             :                     :
     786          67 :                     : [shuf] "m" (crc32_shuf_shift[32 - inlen]),
     787             :                       [crc] "m" (*pcrc),
     788             :                       [my_p] "m" (consts->my_p[0]),
     789             :                       [k3k4] "m" (consts->k[3 - 1])
     790             :                     );
     791             : 
     792          67 :       if (inlen >= 8)
     793             :         {
     794          51 :           asm volatile ("movq %[inbuf], %%xmm0\n\t"
     795             :                         :
     796             :                         : [inbuf] "m" (*inbuf)
     797             :                         );
     798          51 :           if (inlen > 8)
     799             :             {
     800          45 :               asm volatile (/*"pinsrq $1, %[inbuf_tail], %%xmm0\n\t"*/
     801             :                             "movq %[inbuf_tail], %%xmm2\n\t"
     802             :                             "punpcklqdq %%xmm2, %%xmm0\n\t"
     803             :                             "pshufb %[merge_shuf], %%xmm0\n\t"
     804             :                             :
     805          45 :                             : [inbuf_tail] "m" (inbuf[inlen - 8]),
     806             :                               [merge_shuf] "m"
     807          45 :                                 (*crc32_merge9to15_shuf[inlen - 9])
     808             :                             );
     809             :             }
     810             :         }
     811             :       else
     812             :         {
     813          16 :           asm volatile ("movd %[inbuf], %%xmm0\n\t"
     814             :                         "pinsrd $1, %[inbuf_tail], %%xmm0\n\t"
     815             :                         "pshufb %[merge_shuf], %%xmm0\n\t"
     816             :                         :
     817             :                         : [inbuf] "m" (*inbuf),
     818          16 :                           [inbuf_tail] "m" (inbuf[inlen - 4]),
     819             :                           [merge_shuf] "m"
     820          16 :                             (*crc32_merge5to7_shuf[inlen - 5])
     821             :                         );
     822             :         }
     823             : 
     824             :       /* Final fold. */
     825          67 :       asm volatile ("pxor %%xmm1, %%xmm0\n\t"
     826             :                     "pshufb %%xmm7, %%xmm0\n\t"
     827             : 
     828             :                     /* reduce 128-bits to 96-bits */
     829             :                     "movdqa %%xmm0, %%xmm1\n\t"
     830             :                     "pclmulqdq $0x11, %%xmm6, %%xmm0\n\t"
     831             :                     "pslldq $8, %%xmm1\n\t"
     832             :                     "pxor %%xmm1, %%xmm0\n\t" /* bottom 32-bit are zero */
     833             : 
     834             :                     /* reduce 96-bits to 64-bits */
     835             :                     "pshufd $0x30, %%xmm0, %%xmm1\n\t" /* [00][x>>96][00][00] */
     836             :                     "pshufd $0x24, %%xmm0, %%xmm0\n\t" /* [00][xx][xx][00] */
     837             :                     "pclmulqdq $0x01, %[k5], %%xmm1\n\t" /* [00][xx][xx][00] */
     838             :                     "pxor %%xmm1, %%xmm0\n\t" /* top and bottom 32-bit are zero */
     839             : 
     840             :                     /* barrett reduction */
     841             :                     "pshufd $0x01, %%xmm0, %%xmm1\n\t" /* [00][00][00][x>>32] */
     842             :                     "pclmulqdq $0x01, %%xmm5, %%xmm0\n\t" /* [00][xx][xx][xx] */
     843             :                     "psrldq $4, %%xmm0\n\t" /* [00][00][xx][xx] */
     844             :                     "pclmulqdq $0x10, %%xmm5, %%xmm0\n\t"
     845             :                     "pxor %%xmm1, %%xmm0\n\t"
     846             : 
     847             :                     /* store CRC in input endian */
     848             :                     "movd %%xmm0, %%eax\n\t"
     849             :                     "bswapl %%eax\n\t"
     850             :                     "movl %%eax, %[out]\n\t"
     851             :                     : [out] "=m" (*pcrc)
     852             :                     : [k5] "m" (consts->k[5 - 1])
     853             :                     : "eax" );
     854             :     }
     855     1000089 : }
     856             : 
     857             : void
     858     2038108 : _gcry_crc32_intel_pclmul (u32 *pcrc, const byte *inbuf, size_t inlen)
     859             : {
     860     2038108 :   const struct crc32_consts_s *consts = &crc32_consts;
     861             : #if defined(__x86_64__) && defined(__WIN64__)
     862             :   char win64tmp[2 * 16];
     863             : 
     864             :   /* XMM6-XMM7 need to be restored after use. */
     865             :   asm volatile ("movdqu %%xmm6, 0*16(%0)\n\t"
     866             :                 "movdqu %%xmm7, 1*16(%0)\n\t"
     867             :                 :
     868             :                 : "r" (win64tmp)
     869             :                 : "memory");
     870             : #endif
     871             : 
     872     2038108 :   if (!inlen)
     873        1957 :     return;
     874             : 
     875     2036151 :   if (inlen >= 16)
     876       35948 :     crc32_reflected_bulk(pcrc, inbuf, inlen, consts);
     877             :   else
     878     2000203 :     crc32_reflected_less_than_16(pcrc, inbuf, inlen, consts);
     879             : 
     880             : #if defined(__x86_64__) && defined(__WIN64__)
     881             :   /* Restore used registers. */
     882             :   asm volatile("movdqu 0*16(%0), %%xmm6\n\t"
     883             :                "movdqu 1*16(%0), %%xmm7\n\t"
     884             :                :
     885             :                : "r" (win64tmp)
     886             :                : "memory");
     887             : #endif
     888             : }
     889             : 
     890             : void
     891     1018492 : _gcry_crc24rfc2440_intel_pclmul (u32 *pcrc, const byte *inbuf, size_t inlen)
     892             : {
     893     1018492 :   const struct crc32_consts_s *consts = &crc24rfc2440_consts;
     894             : #if defined(__x86_64__) && defined(__WIN64__)
     895             :   char win64tmp[2 * 16];
     896             : 
     897             :   /* XMM6-XMM7 need to be restored after use. */
     898             :   asm volatile ("movdqu %%xmm6, 0*16(%0)\n\t"
     899             :                 "movdqu %%xmm7, 1*16(%0)\n\t"
     900             :                 :
     901             :                 : "r" (win64tmp)
     902             :                 : "memory");
     903             : #endif
     904             : 
     905     1018492 :   if (!inlen)
     906         978 :     return;
     907             : 
     908             :   /* Note: *pcrc in input endian. */
     909             : 
     910     1017514 :   if (inlen >= 16)
     911       17425 :     crc32_bulk(pcrc, inbuf, inlen, consts);
     912             :   else
     913     1000089 :     crc32_less_than_16(pcrc, inbuf, inlen, consts);
     914             : 
     915             : #if defined(__x86_64__) && defined(__WIN64__)
     916             :   /* Restore used registers. */
     917             :   asm volatile("movdqu 0*16(%0), %%xmm6\n\t"
     918             :                "movdqu 1*16(%0), %%xmm7\n\t"
     919             :                :
     920             :                : "r" (win64tmp)
     921             :                : "memory");
     922             : #endif
     923             : }
     924             : 
     925             : #endif /* USE_INTEL_PCLMUL */

Generated by: LCOV version 1.13