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