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