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