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