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