Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/lib/crypto/arm/chacha-neon-core.S
26285 views
1
/*
2
* ChaCha/HChaCha NEON helper functions
3
*
4
* Copyright (C) 2016 Linaro, Ltd. <[email protected]>
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2 as
8
* published by the Free Software Foundation.
9
*
10
* Based on:
11
* ChaCha20 256-bit cipher algorithm, RFC7539, x64 SSE3 functions
12
*
13
* Copyright (C) 2015 Martin Willi
14
*
15
* This program is free software; you can redistribute it and/or modify
16
* it under the terms of the GNU General Public License as published by
17
* the Free Software Foundation; either version 2 of the License, or
18
* (at your option) any later version.
19
*/
20
21
/*
22
* NEON doesn't have a rotate instruction. The alternatives are, more or less:
23
*
24
* (a) vshl.u32 + vsri.u32 (needs temporary register)
25
* (b) vshl.u32 + vshr.u32 + vorr (needs temporary register)
26
* (c) vrev32.16 (16-bit rotations only)
27
* (d) vtbl.8 + vtbl.8 (multiple of 8 bits rotations only,
28
* needs index vector)
29
*
30
* ChaCha has 16, 12, 8, and 7-bit rotations. For the 12 and 7-bit rotations,
31
* the only choices are (a) and (b). We use (a) since it takes two-thirds the
32
* cycles of (b) on both Cortex-A7 and Cortex-A53.
33
*
34
* For the 16-bit rotation, we use vrev32.16 since it's consistently fastest
35
* and doesn't need a temporary register.
36
*
37
* For the 8-bit rotation, we use vtbl.8 + vtbl.8. On Cortex-A7, this sequence
38
* is twice as fast as (a), even when doing (a) on multiple registers
39
* simultaneously to eliminate the stall between vshl and vsri. Also, it
40
* parallelizes better when temporary registers are scarce.
41
*
42
* A disadvantage is that on Cortex-A53, the vtbl sequence is the same speed as
43
* (a), so the need to load the rotation table actually makes the vtbl method
44
* slightly slower overall on that CPU (~1.3% slower ChaCha20). Still, it
45
* seems to be a good compromise to get a more significant speed boost on some
46
* CPUs, e.g. ~4.8% faster ChaCha20 on Cortex-A7.
47
*/
48
49
#include <linux/linkage.h>
50
#include <asm/cache.h>
51
52
.text
53
.fpu neon
54
.align 5
55
56
/*
57
* chacha_permute - permute one block
58
*
59
* Permute one 64-byte block where the state matrix is stored in the four NEON
60
* registers q0-q3. It performs matrix operations on four words in parallel,
61
* but requires shuffling to rearrange the words after each round.
62
*
63
* The round count is given in r3.
64
*
65
* Clobbers: r3, ip, q4-q5
66
*/
67
chacha_permute:
68
69
adr ip, .Lrol8_table
70
vld1.8 {d10}, [ip, :64]
71
72
.Ldoubleround:
73
// x0 += x1, x3 = rotl32(x3 ^ x0, 16)
74
vadd.i32 q0, q0, q1
75
veor q3, q3, q0
76
vrev32.16 q3, q3
77
78
// x2 += x3, x1 = rotl32(x1 ^ x2, 12)
79
vadd.i32 q2, q2, q3
80
veor q4, q1, q2
81
vshl.u32 q1, q4, #12
82
vsri.u32 q1, q4, #20
83
84
// x0 += x1, x3 = rotl32(x3 ^ x0, 8)
85
vadd.i32 q0, q0, q1
86
veor q3, q3, q0
87
vtbl.8 d6, {d6}, d10
88
vtbl.8 d7, {d7}, d10
89
90
// x2 += x3, x1 = rotl32(x1 ^ x2, 7)
91
vadd.i32 q2, q2, q3
92
veor q4, q1, q2
93
vshl.u32 q1, q4, #7
94
vsri.u32 q1, q4, #25
95
96
// x1 = shuffle32(x1, MASK(0, 3, 2, 1))
97
vext.8 q1, q1, q1, #4
98
// x2 = shuffle32(x2, MASK(1, 0, 3, 2))
99
vext.8 q2, q2, q2, #8
100
// x3 = shuffle32(x3, MASK(2, 1, 0, 3))
101
vext.8 q3, q3, q3, #12
102
103
// x0 += x1, x3 = rotl32(x3 ^ x0, 16)
104
vadd.i32 q0, q0, q1
105
veor q3, q3, q0
106
vrev32.16 q3, q3
107
108
// x2 += x3, x1 = rotl32(x1 ^ x2, 12)
109
vadd.i32 q2, q2, q3
110
veor q4, q1, q2
111
vshl.u32 q1, q4, #12
112
vsri.u32 q1, q4, #20
113
114
// x0 += x1, x3 = rotl32(x3 ^ x0, 8)
115
vadd.i32 q0, q0, q1
116
veor q3, q3, q0
117
vtbl.8 d6, {d6}, d10
118
vtbl.8 d7, {d7}, d10
119
120
// x2 += x3, x1 = rotl32(x1 ^ x2, 7)
121
vadd.i32 q2, q2, q3
122
veor q4, q1, q2
123
vshl.u32 q1, q4, #7
124
vsri.u32 q1, q4, #25
125
126
// x1 = shuffle32(x1, MASK(2, 1, 0, 3))
127
vext.8 q1, q1, q1, #12
128
// x2 = shuffle32(x2, MASK(1, 0, 3, 2))
129
vext.8 q2, q2, q2, #8
130
// x3 = shuffle32(x3, MASK(0, 3, 2, 1))
131
vext.8 q3, q3, q3, #4
132
133
subs r3, r3, #2
134
bne .Ldoubleround
135
136
bx lr
137
ENDPROC(chacha_permute)
138
139
ENTRY(chacha_block_xor_neon)
140
// r0: Input state matrix, s
141
// r1: 1 data block output, o
142
// r2: 1 data block input, i
143
// r3: nrounds
144
push {lr}
145
146
// x0..3 = s0..3
147
add ip, r0, #0x20
148
vld1.32 {q0-q1}, [r0]
149
vld1.32 {q2-q3}, [ip]
150
151
vmov q8, q0
152
vmov q9, q1
153
vmov q10, q2
154
vmov q11, q3
155
156
bl chacha_permute
157
158
add ip, r2, #0x20
159
vld1.8 {q4-q5}, [r2]
160
vld1.8 {q6-q7}, [ip]
161
162
// o0 = i0 ^ (x0 + s0)
163
vadd.i32 q0, q0, q8
164
veor q0, q0, q4
165
166
// o1 = i1 ^ (x1 + s1)
167
vadd.i32 q1, q1, q9
168
veor q1, q1, q5
169
170
// o2 = i2 ^ (x2 + s2)
171
vadd.i32 q2, q2, q10
172
veor q2, q2, q6
173
174
// o3 = i3 ^ (x3 + s3)
175
vadd.i32 q3, q3, q11
176
veor q3, q3, q7
177
178
add ip, r1, #0x20
179
vst1.8 {q0-q1}, [r1]
180
vst1.8 {q2-q3}, [ip]
181
182
pop {pc}
183
ENDPROC(chacha_block_xor_neon)
184
185
ENTRY(hchacha_block_neon)
186
// r0: Input state matrix, s
187
// r1: output (8 32-bit words)
188
// r2: nrounds
189
push {lr}
190
191
vld1.32 {q0-q1}, [r0]!
192
vld1.32 {q2-q3}, [r0]
193
194
mov r3, r2
195
bl chacha_permute
196
197
vst1.32 {q0}, [r1]!
198
vst1.32 {q3}, [r1]
199
200
pop {pc}
201
ENDPROC(hchacha_block_neon)
202
203
.align 4
204
.Lctrinc: .word 0, 1, 2, 3
205
.Lrol8_table: .byte 3, 0, 1, 2, 7, 4, 5, 6
206
207
.align 5
208
ENTRY(chacha_4block_xor_neon)
209
push {r4, lr}
210
mov r4, sp // preserve the stack pointer
211
sub ip, sp, #0x20 // allocate a 32 byte buffer
212
bic ip, ip, #0x1f // aligned to 32 bytes
213
mov sp, ip
214
215
// r0: Input state matrix, s
216
// r1: 4 data blocks output, o
217
// r2: 4 data blocks input, i
218
// r3: nrounds
219
220
//
221
// This function encrypts four consecutive ChaCha blocks by loading
222
// the state matrix in NEON registers four times. The algorithm performs
223
// each operation on the corresponding word of each state matrix, hence
224
// requires no word shuffling. The words are re-interleaved before the
225
// final addition of the original state and the XORing step.
226
//
227
228
// x0..15[0-3] = s0..15[0-3]
229
add ip, r0, #0x20
230
vld1.32 {q0-q1}, [r0]
231
vld1.32 {q2-q3}, [ip]
232
233
adr lr, .Lctrinc
234
vdup.32 q15, d7[1]
235
vdup.32 q14, d7[0]
236
vld1.32 {q4}, [lr, :128]
237
vdup.32 q13, d6[1]
238
vdup.32 q12, d6[0]
239
vdup.32 q11, d5[1]
240
vdup.32 q10, d5[0]
241
vadd.u32 q12, q12, q4 // x12 += counter values 0-3
242
vdup.32 q9, d4[1]
243
vdup.32 q8, d4[0]
244
vdup.32 q7, d3[1]
245
vdup.32 q6, d3[0]
246
vdup.32 q5, d2[1]
247
vdup.32 q4, d2[0]
248
vdup.32 q3, d1[1]
249
vdup.32 q2, d1[0]
250
vdup.32 q1, d0[1]
251
vdup.32 q0, d0[0]
252
253
adr ip, .Lrol8_table
254
b 1f
255
256
.Ldoubleround4:
257
vld1.32 {q8-q9}, [sp, :256]
258
1:
259
// x0 += x4, x12 = rotl32(x12 ^ x0, 16)
260
// x1 += x5, x13 = rotl32(x13 ^ x1, 16)
261
// x2 += x6, x14 = rotl32(x14 ^ x2, 16)
262
// x3 += x7, x15 = rotl32(x15 ^ x3, 16)
263
vadd.i32 q0, q0, q4
264
vadd.i32 q1, q1, q5
265
vadd.i32 q2, q2, q6
266
vadd.i32 q3, q3, q7
267
268
veor q12, q12, q0
269
veor q13, q13, q1
270
veor q14, q14, q2
271
veor q15, q15, q3
272
273
vrev32.16 q12, q12
274
vrev32.16 q13, q13
275
vrev32.16 q14, q14
276
vrev32.16 q15, q15
277
278
// x8 += x12, x4 = rotl32(x4 ^ x8, 12)
279
// x9 += x13, x5 = rotl32(x5 ^ x9, 12)
280
// x10 += x14, x6 = rotl32(x6 ^ x10, 12)
281
// x11 += x15, x7 = rotl32(x7 ^ x11, 12)
282
vadd.i32 q8, q8, q12
283
vadd.i32 q9, q9, q13
284
vadd.i32 q10, q10, q14
285
vadd.i32 q11, q11, q15
286
287
vst1.32 {q8-q9}, [sp, :256]
288
289
veor q8, q4, q8
290
veor q9, q5, q9
291
vshl.u32 q4, q8, #12
292
vshl.u32 q5, q9, #12
293
vsri.u32 q4, q8, #20
294
vsri.u32 q5, q9, #20
295
296
veor q8, q6, q10
297
veor q9, q7, q11
298
vshl.u32 q6, q8, #12
299
vshl.u32 q7, q9, #12
300
vsri.u32 q6, q8, #20
301
vsri.u32 q7, q9, #20
302
303
// x0 += x4, x12 = rotl32(x12 ^ x0, 8)
304
// x1 += x5, x13 = rotl32(x13 ^ x1, 8)
305
// x2 += x6, x14 = rotl32(x14 ^ x2, 8)
306
// x3 += x7, x15 = rotl32(x15 ^ x3, 8)
307
vld1.8 {d16}, [ip, :64]
308
vadd.i32 q0, q0, q4
309
vadd.i32 q1, q1, q5
310
vadd.i32 q2, q2, q6
311
vadd.i32 q3, q3, q7
312
313
veor q12, q12, q0
314
veor q13, q13, q1
315
veor q14, q14, q2
316
veor q15, q15, q3
317
318
vtbl.8 d24, {d24}, d16
319
vtbl.8 d25, {d25}, d16
320
vtbl.8 d26, {d26}, d16
321
vtbl.8 d27, {d27}, d16
322
vtbl.8 d28, {d28}, d16
323
vtbl.8 d29, {d29}, d16
324
vtbl.8 d30, {d30}, d16
325
vtbl.8 d31, {d31}, d16
326
327
vld1.32 {q8-q9}, [sp, :256]
328
329
// x8 += x12, x4 = rotl32(x4 ^ x8, 7)
330
// x9 += x13, x5 = rotl32(x5 ^ x9, 7)
331
// x10 += x14, x6 = rotl32(x6 ^ x10, 7)
332
// x11 += x15, x7 = rotl32(x7 ^ x11, 7)
333
vadd.i32 q8, q8, q12
334
vadd.i32 q9, q9, q13
335
vadd.i32 q10, q10, q14
336
vadd.i32 q11, q11, q15
337
338
vst1.32 {q8-q9}, [sp, :256]
339
340
veor q8, q4, q8
341
veor q9, q5, q9
342
vshl.u32 q4, q8, #7
343
vshl.u32 q5, q9, #7
344
vsri.u32 q4, q8, #25
345
vsri.u32 q5, q9, #25
346
347
veor q8, q6, q10
348
veor q9, q7, q11
349
vshl.u32 q6, q8, #7
350
vshl.u32 q7, q9, #7
351
vsri.u32 q6, q8, #25
352
vsri.u32 q7, q9, #25
353
354
vld1.32 {q8-q9}, [sp, :256]
355
356
// x0 += x5, x15 = rotl32(x15 ^ x0, 16)
357
// x1 += x6, x12 = rotl32(x12 ^ x1, 16)
358
// x2 += x7, x13 = rotl32(x13 ^ x2, 16)
359
// x3 += x4, x14 = rotl32(x14 ^ x3, 16)
360
vadd.i32 q0, q0, q5
361
vadd.i32 q1, q1, q6
362
vadd.i32 q2, q2, q7
363
vadd.i32 q3, q3, q4
364
365
veor q15, q15, q0
366
veor q12, q12, q1
367
veor q13, q13, q2
368
veor q14, q14, q3
369
370
vrev32.16 q15, q15
371
vrev32.16 q12, q12
372
vrev32.16 q13, q13
373
vrev32.16 q14, q14
374
375
// x10 += x15, x5 = rotl32(x5 ^ x10, 12)
376
// x11 += x12, x6 = rotl32(x6 ^ x11, 12)
377
// x8 += x13, x7 = rotl32(x7 ^ x8, 12)
378
// x9 += x14, x4 = rotl32(x4 ^ x9, 12)
379
vadd.i32 q10, q10, q15
380
vadd.i32 q11, q11, q12
381
vadd.i32 q8, q8, q13
382
vadd.i32 q9, q9, q14
383
384
vst1.32 {q8-q9}, [sp, :256]
385
386
veor q8, q7, q8
387
veor q9, q4, q9
388
vshl.u32 q7, q8, #12
389
vshl.u32 q4, q9, #12
390
vsri.u32 q7, q8, #20
391
vsri.u32 q4, q9, #20
392
393
veor q8, q5, q10
394
veor q9, q6, q11
395
vshl.u32 q5, q8, #12
396
vshl.u32 q6, q9, #12
397
vsri.u32 q5, q8, #20
398
vsri.u32 q6, q9, #20
399
400
// x0 += x5, x15 = rotl32(x15 ^ x0, 8)
401
// x1 += x6, x12 = rotl32(x12 ^ x1, 8)
402
// x2 += x7, x13 = rotl32(x13 ^ x2, 8)
403
// x3 += x4, x14 = rotl32(x14 ^ x3, 8)
404
vld1.8 {d16}, [ip, :64]
405
vadd.i32 q0, q0, q5
406
vadd.i32 q1, q1, q6
407
vadd.i32 q2, q2, q7
408
vadd.i32 q3, q3, q4
409
410
veor q15, q15, q0
411
veor q12, q12, q1
412
veor q13, q13, q2
413
veor q14, q14, q3
414
415
vtbl.8 d30, {d30}, d16
416
vtbl.8 d31, {d31}, d16
417
vtbl.8 d24, {d24}, d16
418
vtbl.8 d25, {d25}, d16
419
vtbl.8 d26, {d26}, d16
420
vtbl.8 d27, {d27}, d16
421
vtbl.8 d28, {d28}, d16
422
vtbl.8 d29, {d29}, d16
423
424
vld1.32 {q8-q9}, [sp, :256]
425
426
// x10 += x15, x5 = rotl32(x5 ^ x10, 7)
427
// x11 += x12, x6 = rotl32(x6 ^ x11, 7)
428
// x8 += x13, x7 = rotl32(x7 ^ x8, 7)
429
// x9 += x14, x4 = rotl32(x4 ^ x9, 7)
430
vadd.i32 q10, q10, q15
431
vadd.i32 q11, q11, q12
432
vadd.i32 q8, q8, q13
433
vadd.i32 q9, q9, q14
434
435
vst1.32 {q8-q9}, [sp, :256]
436
437
veor q8, q7, q8
438
veor q9, q4, q9
439
vshl.u32 q7, q8, #7
440
vshl.u32 q4, q9, #7
441
vsri.u32 q7, q8, #25
442
vsri.u32 q4, q9, #25
443
444
veor q8, q5, q10
445
veor q9, q6, q11
446
vshl.u32 q5, q8, #7
447
vshl.u32 q6, q9, #7
448
vsri.u32 q5, q8, #25
449
vsri.u32 q6, q9, #25
450
451
subs r3, r3, #2
452
bne .Ldoubleround4
453
454
// x0..7[0-3] are in q0-q7, x10..15[0-3] are in q10-q15.
455
// x8..9[0-3] are on the stack.
456
457
// Re-interleave the words in the first two rows of each block (x0..7).
458
// Also add the counter values 0-3 to x12[0-3].
459
vld1.32 {q8}, [lr, :128] // load counter values 0-3
460
vzip.32 q0, q1 // => (0 1 0 1) (0 1 0 1)
461
vzip.32 q2, q3 // => (2 3 2 3) (2 3 2 3)
462
vzip.32 q4, q5 // => (4 5 4 5) (4 5 4 5)
463
vzip.32 q6, q7 // => (6 7 6 7) (6 7 6 7)
464
vadd.u32 q12, q8 // x12 += counter values 0-3
465
vswp d1, d4
466
vswp d3, d6
467
vld1.32 {q8-q9}, [r0]! // load s0..7
468
vswp d9, d12
469
vswp d11, d14
470
471
// Swap q1 and q4 so that we'll free up consecutive registers (q0-q1)
472
// after XORing the first 32 bytes.
473
vswp q1, q4
474
475
// First two rows of each block are (q0 q1) (q2 q6) (q4 q5) (q3 q7)
476
477
// x0..3[0-3] += s0..3[0-3] (add orig state to 1st row of each block)
478
vadd.u32 q0, q0, q8
479
vadd.u32 q2, q2, q8
480
vadd.u32 q4, q4, q8
481
vadd.u32 q3, q3, q8
482
483
// x4..7[0-3] += s4..7[0-3] (add orig state to 2nd row of each block)
484
vadd.u32 q1, q1, q9
485
vadd.u32 q6, q6, q9
486
vadd.u32 q5, q5, q9
487
vadd.u32 q7, q7, q9
488
489
// XOR first 32 bytes using keystream from first two rows of first block
490
vld1.8 {q8-q9}, [r2]!
491
veor q8, q8, q0
492
veor q9, q9, q1
493
vst1.8 {q8-q9}, [r1]!
494
495
// Re-interleave the words in the last two rows of each block (x8..15).
496
vld1.32 {q8-q9}, [sp, :256]
497
mov sp, r4 // restore original stack pointer
498
ldr r4, [r4, #8] // load number of bytes
499
vzip.32 q12, q13 // => (12 13 12 13) (12 13 12 13)
500
vzip.32 q14, q15 // => (14 15 14 15) (14 15 14 15)
501
vzip.32 q8, q9 // => (8 9 8 9) (8 9 8 9)
502
vzip.32 q10, q11 // => (10 11 10 11) (10 11 10 11)
503
vld1.32 {q0-q1}, [r0] // load s8..15
504
vswp d25, d28
505
vswp d27, d30
506
vswp d17, d20
507
vswp d19, d22
508
509
// Last two rows of each block are (q8 q12) (q10 q14) (q9 q13) (q11 q15)
510
511
// x8..11[0-3] += s8..11[0-3] (add orig state to 3rd row of each block)
512
vadd.u32 q8, q8, q0
513
vadd.u32 q10, q10, q0
514
vadd.u32 q9, q9, q0
515
vadd.u32 q11, q11, q0
516
517
// x12..15[0-3] += s12..15[0-3] (add orig state to 4th row of each block)
518
vadd.u32 q12, q12, q1
519
vadd.u32 q14, q14, q1
520
vadd.u32 q13, q13, q1
521
vadd.u32 q15, q15, q1
522
523
// XOR the rest of the data with the keystream
524
525
vld1.8 {q0-q1}, [r2]!
526
subs r4, r4, #96
527
veor q0, q0, q8
528
veor q1, q1, q12
529
ble .Lle96
530
vst1.8 {q0-q1}, [r1]!
531
532
vld1.8 {q0-q1}, [r2]!
533
subs r4, r4, #32
534
veor q0, q0, q2
535
veor q1, q1, q6
536
ble .Lle128
537
vst1.8 {q0-q1}, [r1]!
538
539
vld1.8 {q0-q1}, [r2]!
540
subs r4, r4, #32
541
veor q0, q0, q10
542
veor q1, q1, q14
543
ble .Lle160
544
vst1.8 {q0-q1}, [r1]!
545
546
vld1.8 {q0-q1}, [r2]!
547
subs r4, r4, #32
548
veor q0, q0, q4
549
veor q1, q1, q5
550
ble .Lle192
551
vst1.8 {q0-q1}, [r1]!
552
553
vld1.8 {q0-q1}, [r2]!
554
subs r4, r4, #32
555
veor q0, q0, q9
556
veor q1, q1, q13
557
ble .Lle224
558
vst1.8 {q0-q1}, [r1]!
559
560
vld1.8 {q0-q1}, [r2]!
561
subs r4, r4, #32
562
veor q0, q0, q3
563
veor q1, q1, q7
564
blt .Llt256
565
.Lout:
566
vst1.8 {q0-q1}, [r1]!
567
568
vld1.8 {q0-q1}, [r2]
569
veor q0, q0, q11
570
veor q1, q1, q15
571
vst1.8 {q0-q1}, [r1]
572
573
pop {r4, pc}
574
575
.Lle192:
576
vmov q4, q9
577
vmov q5, q13
578
579
.Lle160:
580
// nothing to do
581
582
.Lfinalblock:
583
// Process the final block if processing less than 4 full blocks.
584
// Entered with 32 bytes of ChaCha cipher stream in q4-q5, and the
585
// previous 32 byte output block that still needs to be written at
586
// [r1] in q0-q1.
587
beq .Lfullblock
588
589
.Lpartialblock:
590
adr lr, .Lpermute + 32
591
add r2, r2, r4
592
add lr, lr, r4
593
add r4, r4, r1
594
595
vld1.8 {q2-q3}, [lr]
596
vld1.8 {q6-q7}, [r2]
597
598
add r4, r4, #32
599
600
vtbl.8 d4, {q4-q5}, d4
601
vtbl.8 d5, {q4-q5}, d5
602
vtbl.8 d6, {q4-q5}, d6
603
vtbl.8 d7, {q4-q5}, d7
604
605
veor q6, q6, q2
606
veor q7, q7, q3
607
608
vst1.8 {q6-q7}, [r4] // overlapping stores
609
vst1.8 {q0-q1}, [r1]
610
pop {r4, pc}
611
612
.Lfullblock:
613
vmov q11, q4
614
vmov q15, q5
615
b .Lout
616
.Lle96:
617
vmov q4, q2
618
vmov q5, q6
619
b .Lfinalblock
620
.Lle128:
621
vmov q4, q10
622
vmov q5, q14
623
b .Lfinalblock
624
.Lle224:
625
vmov q4, q3
626
vmov q5, q7
627
b .Lfinalblock
628
.Llt256:
629
vmov q4, q11
630
vmov q5, q15
631
b .Lpartialblock
632
ENDPROC(chacha_4block_xor_neon)
633
634
.align L1_CACHE_SHIFT
635
.Lpermute:
636
.byte 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
637
.byte 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
638
.byte 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
639
.byte 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
640
.byte 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
641
.byte 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
642
.byte 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
643
.byte 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
644
645