Whamcloud - gitweb
ede54c7084d4d8cbfa70753275801bd28b5902c9
[fs/lustre-release.git] / libcfs / libcfs / linux / crc32-pclmul_asm.S
1 /* GPL HEADER START
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 only,
7  * as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License version 2 for more details (a copy is included
13  * in the LICENSE file that accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License
16  * version 2 along with this program; If not, see http://www.gnu.org/licenses
17  *
18  * Please  visit http://www.xyratex.com/contact if you need additional
19  * information or have any questions.
20  *
21  * GPL HEADER END
22  */
23
24 /*
25  * Copyright 2012 Xyratex Technology Limited
26  *
27  * Using hardware provided PCLMULQDQ instruction to accelerate the CRC32
28  * calculation.
29  * CRC32 polynomial:0x04c11db7(BE)/0xEDB88320(LE)
30  * PCLMULQDQ is a new instruction in Intel SSE4.2, the reference can be found
31  * at:
32  * http://www.intel.com/products/processor/manuals/
33  * Intel(R) 64 and IA-32 Architectures Software Developer's Manual
34  * Volume 2B: Instruction Set Reference, N-Z
35  *
36  * Authors:     Gregory Prestas <Gregory_Prestas@us.xyratex.com>
37  *            Alexander Boyko <Alexander_Boyko@xyratex.com>
38  */
39
40 #define __ASSEMBLY__ 1
41 #include "inst.h"
42
43 .align 16
44 /*
45  * [x4*128+32 mod P(x) << 32)]'  << 1   = 0x154442bd4
46  * #define CONSTANT_R1  0x154442bd4LL
47  *
48  * [(x4*128-32 mod P(x) << 32)]' << 1   = 0x1c6e41596
49  * #define CONSTANT_R2  0x1c6e41596LL
50  */
51 .Lconstant_R2R1:
52         .octa 0x00000001c6e415960000000154442bd4
53 /*
54  * [(x128+32 mod P(x) << 32)]'   << 1   = 0x1751997d0
55  * #define CONSTANT_R3  0x1751997d0LL
56  *
57  * [(x128-32 mod P(x) << 32)]'   << 1   = 0x0ccaa009e
58  * #define CONSTANT_R4  0x0ccaa009eLL
59  */
60 .Lconstant_R4R3:
61         .octa 0x00000000ccaa009e00000001751997d0
62 /*
63  * [(x64 mod P(x) << 32)]'       << 1   = 0x163cd6124
64  * #define CONSTANT_R5  0x163cd6124LL
65  */
66 .Lconstant_R5:
67         .octa 0x00000000000000000000000163cd6124
68 .Lconstant_mask32:
69         .octa 0x000000000000000000000000FFFFFFFF
70 /*
71  * #define CRCPOLY_TRUE_LE_FULL 0x1DB710641LL
72  *
73  * Barrett Reduction constant (u64`) = u` = (x**64 / P(x))` = 0x1F7011641LL
74  * #define CONSTANT_RU  0x1F7011641LL
75  */
76 .Lconstant_RUpoly:
77         .octa 0x00000001F701164100000001DB710641
78
79 #define CONSTANT %xmm0
80
81 #ifdef __x86_64__
82 #define BUF     %rdi
83 #define LEN     %rsi
84 #define CRC     %edx
85 #else
86 #define BUF     %eax
87 #define LEN     %edx
88 #define CRC     %ecx
89 #endif
90
91 .text
92 /**
93  *      Calculate crc32
94  *      BUF - buffer (16 bytes aligned)
95  *      LEN - sizeof buffer (16 bytes aligned), LEN should be grater than 63
96  *      CRC - initial crc32
97  *      return %eax crc32
98  *      uint crc32_pclmul_le_16(unsigned char const *buffer,
99  *                           size_t len, uint crc32)
100  */
101 .globl crc32_pclmul_le_16
102 .align 4, 0x90
103 crc32_pclmul_le_16:/* buffer and buffer size are 16 bytes aligned */
104         movdqa  (BUF), %xmm1
105         movdqa  0x10(BUF), %xmm2
106         movdqa  0x20(BUF), %xmm3
107         movdqa  0x30(BUF), %xmm4
108         movd    CRC, CONSTANT
109         pxor    CONSTANT, %xmm1
110         sub     $0x40, LEN
111         add     $0x40, BUF
112 #ifndef __x86_64__
113         /* This is for position independed code(-fPIC) support for 32bit */
114         call    delta
115 delta:
116         pop     %ecx
117 #endif
118         cmp     $0x40, LEN
119         jb      less_64
120
121 #ifdef __x86_64__
122         movdqa .Lconstant_R2R1(%rip), CONSTANT
123 #else
124         movdqa .Lconstant_R2R1 - delta(%ecx), CONSTANT
125 #endif
126
127 loop_64:/*  64 bytes Full cache line folding */
128         prefetchnta    0x40(BUF)
129         movdqa  %xmm1, %xmm5
130         movdqa  %xmm2, %xmm6
131         movdqa  %xmm3, %xmm7
132 #ifdef __x86_64__
133         movdqa  %xmm4, %xmm8
134 #endif
135         PCLMULQDQ 00, CONSTANT, %xmm1
136         PCLMULQDQ 00, CONSTANT, %xmm2
137         PCLMULQDQ 00, CONSTANT, %xmm3
138 #ifdef __x86_64__
139         PCLMULQDQ 00, CONSTANT, %xmm4
140 #endif
141         PCLMULQDQ 0x11, CONSTANT, %xmm5
142         PCLMULQDQ 0x11, CONSTANT, %xmm6
143         PCLMULQDQ 0x11, CONSTANT, %xmm7
144 #ifdef __x86_64__
145         PCLMULQDQ 0x11, CONSTANT, %xmm8
146 #endif
147         pxor    %xmm5, %xmm1
148         pxor    %xmm6, %xmm2
149         pxor    %xmm7, %xmm3
150 #ifdef __x86_64__
151         pxor    %xmm8, %xmm4
152 #else
153         /* xmm8 unsupported for x32 */
154         movdqa  %xmm4, %xmm5
155         PCLMULQDQ 00, CONSTANT, %xmm4
156         PCLMULQDQ 0x11, CONSTANT, %xmm5
157         pxor    %xmm5, %xmm4
158 #endif
159
160         pxor    (BUF), %xmm1
161         pxor    0x10(BUF), %xmm2
162         pxor    0x20(BUF), %xmm3
163         pxor    0x30(BUF), %xmm4
164
165         sub     $0x40, LEN
166         add     $0x40, BUF
167         cmp     $0x40, LEN
168         jge     loop_64
169 less_64:/*  Folding cache line into 128bit */
170 #ifdef __x86_64__
171         movdqa  .Lconstant_R4R3(%rip), CONSTANT
172 #else
173         movdqa  .Lconstant_R4R3 - delta(%ecx), CONSTANT
174 #endif
175         prefetchnta     (BUF)
176
177         movdqa  %xmm1, %xmm5
178         PCLMULQDQ 0x00, CONSTANT, %xmm1
179         PCLMULQDQ 0x11, CONSTANT, %xmm5
180         pxor    %xmm5, %xmm1
181         pxor    %xmm2, %xmm1
182
183         movdqa  %xmm1, %xmm5
184         PCLMULQDQ 0x00, CONSTANT, %xmm1
185         PCLMULQDQ 0x11, CONSTANT, %xmm5
186         pxor    %xmm5, %xmm1
187         pxor    %xmm3, %xmm1
188
189         movdqa  %xmm1, %xmm5
190         PCLMULQDQ 0x00, CONSTANT, %xmm1
191         PCLMULQDQ 0x11, CONSTANT, %xmm5
192         pxor    %xmm5, %xmm1
193         pxor    %xmm4, %xmm1
194
195         cmp     $0x10, LEN
196         jb      fold_64
197 loop_16:/* Folding rest buffer into 128bit */
198         movdqa  %xmm1, %xmm5
199         PCLMULQDQ 0x00, CONSTANT, %xmm1
200         PCLMULQDQ 0x11, CONSTANT, %xmm5
201         pxor    %xmm5, %xmm1
202         pxor    (BUF), %xmm1
203         sub     $0x10, LEN
204         add     $0x10, BUF
205         cmp     $0x10, LEN
206         jge     loop_16
207
208 fold_64:
209         /* perform the last 64 bit fold, also adds 32 zeroes
210          * to the input stream */
211         PCLMULQDQ 0x01, %xmm1, CONSTANT /* R4 * xmm1.low */
212         psrldq  $0x08, %xmm1
213         pxor    CONSTANT, %xmm1
214
215         /* final 32-bit fold */
216         movdqa  %xmm1, %xmm2
217 #ifdef __x86_64__
218         movdqa  .Lconstant_R5(%rip), CONSTANT
219         movdqa  .Lconstant_mask32(%rip), %xmm3
220 #else
221         movdqa  .Lconstant_R5 - delta(%ecx), CONSTANT
222         movdqa  .Lconstant_mask32 - delta(%ecx), %xmm3
223 #endif
224         psrldq  $0x04, %xmm2
225         pand    %xmm3, %xmm1
226         PCLMULQDQ 0x00, CONSTANT, %xmm1
227         pxor    %xmm2, %xmm1
228
229         /* Finish up with the bit-reversed barrett reduction 64 ==> 32 bits */
230 #ifdef __x86_64__
231         movdqa  .Lconstant_RUpoly(%rip), CONSTANT
232 #else
233         movdqa  .Lconstant_RUpoly - delta(%ecx), CONSTANT
234 #endif
235         movdqa  %xmm1, %xmm2
236         pand    %xmm3, %xmm1
237         PCLMULQDQ 0x10, CONSTANT, %xmm1
238         pand    %xmm3, %xmm1
239         PCLMULQDQ 0x00, CONSTANT, %xmm1
240         pxor    %xmm2, %xmm1
241         PEXTRD  0x01, %xmm1, %eax
242
243         ret