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