1 #include "arm_arch.h"
2 
3 #if defined(__thumb2__)
4 .syntax	unified
5 .thumb
6 #else
7 .code	32
8 #endif
9 
10 .text
11 
12 .globl	poly1305_emit
13 .globl	poly1305_blocks
14 .globl	poly1305_init
15 .type	poly1305_init,%function
16 .align	5
17 poly1305_init:
18 .Lpoly1305_init:
19 	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11}
20 
21 	eor	r3,r3,r3
22 	cmp	r1,#0
23 	str	r3,[r0,#0]		@ zero hash value
24 	str	r3,[r0,#4]
25 	str	r3,[r0,#8]
26 	str	r3,[r0,#12]
27 	str	r3,[r0,#16]
28 	str	r3,[r0,#36]		@ is_base2_26
29 	add	r0,r0,#20
30 
31 #ifdef	__thumb2__
32 	it	eq
33 #endif
34 	moveq	r0,#0
35 	beq	.Lno_key
36 
37 #if	__ARM_MAX_ARCH__>=7
38 	adr	r11,.Lpoly1305_init
39 	ldr	r12,.LOPENSSL_armcap
40 #endif
41 	ldrb	r4,[r1,#0]
42 	mov	r10,#0x0fffffff
43 	ldrb	r5,[r1,#1]
44 	and	r3,r10,#-4		@ 0x0ffffffc
45 	ldrb	r6,[r1,#2]
46 	ldrb	r7,[r1,#3]
47 	orr	r4,r4,r5,lsl#8
48 	ldrb	r5,[r1,#4]
49 	orr	r4,r4,r6,lsl#16
50 	ldrb	r6,[r1,#5]
51 	orr	r4,r4,r7,lsl#24
52 	ldrb	r7,[r1,#6]
53 	and	r4,r4,r10
54 
55 #if	__ARM_MAX_ARCH__>=7
56 # if !defined(_WIN32)
57 	ldr	r12,[r11,r12]		@ OPENSSL_armcap_P
58 # endif
59 # if defined(__APPLE__) || defined(_WIN32)
60 	ldr	r12,[r12]
61 # endif
62 #endif
63 	ldrb	r8,[r1,#7]
64 	orr	r5,r5,r6,lsl#8
65 	ldrb	r6,[r1,#8]
66 	orr	r5,r5,r7,lsl#16
67 	ldrb	r7,[r1,#9]
68 	orr	r5,r5,r8,lsl#24
69 	ldrb	r8,[r1,#10]
70 	and	r5,r5,r3
71 
72 #if	__ARM_MAX_ARCH__>=7
73 	tst	r12,#ARMV7_NEON		@ check for NEON
74 # ifdef	__thumb2__
75 	adr	r9,.Lpoly1305_blocks_neon
76 	adr	r11,.Lpoly1305_blocks
77 	adr	r12,.Lpoly1305_emit
78 	adr	r10,.Lpoly1305_emit_neon
79 	itt	ne
80 	movne	r11,r9
81 	movne	r12,r10
82 	orr	r11,r11,#1	@ thumb-ify address
83 	orr	r12,r12,#1
84 # else
85 	addeq	r12,r11,#(.Lpoly1305_emit-.Lpoly1305_init)
86 	addne	r12,r11,#(.Lpoly1305_emit_neon-.Lpoly1305_init)
87 	addeq	r11,r11,#(.Lpoly1305_blocks-.Lpoly1305_init)
88 	addne	r11,r11,#(.Lpoly1305_blocks_neon-.Lpoly1305_init)
89 # endif
90 #endif
91 	ldrb	r9,[r1,#11]
92 	orr	r6,r6,r7,lsl#8
93 	ldrb	r7,[r1,#12]
94 	orr	r6,r6,r8,lsl#16
95 	ldrb	r8,[r1,#13]
96 	orr	r6,r6,r9,lsl#24
97 	ldrb	r9,[r1,#14]
98 	and	r6,r6,r3
99 
100 	ldrb	r10,[r1,#15]
101 	orr	r7,r7,r8,lsl#8
102 	str	r4,[r0,#0]
103 	orr	r7,r7,r9,lsl#16
104 	str	r5,[r0,#4]
105 	orr	r7,r7,r10,lsl#24
106 	str	r6,[r0,#8]
107 	and	r7,r7,r3
108 	str	r7,[r0,#12]
109 #if	__ARM_MAX_ARCH__>=7
110 	stmia	r2,{r11,r12}		@ fill functions table
111 	mov	r0,#1
112 #else
113 	mov	r0,#0
114 #endif
115 .Lno_key:
116 	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11}
117 #if	__ARM_ARCH__>=5
118 	bx	lr				@ bx	lr
119 #else
120 	tst	lr,#1
121 	moveq	pc,lr			@ be binary compatible with V4, yet
122 .word	0xe12fff1e			@ interoperable with Thumb ISA:-)
123 #endif
124 .size	poly1305_init,.-poly1305_init
125 .type	poly1305_blocks,%function
126 .align	5
127 poly1305_blocks:
128 .Lpoly1305_blocks:
129 	stmdb	sp!,{r3,r4,r5,r6,r7,r8,r9,r10,r11,lr}
130 
131 	ands	r2,r2,#-16
132 	beq	.Lno_data
133 
134 	cmp	r3,#0
135 	add	r2,r2,r1		@ end pointer
136 	sub	sp,sp,#32
137 
138 	ldmia	r0,{r4,r5,r6,r7,r8,r9,r10,r11,r12}		@ load context
139 
140 	str	r0,[sp,#12]		@ offload stuff
141 	mov	lr,r1
142 	str	r2,[sp,#16]
143 	str	r10,[sp,#20]
144 	str	r11,[sp,#24]
145 	str	r12,[sp,#28]
146 	b	.Loop
147 
148 .Loop:
149 #if __ARM_ARCH__<7
150 	ldrb	r0,[lr],#16		@ load input
151 # ifdef	__thumb2__
152 	it	hi
153 # endif
154 	addhi	r8,r8,#1		@ 1<<128
155 	ldrb	r1,[lr,#-15]
156 	ldrb	r2,[lr,#-14]
157 	ldrb	r3,[lr,#-13]
158 	orr	r1,r0,r1,lsl#8
159 	ldrb	r0,[lr,#-12]
160 	orr	r2,r1,r2,lsl#16
161 	ldrb	r1,[lr,#-11]
162 	orr	r3,r2,r3,lsl#24
163 	ldrb	r2,[lr,#-10]
164 	adds	r4,r4,r3		@ accumulate input
165 
166 	ldrb	r3,[lr,#-9]
167 	orr	r1,r0,r1,lsl#8
168 	ldrb	r0,[lr,#-8]
169 	orr	r2,r1,r2,lsl#16
170 	ldrb	r1,[lr,#-7]
171 	orr	r3,r2,r3,lsl#24
172 	ldrb	r2,[lr,#-6]
173 	adcs	r5,r5,r3
174 
175 	ldrb	r3,[lr,#-5]
176 	orr	r1,r0,r1,lsl#8
177 	ldrb	r0,[lr,#-4]
178 	orr	r2,r1,r2,lsl#16
179 	ldrb	r1,[lr,#-3]
180 	orr	r3,r2,r3,lsl#24
181 	ldrb	r2,[lr,#-2]
182 	adcs	r6,r6,r3
183 
184 	ldrb	r3,[lr,#-1]
185 	orr	r1,r0,r1,lsl#8
186 	str	lr,[sp,#8]		@ offload input pointer
187 	orr	r2,r1,r2,lsl#16
188 	add	r10,r10,r10,lsr#2
189 	orr	r3,r2,r3,lsl#24
190 #else
191 	ldr	r0,[lr],#16		@ load input
192 # ifdef	__thumb2__
193 	it	hi
194 # endif
195 	addhi	r8,r8,#1		@ padbit
196 	ldr	r1,[lr,#-12]
197 	ldr	r2,[lr,#-8]
198 	ldr	r3,[lr,#-4]
199 # ifdef	__ARMEB__
200 	rev	r0,r0
201 	rev	r1,r1
202 	rev	r2,r2
203 	rev	r3,r3
204 # endif
205 	adds	r4,r4,r0		@ accumulate input
206 	str	lr,[sp,#8]		@ offload input pointer
207 	adcs	r5,r5,r1
208 	add	r10,r10,r10,lsr#2
209 	adcs	r6,r6,r2
210 #endif
211 	add	r11,r11,r11,lsr#2
212 	adcs	r7,r7,r3
213 	add	r12,r12,r12,lsr#2
214 
215 	umull	r2,r3,r5,r9
216 	adc	r8,r8,#0
217 	umull	r0,r1,r4,r9
218 	umlal	r2,r3,r8,r10
219 	umlal	r0,r1,r7,r10
220 	ldr	r10,[sp,#20]		@ reload r10
221 	umlal	r2,r3,r6,r12
222 	umlal	r0,r1,r5,r12
223 	umlal	r2,r3,r7,r11
224 	umlal	r0,r1,r6,r11
225 	umlal	r2,r3,r4,r10
226 	str	r0,[sp,#0]		@ future r4
227 	mul	r0,r11,r8
228 	ldr	r11,[sp,#24]		@ reload r11
229 	adds	r2,r2,r1		@ d1+=d0>>32
230 	eor	r1,r1,r1
231 	adc	lr,r3,#0		@ future r6
232 	str	r2,[sp,#4]		@ future r5
233 
234 	mul	r2,r12,r8
235 	eor	r3,r3,r3
236 	umlal	r0,r1,r7,r12
237 	ldr	r12,[sp,#28]		@ reload r12
238 	umlal	r2,r3,r7,r9
239 	umlal	r0,r1,r6,r9
240 	umlal	r2,r3,r6,r10
241 	umlal	r0,r1,r5,r10
242 	umlal	r2,r3,r5,r11
243 	umlal	r0,r1,r4,r11
244 	umlal	r2,r3,r4,r12
245 	ldr	r4,[sp,#0]
246 	mul	r8,r9,r8
247 	ldr	r5,[sp,#4]
248 
249 	adds	r6,lr,r0		@ d2+=d1>>32
250 	ldr	lr,[sp,#8]		@ reload input pointer
251 	adc	r1,r1,#0
252 	adds	r7,r2,r1		@ d3+=d2>>32
253 	ldr	r0,[sp,#16]		@ reload end pointer
254 	adc	r3,r3,#0
255 	add	r8,r8,r3		@ h4+=d3>>32
256 
257 	and	r1,r8,#-4
258 	and	r8,r8,#3
259 	add	r1,r1,r1,lsr#2		@ *=5
260 	adds	r4,r4,r1
261 	adcs	r5,r5,#0
262 	adcs	r6,r6,#0
263 	adcs	r7,r7,#0
264 	adc	r8,r8,#0
265 
266 	cmp	r0,lr			@ done yet?
267 	bhi	.Loop
268 
269 	ldr	r0,[sp,#12]
270 	add	sp,sp,#32
271 	stmia	r0,{r4,r5,r6,r7,r8}		@ store the result
272 
273 .Lno_data:
274 #if	__ARM_ARCH__>=5
275 	ldmia	sp!,{r3,r4,r5,r6,r7,r8,r9,r10,r11,pc}
276 #else
277 	ldmia	sp!,{r3,r4,r5,r6,r7,r8,r9,r10,r11,lr}
278 	tst	lr,#1
279 	moveq	pc,lr			@ be binary compatible with V4, yet
280 .word	0xe12fff1e			@ interoperable with Thumb ISA:-)
281 #endif
282 .size	poly1305_blocks,.-poly1305_blocks
283 .type	poly1305_emit,%function
284 .align	5
285 poly1305_emit:
286 .Lpoly1305_emit:
287 	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11}
288 .Lpoly1305_emit_enter:
289 
290 	ldmia	r0,{r3,r4,r5,r6,r7}
291 	adds	r8,r3,#5		@ compare to modulus
292 	adcs	r9,r4,#0
293 	adcs	r10,r5,#0
294 	adcs	r11,r6,#0
295 	adc	r7,r7,#0
296 	tst	r7,#4			@ did it carry/borrow?
297 
298 #ifdef	__thumb2__
299 	it	ne
300 #endif
301 	movne	r3,r8
302 	ldr	r8,[r2,#0]
303 #ifdef	__thumb2__
304 	it	ne
305 #endif
306 	movne	r4,r9
307 	ldr	r9,[r2,#4]
308 #ifdef	__thumb2__
309 	it	ne
310 #endif
311 	movne	r5,r10
312 	ldr	r10,[r2,#8]
313 #ifdef	__thumb2__
314 	it	ne
315 #endif
316 	movne	r6,r11
317 	ldr	r11,[r2,#12]
318 
319 	adds	r3,r3,r8
320 	adcs	r4,r4,r9
321 	adcs	r5,r5,r10
322 	adc	r6,r6,r11
323 
324 #if __ARM_ARCH__>=7
325 # ifdef __ARMEB__
326 	rev	r3,r3
327 	rev	r4,r4
328 	rev	r5,r5
329 	rev	r6,r6
330 # endif
331 	str	r3,[r1,#0]
332 	str	r4,[r1,#4]
333 	str	r5,[r1,#8]
334 	str	r6,[r1,#12]
335 #else
336 	strb	r3,[r1,#0]
337 	mov	r3,r3,lsr#8
338 	strb	r4,[r1,#4]
339 	mov	r4,r4,lsr#8
340 	strb	r5,[r1,#8]
341 	mov	r5,r5,lsr#8
342 	strb	r6,[r1,#12]
343 	mov	r6,r6,lsr#8
344 
345 	strb	r3,[r1,#1]
346 	mov	r3,r3,lsr#8
347 	strb	r4,[r1,#5]
348 	mov	r4,r4,lsr#8
349 	strb	r5,[r1,#9]
350 	mov	r5,r5,lsr#8
351 	strb	r6,[r1,#13]
352 	mov	r6,r6,lsr#8
353 
354 	strb	r3,[r1,#2]
355 	mov	r3,r3,lsr#8
356 	strb	r4,[r1,#6]
357 	mov	r4,r4,lsr#8
358 	strb	r5,[r1,#10]
359 	mov	r5,r5,lsr#8
360 	strb	r6,[r1,#14]
361 	mov	r6,r6,lsr#8
362 
363 	strb	r3,[r1,#3]
364 	strb	r4,[r1,#7]
365 	strb	r5,[r1,#11]
366 	strb	r6,[r1,#15]
367 #endif
368 	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11}
369 #if	__ARM_ARCH__>=5
370 	bx	lr				@ bx	lr
371 #else
372 	tst	lr,#1
373 	moveq	pc,lr			@ be binary compatible with V4, yet
374 .word	0xe12fff1e			@ interoperable with Thumb ISA:-)
375 #endif
376 .size	poly1305_emit,.-poly1305_emit
377 #if	__ARM_MAX_ARCH__>=7
378 .fpu	neon
379 
380 .type	poly1305_init_neon,%function
381 .align	5
382 poly1305_init_neon:
383 	ldr	r4,[r0,#20]		@ load key base 2^32
384 	ldr	r5,[r0,#24]
385 	ldr	r6,[r0,#28]
386 	ldr	r7,[r0,#32]
387 
388 	and	r2,r4,#0x03ffffff	@ base 2^32 -> base 2^26
389 	mov	r3,r4,lsr#26
390 	mov	r4,r5,lsr#20
391 	orr	r3,r3,r5,lsl#6
392 	mov	r5,r6,lsr#14
393 	orr	r4,r4,r6,lsl#12
394 	mov	r6,r7,lsr#8
395 	orr	r5,r5,r7,lsl#18
396 	and	r3,r3,#0x03ffffff
397 	and	r4,r4,#0x03ffffff
398 	and	r5,r5,#0x03ffffff
399 
400 	vdup.32	d0,r2			@ r^1 in both lanes
401 	add	r2,r3,r3,lsl#2		@ *5
402 	vdup.32	d1,r3
403 	add	r3,r4,r4,lsl#2
404 	vdup.32	d2,r2
405 	vdup.32	d3,r4
406 	add	r4,r5,r5,lsl#2
407 	vdup.32	d4,r3
408 	vdup.32	d5,r5
409 	add	r5,r6,r6,lsl#2
410 	vdup.32	d6,r4
411 	vdup.32	d7,r6
412 	vdup.32	d8,r5
413 
414 	mov	r5,#2		@ counter
415 
416 .Lsquare_neon:
417 	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
418 	@ d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
419 	@ d1 = h1*r0 + h0*r1   + h4*5*r2 + h3*5*r3 + h2*5*r4
420 	@ d2 = h2*r0 + h1*r1   + h0*r2   + h4*5*r3 + h3*5*r4
421 	@ d3 = h3*r0 + h2*r1   + h1*r2   + h0*r3   + h4*5*r4
422 	@ d4 = h4*r0 + h3*r1   + h2*r2   + h1*r3   + h0*r4
423 
424 	vmull.u32	q5,d0,d0[1]
425 	vmull.u32	q6,d1,d0[1]
426 	vmull.u32	q7,d3,d0[1]
427 	vmull.u32	q8,d5,d0[1]
428 	vmull.u32	q9,d7,d0[1]
429 
430 	vmlal.u32	q5,d7,d2[1]
431 	vmlal.u32	q6,d0,d1[1]
432 	vmlal.u32	q7,d1,d1[1]
433 	vmlal.u32	q8,d3,d1[1]
434 	vmlal.u32	q9,d5,d1[1]
435 
436 	vmlal.u32	q5,d5,d4[1]
437 	vmlal.u32	q6,d7,d4[1]
438 	vmlal.u32	q8,d1,d3[1]
439 	vmlal.u32	q7,d0,d3[1]
440 	vmlal.u32	q9,d3,d3[1]
441 
442 	vmlal.u32	q5,d3,d6[1]
443 	vmlal.u32	q8,d0,d5[1]
444 	vmlal.u32	q6,d5,d6[1]
445 	vmlal.u32	q7,d7,d6[1]
446 	vmlal.u32	q9,d1,d5[1]
447 
448 	vmlal.u32	q8,d7,d8[1]
449 	vmlal.u32	q5,d1,d8[1]
450 	vmlal.u32	q6,d3,d8[1]
451 	vmlal.u32	q7,d5,d8[1]
452 	vmlal.u32	q9,d0,d7[1]
453 
454 	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
455 	@ lazy reduction as discussed in "NEON crypto" by D.J. Bernstein
456 	@ and P. Schwabe
457 	@
458 	@ H0>>+H1>>+H2>>+H3>>+H4
459 	@ H3>>+H4>>*5+H0>>+H1
460 	@
461 	@ Trivia.
462 	@
463 	@ Result of multiplication of n-bit number by m-bit number is
464 	@ n+m bits wide. However! Even though 2^n is a n+1-bit number,
465 	@ m-bit number multiplied by 2^n is still n+m bits wide.
466 	@
467 	@ Sum of two n-bit numbers is n+1 bits wide, sum of three - n+2,
468 	@ and so is sum of four. Sum of 2^m n-m-bit numbers and n-bit
469 	@ one is n+1 bits wide.
470 	@
471 	@ >>+ denotes Hnext += Hn>>26, Hn &= 0x3ffffff. This means that
472 	@ H0, H2, H3 are guaranteed to be 26 bits wide, while H1 and H4
473 	@ can be 27. However! In cases when their width exceeds 26 bits
474 	@ they are limited by 2^26+2^6. This in turn means that *sum*
475 	@ of the products with these values can still be viewed as sum
476 	@ of 52-bit numbers as long as the amount of addends is not a
477 	@ power of 2. For example,
478 	@
479 	@ H4 = H4*R0 + H3*R1 + H2*R2 + H1*R3 + H0 * R4,
480 	@
481 	@ which can't be larger than 5 * (2^26 + 2^6) * (2^26 + 2^6), or
482 	@ 5 * (2^52 + 2*2^32 + 2^12), which in turn is smaller than
483 	@ 8 * (2^52) or 2^55. However, the value is then multiplied by
484 	@ by 5, so we should be looking at 5 * 5 * (2^52 + 2^33 + 2^12),
485 	@ which is less than 32 * (2^52) or 2^57. And when processing
486 	@ data we are looking at triple as many addends...
487 	@
488 	@ In key setup procedure pre-reduced H0 is limited by 5*4+1 and
489 	@ 5*H4 - by 5*5 52-bit addends, or 57 bits. But when hashing the
490 	@ input H0 is limited by (5*4+1)*3 addends, or 58 bits, while
491 	@ 5*H4 by 5*5*3, or 59[!] bits. How is this relevant? vmlal.u32
492 	@ instruction accepts 2x32-bit input and writes 2x64-bit result.
493 	@ This means that result of reduction have to be compressed upon
494 	@ loop wrap-around. This can be done in the process of reduction
495 	@ to minimize amount of instructions [as well as amount of
496 	@ 128-bit instructions, which benefits low-end processors], but
497 	@ one has to watch for H2 (which is narrower than H0) and 5*H4
498 	@ not being wider than 58 bits, so that result of right shift
499 	@ by 26 bits fits in 32 bits. This is also useful on x86,
500 	@ because it allows to use paddd in place for paddq, which
501 	@ benefits Atom, where paddq is ridiculously slow.
502 
503 	vshr.u64	q15,q8,#26
504 	vmovn.i64	d16,q8
505 	vshr.u64	q4,q5,#26
506 	vmovn.i64	d10,q5
507 	vadd.i64	q9,q9,q15		@ h3 -> h4
508 	vbic.i32	d16,#0xfc000000	@ &=0x03ffffff
509 	vadd.i64	q6,q6,q4		@ h0 -> h1
510 	vbic.i32	d10,#0xfc000000
511 
512 	vshrn.u64	d30,q9,#26
513 	vmovn.i64	d18,q9
514 	vshr.u64	q4,q6,#26
515 	vmovn.i64	d12,q6
516 	vadd.i64	q7,q7,q4		@ h1 -> h2
517 	vbic.i32	d18,#0xfc000000
518 	vbic.i32	d12,#0xfc000000
519 
520 	vadd.i32	d10,d10,d30
521 	vshl.u32	d30,d30,#2
522 	vshrn.u64	d8,q7,#26
523 	vmovn.i64	d14,q7
524 	vadd.i32	d10,d10,d30	@ h4 -> h0
525 	vadd.i32	d16,d16,d8	@ h2 -> h3
526 	vbic.i32	d14,#0xfc000000
527 
528 	vshr.u32	d30,d10,#26
529 	vbic.i32	d10,#0xfc000000
530 	vshr.u32	d8,d16,#26
531 	vbic.i32	d16,#0xfc000000
532 	vadd.i32	d12,d12,d30	@ h0 -> h1
533 	vadd.i32	d18,d18,d8	@ h3 -> h4
534 
535 	subs	r5,r5,#1
536 	beq	.Lsquare_break_neon
537 
538 	add	r6,r0,#(48+0*9*4)
539 	add	r7,r0,#(48+1*9*4)
540 
541 	vtrn.32	d0,d10		@ r^2:r^1
542 	vtrn.32	d3,d14
543 	vtrn.32	d5,d16
544 	vtrn.32	d1,d12
545 	vtrn.32	d7,d18
546 
547 	vshl.u32	d4,d3,#2		@ *5
548 	vshl.u32	d6,d5,#2
549 	vshl.u32	d2,d1,#2
550 	vshl.u32	d8,d7,#2
551 	vadd.i32	d4,d4,d3
552 	vadd.i32	d2,d2,d1
553 	vadd.i32	d6,d6,d5
554 	vadd.i32	d8,d8,d7
555 
556 	vst4.32	{d0[0],d1[0],d2[0],d3[0]},[r6]!
557 	vst4.32	{d0[1],d1[1],d2[1],d3[1]},[r7]!
558 	vst4.32	{d4[0],d5[0],d6[0],d7[0]},[r6]!
559 	vst4.32	{d4[1],d5[1],d6[1],d7[1]},[r7]!
560 	vst1.32	{d8[0]},[r6,:32]
561 	vst1.32	{d8[1]},[r7,:32]
562 
563 	b	.Lsquare_neon
564 
565 .align	4
566 .Lsquare_break_neon:
567 	add	r6,r0,#(48+2*4*9)
568 	add	r7,r0,#(48+3*4*9)
569 
570 	vmov	d0,d10		@ r^4:r^3
571 	vshl.u32	d2,d12,#2		@ *5
572 	vmov	d1,d12
573 	vshl.u32	d4,d14,#2
574 	vmov	d3,d14
575 	vshl.u32	d6,d16,#2
576 	vmov	d5,d16
577 	vshl.u32	d8,d18,#2
578 	vmov	d7,d18
579 	vadd.i32	d2,d2,d12
580 	vadd.i32	d4,d4,d14
581 	vadd.i32	d6,d6,d16
582 	vadd.i32	d8,d8,d18
583 
584 	vst4.32	{d0[0],d1[0],d2[0],d3[0]},[r6]!
585 	vst4.32	{d0[1],d1[1],d2[1],d3[1]},[r7]!
586 	vst4.32	{d4[0],d5[0],d6[0],d7[0]},[r6]!
587 	vst4.32	{d4[1],d5[1],d6[1],d7[1]},[r7]!
588 	vst1.32	{d8[0]},[r6]
589 	vst1.32	{d8[1]},[r7]
590 
591 	bx	lr				@ bx	lr
592 .size	poly1305_init_neon,.-poly1305_init_neon
593 
594 .type	poly1305_blocks_neon,%function
595 .align	5
596 poly1305_blocks_neon:
597 .Lpoly1305_blocks_neon:
598 	ldr	ip,[r0,#36]		@ is_base2_26
599 	ands	r2,r2,#-16
600 	beq	.Lno_data_neon
601 
602 	cmp	r2,#64
603 	bhs	.Lenter_neon
604 	tst	ip,ip			@ is_base2_26?
605 	beq	.Lpoly1305_blocks
606 
607 .Lenter_neon:
608 	stmdb	sp!,{r4,r5,r6,r7}
609 	vstmdb	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}		@ ABI specification says so
610 
611 	tst	ip,ip			@ is_base2_26?
612 	bne	.Lbase2_26_neon
613 
614 	stmdb	sp!,{r1,r2,r3,lr}
615 	bl	poly1305_init_neon
616 
617 	ldr	r4,[r0,#0]		@ load hash value base 2^32
618 	ldr	r5,[r0,#4]
619 	ldr	r6,[r0,#8]
620 	ldr	r7,[r0,#12]
621 	ldr	ip,[r0,#16]
622 
623 	and	r2,r4,#0x03ffffff	@ base 2^32 -> base 2^26
624 	mov	r3,r4,lsr#26
625 	veor	d10,d10,d10
626 	mov	r4,r5,lsr#20
627 	orr	r3,r3,r5,lsl#6
628 	veor	d12,d12,d12
629 	mov	r5,r6,lsr#14
630 	orr	r4,r4,r6,lsl#12
631 	veor	d14,d14,d14
632 	mov	r6,r7,lsr#8
633 	orr	r5,r5,r7,lsl#18
634 	veor	d16,d16,d16
635 	and	r3,r3,#0x03ffffff
636 	orr	r6,r6,ip,lsl#24
637 	veor	d18,d18,d18
638 	and	r4,r4,#0x03ffffff
639 	mov	r1,#1
640 	and	r5,r5,#0x03ffffff
641 	str	r1,[r0,#36]		@ is_base2_26
642 
643 	vmov.32	d10[0],r2
644 	vmov.32	d12[0],r3
645 	vmov.32	d14[0],r4
646 	vmov.32	d16[0],r5
647 	vmov.32	d18[0],r6
648 	adr	r5,.Lzeros
649 
650 	ldmia	sp!,{r1,r2,r3,lr}
651 	b	.Lbase2_32_neon
652 
653 .align	4
654 .Lbase2_26_neon:
655 	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
656 	@ load hash value
657 
658 	veor	d10,d10,d10
659 	veor	d12,d12,d12
660 	veor	d14,d14,d14
661 	veor	d16,d16,d16
662 	veor	d18,d18,d18
663 	vld4.32	{d10[0],d12[0],d14[0],d16[0]},[r0]!
664 	adr	r5,.Lzeros
665 	vld1.32	{d18[0]},[r0]
666 	sub	r0,r0,#16		@ rewind
667 
668 .Lbase2_32_neon:
669 	add	r4,r1,#32
670 	mov	r3,r3,lsl#24
671 	tst	r2,#31
672 	beq	.Leven
673 
674 	vld4.32	{d20[0],d22[0],d24[0],d26[0]},[r1]!
675 	vmov.32	d28[0],r3
676 	sub	r2,r2,#16
677 	add	r4,r1,#32
678 
679 # ifdef	__ARMEB__
680 	vrev32.8	q10,q10
681 	vrev32.8	q13,q13
682 	vrev32.8	q11,q11
683 	vrev32.8	q12,q12
684 # endif
685 	vsri.u32	d28,d26,#8	@ base 2^32 -> base 2^26
686 	vshl.u32	d26,d26,#18
687 
688 	vsri.u32	d26,d24,#14
689 	vshl.u32	d24,d24,#12
690 	vadd.i32	d29,d28,d18	@ add hash value and move to #hi
691 
692 	vbic.i32	d26,#0xfc000000
693 	vsri.u32	d24,d22,#20
694 	vshl.u32	d22,d22,#6
695 
696 	vbic.i32	d24,#0xfc000000
697 	vsri.u32	d22,d20,#26
698 	vadd.i32	d27,d26,d16
699 
700 	vbic.i32	d20,#0xfc000000
701 	vbic.i32	d22,#0xfc000000
702 	vadd.i32	d25,d24,d14
703 
704 	vadd.i32	d21,d20,d10
705 	vadd.i32	d23,d22,d12
706 
707 	mov	r7,r5
708 	add	r6,r0,#48
709 
710 	cmp	r2,r2
711 	b	.Long_tail
712 
713 .align	4
714 .Leven:
715 	subs	r2,r2,#64
716 	it	lo
717 	movlo	r4,r5
718 
719 	vmov.i32	q14,#1<<24		@ padbit, yes, always
720 	vld4.32	{d20,d22,d24,d26},[r1]	@ inp[0:1]
721 	add	r1,r1,#64
722 	vld4.32	{d21,d23,d25,d27},[r4]	@ inp[2:3] (or 0)
723 	add	r4,r4,#64
724 	itt	hi
725 	addhi	r7,r0,#(48+1*9*4)
726 	addhi	r6,r0,#(48+3*9*4)
727 
728 # ifdef	__ARMEB__
729 	vrev32.8	q10,q10
730 	vrev32.8	q13,q13
731 	vrev32.8	q11,q11
732 	vrev32.8	q12,q12
733 # endif
734 	vsri.u32	q14,q13,#8		@ base 2^32 -> base 2^26
735 	vshl.u32	q13,q13,#18
736 
737 	vsri.u32	q13,q12,#14
738 	vshl.u32	q12,q12,#12
739 
740 	vbic.i32	q13,#0xfc000000
741 	vsri.u32	q12,q11,#20
742 	vshl.u32	q11,q11,#6
743 
744 	vbic.i32	q12,#0xfc000000
745 	vsri.u32	q11,q10,#26
746 
747 	vbic.i32	q10,#0xfc000000
748 	vbic.i32	q11,#0xfc000000
749 
750 	bls	.Lskip_loop
751 
752 	vld4.32	{d0[1],d1[1],d2[1],d3[1]},[r7]!	@ load r^2
753 	vld4.32	{d0[0],d1[0],d2[0],d3[0]},[r6]!	@ load r^4
754 	vld4.32	{d4[1],d5[1],d6[1],d7[1]},[r7]!
755 	vld4.32	{d4[0],d5[0],d6[0],d7[0]},[r6]!
756 	b	.Loop_neon
757 
758 .align	5
759 .Loop_neon:
760 	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
761 	@ ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2
762 	@ ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r
763 	@   ___________________/
764 	@ ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2
765 	@ ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r
766 	@   ___________________/ ____________________/
767 	@
768 	@ Note that we start with inp[2:3]*r^2. This is because it
769 	@ doesn't depend on reduction in previous iteration.
770 	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
771 	@ d4 = h4*r0 + h3*r1   + h2*r2   + h1*r3   + h0*r4
772 	@ d3 = h3*r0 + h2*r1   + h1*r2   + h0*r3   + h4*5*r4
773 	@ d2 = h2*r0 + h1*r1   + h0*r2   + h4*5*r3 + h3*5*r4
774 	@ d1 = h1*r0 + h0*r1   + h4*5*r2 + h3*5*r3 + h2*5*r4
775 	@ d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
776 
777 	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
778 	@ inp[2:3]*r^2
779 
780 	vadd.i32	d24,d24,d14	@ accumulate inp[0:1]
781 	vmull.u32	q7,d25,d0[1]
782 	vadd.i32	d20,d20,d10
783 	vmull.u32	q5,d21,d0[1]
784 	vadd.i32	d26,d26,d16
785 	vmull.u32	q8,d27,d0[1]
786 	vmlal.u32	q7,d23,d1[1]
787 	vadd.i32	d22,d22,d12
788 	vmull.u32	q6,d23,d0[1]
789 
790 	vadd.i32	d28,d28,d18
791 	vmull.u32	q9,d29,d0[1]
792 	subs	r2,r2,#64
793 	vmlal.u32	q5,d29,d2[1]
794 	it	lo
795 	movlo	r4,r5
796 	vmlal.u32	q8,d25,d1[1]
797 	vld1.32	d8[1],[r7,:32]
798 	vmlal.u32	q6,d21,d1[1]
799 	vmlal.u32	q9,d27,d1[1]
800 
801 	vmlal.u32	q5,d27,d4[1]
802 	vmlal.u32	q8,d23,d3[1]
803 	vmlal.u32	q9,d25,d3[1]
804 	vmlal.u32	q6,d29,d4[1]
805 	vmlal.u32	q7,d21,d3[1]
806 
807 	vmlal.u32	q8,d21,d5[1]
808 	vmlal.u32	q5,d25,d6[1]
809 	vmlal.u32	q9,d23,d5[1]
810 	vmlal.u32	q6,d27,d6[1]
811 	vmlal.u32	q7,d29,d6[1]
812 
813 	vmlal.u32	q8,d29,d8[1]
814 	vmlal.u32	q5,d23,d8[1]
815 	vmlal.u32	q9,d21,d7[1]
816 	vmlal.u32	q6,d25,d8[1]
817 	vmlal.u32	q7,d27,d8[1]
818 
819 	vld4.32	{d21,d23,d25,d27},[r4]	@ inp[2:3] (or 0)
820 	add	r4,r4,#64
821 
822 	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
823 	@ (hash+inp[0:1])*r^4 and accumulate
824 
825 	vmlal.u32	q8,d26,d0[0]
826 	vmlal.u32	q5,d20,d0[0]
827 	vmlal.u32	q9,d28,d0[0]
828 	vmlal.u32	q6,d22,d0[0]
829 	vmlal.u32	q7,d24,d0[0]
830 	vld1.32	d8[0],[r6,:32]
831 
832 	vmlal.u32	q8,d24,d1[0]
833 	vmlal.u32	q5,d28,d2[0]
834 	vmlal.u32	q9,d26,d1[0]
835 	vmlal.u32	q6,d20,d1[0]
836 	vmlal.u32	q7,d22,d1[0]
837 
838 	vmlal.u32	q8,d22,d3[0]
839 	vmlal.u32	q5,d26,d4[0]
840 	vmlal.u32	q9,d24,d3[0]
841 	vmlal.u32	q6,d28,d4[0]
842 	vmlal.u32	q7,d20,d3[0]
843 
844 	vmlal.u32	q8,d20,d5[0]
845 	vmlal.u32	q5,d24,d6[0]
846 	vmlal.u32	q9,d22,d5[0]
847 	vmlal.u32	q6,d26,d6[0]
848 	vmlal.u32	q8,d28,d8[0]
849 
850 	vmlal.u32	q7,d28,d6[0]
851 	vmlal.u32	q5,d22,d8[0]
852 	vmlal.u32	q9,d20,d7[0]
853 	vmov.i32	q14,#1<<24		@ padbit, yes, always
854 	vmlal.u32	q6,d24,d8[0]
855 	vmlal.u32	q7,d26,d8[0]
856 
857 	vld4.32	{d20,d22,d24,d26},[r1]	@ inp[0:1]
858 	add	r1,r1,#64
859 # ifdef	__ARMEB__
860 	vrev32.8	q10,q10
861 	vrev32.8	q11,q11
862 	vrev32.8	q12,q12
863 	vrev32.8	q13,q13
864 # endif
865 
866 	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
867 	@ lazy reduction interleaved with base 2^32 -> base 2^26 of
868 	@ inp[0:3] previously loaded to q10-q13 and smashed to q10-q14.
869 
870 	vshr.u64	q15,q8,#26
871 	vmovn.i64	d16,q8
872 	vshr.u64	q4,q5,#26
873 	vmovn.i64	d10,q5
874 	vadd.i64	q9,q9,q15		@ h3 -> h4
875 	vbic.i32	d16,#0xfc000000
876 	vsri.u32	q14,q13,#8		@ base 2^32 -> base 2^26
877 	vadd.i64	q6,q6,q4		@ h0 -> h1
878 	vshl.u32	q13,q13,#18
879 	vbic.i32	d10,#0xfc000000
880 
881 	vshrn.u64	d30,q9,#26
882 	vmovn.i64	d18,q9
883 	vshr.u64	q4,q6,#26
884 	vmovn.i64	d12,q6
885 	vadd.i64	q7,q7,q4		@ h1 -> h2
886 	vsri.u32	q13,q12,#14
887 	vbic.i32	d18,#0xfc000000
888 	vshl.u32	q12,q12,#12
889 	vbic.i32	d12,#0xfc000000
890 
891 	vadd.i32	d10,d10,d30
892 	vshl.u32	d30,d30,#2
893 	vbic.i32	q13,#0xfc000000
894 	vshrn.u64	d8,q7,#26
895 	vmovn.i64	d14,q7
896 	vaddl.u32	q5,d10,d30	@ h4 -> h0 [widen for a sec]
897 	vsri.u32	q12,q11,#20
898 	vadd.i32	d16,d16,d8	@ h2 -> h3
899 	vshl.u32	q11,q11,#6
900 	vbic.i32	d14,#0xfc000000
901 	vbic.i32	q12,#0xfc000000
902 
903 	vshrn.u64	d30,q5,#26		@ re-narrow
904 	vmovn.i64	d10,q5
905 	vsri.u32	q11,q10,#26
906 	vbic.i32	q10,#0xfc000000
907 	vshr.u32	d8,d16,#26
908 	vbic.i32	d16,#0xfc000000
909 	vbic.i32	d10,#0xfc000000
910 	vadd.i32	d12,d12,d30	@ h0 -> h1
911 	vadd.i32	d18,d18,d8	@ h3 -> h4
912 	vbic.i32	q11,#0xfc000000
913 
914 	bhi	.Loop_neon
915 
916 .Lskip_loop:
917 	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
918 	@ multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1
919 
920 	add	r7,r0,#(48+0*9*4)
921 	add	r6,r0,#(48+1*9*4)
922 	adds	r2,r2,#32
923 	it	ne
924 	movne	r2,#0
925 	bne	.Long_tail
926 
927 	vadd.i32	d25,d24,d14	@ add hash value and move to #hi
928 	vadd.i32	d21,d20,d10
929 	vadd.i32	d27,d26,d16
930 	vadd.i32	d23,d22,d12
931 	vadd.i32	d29,d28,d18
932 
933 .Long_tail:
934 	vld4.32	{d0[1],d1[1],d2[1],d3[1]},[r7]!	@ load r^1
935 	vld4.32	{d0[0],d1[0],d2[0],d3[0]},[r6]!	@ load r^2
936 
937 	vadd.i32	d24,d24,d14	@ can be redundant
938 	vmull.u32	q7,d25,d0
939 	vadd.i32	d20,d20,d10
940 	vmull.u32	q5,d21,d0
941 	vadd.i32	d26,d26,d16
942 	vmull.u32	q8,d27,d0
943 	vadd.i32	d22,d22,d12
944 	vmull.u32	q6,d23,d0
945 	vadd.i32	d28,d28,d18
946 	vmull.u32	q9,d29,d0
947 
948 	vmlal.u32	q5,d29,d2
949 	vld4.32	{d4[1],d5[1],d6[1],d7[1]},[r7]!
950 	vmlal.u32	q8,d25,d1
951 	vld4.32	{d4[0],d5[0],d6[0],d7[0]},[r6]!
952 	vmlal.u32	q6,d21,d1
953 	vmlal.u32	q9,d27,d1
954 	vmlal.u32	q7,d23,d1
955 
956 	vmlal.u32	q8,d23,d3
957 	vld1.32	d8[1],[r7,:32]
958 	vmlal.u32	q5,d27,d4
959 	vld1.32	d8[0],[r6,:32]
960 	vmlal.u32	q9,d25,d3
961 	vmlal.u32	q6,d29,d4
962 	vmlal.u32	q7,d21,d3
963 
964 	vmlal.u32	q8,d21,d5
965 	it	ne
966 	addne	r7,r0,#(48+2*9*4)
967 	vmlal.u32	q5,d25,d6
968 	it	ne
969 	addne	r6,r0,#(48+3*9*4)
970 	vmlal.u32	q9,d23,d5
971 	vmlal.u32	q6,d27,d6
972 	vmlal.u32	q7,d29,d6
973 
974 	vmlal.u32	q8,d29,d8
975 	vorn	q0,q0,q0	@ all-ones, can be redundant
976 	vmlal.u32	q5,d23,d8
977 	vshr.u64	q0,q0,#38
978 	vmlal.u32	q9,d21,d7
979 	vmlal.u32	q6,d25,d8
980 	vmlal.u32	q7,d27,d8
981 
982 	beq	.Lshort_tail
983 
984 	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
985 	@ (hash+inp[0:1])*r^4:r^3 and accumulate
986 
987 	vld4.32	{d0[1],d1[1],d2[1],d3[1]},[r7]!	@ load r^3
988 	vld4.32	{d0[0],d1[0],d2[0],d3[0]},[r6]!	@ load r^4
989 
990 	vmlal.u32	q7,d24,d0
991 	vmlal.u32	q5,d20,d0
992 	vmlal.u32	q8,d26,d0
993 	vmlal.u32	q6,d22,d0
994 	vmlal.u32	q9,d28,d0
995 
996 	vmlal.u32	q5,d28,d2
997 	vld4.32	{d4[1],d5[1],d6[1],d7[1]},[r7]!
998 	vmlal.u32	q8,d24,d1
999 	vld4.32	{d4[0],d5[0],d6[0],d7[0]},[r6]!
1000 	vmlal.u32	q6,d20,d1
1001 	vmlal.u32	q9,d26,d1
1002 	vmlal.u32	q7,d22,d1
1003 
1004 	vmlal.u32	q8,d22,d3
1005 	vld1.32	d8[1],[r7,:32]
1006 	vmlal.u32	q5,d26,d4
1007 	vld1.32	d8[0],[r6,:32]
1008 	vmlal.u32	q9,d24,d3
1009 	vmlal.u32	q6,d28,d4
1010 	vmlal.u32	q7,d20,d3
1011 
1012 	vmlal.u32	q8,d20,d5
1013 	vmlal.u32	q5,d24,d6
1014 	vmlal.u32	q9,d22,d5
1015 	vmlal.u32	q6,d26,d6
1016 	vmlal.u32	q7,d28,d6
1017 
1018 	vmlal.u32	q8,d28,d8
1019 	vorn	q0,q0,q0	@ all-ones
1020 	vmlal.u32	q5,d22,d8
1021 	vshr.u64	q0,q0,#38
1022 	vmlal.u32	q9,d20,d7
1023 	vmlal.u32	q6,d24,d8
1024 	vmlal.u32	q7,d26,d8
1025 
1026 .Lshort_tail:
1027 	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
1028 	@ horizontal addition
1029 
1030 	vadd.i64	d16,d16,d17
1031 	vadd.i64	d10,d10,d11
1032 	vadd.i64	d18,d18,d19
1033 	vadd.i64	d12,d12,d13
1034 	vadd.i64	d14,d14,d15
1035 
1036 	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
1037 	@ lazy reduction, but without narrowing
1038 
1039 	vshr.u64	q15,q8,#26
1040 	vand.i64	q8,q8,q0
1041 	vshr.u64	q4,q5,#26
1042 	vand.i64	q5,q5,q0
1043 	vadd.i64	q9,q9,q15		@ h3 -> h4
1044 	vadd.i64	q6,q6,q4		@ h0 -> h1
1045 
1046 	vshr.u64	q15,q9,#26
1047 	vand.i64	q9,q9,q0
1048 	vshr.u64	q4,q6,#26
1049 	vand.i64	q6,q6,q0
1050 	vadd.i64	q7,q7,q4		@ h1 -> h2
1051 
1052 	vadd.i64	q5,q5,q15
1053 	vshl.u64	q15,q15,#2
1054 	vshr.u64	q4,q7,#26
1055 	vand.i64	q7,q7,q0
1056 	vadd.i64	q5,q5,q15		@ h4 -> h0
1057 	vadd.i64	q8,q8,q4		@ h2 -> h3
1058 
1059 	vshr.u64	q15,q5,#26
1060 	vand.i64	q5,q5,q0
1061 	vshr.u64	q4,q8,#26
1062 	vand.i64	q8,q8,q0
1063 	vadd.i64	q6,q6,q15		@ h0 -> h1
1064 	vadd.i64	q9,q9,q4		@ h3 -> h4
1065 
1066 	cmp	r2,#0
1067 	bne	.Leven
1068 
1069 	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
1070 	@ store hash value
1071 
1072 	vst4.32	{d10[0],d12[0],d14[0],d16[0]},[r0]!
1073 	vst1.32	{d18[0]},[r0]
1074 
1075 	vldmia	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}			@ epilogue
1076 	ldmia	sp!,{r4,r5,r6,r7}
1077 .Lno_data_neon:
1078 	bx	lr					@ bx	lr
1079 .size	poly1305_blocks_neon,.-poly1305_blocks_neon
1080 
1081 .type	poly1305_emit_neon,%function
1082 .align	5
1083 poly1305_emit_neon:
1084 .Lpoly1305_emit_neon:
1085 	ldr	ip,[r0,#36]		@ is_base2_26
1086 
1087 	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11}
1088 
1089 	tst	ip,ip
1090 	beq	.Lpoly1305_emit_enter
1091 
1092 	ldmia	r0,{r3,r4,r5,r6,r7}
1093 	eor	r8,r8,r8
1094 
1095 	adds	r3,r3,r4,lsl#26	@ base 2^26 -> base 2^32
1096 	mov	r4,r4,lsr#6
1097 	adcs	r4,r4,r5,lsl#20
1098 	mov	r5,r5,lsr#12
1099 	adcs	r5,r5,r6,lsl#14
1100 	mov	r6,r6,lsr#18
1101 	adcs	r6,r6,r7,lsl#8
1102 	adc	r7,r8,r7,lsr#24	@ can be partially reduced ...
1103 
1104 	and	r8,r7,#-4		@ ... so reduce
1105 	and	r7,r6,#3
1106 	add	r8,r8,r8,lsr#2	@ *= 5
1107 	adds	r3,r3,r8
1108 	adcs	r4,r4,#0
1109 	adcs	r5,r5,#0
1110 	adcs	r6,r6,#0
1111 	adc	r7,r7,#0
1112 
1113 	adds	r8,r3,#5		@ compare to modulus
1114 	adcs	r9,r4,#0
1115 	adcs	r10,r5,#0
1116 	adcs	r11,r6,#0
1117 	adc	r7,r7,#0
1118 	tst	r7,#4			@ did it carry/borrow?
1119 
1120 	it	ne
1121 	movne	r3,r8
1122 	ldr	r8,[r2,#0]
1123 	it	ne
1124 	movne	r4,r9
1125 	ldr	r9,[r2,#4]
1126 	it	ne
1127 	movne	r5,r10
1128 	ldr	r10,[r2,#8]
1129 	it	ne
1130 	movne	r6,r11
1131 	ldr	r11,[r2,#12]
1132 
1133 	adds	r3,r3,r8		@ accumulate nonce
1134 	adcs	r4,r4,r9
1135 	adcs	r5,r5,r10
1136 	adc	r6,r6,r11
1137 
1138 # ifdef __ARMEB__
1139 	rev	r3,r3
1140 	rev	r4,r4
1141 	rev	r5,r5
1142 	rev	r6,r6
1143 # endif
1144 	str	r3,[r1,#0]		@ store the result
1145 	str	r4,[r1,#4]
1146 	str	r5,[r1,#8]
1147 	str	r6,[r1,#12]
1148 
1149 	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11}
1150 	bx	lr				@ bx	lr
1151 .size	poly1305_emit_neon,.-poly1305_emit_neon
1152 
1153 .align	5
1154 .Lzeros:
1155 .long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
1156 .LOPENSSL_armcap:
1157 # ifdef	_WIN32
1158 .word	OPENSSL_armcap_P
1159 # else
1160 .word	OPENSSL_armcap_P-.Lpoly1305_init
1161 # endif
1162 #endif
1163 .byte	80,111,108,121,49,51,48,53,32,102,111,114,32,65,82,77,118,52,47,78,69,79,78,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
1164 .align	2
1165 .align	2
1166 #if	__ARM_MAX_ARCH__>=7
1167 .comm	OPENSSL_armcap_P,4,4
1168 #endif
1169