octeon_cop2var.h revision 1.2 1 /* $NetBSD: octeon_cop2var.h,v 1.2 2020/06/18 13:52:08 simonb Exp $ */
2
3 /*
4 * TODO:
5 *
6 * - Utilize prefetch.
7 *
8 * - Implement loop in CBC operations. Take an argument of the number of
9 * blocks. Better if prefetch is used too.
10 *
11 * - In AES and DES buffer block loop, merge encrypt / decrypt. Take a
12 * direction argument (int dir, 0 => encrypt, 1 => decrypt) then branch.
13 */
14
15 #ifndef _OCTEON_COP2VAR_H_
16 #define _OCTEON_COP2VAR_H_
17
18 #ifdef __OCTEON_USEUN__
19 #define CNASM_ULD(r, o, b) "uld %["#r"], "#o"(%["#b"]) \n\t"
20 #define CNASM_USD(r, o, b) "usd %["#r"], "#o"(%["#b"]) \n\t"
21 #define CNASM_ULW(r, o, b) "ulw %["#r"], "#o"(%["#b"]) \n\t"
22 #define CNASM_USW(r, o, b) "usw %["#r"], "#o"(%["#b"]) \n\t"
23 #else
24 #define __CNASM_ULH(i, r, o, x, b) i" %["#r"], ("#o" + "#x")(%["#b"]) \n\t"
25 #define __CNASM_ULS(p, r, o, l, h, b) __CNASM_ULH(#p"l", r, o, l, b) \
26 __CNASM_ULH(#p"r", r, o, h, b)
27 #define CNASM_ULD(r, o, b) __CNASM_ULS(ld, r, o, 0, 7, b)
28 #define CNASM_USD(r, o, b) __CNASM_ULS(sd, r, o, 0, 7, b)
29 #define CNASM_ULW(r, o, b) __CNASM_ULS(lw, r, o, 0, 3, b)
30 #define CNASM_USW(r, o, b) __CNASM_ULS(sw, r, o, 0, 3, b)
31 #endif
32
33 #define CNASM_ALD(r, o, b) "ld %["#r"], "#o"(%["#b"]) \n\t"
34 #define CNASM_ASD(r, o, b) "sd %["#r"], "#o"(%["#b"]) \n\t"
35
36 #undef __s
37 #define __s(s) #s /* stringify */
38 #define CNASM_MT2(r, n, o) "dmtc2 %["#r"], ("__s(n)" + "#o") \n\t"
39 #define CNASM_MF2(r, n, o) "dmfc2 %["#r"], ("__s(n)" + "#o") \n\t"
40 #define CNASM_MT2ZERO(n, o) "dmtc2 $0, ("__s(n)" + "#o") \n\t"
41 #define CNASM_MT2ZERO(n, o) "dmtc2 $0, ("__s(n)" + "#o") \n\t"
42
43 #define CNASM_START() ".set push \n\t" \
44 ".set mips64 \n\t" \
45 ".set arch=octeon \n\t" \
46 ".set noreorder \n\t"
47 #define CNASM_END() ".set pop"
48
49 #define __aligned_t uint64_t
50 #define __unaligned_t uint8_t
51
52 /* -------------------------------------------------------------------------- */
53
54 /* AES */
55
56 #define __octeon_cop2_aes_set_key_au_vaddr64(au, AU) \
57 static inline void \
58 octeon_cop2_aes_set_key_##au##_vaddr64(uint64_t key, uint32_t klen) \
59 { \
60 uint64_t tmp0, tmp1, tmp2, tmp3; \
61 \
62 asm volatile ( \
63 CNASM_START() \
64 /* %[cnt] is either 4 (256), 3 (192), or 2 (128) */ \
65 /* Each operation set AESKEYLEN of cop2 also */ \
66 /* >= 64 */ \
67 CNASM_##AU##LD(tmp0, 0, key) \
68 " subu %[cnt], %[cnt], 1 \n" \
69 " beqz %[cnt], 1f \n" \
70 CNASM_MT2(tmp0, CVM_MT_AES_KEY, 0) /* delay slot */ \
71 /* >= 128 */ \
72 CNASM_##AU##LD(tmp1, 8, key) \
73 " subu %[cnt], %[cnt], 1 \n" \
74 " beqz %[cnt], 1f \n" \
75 CNASM_MT2(tmp1, CVM_MT_AES_KEY, 1) /* delay slot */ \
76 /* >= 192 */ \
77 CNASM_##AU##LD(tmp2, 16, key) \
78 " subu %[cnt], %[cnt], 1 \n" \
79 " beqz %[cnt], 1f \n" \
80 CNASM_MT2(tmp2, CVM_MT_AES_KEY, 2) /* delay slot */ \
81 /* >= 256 */ \
82 CNASM_##AU##LD(tmp3, 24, key) \
83 CNASM_MT2(tmp3, CVM_MT_AES_KEY, 3) \
84 /* done */ \
85 "1: \n" \
86 CNASM_END() \
87 : [tmp0] "=&r" (tmp0), \
88 [tmp1] "=&r" (tmp1), \
89 [tmp2] "=&r" (tmp2), \
90 [tmp3] "=&r" (tmp3) \
91 : [key] "d" (key), \
92 [cnt] "d" (klen >> 6)); \
93 }
94
95 #define __octeon_cop2_aes_set_key_au_ptr(au, AU, ptr) \
96 static inline void \
97 octeon_cop2_aes_set_key_##au(ptr key, uint32_t klen) \
98 { \
99 octeon_cop2_aes_set_key_##au##_vaddr64((intptr_t)key, klen); \
100 }
101
102 #define __octeon_cop2_aes_set_key_au(au, AU) \
103 __octeon_cop2_aes_set_key_au_vaddr64(au, AU) \
104 __octeon_cop2_aes_set_key_au_ptr(au, AU, __##au##_t *)
105
106 #define __octeon_cop2_aes_set_key \
107 __octeon_cop2_aes_set_key_au(aligned, A) \
108 __octeon_cop2_aes_set_key_au(unaligned, U)
109
110 __octeon_cop2_aes_set_key
111
112 static inline void
113 octeon_cop2_aes_set_iv_unaligned_vaddr64(uint64_t iv)
114 {
115 uint64_t tmp0, tmp1;
116
117 asm volatile (
118 CNASM_START()
119 /* Store the IV to cop2 */
120 CNASM_ULD(tmp0, 0, iv)
121 CNASM_ULD(tmp1, 8, iv)
122 CNASM_MT2(tmp0, CVM_MT_AES_IV, 0)
123 CNASM_MT2(tmp1, CVM_MT_AES_IV, 1)
124 CNASM_END()
125 : [tmp0] "=&r" (tmp0),
126 [tmp1] "=&r" (tmp1)
127 : [iv] "d" (iv));
128 }
129
130 static inline void
131 octeon_cop2_aes_set_iv_unaligned(uint8_t *iv)
132 {
133 octeon_cop2_aes_set_iv_unaligned_vaddr64((intptr_t)iv);
134 }
135
136 #define __octeon_cop2_aes_ed_16_au_vaddr64(ed, ED, au, AU) \
137 static inline void \
138 octeon_cop2_aes_##ed##_16_##au##_vaddr64(uint64_t d, uint64_t s) \
139 { \
140 uint64_t tmp0, tmp1; \
141 \
142 asm volatile ( \
143 CNASM_START() \
144 CNASM_##AU##LD(tmp0, 0, s) \
145 CNASM_##AU##LD(tmp1, 8, s) \
146 CNASM_MT2(tmp0, CVM_MT_AES_##ED##0, 0) \
147 CNASM_MT2(tmp1, CVM_MT_AES_##ED##1, 0) \
148 CNASM_MF2(tmp0, CVM_MF_AES_RESINP, 0) \
149 CNASM_MF2(tmp1, CVM_MF_AES_RESINP, 1) \
150 CNASM_##AU##SD(tmp0, 0, d) \
151 CNASM_##AU##SD(tmp1, 8, d) \
152 CNASM_END() \
153 : [tmp0] "=&r" (tmp0), \
154 [tmp1] "=&r" (tmp1) \
155 : [d] "d" (d), \
156 [s] "d" (s)); \
157 }
158
159 #define __octeon_cop2_aes_ed_16_au_ptr(ed, ED, au, AU, ptr) \
160 static inline void \
161 octeon_cop2_aes_##ed##_16_##au(ptr d, ptr s) \
162 { \
163 octeon_cop2_aes_##ed##_16_##au##_vaddr64((intptr_t)d, (intptr_t)s); \
164 }
165
166 #define __octeon_cop2_aes_ed_16_au(ed, ED, au, AU) \
167 __octeon_cop2_aes_ed_16_au_vaddr64(ed, ED, au, AU) \
168 __octeon_cop2_aes_ed_16_au_ptr(ed, ED, au, AU, __##au##_t *)
169
170 #define __octeon_cop2_aes_ed_16(ed, ED) \
171 __octeon_cop2_aes_ed_16_au(ed, ED, aligned, A) \
172 __octeon_cop2_aes_ed_16_au(ed, ED, unaligned, U)
173
174 #define __octeon_cop2_aes_16 \
175 __octeon_cop2_aes_ed_16(encrypt, ENC) \
176 __octeon_cop2_aes_ed_16(decrypt, DEC) \
177 __octeon_cop2_aes_ed_16(cbc_encrypt, ENC_CBC) \
178 __octeon_cop2_aes_ed_16(cbc_decrypt, DEC_CBC)
179
180 __octeon_cop2_aes_16
181
182 #define __octeon_cop2_aes_ed_block_au_vaddr64(ed, ED, au, AU) \
183 static inline void \
184 octeon_cop2_aes_##ed##_block_##au##_vaddr64(uint64_t d, uint64_t s, int n) \
185 { \
186 uint64_t tmp0, tmp1; \
187 uint64_t x = d + 16 * n; \
188 \
189 asm volatile ( \
190 CNASM_START() \
191 "1: \n" \
192 CNASM_##AU##LD(tmp0, 0, s) \
193 CNASM_##AU##LD(tmp1, 8, s) \
194 CNASM_MT2(tmp0, CVM_MT_AES_##ED##0, 0) \
195 CNASM_MT2(tmp1, CVM_MT_AES_##ED##1, 0) \
196 CNASM_MF2(tmp0, CVM_MF_AES_RESINP, 0) \
197 CNASM_MF2(tmp1, CVM_MF_AES_RESINP, 1) \
198 CNASM_##AU##SD(tmp0, 0, d) \
199 CNASM_##AU##SD(tmp1, 8, d) \
200 " daddu %[d], %[d], 16 \n" \
201 " bne %[d], %[x], 1b \n" \
202 " daddu %[s], %[s], 16 \n" /* delay slot */ \
203 CNASM_END() \
204 : [d] "=d" (d), \
205 [s] "=d" (s), \
206 [tmp0] "=&r" (tmp0), \
207 [tmp1] "=&r" (tmp1) \
208 : "0" (d), \
209 "1" (s), \
210 [x] "d" (x)); \
211 }
212
213 #define __octeon_cop2_aes_ed_block_au_ptr(ed, ED, au, AU, ptr) \
214 static inline void \
215 octeon_cop2_aes_##ed##_block_##au(ptr d, ptr s, int n) \
216 { \
217 octeon_cop2_aes_##ed##_block_##au##_vaddr64((intptr_t)d, (intptr_t)s, n); \
218 }
219
220 #define __octeon_cop2_aes_ed_block_au(ed, ED, au, AU) \
221 __octeon_cop2_aes_ed_block_au_vaddr64(ed, ED, au, AU) \
222 __octeon_cop2_aes_ed_block_au_ptr(ed, ED, au, AU, __##au##_t *)
223
224 #define __octeon_cop2_aes_ed_block(ed, ED) \
225 __octeon_cop2_aes_ed_block_au(ed, ED, aligned, A) \
226 __octeon_cop2_aes_ed_block_au(ed, ED, unaligned, U)
227
228 #define __octeon_cop2_aes_block \
229 /* __octeon_cop2_aes_ed_block(encrypt, ENC) */ \
230 /* __octeon_cop2_aes_ed_block(decrypt, DEC) */ \
231 __octeon_cop2_aes_ed_block(cbc_encrypt, ENC_CBC) \
232 __octeon_cop2_aes_ed_block(cbc_decrypt, DEC_CBC)
233
234 __octeon_cop2_aes_block
235
236 #define __octeon_cop2_aes_ed_64_au_vaddr64(ed, ED, au, AU) \
237 static inline void \
238 octeon_cop2_aes_##ed##_64_##au##_vaddr64(uint64_t d, uint64_t s) \
239 { \
240 uint64_t tmp0, tmp1, tmp2, tmp3; \
241 \
242 asm volatile ( \
243 CNASM_START() \
244 CNASM_##AU##LD(tmp0, 0, s) \
245 CNASM_##AU##LD(tmp1, 8, s) \
246 CNASM_MT2(tmp0, CVM_MT_AES_##ED##0, 0) \
247 CNASM_MT2(tmp1, CVM_MT_AES_##ED##1, 0) \
248 CNASM_##AU##LD(tmp2, 16, s) \
249 CNASM_##AU##LD(tmp3, 24, s) \
250 CNASM_MF2(tmp0, CVM_MF_AES_RESINP, 0) \
251 CNASM_MF2(tmp1, CVM_MF_AES_RESINP, 1) \
252 CNASM_MT2(tmp2, CVM_MT_AES_##ED##0, 0) \
253 CNASM_MT2(tmp3, CVM_MT_AES_##ED##1, 0) \
254 CNASM_##AU##SD(tmp0, 0, d) \
255 CNASM_##AU##SD(tmp1, 8, d) \
256 CNASM_MF2(tmp2, CVM_MF_AES_RESINP, 0) \
257 CNASM_MF2(tmp3, CVM_MF_AES_RESINP, 1) \
258 CNASM_##AU##SD(tmp2, 16, d) \
259 CNASM_##AU##SD(tmp3, 24, d) \
260 CNASM_##AU##LD(tmp0, 32, s) \
261 CNASM_##AU##LD(tmp1, 40, s) \
262 CNASM_MT2(tmp0, CVM_MT_AES_##ED##0, 0) \
263 CNASM_MT2(tmp1, CVM_MT_AES_##ED##1, 0) \
264 CNASM_##AU##LD(tmp2, 48, s) \
265 CNASM_##AU##LD(tmp3, 56, s) \
266 CNASM_MF2(tmp0, CVM_MF_AES_RESINP, 0) \
267 CNASM_MF2(tmp1, CVM_MF_AES_RESINP, 1) \
268 CNASM_MT2(tmp2, CVM_MT_AES_##ED##0, 0) \
269 CNASM_MT2(tmp3, CVM_MT_AES_##ED##1, 0) \
270 CNASM_##AU##SD(tmp0, 32, d) \
271 CNASM_##AU##SD(tmp1, 40, d) \
272 CNASM_MF2(tmp2, CVM_MF_AES_RESINP, 0) \
273 CNASM_MF2(tmp3, CVM_MF_AES_RESINP, 1) \
274 CNASM_##AU##SD(tmp2, 48, d) \
275 CNASM_##AU##SD(tmp3, 56, d) \
276 CNASM_END() \
277 : [tmp0] "=&r" (tmp0), \
278 [tmp1] "=&r" (tmp1), \
279 [tmp2] "=&r" (tmp2), \
280 [tmp3] "=&r" (tmp3) \
281 : [d] "d" (d), \
282 [s] "d" (s)); \
283 }
284
285 #define __octeon_cop2_aes_ed_64_au_ptr(ed, ED, au, AU, ptr) \
286 static inline void \
287 octeon_cop2_aes_##ed##_64_##au(ptr d, ptr s) \
288 { \
289 octeon_cop2_aes_##ed##_64_##au##_vaddr64((intptr_t)d, (intptr_t)s); \
290 }
291
292 #define __octeon_cop2_aes_ed_64_au(ed, ED, au, AU) \
293 __octeon_cop2_aes_ed_64_au_vaddr64(ed, ED, au, AU) \
294 __octeon_cop2_aes_ed_64_au_ptr(ed, ED, au, AU, __##au##_t *)
295
296 #define __octeon_cop2_aes_ed_64(ed, ED) \
297 __octeon_cop2_aes_ed_64_au(ed, ED, aligned, A) \
298 __octeon_cop2_aes_ed_64_au(ed, ED, unaligned, U)
299
300 #define __octeon_cop2_aes_64 \
301 /* __octeon_cop2_aes_ed_64(encrypt, ENC) */ \
302 /* __octeon_cop2_aes_ed_64(decrypt, DEC) */ \
303 __octeon_cop2_aes_ed_64(cbc_encrypt, ENC_CBC) \
304 __octeon_cop2_aes_ed_64(cbc_decrypt, DEC_CBC)
305
306 __octeon_cop2_aes_64
307
308 /* -------------------------------------------------------------------------- */
309
310 /* DES */
311
312 static inline void
313 octeon_cop2_des_set_key_unaligned_vaddr64(uint64_t k1, uint64_t k2, uint64_t k3)
314 {
315 uint64_t tmp0, tmp1, tmp2;
316
317 asm volatile (
318 CNASM_START()
319 /* Set key */
320 CNASM_ULD(tmp0, 0, k1)
321 CNASM_ULD(tmp1, 0, k2)
322 CNASM_ULD(tmp2, 0, k3)
323 CNASM_MT2(tmp0, CVM_MT_3DES_KEY, 0)
324 CNASM_MT2(tmp1, CVM_MT_3DES_KEY, 1)
325 CNASM_MT2(tmp2, CVM_MT_3DES_KEY, 2)
326 CNASM_END()
327 : [tmp0] "=&r" (tmp0),
328 [tmp1] "=&r" (tmp1),
329 [tmp2] "=&r" (tmp2)
330 : [k1] "d" (k1),
331 [k2] "d" (k2),
332 [k3] "d" (k3));
333 }
334
335 static inline void
336 octeon_cop2_des_set_key_unaligned(uint64_t *k1, uint64_t *k2, uint64_t *k3)
337 {
338 octeon_cop2_des_set_key_unaligned_vaddr64((intptr_t)k1, (intptr_t)k2, (intptr_t)k3);
339 }
340
341 static inline void
342 octeon_cop2_des_set_iv_unaligned_vaddr64(uint64_t iv)
343 {
344 uint64_t tmp0;
345
346 asm volatile (
347 CNASM_START()
348 /* Load IV to a register */
349 CNASM_ULD(tmp0, 0, iv)
350 /* Store the IV to cop2 */
351 CNASM_MT2(tmp0, CVM_MT_3DES_IV, 0)
352 CNASM_END()
353 : [tmp0] "=&r" (tmp0)
354 : [iv] "d" (iv));
355 }
356
357 static inline void
358 octeon_cop2_des_set_iv_unaligned(uint8_t *iv)
359 {
360 octeon_cop2_des_set_iv_unaligned_vaddr64((intptr_t)iv);
361 }
362
363 #define __octeon_cop2_des_ed_8_au_vaddr64(ed, ED, au, AU) \
364 static inline void \
365 octeon_cop2_des_##ed##_8_##au##_vaddr64(uint64_t d, uint64_t s) \
366 { \
367 uint64_t tmp0; \
368 \
369 asm volatile ( \
370 CNASM_START() \
371 CNASM_##AU##LD(tmp0, 0, s) \
372 CNASM_MT2(tmp0, CVM_MT_3DES_##ED, 0) \
373 CNASM_MF2(tmp0, CVM_MF_3DES_RESULT, 0) \
374 CNASM_##AU##SD(tmp0, 0, s) \
375 CNASM_END() \
376 : [tmp0] "=&r" (tmp0) \
377 : [d] "d" (d), \
378 [s] "d" (s)); \
379 }
380
381 #define __octeon_cop2_des_ed_8_au_ptr(ed, ED, au, AU, ptr) \
382 static inline void \
383 octeon_cop2_des_##ed##_8_##au(ptr d, ptr s) \
384 { \
385 octeon_cop2_des_##ed##_8_##au##_vaddr64((intptr_t)d, (intptr_t)s); \
386 }
387
388 #define __octeon_cop2_des_ed_8_au(ed, ED, au, AU) \
389 __octeon_cop2_des_ed_8_au_vaddr64(ed, ED, au, AU) \
390 __octeon_cop2_des_ed_8_au_ptr(ed, ED, au, AU, __##au##_t *)
391
392 #define __octeon_cop2_des_ed_8(ed, ED) \
393 __octeon_cop2_des_ed_8_au(ed, ED, aligned, A) \
394 __octeon_cop2_des_ed_8_au(ed, ED, unaligned, U)
395
396 #define __octeon_cop2_des_8 \
397 __octeon_cop2_des_ed_8(encrypt, ENC) \
398 __octeon_cop2_des_ed_8(decrypt, DEC) \
399 __octeon_cop2_des_ed_8(cbc_encrypt, ENC_CBC) \
400 __octeon_cop2_des_ed_8(cbc_decrypt, DEC_CBC)
401
402 __octeon_cop2_des_8
403
404 #define __octeon_cop2_des_ed_block_au_vaddr64(ed, ED, au, AU) \
405 static inline void \
406 octeon_cop2_des_##ed##_block_##au##_vaddr64(uint64_t d, uint64_t s, int n) \
407 { \
408 uint64_t tmp0; \
409 uint64_t x = d + 8 * n; \
410 \
411 asm volatile ( \
412 CNASM_START() \
413 "1: \n" \
414 CNASM_##AU##LD(tmp0, 0, s) \
415 CNASM_MT2(tmp0, CVM_MT_3DES_##ED, 0) \
416 CNASM_MF2(tmp0, CVM_MF_3DES_RESULT, 0) \
417 CNASM_##AU##SD(tmp0, 0, d) \
418 " daddu %[d], %[d], 8 \n" \
419 " bne %[d], %[x], 1b \n" \
420 " daddu %[s], %[s], 8 \n" \
421 CNASM_END() \
422 : [d] "=d" (d), \
423 [s] "=d" (s), \
424 [tmp0] "=&r" (tmp0) \
425 : "0" (d), \
426 "1" (s), \
427 [x] "d" (x)); \
428 }
429
430 #define __octeon_cop2_des_ed_block_au_ptr(ed, ED, au, AU, ptr) \
431 static inline void \
432 octeon_cop2_des_##ed##_block_##au(ptr d, ptr s, int n) \
433 { \
434 octeon_cop2_des_##ed##_block_##au##_vaddr64((intptr_t)d, (intptr_t)s, n); \
435 }
436
437 #define __octeon_cop2_des_ed_block_au(ed, ED, au, AU) \
438 __octeon_cop2_des_ed_block_au_vaddr64(ed, ED, au, AU) \
439 __octeon_cop2_des_ed_block_au_ptr(ed, ED, au, AU, __##au##_t *)
440
441 #define __octeon_cop2_des_ed_block(ed, ED) \
442 __octeon_cop2_des_ed_block_au(ed, ED, aligned, A) \
443 __octeon_cop2_des_ed_block_au(ed, ED, unaligned, U)
444
445 #define __octeon_cop2_des_block \
446 /* __octeon_cop2_des_ed_block(encrypt, ENC) */ \
447 /* __octeon_cop2_des_ed_block(decrypt, DEC) */ \
448 __octeon_cop2_des_ed_block(cbc_encrypt, ENC_CBC) \
449 __octeon_cop2_des_ed_block(cbc_decrypt, DEC_CBC)
450
451 __octeon_cop2_des_block
452
453 #define __octeon_cop2_des_ed_64_au_vaddr64(ed, ED, au, AU) \
454 static inline void \
455 octeon_cop2_des_##ed##_64_##au##_vaddr64(uint64_t d, uint64_t s) \
456 { \
457 uint64_t tmp0, tmp1, tmp2, tmp3; \
458 \
459 asm volatile ( \
460 CNASM_START() \
461 CNASM_##AU##LD(tmp0, 0, s) \
462 CNASM_##AU##LD(tmp1, 8, s) \
463 CNASM_MT2(tmp0, CVM_MT_3DES_##ED, 0) \
464 CNASM_##AU##LD(tmp2, 16, s) \
465 CNASM_MF2(tmp0, CVM_MF_3DES_RESULT, 0) \
466 CNASM_MT2(tmp1, CVM_MT_3DES_##ED, 0) \
467 CNASM_##AU##LD(tmp3, 24, s) \
468 CNASM_MF2(tmp1, CVM_MF_3DES_RESULT, 0) \
469 CNASM_MT2(tmp2, CVM_MT_3DES_##ED, 0) \
470 CNASM_##AU##SD(tmp0, 0, d) \
471 CNASM_MF2(tmp2, CVM_MF_3DES_RESULT, 0) \
472 CNASM_MT2(tmp3, CVM_MT_3DES_##ED, 0) \
473 CNASM_##AU##SD(tmp1, 8, d) \
474 CNASM_MF2(tmp3, CVM_MF_3DES_RESULT, 0) \
475 CNASM_##AU##SD(tmp2, 16, d) \
476 CNASM_##AU##SD(tmp3, 24, d) \
477 CNASM_##AU##LD(tmp0, 32, s) \
478 CNASM_##AU##LD(tmp1, 40, s) \
479 CNASM_MT2(tmp0, CVM_MT_3DES_##ED, 0) \
480 CNASM_##AU##LD(tmp2, 48, s) \
481 CNASM_MF2(tmp0, CVM_MF_3DES_RESULT, 0) \
482 CNASM_MT2(tmp1, CVM_MT_3DES_##ED, 0) \
483 CNASM_##AU##LD(tmp3, 56, s) \
484 CNASM_MF2(tmp1, CVM_MF_3DES_RESULT, 0) \
485 CNASM_MT2(tmp2, CVM_MT_3DES_##ED, 0) \
486 CNASM_##AU##SD(tmp0, 32, d) \
487 CNASM_MF2(tmp2, CVM_MF_3DES_RESULT, 0) \
488 CNASM_MT2(tmp3, CVM_MT_3DES_##ED, 0) \
489 CNASM_##AU##SD(tmp1, 40, d) \
490 CNASM_MF2(tmp3, CVM_MF_3DES_RESULT, 0) \
491 CNASM_##AU##SD(tmp2, 48, d) \
492 CNASM_##AU##SD(tmp3, 56, d) \
493 CNASM_END() \
494 : [tmp0] "=&r" (tmp0), \
495 [tmp1] "=&r" (tmp1), \
496 [tmp2] "=&r" (tmp2), \
497 [tmp3] "=&r" (tmp3) \
498 : [d] "d" (d), \
499 [s] "d" (s)); \
500 }
501
502 #define __octeon_cop2_des_ed_64_au_ptr(ed, ED, au, AU, ptr) \
503 static inline void \
504 octeon_cop2_des_##ed##_64_##au(ptr d, ptr s) \
505 { \
506 octeon_cop2_des_##ed##_64_##au##_vaddr64((intptr_t)d, (intptr_t)s); \
507 }
508
509 #define __octeon_cop2_des_ed_64_au(ed, ED, au, AU) \
510 __octeon_cop2_des_ed_64_au_vaddr64(ed, ED, au, AU) \
511 __octeon_cop2_des_ed_64_au_ptr(ed, ED, au, AU, __##au##_t *)
512
513 #define __octeon_cop2_des_ed_64(ed, ED) \
514 __octeon_cop2_des_ed_64_au(ed, ED, aligned, A) \
515 __octeon_cop2_des_ed_64_au(ed, ED, unaligned, U)
516
517 #define __octeon_cop2_des_64 \
518 /* __octeon_cop2_des_ed_64(encrypt, ENC) */ \
519 /* __octeon_cop2_des_ed_64(decrypt, DEC) */ \
520 __octeon_cop2_des_ed_64(cbc_encrypt, ENC_CBC) \
521 __octeon_cop2_des_ed_64(cbc_decrypt, DEC_CBC)
522
523 __octeon_cop2_des_64
524
525 /* -------------------------------------------------------------------------- */
526
527 /* MD5 */
528
529 static inline void
530 octeon_cop2_md5_set_iv_unaligned_vaddr64(uint64_t iv)
531 {
532 uint64_t tmp0, tmp1;
533
534 asm volatile (
535 CNASM_START()
536 /* Load IV from context */
537 CNASM_ULD(tmp0, 0, iv)
538 CNASM_ULD(tmp1, 8, iv)
539 CNASM_MT2(tmp0, CVM_MT_HSH_IV, 0)
540 CNASM_MT2(tmp1, CVM_MT_HSH_IV, 1)
541 CNASM_MT2ZERO( CVM_MT_HSH_IV, 2)
542 CNASM_MT2ZERO( CVM_MT_HSH_IV, 3)
543 CNASM_END()
544 : [tmp0] "=&r" (tmp0),
545 [tmp1] "=&r" (tmp1)
546 : [iv] "d" (iv));
547 }
548
549 static inline void
550 octeon_cop2_md5_set_iv_unaligned(uint64_t *iv)
551 {
552 octeon_cop2_md5_set_iv_unaligned_vaddr64((intptr_t)iv);
553 }
554
555 static inline void
556 octeon_cop2_md5_get_iv_unaligned_vaddr64(uint64_t iv)
557 {
558 uint64_t tmp0, tmp1;
559
560 asm volatile (
561 CNASM_START()
562 /* Store IV to context */
563 CNASM_MF2(tmp0, CVM_MF_HSH_IV, 0)
564 CNASM_MF2(tmp1, CVM_MF_HSH_IV, 1)
565 CNASM_USD(tmp0, 0, iv)
566 CNASM_USD(tmp1, 8, iv)
567 CNASM_END()
568 : [tmp0] "=&r" (tmp0),
569 [tmp1] "=&r" (tmp1)
570 : [iv] "d" (iv));
571 }
572
573 static inline void
574 octeon_cop2_md5_get_iv_unaligned(uint64_t *iv)
575 {
576 octeon_cop2_md5_get_iv_unaligned_vaddr64((intptr_t)iv);
577 }
578
579 static inline void
580 octeon_cop2_md5_update_unaligned_vaddr64(uint64_t src)
581 {
582 uint64_t tmp0, tmp1, tmp2, tmp3;
583
584 asm volatile (
585 CNASM_START()
586 /* Update HASH */
587 CNASM_ULD(tmp0, 0, src)
588 CNASM_ULD(tmp1, 8, src)
589 CNASM_ULD(tmp2, 16, src)
590 CNASM_ULD(tmp3, 24, src)
591 CNASM_MT2(tmp0, CVM_MT_HSH_DAT, 0)
592 CNASM_MT2(tmp1, CVM_MT_HSH_DAT, 1)
593 CNASM_MT2(tmp2, CVM_MT_HSH_DAT, 2)
594 CNASM_MT2(tmp3, CVM_MT_HSH_DAT, 3)
595 CNASM_ULD(tmp0, 32, src)
596 CNASM_ULD(tmp1, 40, src)
597 CNASM_ULD(tmp2, 48, src)
598 CNASM_ULD(tmp3, 56, src)
599 CNASM_MT2(tmp0, CVM_MT_HSH_DAT, 4)
600 CNASM_MT2(tmp1, CVM_MT_HSH_DAT, 5)
601 CNASM_MT2(tmp2, CVM_MT_HSH_DAT, 6)
602 CNASM_MT2(tmp3, CVM_MT_HSH_STANDARD5, 0)
603 CNASM_END()
604 : [tmp0] "=&r" (tmp0),
605 [tmp1] "=&r" (tmp1),
606 [tmp2] "=&r" (tmp2),
607 [tmp3] "=&r" (tmp3)
608 : [src] "d" (src));
609 }
610
611 static inline void
612 octeon_cop2_md5_update_unaligned(uint64_t *src)
613 {
614 octeon_cop2_md5_update_unaligned_vaddr64((intptr_t)src);
615 }
616
617 /* -------------------------------------------------------------------------- */
618
619 /* SHA1 */
620
621 static inline void
622 octeon_cop2_sha1_set_iv_unaligned_vaddr64(uint64_t iv)
623 {
624 uint64_t tmp0, tmp1, tmp2;
625
626 asm volatile (
627 CNASM_START()
628 /* Load IV from context */
629 CNASM_ULD(tmp0, 0, iv)
630 CNASM_ULD(tmp1, 8, iv)
631 CNASM_ULW(tmp2, 16, iv)
632 "dsll %[tmp2], %[tmp2], 32 \n\t"
633 CNASM_MT2(tmp0, CVM_MT_HSH_IV, 0)
634 CNASM_MT2(tmp1, CVM_MT_HSH_IV, 1)
635 CNASM_MT2(tmp2, CVM_MT_HSH_IV, 2)
636 CNASM_MT2ZERO( CVM_MT_HSH_IV, 3)
637 CNASM_END()
638 : [tmp0] "=&r" (tmp0),
639 [tmp1] "=&r" (tmp1),
640 [tmp2] "=&r" (tmp2)
641 : [iv] "d" (iv));
642 }
643
644 static inline void
645 octeon_cop2_sha1_set_iv_unaligned(uint8_t *iv)
646 {
647 octeon_cop2_sha1_set_iv_unaligned_vaddr64((intptr_t)iv);
648 }
649
650 static inline void
651 octeon_cop2_sha1_get_iv_unaligned_vaddr64(uint64_t iv)
652 {
653 uint64_t tmp0, tmp1, tmp2;
654
655 asm volatile (
656 CNASM_START()
657 /* Store IV to context */
658 CNASM_MF2(tmp0, CVM_MF_HSH_IV, 0)
659 CNASM_MF2(tmp1, CVM_MF_HSH_IV, 1)
660 CNASM_MF2(tmp2, CVM_MF_HSH_IV, 2)
661 CNASM_USD(tmp0, 0, iv)
662 CNASM_USD(tmp1, 8, iv)
663 "dsrl %[tmp2], %[tmp2], 32 \n\t"
664 CNASM_USW(tmp2, 16, iv)
665 CNASM_END()
666 : [tmp0] "=&r" (tmp0),
667 [tmp1] "=&r" (tmp1),
668 [tmp2] "=&r" (tmp2)
669 : [iv] "d" (iv));
670 }
671
672 static inline void
673 octeon_cop2_sha1_get_iv_unaligned(uint8_t *iv)
674 {
675 octeon_cop2_sha1_get_iv_unaligned_vaddr64((intptr_t)iv);
676 }
677
678 static inline void
679 octeon_cop2_sha1_update_unaligned_vaddr64(uint64_t src)
680 {
681 uint64_t tmp0, tmp1, tmp2, tmp3;
682
683 asm volatile (
684 CNASM_START()
685 /* Update HASH */
686 CNASM_ULD(tmp0, 0, src)
687 CNASM_ULD(tmp1, 8, src)
688 CNASM_ULD(tmp2, 16, src)
689 CNASM_ULD(tmp3, 24, src)
690 CNASM_MT2(tmp0, CVM_MT_HSH_DAT, 0)
691 CNASM_MT2(tmp1, CVM_MT_HSH_DAT, 1)
692 CNASM_MT2(tmp2, CVM_MT_HSH_DAT, 2)
693 CNASM_MT2(tmp3, CVM_MT_HSH_DAT, 3)
694 CNASM_ULD(tmp0, 32, src)
695 CNASM_ULD(tmp1, 40, src)
696 CNASM_ULD(tmp2, 48, src)
697 CNASM_ULD(tmp3, 56, src)
698 CNASM_MT2(tmp0, CVM_MT_HSH_DAT, 4)
699 CNASM_MT2(tmp1, CVM_MT_HSH_DAT, 5)
700 CNASM_MT2(tmp2, CVM_MT_HSH_DAT, 6)
701 CNASM_MT2(tmp3, CVM_MT_HSH_STARTSHA, 0)
702 CNASM_END()
703 : [tmp0] "=&r" (tmp0),
704 [tmp1] "=&r" (tmp1),
705 [tmp2] "=&r" (tmp2),
706 [tmp3] "=&r" (tmp3)
707 : [src] "d" (src));
708 }
709
710 static inline void
711 octeon_cop2_sha1_update_unaligned(uint8_t *src)
712 {
713 octeon_cop2_sha1_update_unaligned_vaddr64((intptr_t)src);
714 }
715
716 /* -------------------------------------------------------------------------- */
717
718 /* SHA256 */
719
720 static inline void
721 octeon_cop2_sha256_set_iv_unaligned_vaddr64(uint64_t iv)
722 {
723 uint64_t tmp0, tmp1, tmp2, tmp3;
724
725 asm volatile (
726 CNASM_START()
727 /* Load IV from context */
728 CNASM_ULD(tmp0, 0, iv)
729 CNASM_ULD(tmp1, 8, iv)
730 CNASM_ULD(tmp2, 16, iv)
731 CNASM_ULD(tmp3, 24, iv)
732 CNASM_MT2(tmp0, CVM_MT_HSH_IV, 0)
733 CNASM_MT2(tmp1, CVM_MT_HSH_IV, 1)
734 CNASM_MT2(tmp2, CVM_MT_HSH_IV, 2)
735 CNASM_MT2(tmp3, CVM_MT_HSH_IV, 3)
736 CNASM_END()
737 : [tmp0] "=&r" (tmp0),
738 [tmp1] "=&r" (tmp1),
739 [tmp2] "=&r" (tmp2),
740 [tmp3] "=&r" (tmp3)
741 : [iv] "d" (iv));
742 }
743
744 static inline void
745 octeon_cop2_sha256_set_iv_unaligned(uint8_t *iv)
746 {
747 octeon_cop2_sha256_set_iv_unaligned_vaddr64((intptr_t)iv);
748 }
749
750 static inline void
751 octeon_cop2_sha256_get_iv_unaligned_vaddr64(uint64_t iv)
752 {
753 uint64_t tmp0, tmp1, tmp2, tmp3;
754
755 asm volatile (
756 CNASM_START()
757 /* Store IV to context */
758 CNASM_MF2(tmp0, CVM_MF_HSH_IV, 0)
759 CNASM_MF2(tmp1, CVM_MF_HSH_IV, 1)
760 CNASM_MF2(tmp2, CVM_MF_HSH_IV, 2)
761 CNASM_MF2(tmp3, CVM_MF_HSH_IV, 3)
762 CNASM_USD(tmp0, 0, iv)
763 CNASM_USD(tmp1, 8, iv)
764 CNASM_USD(tmp2, 16, iv)
765 CNASM_USD(tmp3, 24, iv)
766 CNASM_END()
767 : [tmp0] "=&r" (tmp0),
768 [tmp1] "=&r" (tmp1),
769 [tmp2] "=&r" (tmp2),
770 [tmp3] "=&r" (tmp3)
771 : [iv] "d" (iv));
772 }
773
774 static inline void
775 octeon_cop2_sha256_get_iv_unaligned(uint8_t *iv)
776 {
777 octeon_cop2_sha256_get_iv_unaligned_vaddr64((intptr_t)iv);
778 }
779
780 static inline void
781 octeon_cop2_sha256_update_unaligned_vaddr64(uint64_t src)
782 {
783 uint64_t tmp0, tmp1, tmp2, tmp3;
784
785 asm volatile (
786 CNASM_START()
787 /* Update HASH */
788 CNASM_ULD(tmp0, 0, src)
789 CNASM_ULD(tmp1, 8, src)
790 CNASM_ULD(tmp2, 16, src)
791 CNASM_ULD(tmp3, 24, src)
792 CNASM_MT2(tmp0, CVM_MT_HSH_DAT, 0)
793 CNASM_MT2(tmp1, CVM_MT_HSH_DAT, 1)
794 CNASM_MT2(tmp2, CVM_MT_HSH_DAT, 2)
795 CNASM_MT2(tmp3, CVM_MT_HSH_DAT, 3)
796 CNASM_ULD(tmp0, 32, src)
797 CNASM_ULD(tmp1, 40, src)
798 CNASM_ULD(tmp2, 48, src)
799 CNASM_ULD(tmp3, 56, src)
800 CNASM_MT2(tmp0, CVM_MT_HSH_DAT, 4)
801 CNASM_MT2(tmp1, CVM_MT_HSH_DAT, 5)
802 CNASM_MT2(tmp2, CVM_MT_HSH_DAT, 6)
803 CNASM_MT2(tmp3, CVM_MT_HSH_STARTSHA256, 0)
804 CNASM_END()
805 : [tmp0] "=&r" (tmp0),
806 [tmp1] "=&r" (tmp1),
807 [tmp2] "=&r" (tmp2),
808 [tmp3] "=&r" (tmp3)
809 : [src] "d" (src));
810 }
811
812 static inline void
813 octeon_cop2_sha256_update_unaligned(uint8_t *src)
814 {
815 octeon_cop2_sha256_update_unaligned_vaddr64((intptr_t)src);
816 }
817
818 /* -------------------------------------------------------------------------- */
819
820 /* SHA512 */
821
822 static inline void
823 octeon_cop2_sha512_set_iv_unaligned_vaddr64(uint64_t iv)
824 {
825 uint64_t tmp0, tmp1, tmp2, tmp3;
826
827 asm volatile (
828 CNASM_START()
829 /* Load IV from context */
830 CNASM_ULD(tmp0, 0, iv)
831 CNASM_ULD(tmp1, 8, iv)
832 CNASM_ULD(tmp2, 16, iv)
833 CNASM_ULD(tmp3, 24, iv)
834 CNASM_MT2(tmp0, CVM_MT_HSH_IVW, 0)
835 CNASM_MT2(tmp1, CVM_MT_HSH_IVW, 1)
836 CNASM_MT2(tmp2, CVM_MT_HSH_IVW, 2)
837 CNASM_MT2(tmp3, CVM_MT_HSH_IVW, 3)
838 CNASM_ULD(tmp0, 32, iv)
839 CNASM_ULD(tmp1, 40, iv)
840 CNASM_ULD(tmp2, 48, iv)
841 CNASM_ULD(tmp3, 56, iv)
842 CNASM_MT2(tmp0, CVM_MT_HSH_IVW, 4)
843 CNASM_MT2(tmp1, CVM_MT_HSH_IVW, 5)
844 CNASM_MT2(tmp2, CVM_MT_HSH_IVW, 6)
845 CNASM_MT2(tmp3, CVM_MT_HSH_IVW, 7)
846 CNASM_END()
847 : [tmp0] "=&r" (tmp0),
848 [tmp1] "=&r" (tmp1),
849 [tmp2] "=&r" (tmp2),
850 [tmp3] "=&r" (tmp3)
851 : [iv] "d" (iv));
852 }
853
854 static inline void
855 octeon_cop2_sha512_set_iv_unaligned(uint8_t *iv)
856 {
857 octeon_cop2_sha512_set_iv_unaligned_vaddr64((intptr_t)iv);
858 }
859
860 static inline void
861 octeon_cop2_sha512_get_iv_unaligned_vaddr64(uint64_t iv)
862 {
863 uint64_t tmp0, tmp1, tmp2, tmp3;
864
865 asm volatile (
866 CNASM_START()
867 /* Store IV to context */
868 CNASM_MF2(tmp0, CVM_MF_HSH_IVW, 0)
869 CNASM_MF2(tmp1, CVM_MF_HSH_IVW, 1)
870 CNASM_MF2(tmp2, CVM_MF_HSH_IVW, 2)
871 CNASM_MF2(tmp3, CVM_MF_HSH_IVW, 3)
872 CNASM_USD(tmp0, 0, iv)
873 CNASM_USD(tmp1, 8, iv)
874 CNASM_USD(tmp2, 16, iv)
875 CNASM_USD(tmp3, 24, iv)
876 CNASM_MF2(tmp0, CVM_MF_HSH_IVW, 4)
877 CNASM_MF2(tmp1, CVM_MF_HSH_IVW, 5)
878 CNASM_MF2(tmp2, CVM_MF_HSH_IVW, 6)
879 CNASM_MF2(tmp3, CVM_MF_HSH_IVW, 7)
880 CNASM_USD(tmp0, 32, iv)
881 CNASM_USD(tmp1, 40, iv)
882 CNASM_USD(tmp2, 48, iv)
883 CNASM_USD(tmp3, 56, iv)
884 CNASM_END()
885 : [tmp0] "=&r" (tmp0),
886 [tmp1] "=&r" (tmp1),
887 [tmp2] "=&r" (tmp2),
888 [tmp3] "=&r" (tmp3)
889 : [iv] "d" (iv));
890 }
891
892 static inline void
893 octeon_cop2_sha512_get_iv_unaligned(uint8_t *iv)
894 {
895 octeon_cop2_sha512_get_iv_unaligned_vaddr64((intptr_t)iv);
896 }
897
898 static inline void
899 octeon_cop2_sha512_update_unaligned_vaddr64(uint64_t src)
900 {
901 uint64_t tmp0, tmp1, tmp2, tmp3;
902
903 asm volatile (
904 CNASM_START()
905 /* Update HASH */
906 CNASM_ULD(tmp0, 0, src)
907 CNASM_ULD(tmp1, 8, src)
908 CNASM_ULD(tmp2, 16, src)
909 CNASM_ULD(tmp3, 24, src)
910 CNASM_MT2(tmp0, CVM_MT_HSH_DATW, 0)
911 CNASM_MT2(tmp1, CVM_MT_HSH_DATW, 1)
912 CNASM_MT2(tmp2, CVM_MT_HSH_DATW, 2)
913 CNASM_MT2(tmp3, CVM_MT_HSH_DATW, 3)
914 CNASM_ULD(tmp0, 32, src)
915 CNASM_ULD(tmp1, 40, src)
916 CNASM_ULD(tmp2, 48, src)
917 CNASM_ULD(tmp3, 56, src)
918 CNASM_MT2(tmp0, CVM_MT_HSH_DATW, 4)
919 CNASM_MT2(tmp1, CVM_MT_HSH_DATW, 5)
920 CNASM_MT2(tmp2, CVM_MT_HSH_DATW, 6)
921 CNASM_MT2(tmp3, CVM_MT_HSH_DATW, 7)
922 CNASM_ULD(tmp0, 64, src)
923 CNASM_ULD(tmp1, 72, src)
924 CNASM_ULD(tmp2, 80, src)
925 CNASM_ULD(tmp3, 88, src)
926 CNASM_MT2(tmp0, CVM_MT_HSH_DATW, 8)
927 CNASM_MT2(tmp1, CVM_MT_HSH_DATW, 9)
928 CNASM_MT2(tmp2, CVM_MT_HSH_DATW, 10)
929 CNASM_MT2(tmp3, CVM_MT_HSH_DATW, 11)
930 CNASM_ULD(tmp0, 96, src)
931 CNASM_ULD(tmp1, 104, src)
932 CNASM_ULD(tmp2, 112, src)
933 CNASM_ULD(tmp3, 120, src)
934 CNASM_MT2(tmp0, CVM_MT_HSH_DATW, 12)
935 CNASM_MT2(tmp1, CVM_MT_HSH_DATW, 13)
936 CNASM_MT2(tmp2, CVM_MT_HSH_DATW, 14)
937 CNASM_MT2(tmp3, CVM_MT_HSH_STARTSHA512, 0)
938 CNASM_END()
939 : [tmp0] "=&r" (tmp0),
940 [tmp1] "=&r" (tmp1),
941 [tmp2] "=&r" (tmp2),
942 [tmp3] "=&r" (tmp3)
943 : [src] "d" (src));
944 }
945
946 static inline void
947 octeon_cop2_sha512_update_unaligned(uint8_t *src)
948 {
949 octeon_cop2_sha512_update_unaligned_vaddr64((intptr_t)src);
950 }
951
952 /* -------------------------------------------------------------------------- */
953
954 /* CRC */
955
956 /* XXX */
957
958 #ifdef notyet
959 static inline void
960 octeon_cop2_crc_polynomial(val)
961 {
962 __asm __volatile (
963 CNASM_START()
964 " dmtc2 %[val], 0x4200"
965 CNASM_END()
966 :
967 : [val] "d" (val))
968 }
969
970 #define CVMX_MT_CRC_IV(val) \
971 __asm __volatile (__PUSH "dmtc2 %0,0x0201" __POP :: "d"(val))
972 #define CVMX_MT_CRC_BYTE_REFLECT(val) \
973 __asm __volatile (__PUSH "dmtc2 %0,0x0214" __POP :: "d"(val))
974 #define CVMX_MT_CRC_HALF_REFLECT(val) \
975 __asm __volatile (__PUSH "dmtc2 %0,0x0215" __POP :: "d"(val))
976 #define CVMX_MT_CRC_DWORD_REFLECT(val) \
977 __asm __volatile (__PUSH "dmtc2 %0,0x1217" __POP :: "d"(val))
978 #define CVMX_MF_CRC_IV_REFLECT(val) \
979 __asm __volatile (__PUSH "dmfc2 %0,0x0203" __POP : "=d"(val))
980
981 static inline void
982 octeon_cop2_crc_reflect(XXX)
983 {
984 __asm __volatile (
985 CNASM_START()
986 " and %[val], %[len], 15 \n"
987 " beq %[val], %[len], 2f \n"
988 " subu %[tmp], %[len], %[val] \n"
989 " move %[len], %[val] \n"
990 " addu %[tmp], %[buf] \n"
991
992 " .align 3 \n"
993 "1: \n"
994 CNASM_ULD(val, 0, buf)
995 " addu %[buf], 16 \n"
996 CNASM_MT2(val, CVM_MT_CRC_DWORD_REFLECT, 0)
997 CNASM_ULD(val, -8, buf)
998 " bne %[buf], %[tmp], 1b \n"
999 CNASM_MT2(val, CVM_MT_CRC_DWORD_REFLECT, 0)
1000
1001 " .align 3 \n"
1002 "2: and %[val], %[len], 1 \n"
1003 " beq %[val], %[len], 4f \n"
1004 " subu %[tmp], %[len], %[val] \n"
1005 " move %[len], %[val] \n"
1006 " addu %[tmp], %[buf] \n"
1007
1008 " .align 3 \n"
1009 "3: addu %[buf], 2 \n"
1010 " lhu %[val], -2(%[buf]) \n"
1011 " bne %[buf], %[tmp], 3b \n"
1012 CNASM_MT2(val, CVM_MT_CRC_HALF_REFLECT, 0)
1013
1014 " .align 3 \n"
1015 "4: beqz %[len], 5f \n"
1016 " nop \n"
1017 " lbu %[val], 0(%[buf]) \n"
1018 CNASM_MT2(val, CVM_MT_CRC_BYTE_REFLECT, 0)
1019
1020 " .align 3 \n"
1021 "5: \n"
1022 CNASM_END()
1023 : [len] "=d" (len),
1024 [buf] "=d" (buf),
1025 [val] "=d" (val),
1026 [tmp] "=d" (tmp)
1027 : "0" (len),
1028 "1" (buf)
1029 );
1030 #endif
1031
1032 /* -------------------------------------------------------------------------- */
1033
1034 /* GFM */
1035
1036 /* XXX */
1037
1038 #endif /* _OCTEON_COP2VAR_H_ */
1039