7 #if __ARM_MAX_ARCH__>=7
10 .word OPENSSL_armcap_P-bn_mul_mont
14 .type bn_mul_mont,%function
18 ldr ip,[sp,#4] @ load num
19 stmdb sp!,{r0,r2} @ sp points at argument block
20 #if __ARM_MAX_ARCH__>=7
24 ldr r2,.LOPENSSL_armcap
26 tst r0,#1 @ NEON available?
40 stmdb sp!,{r4-r12,lr} @ save 10 registers
42 mov r0,r0,lsl#2 @ rescale r0 for byte count
43 sub sp,sp,r0 @ alloca(4*num)
44 sub sp,sp,#4 @ +extra dword
45 sub r0,r0,#4 @ "num=num-1"
46 add r4,r2,r0 @ &bp[num-1]
48 add r0,sp,r0 @ r0 to point at &tp[num-1]
49 ldr r8,[r0,#14*4] @ &n0
51 ldr r5,[r1],#4 @ ap[0],ap++
52 ldr r6,[r3],#4 @ np[0],np++
54 str r4,[r0,#15*4] @ save &bp[num]
56 umull r10,r11,r5,r2 @ ap[0]*bp[0]
57 str r8,[r0,#14*4] @ save n0 value
58 mul r8,r10,r8 @ "tp[0]"*n0
60 umlal r10,r12,r6,r8 @ np[0]*n0+"t[0]"
64 ldr r5,[r1],#4 @ ap[j],ap++
66 ldr r6,[r3],#4 @ np[j],np++
68 umlal r10,r11,r5,r2 @ ap[j]*bp[0]
70 umlal r12,r14,r6,r8 @ np[j]*n0
72 str r12,[r4],#4 @ tp[j-1]=,tp++
78 ldr r4,[r0,#13*4] @ restore bp
80 ldr r8,[r0,#14*4] @ restore n0
82 str r12,[r0] @ tp[num-1]=
83 str r14,[r0,#4] @ tp[num]=
86 sub r7,r0,sp @ "original" r0-1 value
87 sub r1,r1,r7 @ "rewind" ap to &ap[1]
88 ldr r2,[r4,#4]! @ *(++bp)
89 sub r3,r3,r7 @ "rewind" np to &np[1]
90 ldr r5,[r1,#-4] @ ap[0]
92 ldr r6,[r3,#-4] @ np[0]
93 ldr r7,[sp,#4] @ tp[1]
96 umlal r10,r11,r5,r2 @ ap[0]*bp[i]+tp[0]
97 str r4,[r0,#13*4] @ save bp
100 umlal r10,r12,r6,r8 @ np[0]*n0+"tp[0]"
104 ldr r5,[r1],#4 @ ap[j],ap++
105 adds r10,r11,r7 @ +=tp[j]
106 ldr r6,[r3],#4 @ np[j],np++
108 umlal r10,r11,r5,r2 @ ap[j]*bp[i]
110 umlal r12,r14,r6,r8 @ np[j]*n0
112 ldr r7,[r4,#8] @ tp[j+1]
114 str r12,[r4],#4 @ tp[j-1]=,tp++
121 ldr r4,[r0,#13*4] @ restore bp
123 ldr r8,[r0,#14*4] @ restore n0
125 ldr r7,[r0,#15*4] @ restore &bp[num]
127 str r12,[r0] @ tp[num-1]=
128 str r14,[r0,#4] @ tp[num]=
133 ldr r2,[r0,#12*4] @ pull rp
134 add r0,r0,#4 @ r0 to point at &tp[num]
135 sub r5,r0,sp @ "original" num value
136 mov r4,sp @ "rewind" r4
137 mov r1,r4 @ "borrow" r1
138 sub r3,r3,r5 @ "rewind" r3 to &np[0]
140 subs r7,r7,r7 @ "clear" carry flag
141 .Lsub: ldr r7,[r4],#4
143 sbcs r7,r7,r6 @ tp[j]-np[j]
144 str r7,[r2],#4 @ rp[j]=
145 teq r4,r0 @ preserve carry
147 sbcs r14,r14,#0 @ upmost carry
148 mov r4,sp @ "rewind" r4
149 sub r2,r2,r5 @ "rewind" r2
153 orr r1,r1,r3 @ ap=borrow?tp:rp
155 .Lcopy: ldr r7,[r1],#4 @ copy or in-place refresh
156 str sp,[r4],#4 @ zap tp
161 add sp,r0,#4 @ skip over tp[num+1]
162 ldmia sp!,{r4-r12,lr} @ restore registers
163 add sp,sp,#2*4 @ skip over {r0,r2}
167 RET @ .word 0xe12fff1e
170 moveq pc,lr @ be binary compatible with V4, yet
171 .word 0xe12fff1e @ interoperable with Thumb ISA:-)
173 .size bn_mul_mont,.-bn_mul_mont
174 #if __ARM_MAX_ARCH__>=7
178 .type bn_mul8x_mont_neon,%function
183 vstmdb sp!,{d8-d15} @ ABI specification says so
184 ldmia ip,{r4-r5} @ load rest of parameter block
187 vld1.32 {d28[0]}, [r2,:32]!
189 vld1.32 {d0-d3}, [r1]! @ can't specify :32 :-(
191 vld1.32 {d30[0]}, [r4,:32]
197 vmull.u32 q6,d28,d0[0]
198 vmull.u32 q7,d28,d0[1]
199 vmull.u32 q8,d28,d1[0]
201 vmull.u32 q9,d28,d1[1]
207 vmull.u32 q10,d28,d2[0]
208 vld1.32 {d4-d7}, [r3]!
209 vmull.u32 q11,d28,d2[1]
210 vmull.u32 q12,d28,d3[0]
212 vmull.u32 q13,d28,d3[1]
216 @ special case for num=8, everything is in register bank...
218 vmlal.u32 q6,d29,d4[0]
220 vmlal.u32 q7,d29,d4[1]
221 vmlal.u32 q8,d29,d5[0]
222 vmlal.u32 q9,d29,d5[1]
224 vmlal.u32 q10,d29,d6[0]
226 vmlal.u32 q11,d29,d6[1]
228 vmlal.u32 q12,d29,d7[0]
230 vmlal.u32 q13,d29,d7[1]
245 vld1.32 {d28[0]}, [r2,:32]!
250 vmlal.u32 q6,d28,d0[0]
251 vmlal.u32 q7,d28,d0[1]
252 vmlal.u32 q8,d28,d1[0]
254 vmlal.u32 q9,d28,d1[1]
261 vmlal.u32 q10,d28,d2[0]
262 vmlal.u32 q11,d28,d2[1]
263 vmlal.u32 q12,d28,d3[0]
265 vmlal.u32 q13,d28,d3[1]
267 vmlal.u32 q6,d29,d4[0]
268 vmlal.u32 q7,d29,d4[1]
269 vmlal.u32 q8,d29,d5[0]
270 vmlal.u32 q9,d29,d5[1]
272 vmlal.u32 q10,d29,d6[0]
274 vmlal.u32 q11,d29,d6[1]
276 vmlal.u32 q12,d29,d7[0]
278 vmlal.u32 q13,d29,d7[1]
304 vmlal.u32 q6,d29,d4[0]
305 vld1.32 {d0-d3}, [r1]!
306 vmlal.u32 q7,d29,d4[1]
308 vmlal.u32 q8,d29,d5[0]
309 vmlal.u32 q9,d29,d5[1]
311 vmlal.u32 q10,d29,d6[0]
312 vld1.32 {d4-d5}, [r3]!
313 vmlal.u32 q11,d29,d6[1]
314 vst1.64 {q6-q7}, [r7,:256]!
315 vmlal.u32 q12,d29,d7[0]
316 vmlal.u32 q13,d29,d7[1]
317 vst1.64 {q8-q9}, [r7,:256]!
319 vmull.u32 q6,d28,d0[0]
320 vld1.32 {d6-d7}, [r3]!
321 vmull.u32 q7,d28,d0[1]
322 vst1.64 {q10-q11}, [r7,:256]!
323 vmull.u32 q8,d28,d1[0]
324 vmull.u32 q9,d28,d1[1]
325 vst1.64 {q12-q13}, [r7,:256]!
327 vmull.u32 q10,d28,d2[0]
328 vmull.u32 q11,d28,d2[1]
329 vmull.u32 q12,d28,d3[0]
330 vmull.u32 q13,d28,d3[1]
334 vmlal.u32 q6,d29,d4[0]
336 vmlal.u32 q7,d29,d4[1]
337 sub r1,r1,r5,lsl#2 @ rewind r1
338 vmlal.u32 q8,d29,d5[0]
339 vld1.64 {q5}, [sp,:128]
340 vmlal.u32 q9,d29,d5[1]
343 vmlal.u32 q10,d29,d6[0]
344 vst1.64 {q6-q7}, [r7,:256]!
345 vmlal.u32 q11,d29,d6[1]
347 vld1.64 {q6}, [r6, :128]!
348 vmlal.u32 q12,d29,d7[0]
349 vst1.64 {q8-q9}, [r7,:256]!
350 vmlal.u32 q13,d29,d7[1]
352 vst1.64 {q10-q11}, [r7,:256]!
355 vst1.64 {q12-q13}, [r7,:256]!
356 vld1.64 {q7-q8}, [r6, :256]!
357 vst1.64 {q4}, [r7,:128]
364 vld1.32 {d28[0]}, [r2,:32]!
365 sub r3,r3,r5,lsl#2 @ rewind r3
366 vld1.32 {d0-d3}, [r1]!
373 vmlal.u32 q6,d28,d0[0]
374 vld1.64 {q9-q10},[r6,:256]!
375 vmlal.u32 q7,d28,d0[1]
376 vmlal.u32 q8,d28,d1[0]
377 vld1.64 {q11-q12},[r6,:256]!
378 vmlal.u32 q9,d28,d1[1]
383 vld1.64 {q13},[r6,:128]!
386 vmlal.u32 q10,d28,d2[0]
387 vld1.32 {d4-d7}, [r3]!
388 vmlal.u32 q11,d28,d2[1]
389 vmlal.u32 q12,d28,d3[0]
391 vmlal.u32 q13,d28,d3[1]
394 vmlal.u32 q6,d29,d4[0]
395 vld1.32 {d0-d3}, [r1]!
396 vmlal.u32 q7,d29,d4[1]
398 vmlal.u32 q8,d29,d5[0]
399 vmlal.u32 q9,d29,d5[1]
400 vst1.64 {q6-q7}, [r7,:256]!
402 vmlal.u32 q10,d29,d6[0]
403 vld1.64 {q6}, [r6, :128]!
404 vmlal.u32 q11,d29,d6[1]
405 vst1.64 {q8-q9}, [r7,:256]!
406 vmlal.u32 q12,d29,d7[0]
407 vld1.64 {q7-q8}, [r6, :256]!
408 vmlal.u32 q13,d29,d7[1]
409 vst1.64 {q10-q11}, [r7,:256]!
411 vmlal.u32 q6,d28,d0[0]
412 vld1.64 {q9-q10}, [r6, :256]!
413 vmlal.u32 q7,d28,d0[1]
414 vst1.64 {q12-q13}, [r7,:256]!
415 vmlal.u32 q8,d28,d1[0]
416 vld1.64 {q11-q12}, [r6, :256]!
417 vmlal.u32 q9,d28,d1[1]
418 vld1.32 {d4-d7}, [r3]!
420 vmlal.u32 q10,d28,d2[0]
421 vld1.64 {q13}, [r6, :128]!
422 vmlal.u32 q11,d28,d2[1]
423 vmlal.u32 q12,d28,d3[0]
424 vmlal.u32 q13,d28,d3[1]
428 vmlal.u32 q6,d29,d4[0]
430 vmlal.u32 q7,d29,d4[1]
431 sub r1,r1,r5,lsl#2 @ rewind r1
432 vmlal.u32 q8,d29,d5[0]
433 vld1.64 {q5}, [sp,:128]
434 vmlal.u32 q9,d29,d5[1]
437 vmlal.u32 q10,d29,d6[0]
438 vst1.64 {q6-q7}, [r7,:256]!
439 vmlal.u32 q11,d29,d6[1]
440 vld1.64 {q6}, [r6, :128]!
442 vst1.64 {q8-q9}, [r7,:256]!
443 vmlal.u32 q12,d29,d7[0]
444 vld1.64 {q7-q8}, [r6, :256]!
445 vmlal.u32 q13,d29,d7[1]
447 vst1.64 {q10-q11}, [r7,:256]!
449 vst1.64 {q12-q13}, [r7,:256]!
459 vld1.64 {q9-q10}, [r6, :256]!
462 vld1.64 {q11-q12}, [r6, :256]!
464 vld1.64 {q13}, [r6, :128]!
469 vst1.32 {d12[0]}, [r7, :32]!
476 vst1.32 {d14[0]}, [r7, :32]!
483 vst1.32 {d16[0]}, [r7, :32]!
490 vst1.32 {d18[0]}, [r7, :32]!
497 vst1.32 {d20[0]}, [r7, :32]!
504 vst1.32 {d22[0]}, [r7, :32]!
507 vld1.64 {q6}, [r6, :128]!
512 vst1.32 {d24[0]}, [r7, :32]!
515 vld1.64 {q7-q8}, [r6, :256]!
519 vst1.32 {d26[0]}, [r7, :32]!
523 vst1.32 {d10[0]}, [r7, :32] @ top-most bit
524 sub r3,r3,r5,lsl#2 @ rewind r3
525 subs r1,sp,#0 @ clear carry flag
535 teq r1,r2 @ preserves carry
539 ldr r10, [r1] @ load top-most bit
541 sub r11,r2,sp @ this is num*4
544 sub r0,r0,r11 @ rewind r0
545 mov r3,r2 @ second 3/4th of frame
546 sbcs r10,r10,#0 @ result is carry flag
552 vst1.64 {q0-q1}, [r3,:256]! @ wipe
555 vst1.64 {q0-q1}, [r3,:256]! @ wipe
562 vst1.64 {q0-q1}, [r1,:256]! @ wipe
565 vst1.64 {q0-q1}, [r3,:256]! @ wipe
567 teq r1,r2 @ preserves carry
569 bne .LNEON_copy_n_zap
574 RET @ .word 0xe12fff1e
575 .size bn_mul8x_mont_neon,.-bn_mul8x_mont_neon
577 .asciz "Montgomery multiplication for ARMv4/NEON, CRYPTOGAMS by <appro@openssl.org>"
579 #if __ARM_MAX_ARCH__>=7
580 .comm OPENSSL_armcap_P,4,4