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