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