xref: /netbsd-src/crypto/external/bsd/openssl.old/lib/libcrypto/arch/arm/poly1305-armv8.S (revision 4724848cf0da353df257f730694b7882798e5daf)
1*4724848cSchristos#include "arm_asm.h"
2*4724848cSchristos#include "arm_arch.h"
3*4724848cSchristos
4*4724848cSchristos.text
5*4724848cSchristos
6*4724848cSchristos// forward "declarations" are required for Apple
7*4724848cSchristos
8*4724848cSchristos.hidden	OPENSSL_armcap_P
9*4724848cSchristos.globl	poly1305_init
10*4724848cSchristos.hidden	poly1305_init
11*4724848cSchristos.globl	poly1305_blocks
12*4724848cSchristos.hidden	poly1305_blocks
13*4724848cSchristos.globl	poly1305_emit
14*4724848cSchristos.hidden	poly1305_emit
15*4724848cSchristos
16*4724848cSchristos.type	poly1305_init,%function
17*4724848cSchristos.align	5
18*4724848cSchristospoly1305_init:
19*4724848cSchristos	cmp	x1,xzr
20*4724848cSchristos	stp	xzr,xzr,[x0]		// zero hash value
21*4724848cSchristos	stp	xzr,xzr,[x0,#16]	// [along with is_base2_26]
22*4724848cSchristos
23*4724848cSchristos	csel	x0,xzr,x0,eq
24*4724848cSchristos	b.eq	.Lno_key
25*4724848cSchristos
26*4724848cSchristos#ifdef	__ILP32__
27*4724848cSchristos	ldrsw	x11,.LOPENSSL_armcap_P
28*4724848cSchristos#else
29*4724848cSchristos	ldr	x11,.LOPENSSL_armcap_P
30*4724848cSchristos#endif
31*4724848cSchristos	adr	x10,.LOPENSSL_armcap_P
32*4724848cSchristos
33*4724848cSchristos	ldp	x7,x8,[x1]		// load key
34*4724848cSchristos	mov	x9,#0xfffffffc0fffffff
35*4724848cSchristos	movk	x9,#0x0fff,lsl#48
36*4724848cSchristos	ldr	w17,[x10,x11]
37*4724848cSchristos#ifdef	__ARMEB__
38*4724848cSchristos	rev	x7,x7			// flip bytes
39*4724848cSchristos	rev	x8,x8
40*4724848cSchristos#endif
41*4724848cSchristos	and	x7,x7,x9		// &=0ffffffc0fffffff
42*4724848cSchristos	and	x9,x9,#-4
43*4724848cSchristos	and	x8,x8,x9		// &=0ffffffc0ffffffc
44*4724848cSchristos	stp	x7,x8,[x0,#32]	// save key value
45*4724848cSchristos
46*4724848cSchristos	tst	w17,#ARMV7_NEON
47*4724848cSchristos
48*4724848cSchristos	adr	x12,poly1305_blocks
49*4724848cSchristos	adr	x7,poly1305_blocks_neon
50*4724848cSchristos	adr	x13,poly1305_emit
51*4724848cSchristos	adr	x8,poly1305_emit_neon
52*4724848cSchristos
53*4724848cSchristos	csel	x12,x12,x7,eq
54*4724848cSchristos	csel	x13,x13,x8,eq
55*4724848cSchristos
56*4724848cSchristos#ifdef	__ILP32__
57*4724848cSchristos	stp	w12,w13,[x2]
58*4724848cSchristos#else
59*4724848cSchristos	stp	x12,x13,[x2]
60*4724848cSchristos#endif
61*4724848cSchristos
62*4724848cSchristos	mov	x0,#1
63*4724848cSchristos.Lno_key:
64*4724848cSchristos	ret
65*4724848cSchristos.size	poly1305_init,.-poly1305_init
66*4724848cSchristos
67*4724848cSchristos.type	poly1305_blocks,%function
68*4724848cSchristos.align	5
69*4724848cSchristospoly1305_blocks:
70*4724848cSchristos	ands	x2,x2,#-16
71*4724848cSchristos	b.eq	.Lno_data
72*4724848cSchristos
73*4724848cSchristos	ldp	x4,x5,[x0]		// load hash value
74*4724848cSchristos	ldp	x7,x8,[x0,#32]	// load key value
75*4724848cSchristos	ldr	x6,[x0,#16]
76*4724848cSchristos	add	x9,x8,x8,lsr#2	// s1 = r1 + (r1 >> 2)
77*4724848cSchristos	b	.Loop
78*4724848cSchristos
79*4724848cSchristos.align	5
80*4724848cSchristos.Loop:
81*4724848cSchristos	ldp	x10,x11,[x1],#16	// load input
82*4724848cSchristos	sub	x2,x2,#16
83*4724848cSchristos#ifdef	__ARMEB__
84*4724848cSchristos	rev	x10,x10
85*4724848cSchristos	rev	x11,x11
86*4724848cSchristos#endif
87*4724848cSchristos	adds	x4,x4,x10		// accumulate input
88*4724848cSchristos	adcs	x5,x5,x11
89*4724848cSchristos
90*4724848cSchristos	mul	x12,x4,x7		// h0*r0
91*4724848cSchristos	adc	x6,x6,x3
92*4724848cSchristos	umulh	x13,x4,x7
93*4724848cSchristos
94*4724848cSchristos	mul	x10,x5,x9		// h1*5*r1
95*4724848cSchristos	umulh	x11,x5,x9
96*4724848cSchristos
97*4724848cSchristos	adds	x12,x12,x10
98*4724848cSchristos	mul	x10,x4,x8		// h0*r1
99*4724848cSchristos	adc	x13,x13,x11
100*4724848cSchristos	umulh	x14,x4,x8
101*4724848cSchristos
102*4724848cSchristos	adds	x13,x13,x10
103*4724848cSchristos	mul	x10,x5,x7		// h1*r0
104*4724848cSchristos	adc	x14,x14,xzr
105*4724848cSchristos	umulh	x11,x5,x7
106*4724848cSchristos
107*4724848cSchristos	adds	x13,x13,x10
108*4724848cSchristos	mul	x10,x6,x9		// h2*5*r1
109*4724848cSchristos	adc	x14,x14,x11
110*4724848cSchristos	mul	x11,x6,x7		// h2*r0
111*4724848cSchristos
112*4724848cSchristos	adds	x13,x13,x10
113*4724848cSchristos	adc	x14,x14,x11
114*4724848cSchristos
115*4724848cSchristos	and	x10,x14,#-4		// final reduction
116*4724848cSchristos	and	x6,x14,#3
117*4724848cSchristos	add	x10,x10,x14,lsr#2
118*4724848cSchristos	adds	x4,x12,x10
119*4724848cSchristos	adcs	x5,x13,xzr
120*4724848cSchristos	adc	x6,x6,xzr
121*4724848cSchristos
122*4724848cSchristos	cbnz	x2,.Loop
123*4724848cSchristos
124*4724848cSchristos	stp	x4,x5,[x0]		// store hash value
125*4724848cSchristos	str	x6,[x0,#16]
126*4724848cSchristos
127*4724848cSchristos.Lno_data:
128*4724848cSchristos	ret
129*4724848cSchristos.size	poly1305_blocks,.-poly1305_blocks
130*4724848cSchristos
131*4724848cSchristos.type	poly1305_emit,%function
132*4724848cSchristos.align	5
133*4724848cSchristospoly1305_emit:
134*4724848cSchristos	ldp	x4,x5,[x0]		// load hash base 2^64
135*4724848cSchristos	ldr	x6,[x0,#16]
136*4724848cSchristos	ldp	x10,x11,[x2]	// load nonce
137*4724848cSchristos
138*4724848cSchristos	adds	x12,x4,#5		// compare to modulus
139*4724848cSchristos	adcs	x13,x5,xzr
140*4724848cSchristos	adc	x14,x6,xzr
141*4724848cSchristos
142*4724848cSchristos	tst	x14,#-4			// see if it's carried/borrowed
143*4724848cSchristos
144*4724848cSchristos	csel	x4,x4,x12,eq
145*4724848cSchristos	csel	x5,x5,x13,eq
146*4724848cSchristos
147*4724848cSchristos#ifdef	__ARMEB__
148*4724848cSchristos	ror	x10,x10,#32		// flip nonce words
149*4724848cSchristos	ror	x11,x11,#32
150*4724848cSchristos#endif
151*4724848cSchristos	adds	x4,x4,x10		// accumulate nonce
152*4724848cSchristos	adc	x5,x5,x11
153*4724848cSchristos#ifdef	__ARMEB__
154*4724848cSchristos	rev	x4,x4			// flip output bytes
155*4724848cSchristos	rev	x5,x5
156*4724848cSchristos#endif
157*4724848cSchristos	stp	x4,x5,[x1]		// write result
158*4724848cSchristos
159*4724848cSchristos	ret
160*4724848cSchristos.size	poly1305_emit,.-poly1305_emit
161*4724848cSchristos.type	poly1305_mult,%function
162*4724848cSchristos.align	5
163*4724848cSchristospoly1305_mult:
164*4724848cSchristos	mul	x12,x4,x7		// h0*r0
165*4724848cSchristos	umulh	x13,x4,x7
166*4724848cSchristos
167*4724848cSchristos	mul	x10,x5,x9		// h1*5*r1
168*4724848cSchristos	umulh	x11,x5,x9
169*4724848cSchristos
170*4724848cSchristos	adds	x12,x12,x10
171*4724848cSchristos	mul	x10,x4,x8		// h0*r1
172*4724848cSchristos	adc	x13,x13,x11
173*4724848cSchristos	umulh	x14,x4,x8
174*4724848cSchristos
175*4724848cSchristos	adds	x13,x13,x10
176*4724848cSchristos	mul	x10,x5,x7		// h1*r0
177*4724848cSchristos	adc	x14,x14,xzr
178*4724848cSchristos	umulh	x11,x5,x7
179*4724848cSchristos
180*4724848cSchristos	adds	x13,x13,x10
181*4724848cSchristos	mul	x10,x6,x9		// h2*5*r1
182*4724848cSchristos	adc	x14,x14,x11
183*4724848cSchristos	mul	x11,x6,x7		// h2*r0
184*4724848cSchristos
185*4724848cSchristos	adds	x13,x13,x10
186*4724848cSchristos	adc	x14,x14,x11
187*4724848cSchristos
188*4724848cSchristos	and	x10,x14,#-4		// final reduction
189*4724848cSchristos	and	x6,x14,#3
190*4724848cSchristos	add	x10,x10,x14,lsr#2
191*4724848cSchristos	adds	x4,x12,x10
192*4724848cSchristos	adcs	x5,x13,xzr
193*4724848cSchristos	adc	x6,x6,xzr
194*4724848cSchristos
195*4724848cSchristos	ret
196*4724848cSchristos.size	poly1305_mult,.-poly1305_mult
197*4724848cSchristos
198*4724848cSchristos.type	poly1305_splat,%function
199*4724848cSchristos.align	5
200*4724848cSchristospoly1305_splat:
201*4724848cSchristos	and	x12,x4,#0x03ffffff	// base 2^64 -> base 2^26
202*4724848cSchristos	ubfx	x13,x4,#26,#26
203*4724848cSchristos	extr	x14,x5,x4,#52
204*4724848cSchristos	and	x14,x14,#0x03ffffff
205*4724848cSchristos	ubfx	x15,x5,#14,#26
206*4724848cSchristos	extr	x16,x6,x5,#40
207*4724848cSchristos
208*4724848cSchristos	str	w12,[x0,#16*0]	// r0
209*4724848cSchristos	add	w12,w13,w13,lsl#2	// r1*5
210*4724848cSchristos	str	w13,[x0,#16*1]	// r1
211*4724848cSchristos	add	w13,w14,w14,lsl#2	// r2*5
212*4724848cSchristos	str	w12,[x0,#16*2]	// s1
213*4724848cSchristos	str	w14,[x0,#16*3]	// r2
214*4724848cSchristos	add	w14,w15,w15,lsl#2	// r3*5
215*4724848cSchristos	str	w13,[x0,#16*4]	// s2
216*4724848cSchristos	str	w15,[x0,#16*5]	// r3
217*4724848cSchristos	add	w15,w16,w16,lsl#2	// r4*5
218*4724848cSchristos	str	w14,[x0,#16*6]	// s3
219*4724848cSchristos	str	w16,[x0,#16*7]	// r4
220*4724848cSchristos	str	w15,[x0,#16*8]	// s4
221*4724848cSchristos
222*4724848cSchristos	ret
223*4724848cSchristos.size	poly1305_splat,.-poly1305_splat
224*4724848cSchristos
225*4724848cSchristos.type	poly1305_blocks_neon,%function
226*4724848cSchristos.align	5
227*4724848cSchristospoly1305_blocks_neon:
228*4724848cSchristos	ldr	x17,[x0,#24]
229*4724848cSchristos	cmp	x2,#128
230*4724848cSchristos	b.hs	.Lblocks_neon
231*4724848cSchristos	cbz	x17,poly1305_blocks
232*4724848cSchristos
233*4724848cSchristos.Lblocks_neon:
234*4724848cSchristos.inst	0xd503233f		// paciasp
235*4724848cSchristos	stp	x29,x30,[sp,#-80]!
236*4724848cSchristos	add	x29,sp,#0
237*4724848cSchristos
238*4724848cSchristos	ands	x2,x2,#-16
239*4724848cSchristos	b.eq	.Lno_data_neon
240*4724848cSchristos
241*4724848cSchristos	cbz	x17,.Lbase2_64_neon
242*4724848cSchristos
243*4724848cSchristos	ldp	w10,w11,[x0]		// load hash value base 2^26
244*4724848cSchristos	ldp	w12,w13,[x0,#8]
245*4724848cSchristos	ldr	w14,[x0,#16]
246*4724848cSchristos
247*4724848cSchristos	tst	x2,#31
248*4724848cSchristos	b.eq	.Leven_neon
249*4724848cSchristos
250*4724848cSchristos	ldp	x7,x8,[x0,#32]	// load key value
251*4724848cSchristos
252*4724848cSchristos	add	x4,x10,x11,lsl#26	// base 2^26 -> base 2^64
253*4724848cSchristos	lsr	x5,x12,#12
254*4724848cSchristos	adds	x4,x4,x12,lsl#52
255*4724848cSchristos	add	x5,x5,x13,lsl#14
256*4724848cSchristos	adc	x5,x5,xzr
257*4724848cSchristos	lsr	x6,x14,#24
258*4724848cSchristos	adds	x5,x5,x14,lsl#40
259*4724848cSchristos	adc	x14,x6,xzr		// can be partially reduced...
260*4724848cSchristos
261*4724848cSchristos	ldp	x12,x13,[x1],#16	// load input
262*4724848cSchristos	sub	x2,x2,#16
263*4724848cSchristos	add	x9,x8,x8,lsr#2	// s1 = r1 + (r1 >> 2)
264*4724848cSchristos
265*4724848cSchristos	and	x10,x14,#-4		// ... so reduce
266*4724848cSchristos	and	x6,x14,#3
267*4724848cSchristos	add	x10,x10,x14,lsr#2
268*4724848cSchristos	adds	x4,x4,x10
269*4724848cSchristos	adcs	x5,x5,xzr
270*4724848cSchristos	adc	x6,x6,xzr
271*4724848cSchristos
272*4724848cSchristos#ifdef	__ARMEB__
273*4724848cSchristos	rev	x12,x12
274*4724848cSchristos	rev	x13,x13
275*4724848cSchristos#endif
276*4724848cSchristos	adds	x4,x4,x12		// accumulate input
277*4724848cSchristos	adcs	x5,x5,x13
278*4724848cSchristos	adc	x6,x6,x3
279*4724848cSchristos
280*4724848cSchristos	bl	poly1305_mult
281*4724848cSchristos	ldr	x30,[sp,#8]
282*4724848cSchristos
283*4724848cSchristos	cbz	x3,.Lstore_base2_64_neon
284*4724848cSchristos
285*4724848cSchristos	and	x10,x4,#0x03ffffff	// base 2^64 -> base 2^26
286*4724848cSchristos	ubfx	x11,x4,#26,#26
287*4724848cSchristos	extr	x12,x5,x4,#52
288*4724848cSchristos	and	x12,x12,#0x03ffffff
289*4724848cSchristos	ubfx	x13,x5,#14,#26
290*4724848cSchristos	extr	x14,x6,x5,#40
291*4724848cSchristos
292*4724848cSchristos	cbnz	x2,.Leven_neon
293*4724848cSchristos
294*4724848cSchristos	stp	w10,w11,[x0]		// store hash value base 2^26
295*4724848cSchristos	stp	w12,w13,[x0,#8]
296*4724848cSchristos	str	w14,[x0,#16]
297*4724848cSchristos	b	.Lno_data_neon
298*4724848cSchristos
299*4724848cSchristos.align	4
300*4724848cSchristos.Lstore_base2_64_neon:
301*4724848cSchristos	stp	x4,x5,[x0]		// store hash value base 2^64
302*4724848cSchristos	stp	x6,xzr,[x0,#16]	// note that is_base2_26 is zeroed
303*4724848cSchristos	b	.Lno_data_neon
304*4724848cSchristos
305*4724848cSchristos.align	4
306*4724848cSchristos.Lbase2_64_neon:
307*4724848cSchristos	ldp	x7,x8,[x0,#32]	// load key value
308*4724848cSchristos
309*4724848cSchristos	ldp	x4,x5,[x0]		// load hash value base 2^64
310*4724848cSchristos	ldr	x6,[x0,#16]
311*4724848cSchristos
312*4724848cSchristos	tst	x2,#31
313*4724848cSchristos	b.eq	.Linit_neon
314*4724848cSchristos
315*4724848cSchristos	ldp	x12,x13,[x1],#16	// load input
316*4724848cSchristos	sub	x2,x2,#16
317*4724848cSchristos	add	x9,x8,x8,lsr#2	// s1 = r1 + (r1 >> 2)
318*4724848cSchristos#ifdef	__ARMEB__
319*4724848cSchristos	rev	x12,x12
320*4724848cSchristos	rev	x13,x13
321*4724848cSchristos#endif
322*4724848cSchristos	adds	x4,x4,x12		// accumulate input
323*4724848cSchristos	adcs	x5,x5,x13
324*4724848cSchristos	adc	x6,x6,x3
325*4724848cSchristos
326*4724848cSchristos	bl	poly1305_mult
327*4724848cSchristos
328*4724848cSchristos.Linit_neon:
329*4724848cSchristos	and	x10,x4,#0x03ffffff	// base 2^64 -> base 2^26
330*4724848cSchristos	ubfx	x11,x4,#26,#26
331*4724848cSchristos	extr	x12,x5,x4,#52
332*4724848cSchristos	and	x12,x12,#0x03ffffff
333*4724848cSchristos	ubfx	x13,x5,#14,#26
334*4724848cSchristos	extr	x14,x6,x5,#40
335*4724848cSchristos
336*4724848cSchristos	stp	d8,d9,[sp,#16]		// meet ABI requirements
337*4724848cSchristos	stp	d10,d11,[sp,#32]
338*4724848cSchristos	stp	d12,d13,[sp,#48]
339*4724848cSchristos	stp	d14,d15,[sp,#64]
340*4724848cSchristos
341*4724848cSchristos	fmov	d24,x10
342*4724848cSchristos	fmov	d25,x11
343*4724848cSchristos	fmov	d26,x12
344*4724848cSchristos	fmov	d27,x13
345*4724848cSchristos	fmov	d28,x14
346*4724848cSchristos
347*4724848cSchristos	////////////////////////////////// initialize r^n table
348*4724848cSchristos	mov	x4,x7			// r^1
349*4724848cSchristos	add	x9,x8,x8,lsr#2	// s1 = r1 + (r1 >> 2)
350*4724848cSchristos	mov	x5,x8
351*4724848cSchristos	mov	x6,xzr
352*4724848cSchristos	add	x0,x0,#48+12
353*4724848cSchristos	bl	poly1305_splat
354*4724848cSchristos
355*4724848cSchristos	bl	poly1305_mult		// r^2
356*4724848cSchristos	sub	x0,x0,#4
357*4724848cSchristos	bl	poly1305_splat
358*4724848cSchristos
359*4724848cSchristos	bl	poly1305_mult		// r^3
360*4724848cSchristos	sub	x0,x0,#4
361*4724848cSchristos	bl	poly1305_splat
362*4724848cSchristos
363*4724848cSchristos	bl	poly1305_mult		// r^4
364*4724848cSchristos	sub	x0,x0,#4
365*4724848cSchristos	bl	poly1305_splat
366*4724848cSchristos	ldr	x30,[sp,#8]
367*4724848cSchristos
368*4724848cSchristos	add	x16,x1,#32
369*4724848cSchristos	adr	x17,.Lzeros
370*4724848cSchristos	subs	x2,x2,#64
371*4724848cSchristos	csel	x16,x17,x16,lo
372*4724848cSchristos
373*4724848cSchristos	mov	x4,#1
374*4724848cSchristos	str	x4,[x0,#-24]		// set is_base2_26
375*4724848cSchristos	sub	x0,x0,#48		// restore original x0
376*4724848cSchristos	b	.Ldo_neon
377*4724848cSchristos
378*4724848cSchristos.align	4
379*4724848cSchristos.Leven_neon:
380*4724848cSchristos	add	x16,x1,#32
381*4724848cSchristos	adr	x17,.Lzeros
382*4724848cSchristos	subs	x2,x2,#64
383*4724848cSchristos	csel	x16,x17,x16,lo
384*4724848cSchristos
385*4724848cSchristos	stp	d8,d9,[sp,#16]		// meet ABI requirements
386*4724848cSchristos	stp	d10,d11,[sp,#32]
387*4724848cSchristos	stp	d12,d13,[sp,#48]
388*4724848cSchristos	stp	d14,d15,[sp,#64]
389*4724848cSchristos
390*4724848cSchristos	fmov	d24,x10
391*4724848cSchristos	fmov	d25,x11
392*4724848cSchristos	fmov	d26,x12
393*4724848cSchristos	fmov	d27,x13
394*4724848cSchristos	fmov	d28,x14
395*4724848cSchristos
396*4724848cSchristos.Ldo_neon:
397*4724848cSchristos	ldp	x8,x12,[x16],#16	// inp[2:3] (or zero)
398*4724848cSchristos	ldp	x9,x13,[x16],#48
399*4724848cSchristos
400*4724848cSchristos	lsl	x3,x3,#24
401*4724848cSchristos	add	x15,x0,#48
402*4724848cSchristos
403*4724848cSchristos#ifdef	__ARMEB__
404*4724848cSchristos	rev	x8,x8
405*4724848cSchristos	rev	x12,x12
406*4724848cSchristos	rev	x9,x9
407*4724848cSchristos	rev	x13,x13
408*4724848cSchristos#endif
409*4724848cSchristos	and	x4,x8,#0x03ffffff	// base 2^64 -> base 2^26
410*4724848cSchristos	and	x5,x9,#0x03ffffff
411*4724848cSchristos	ubfx	x6,x8,#26,#26
412*4724848cSchristos	ubfx	x7,x9,#26,#26
413*4724848cSchristos	add	x4,x4,x5,lsl#32		// bfi	x4,x5,#32,#32
414*4724848cSchristos	extr	x8,x12,x8,#52
415*4724848cSchristos	extr	x9,x13,x9,#52
416*4724848cSchristos	add	x6,x6,x7,lsl#32		// bfi	x6,x7,#32,#32
417*4724848cSchristos	fmov	d14,x4
418*4724848cSchristos	and	x8,x8,#0x03ffffff
419*4724848cSchristos	and	x9,x9,#0x03ffffff
420*4724848cSchristos	ubfx	x10,x12,#14,#26
421*4724848cSchristos	ubfx	x11,x13,#14,#26
422*4724848cSchristos	add	x12,x3,x12,lsr#40
423*4724848cSchristos	add	x13,x3,x13,lsr#40
424*4724848cSchristos	add	x8,x8,x9,lsl#32		// bfi	x8,x9,#32,#32
425*4724848cSchristos	fmov	d15,x6
426*4724848cSchristos	add	x10,x10,x11,lsl#32	// bfi	x10,x11,#32,#32
427*4724848cSchristos	add	x12,x12,x13,lsl#32	// bfi	x12,x13,#32,#32
428*4724848cSchristos	fmov	d16,x8
429*4724848cSchristos	fmov	d17,x10
430*4724848cSchristos	fmov	d18,x12
431*4724848cSchristos
432*4724848cSchristos	ldp	x8,x12,[x1],#16	// inp[0:1]
433*4724848cSchristos	ldp	x9,x13,[x1],#48
434*4724848cSchristos
435*4724848cSchristos	ld1	{v0.4s,v1.4s,v2.4s,v3.4s},[x15],#64
436*4724848cSchristos	ld1	{v4.4s,v5.4s,v6.4s,v7.4s},[x15],#64
437*4724848cSchristos	ld1	{v8.4s},[x15]
438*4724848cSchristos
439*4724848cSchristos#ifdef	__ARMEB__
440*4724848cSchristos	rev	x8,x8
441*4724848cSchristos	rev	x12,x12
442*4724848cSchristos	rev	x9,x9
443*4724848cSchristos	rev	x13,x13
444*4724848cSchristos#endif
445*4724848cSchristos	and	x4,x8,#0x03ffffff	// base 2^64 -> base 2^26
446*4724848cSchristos	and	x5,x9,#0x03ffffff
447*4724848cSchristos	ubfx	x6,x8,#26,#26
448*4724848cSchristos	ubfx	x7,x9,#26,#26
449*4724848cSchristos	add	x4,x4,x5,lsl#32		// bfi	x4,x5,#32,#32
450*4724848cSchristos	extr	x8,x12,x8,#52
451*4724848cSchristos	extr	x9,x13,x9,#52
452*4724848cSchristos	add	x6,x6,x7,lsl#32		// bfi	x6,x7,#32,#32
453*4724848cSchristos	fmov	d9,x4
454*4724848cSchristos	and	x8,x8,#0x03ffffff
455*4724848cSchristos	and	x9,x9,#0x03ffffff
456*4724848cSchristos	ubfx	x10,x12,#14,#26
457*4724848cSchristos	ubfx	x11,x13,#14,#26
458*4724848cSchristos	add	x12,x3,x12,lsr#40
459*4724848cSchristos	add	x13,x3,x13,lsr#40
460*4724848cSchristos	add	x8,x8,x9,lsl#32		// bfi	x8,x9,#32,#32
461*4724848cSchristos	fmov	d10,x6
462*4724848cSchristos	add	x10,x10,x11,lsl#32	// bfi	x10,x11,#32,#32
463*4724848cSchristos	add	x12,x12,x13,lsl#32	// bfi	x12,x13,#32,#32
464*4724848cSchristos	movi	v31.2d,#-1
465*4724848cSchristos	fmov	d11,x8
466*4724848cSchristos	fmov	d12,x10
467*4724848cSchristos	fmov	d13,x12
468*4724848cSchristos	ushr	v31.2d,v31.2d,#38
469*4724848cSchristos
470*4724848cSchristos	b.ls	.Lskip_loop
471*4724848cSchristos
472*4724848cSchristos.align	4
473*4724848cSchristos.Loop_neon:
474*4724848cSchristos	////////////////////////////////////////////////////////////////
475*4724848cSchristos	// ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2
476*4724848cSchristos	// ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r
477*4724848cSchristos	//   ___________________/
478*4724848cSchristos	// ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2
479*4724848cSchristos	// ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r
480*4724848cSchristos	//   ___________________/ ____________________/
481*4724848cSchristos	//
482*4724848cSchristos	// Note that we start with inp[2:3]*r^2. This is because it
483*4724848cSchristos	// doesn't depend on reduction in previous iteration.
484*4724848cSchristos	////////////////////////////////////////////////////////////////
485*4724848cSchristos	// d4 = h0*r4 + h1*r3   + h2*r2   + h3*r1   + h4*r0
486*4724848cSchristos	// d3 = h0*r3 + h1*r2   + h2*r1   + h3*r0   + h4*5*r4
487*4724848cSchristos	// d2 = h0*r2 + h1*r1   + h2*r0   + h3*5*r4 + h4*5*r3
488*4724848cSchristos	// d1 = h0*r1 + h1*r0   + h2*5*r4 + h3*5*r3 + h4*5*r2
489*4724848cSchristos	// d0 = h0*r0 + h1*5*r4 + h2*5*r3 + h3*5*r2 + h4*5*r1
490*4724848cSchristos
491*4724848cSchristos	subs	x2,x2,#64
492*4724848cSchristos	umull	v23.2d,v14.2s,v7.s[2]
493*4724848cSchristos	csel	x16,x17,x16,lo
494*4724848cSchristos	umull	v22.2d,v14.2s,v5.s[2]
495*4724848cSchristos	umull	v21.2d,v14.2s,v3.s[2]
496*4724848cSchristos	ldp	x8,x12,[x16],#16	// inp[2:3] (or zero)
497*4724848cSchristos	umull	v20.2d,v14.2s,v1.s[2]
498*4724848cSchristos	ldp	x9,x13,[x16],#48
499*4724848cSchristos	umull	v19.2d,v14.2s,v0.s[2]
500*4724848cSchristos#ifdef	__ARMEB__
501*4724848cSchristos	rev	x8,x8
502*4724848cSchristos	rev	x12,x12
503*4724848cSchristos	rev	x9,x9
504*4724848cSchristos	rev	x13,x13
505*4724848cSchristos#endif
506*4724848cSchristos
507*4724848cSchristos	umlal	v23.2d,v15.2s,v5.s[2]
508*4724848cSchristos	and	x4,x8,#0x03ffffff	// base 2^64 -> base 2^26
509*4724848cSchristos	umlal	v22.2d,v15.2s,v3.s[2]
510*4724848cSchristos	and	x5,x9,#0x03ffffff
511*4724848cSchristos	umlal	v21.2d,v15.2s,v1.s[2]
512*4724848cSchristos	ubfx	x6,x8,#26,#26
513*4724848cSchristos	umlal	v20.2d,v15.2s,v0.s[2]
514*4724848cSchristos	ubfx	x7,x9,#26,#26
515*4724848cSchristos	umlal	v19.2d,v15.2s,v8.s[2]
516*4724848cSchristos	add	x4,x4,x5,lsl#32		// bfi	x4,x5,#32,#32
517*4724848cSchristos
518*4724848cSchristos	umlal	v23.2d,v16.2s,v3.s[2]
519*4724848cSchristos	extr	x8,x12,x8,#52
520*4724848cSchristos	umlal	v22.2d,v16.2s,v1.s[2]
521*4724848cSchristos	extr	x9,x13,x9,#52
522*4724848cSchristos	umlal	v21.2d,v16.2s,v0.s[2]
523*4724848cSchristos	add	x6,x6,x7,lsl#32		// bfi	x6,x7,#32,#32
524*4724848cSchristos	umlal	v20.2d,v16.2s,v8.s[2]
525*4724848cSchristos	fmov	d14,x4
526*4724848cSchristos	umlal	v19.2d,v16.2s,v6.s[2]
527*4724848cSchristos	and	x8,x8,#0x03ffffff
528*4724848cSchristos
529*4724848cSchristos	umlal	v23.2d,v17.2s,v1.s[2]
530*4724848cSchristos	and	x9,x9,#0x03ffffff
531*4724848cSchristos	umlal	v22.2d,v17.2s,v0.s[2]
532*4724848cSchristos	ubfx	x10,x12,#14,#26
533*4724848cSchristos	umlal	v21.2d,v17.2s,v8.s[2]
534*4724848cSchristos	ubfx	x11,x13,#14,#26
535*4724848cSchristos	umlal	v20.2d,v17.2s,v6.s[2]
536*4724848cSchristos	add	x8,x8,x9,lsl#32		// bfi	x8,x9,#32,#32
537*4724848cSchristos	umlal	v19.2d,v17.2s,v4.s[2]
538*4724848cSchristos	fmov	d15,x6
539*4724848cSchristos
540*4724848cSchristos	add	v11.2s,v11.2s,v26.2s
541*4724848cSchristos	add	x12,x3,x12,lsr#40
542*4724848cSchristos	umlal	v23.2d,v18.2s,v0.s[2]
543*4724848cSchristos	add	x13,x3,x13,lsr#40
544*4724848cSchristos	umlal	v22.2d,v18.2s,v8.s[2]
545*4724848cSchristos	add	x10,x10,x11,lsl#32	// bfi	x10,x11,#32,#32
546*4724848cSchristos	umlal	v21.2d,v18.2s,v6.s[2]
547*4724848cSchristos	add	x12,x12,x13,lsl#32	// bfi	x12,x13,#32,#32
548*4724848cSchristos	umlal	v20.2d,v18.2s,v4.s[2]
549*4724848cSchristos	fmov	d16,x8
550*4724848cSchristos	umlal	v19.2d,v18.2s,v2.s[2]
551*4724848cSchristos	fmov	d17,x10
552*4724848cSchristos
553*4724848cSchristos	////////////////////////////////////////////////////////////////
554*4724848cSchristos	// (hash+inp[0:1])*r^4 and accumulate
555*4724848cSchristos
556*4724848cSchristos	add	v9.2s,v9.2s,v24.2s
557*4724848cSchristos	fmov	d18,x12
558*4724848cSchristos	umlal	v22.2d,v11.2s,v1.s[0]
559*4724848cSchristos	ldp	x8,x12,[x1],#16	// inp[0:1]
560*4724848cSchristos	umlal	v19.2d,v11.2s,v6.s[0]
561*4724848cSchristos	ldp	x9,x13,[x1],#48
562*4724848cSchristos	umlal	v23.2d,v11.2s,v3.s[0]
563*4724848cSchristos	umlal	v20.2d,v11.2s,v8.s[0]
564*4724848cSchristos	umlal	v21.2d,v11.2s,v0.s[0]
565*4724848cSchristos#ifdef	__ARMEB__
566*4724848cSchristos	rev	x8,x8
567*4724848cSchristos	rev	x12,x12
568*4724848cSchristos	rev	x9,x9
569*4724848cSchristos	rev	x13,x13
570*4724848cSchristos#endif
571*4724848cSchristos
572*4724848cSchristos	add	v10.2s,v10.2s,v25.2s
573*4724848cSchristos	umlal	v22.2d,v9.2s,v5.s[0]
574*4724848cSchristos	umlal	v23.2d,v9.2s,v7.s[0]
575*4724848cSchristos	and	x4,x8,#0x03ffffff	// base 2^64 -> base 2^26
576*4724848cSchristos	umlal	v21.2d,v9.2s,v3.s[0]
577*4724848cSchristos	and	x5,x9,#0x03ffffff
578*4724848cSchristos	umlal	v19.2d,v9.2s,v0.s[0]
579*4724848cSchristos	ubfx	x6,x8,#26,#26
580*4724848cSchristos	umlal	v20.2d,v9.2s,v1.s[0]
581*4724848cSchristos	ubfx	x7,x9,#26,#26
582*4724848cSchristos
583*4724848cSchristos	add	v12.2s,v12.2s,v27.2s
584*4724848cSchristos	add	x4,x4,x5,lsl#32		// bfi	x4,x5,#32,#32
585*4724848cSchristos	umlal	v22.2d,v10.2s,v3.s[0]
586*4724848cSchristos	extr	x8,x12,x8,#52
587*4724848cSchristos	umlal	v23.2d,v10.2s,v5.s[0]
588*4724848cSchristos	extr	x9,x13,x9,#52
589*4724848cSchristos	umlal	v19.2d,v10.2s,v8.s[0]
590*4724848cSchristos	add	x6,x6,x7,lsl#32		// bfi	x6,x7,#32,#32
591*4724848cSchristos	umlal	v21.2d,v10.2s,v1.s[0]
592*4724848cSchristos	fmov	d9,x4
593*4724848cSchristos	umlal	v20.2d,v10.2s,v0.s[0]
594*4724848cSchristos	and	x8,x8,#0x03ffffff
595*4724848cSchristos
596*4724848cSchristos	add	v13.2s,v13.2s,v28.2s
597*4724848cSchristos	and	x9,x9,#0x03ffffff
598*4724848cSchristos	umlal	v22.2d,v12.2s,v0.s[0]
599*4724848cSchristos	ubfx	x10,x12,#14,#26
600*4724848cSchristos	umlal	v19.2d,v12.2s,v4.s[0]
601*4724848cSchristos	ubfx	x11,x13,#14,#26
602*4724848cSchristos	umlal	v23.2d,v12.2s,v1.s[0]
603*4724848cSchristos	add	x8,x8,x9,lsl#32		// bfi	x8,x9,#32,#32
604*4724848cSchristos	umlal	v20.2d,v12.2s,v6.s[0]
605*4724848cSchristos	fmov	d10,x6
606*4724848cSchristos	umlal	v21.2d,v12.2s,v8.s[0]
607*4724848cSchristos	add	x12,x3,x12,lsr#40
608*4724848cSchristos
609*4724848cSchristos	umlal	v22.2d,v13.2s,v8.s[0]
610*4724848cSchristos	add	x13,x3,x13,lsr#40
611*4724848cSchristos	umlal	v19.2d,v13.2s,v2.s[0]
612*4724848cSchristos	add	x10,x10,x11,lsl#32	// bfi	x10,x11,#32,#32
613*4724848cSchristos	umlal	v23.2d,v13.2s,v0.s[0]
614*4724848cSchristos	add	x12,x12,x13,lsl#32	// bfi	x12,x13,#32,#32
615*4724848cSchristos	umlal	v20.2d,v13.2s,v4.s[0]
616*4724848cSchristos	fmov	d11,x8
617*4724848cSchristos	umlal	v21.2d,v13.2s,v6.s[0]
618*4724848cSchristos	fmov	d12,x10
619*4724848cSchristos	fmov	d13,x12
620*4724848cSchristos
621*4724848cSchristos	/////////////////////////////////////////////////////////////////
622*4724848cSchristos	// lazy reduction as discussed in "NEON crypto" by D.J. Bernstein
623*4724848cSchristos	// and P. Schwabe
624*4724848cSchristos	//
625*4724848cSchristos	// [see discussion in poly1305-armv4 module]
626*4724848cSchristos
627*4724848cSchristos	ushr	v29.2d,v22.2d,#26
628*4724848cSchristos	xtn	v27.2s,v22.2d
629*4724848cSchristos	ushr	v30.2d,v19.2d,#26
630*4724848cSchristos	and	v19.16b,v19.16b,v31.16b
631*4724848cSchristos	add	v23.2d,v23.2d,v29.2d	// h3 -> h4
632*4724848cSchristos	bic	v27.2s,#0xfc,lsl#24	// &=0x03ffffff
633*4724848cSchristos	add	v20.2d,v20.2d,v30.2d	// h0 -> h1
634*4724848cSchristos
635*4724848cSchristos	ushr	v29.2d,v23.2d,#26
636*4724848cSchristos	xtn	v28.2s,v23.2d
637*4724848cSchristos	ushr	v30.2d,v20.2d,#26
638*4724848cSchristos	xtn	v25.2s,v20.2d
639*4724848cSchristos	bic	v28.2s,#0xfc,lsl#24
640*4724848cSchristos	add	v21.2d,v21.2d,v30.2d	// h1 -> h2
641*4724848cSchristos
642*4724848cSchristos	add	v19.2d,v19.2d,v29.2d
643*4724848cSchristos	shl	v29.2d,v29.2d,#2
644*4724848cSchristos	shrn	v30.2s,v21.2d,#26
645*4724848cSchristos	xtn	v26.2s,v21.2d
646*4724848cSchristos	add	v19.2d,v19.2d,v29.2d	// h4 -> h0
647*4724848cSchristos	bic	v25.2s,#0xfc,lsl#24
648*4724848cSchristos	add	v27.2s,v27.2s,v30.2s		// h2 -> h3
649*4724848cSchristos	bic	v26.2s,#0xfc,lsl#24
650*4724848cSchristos
651*4724848cSchristos	shrn	v29.2s,v19.2d,#26
652*4724848cSchristos	xtn	v24.2s,v19.2d
653*4724848cSchristos	ushr	v30.2s,v27.2s,#26
654*4724848cSchristos	bic	v27.2s,#0xfc,lsl#24
655*4724848cSchristos	bic	v24.2s,#0xfc,lsl#24
656*4724848cSchristos	add	v25.2s,v25.2s,v29.2s		// h0 -> h1
657*4724848cSchristos	add	v28.2s,v28.2s,v30.2s		// h3 -> h4
658*4724848cSchristos
659*4724848cSchristos	b.hi	.Loop_neon
660*4724848cSchristos
661*4724848cSchristos.Lskip_loop:
662*4724848cSchristos	dup	v16.2d,v16.d[0]
663*4724848cSchristos	add	v11.2s,v11.2s,v26.2s
664*4724848cSchristos
665*4724848cSchristos	////////////////////////////////////////////////////////////////
666*4724848cSchristos	// multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1
667*4724848cSchristos
668*4724848cSchristos	adds	x2,x2,#32
669*4724848cSchristos	b.ne	.Long_tail
670*4724848cSchristos
671*4724848cSchristos	dup	v16.2d,v11.d[0]
672*4724848cSchristos	add	v14.2s,v9.2s,v24.2s
673*4724848cSchristos	add	v17.2s,v12.2s,v27.2s
674*4724848cSchristos	add	v15.2s,v10.2s,v25.2s
675*4724848cSchristos	add	v18.2s,v13.2s,v28.2s
676*4724848cSchristos
677*4724848cSchristos.Long_tail:
678*4724848cSchristos	dup	v14.2d,v14.d[0]
679*4724848cSchristos	umull2	v19.2d,v16.4s,v6.4s
680*4724848cSchristos	umull2	v22.2d,v16.4s,v1.4s
681*4724848cSchristos	umull2	v23.2d,v16.4s,v3.4s
682*4724848cSchristos	umull2	v21.2d,v16.4s,v0.4s
683*4724848cSchristos	umull2	v20.2d,v16.4s,v8.4s
684*4724848cSchristos
685*4724848cSchristos	dup	v15.2d,v15.d[0]
686*4724848cSchristos	umlal2	v19.2d,v14.4s,v0.4s
687*4724848cSchristos	umlal2	v21.2d,v14.4s,v3.4s
688*4724848cSchristos	umlal2	v22.2d,v14.4s,v5.4s
689*4724848cSchristos	umlal2	v23.2d,v14.4s,v7.4s
690*4724848cSchristos	umlal2	v20.2d,v14.4s,v1.4s
691*4724848cSchristos
692*4724848cSchristos	dup	v17.2d,v17.d[0]
693*4724848cSchristos	umlal2	v19.2d,v15.4s,v8.4s
694*4724848cSchristos	umlal2	v22.2d,v15.4s,v3.4s
695*4724848cSchristos	umlal2	v21.2d,v15.4s,v1.4s
696*4724848cSchristos	umlal2	v23.2d,v15.4s,v5.4s
697*4724848cSchristos	umlal2	v20.2d,v15.4s,v0.4s
698*4724848cSchristos
699*4724848cSchristos	dup	v18.2d,v18.d[0]
700*4724848cSchristos	umlal2	v22.2d,v17.4s,v0.4s
701*4724848cSchristos	umlal2	v23.2d,v17.4s,v1.4s
702*4724848cSchristos	umlal2	v19.2d,v17.4s,v4.4s
703*4724848cSchristos	umlal2	v20.2d,v17.4s,v6.4s
704*4724848cSchristos	umlal2	v21.2d,v17.4s,v8.4s
705*4724848cSchristos
706*4724848cSchristos	umlal2	v22.2d,v18.4s,v8.4s
707*4724848cSchristos	umlal2	v19.2d,v18.4s,v2.4s
708*4724848cSchristos	umlal2	v23.2d,v18.4s,v0.4s
709*4724848cSchristos	umlal2	v20.2d,v18.4s,v4.4s
710*4724848cSchristos	umlal2	v21.2d,v18.4s,v6.4s
711*4724848cSchristos
712*4724848cSchristos	b.eq	.Lshort_tail
713*4724848cSchristos
714*4724848cSchristos	////////////////////////////////////////////////////////////////
715*4724848cSchristos	// (hash+inp[0:1])*r^4:r^3 and accumulate
716*4724848cSchristos
717*4724848cSchristos	add	v9.2s,v9.2s,v24.2s
718*4724848cSchristos	umlal	v22.2d,v11.2s,v1.2s
719*4724848cSchristos	umlal	v19.2d,v11.2s,v6.2s
720*4724848cSchristos	umlal	v23.2d,v11.2s,v3.2s
721*4724848cSchristos	umlal	v20.2d,v11.2s,v8.2s
722*4724848cSchristos	umlal	v21.2d,v11.2s,v0.2s
723*4724848cSchristos
724*4724848cSchristos	add	v10.2s,v10.2s,v25.2s
725*4724848cSchristos	umlal	v22.2d,v9.2s,v5.2s
726*4724848cSchristos	umlal	v19.2d,v9.2s,v0.2s
727*4724848cSchristos	umlal	v23.2d,v9.2s,v7.2s
728*4724848cSchristos	umlal	v20.2d,v9.2s,v1.2s
729*4724848cSchristos	umlal	v21.2d,v9.2s,v3.2s
730*4724848cSchristos
731*4724848cSchristos	add	v12.2s,v12.2s,v27.2s
732*4724848cSchristos	umlal	v22.2d,v10.2s,v3.2s
733*4724848cSchristos	umlal	v19.2d,v10.2s,v8.2s
734*4724848cSchristos	umlal	v23.2d,v10.2s,v5.2s
735*4724848cSchristos	umlal	v20.2d,v10.2s,v0.2s
736*4724848cSchristos	umlal	v21.2d,v10.2s,v1.2s
737*4724848cSchristos
738*4724848cSchristos	add	v13.2s,v13.2s,v28.2s
739*4724848cSchristos	umlal	v22.2d,v12.2s,v0.2s
740*4724848cSchristos	umlal	v19.2d,v12.2s,v4.2s
741*4724848cSchristos	umlal	v23.2d,v12.2s,v1.2s
742*4724848cSchristos	umlal	v20.2d,v12.2s,v6.2s
743*4724848cSchristos	umlal	v21.2d,v12.2s,v8.2s
744*4724848cSchristos
745*4724848cSchristos	umlal	v22.2d,v13.2s,v8.2s
746*4724848cSchristos	umlal	v19.2d,v13.2s,v2.2s
747*4724848cSchristos	umlal	v23.2d,v13.2s,v0.2s
748*4724848cSchristos	umlal	v20.2d,v13.2s,v4.2s
749*4724848cSchristos	umlal	v21.2d,v13.2s,v6.2s
750*4724848cSchristos
751*4724848cSchristos.Lshort_tail:
752*4724848cSchristos	////////////////////////////////////////////////////////////////
753*4724848cSchristos	// horizontal add
754*4724848cSchristos
755*4724848cSchristos	addp	v22.2d,v22.2d,v22.2d
756*4724848cSchristos	ldp	d8,d9,[sp,#16]		// meet ABI requirements
757*4724848cSchristos	addp	v19.2d,v19.2d,v19.2d
758*4724848cSchristos	ldp	d10,d11,[sp,#32]
759*4724848cSchristos	addp	v23.2d,v23.2d,v23.2d
760*4724848cSchristos	ldp	d12,d13,[sp,#48]
761*4724848cSchristos	addp	v20.2d,v20.2d,v20.2d
762*4724848cSchristos	ldp	d14,d15,[sp,#64]
763*4724848cSchristos	addp	v21.2d,v21.2d,v21.2d
764*4724848cSchristos
765*4724848cSchristos	////////////////////////////////////////////////////////////////
766*4724848cSchristos	// lazy reduction, but without narrowing
767*4724848cSchristos
768*4724848cSchristos	ushr	v29.2d,v22.2d,#26
769*4724848cSchristos	and	v22.16b,v22.16b,v31.16b
770*4724848cSchristos	ushr	v30.2d,v19.2d,#26
771*4724848cSchristos	and	v19.16b,v19.16b,v31.16b
772*4724848cSchristos
773*4724848cSchristos	add	v23.2d,v23.2d,v29.2d	// h3 -> h4
774*4724848cSchristos	add	v20.2d,v20.2d,v30.2d	// h0 -> h1
775*4724848cSchristos
776*4724848cSchristos	ushr	v29.2d,v23.2d,#26
777*4724848cSchristos	and	v23.16b,v23.16b,v31.16b
778*4724848cSchristos	ushr	v30.2d,v20.2d,#26
779*4724848cSchristos	and	v20.16b,v20.16b,v31.16b
780*4724848cSchristos	add	v21.2d,v21.2d,v30.2d	// h1 -> h2
781*4724848cSchristos
782*4724848cSchristos	add	v19.2d,v19.2d,v29.2d
783*4724848cSchristos	shl	v29.2d,v29.2d,#2
784*4724848cSchristos	ushr	v30.2d,v21.2d,#26
785*4724848cSchristos	and	v21.16b,v21.16b,v31.16b
786*4724848cSchristos	add	v19.2d,v19.2d,v29.2d	// h4 -> h0
787*4724848cSchristos	add	v22.2d,v22.2d,v30.2d	// h2 -> h3
788*4724848cSchristos
789*4724848cSchristos	ushr	v29.2d,v19.2d,#26
790*4724848cSchristos	and	v19.16b,v19.16b,v31.16b
791*4724848cSchristos	ushr	v30.2d,v22.2d,#26
792*4724848cSchristos	and	v22.16b,v22.16b,v31.16b
793*4724848cSchristos	add	v20.2d,v20.2d,v29.2d	// h0 -> h1
794*4724848cSchristos	add	v23.2d,v23.2d,v30.2d	// h3 -> h4
795*4724848cSchristos
796*4724848cSchristos	////////////////////////////////////////////////////////////////
797*4724848cSchristos	// write the result, can be partially reduced
798*4724848cSchristos
799*4724848cSchristos	st4	{v19.s,v20.s,v21.s,v22.s}[0],[x0],#16
800*4724848cSchristos	st1	{v23.s}[0],[x0]
801*4724848cSchristos
802*4724848cSchristos.Lno_data_neon:
803*4724848cSchristos	ldr	x29,[sp],#80
804*4724848cSchristos.inst	0xd50323bf		// autiasp
805*4724848cSchristos	ret
806*4724848cSchristos.size	poly1305_blocks_neon,.-poly1305_blocks_neon
807*4724848cSchristos
808*4724848cSchristos.type	poly1305_emit_neon,%function
809*4724848cSchristos.align	5
810*4724848cSchristospoly1305_emit_neon:
811*4724848cSchristos	ldr	x17,[x0,#24]
812*4724848cSchristos	cbz	x17,poly1305_emit
813*4724848cSchristos
814*4724848cSchristos	ldp	w10,w11,[x0]		// load hash value base 2^26
815*4724848cSchristos	ldp	w12,w13,[x0,#8]
816*4724848cSchristos	ldr	w14,[x0,#16]
817*4724848cSchristos
818*4724848cSchristos	add	x4,x10,x11,lsl#26	// base 2^26 -> base 2^64
819*4724848cSchristos	lsr	x5,x12,#12
820*4724848cSchristos	adds	x4,x4,x12,lsl#52
821*4724848cSchristos	add	x5,x5,x13,lsl#14
822*4724848cSchristos	adc	x5,x5,xzr
823*4724848cSchristos	lsr	x6,x14,#24
824*4724848cSchristos	adds	x5,x5,x14,lsl#40
825*4724848cSchristos	adc	x6,x6,xzr		// can be partially reduced...
826*4724848cSchristos
827*4724848cSchristos	ldp	x10,x11,[x2]	// load nonce
828*4724848cSchristos
829*4724848cSchristos	and	x12,x6,#-4		// ... so reduce
830*4724848cSchristos	add	x12,x12,x6,lsr#2
831*4724848cSchristos	and	x6,x6,#3
832*4724848cSchristos	adds	x4,x4,x12
833*4724848cSchristos	adcs	x5,x5,xzr
834*4724848cSchristos	adc	x6,x6,xzr
835*4724848cSchristos
836*4724848cSchristos	adds	x12,x4,#5		// compare to modulus
837*4724848cSchristos	adcs	x13,x5,xzr
838*4724848cSchristos	adc	x14,x6,xzr
839*4724848cSchristos
840*4724848cSchristos	tst	x14,#-4			// see if it's carried/borrowed
841*4724848cSchristos
842*4724848cSchristos	csel	x4,x4,x12,eq
843*4724848cSchristos	csel	x5,x5,x13,eq
844*4724848cSchristos
845*4724848cSchristos#ifdef	__ARMEB__
846*4724848cSchristos	ror	x10,x10,#32		// flip nonce words
847*4724848cSchristos	ror	x11,x11,#32
848*4724848cSchristos#endif
849*4724848cSchristos	adds	x4,x4,x10		// accumulate nonce
850*4724848cSchristos	adc	x5,x5,x11
851*4724848cSchristos#ifdef	__ARMEB__
852*4724848cSchristos	rev	x4,x4			// flip output bytes
853*4724848cSchristos	rev	x5,x5
854*4724848cSchristos#endif
855*4724848cSchristos	stp	x4,x5,[x1]		// write result
856*4724848cSchristos
857*4724848cSchristos	ret
858*4724848cSchristos.size	poly1305_emit_neon,.-poly1305_emit_neon
859*4724848cSchristos
860*4724848cSchristos.align	5
861*4724848cSchristos.Lzeros:
862*4724848cSchristos.long	0,0,0,0,0,0,0,0
863*4724848cSchristos.LOPENSSL_armcap_P:
864*4724848cSchristos#ifdef	__ILP32__
865*4724848cSchristos.long	OPENSSL_armcap_P-.
866*4724848cSchristos#else
867*4724848cSchristos.quad	OPENSSL_armcap_P-.
868*4724848cSchristos#endif
869*4724848cSchristos.byte	80,111,108,121,49,51,48,53,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
870*4724848cSchristos.align	2
871*4724848cSchristos.align	2
872