Add ARM/NEON implementation of Poly1305
[libgcrypt.git] / cipher / poly1305-armv7-neon.S
1 /* poly1305-armv7-neon.S  -  ARMv7/NEON implementation of Poly1305
2  *
3  * Copyright (C) 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
4  *
5  * This file is part of Libgcrypt.
6  *
7  * Libgcrypt is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * Libgcrypt is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /*
22  * Based on public domain implementation by Andrew Moon at
23  *  https://github.com/floodyberry/poly1305-opt
24  */
25
26 #include <config.h>
27
28 #if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) && \
29     defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) && \
30     defined(HAVE_GCC_INLINE_ASM_NEON)
31
32 .syntax unified
33 .fpu neon
34 .arm
35
36 .text
37
38 .p2align 2
39 .Lpoly1305_init_constants_neon:
40 .long 0x3ffff03
41 .long 0x3ffc0ff
42 .long 0x3f03fff
43 .long 0x00fffff
44
45 .globl _gcry_poly1305_armv7_neon_init_ext
46 .type  _gcry_poly1305_armv7_neon_init_ext,%function;
47 _gcry_poly1305_armv7_neon_init_ext:
48 .Lpoly1305_init_ext_neon_local:
49         stmfd sp!, {r4-r11, lr}
50         sub sp, sp, #32
51         mov r14, r2
52         and r2, r2, r2
53         moveq r14, #-1
54         ldmia r1!, {r2-r5}
55         ldr r7, =.Lpoly1305_init_constants_neon
56         mov r6, r2
57         mov r8, r2, lsr #26
58         mov r9, r3, lsr #20
59         mov r10, r4, lsr #14
60         mov r11, r5, lsr #8
61         orr r8, r8, r3, lsl #6
62         orr r9, r9, r4, lsl #12
63         orr r10, r10, r5, lsl #18
64         ldmia r7, {r2-r5}
65         and r2, r2, r8
66         and r3, r3, r9
67         and r4, r4, r10
68         and r5, r5, r11
69         and r6, r6, 0x3ffffff
70         stmia r0!, {r2-r6}
71         eor r8, r8, r8
72         str r8, [sp, #24]
73 .Lpoly1305_init_ext_neon_squareloop:
74         ldr r8, [sp, #24]
75         mov r12, #16
76         cmp r8, #2
77         beq .Lpoly1305_init_ext_neon_donesquaring
78         cmp r8, #1
79         moveq r12, #64
80         cmp r14, r12
81         bls .Lpoly1305_init_ext_neon_donesquaring
82         add r8, #1
83         str r8, [sp, #24]
84         mov r6, r6, lsl #1
85         mov r2, r2, lsl #1
86         umull r7, r8, r3, r3
87         umull r9, r10, r6, r4
88         umlal r7, r8, r6, r5
89         umlal r9, r10, r2, r3
90         add r11, r5, r5, lsl #2
91         umlal r7, r8, r2, r4
92         umlal r9, r10, r5, r11
93         str r7, [sp, #16]
94         str r8, [sp, #20]
95         mov r2, r2, lsr #1
96         mov r5, r5, lsl #1
97         str r9, [sp, #8]
98         str r10, [sp, #12]
99         umull r7, r8, r2, r2
100         umull r9, r10, r6, r2
101         add r11, r3, r3, lsl #2
102         add r12, r4, r4, lsl #2
103         umlal r7, r8, r6, r3
104         umlal r9, r10, r5, r11
105         umlal r7, r8, r5, r12
106         umlal r9, r10, r4, r12
107         mov r6, r6, lsr #1
108         mov r3, r3, lsl #1
109         add r11, r2, r2, lsl #2
110         str r7, [sp, #0]
111         str r8, [sp, #4]
112         umull r7, r8, r6, r6
113         umlal r7, r8, r3, r12
114         umlal r7, r8, r5, r11
115         and r6, r7, 0x3ffffff
116         mov r11, r7, lsr #26
117         orr r11, r11, r8, lsl #6
118         ldr r7, [sp, #0]
119         ldr r8, [sp, #4]
120         adds r9, r9, r11
121         adc r10, r10, #0
122         and r2, r9, 0x3ffffff
123         mov r11, r9, lsr #26
124         orr r11, r11, r10, lsl #6
125         ldr r9, [sp, #8]
126         ldr r10, [sp, #12]
127         adds r7, r7, r11
128         adc r8, r8, #0
129         and r3, r7, 0x3ffffff
130         mov r11, r7, lsr #26
131         orr r11, r11, r8, lsl #6
132         ldr r7, [sp, #16]
133         ldr r8, [sp, #20]
134         adds r9, r9, r11
135         adc r10, r10, #0
136         and r4, r9, 0x3ffffff
137         mov r11, r9, lsr #26
138         orr r11, r11, r10, lsl #6
139         adds r7, r7, r11
140         adc r8, r8, #0
141         and r5, r7, 0x3ffffff
142         mov r11, r7, lsr #26
143         orr r11, r11, r8, lsl #6
144         add r11, r11, r11, lsl #2
145         add r6, r6, r11
146         mov r11, r6, lsr #26
147         and r6, r6, 0x3ffffff
148         add r2, r2, r11
149         stmia r0!, {r2-r6}
150         b .Lpoly1305_init_ext_neon_squareloop
151 .Lpoly1305_init_ext_neon_donesquaring:
152         mov r2, #2
153         ldr r14, [sp, #24]
154         sub r14, r2, r14
155         mov r3, r14, lsl #4
156         add r3, r3, r14, lsl #2
157         add r0, r0, r3
158         eor r2, r2, r2
159         eor r3, r3, r3
160         eor r4, r4, r4
161         eor r5, r5, r5
162         eor r6, r6, r6
163         stmia r0!, {r2-r6}
164         stmia r0!, {r2-r6}
165         ldmia r1!, {r2-r5}
166         stmia r0, {r2-r6}
167         add sp, sp, #32
168         ldmfd sp!, {r4-r11, lr}
169         mov r0, #(9*4+32)
170         bx lr
171 .ltorg
172 .size _gcry_poly1305_armv7_neon_init_ext,.-_gcry_poly1305_armv7_neon_init_ext;
173
174 .globl _gcry_poly1305_armv7_neon_blocks
175 .type  _gcry_poly1305_armv7_neon_blocks,%function;
176 _gcry_poly1305_armv7_neon_blocks:
177 .Lpoly1305_blocks_neon_local:
178         vmov.i32 q0, #0xffffffff
179         vmov.i32 d4, #1
180         vsubw.u32 q0, q0, d4
181         vstmdb sp!, {q4,q5,q6,q7}
182         stmfd sp!, {r4-r11, lr}
183         mov r8, sp
184         and sp, sp, #~63
185         sub sp, sp, #192
186         str r0, [sp, #108]
187         str r1, [sp, #112]
188         str r2, [sp, #116]
189         str r8, [sp, #120]
190         mov r3, r0
191         mov r0, r1
192         mov r1, r2
193         mov r2, r3
194         ldr r8, [r2, #116]
195         veor d15, d15, d15
196         vorr.i32 d15, #(1 << 24)
197         tst r8, #2
198         beq .Lpoly1305_blocks_neon_skip_shift8
199         vshr.u64 d15, #32
200 .Lpoly1305_blocks_neon_skip_shift8:
201         tst r8, #4
202         beq .Lpoly1305_blocks_neon_skip_shift16
203         veor d15, d15, d15
204 .Lpoly1305_blocks_neon_skip_shift16:
205         vst1.64 d15, [sp, :64]
206         tst r8, #1
207         bne .Lpoly1305_blocks_neon_started
208         vld1.64 {q0-q1}, [r0]!
209         vswp d1, d2
210         vmovn.i64 d21, q0
211         vshrn.i64 d22, q0, #26
212         vshrn.u64 d24, q1, #14
213         vext.8 d0, d0, d2, #4
214         vext.8 d1, d1, d3, #4
215         vshr.u64 q1, q1, #32
216         vshrn.i64 d23, q0, #20
217         vshrn.u64 d25, q1, #8
218         vand.i32 d21, #0x03ffffff
219         vand.i32 q11, #0x03ffffff
220         vand.i32 q12, #0x03ffffff
221         orr r8, r8, #1
222         sub r1, r1, #32
223         str r8, [r2, #116]
224         vorr d25, d25, d15
225         b .Lpoly1305_blocks_neon_setupr20
226 .Lpoly1305_blocks_neon_started:
227         add r9, r2, #60
228         vldm r9, {d21-d25}
229 .Lpoly1305_blocks_neon_setupr20:
230         vmov.i32 d0, #5
231         tst r8, #(8|16)
232         beq .Lpoly1305_blocks_neon_setupr20_simple
233         tst r8, #(8)
234         beq .Lpoly1305_blocks_neon_setupr20_r_1
235         mov r9, r2
236         add r10, r2, #20
237         vld1.64 {q9}, [r9]!
238         vld1.64 {q8}, [r10]!
239         vld1.64 {d2}, [r9]
240         vld1.64 {d20}, [r10]
241         b .Lpoly1305_blocks_neon_setupr20_hard
242 .Lpoly1305_blocks_neon_setupr20_r_1:
243         mov r9, r2
244         vmov.i32 d2, #1
245         vld1.64 {q8}, [r9]!
246         veor q9, q9, q9
247         vshr.u64 d2, d2, #32
248         vld1.64 {d20}, [r9]
249 .Lpoly1305_blocks_neon_setupr20_hard:
250         vzip.i32 q8, q9
251         vzip.i32 d20, d2
252         b .Lpoly1305_blocks_neon_setups20
253 .Lpoly1305_blocks_neon_setupr20_simple:
254         add r9, r2, #20
255         vld1.64 {d2-d4}, [r9]
256         vdup.32 d16, d2[0]
257         vdup.32 d17, d2[1]
258         vdup.32 d18, d3[0]
259         vdup.32 d19, d3[1]
260         vdup.32 d20, d4[0]
261 .Lpoly1305_blocks_neon_setups20:
262         vmul.i32 q13, q8, d0[0]
263         vmov.i64 q15, 0x00000000ffffffff
264         vmul.i32 q14, q9, d0[0]
265         vshr.u64 q15, q15, #6
266         cmp r1, #64
267         blo .Lpoly1305_blocks_neon_try32
268         add r9, sp, #16
269         add r10, r2, #40
270         add r11, sp, #64
271         str r1, [sp, #116]
272         vld1.64 {d10-d12}, [r10]
273         vmov d14, d12
274         vmul.i32 q6, q5, d0[0]
275 .Lpoly1305_blocks_neon_mainloop:
276         ldmia r0!, {r2-r5}
277         vmull.u32 q0, d25, d12[0]
278         mov r7, r2, lsr #26
279         vmlal.u32 q0, d24, d12[1]
280         mov r8, r3, lsr #20
281         ldr r6, [sp, #0]
282         vmlal.u32 q0, d23, d13[0]
283         mov r9, r4, lsr #14
284         vmlal.u32 q0, d22, d13[1]
285         orr r6, r6, r5, lsr #8
286         vmlal.u32 q0, d21, d14[0]
287         orr r3, r7, r3, lsl #6
288         vmull.u32 q1, d25, d12[1]
289         orr r4, r8, r4, lsl #12
290         orr r5, r9, r5, lsl #18
291         vmlal.u32 q1, d24, d13[0]
292         ldmia r0!, {r7-r10}
293         vmlal.u32 q1, d23, d13[1]
294         mov r1, r7, lsr #26
295         vmlal.u32 q1, d22, d14[0]
296         ldr r11, [sp, #4]
297         mov r12, r8, lsr #20
298         vmlal.u32 q1, d21, d10[0]
299         mov r14, r9, lsr #14
300         vmull.u32 q2, d25, d13[0]
301         orr r11, r11, r10, lsr #8
302         orr r8, r1, r8, lsl #6
303         vmlal.u32 q2, d24, d13[1]
304         orr r9, r12, r9, lsl #12
305         vmlal.u32 q2, d23, d14[0]
306         orr r10, r14, r10, lsl #18
307         vmlal.u32 q2, d22, d10[0]
308         mov r12, r3
309         and r2, r2, #0x3ffffff
310         vmlal.u32 q2, d21, d10[1]
311         mov r14, r5
312         vmull.u32 q3, d25, d13[1]
313         and r3, r7, #0x3ffffff
314         vmlal.u32 q3, d24, d14[0]
315         and r5, r8, #0x3ffffff
316         vmlal.u32 q3, d23, d10[0]
317         and r7, r9, #0x3ffffff
318         vmlal.u32 q3, d22, d10[1]
319         and r8, r14, #0x3ffffff
320         vmlal.u32 q3, d21, d11[0]
321         and r9, r10, #0x3ffffff
322         add r14, sp, #128
323         vmull.u32 q4, d25, d14[0]
324         mov r10, r6
325         vmlal.u32 q4, d24, d10[0]
326         and r6, r4, #0x3ffffff
327         vmlal.u32 q4, d23, d10[1]
328         and r4, r12, #0x3ffffff
329         vmlal.u32 q4, d22, d11[0]
330         stm r14, {r2-r11}
331         vmlal.u32 q4, d21, d11[1]
332         vld1.64 {d21-d24}, [r14, :256]!
333         vld1.64 {d25}, [r14, :64]
334         ldmia r0!, {r2-r5}
335         vmlal.u32 q0, d25, d26
336         mov r7, r2, lsr #26
337         vmlal.u32 q0, d24, d27
338         ldr r6, [sp, #0]
339         mov r8, r3, lsr #20
340         vmlal.u32 q0, d23, d28
341         mov r9, r4, lsr #14
342         vmlal.u32 q0, d22, d29
343         orr r6, r6, r5, lsr #8
344         vmlal.u32 q0, d21, d20
345         orr r3, r7, r3, lsl #6
346         vmlal.u32 q1, d25, d27
347         orr r4, r8, r4, lsl #12
348         orr r5, r9, r5, lsl #18
349         vmlal.u32 q1, d24, d28
350         ldmia r0!, {r7-r10}
351         vmlal.u32 q1, d23, d29
352         mov r1, r7, lsr #26
353         vmlal.u32 q1, d22, d20
354         ldr r11, [sp, #4]
355         mov r12, r8, lsr #20
356         vmlal.u32 q1, d21, d16
357         mov r14, r9, lsr #14
358         vmlal.u32 q2, d25, d28
359         orr r11, r11, r10, lsr #8
360         orr r8, r1, r8, lsl #6
361         orr r9, r12, r9, lsl #12
362         vmlal.u32 q2, d24, d29
363         orr r10, r14, r10, lsl #18
364         and r2, r2, #0x3ffffff
365         mov r12, r3
366         vmlal.u32 q2, d23, d20
367         mov r14, r5
368         vmlal.u32 q2, d22, d16
369         and r3, r7, #0x3ffffff
370         vmlal.u32 q2, d21, d17
371         and r5, r8, #0x3ffffff
372         vmlal.u32 q3, d25, d29
373         and r7, r9, #0x3ffffff
374         vmlal.u32 q3, d24, d20
375         and r8, r14, #0x3ffffff
376         vmlal.u32 q3, d23, d16
377         and r9, r10, #0x3ffffff
378         vmlal.u32 q3, d22, d17
379         add r14, sp, #128
380         vmlal.u32 q3, d21, d18
381         mov r10, r6
382         vmlal.u32 q4, d25, d20
383         vmlal.u32 q4, d24, d16
384         and r6, r4, #0x3ffffff
385         vmlal.u32 q4, d23, d17
386         and r4, r12, #0x3ffffff
387         vmlal.u32 q4, d22, d18
388         stm r14, {r2-r11}
389         vmlal.u32 q4, d21, d19
390         vld1.64 {d21-d24}, [r14, :256]!
391         vld1.64 {d25}, [r14, :64]
392         vaddw.u32 q0, q0, d21
393         vaddw.u32 q1, q1, d22
394         vaddw.u32 q2, q2, d23
395         vaddw.u32 q3, q3, d24
396         vaddw.u32 q4, q4, d25
397         vshr.u64 q11, q0, #26
398         vand q0, q0, q15
399         vadd.i64 q1, q1, q11
400         vshr.u64 q12, q3, #26
401         vand q3, q3, q15
402         vadd.i64 q4, q4, q12
403         vshr.u64 q11, q1, #26
404         vand q1, q1, q15
405         vadd.i64 q2, q2, q11
406         vshr.u64 q12, q4, #26
407         vand q4, q4, q15
408         vadd.i64 q0, q0, q12
409         vshl.i64 q12, q12, #2
410         ldr r1, [sp, #116]
411         vadd.i64 q0, q0, q12
412         vshr.u64 q11, q2, #26
413         vand q2, q2, q15
414         vadd.i64 q3, q3, q11
415         sub r1, #64
416         vshr.u64 q12, q0, #26
417         vand q0, q0, q15
418         vadd.i64 q1, q1, q12
419         cmp r1, #64
420         vshr.u64 q11, q3, #26
421         vand q3, q3, q15
422         vadd.i64 q4, q4, q11
423         vmovn.i64 d21, q0
424         str r1, [sp, #116]
425         vmovn.i64 d22, q1
426         vmovn.i64 d23, q2
427         vmovn.i64 d24, q3
428         vmovn.i64 d25, q4
429         bhs .Lpoly1305_blocks_neon_mainloop
430 .Lpoly1305_blocks_neon_try32:
431         cmp r1, #32
432         blo .Lpoly1305_blocks_neon_done
433         tst r0, r0
434         bne .Lpoly1305_blocks_loadm32
435         veor q0, q0, q0
436         veor q1, q1, q1
437         veor q2, q2, q2
438         veor q3, q3, q3
439         veor q4, q4, q4
440         b .Lpoly1305_blocks_continue32
441 .Lpoly1305_blocks_loadm32:
442         vld1.64 {q0-q1}, [r0]!
443         veor q4, q4, q4
444         vswp d1, d2
445         veor q3, q3, q3
446         vtrn.32 q0, q4
447         vtrn.32 q1, q3
448         vshl.i64 q2, q1, #12
449         vshl.i64 q3, q3, #18
450         vshl.i64 q1, q4, #6
451         vmovl.u32 q4, d15
452 .Lpoly1305_blocks_continue32:
453         vmlal.u32 q0, d25, d26
454         vmlal.u32 q0, d24, d27
455         vmlal.u32 q0, d23, d28
456         vmlal.u32 q0, d22, d29
457         vmlal.u32 q0, d21, d20
458         vmlal.u32 q1, d25, d27
459         vmlal.u32 q1, d24, d28
460         vmlal.u32 q1, d23, d29
461         vmlal.u32 q1, d22, d20
462         vmlal.u32 q1, d21, d16
463         vmlal.u32 q2, d25, d28
464         vmlal.u32 q2, d24, d29
465         vmlal.u32 q2, d23, d20
466         vmlal.u32 q2, d22, d16
467         vmlal.u32 q2, d21, d17
468         vmlal.u32 q3, d25, d29
469         vmlal.u32 q3, d24, d20
470         vmlal.u32 q3, d23, d16
471         vmlal.u32 q3, d22, d17
472         vmlal.u32 q3, d21, d18
473         vmlal.u32 q4, d25, d20
474         vmlal.u32 q4, d24, d16
475         vmlal.u32 q4, d23, d17
476         vmlal.u32 q4, d22, d18
477         vmlal.u32 q4, d21, d19
478         vshr.u64 q11, q0, #26
479         vand q0, q0, q15
480         vadd.i64 q1, q1, q11
481         vshr.u64 q12, q3, #26
482         vand q3, q3, q15
483         vadd.i64 q4, q4, q12
484         vshr.u64 q11, q1, #26
485         vand q1, q1, q15
486         vadd.i64 q2, q2, q11
487         vshr.u64 q12, q4, #26
488         vand q4, q4, q15
489         vadd.i64 q0, q0, q12
490         vshl.i64 q12, q12, #2
491         vadd.i64 q0, q0, q12
492         vshr.u64 q11, q2, #26
493         vand q2, q2, q15
494         vadd.i64 q3, q3, q11
495         vshr.u64 q12, q0, #26
496         vand q0, q0, q15
497         vadd.i64 q1, q1, q12
498         vshr.u64 q11, q3, #26
499         vand q3, q3, q15
500         vadd.i64 q4, q4, q11
501         vmovn.i64 d21, q0
502         vmovn.i64 d22, q1
503         vmovn.i64 d23, q2
504         vmovn.i64 d24, q3
505         vmovn.i64 d25, q4
506 .Lpoly1305_blocks_neon_done:
507         tst r0, r0
508         beq .Lpoly1305_blocks_neon_final
509         ldr r2, [sp, #108]
510         add r2, r2, #60
511         vst1.64 {d21}, [r2]!
512         vst1.64 {d22-d25}, [r2]
513         b .Lpoly1305_blocks_neon_leave
514 .Lpoly1305_blocks_neon_final:
515         vadd.u32 d10, d0, d1
516         vadd.u32 d13, d2, d3
517         vadd.u32 d11, d4, d5
518         ldr r5, [sp, #108]
519         vadd.u32 d14, d6, d7
520         vadd.u32 d12, d8, d9
521         vtrn.32 d10, d13
522         vtrn.32 d11, d14
523         vst1.64 {d10-d12}, [sp]
524         ldm sp, {r0-r4}
525         mov r12, r0, lsr #26
526         and r0, r0, #0x3ffffff
527         add r1, r1, r12
528         mov r12, r1, lsr #26
529         and r1, r1, #0x3ffffff
530         add r2, r2, r12
531         mov r12, r2, lsr #26
532         and r2, r2, #0x3ffffff
533         add r3, r3, r12
534         mov r12, r3, lsr #26
535         and r3, r3, #0x3ffffff
536         add r4, r4, r12
537         mov r12, r4, lsr #26
538         and r4, r4, #0x3ffffff
539         add r12, r12, r12, lsl #2
540         add r0, r0, r12
541         mov r12, r0, lsr #26
542         and r0, r0, #0x3ffffff
543         add r1, r1, r12
544         mov r12, r1, lsr #26
545         and r1, r1, #0x3ffffff
546         add r2, r2, r12
547         mov r12, r2, lsr #26
548         and r2, r2, #0x3ffffff
549         add r3, r3, r12
550         mov r12, r3, lsr #26
551         and r3, r3, #0x3ffffff
552         add r4, r4, r12
553         mov r12, r4, lsr #26
554         and r4, r4, #0x3ffffff
555         add r12, r12, r12, lsl #2
556         add r0, r0, r12
557         mov r12, r0, lsr #26
558         and r0, r0, #0x3ffffff
559         add r1, r1, r12
560         add r6, r0, #5
561         mov r12, r6, lsr #26
562         and r6, r6, #0x3ffffff
563         add r7, r1, r12
564         mov r12, r7, lsr #26
565         and r7, r7, #0x3ffffff
566         add r10, r2, r12
567         mov r12, r10, lsr #26
568         and r10, r10, #0x3ffffff
569         add r11, r3, r12
570         mov r12, #-(1 << 26)
571         add r12, r12, r11, lsr #26
572         and r11, r11, #0x3ffffff
573         add r14, r4, r12
574         mov r12, r14, lsr #31
575         sub r12, #1
576         and r6, r6, r12
577         and r7, r7, r12
578         and r10, r10, r12
579         and r11, r11, r12
580         and r14, r14, r12
581         mvn r12, r12
582         and r0, r0, r12
583         and r1, r1, r12
584         and r2, r2, r12
585         and r3, r3, r12
586         and r4, r4, r12
587         orr r0, r0, r6
588         orr r1, r1, r7
589         orr r2, r2, r10
590         orr r3, r3, r11
591         orr r4, r4, r14
592         orr r0, r0, r1, lsl #26
593         lsr r1, r1, #6
594         orr r1, r1, r2, lsl #20
595         lsr r2, r2, #12
596         orr r2, r2, r3, lsl #14
597         lsr r3, r3, #18
598         orr r3, r3, r4, lsl #8
599         add r5, r5, #60
600         stm r5, {r0-r3}
601 .Lpoly1305_blocks_neon_leave:
602         sub r0, sp, #8
603         ldr sp, [sp, #120]
604         ldmfd sp!, {r4-r11, lr}
605         vldm sp!, {q4-q7}
606         sub r0, sp, r0
607         bx lr
608 .size _gcry_poly1305_armv7_neon_blocks,.-_gcry_poly1305_armv7_neon_blocks;
609
610 .globl _gcry_poly1305_armv7_neon_finish_ext
611 .type  _gcry_poly1305_armv7_neon_finish_ext,%function;
612 _gcry_poly1305_armv7_neon_finish_ext:
613 .Lpoly1305_finish_ext_neon_local:
614         stmfd sp!, {r4-r11, lr}
615         sub sp, sp, #32
616         mov r5, r0
617         mov r6, r1
618         mov r7, r2
619         mov r8, r3
620         ands r7, r7, r7
621         beq .Lpoly1305_finish_ext_neon_noremaining
622         mov r9, sp
623         veor q0, q0, q0
624         veor q1, q1, q1
625         vst1.64 {q0-q1}, [sp]
626         tst r7, #16
627         beq .Lpoly1305_finish_ext_neon_skip16
628         vld1.u64 {q0}, [r1]!
629         vst1.64 {q0}, [r9]!
630 .Lpoly1305_finish_ext_neon_skip16:
631         tst r7, #8
632         beq .Lpoly1305_finish_ext_neon_skip8
633         ldmia r1!, {r10-r11}
634         stmia r9!, {r10-r11}
635 .Lpoly1305_finish_ext_neon_skip8:
636         tst r7, #4
637         beq .Lpoly1305_finish_ext_neon_skip4
638         ldr r10, [r1], #4
639         str r10, [r9], #4
640 .Lpoly1305_finish_ext_neon_skip4:
641         tst r7, #2
642         beq .Lpoly1305_finish_ext_neon_skip2
643         ldrh r10, [r1], #2
644         strh r10, [r9], #2
645 .Lpoly1305_finish_ext_neon_skip2:
646         tst r7, #1
647         beq .Lpoly1305_finish_ext_neon_skip1
648         ldrb r10, [r1], #1
649         strb r10, [r9], #1
650 .Lpoly1305_finish_ext_neon_skip1:
651         cmp r7, #16
652         beq .Lpoly1305_finish_ext_neon_skipfinalbit
653         mov r10, #1
654         strb r10, [r9]
655 .Lpoly1305_finish_ext_neon_skipfinalbit:
656         ldr r10, [r5, #116]
657         orrhs r10, #2
658         orrlo r10, #4
659         str r10, [r5, #116]
660         mov r0, r5
661         mov r1, sp
662         mov r2, #32
663         bl .Lpoly1305_blocks_neon_local
664 .Lpoly1305_finish_ext_neon_noremaining:
665         ldr r10, [r5, #116]
666         tst r10, #1
667         beq .Lpoly1305_finish_ext_neon_notstarted
668         cmp r7, #0
669         beq .Lpoly1305_finish_ext_neon_user2r
670         cmp r7, #16
671         bls .Lpoly1305_finish_ext_neon_user1
672 .Lpoly1305_finish_ext_neon_user2r:
673         orr r10, r10, #8
674         b .Lpoly1305_finish_ext_neon_finalblock
675 .Lpoly1305_finish_ext_neon_user1:
676         orr r10, r10, #16
677 .Lpoly1305_finish_ext_neon_finalblock:
678         str r10, [r5, #116]
679         mov r0, r5
680         eor r1, r1, r1
681         mov r2, #32
682         bl .Lpoly1305_blocks_neon_local
683 .Lpoly1305_finish_ext_neon_notstarted:
684         add r0, r5, #60
685         add r9, r5, #100
686         ldm r0, {r0-r3}
687         ldm r9, {r9-r12}
688         adds r0, r0, r9
689         adcs r1, r1, r10
690         adcs r2, r2, r11
691         adcs r3, r3, r12
692         stm r8, {r0-r3}
693         veor q0, q0, q0
694         veor q1, q1, q1
695         veor q2, q2, q2
696         veor q3, q3, q3
697         vstmia r5!, {q0-q3}
698         vstm r5, {q0-q3}
699         add sp, sp, #32
700         ldmfd sp!, {r4-r11, lr}
701         mov r0, #(9*4+32)
702         bx lr
703 .size _gcry_poly1305_armv7_neon_finish_ext,.-_gcry_poly1305_armv7_neon_finish_ext;
704
705 #endif