• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#include "arm_arch.h"
2
3.text
4#if defined(__thumb2__)
5.syntax	unified
6.thumb
7#else
8.code	32
9#endif
10
11#if __ARM_MAX_ARCH__>=7
12.align	5
13.LOPENSSL_armcap:
14.word	OPENSSL_armcap_P-.Lbn_mul_mont
15#endif
16
17.global	bn_mul_mont
18.type	bn_mul_mont,%function
19
20.align	5
21bn_mul_mont:
22.Lbn_mul_mont:
23	ldr	ip,[sp,#4]		@ load num
24	stmdb	sp!,{r0,r2}		@ sp points at argument block
25#if __ARM_MAX_ARCH__>=7
26	tst	ip,#7
27	bne	.Lialu
28	adr	r0,.Lbn_mul_mont
29	ldr	r2,.LOPENSSL_armcap
30	ldr	r0,[r0,r2]
31#ifdef	__APPLE__
32	ldr	r0,[r0]
33#endif
34	tst	r0,#ARMV7_NEON		@ NEON available?
35	ldmia	sp, {r0,r2}
36	beq	.Lialu
37	add	sp,sp,#8
38	b	bn_mul8x_mont_neon
39.align	4
40.Lialu:
41#endif
42	cmp	ip,#2
43	mov	r0,ip			@ load num
44#ifdef	__thumb2__
45	ittt	lt
46#endif
47	movlt	r0,#0
48	addlt	sp,sp,#2*4
49	blt	.Labrt
50
51	stmdb	sp!,{r4-r12,lr}		@ save 10 registers
52
53	mov	r0,r0,lsl#2		@ rescale r0 for byte count
54	sub	sp,sp,r0		@ alloca(4*num)
55	sub	sp,sp,#4		@ +extra dword
56	sub	r0,r0,#4		@ "num=num-1"
57	add	r4,r2,r0		@ &bp[num-1]
58
59	add	r0,sp,r0		@ r0 to point at &tp[num-1]
60	ldr	r8,[r0,#14*4]		@ &n0
61	ldr	r2,[r2]		@ bp[0]
62	ldr	r5,[r1],#4		@ ap[0],ap++
63	ldr	r6,[r3],#4		@ np[0],np++
64	ldr	r8,[r8]		@ *n0
65	str	r4,[r0,#15*4]		@ save &bp[num]
66
67	umull	r10,r11,r5,r2	@ ap[0]*bp[0]
68	str	r8,[r0,#14*4]		@ save n0 value
69	mul	r8,r10,r8		@ "tp[0]"*n0
70	mov	r12,#0
71	umlal	r10,r12,r6,r8	@ np[0]*n0+"t[0]"
72	mov	r4,sp
73
74.L1st:
75	ldr	r5,[r1],#4		@ ap[j],ap++
76	mov	r10,r11
77	ldr	r6,[r3],#4		@ np[j],np++
78	mov	r11,#0
79	umlal	r10,r11,r5,r2	@ ap[j]*bp[0]
80	mov	r14,#0
81	umlal	r12,r14,r6,r8	@ np[j]*n0
82	adds	r12,r12,r10
83	str	r12,[r4],#4		@ tp[j-1]=,tp++
84	adc	r12,r14,#0
85	cmp	r4,r0
86	bne	.L1st
87
88	adds	r12,r12,r11
89	ldr	r4,[r0,#13*4]		@ restore bp
90	mov	r14,#0
91	ldr	r8,[r0,#14*4]		@ restore n0
92	adc	r14,r14,#0
93	str	r12,[r0]		@ tp[num-1]=
94	mov	r7,sp
95	str	r14,[r0,#4]		@ tp[num]=
96
97.Louter:
98	sub	r7,r0,r7		@ "original" r0-1 value
99	sub	r1,r1,r7		@ "rewind" ap to &ap[1]
100	ldr	r2,[r4,#4]!		@ *(++bp)
101	sub	r3,r3,r7		@ "rewind" np to &np[1]
102	ldr	r5,[r1,#-4]		@ ap[0]
103	ldr	r10,[sp]		@ tp[0]
104	ldr	r6,[r3,#-4]		@ np[0]
105	ldr	r7,[sp,#4]		@ tp[1]
106
107	mov	r11,#0
108	umlal	r10,r11,r5,r2	@ ap[0]*bp[i]+tp[0]
109	str	r4,[r0,#13*4]		@ save bp
110	mul	r8,r10,r8
111	mov	r12,#0
112	umlal	r10,r12,r6,r8	@ np[0]*n0+"tp[0]"
113	mov	r4,sp
114
115.Linner:
116	ldr	r5,[r1],#4		@ ap[j],ap++
117	adds	r10,r11,r7		@ +=tp[j]
118	ldr	r6,[r3],#4		@ np[j],np++
119	mov	r11,#0
120	umlal	r10,r11,r5,r2	@ ap[j]*bp[i]
121	mov	r14,#0
122	umlal	r12,r14,r6,r8	@ np[j]*n0
123	adc	r11,r11,#0
124	ldr	r7,[r4,#8]		@ tp[j+1]
125	adds	r12,r12,r10
126	str	r12,[r4],#4		@ tp[j-1]=,tp++
127	adc	r12,r14,#0
128	cmp	r4,r0
129	bne	.Linner
130
131	adds	r12,r12,r11
132	mov	r14,#0
133	ldr	r4,[r0,#13*4]		@ restore bp
134	adc	r14,r14,#0
135	ldr	r8,[r0,#14*4]		@ restore n0
136	adds	r12,r12,r7
137	ldr	r7,[r0,#15*4]		@ restore &bp[num]
138	adc	r14,r14,#0
139	str	r12,[r0]		@ tp[num-1]=
140	str	r14,[r0,#4]		@ tp[num]=
141
142	cmp	r4,r7
143#ifdef	__thumb2__
144	itt	ne
145#endif
146	movne	r7,sp
147	bne	.Louter
148
149	ldr	r2,[r0,#12*4]		@ pull rp
150	mov	r5,sp
151	add	r0,r0,#4		@ r0 to point at &tp[num]
152	sub	r5,r0,r5		@ "original" num value
153	mov	r4,sp			@ "rewind" r4
154	mov	r1,r4			@ "borrow" r1
155	sub	r3,r3,r5		@ "rewind" r3 to &np[0]
156
157	subs	r7,r7,r7		@ "clear" carry flag
158.Lsub:	ldr	r7,[r4],#4
159	ldr	r6,[r3],#4
160	sbcs	r7,r7,r6		@ tp[j]-np[j]
161	str	r7,[r2],#4		@ rp[j]=
162	teq	r4,r0		@ preserve carry
163	bne	.Lsub
164	sbcs	r14,r14,#0		@ upmost carry
165	mov	r4,sp			@ "rewind" r4
166	sub	r2,r2,r5		@ "rewind" r2
167
168.Lcopy:	ldr	r7,[r4]		@ conditional copy
169	ldr	r5,[r2]
170	str	sp,[r4],#4		@ zap tp
171#ifdef	__thumb2__
172	it	cc
173#endif
174	movcc	r5,r7
175	str	r5,[r2],#4
176	teq	r4,r0		@ preserve carry
177	bne	.Lcopy
178
179	mov	sp,r0
180	add	sp,sp,#4		@ skip over tp[num+1]
181	ldmia	sp!,{r4-r12,lr}		@ restore registers
182	add	sp,sp,#2*4		@ skip over {r0,r2}
183	mov	r0,#1
184.Labrt:
185#if __ARM_ARCH__>=5
186	bx    lr				@ bx lr
187#else
188	tst	lr,#1
189	moveq	pc,lr			@ be binary compatible with V4, yet
190	.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
191#endif
192.size	bn_mul_mont,.-bn_mul_mont
193#if __ARM_MAX_ARCH__>=7
194.arch	armv7-a
195.fpu	neon
196
197.type	bn_mul8x_mont_neon,%function
198.align	5
199bn_mul8x_mont_neon:
200	mov	ip,sp
201	stmdb	sp!,{r4-r11}
202	vstmdb	sp!,{d8-d15}		@ ABI specification says so
203	ldmia	ip,{r4-r5}		@ load rest of parameter block
204	mov	ip,sp
205
206	cmp	r5,#8
207	bhi	.LNEON_8n
208
209	@ special case for r5==8, everything is in register bank...
210
211	vld1.32		{d28[0]}, [r2,:32]!
212	veor		d8,d8,d8
213	sub		r7,sp,r5,lsl#4
214	vld1.32		{d0-d3},  [r1]!		@ can't specify :32 :-(
215	and		r7,r7,#-64
216	vld1.32		{d30[0]}, [r4,:32]
217	mov		sp,r7			@ alloca
218	vzip.16		d28,d8
219
220	vmull.u32	q6,d28,d0[0]
221	vmull.u32	q7,d28,d0[1]
222	vmull.u32	q8,d28,d1[0]
223	vshl.i64	d29,d13,#16
224	vmull.u32	q9,d28,d1[1]
225
226	vadd.u64	d29,d29,d12
227	veor		d8,d8,d8
228	vmul.u32	d29,d29,d30
229
230	vmull.u32	q10,d28,d2[0]
231	 vld1.32	{d4-d7}, [r3]!
232	vmull.u32	q11,d28,d2[1]
233	vmull.u32	q12,d28,d3[0]
234	vzip.16		d29,d8
235	vmull.u32	q13,d28,d3[1]
236
237	vmlal.u32	q6,d29,d4[0]
238	sub		r9,r5,#1
239	vmlal.u32	q7,d29,d4[1]
240	vmlal.u32	q8,d29,d5[0]
241	vmlal.u32	q9,d29,d5[1]
242
243	vmlal.u32	q10,d29,d6[0]
244	vmov		q5,q6
245	vmlal.u32	q11,d29,d6[1]
246	vmov		q6,q7
247	vmlal.u32	q12,d29,d7[0]
248	vmov		q7,q8
249	vmlal.u32	q13,d29,d7[1]
250	vmov		q8,q9
251	vmov		q9,q10
252	vshr.u64	d10,d10,#16
253	vmov		q10,q11
254	vmov		q11,q12
255	vadd.u64	d10,d10,d11
256	vmov		q12,q13
257	veor		q13,q13
258	vshr.u64	d10,d10,#16
259
260	b	.LNEON_outer8
261
262.align	4
263.LNEON_outer8:
264	vld1.32		{d28[0]}, [r2,:32]!
265	veor		d8,d8,d8
266	vzip.16		d28,d8
267	vadd.u64	d12,d12,d10
268
269	vmlal.u32	q6,d28,d0[0]
270	vmlal.u32	q7,d28,d0[1]
271	vmlal.u32	q8,d28,d1[0]
272	vshl.i64	d29,d13,#16
273	vmlal.u32	q9,d28,d1[1]
274
275	vadd.u64	d29,d29,d12
276	veor		d8,d8,d8
277	subs		r9,r9,#1
278	vmul.u32	d29,d29,d30
279
280	vmlal.u32	q10,d28,d2[0]
281	vmlal.u32	q11,d28,d2[1]
282	vmlal.u32	q12,d28,d3[0]
283	vzip.16		d29,d8
284	vmlal.u32	q13,d28,d3[1]
285
286	vmlal.u32	q6,d29,d4[0]
287	vmlal.u32	q7,d29,d4[1]
288	vmlal.u32	q8,d29,d5[0]
289	vmlal.u32	q9,d29,d5[1]
290
291	vmlal.u32	q10,d29,d6[0]
292	vmov		q5,q6
293	vmlal.u32	q11,d29,d6[1]
294	vmov		q6,q7
295	vmlal.u32	q12,d29,d7[0]
296	vmov		q7,q8
297	vmlal.u32	q13,d29,d7[1]
298	vmov		q8,q9
299	vmov		q9,q10
300	vshr.u64	d10,d10,#16
301	vmov		q10,q11
302	vmov		q11,q12
303	vadd.u64	d10,d10,d11
304	vmov		q12,q13
305	veor		q13,q13
306	vshr.u64	d10,d10,#16
307
308	bne	.LNEON_outer8
309
310	vadd.u64	d12,d12,d10
311	mov		r7,sp
312	vshr.u64	d10,d12,#16
313	mov		r8,r5
314	vadd.u64	d13,d13,d10
315	add		r6,sp,#96
316	vshr.u64	d10,d13,#16
317	vzip.16		d12,d13
318
319	b	.LNEON_tail_entry
320
321.align	4
322.LNEON_8n:
323	veor		q6,q6,q6
324	 sub		r7,sp,#128
325	veor		q7,q7,q7
326	 sub		r7,r7,r5,lsl#4
327	veor		q8,q8,q8
328	 and		r7,r7,#-64
329	veor		q9,q9,q9
330	 mov		sp,r7			@ alloca
331	veor		q10,q10,q10
332	 add		r7,r7,#256
333	veor		q11,q11,q11
334	 sub		r8,r5,#8
335	veor		q12,q12,q12
336	veor		q13,q13,q13
337
338.LNEON_8n_init:
339	vst1.64		{q6-q7},[r7,:256]!
340	subs		r8,r8,#8
341	vst1.64		{q8-q9},[r7,:256]!
342	vst1.64		{q10-q11},[r7,:256]!
343	vst1.64		{q12-q13},[r7,:256]!
344	bne		.LNEON_8n_init
345
346	add		r6,sp,#256
347	vld1.32		{d0-d3},[r1]!
348	add		r10,sp,#8
349	vld1.32		{d30[0]},[r4,:32]
350	mov		r9,r5
351	b		.LNEON_8n_outer
352
353.align	4
354.LNEON_8n_outer:
355	vld1.32		{d28[0]},[r2,:32]!	@ *b++
356	veor		d8,d8,d8
357	vzip.16		d28,d8
358	add		r7,sp,#128
359	vld1.32		{d4-d7},[r3]!
360
361	vmlal.u32	q6,d28,d0[0]
362	vmlal.u32	q7,d28,d0[1]
363	 veor		d8,d8,d8
364	vmlal.u32	q8,d28,d1[0]
365	 vshl.i64	d29,d13,#16
366	vmlal.u32	q9,d28,d1[1]
367	 vadd.u64	d29,d29,d12
368	vmlal.u32	q10,d28,d2[0]
369	 vmul.u32	d29,d29,d30
370	vmlal.u32	q11,d28,d2[1]
371	vst1.32		{d28},[sp,:64]		@ put aside smashed b[8*i+0]
372	vmlal.u32	q12,d28,d3[0]
373	 vzip.16	d29,d8
374	vmlal.u32	q13,d28,d3[1]
375	vld1.32		{d28[0]},[r2,:32]!	@ *b++
376	vmlal.u32	q6,d29,d4[0]
377	veor		d10,d10,d10
378	vmlal.u32	q7,d29,d4[1]
379	vzip.16		d28,d10
380	vmlal.u32	q8,d29,d5[0]
381	 vshr.u64	d12,d12,#16
382	vmlal.u32	q9,d29,d5[1]
383	vmlal.u32	q10,d29,d6[0]
384	 vadd.u64	d12,d12,d13
385	vmlal.u32	q11,d29,d6[1]
386	 vshr.u64	d12,d12,#16
387	vmlal.u32	q12,d29,d7[0]
388	vmlal.u32	q13,d29,d7[1]
389	 vadd.u64	d14,d14,d12
390	vst1.32		{d29},[r10,:64]!	@ put aside smashed m[8*i+0]
391	vmlal.u32	q7,d28,d0[0]
392	vld1.64		{q6},[r6,:128]!
393	vmlal.u32	q8,d28,d0[1]
394	 veor		d8,d8,d8
395	vmlal.u32	q9,d28,d1[0]
396	 vshl.i64	d29,d15,#16
397	vmlal.u32	q10,d28,d1[1]
398	 vadd.u64	d29,d29,d14
399	vmlal.u32	q11,d28,d2[0]
400	 vmul.u32	d29,d29,d30
401	vmlal.u32	q12,d28,d2[1]
402	vst1.32		{d28},[r10,:64]!	@ put aside smashed b[8*i+1]
403	vmlal.u32	q13,d28,d3[0]
404	 vzip.16	d29,d8
405	vmlal.u32	q6,d28,d3[1]
406	vld1.32		{d28[0]},[r2,:32]!	@ *b++
407	vmlal.u32	q7,d29,d4[0]
408	veor		d10,d10,d10
409	vmlal.u32	q8,d29,d4[1]
410	vzip.16		d28,d10
411	vmlal.u32	q9,d29,d5[0]
412	 vshr.u64	d14,d14,#16
413	vmlal.u32	q10,d29,d5[1]
414	vmlal.u32	q11,d29,d6[0]
415	 vadd.u64	d14,d14,d15
416	vmlal.u32	q12,d29,d6[1]
417	 vshr.u64	d14,d14,#16
418	vmlal.u32	q13,d29,d7[0]
419	vmlal.u32	q6,d29,d7[1]
420	 vadd.u64	d16,d16,d14
421	vst1.32		{d29},[r10,:64]!	@ put aside smashed m[8*i+1]
422	vmlal.u32	q8,d28,d0[0]
423	vld1.64		{q7},[r6,:128]!
424	vmlal.u32	q9,d28,d0[1]
425	 veor		d8,d8,d8
426	vmlal.u32	q10,d28,d1[0]
427	 vshl.i64	d29,d17,#16
428	vmlal.u32	q11,d28,d1[1]
429	 vadd.u64	d29,d29,d16
430	vmlal.u32	q12,d28,d2[0]
431	 vmul.u32	d29,d29,d30
432	vmlal.u32	q13,d28,d2[1]
433	vst1.32		{d28},[r10,:64]!	@ put aside smashed b[8*i+2]
434	vmlal.u32	q6,d28,d3[0]
435	 vzip.16	d29,d8
436	vmlal.u32	q7,d28,d3[1]
437	vld1.32		{d28[0]},[r2,:32]!	@ *b++
438	vmlal.u32	q8,d29,d4[0]
439	veor		d10,d10,d10
440	vmlal.u32	q9,d29,d4[1]
441	vzip.16		d28,d10
442	vmlal.u32	q10,d29,d5[0]
443	 vshr.u64	d16,d16,#16
444	vmlal.u32	q11,d29,d5[1]
445	vmlal.u32	q12,d29,d6[0]
446	 vadd.u64	d16,d16,d17
447	vmlal.u32	q13,d29,d6[1]
448	 vshr.u64	d16,d16,#16
449	vmlal.u32	q6,d29,d7[0]
450	vmlal.u32	q7,d29,d7[1]
451	 vadd.u64	d18,d18,d16
452	vst1.32		{d29},[r10,:64]!	@ put aside smashed m[8*i+2]
453	vmlal.u32	q9,d28,d0[0]
454	vld1.64		{q8},[r6,:128]!
455	vmlal.u32	q10,d28,d0[1]
456	 veor		d8,d8,d8
457	vmlal.u32	q11,d28,d1[0]
458	 vshl.i64	d29,d19,#16
459	vmlal.u32	q12,d28,d1[1]
460	 vadd.u64	d29,d29,d18
461	vmlal.u32	q13,d28,d2[0]
462	 vmul.u32	d29,d29,d30
463	vmlal.u32	q6,d28,d2[1]
464	vst1.32		{d28},[r10,:64]!	@ put aside smashed b[8*i+3]
465	vmlal.u32	q7,d28,d3[0]
466	 vzip.16	d29,d8
467	vmlal.u32	q8,d28,d3[1]
468	vld1.32		{d28[0]},[r2,:32]!	@ *b++
469	vmlal.u32	q9,d29,d4[0]
470	veor		d10,d10,d10
471	vmlal.u32	q10,d29,d4[1]
472	vzip.16		d28,d10
473	vmlal.u32	q11,d29,d5[0]
474	 vshr.u64	d18,d18,#16
475	vmlal.u32	q12,d29,d5[1]
476	vmlal.u32	q13,d29,d6[0]
477	 vadd.u64	d18,d18,d19
478	vmlal.u32	q6,d29,d6[1]
479	 vshr.u64	d18,d18,#16
480	vmlal.u32	q7,d29,d7[0]
481	vmlal.u32	q8,d29,d7[1]
482	 vadd.u64	d20,d20,d18
483	vst1.32		{d29},[r10,:64]!	@ put aside smashed m[8*i+3]
484	vmlal.u32	q10,d28,d0[0]
485	vld1.64		{q9},[r6,:128]!
486	vmlal.u32	q11,d28,d0[1]
487	 veor		d8,d8,d8
488	vmlal.u32	q12,d28,d1[0]
489	 vshl.i64	d29,d21,#16
490	vmlal.u32	q13,d28,d1[1]
491	 vadd.u64	d29,d29,d20
492	vmlal.u32	q6,d28,d2[0]
493	 vmul.u32	d29,d29,d30
494	vmlal.u32	q7,d28,d2[1]
495	vst1.32		{d28},[r10,:64]!	@ put aside smashed b[8*i+4]
496	vmlal.u32	q8,d28,d3[0]
497	 vzip.16	d29,d8
498	vmlal.u32	q9,d28,d3[1]
499	vld1.32		{d28[0]},[r2,:32]!	@ *b++
500	vmlal.u32	q10,d29,d4[0]
501	veor		d10,d10,d10
502	vmlal.u32	q11,d29,d4[1]
503	vzip.16		d28,d10
504	vmlal.u32	q12,d29,d5[0]
505	 vshr.u64	d20,d20,#16
506	vmlal.u32	q13,d29,d5[1]
507	vmlal.u32	q6,d29,d6[0]
508	 vadd.u64	d20,d20,d21
509	vmlal.u32	q7,d29,d6[1]
510	 vshr.u64	d20,d20,#16
511	vmlal.u32	q8,d29,d7[0]
512	vmlal.u32	q9,d29,d7[1]
513	 vadd.u64	d22,d22,d20
514	vst1.32		{d29},[r10,:64]!	@ put aside smashed m[8*i+4]
515	vmlal.u32	q11,d28,d0[0]
516	vld1.64		{q10},[r6,:128]!
517	vmlal.u32	q12,d28,d0[1]
518	 veor		d8,d8,d8
519	vmlal.u32	q13,d28,d1[0]
520	 vshl.i64	d29,d23,#16
521	vmlal.u32	q6,d28,d1[1]
522	 vadd.u64	d29,d29,d22
523	vmlal.u32	q7,d28,d2[0]
524	 vmul.u32	d29,d29,d30
525	vmlal.u32	q8,d28,d2[1]
526	vst1.32		{d28},[r10,:64]!	@ put aside smashed b[8*i+5]
527	vmlal.u32	q9,d28,d3[0]
528	 vzip.16	d29,d8
529	vmlal.u32	q10,d28,d3[1]
530	vld1.32		{d28[0]},[r2,:32]!	@ *b++
531	vmlal.u32	q11,d29,d4[0]
532	veor		d10,d10,d10
533	vmlal.u32	q12,d29,d4[1]
534	vzip.16		d28,d10
535	vmlal.u32	q13,d29,d5[0]
536	 vshr.u64	d22,d22,#16
537	vmlal.u32	q6,d29,d5[1]
538	vmlal.u32	q7,d29,d6[0]
539	 vadd.u64	d22,d22,d23
540	vmlal.u32	q8,d29,d6[1]
541	 vshr.u64	d22,d22,#16
542	vmlal.u32	q9,d29,d7[0]
543	vmlal.u32	q10,d29,d7[1]
544	 vadd.u64	d24,d24,d22
545	vst1.32		{d29},[r10,:64]!	@ put aside smashed m[8*i+5]
546	vmlal.u32	q12,d28,d0[0]
547	vld1.64		{q11},[r6,:128]!
548	vmlal.u32	q13,d28,d0[1]
549	 veor		d8,d8,d8
550	vmlal.u32	q6,d28,d1[0]
551	 vshl.i64	d29,d25,#16
552	vmlal.u32	q7,d28,d1[1]
553	 vadd.u64	d29,d29,d24
554	vmlal.u32	q8,d28,d2[0]
555	 vmul.u32	d29,d29,d30
556	vmlal.u32	q9,d28,d2[1]
557	vst1.32		{d28},[r10,:64]!	@ put aside smashed b[8*i+6]
558	vmlal.u32	q10,d28,d3[0]
559	 vzip.16	d29,d8
560	vmlal.u32	q11,d28,d3[1]
561	vld1.32		{d28[0]},[r2,:32]!	@ *b++
562	vmlal.u32	q12,d29,d4[0]
563	veor		d10,d10,d10
564	vmlal.u32	q13,d29,d4[1]
565	vzip.16		d28,d10
566	vmlal.u32	q6,d29,d5[0]
567	 vshr.u64	d24,d24,#16
568	vmlal.u32	q7,d29,d5[1]
569	vmlal.u32	q8,d29,d6[0]
570	 vadd.u64	d24,d24,d25
571	vmlal.u32	q9,d29,d6[1]
572	 vshr.u64	d24,d24,#16
573	vmlal.u32	q10,d29,d7[0]
574	vmlal.u32	q11,d29,d7[1]
575	 vadd.u64	d26,d26,d24
576	vst1.32		{d29},[r10,:64]!	@ put aside smashed m[8*i+6]
577	vmlal.u32	q13,d28,d0[0]
578	vld1.64		{q12},[r6,:128]!
579	vmlal.u32	q6,d28,d0[1]
580	 veor		d8,d8,d8
581	vmlal.u32	q7,d28,d1[0]
582	 vshl.i64	d29,d27,#16
583	vmlal.u32	q8,d28,d1[1]
584	 vadd.u64	d29,d29,d26
585	vmlal.u32	q9,d28,d2[0]
586	 vmul.u32	d29,d29,d30
587	vmlal.u32	q10,d28,d2[1]
588	vst1.32		{d28},[r10,:64]!	@ put aside smashed b[8*i+7]
589	vmlal.u32	q11,d28,d3[0]
590	 vzip.16	d29,d8
591	vmlal.u32	q12,d28,d3[1]
592	vld1.32		{d28},[sp,:64]		@ pull smashed b[8*i+0]
593	vmlal.u32	q13,d29,d4[0]
594	vld1.32		{d0-d3},[r1]!
595	vmlal.u32	q6,d29,d4[1]
596	vmlal.u32	q7,d29,d5[0]
597	 vshr.u64	d26,d26,#16
598	vmlal.u32	q8,d29,d5[1]
599	vmlal.u32	q9,d29,d6[0]
600	 vadd.u64	d26,d26,d27
601	vmlal.u32	q10,d29,d6[1]
602	 vshr.u64	d26,d26,#16
603	vmlal.u32	q11,d29,d7[0]
604	vmlal.u32	q12,d29,d7[1]
605	 vadd.u64	d12,d12,d26
606	vst1.32		{d29},[r10,:64]	@ put aside smashed m[8*i+7]
607	add		r10,sp,#8		@ rewind
608	sub		r8,r5,#8
609	b		.LNEON_8n_inner
610
611.align	4
612.LNEON_8n_inner:
613	subs		r8,r8,#8
614	vmlal.u32	q6,d28,d0[0]
615	vld1.64		{q13},[r6,:128]
616	vmlal.u32	q7,d28,d0[1]
617	vld1.32		{d29},[r10,:64]!	@ pull smashed m[8*i+0]
618	vmlal.u32	q8,d28,d1[0]
619	vld1.32		{d4-d7},[r3]!
620	vmlal.u32	q9,d28,d1[1]
621	it		ne
622	addne		r6,r6,#16	@ don't advance in last iteration
623	vmlal.u32	q10,d28,d2[0]
624	vmlal.u32	q11,d28,d2[1]
625	vmlal.u32	q12,d28,d3[0]
626	vmlal.u32	q13,d28,d3[1]
627	vld1.32		{d28},[r10,:64]!	@ pull smashed b[8*i+1]
628	vmlal.u32	q6,d29,d4[0]
629	vmlal.u32	q7,d29,d4[1]
630	vmlal.u32	q8,d29,d5[0]
631	vmlal.u32	q9,d29,d5[1]
632	vmlal.u32	q10,d29,d6[0]
633	vmlal.u32	q11,d29,d6[1]
634	vmlal.u32	q12,d29,d7[0]
635	vmlal.u32	q13,d29,d7[1]
636	vst1.64		{q6},[r7,:128]!
637	vmlal.u32	q7,d28,d0[0]
638	vld1.64		{q6},[r6,:128]
639	vmlal.u32	q8,d28,d0[1]
640	vld1.32		{d29},[r10,:64]!	@ pull smashed m[8*i+1]
641	vmlal.u32	q9,d28,d1[0]
642	it		ne
643	addne		r6,r6,#16	@ don't advance in last iteration
644	vmlal.u32	q10,d28,d1[1]
645	vmlal.u32	q11,d28,d2[0]
646	vmlal.u32	q12,d28,d2[1]
647	vmlal.u32	q13,d28,d3[0]
648	vmlal.u32	q6,d28,d3[1]
649	vld1.32		{d28},[r10,:64]!	@ pull smashed b[8*i+2]
650	vmlal.u32	q7,d29,d4[0]
651	vmlal.u32	q8,d29,d4[1]
652	vmlal.u32	q9,d29,d5[0]
653	vmlal.u32	q10,d29,d5[1]
654	vmlal.u32	q11,d29,d6[0]
655	vmlal.u32	q12,d29,d6[1]
656	vmlal.u32	q13,d29,d7[0]
657	vmlal.u32	q6,d29,d7[1]
658	vst1.64		{q7},[r7,:128]!
659	vmlal.u32	q8,d28,d0[0]
660	vld1.64		{q7},[r6,:128]
661	vmlal.u32	q9,d28,d0[1]
662	vld1.32		{d29},[r10,:64]!	@ pull smashed m[8*i+2]
663	vmlal.u32	q10,d28,d1[0]
664	it		ne
665	addne		r6,r6,#16	@ don't advance in last iteration
666	vmlal.u32	q11,d28,d1[1]
667	vmlal.u32	q12,d28,d2[0]
668	vmlal.u32	q13,d28,d2[1]
669	vmlal.u32	q6,d28,d3[0]
670	vmlal.u32	q7,d28,d3[1]
671	vld1.32		{d28},[r10,:64]!	@ pull smashed b[8*i+3]
672	vmlal.u32	q8,d29,d4[0]
673	vmlal.u32	q9,d29,d4[1]
674	vmlal.u32	q10,d29,d5[0]
675	vmlal.u32	q11,d29,d5[1]
676	vmlal.u32	q12,d29,d6[0]
677	vmlal.u32	q13,d29,d6[1]
678	vmlal.u32	q6,d29,d7[0]
679	vmlal.u32	q7,d29,d7[1]
680	vst1.64		{q8},[r7,:128]!
681	vmlal.u32	q9,d28,d0[0]
682	vld1.64		{q8},[r6,:128]
683	vmlal.u32	q10,d28,d0[1]
684	vld1.32		{d29},[r10,:64]!	@ pull smashed m[8*i+3]
685	vmlal.u32	q11,d28,d1[0]
686	it		ne
687	addne		r6,r6,#16	@ don't advance in last iteration
688	vmlal.u32	q12,d28,d1[1]
689	vmlal.u32	q13,d28,d2[0]
690	vmlal.u32	q6,d28,d2[1]
691	vmlal.u32	q7,d28,d3[0]
692	vmlal.u32	q8,d28,d3[1]
693	vld1.32		{d28},[r10,:64]!	@ pull smashed b[8*i+4]
694	vmlal.u32	q9,d29,d4[0]
695	vmlal.u32	q10,d29,d4[1]
696	vmlal.u32	q11,d29,d5[0]
697	vmlal.u32	q12,d29,d5[1]
698	vmlal.u32	q13,d29,d6[0]
699	vmlal.u32	q6,d29,d6[1]
700	vmlal.u32	q7,d29,d7[0]
701	vmlal.u32	q8,d29,d7[1]
702	vst1.64		{q9},[r7,:128]!
703	vmlal.u32	q10,d28,d0[0]
704	vld1.64		{q9},[r6,:128]
705	vmlal.u32	q11,d28,d0[1]
706	vld1.32		{d29},[r10,:64]!	@ pull smashed m[8*i+4]
707	vmlal.u32	q12,d28,d1[0]
708	it		ne
709	addne		r6,r6,#16	@ don't advance in last iteration
710	vmlal.u32	q13,d28,d1[1]
711	vmlal.u32	q6,d28,d2[0]
712	vmlal.u32	q7,d28,d2[1]
713	vmlal.u32	q8,d28,d3[0]
714	vmlal.u32	q9,d28,d3[1]
715	vld1.32		{d28},[r10,:64]!	@ pull smashed b[8*i+5]
716	vmlal.u32	q10,d29,d4[0]
717	vmlal.u32	q11,d29,d4[1]
718	vmlal.u32	q12,d29,d5[0]
719	vmlal.u32	q13,d29,d5[1]
720	vmlal.u32	q6,d29,d6[0]
721	vmlal.u32	q7,d29,d6[1]
722	vmlal.u32	q8,d29,d7[0]
723	vmlal.u32	q9,d29,d7[1]
724	vst1.64		{q10},[r7,:128]!
725	vmlal.u32	q11,d28,d0[0]
726	vld1.64		{q10},[r6,:128]
727	vmlal.u32	q12,d28,d0[1]
728	vld1.32		{d29},[r10,:64]!	@ pull smashed m[8*i+5]
729	vmlal.u32	q13,d28,d1[0]
730	it		ne
731	addne		r6,r6,#16	@ don't advance in last iteration
732	vmlal.u32	q6,d28,d1[1]
733	vmlal.u32	q7,d28,d2[0]
734	vmlal.u32	q8,d28,d2[1]
735	vmlal.u32	q9,d28,d3[0]
736	vmlal.u32	q10,d28,d3[1]
737	vld1.32		{d28},[r10,:64]!	@ pull smashed b[8*i+6]
738	vmlal.u32	q11,d29,d4[0]
739	vmlal.u32	q12,d29,d4[1]
740	vmlal.u32	q13,d29,d5[0]
741	vmlal.u32	q6,d29,d5[1]
742	vmlal.u32	q7,d29,d6[0]
743	vmlal.u32	q8,d29,d6[1]
744	vmlal.u32	q9,d29,d7[0]
745	vmlal.u32	q10,d29,d7[1]
746	vst1.64		{q11},[r7,:128]!
747	vmlal.u32	q12,d28,d0[0]
748	vld1.64		{q11},[r6,:128]
749	vmlal.u32	q13,d28,d0[1]
750	vld1.32		{d29},[r10,:64]!	@ pull smashed m[8*i+6]
751	vmlal.u32	q6,d28,d1[0]
752	it		ne
753	addne		r6,r6,#16	@ don't advance in last iteration
754	vmlal.u32	q7,d28,d1[1]
755	vmlal.u32	q8,d28,d2[0]
756	vmlal.u32	q9,d28,d2[1]
757	vmlal.u32	q10,d28,d3[0]
758	vmlal.u32	q11,d28,d3[1]
759	vld1.32		{d28},[r10,:64]!	@ pull smashed b[8*i+7]
760	vmlal.u32	q12,d29,d4[0]
761	vmlal.u32	q13,d29,d4[1]
762	vmlal.u32	q6,d29,d5[0]
763	vmlal.u32	q7,d29,d5[1]
764	vmlal.u32	q8,d29,d6[0]
765	vmlal.u32	q9,d29,d6[1]
766	vmlal.u32	q10,d29,d7[0]
767	vmlal.u32	q11,d29,d7[1]
768	vst1.64		{q12},[r7,:128]!
769	vmlal.u32	q13,d28,d0[0]
770	vld1.64		{q12},[r6,:128]
771	vmlal.u32	q6,d28,d0[1]
772	vld1.32		{d29},[r10,:64]!	@ pull smashed m[8*i+7]
773	vmlal.u32	q7,d28,d1[0]
774	it		ne
775	addne		r6,r6,#16	@ don't advance in last iteration
776	vmlal.u32	q8,d28,d1[1]
777	vmlal.u32	q9,d28,d2[0]
778	vmlal.u32	q10,d28,d2[1]
779	vmlal.u32	q11,d28,d3[0]
780	vmlal.u32	q12,d28,d3[1]
781	it		eq
782	subeq		r1,r1,r5,lsl#2	@ rewind
783	vmlal.u32	q13,d29,d4[0]
784	vld1.32		{d28},[sp,:64]		@ pull smashed b[8*i+0]
785	vmlal.u32	q6,d29,d4[1]
786	vld1.32		{d0-d3},[r1]!
787	vmlal.u32	q7,d29,d5[0]
788	add		r10,sp,#8		@ rewind
789	vmlal.u32	q8,d29,d5[1]
790	vmlal.u32	q9,d29,d6[0]
791	vmlal.u32	q10,d29,d6[1]
792	vmlal.u32	q11,d29,d7[0]
793	vst1.64		{q13},[r7,:128]!
794	vmlal.u32	q12,d29,d7[1]
795
796	bne		.LNEON_8n_inner
797	add		r6,sp,#128
798	vst1.64		{q6-q7},[r7,:256]!
799	veor		q2,q2,q2		@ d4-d5
800	vst1.64		{q8-q9},[r7,:256]!
801	veor		q3,q3,q3		@ d6-d7
802	vst1.64		{q10-q11},[r7,:256]!
803	vst1.64		{q12},[r7,:128]
804
805	subs		r9,r9,#8
806	vld1.64		{q6-q7},[r6,:256]!
807	vld1.64		{q8-q9},[r6,:256]!
808	vld1.64		{q10-q11},[r6,:256]!
809	vld1.64		{q12-q13},[r6,:256]!
810
811	itt		ne
812	subne		r3,r3,r5,lsl#2	@ rewind
813	bne		.LNEON_8n_outer
814
815	add		r7,sp,#128
816	vst1.64		{q2-q3}, [sp,:256]!	@ start wiping stack frame
817	vshr.u64	d10,d12,#16
818	vst1.64		{q2-q3},[sp,:256]!
819	vadd.u64	d13,d13,d10
820	vst1.64		{q2-q3}, [sp,:256]!
821	vshr.u64	d10,d13,#16
822	vst1.64		{q2-q3}, [sp,:256]!
823	vzip.16		d12,d13
824
825	mov		r8,r5
826	b		.LNEON_tail_entry
827
828.align	4
829.LNEON_tail:
830	vadd.u64	d12,d12,d10
831	vshr.u64	d10,d12,#16
832	vld1.64		{q8-q9}, [r6, :256]!
833	vadd.u64	d13,d13,d10
834	vld1.64		{q10-q11}, [r6, :256]!
835	vshr.u64	d10,d13,#16
836	vld1.64		{q12-q13}, [r6, :256]!
837	vzip.16		d12,d13
838
839.LNEON_tail_entry:
840	vadd.u64	d14,d14,d10
841	vst1.32		{d12[0]}, [r7, :32]!
842	vshr.u64	d10,d14,#16
843	vadd.u64	d15,d15,d10
844	vshr.u64	d10,d15,#16
845	vzip.16		d14,d15
846	vadd.u64	d16,d16,d10
847	vst1.32		{d14[0]}, [r7, :32]!
848	vshr.u64	d10,d16,#16
849	vadd.u64	d17,d17,d10
850	vshr.u64	d10,d17,#16
851	vzip.16		d16,d17
852	vadd.u64	d18,d18,d10
853	vst1.32		{d16[0]}, [r7, :32]!
854	vshr.u64	d10,d18,#16
855	vadd.u64	d19,d19,d10
856	vshr.u64	d10,d19,#16
857	vzip.16		d18,d19
858	vadd.u64	d20,d20,d10
859	vst1.32		{d18[0]}, [r7, :32]!
860	vshr.u64	d10,d20,#16
861	vadd.u64	d21,d21,d10
862	vshr.u64	d10,d21,#16
863	vzip.16		d20,d21
864	vadd.u64	d22,d22,d10
865	vst1.32		{d20[0]}, [r7, :32]!
866	vshr.u64	d10,d22,#16
867	vadd.u64	d23,d23,d10
868	vshr.u64	d10,d23,#16
869	vzip.16		d22,d23
870	vadd.u64	d24,d24,d10
871	vst1.32		{d22[0]}, [r7, :32]!
872	vshr.u64	d10,d24,#16
873	vadd.u64	d25,d25,d10
874	vshr.u64	d10,d25,#16
875	vzip.16		d24,d25
876	vadd.u64	d26,d26,d10
877	vst1.32		{d24[0]}, [r7, :32]!
878	vshr.u64	d10,d26,#16
879	vadd.u64	d27,d27,d10
880	vshr.u64	d10,d27,#16
881	vzip.16		d26,d27
882	vld1.64		{q6-q7}, [r6, :256]!
883	subs		r8,r8,#8
884	vst1.32		{d26[0]},   [r7, :32]!
885	bne	.LNEON_tail
886
887	vst1.32	{d10[0]}, [r7, :32]		@ top-most bit
888	sub	r3,r3,r5,lsl#2			@ rewind r3
889	subs	r1,sp,#0				@ clear carry flag
890	add	r2,sp,r5,lsl#2
891
892.LNEON_sub:
893	ldmia	r1!, {r4-r7}
894	ldmia	r3!, {r8-r11}
895	sbcs	r8, r4,r8
896	sbcs	r9, r5,r9
897	sbcs	r10,r6,r10
898	sbcs	r11,r7,r11
899	teq	r1,r2				@ preserves carry
900	stmia	r0!, {r8-r11}
901	bne	.LNEON_sub
902
903	ldr	r10, [r1]				@ load top-most bit
904	mov	r11,sp
905	veor	q0,q0,q0
906	sub	r11,r2,r11				@ this is num*4
907	veor	q1,q1,q1
908	mov	r1,sp
909	sub	r0,r0,r11				@ rewind r0
910	mov	r3,r2				@ second 3/4th of frame
911	sbcs	r10,r10,#0				@ result is carry flag
912
913.LNEON_copy_n_zap:
914	ldmia	r1!, {r4-r7}
915	ldmia	r0,  {r8-r11}
916	it	cc
917	movcc	r8, r4
918	vst1.64	{q0-q1}, [r3,:256]!			@ wipe
919	itt	cc
920	movcc	r9, r5
921	movcc	r10,r6
922	vst1.64	{q0-q1}, [r3,:256]!			@ wipe
923	it	cc
924	movcc	r11,r7
925	ldmia	r1, {r4-r7}
926	stmia	r0!, {r8-r11}
927	sub	r1,r1,#16
928	ldmia	r0, {r8-r11}
929	it	cc
930	movcc	r8, r4
931	vst1.64	{q0-q1}, [r1,:256]!			@ wipe
932	itt	cc
933	movcc	r9, r5
934	movcc	r10,r6
935	vst1.64	{q0-q1}, [r3,:256]!			@ wipe
936	it	cc
937	movcc	r11,r7
938	teq	r1,r2				@ preserves carry
939	stmia	r0!, {r8-r11}
940	bne	.LNEON_copy_n_zap
941
942	mov	sp,ip
943        vldmia  sp!,{d8-d15}
944        ldmia   sp!,{r4-r11}
945	bx    lr						@ bx lr
946.size	bn_mul8x_mont_neon,.-bn_mul8x_mont_neon
947#endif
948.asciz	"Montgomery multiplication for ARMv4/NEON, CRYPTOGAMS by <appro@openssl.org>"
949.align	2
950#if __ARM_MAX_ARCH__>=7
951.comm	OPENSSL_armcap_P,4,4
952#endif
953