xref: /netbsd-src/crypto/external/bsd/openssl/lib/libcrypto/arch/arm/chacha-armv4.S (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1#include "arm_arch.h"
2
3.text
4#if defined(__thumb2__)
5.syntax	unified
6.thumb
7#else
8.code	32
9#endif
10
11#if defined(__thumb2__) || defined(__clang__)
12#define ldrhsb	ldrbhs
13#endif
14
15.align	5
16.Lsigma:
17.long	0x61707865,0x3320646e,0x79622d32,0x6b206574	@ endian-neutral
18.Lone:
19.long	1,0,0,0
20#if __ARM_MAX_ARCH__>=7
21.LOPENSSL_armcap:
22.word	OPENSSL_armcap_P-.LChaCha20_ctr32
23#else
24.word	-1
25#endif
26
27.globl	ChaCha20_ctr32
28.type	ChaCha20_ctr32,%function
29.align	5
30ChaCha20_ctr32:
31.LChaCha20_ctr32:
32	ldr	r12,[sp,#0]		@ pull pointer to counter and nonce
33	stmdb	sp!,{r0,r1,r2,r4-r11,lr}
34#if __ARM_ARCH__<7 && !defined(__thumb2__)
35	sub	r14,pc,#16		@ ChaCha20_ctr32
36#else
37	adr	r14,.LChaCha20_ctr32
38#endif
39	cmp	r2,#0			@ len==0?
40#ifdef	__thumb2__
41	itt	eq
42#endif
43	addeq	sp,sp,#4*3
44	beq	.Lno_data
45#if __ARM_MAX_ARCH__>=7
46	cmp	r2,#192			@ test len
47	bls	.Lshort
48	ldr	r4,[r14,#-32]
49	ldr	r4,[r14,r4]
50# ifdef	__APPLE__
51	ldr	r4,[r4]
52# endif
53	tst	r4,#ARMV7_NEON
54	bne	.LChaCha20_neon
55.Lshort:
56#endif
57	ldmia	r12,{r4,r5,r6,r7}		@ load counter and nonce
58	sub	sp,sp,#4*(16)		@ off-load area
59	sub	r14,r14,#64		@ .Lsigma
60	stmdb	sp!,{r4,r5,r6,r7}		@ copy counter and nonce
61	ldmia	r3,{r4,r5,r6,r7,r8,r9,r10,r11}		@ load key
62	ldmia	r14,{r0,r1,r2,r3}		@ load sigma
63	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11}		@ copy key
64	stmdb	sp!,{r0,r1,r2,r3}		@ copy sigma
65	str	r10,[sp,#4*(16+10)]	@ off-load "rx"
66	str	r11,[sp,#4*(16+11)]	@ off-load "rx"
67	b	.Loop_outer_enter
68
69.align	4
70.Loop_outer:
71	ldmia	sp,{r0,r1,r2,r3,r4,r5,r6,r7,r8,r9}		@ load key material
72	str	r11,[sp,#4*(32+2)]	@ save len
73	str	r12,  [sp,#4*(32+1)]	@ save inp
74	str	r14,  [sp,#4*(32+0)]	@ save out
75.Loop_outer_enter:
76	ldr	r11, [sp,#4*(15)]
77	ldr	r12,[sp,#4*(12)]	@ modulo-scheduled load
78	ldr	r10, [sp,#4*(13)]
79	ldr	r14,[sp,#4*(14)]
80	str	r11, [sp,#4*(16+15)]
81	mov	r11,#10
82	b	.Loop
83
84.align	4
85.Loop:
86	subs	r11,r11,#1
87	add	r0,r0,r4
88	mov	r12,r12,ror#16
89	add	r1,r1,r5
90	mov	r10,r10,ror#16
91	eor	r12,r12,r0,ror#16
92	eor	r10,r10,r1,ror#16
93	add	r8,r8,r12
94	mov	r4,r4,ror#20
95	add	r9,r9,r10
96	mov	r5,r5,ror#20
97	eor	r4,r4,r8,ror#20
98	eor	r5,r5,r9,ror#20
99	add	r0,r0,r4
100	mov	r12,r12,ror#24
101	add	r1,r1,r5
102	mov	r10,r10,ror#24
103	eor	r12,r12,r0,ror#24
104	eor	r10,r10,r1,ror#24
105	add	r8,r8,r12
106	mov	r4,r4,ror#25
107	add	r9,r9,r10
108	mov	r5,r5,ror#25
109	str	r10,[sp,#4*(16+13)]
110	ldr	r10,[sp,#4*(16+15)]
111	eor	r4,r4,r8,ror#25
112	eor	r5,r5,r9,ror#25
113	str	r8,[sp,#4*(16+8)]
114	ldr	r8,[sp,#4*(16+10)]
115	add	r2,r2,r6
116	mov	r14,r14,ror#16
117	str	r9,[sp,#4*(16+9)]
118	ldr	r9,[sp,#4*(16+11)]
119	add	r3,r3,r7
120	mov	r10,r10,ror#16
121	eor	r14,r14,r2,ror#16
122	eor	r10,r10,r3,ror#16
123	add	r8,r8,r14
124	mov	r6,r6,ror#20
125	add	r9,r9,r10
126	mov	r7,r7,ror#20
127	eor	r6,r6,r8,ror#20
128	eor	r7,r7,r9,ror#20
129	add	r2,r2,r6
130	mov	r14,r14,ror#24
131	add	r3,r3,r7
132	mov	r10,r10,ror#24
133	eor	r14,r14,r2,ror#24
134	eor	r10,r10,r3,ror#24
135	add	r8,r8,r14
136	mov	r6,r6,ror#25
137	add	r9,r9,r10
138	mov	r7,r7,ror#25
139	eor	r6,r6,r8,ror#25
140	eor	r7,r7,r9,ror#25
141	add	r0,r0,r5
142	mov	r10,r10,ror#16
143	add	r1,r1,r6
144	mov	r12,r12,ror#16
145	eor	r10,r10,r0,ror#16
146	eor	r12,r12,r1,ror#16
147	add	r8,r8,r10
148	mov	r5,r5,ror#20
149	add	r9,r9,r12
150	mov	r6,r6,ror#20
151	eor	r5,r5,r8,ror#20
152	eor	r6,r6,r9,ror#20
153	add	r0,r0,r5
154	mov	r10,r10,ror#24
155	add	r1,r1,r6
156	mov	r12,r12,ror#24
157	eor	r10,r10,r0,ror#24
158	eor	r12,r12,r1,ror#24
159	add	r8,r8,r10
160	mov	r5,r5,ror#25
161	str	r10,[sp,#4*(16+15)]
162	ldr	r10,[sp,#4*(16+13)]
163	add	r9,r9,r12
164	mov	r6,r6,ror#25
165	eor	r5,r5,r8,ror#25
166	eor	r6,r6,r9,ror#25
167	str	r8,[sp,#4*(16+10)]
168	ldr	r8,[sp,#4*(16+8)]
169	add	r2,r2,r7
170	mov	r10,r10,ror#16
171	str	r9,[sp,#4*(16+11)]
172	ldr	r9,[sp,#4*(16+9)]
173	add	r3,r3,r4
174	mov	r14,r14,ror#16
175	eor	r10,r10,r2,ror#16
176	eor	r14,r14,r3,ror#16
177	add	r8,r8,r10
178	mov	r7,r7,ror#20
179	add	r9,r9,r14
180	mov	r4,r4,ror#20
181	eor	r7,r7,r8,ror#20
182	eor	r4,r4,r9,ror#20
183	add	r2,r2,r7
184	mov	r10,r10,ror#24
185	add	r3,r3,r4
186	mov	r14,r14,ror#24
187	eor	r10,r10,r2,ror#24
188	eor	r14,r14,r3,ror#24
189	add	r8,r8,r10
190	mov	r7,r7,ror#25
191	add	r9,r9,r14
192	mov	r4,r4,ror#25
193	eor	r7,r7,r8,ror#25
194	eor	r4,r4,r9,ror#25
195	bne	.Loop
196
197	ldr	r11,[sp,#4*(32+2)]	@ load len
198
199	str	r8, [sp,#4*(16+8)]	@ modulo-scheduled store
200	str	r9, [sp,#4*(16+9)]
201	str	r12,[sp,#4*(16+12)]
202	str	r10, [sp,#4*(16+13)]
203	str	r14,[sp,#4*(16+14)]
204
205	@ at this point we have first half of 512-bit result in
206	@ rx and second half at sp+4*(16+8)
207
208	cmp	r11,#64		@ done yet?
209#ifdef	__thumb2__
210	itete	lo
211#endif
212	addlo	r12,sp,#4*(0)		@ shortcut or ...
213	ldrhs	r12,[sp,#4*(32+1)]	@ ... load inp
214	addlo	r14,sp,#4*(0)		@ shortcut or ...
215	ldrhs	r14,[sp,#4*(32+0)]	@ ... load out
216
217	ldr	r8,[sp,#4*(0)]	@ load key material
218	ldr	r9,[sp,#4*(1)]
219
220#if __ARM_ARCH__>=6 || !defined(__ARMEB__)
221# if __ARM_ARCH__<7
222	orr	r10,r12,r14
223	tst	r10,#3		@ are input and output aligned?
224	ldr	r10,[sp,#4*(2)]
225	bne	.Lunaligned
226	cmp	r11,#64		@ restore flags
227# else
228	ldr	r10,[sp,#4*(2)]
229# endif
230	ldr	r11,[sp,#4*(3)]
231
232	add	r0,r0,r8	@ accumulate key material
233	add	r1,r1,r9
234# ifdef	__thumb2__
235	itt	hs
236# endif
237	ldrhs	r8,[r12],#16		@ load input
238	ldrhs	r9,[r12,#-12]
239
240	add	r2,r2,r10
241	add	r3,r3,r11
242# ifdef	__thumb2__
243	itt	hs
244# endif
245	ldrhs	r10,[r12,#-8]
246	ldrhs	r11,[r12,#-4]
247# if __ARM_ARCH__>=6 && defined(__ARMEB__)
248	rev	r0,r0
249	rev	r1,r1
250	rev	r2,r2
251	rev	r3,r3
252# endif
253# ifdef	__thumb2__
254	itt	hs
255# endif
256	eorhs	r0,r0,r8	@ xor with input
257	eorhs	r1,r1,r9
258	add	r8,sp,#4*(4)
259	str	r0,[r14],#16		@ store output
260# ifdef	__thumb2__
261	itt	hs
262# endif
263	eorhs	r2,r2,r10
264	eorhs	r3,r3,r11
265	ldmia	r8,{r8,r9,r10,r11}	@ load key material
266	str	r1,[r14,#-12]
267	str	r2,[r14,#-8]
268	str	r3,[r14,#-4]
269
270	add	r4,r4,r8	@ accumulate key material
271	add	r5,r5,r9
272# ifdef	__thumb2__
273	itt	hs
274# endif
275	ldrhs	r8,[r12],#16		@ load input
276	ldrhs	r9,[r12,#-12]
277	add	r6,r6,r10
278	add	r7,r7,r11
279# ifdef	__thumb2__
280	itt	hs
281# endif
282	ldrhs	r10,[r12,#-8]
283	ldrhs	r11,[r12,#-4]
284# if __ARM_ARCH__>=6 && defined(__ARMEB__)
285	rev	r4,r4
286	rev	r5,r5
287	rev	r6,r6
288	rev	r7,r7
289# endif
290# ifdef	__thumb2__
291	itt	hs
292# endif
293	eorhs	r4,r4,r8
294	eorhs	r5,r5,r9
295	add	r8,sp,#4*(8)
296	str	r4,[r14],#16		@ store output
297# ifdef	__thumb2__
298	itt	hs
299# endif
300	eorhs	r6,r6,r10
301	eorhs	r7,r7,r11
302	str	r5,[r14,#-12]
303	ldmia	r8,{r8,r9,r10,r11}	@ load key material
304	str	r6,[r14,#-8]
305	add	r0,sp,#4*(16+8)
306	str	r7,[r14,#-4]
307
308	ldmia	r0,{r0,r1,r2,r3,r4,r5,r6,r7}	@ load second half
309
310	add	r0,r0,r8	@ accumulate key material
311	add	r1,r1,r9
312# ifdef	__thumb2__
313	itt	hs
314# endif
315	ldrhs	r8,[r12],#16		@ load input
316	ldrhs	r9,[r12,#-12]
317# ifdef	__thumb2__
318	itt	hi
319# endif
320	strhi	r10,[sp,#4*(16+10)]	@ copy "rx" while at it
321	strhi	r11,[sp,#4*(16+11)]	@ copy "rx" while at it
322	add	r2,r2,r10
323	add	r3,r3,r11
324# ifdef	__thumb2__
325	itt	hs
326# endif
327	ldrhs	r10,[r12,#-8]
328	ldrhs	r11,[r12,#-4]
329# if __ARM_ARCH__>=6 && defined(__ARMEB__)
330	rev	r0,r0
331	rev	r1,r1
332	rev	r2,r2
333	rev	r3,r3
334# endif
335# ifdef	__thumb2__
336	itt	hs
337# endif
338	eorhs	r0,r0,r8
339	eorhs	r1,r1,r9
340	add	r8,sp,#4*(12)
341	str	r0,[r14],#16		@ store output
342# ifdef	__thumb2__
343	itt	hs
344# endif
345	eorhs	r2,r2,r10
346	eorhs	r3,r3,r11
347	str	r1,[r14,#-12]
348	ldmia	r8,{r8,r9,r10,r11}	@ load key material
349	str	r2,[r14,#-8]
350	str	r3,[r14,#-4]
351
352	add	r4,r4,r8	@ accumulate key material
353	add	r5,r5,r9
354# ifdef	__thumb2__
355	itt	hi
356# endif
357	addhi	r8,r8,#1		@ next counter value
358	strhi	r8,[sp,#4*(12)]	@ save next counter value
359# ifdef	__thumb2__
360	itt	hs
361# endif
362	ldrhs	r8,[r12],#16		@ load input
363	ldrhs	r9,[r12,#-12]
364	add	r6,r6,r10
365	add	r7,r7,r11
366# ifdef	__thumb2__
367	itt	hs
368# endif
369	ldrhs	r10,[r12,#-8]
370	ldrhs	r11,[r12,#-4]
371# if __ARM_ARCH__>=6 && defined(__ARMEB__)
372	rev	r4,r4
373	rev	r5,r5
374	rev	r6,r6
375	rev	r7,r7
376# endif
377# ifdef	__thumb2__
378	itt	hs
379# endif
380	eorhs	r4,r4,r8
381	eorhs	r5,r5,r9
382# ifdef	__thumb2__
383	it	ne
384# endif
385	ldrne	r8,[sp,#4*(32+2)]	@ re-load len
386# ifdef	__thumb2__
387	itt	hs
388# endif
389	eorhs	r6,r6,r10
390	eorhs	r7,r7,r11
391	str	r4,[r14],#16		@ store output
392	str	r5,[r14,#-12]
393# ifdef	__thumb2__
394	it	hs
395# endif
396	subhs	r11,r8,#64		@ len-=64
397	str	r6,[r14,#-8]
398	str	r7,[r14,#-4]
399	bhi	.Loop_outer
400
401	beq	.Ldone
402# if __ARM_ARCH__<7
403	b	.Ltail
404
405.align	4
406.Lunaligned:@ unaligned endian-neutral path
407	cmp	r11,#64		@ restore flags
408# endif
409#endif
410#if __ARM_ARCH__<7
411	ldr	r11,[sp,#4*(3)]
412	add	r0,r0,r8		@ accumulate key material
413	add	r1,r1,r9
414	add	r2,r2,r10
415# ifdef	__thumb2__
416	itete	lo
417# endif
418	eorlo	r8,r8,r8		@ zero or ...
419	ldrhsb	r8,[r12],#16			@ ... load input
420	eorlo	r9,r9,r9
421	ldrhsb	r9,[r12,#-12]
422
423	add	r3,r3,r11
424# ifdef	__thumb2__
425	itete	lo
426# endif
427	eorlo	r10,r10,r10
428	ldrhsb	r10,[r12,#-8]
429	eorlo	r11,r11,r11
430	ldrhsb	r11,[r12,#-4]
431
432	eor	r0,r8,r0		@ xor with input (or zero)
433	eor	r1,r9,r1
434# ifdef	__thumb2__
435	itt	hs
436# endif
437	ldrhsb	r8,[r12,#-15]		@ load more input
438	ldrhsb	r9,[r12,#-11]
439	eor	r2,r10,r2
440	strb	r0,[r14],#16		@ store output
441	eor	r3,r11,r3
442# ifdef	__thumb2__
443	itt	hs
444# endif
445	ldrhsb	r10,[r12,#-7]
446	ldrhsb	r11,[r12,#-3]
447	strb	r1,[r14,#-12]
448	eor	r0,r8,r0,lsr#8
449	strb	r2,[r14,#-8]
450	eor	r1,r9,r1,lsr#8
451# ifdef	__thumb2__
452	itt	hs
453# endif
454	ldrhsb	r8,[r12,#-14]		@ load more input
455	ldrhsb	r9,[r12,#-10]
456	strb	r3,[r14,#-4]
457	eor	r2,r10,r2,lsr#8
458	strb	r0,[r14,#-15]
459	eor	r3,r11,r3,lsr#8
460# ifdef	__thumb2__
461	itt	hs
462# endif
463	ldrhsb	r10,[r12,#-6]
464	ldrhsb	r11,[r12,#-2]
465	strb	r1,[r14,#-11]
466	eor	r0,r8,r0,lsr#8
467	strb	r2,[r14,#-7]
468	eor	r1,r9,r1,lsr#8
469# ifdef	__thumb2__
470	itt	hs
471# endif
472	ldrhsb	r8,[r12,#-13]		@ load more input
473	ldrhsb	r9,[r12,#-9]
474	strb	r3,[r14,#-3]
475	eor	r2,r10,r2,lsr#8
476	strb	r0,[r14,#-14]
477	eor	r3,r11,r3,lsr#8
478# ifdef	__thumb2__
479	itt	hs
480# endif
481	ldrhsb	r10,[r12,#-5]
482	ldrhsb	r11,[r12,#-1]
483	strb	r1,[r14,#-10]
484	strb	r2,[r14,#-6]
485	eor	r0,r8,r0,lsr#8
486	strb	r3,[r14,#-2]
487	eor	r1,r9,r1,lsr#8
488	strb	r0,[r14,#-13]
489	eor	r2,r10,r2,lsr#8
490	strb	r1,[r14,#-9]
491	eor	r3,r11,r3,lsr#8
492	strb	r2,[r14,#-5]
493	strb	r3,[r14,#-1]
494	add	r8,sp,#4*(4+0)
495	ldmia	r8,{r8,r9,r10,r11}		@ load key material
496	add	r0,sp,#4*(16+8)
497	add	r4,r4,r8		@ accumulate key material
498	add	r5,r5,r9
499	add	r6,r6,r10
500# ifdef	__thumb2__
501	itete	lo
502# endif
503	eorlo	r8,r8,r8		@ zero or ...
504	ldrhsb	r8,[r12],#16			@ ... load input
505	eorlo	r9,r9,r9
506	ldrhsb	r9,[r12,#-12]
507
508	add	r7,r7,r11
509# ifdef	__thumb2__
510	itete	lo
511# endif
512	eorlo	r10,r10,r10
513	ldrhsb	r10,[r12,#-8]
514	eorlo	r11,r11,r11
515	ldrhsb	r11,[r12,#-4]
516
517	eor	r4,r8,r4		@ xor with input (or zero)
518	eor	r5,r9,r5
519# ifdef	__thumb2__
520	itt	hs
521# endif
522	ldrhsb	r8,[r12,#-15]		@ load more input
523	ldrhsb	r9,[r12,#-11]
524	eor	r6,r10,r6
525	strb	r4,[r14],#16		@ store output
526	eor	r7,r11,r7
527# ifdef	__thumb2__
528	itt	hs
529# endif
530	ldrhsb	r10,[r12,#-7]
531	ldrhsb	r11,[r12,#-3]
532	strb	r5,[r14,#-12]
533	eor	r4,r8,r4,lsr#8
534	strb	r6,[r14,#-8]
535	eor	r5,r9,r5,lsr#8
536# ifdef	__thumb2__
537	itt	hs
538# endif
539	ldrhsb	r8,[r12,#-14]		@ load more input
540	ldrhsb	r9,[r12,#-10]
541	strb	r7,[r14,#-4]
542	eor	r6,r10,r6,lsr#8
543	strb	r4,[r14,#-15]
544	eor	r7,r11,r7,lsr#8
545# ifdef	__thumb2__
546	itt	hs
547# endif
548	ldrhsb	r10,[r12,#-6]
549	ldrhsb	r11,[r12,#-2]
550	strb	r5,[r14,#-11]
551	eor	r4,r8,r4,lsr#8
552	strb	r6,[r14,#-7]
553	eor	r5,r9,r5,lsr#8
554# ifdef	__thumb2__
555	itt	hs
556# endif
557	ldrhsb	r8,[r12,#-13]		@ load more input
558	ldrhsb	r9,[r12,#-9]
559	strb	r7,[r14,#-3]
560	eor	r6,r10,r6,lsr#8
561	strb	r4,[r14,#-14]
562	eor	r7,r11,r7,lsr#8
563# ifdef	__thumb2__
564	itt	hs
565# endif
566	ldrhsb	r10,[r12,#-5]
567	ldrhsb	r11,[r12,#-1]
568	strb	r5,[r14,#-10]
569	strb	r6,[r14,#-6]
570	eor	r4,r8,r4,lsr#8
571	strb	r7,[r14,#-2]
572	eor	r5,r9,r5,lsr#8
573	strb	r4,[r14,#-13]
574	eor	r6,r10,r6,lsr#8
575	strb	r5,[r14,#-9]
576	eor	r7,r11,r7,lsr#8
577	strb	r6,[r14,#-5]
578	strb	r7,[r14,#-1]
579	add	r8,sp,#4*(4+4)
580	ldmia	r8,{r8,r9,r10,r11}		@ load key material
581	ldmia	r0,{r0,r1,r2,r3,r4,r5,r6,r7}		@ load second half
582# ifdef	__thumb2__
583	itt	hi
584# endif
585	strhi	r10,[sp,#4*(16+10)]		@ copy "rx"
586	strhi	r11,[sp,#4*(16+11)]		@ copy "rx"
587	add	r0,r0,r8		@ accumulate key material
588	add	r1,r1,r9
589	add	r2,r2,r10
590# ifdef	__thumb2__
591	itete	lo
592# endif
593	eorlo	r8,r8,r8		@ zero or ...
594	ldrhsb	r8,[r12],#16			@ ... load input
595	eorlo	r9,r9,r9
596	ldrhsb	r9,[r12,#-12]
597
598	add	r3,r3,r11
599# ifdef	__thumb2__
600	itete	lo
601# endif
602	eorlo	r10,r10,r10
603	ldrhsb	r10,[r12,#-8]
604	eorlo	r11,r11,r11
605	ldrhsb	r11,[r12,#-4]
606
607	eor	r0,r8,r0		@ xor with input (or zero)
608	eor	r1,r9,r1
609# ifdef	__thumb2__
610	itt	hs
611# endif
612	ldrhsb	r8,[r12,#-15]		@ load more input
613	ldrhsb	r9,[r12,#-11]
614	eor	r2,r10,r2
615	strb	r0,[r14],#16		@ store output
616	eor	r3,r11,r3
617# ifdef	__thumb2__
618	itt	hs
619# endif
620	ldrhsb	r10,[r12,#-7]
621	ldrhsb	r11,[r12,#-3]
622	strb	r1,[r14,#-12]
623	eor	r0,r8,r0,lsr#8
624	strb	r2,[r14,#-8]
625	eor	r1,r9,r1,lsr#8
626# ifdef	__thumb2__
627	itt	hs
628# endif
629	ldrhsb	r8,[r12,#-14]		@ load more input
630	ldrhsb	r9,[r12,#-10]
631	strb	r3,[r14,#-4]
632	eor	r2,r10,r2,lsr#8
633	strb	r0,[r14,#-15]
634	eor	r3,r11,r3,lsr#8
635# ifdef	__thumb2__
636	itt	hs
637# endif
638	ldrhsb	r10,[r12,#-6]
639	ldrhsb	r11,[r12,#-2]
640	strb	r1,[r14,#-11]
641	eor	r0,r8,r0,lsr#8
642	strb	r2,[r14,#-7]
643	eor	r1,r9,r1,lsr#8
644# ifdef	__thumb2__
645	itt	hs
646# endif
647	ldrhsb	r8,[r12,#-13]		@ load more input
648	ldrhsb	r9,[r12,#-9]
649	strb	r3,[r14,#-3]
650	eor	r2,r10,r2,lsr#8
651	strb	r0,[r14,#-14]
652	eor	r3,r11,r3,lsr#8
653# ifdef	__thumb2__
654	itt	hs
655# endif
656	ldrhsb	r10,[r12,#-5]
657	ldrhsb	r11,[r12,#-1]
658	strb	r1,[r14,#-10]
659	strb	r2,[r14,#-6]
660	eor	r0,r8,r0,lsr#8
661	strb	r3,[r14,#-2]
662	eor	r1,r9,r1,lsr#8
663	strb	r0,[r14,#-13]
664	eor	r2,r10,r2,lsr#8
665	strb	r1,[r14,#-9]
666	eor	r3,r11,r3,lsr#8
667	strb	r2,[r14,#-5]
668	strb	r3,[r14,#-1]
669	add	r8,sp,#4*(4+8)
670	ldmia	r8,{r8,r9,r10,r11}		@ load key material
671	add	r4,r4,r8		@ accumulate key material
672# ifdef	__thumb2__
673	itt	hi
674# endif
675	addhi	r8,r8,#1			@ next counter value
676	strhi	r8,[sp,#4*(12)]		@ save next counter value
677	add	r5,r5,r9
678	add	r6,r6,r10
679# ifdef	__thumb2__
680	itete	lo
681# endif
682	eorlo	r8,r8,r8		@ zero or ...
683	ldrhsb	r8,[r12],#16			@ ... load input
684	eorlo	r9,r9,r9
685	ldrhsb	r9,[r12,#-12]
686
687	add	r7,r7,r11
688# ifdef	__thumb2__
689	itete	lo
690# endif
691	eorlo	r10,r10,r10
692	ldrhsb	r10,[r12,#-8]
693	eorlo	r11,r11,r11
694	ldrhsb	r11,[r12,#-4]
695
696	eor	r4,r8,r4		@ xor with input (or zero)
697	eor	r5,r9,r5
698# ifdef	__thumb2__
699	itt	hs
700# endif
701	ldrhsb	r8,[r12,#-15]		@ load more input
702	ldrhsb	r9,[r12,#-11]
703	eor	r6,r10,r6
704	strb	r4,[r14],#16		@ store output
705	eor	r7,r11,r7
706# ifdef	__thumb2__
707	itt	hs
708# endif
709	ldrhsb	r10,[r12,#-7]
710	ldrhsb	r11,[r12,#-3]
711	strb	r5,[r14,#-12]
712	eor	r4,r8,r4,lsr#8
713	strb	r6,[r14,#-8]
714	eor	r5,r9,r5,lsr#8
715# ifdef	__thumb2__
716	itt	hs
717# endif
718	ldrhsb	r8,[r12,#-14]		@ load more input
719	ldrhsb	r9,[r12,#-10]
720	strb	r7,[r14,#-4]
721	eor	r6,r10,r6,lsr#8
722	strb	r4,[r14,#-15]
723	eor	r7,r11,r7,lsr#8
724# ifdef	__thumb2__
725	itt	hs
726# endif
727	ldrhsb	r10,[r12,#-6]
728	ldrhsb	r11,[r12,#-2]
729	strb	r5,[r14,#-11]
730	eor	r4,r8,r4,lsr#8
731	strb	r6,[r14,#-7]
732	eor	r5,r9,r5,lsr#8
733# ifdef	__thumb2__
734	itt	hs
735# endif
736	ldrhsb	r8,[r12,#-13]		@ load more input
737	ldrhsb	r9,[r12,#-9]
738	strb	r7,[r14,#-3]
739	eor	r6,r10,r6,lsr#8
740	strb	r4,[r14,#-14]
741	eor	r7,r11,r7,lsr#8
742# ifdef	__thumb2__
743	itt	hs
744# endif
745	ldrhsb	r10,[r12,#-5]
746	ldrhsb	r11,[r12,#-1]
747	strb	r5,[r14,#-10]
748	strb	r6,[r14,#-6]
749	eor	r4,r8,r4,lsr#8
750	strb	r7,[r14,#-2]
751	eor	r5,r9,r5,lsr#8
752	strb	r4,[r14,#-13]
753	eor	r6,r10,r6,lsr#8
754	strb	r5,[r14,#-9]
755	eor	r7,r11,r7,lsr#8
756	strb	r6,[r14,#-5]
757	strb	r7,[r14,#-1]
758# ifdef	__thumb2__
759	it	ne
760# endif
761	ldrne	r8,[sp,#4*(32+2)]		@ re-load len
762# ifdef	__thumb2__
763	it	hs
764# endif
765	subhs	r11,r8,#64			@ len-=64
766	bhi	.Loop_outer
767
768	beq	.Ldone
769#endif
770
771.Ltail:
772	ldr	r12,[sp,#4*(32+1)]	@ load inp
773	add	r9,sp,#4*(0)
774	ldr	r14,[sp,#4*(32+0)]	@ load out
775
776.Loop_tail:
777	ldrb	r10,[r9],#1	@ read buffer on stack
778	ldrb	r11,[r12],#1		@ read input
779	subs	r8,r8,#1
780	eor	r11,r11,r10
781	strb	r11,[r14],#1		@ store output
782	bne	.Loop_tail
783
784.Ldone:
785	add	sp,sp,#4*(32+3)
786.Lno_data:
787	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,pc}
788.size	ChaCha20_ctr32,.-ChaCha20_ctr32
789#if __ARM_MAX_ARCH__>=7
790.arch	armv7-a
791.fpu	neon
792
793.type	ChaCha20_neon,%function
794.align	5
795ChaCha20_neon:
796	ldr	r12,[sp,#0]		@ pull pointer to counter and nonce
797	stmdb	sp!,{r0,r1,r2,r4-r11,lr}
798.LChaCha20_neon:
799	adr	r14,.Lsigma
800	vstmdb	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}		@ ABI spec says so
801	stmdb	sp!,{r0,r1,r2,r3}
802
803	vld1.32	{q1,q2},[r3]		@ load key
804	ldmia	r3,{r4,r5,r6,r7,r8,r9,r10,r11}		@ load key
805
806	sub	sp,sp,#4*(16+16)
807	vld1.32	{q3},[r12]		@ load counter and nonce
808	add	r12,sp,#4*8
809	ldmia	r14,{r0,r1,r2,r3}		@ load sigma
810	vld1.32	{q0},[r14]!		@ load sigma
811	vld1.32	{q12},[r14]		@ one
812	vst1.32	{q2,q3},[r12]		@ copy 1/2key|counter|nonce
813	vst1.32	{q0,q1},[sp]		@ copy sigma|1/2key
814
815	str	r10,[sp,#4*(16+10)]	@ off-load "rx"
816	str	r11,[sp,#4*(16+11)]	@ off-load "rx"
817	vshl.i32	d26,d24,#1	@ two
818	vstr	d24,[sp,#4*(16+0)]
819	vshl.i32	d28,d24,#2	@ four
820	vstr	d26,[sp,#4*(16+2)]
821	vmov	q4,q0
822	vstr	d28,[sp,#4*(16+4)]
823	vmov	q8,q0
824	vmov	q5,q1
825	vmov	q9,q1
826	b	.Loop_neon_enter
827
828.align	4
829.Loop_neon_outer:
830	ldmia	sp,{r0,r1,r2,r3,r4,r5,r6,r7,r8,r9}		@ load key material
831	cmp	r11,#64*2		@ if len<=64*2
832	bls	.Lbreak_neon		@ switch to integer-only
833	vmov	q4,q0
834	str	r11,[sp,#4*(32+2)]	@ save len
835	vmov	q8,q0
836	str	r12,  [sp,#4*(32+1)]	@ save inp
837	vmov	q5,q1
838	str	r14,  [sp,#4*(32+0)]	@ save out
839	vmov	q9,q1
840.Loop_neon_enter:
841	ldr	r11, [sp,#4*(15)]
842	vadd.i32	q7,q3,q12		@ counter+1
843	ldr	r12,[sp,#4*(12)]	@ modulo-scheduled load
844	vmov	q6,q2
845	ldr	r10, [sp,#4*(13)]
846	vmov	q10,q2
847	ldr	r14,[sp,#4*(14)]
848	vadd.i32	q11,q7,q12		@ counter+2
849	str	r11, [sp,#4*(16+15)]
850	mov	r11,#10
851	add	r12,r12,#3	@ counter+3
852	b	.Loop_neon
853
854.align	4
855.Loop_neon:
856	subs	r11,r11,#1
857	vadd.i32	q0,q0,q1
858	add	r0,r0,r4
859	vadd.i32	q4,q4,q5
860	mov	r12,r12,ror#16
861	vadd.i32	q8,q8,q9
862	add	r1,r1,r5
863	veor	q3,q3,q0
864	mov	r10,r10,ror#16
865	veor	q7,q7,q4
866	eor	r12,r12,r0,ror#16
867	veor	q11,q11,q8
868	eor	r10,r10,r1,ror#16
869	vrev32.16	q3,q3
870	add	r8,r8,r12
871	vrev32.16	q7,q7
872	mov	r4,r4,ror#20
873	vrev32.16	q11,q11
874	add	r9,r9,r10
875	vadd.i32	q2,q2,q3
876	mov	r5,r5,ror#20
877	vadd.i32	q6,q6,q7
878	eor	r4,r4,r8,ror#20
879	vadd.i32	q10,q10,q11
880	eor	r5,r5,r9,ror#20
881	veor	q12,q1,q2
882	add	r0,r0,r4
883	veor	q13,q5,q6
884	mov	r12,r12,ror#24
885	veor	q14,q9,q10
886	add	r1,r1,r5
887	vshr.u32	q1,q12,#20
888	mov	r10,r10,ror#24
889	vshr.u32	q5,q13,#20
890	eor	r12,r12,r0,ror#24
891	vshr.u32	q9,q14,#20
892	eor	r10,r10,r1,ror#24
893	vsli.32	q1,q12,#12
894	add	r8,r8,r12
895	vsli.32	q5,q13,#12
896	mov	r4,r4,ror#25
897	vsli.32	q9,q14,#12
898	add	r9,r9,r10
899	vadd.i32	q0,q0,q1
900	mov	r5,r5,ror#25
901	vadd.i32	q4,q4,q5
902	str	r10,[sp,#4*(16+13)]
903	vadd.i32	q8,q8,q9
904	ldr	r10,[sp,#4*(16+15)]
905	veor	q12,q3,q0
906	eor	r4,r4,r8,ror#25
907	veor	q13,q7,q4
908	eor	r5,r5,r9,ror#25
909	veor	q14,q11,q8
910	str	r8,[sp,#4*(16+8)]
911	vshr.u32	q3,q12,#24
912	ldr	r8,[sp,#4*(16+10)]
913	vshr.u32	q7,q13,#24
914	add	r2,r2,r6
915	vshr.u32	q11,q14,#24
916	mov	r14,r14,ror#16
917	vsli.32	q3,q12,#8
918	str	r9,[sp,#4*(16+9)]
919	vsli.32	q7,q13,#8
920	ldr	r9,[sp,#4*(16+11)]
921	vsli.32	q11,q14,#8
922	add	r3,r3,r7
923	vadd.i32	q2,q2,q3
924	mov	r10,r10,ror#16
925	vadd.i32	q6,q6,q7
926	eor	r14,r14,r2,ror#16
927	vadd.i32	q10,q10,q11
928	eor	r10,r10,r3,ror#16
929	veor	q12,q1,q2
930	add	r8,r8,r14
931	veor	q13,q5,q6
932	mov	r6,r6,ror#20
933	veor	q14,q9,q10
934	add	r9,r9,r10
935	vshr.u32	q1,q12,#25
936	mov	r7,r7,ror#20
937	vshr.u32	q5,q13,#25
938	eor	r6,r6,r8,ror#20
939	vshr.u32	q9,q14,#25
940	eor	r7,r7,r9,ror#20
941	vsli.32	q1,q12,#7
942	add	r2,r2,r6
943	vsli.32	q5,q13,#7
944	mov	r14,r14,ror#24
945	vsli.32	q9,q14,#7
946	add	r3,r3,r7
947	vext.8	q2,q2,q2,#8
948	mov	r10,r10,ror#24
949	vext.8	q6,q6,q6,#8
950	eor	r14,r14,r2,ror#24
951	vext.8	q10,q10,q10,#8
952	eor	r10,r10,r3,ror#24
953	vext.8	q1,q1,q1,#4
954	add	r8,r8,r14
955	vext.8	q5,q5,q5,#4
956	mov	r6,r6,ror#25
957	vext.8	q9,q9,q9,#4
958	add	r9,r9,r10
959	vext.8	q3,q3,q3,#12
960	mov	r7,r7,ror#25
961	vext.8	q7,q7,q7,#12
962	eor	r6,r6,r8,ror#25
963	vext.8	q11,q11,q11,#12
964	eor	r7,r7,r9,ror#25
965	vadd.i32	q0,q0,q1
966	add	r0,r0,r5
967	vadd.i32	q4,q4,q5
968	mov	r10,r10,ror#16
969	vadd.i32	q8,q8,q9
970	add	r1,r1,r6
971	veor	q3,q3,q0
972	mov	r12,r12,ror#16
973	veor	q7,q7,q4
974	eor	r10,r10,r0,ror#16
975	veor	q11,q11,q8
976	eor	r12,r12,r1,ror#16
977	vrev32.16	q3,q3
978	add	r8,r8,r10
979	vrev32.16	q7,q7
980	mov	r5,r5,ror#20
981	vrev32.16	q11,q11
982	add	r9,r9,r12
983	vadd.i32	q2,q2,q3
984	mov	r6,r6,ror#20
985	vadd.i32	q6,q6,q7
986	eor	r5,r5,r8,ror#20
987	vadd.i32	q10,q10,q11
988	eor	r6,r6,r9,ror#20
989	veor	q12,q1,q2
990	add	r0,r0,r5
991	veor	q13,q5,q6
992	mov	r10,r10,ror#24
993	veor	q14,q9,q10
994	add	r1,r1,r6
995	vshr.u32	q1,q12,#20
996	mov	r12,r12,ror#24
997	vshr.u32	q5,q13,#20
998	eor	r10,r10,r0,ror#24
999	vshr.u32	q9,q14,#20
1000	eor	r12,r12,r1,ror#24
1001	vsli.32	q1,q12,#12
1002	add	r8,r8,r10
1003	vsli.32	q5,q13,#12
1004	mov	r5,r5,ror#25
1005	vsli.32	q9,q14,#12
1006	str	r10,[sp,#4*(16+15)]
1007	vadd.i32	q0,q0,q1
1008	ldr	r10,[sp,#4*(16+13)]
1009	vadd.i32	q4,q4,q5
1010	add	r9,r9,r12
1011	vadd.i32	q8,q8,q9
1012	mov	r6,r6,ror#25
1013	veor	q12,q3,q0
1014	eor	r5,r5,r8,ror#25
1015	veor	q13,q7,q4
1016	eor	r6,r6,r9,ror#25
1017	veor	q14,q11,q8
1018	str	r8,[sp,#4*(16+10)]
1019	vshr.u32	q3,q12,#24
1020	ldr	r8,[sp,#4*(16+8)]
1021	vshr.u32	q7,q13,#24
1022	add	r2,r2,r7
1023	vshr.u32	q11,q14,#24
1024	mov	r10,r10,ror#16
1025	vsli.32	q3,q12,#8
1026	str	r9,[sp,#4*(16+11)]
1027	vsli.32	q7,q13,#8
1028	ldr	r9,[sp,#4*(16+9)]
1029	vsli.32	q11,q14,#8
1030	add	r3,r3,r4
1031	vadd.i32	q2,q2,q3
1032	mov	r14,r14,ror#16
1033	vadd.i32	q6,q6,q7
1034	eor	r10,r10,r2,ror#16
1035	vadd.i32	q10,q10,q11
1036	eor	r14,r14,r3,ror#16
1037	veor	q12,q1,q2
1038	add	r8,r8,r10
1039	veor	q13,q5,q6
1040	mov	r7,r7,ror#20
1041	veor	q14,q9,q10
1042	add	r9,r9,r14
1043	vshr.u32	q1,q12,#25
1044	mov	r4,r4,ror#20
1045	vshr.u32	q5,q13,#25
1046	eor	r7,r7,r8,ror#20
1047	vshr.u32	q9,q14,#25
1048	eor	r4,r4,r9,ror#20
1049	vsli.32	q1,q12,#7
1050	add	r2,r2,r7
1051	vsli.32	q5,q13,#7
1052	mov	r10,r10,ror#24
1053	vsli.32	q9,q14,#7
1054	add	r3,r3,r4
1055	vext.8	q2,q2,q2,#8
1056	mov	r14,r14,ror#24
1057	vext.8	q6,q6,q6,#8
1058	eor	r10,r10,r2,ror#24
1059	vext.8	q10,q10,q10,#8
1060	eor	r14,r14,r3,ror#24
1061	vext.8	q1,q1,q1,#12
1062	add	r8,r8,r10
1063	vext.8	q5,q5,q5,#12
1064	mov	r7,r7,ror#25
1065	vext.8	q9,q9,q9,#12
1066	add	r9,r9,r14
1067	vext.8	q3,q3,q3,#4
1068	mov	r4,r4,ror#25
1069	vext.8	q7,q7,q7,#4
1070	eor	r7,r7,r8,ror#25
1071	vext.8	q11,q11,q11,#4
1072	eor	r4,r4,r9,ror#25
1073	bne	.Loop_neon
1074
1075	add	r11,sp,#32
1076	vld1.32	{q12,q13},[sp]		@ load key material
1077	vld1.32	{q14,q15},[r11]
1078
1079	ldr	r11,[sp,#4*(32+2)]	@ load len
1080
1081	str	r8, [sp,#4*(16+8)]	@ modulo-scheduled store
1082	str	r9, [sp,#4*(16+9)]
1083	str	r12,[sp,#4*(16+12)]
1084	str	r10, [sp,#4*(16+13)]
1085	str	r14,[sp,#4*(16+14)]
1086
1087	@ at this point we have first half of 512-bit result in
1088	@ rx and second half at sp+4*(16+8)
1089
1090	ldr	r12,[sp,#4*(32+1)]	@ load inp
1091	ldr	r14,[sp,#4*(32+0)]	@ load out
1092
1093	vadd.i32	q0,q0,q12		@ accumulate key material
1094	vadd.i32	q4,q4,q12
1095	vadd.i32	q8,q8,q12
1096	vldr	d24,[sp,#4*(16+0)]	@ one
1097
1098	vadd.i32	q1,q1,q13
1099	vadd.i32	q5,q5,q13
1100	vadd.i32	q9,q9,q13
1101	vldr	d26,[sp,#4*(16+2)]	@ two
1102
1103	vadd.i32	q2,q2,q14
1104	vadd.i32	q6,q6,q14
1105	vadd.i32	q10,q10,q14
1106	vadd.i32	d14,d14,d24	@ counter+1
1107	vadd.i32	d22,d22,d26	@ counter+2
1108
1109	vadd.i32	q3,q3,q15
1110	vadd.i32	q7,q7,q15
1111	vadd.i32	q11,q11,q15
1112
1113	cmp	r11,#64*4
1114	blo	.Ltail_neon
1115
1116	vld1.8	{q12,q13},[r12]!	@ load input
1117	mov	r11,sp
1118	vld1.8	{q14,q15},[r12]!
1119	veor	q0,q0,q12		@ xor with input
1120	veor	q1,q1,q13
1121	vld1.8	{q12,q13},[r12]!
1122	veor	q2,q2,q14
1123	veor	q3,q3,q15
1124	vld1.8	{q14,q15},[r12]!
1125
1126	veor	q4,q4,q12
1127	vst1.8	{q0,q1},[r14]!	@ store output
1128	veor	q5,q5,q13
1129	vld1.8	{q12,q13},[r12]!
1130	veor	q6,q6,q14
1131	vst1.8	{q2,q3},[r14]!
1132	veor	q7,q7,q15
1133	vld1.8	{q14,q15},[r12]!
1134
1135	veor	q8,q8,q12
1136	vld1.32	{q0,q1},[r11]!	@ load for next iteration
1137	veor	d25,d25,d25
1138	vldr	d24,[sp,#4*(16+4)]	@ four
1139	veor	q9,q9,q13
1140	vld1.32	{q2,q3},[r11]
1141	veor	q10,q10,q14
1142	vst1.8	{q4,q5},[r14]!
1143	veor	q11,q11,q15
1144	vst1.8	{q6,q7},[r14]!
1145
1146	vadd.i32	d6,d6,d24	@ next counter value
1147	vldr	d24,[sp,#4*(16+0)]	@ one
1148
1149	ldmia	sp,{r8,r9,r10,r11}	@ load key material
1150	add	r0,r0,r8	@ accumulate key material
1151	ldr	r8,[r12],#16		@ load input
1152	vst1.8	{q8,q9},[r14]!
1153	add	r1,r1,r9
1154	ldr	r9,[r12,#-12]
1155	vst1.8	{q10,q11},[r14]!
1156	add	r2,r2,r10
1157	ldr	r10,[r12,#-8]
1158	add	r3,r3,r11
1159	ldr	r11,[r12,#-4]
1160# ifdef	__ARMEB__
1161	rev	r0,r0
1162	rev	r1,r1
1163	rev	r2,r2
1164	rev	r3,r3
1165# endif
1166	eor	r0,r0,r8	@ xor with input
1167	add	r8,sp,#4*(4)
1168	eor	r1,r1,r9
1169	str	r0,[r14],#16		@ store output
1170	eor	r2,r2,r10
1171	str	r1,[r14,#-12]
1172	eor	r3,r3,r11
1173	ldmia	r8,{r8,r9,r10,r11}	@ load key material
1174	str	r2,[r14,#-8]
1175	str	r3,[r14,#-4]
1176
1177	add	r4,r4,r8	@ accumulate key material
1178	ldr	r8,[r12],#16		@ load input
1179	add	r5,r5,r9
1180	ldr	r9,[r12,#-12]
1181	add	r6,r6,r10
1182	ldr	r10,[r12,#-8]
1183	add	r7,r7,r11
1184	ldr	r11,[r12,#-4]
1185# ifdef	__ARMEB__
1186	rev	r4,r4
1187	rev	r5,r5
1188	rev	r6,r6
1189	rev	r7,r7
1190# endif
1191	eor	r4,r4,r8
1192	add	r8,sp,#4*(8)
1193	eor	r5,r5,r9
1194	str	r4,[r14],#16		@ store output
1195	eor	r6,r6,r10
1196	str	r5,[r14,#-12]
1197	eor	r7,r7,r11
1198	ldmia	r8,{r8,r9,r10,r11}	@ load key material
1199	str	r6,[r14,#-8]
1200	add	r0,sp,#4*(16+8)
1201	str	r7,[r14,#-4]
1202
1203	ldmia	r0,{r0,r1,r2,r3,r4,r5,r6,r7}	@ load second half
1204
1205	add	r0,r0,r8	@ accumulate key material
1206	ldr	r8,[r12],#16		@ load input
1207	add	r1,r1,r9
1208	ldr	r9,[r12,#-12]
1209# ifdef	__thumb2__
1210	it	hi
1211# endif
1212	strhi	r10,[sp,#4*(16+10)]	@ copy "rx" while at it
1213	add	r2,r2,r10
1214	ldr	r10,[r12,#-8]
1215# ifdef	__thumb2__
1216	it	hi
1217# endif
1218	strhi	r11,[sp,#4*(16+11)]	@ copy "rx" while at it
1219	add	r3,r3,r11
1220	ldr	r11,[r12,#-4]
1221# ifdef	__ARMEB__
1222	rev	r0,r0
1223	rev	r1,r1
1224	rev	r2,r2
1225	rev	r3,r3
1226# endif
1227	eor	r0,r0,r8
1228	add	r8,sp,#4*(12)
1229	eor	r1,r1,r9
1230	str	r0,[r14],#16		@ store output
1231	eor	r2,r2,r10
1232	str	r1,[r14,#-12]
1233	eor	r3,r3,r11
1234	ldmia	r8,{r8,r9,r10,r11}	@ load key material
1235	str	r2,[r14,#-8]
1236	str	r3,[r14,#-4]
1237
1238	add	r4,r4,r8	@ accumulate key material
1239	add	r8,r8,#4		@ next counter value
1240	add	r5,r5,r9
1241	str	r8,[sp,#4*(12)]	@ save next counter value
1242	ldr	r8,[r12],#16		@ load input
1243	add	r6,r6,r10
1244	add	r4,r4,#3		@ counter+3
1245	ldr	r9,[r12,#-12]
1246	add	r7,r7,r11
1247	ldr	r10,[r12,#-8]
1248	ldr	r11,[r12,#-4]
1249# ifdef	__ARMEB__
1250	rev	r4,r4
1251	rev	r5,r5
1252	rev	r6,r6
1253	rev	r7,r7
1254# endif
1255	eor	r4,r4,r8
1256# ifdef	__thumb2__
1257	it	hi
1258# endif
1259	ldrhi	r8,[sp,#4*(32+2)]	@ re-load len
1260	eor	r5,r5,r9
1261	eor	r6,r6,r10
1262	str	r4,[r14],#16		@ store output
1263	eor	r7,r7,r11
1264	str	r5,[r14,#-12]
1265	sub	r11,r8,#64*4	@ len-=64*4
1266	str	r6,[r14,#-8]
1267	str	r7,[r14,#-4]
1268	bhi	.Loop_neon_outer
1269
1270	b	.Ldone_neon
1271
1272.align	4
1273.Lbreak_neon:
1274	@ harmonize NEON and integer-only stack frames: load data
1275	@ from NEON frame, but save to integer-only one; distance
1276	@ between the two is 4*(32+4+16-32)=4*(20).
1277
1278	str	r11, [sp,#4*(20+32+2)]	@ save len
1279	add	r11,sp,#4*(32+4)
1280	str	r12,   [sp,#4*(20+32+1)]	@ save inp
1281	str	r14,   [sp,#4*(20+32+0)]	@ save out
1282
1283	ldr	r12,[sp,#4*(16+10)]
1284	ldr	r14,[sp,#4*(16+11)]
1285	vldmia	r11,{d8,d9,d10,d11,d12,d13,d14,d15}			@ fulfill ABI requirement
1286	str	r12,[sp,#4*(20+16+10)]	@ copy "rx"
1287	str	r14,[sp,#4*(20+16+11)]	@ copy "rx"
1288
1289	ldr	r11, [sp,#4*(15)]
1290	ldr	r12,[sp,#4*(12)]		@ modulo-scheduled load
1291	ldr	r10, [sp,#4*(13)]
1292	ldr	r14,[sp,#4*(14)]
1293	str	r11, [sp,#4*(20+16+15)]
1294	add	r11,sp,#4*(20)
1295	vst1.32	{q0,q1},[r11]!		@ copy key
1296	add	sp,sp,#4*(20)			@ switch frame
1297	vst1.32	{q2,q3},[r11]
1298	mov	r11,#10
1299	b	.Loop				@ go integer-only
1300
1301.align	4
1302.Ltail_neon:
1303	cmp	r11,#64*3
1304	bhs	.L192_or_more_neon
1305	cmp	r11,#64*2
1306	bhs	.L128_or_more_neon
1307	cmp	r11,#64*1
1308	bhs	.L64_or_more_neon
1309
1310	add	r8,sp,#4*(8)
1311	vst1.8	{q0,q1},[sp]
1312	add	r10,sp,#4*(0)
1313	vst1.8	{q2,q3},[r8]
1314	b	.Loop_tail_neon
1315
1316.align	4
1317.L64_or_more_neon:
1318	vld1.8	{q12,q13},[r12]!
1319	vld1.8	{q14,q15},[r12]!
1320	veor	q0,q0,q12
1321	veor	q1,q1,q13
1322	veor	q2,q2,q14
1323	veor	q3,q3,q15
1324	vst1.8	{q0,q1},[r14]!
1325	vst1.8	{q2,q3},[r14]!
1326
1327	beq	.Ldone_neon
1328
1329	add	r8,sp,#4*(8)
1330	vst1.8	{q4,q5},[sp]
1331	add	r10,sp,#4*(0)
1332	vst1.8	{q6,q7},[r8]
1333	sub	r11,r11,#64*1	@ len-=64*1
1334	b	.Loop_tail_neon
1335
1336.align	4
1337.L128_or_more_neon:
1338	vld1.8	{q12,q13},[r12]!
1339	vld1.8	{q14,q15},[r12]!
1340	veor	q0,q0,q12
1341	veor	q1,q1,q13
1342	vld1.8	{q12,q13},[r12]!
1343	veor	q2,q2,q14
1344	veor	q3,q3,q15
1345	vld1.8	{q14,q15},[r12]!
1346
1347	veor	q4,q4,q12
1348	veor	q5,q5,q13
1349	vst1.8	{q0,q1},[r14]!
1350	veor	q6,q6,q14
1351	vst1.8	{q2,q3},[r14]!
1352	veor	q7,q7,q15
1353	vst1.8	{q4,q5},[r14]!
1354	vst1.8	{q6,q7},[r14]!
1355
1356	beq	.Ldone_neon
1357
1358	add	r8,sp,#4*(8)
1359	vst1.8	{q8,q9},[sp]
1360	add	r10,sp,#4*(0)
1361	vst1.8	{q10,q11},[r8]
1362	sub	r11,r11,#64*2	@ len-=64*2
1363	b	.Loop_tail_neon
1364
1365.align	4
1366.L192_or_more_neon:
1367	vld1.8	{q12,q13},[r12]!
1368	vld1.8	{q14,q15},[r12]!
1369	veor	q0,q0,q12
1370	veor	q1,q1,q13
1371	vld1.8	{q12,q13},[r12]!
1372	veor	q2,q2,q14
1373	veor	q3,q3,q15
1374	vld1.8	{q14,q15},[r12]!
1375
1376	veor	q4,q4,q12
1377	veor	q5,q5,q13
1378	vld1.8	{q12,q13},[r12]!
1379	veor	q6,q6,q14
1380	vst1.8	{q0,q1},[r14]!
1381	veor	q7,q7,q15
1382	vld1.8	{q14,q15},[r12]!
1383
1384	veor	q8,q8,q12
1385	vst1.8	{q2,q3},[r14]!
1386	veor	q9,q9,q13
1387	vst1.8	{q4,q5},[r14]!
1388	veor	q10,q10,q14
1389	vst1.8	{q6,q7},[r14]!
1390	veor	q11,q11,q15
1391	vst1.8	{q8,q9},[r14]!
1392	vst1.8	{q10,q11},[r14]!
1393
1394	beq	.Ldone_neon
1395
1396	ldmia	sp,{r8,r9,r10,r11}	@ load key material
1397	add	r0,r0,r8	@ accumulate key material
1398	add	r8,sp,#4*(4)
1399	add	r1,r1,r9
1400	add	r2,r2,r10
1401	add	r3,r3,r11
1402	ldmia	r8,{r8,r9,r10,r11}	@ load key material
1403
1404	add	r4,r4,r8	@ accumulate key material
1405	add	r8,sp,#4*(8)
1406	add	r5,r5,r9
1407	add	r6,r6,r10
1408	add	r7,r7,r11
1409	ldmia	r8,{r8,r9,r10,r11}	@ load key material
1410# ifdef	__ARMEB__
1411	rev	r0,r0
1412	rev	r1,r1
1413	rev	r2,r2
1414	rev	r3,r3
1415	rev	r4,r4
1416	rev	r5,r5
1417	rev	r6,r6
1418	rev	r7,r7
1419# endif
1420	stmia	sp,{r0,r1,r2,r3,r4,r5,r6,r7}
1421	add	r0,sp,#4*(16+8)
1422
1423	ldmia	r0,{r0,r1,r2,r3,r4,r5,r6,r7}	@ load second half
1424
1425	add	r0,r0,r8	@ accumulate key material
1426	add	r8,sp,#4*(12)
1427	add	r1,r1,r9
1428	add	r2,r2,r10
1429	add	r3,r3,r11
1430	ldmia	r8,{r8,r9,r10,r11}	@ load key material
1431
1432	add	r4,r4,r8	@ accumulate key material
1433	add	r8,sp,#4*(8)
1434	add	r5,r5,r9
1435	add	r4,r4,#3		@ counter+3
1436	add	r6,r6,r10
1437	add	r7,r7,r11
1438	ldr	r11,[sp,#4*(32+2)]	@ re-load len
1439# ifdef	__ARMEB__
1440	rev	r0,r0
1441	rev	r1,r1
1442	rev	r2,r2
1443	rev	r3,r3
1444	rev	r4,r4
1445	rev	r5,r5
1446	rev	r6,r6
1447	rev	r7,r7
1448# endif
1449	stmia	r8,{r0,r1,r2,r3,r4,r5,r6,r7}
1450	add	r10,sp,#4*(0)
1451	sub	r11,r11,#64*3	@ len-=64*3
1452
1453.Loop_tail_neon:
1454	ldrb	r8,[r10],#1	@ read buffer on stack
1455	ldrb	r9,[r12],#1		@ read input
1456	subs	r11,r11,#1
1457	eor	r8,r8,r9
1458	strb	r8,[r14],#1		@ store output
1459	bne	.Loop_tail_neon
1460
1461.Ldone_neon:
1462	add	sp,sp,#4*(32+4)
1463	vldmia	sp,{d8,d9,d10,d11,d12,d13,d14,d15}
1464	add	sp,sp,#4*(16+3)
1465	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,pc}
1466.size	ChaCha20_neon,.-ChaCha20_neon
1467.comm	OPENSSL_armcap_P,4,4
1468#endif
1469