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.globl poly1305_emit 12.globl poly1305_blocks 13.globl poly1305_init 14.type poly1305_init,%function 15.align 5 16poly1305_init: 17.Lpoly1305_init: 18 stmdb sp!,{r4-r11} 19 20 eor r3,r3,r3 21 cmp r1,#0 22 str r3,[r0,#0] @ zero hash value 23 str r3,[r0,#4] 24 str r3,[r0,#8] 25 str r3,[r0,#12] 26 str r3,[r0,#16] 27 str r3,[r0,#36] @ is_base2_26 28 add r0,r0,#20 29 30#ifdef __thumb2__ 31 it eq 32#endif 33 moveq r0,#0 34 beq .Lno_key 35 36#if __ARM_MAX_ARCH__>=7 37 adr r11,.Lpoly1305_init 38 ldr r12,.LOPENSSL_armcap 39#endif 40 ldrb r4,[r1,#0] 41 mov r10,#0x0fffffff 42 ldrb r5,[r1,#1] 43 and r3,r10,#-4 @ 0x0ffffffc 44 ldrb r6,[r1,#2] 45 ldrb r7,[r1,#3] 46 orr r4,r4,r5,lsl#8 47 ldrb r5,[r1,#4] 48 orr r4,r4,r6,lsl#16 49 ldrb r6,[r1,#5] 50 orr r4,r4,r7,lsl#24 51 ldrb r7,[r1,#6] 52 and r4,r4,r10 53 54#if __ARM_MAX_ARCH__>=7 55 ldr r12,[r11,r12] @ OPENSSL_armcap_P 56# ifdef __APPLE__ 57 ldr r12,[r12] 58# endif 59#endif 60 ldrb r8,[r1,#7] 61 orr r5,r5,r6,lsl#8 62 ldrb r6,[r1,#8] 63 orr r5,r5,r7,lsl#16 64 ldrb r7,[r1,#9] 65 orr r5,r5,r8,lsl#24 66 ldrb r8,[r1,#10] 67 and r5,r5,r3 68 69#if __ARM_MAX_ARCH__>=7 70 tst r12,#ARMV7_NEON @ check for NEON 71# ifdef __APPLE__ 72 adr r9,poly1305_blocks_neon 73 adr r11,poly1305_blocks 74# ifdef __thumb2__ 75 it ne 76# endif 77 movne r11,r9 78 adr r12,poly1305_emit 79 adr r10,poly1305_emit_neon 80# ifdef __thumb2__ 81 it ne 82# endif 83 movne r12,r10 84# else 85# ifdef __thumb2__ 86 itete eq 87# endif 88 addeq r12,r11,#(.Lpoly1305_emit-.Lpoly1305_init) 89 addne r12,r11,#(.Lpoly1305_emit_neon-.Lpoly1305_init) 90 addeq r11,r11,#(.Lpoly1305_blocks-.Lpoly1305_init) 91 addne r11,r11,#(.Lpoly1305_blocks_neon-.Lpoly1305_init) 92# endif 93# ifdef __thumb2__ 94 orr r12,r12,#1 @ thumb-ify address 95 orr r11,r11,#1 96# endif 97#endif 98 ldrb r9,[r1,#11] 99 orr r6,r6,r7,lsl#8 100 ldrb r7,[r1,#12] 101 orr r6,r6,r8,lsl#16 102 ldrb r8,[r1,#13] 103 orr r6,r6,r9,lsl#24 104 ldrb r9,[r1,#14] 105 and r6,r6,r3 106 107 ldrb r10,[r1,#15] 108 orr r7,r7,r8,lsl#8 109 str r4,[r0,#0] 110 orr r7,r7,r9,lsl#16 111 str r5,[r0,#4] 112 orr r7,r7,r10,lsl#24 113 str r6,[r0,#8] 114 and r7,r7,r3 115 str r7,[r0,#12] 116#if __ARM_MAX_ARCH__>=7 117 stmia r2,{r11,r12} @ fill functions table 118 mov r0,#1 119#else 120 mov r0,#0 121#endif 122.Lno_key: 123 ldmia sp!,{r4-r11} 124#if __ARM_ARCH__>=5 125 bx lr @ bx lr 126#else 127 tst lr,#1 128 moveq pc,lr @ be binary compatible with V4, yet 129 .word 0xe12fff1e @ interoperable with Thumb ISA:-) 130#endif 131.size poly1305_init,.-poly1305_init 132.type poly1305_blocks,%function 133.align 5 134poly1305_blocks: 135.Lpoly1305_blocks: 136 stmdb sp!,{r3-r11,lr} 137 138 ands r2,r2,#-16 139 beq .Lno_data 140 141 cmp r3,#0 142 add r2,r2,r1 @ end pointer 143 sub sp,sp,#32 144 145 ldmia r0,{r4-r12} @ load context 146 147 str r0,[sp,#12] @ offload stuff 148 mov lr,r1 149 str r2,[sp,#16] 150 str r10,[sp,#20] 151 str r11,[sp,#24] 152 str r12,[sp,#28] 153 b .Loop 154 155.Loop: 156#if __ARM_ARCH__<7 157 ldrb r0,[lr],#16 @ load input 158# ifdef __thumb2__ 159 it hi 160# endif 161 addhi r8,r8,#1 @ 1<<128 162 ldrb r1,[lr,#-15] 163 ldrb r2,[lr,#-14] 164 ldrb r3,[lr,#-13] 165 orr r1,r0,r1,lsl#8 166 ldrb r0,[lr,#-12] 167 orr r2,r1,r2,lsl#16 168 ldrb r1,[lr,#-11] 169 orr r3,r2,r3,lsl#24 170 ldrb r2,[lr,#-10] 171 adds r4,r4,r3 @ accumulate input 172 173 ldrb r3,[lr,#-9] 174 orr r1,r0,r1,lsl#8 175 ldrb r0,[lr,#-8] 176 orr r2,r1,r2,lsl#16 177 ldrb r1,[lr,#-7] 178 orr r3,r2,r3,lsl#24 179 ldrb r2,[lr,#-6] 180 adcs r5,r5,r3 181 182 ldrb r3,[lr,#-5] 183 orr r1,r0,r1,lsl#8 184 ldrb r0,[lr,#-4] 185 orr r2,r1,r2,lsl#16 186 ldrb r1,[lr,#-3] 187 orr r3,r2,r3,lsl#24 188 ldrb r2,[lr,#-2] 189 adcs r6,r6,r3 190 191 ldrb r3,[lr,#-1] 192 orr r1,r0,r1,lsl#8 193 str lr,[sp,#8] @ offload input pointer 194 orr r2,r1,r2,lsl#16 195 add r10,r10,r10,lsr#2 196 orr r3,r2,r3,lsl#24 197#else 198 ldr r0,[lr],#16 @ load input 199# ifdef __thumb2__ 200 it hi 201# endif 202 addhi r8,r8,#1 @ padbit 203 ldr r1,[lr,#-12] 204 ldr r2,[lr,#-8] 205 ldr r3,[lr,#-4] 206# ifdef __ARMEB__ 207 rev r0,r0 208 rev r1,r1 209 rev r2,r2 210 rev r3,r3 211# endif 212 adds r4,r4,r0 @ accumulate input 213 str lr,[sp,#8] @ offload input pointer 214 adcs r5,r5,r1 215 add r10,r10,r10,lsr#2 216 adcs r6,r6,r2 217#endif 218 add r11,r11,r11,lsr#2 219 adcs r7,r7,r3 220 add r12,r12,r12,lsr#2 221 222 umull r2,r3,r5,r9 223 adc r8,r8,#0 224 umull r0,r1,r4,r9 225 umlal r2,r3,r8,r10 226 umlal r0,r1,r7,r10 227 ldr r10,[sp,#20] @ reload r10 228 umlal r2,r3,r6,r12 229 umlal r0,r1,r5,r12 230 umlal r2,r3,r7,r11 231 umlal r0,r1,r6,r11 232 umlal r2,r3,r4,r10 233 str r0,[sp,#0] @ future r4 234 mul r0,r11,r8 235 ldr r11,[sp,#24] @ reload r11 236 adds r2,r2,r1 @ d1+=d0>>32 237 eor r1,r1,r1 238 adc lr,r3,#0 @ future r6 239 str r2,[sp,#4] @ future r5 240 241 mul r2,r12,r8 242 eor r3,r3,r3 243 umlal r0,r1,r7,r12 244 ldr r12,[sp,#28] @ reload r12 245 umlal r2,r3,r7,r9 246 umlal r0,r1,r6,r9 247 umlal r2,r3,r6,r10 248 umlal r0,r1,r5,r10 249 umlal r2,r3,r5,r11 250 umlal r0,r1,r4,r11 251 umlal r2,r3,r4,r12 252 ldr r4,[sp,#0] 253 mul r8,r9,r8 254 ldr r5,[sp,#4] 255 256 adds r6,lr,r0 @ d2+=d1>>32 257 ldr lr,[sp,#8] @ reload input pointer 258 adc r1,r1,#0 259 adds r7,r2,r1 @ d3+=d2>>32 260 ldr r0,[sp,#16] @ reload end pointer 261 adc r3,r3,#0 262 add r8,r8,r3 @ h4+=d3>>32 263 264 and r1,r8,#-4 265 and r8,r8,#3 266 add r1,r1,r1,lsr#2 @ *=5 267 adds r4,r4,r1 268 adcs r5,r5,#0 269 adcs r6,r6,#0 270 adcs r7,r7,#0 271 adc r8,r8,#0 272 273 cmp r0,lr @ done yet? 274 bhi .Loop 275 276 ldr r0,[sp,#12] 277 add sp,sp,#32 278 stmia r0,{r4-r8} @ store the result 279 280.Lno_data: 281#if __ARM_ARCH__>=5 282 ldmia sp!,{r3-r11,pc} 283#else 284 ldmia sp!,{r3-r11,lr} 285 tst lr,#1 286 moveq pc,lr @ be binary compatible with V4, yet 287 .word 0xe12fff1e @ interoperable with Thumb ISA:-) 288#endif 289.size poly1305_blocks,.-poly1305_blocks 290.type poly1305_emit,%function 291.align 5 292poly1305_emit: 293.Lpoly1305_emit: 294 stmdb sp!,{r4-r11} 295.Lpoly1305_emit_enter: 296 297 ldmia r0,{r3-r7} 298 adds r8,r3,#5 @ compare to modulus 299 adcs r9,r4,#0 300 adcs r10,r5,#0 301 adcs r11,r6,#0 302 adc r7,r7,#0 303 tst r7,#4 @ did it carry/borrow? 304 305#ifdef __thumb2__ 306 it ne 307#endif 308 movne r3,r8 309 ldr r8,[r2,#0] 310#ifdef __thumb2__ 311 it ne 312#endif 313 movne r4,r9 314 ldr r9,[r2,#4] 315#ifdef __thumb2__ 316 it ne 317#endif 318 movne r5,r10 319 ldr r10,[r2,#8] 320#ifdef __thumb2__ 321 it ne 322#endif 323 movne r6,r11 324 ldr r11,[r2,#12] 325 326 adds r3,r3,r8 327 adcs r4,r4,r9 328 adcs r5,r5,r10 329 adc r6,r6,r11 330 331#if __ARM_ARCH__>=7 332# ifdef __ARMEB__ 333 rev r3,r3 334 rev r4,r4 335 rev r5,r5 336 rev r6,r6 337# endif 338 str r3,[r1,#0] 339 str r4,[r1,#4] 340 str r5,[r1,#8] 341 str r6,[r1,#12] 342#else 343 strb r3,[r1,#0] 344 mov r3,r3,lsr#8 345 strb r4,[r1,#4] 346 mov r4,r4,lsr#8 347 strb r5,[r1,#8] 348 mov r5,r5,lsr#8 349 strb r6,[r1,#12] 350 mov r6,r6,lsr#8 351 352 strb r3,[r1,#1] 353 mov r3,r3,lsr#8 354 strb r4,[r1,#5] 355 mov r4,r4,lsr#8 356 strb r5,[r1,#9] 357 mov r5,r5,lsr#8 358 strb r6,[r1,#13] 359 mov r6,r6,lsr#8 360 361 strb r3,[r1,#2] 362 mov r3,r3,lsr#8 363 strb r4,[r1,#6] 364 mov r4,r4,lsr#8 365 strb r5,[r1,#10] 366 mov r5,r5,lsr#8 367 strb r6,[r1,#14] 368 mov r6,r6,lsr#8 369 370 strb r3,[r1,#3] 371 strb r4,[r1,#7] 372 strb r5,[r1,#11] 373 strb r6,[r1,#15] 374#endif 375 ldmia sp!,{r4-r11} 376#if __ARM_ARCH__>=5 377 bx lr @ bx lr 378#else 379 tst lr,#1 380 moveq pc,lr @ be binary compatible with V4, yet 381 .word 0xe12fff1e @ interoperable with Thumb ISA:-) 382#endif 383.size poly1305_emit,.-poly1305_emit 384#if __ARM_MAX_ARCH__>=7 385.fpu neon 386 387.type poly1305_init_neon,%function 388.align 5 389poly1305_init_neon: 390 ldr r4,[r0,#20] @ load key base 2^32 391 ldr r5,[r0,#24] 392 ldr r6,[r0,#28] 393 ldr r7,[r0,#32] 394 395 and r2,r4,#0x03ffffff @ base 2^32 -> base 2^26 396 mov r3,r4,lsr#26 397 mov r4,r5,lsr#20 398 orr r3,r3,r5,lsl#6 399 mov r5,r6,lsr#14 400 orr r4,r4,r6,lsl#12 401 mov r6,r7,lsr#8 402 orr r5,r5,r7,lsl#18 403 and r3,r3,#0x03ffffff 404 and r4,r4,#0x03ffffff 405 and r5,r5,#0x03ffffff 406 407 vdup.32 d0,r2 @ r^1 in both lanes 408 add r2,r3,r3,lsl#2 @ *5 409 vdup.32 d1,r3 410 add r3,r4,r4,lsl#2 411 vdup.32 d2,r2 412 vdup.32 d3,r4 413 add r4,r5,r5,lsl#2 414 vdup.32 d4,r3 415 vdup.32 d5,r5 416 add r5,r6,r6,lsl#2 417 vdup.32 d6,r4 418 vdup.32 d7,r6 419 vdup.32 d8,r5 420 421 mov r5,#2 @ counter 422 423.Lsquare_neon: 424 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 425 @ d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 426 @ d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 427 @ d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 428 @ d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 429 @ d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 430 431 vmull.u32 q5,d0,d0[1] 432 vmull.u32 q6,d1,d0[1] 433 vmull.u32 q7,d3,d0[1] 434 vmull.u32 q8,d5,d0[1] 435 vmull.u32 q9,d7,d0[1] 436 437 vmlal.u32 q5,d7,d2[1] 438 vmlal.u32 q6,d0,d1[1] 439 vmlal.u32 q7,d1,d1[1] 440 vmlal.u32 q8,d3,d1[1] 441 vmlal.u32 q9,d5,d1[1] 442 443 vmlal.u32 q5,d5,d4[1] 444 vmlal.u32 q6,d7,d4[1] 445 vmlal.u32 q8,d1,d3[1] 446 vmlal.u32 q7,d0,d3[1] 447 vmlal.u32 q9,d3,d3[1] 448 449 vmlal.u32 q5,d3,d6[1] 450 vmlal.u32 q8,d0,d5[1] 451 vmlal.u32 q6,d5,d6[1] 452 vmlal.u32 q7,d7,d6[1] 453 vmlal.u32 q9,d1,d5[1] 454 455 vmlal.u32 q8,d7,d8[1] 456 vmlal.u32 q5,d1,d8[1] 457 vmlal.u32 q6,d3,d8[1] 458 vmlal.u32 q7,d5,d8[1] 459 vmlal.u32 q9,d0,d7[1] 460 461 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 462 @ lazy reduction as discussed in "NEON crypto" by D.J. Bernstein 463 @ and P. Schwabe 464 @ 465 @ H0>>+H1>>+H2>>+H3>>+H4 466 @ H3>>+H4>>*5+H0>>+H1 467 @ 468 @ Trivia. 469 @ 470 @ Result of multiplication of n-bit number by m-bit number is 471 @ n+m bits wide. However! Even though 2^n is a n+1-bit number, 472 @ m-bit number multiplied by 2^n is still n+m bits wide. 473 @ 474 @ Sum of two n-bit numbers is n+1 bits wide, sum of three - n+2, 475 @ and so is sum of four. Sum of 2^m n-m-bit numbers and n-bit 476 @ one is n+1 bits wide. 477 @ 478 @ >>+ denotes Hnext += Hn>>26, Hn &= 0x3ffffff. This means that 479 @ H0, H2, H3 are guaranteed to be 26 bits wide, while H1 and H4 480 @ can be 27. However! In cases when their width exceeds 26 bits 481 @ they are limited by 2^26+2^6. This in turn means that *sum* 482 @ of the products with these values can still be viewed as sum 483 @ of 52-bit numbers as long as the amount of addends is not a 484 @ power of 2. For example, 485 @ 486 @ H4 = H4*R0 + H3*R1 + H2*R2 + H1*R3 + H0 * R4, 487 @ 488 @ which can't be larger than 5 * (2^26 + 2^6) * (2^26 + 2^6), or 489 @ 5 * (2^52 + 2*2^32 + 2^12), which in turn is smaller than 490 @ 8 * (2^52) or 2^55. However, the value is then multiplied by 491 @ by 5, so we should be looking at 5 * 5 * (2^52 + 2^33 + 2^12), 492 @ which is less than 32 * (2^52) or 2^57. And when processing 493 @ data we are looking at triple as many addends... 494 @ 495 @ In key setup procedure pre-reduced H0 is limited by 5*4+1 and 496 @ 5*H4 - by 5*5 52-bit addends, or 57 bits. But when hashing the 497 @ input H0 is limited by (5*4+1)*3 addends, or 58 bits, while 498 @ 5*H4 by 5*5*3, or 59[!] bits. How is this relevant? vmlal.u32 499 @ instruction accepts 2x32-bit input and writes 2x64-bit result. 500 @ This means that result of reduction have to be compressed upon 501 @ loop wrap-around. This can be done in the process of reduction 502 @ to minimize amount of instructions [as well as amount of 503 @ 128-bit instructions, which benefits low-end processors], but 504 @ one has to watch for H2 (which is narrower than H0) and 5*H4 505 @ not being wider than 58 bits, so that result of right shift 506 @ by 26 bits fits in 32 bits. This is also useful on x86, 507 @ because it allows to use paddd in place for paddq, which 508 @ benefits Atom, where paddq is ridiculously slow. 509 510 vshr.u64 q15,q8,#26 511 vmovn.i64 d16,q8 512 vshr.u64 q4,q5,#26 513 vmovn.i64 d10,q5 514 vadd.i64 q9,q9,q15 @ h3 -> h4 515 vbic.i32 d16,#0xfc000000 @ &=0x03ffffff 516 vadd.i64 q6,q6,q4 @ h0 -> h1 517 vbic.i32 d10,#0xfc000000 518 519 vshrn.u64 d30,q9,#26 520 vmovn.i64 d18,q9 521 vshr.u64 q4,q6,#26 522 vmovn.i64 d12,q6 523 vadd.i64 q7,q7,q4 @ h1 -> h2 524 vbic.i32 d18,#0xfc000000 525 vbic.i32 d12,#0xfc000000 526 527 vadd.i32 d10,d10,d30 528 vshl.u32 d30,d30,#2 529 vshrn.u64 d8,q7,#26 530 vmovn.i64 d14,q7 531 vadd.i32 d10,d10,d30 @ h4 -> h0 532 vadd.i32 d16,d16,d8 @ h2 -> h3 533 vbic.i32 d14,#0xfc000000 534 535 vshr.u32 d30,d10,#26 536 vbic.i32 d10,#0xfc000000 537 vshr.u32 d8,d16,#26 538 vbic.i32 d16,#0xfc000000 539 vadd.i32 d12,d12,d30 @ h0 -> h1 540 vadd.i32 d18,d18,d8 @ h3 -> h4 541 542 subs r5,r5,#1 543 beq .Lsquare_break_neon 544 545 add r6,r0,#(48+0*9*4) 546 add r7,r0,#(48+1*9*4) 547 548 vtrn.32 d0,d10 @ r^2:r^1 549 vtrn.32 d3,d14 550 vtrn.32 d5,d16 551 vtrn.32 d1,d12 552 vtrn.32 d7,d18 553 554 vshl.u32 d4,d3,#2 @ *5 555 vshl.u32 d6,d5,#2 556 vshl.u32 d2,d1,#2 557 vshl.u32 d8,d7,#2 558 vadd.i32 d4,d4,d3 559 vadd.i32 d2,d2,d1 560 vadd.i32 d6,d6,d5 561 vadd.i32 d8,d8,d7 562 563 vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r6]! 564 vst4.32 {d0[1],d1[1],d2[1],d3[1]},[r7]! 565 vst4.32 {d4[0],d5[0],d6[0],d7[0]},[r6]! 566 vst4.32 {d4[1],d5[1],d6[1],d7[1]},[r7]! 567 vst1.32 {d8[0]},[r6,:32] 568 vst1.32 {d8[1]},[r7,:32] 569 570 b .Lsquare_neon 571 572.align 4 573.Lsquare_break_neon: 574 add r6,r0,#(48+2*4*9) 575 add r7,r0,#(48+3*4*9) 576 577 vmov d0,d10 @ r^4:r^3 578 vshl.u32 d2,d12,#2 @ *5 579 vmov d1,d12 580 vshl.u32 d4,d14,#2 581 vmov d3,d14 582 vshl.u32 d6,d16,#2 583 vmov d5,d16 584 vshl.u32 d8,d18,#2 585 vmov d7,d18 586 vadd.i32 d2,d2,d12 587 vadd.i32 d4,d4,d14 588 vadd.i32 d6,d6,d16 589 vadd.i32 d8,d8,d18 590 591 vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r6]! 592 vst4.32 {d0[1],d1[1],d2[1],d3[1]},[r7]! 593 vst4.32 {d4[0],d5[0],d6[0],d7[0]},[r6]! 594 vst4.32 {d4[1],d5[1],d6[1],d7[1]},[r7]! 595 vst1.32 {d8[0]},[r6] 596 vst1.32 {d8[1]},[r7] 597 598 bx lr @ bx lr 599.size poly1305_init_neon,.-poly1305_init_neon 600 601.type poly1305_blocks_neon,%function 602.align 5 603poly1305_blocks_neon: 604.Lpoly1305_blocks_neon: 605 ldr ip,[r0,#36] @ is_base2_26 606 ands r2,r2,#-16 607 beq .Lno_data_neon 608 609 cmp r2,#64 610 bhs .Lenter_neon 611 tst ip,ip @ is_base2_26? 612 beq .Lpoly1305_blocks 613 614.Lenter_neon: 615 stmdb sp!,{r4-r7} 616 vstmdb sp!,{d8-d15} @ ABI specification says so 617 618 tst ip,ip @ is_base2_26? 619 bne .Lbase2_26_neon 620 621 stmdb sp!,{r1-r3,lr} 622 bl poly1305_init_neon 623 624 ldr r4,[r0,#0] @ load hash value base 2^32 625 ldr r5,[r0,#4] 626 ldr r6,[r0,#8] 627 ldr r7,[r0,#12] 628 ldr ip,[r0,#16] 629 630 and r2,r4,#0x03ffffff @ base 2^32 -> base 2^26 631 mov r3,r4,lsr#26 632 veor d10,d10,d10 633 mov r4,r5,lsr#20 634 orr r3,r3,r5,lsl#6 635 veor d12,d12,d12 636 mov r5,r6,lsr#14 637 orr r4,r4,r6,lsl#12 638 veor d14,d14,d14 639 mov r6,r7,lsr#8 640 orr r5,r5,r7,lsl#18 641 veor d16,d16,d16 642 and r3,r3,#0x03ffffff 643 orr r6,r6,ip,lsl#24 644 veor d18,d18,d18 645 and r4,r4,#0x03ffffff 646 mov r1,#1 647 and r5,r5,#0x03ffffff 648 str r1,[r0,#36] @ is_base2_26 649 650 vmov.32 d10[0],r2 651 vmov.32 d12[0],r3 652 vmov.32 d14[0],r4 653 vmov.32 d16[0],r5 654 vmov.32 d18[0],r6 655 adr r5,.Lzeros 656 657 ldmia sp!,{r1-r3,lr} 658 b .Lbase2_32_neon 659 660.align 4 661.Lbase2_26_neon: 662 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 663 @ load hash value 664 665 veor d10,d10,d10 666 veor d12,d12,d12 667 veor d14,d14,d14 668 veor d16,d16,d16 669 veor d18,d18,d18 670 vld4.32 {d10[0],d12[0],d14[0],d16[0]},[r0]! 671 adr r5,.Lzeros 672 vld1.32 {d18[0]},[r0] 673 sub r0,r0,#16 @ rewind 674 675.Lbase2_32_neon: 676 add r4,r1,#32 677 mov r3,r3,lsl#24 678 tst r2,#31 679 beq .Leven 680 681 vld4.32 {d20[0],d22[0],d24[0],d26[0]},[r1]! 682 vmov.32 d28[0],r3 683 sub r2,r2,#16 684 add r4,r1,#32 685 686# ifdef __ARMEB__ 687 vrev32.8 q10,q10 688 vrev32.8 q13,q13 689 vrev32.8 q11,q11 690 vrev32.8 q12,q12 691# endif 692 vsri.u32 d28,d26,#8 @ base 2^32 -> base 2^26 693 vshl.u32 d26,d26,#18 694 695 vsri.u32 d26,d24,#14 696 vshl.u32 d24,d24,#12 697 vadd.i32 d29,d28,d18 @ add hash value and move to #hi 698 699 vbic.i32 d26,#0xfc000000 700 vsri.u32 d24,d22,#20 701 vshl.u32 d22,d22,#6 702 703 vbic.i32 d24,#0xfc000000 704 vsri.u32 d22,d20,#26 705 vadd.i32 d27,d26,d16 706 707 vbic.i32 d20,#0xfc000000 708 vbic.i32 d22,#0xfc000000 709 vadd.i32 d25,d24,d14 710 711 vadd.i32 d21,d20,d10 712 vadd.i32 d23,d22,d12 713 714 mov r7,r5 715 add r6,r0,#48 716 717 cmp r2,r2 718 b .Long_tail 719 720.align 4 721.Leven: 722 subs r2,r2,#64 723 it lo 724 movlo r4,r5 725 726 vmov.i32 q14,#1<<24 @ padbit, yes, always 727 vld4.32 {d20,d22,d24,d26},[r1] @ inp[0:1] 728 add r1,r1,#64 729 vld4.32 {d21,d23,d25,d27},[r4] @ inp[2:3] (or 0) 730 add r4,r4,#64 731 itt hi 732 addhi r7,r0,#(48+1*9*4) 733 addhi r6,r0,#(48+3*9*4) 734 735# ifdef __ARMEB__ 736 vrev32.8 q10,q10 737 vrev32.8 q13,q13 738 vrev32.8 q11,q11 739 vrev32.8 q12,q12 740# endif 741 vsri.u32 q14,q13,#8 @ base 2^32 -> base 2^26 742 vshl.u32 q13,q13,#18 743 744 vsri.u32 q13,q12,#14 745 vshl.u32 q12,q12,#12 746 747 vbic.i32 q13,#0xfc000000 748 vsri.u32 q12,q11,#20 749 vshl.u32 q11,q11,#6 750 751 vbic.i32 q12,#0xfc000000 752 vsri.u32 q11,q10,#26 753 754 vbic.i32 q10,#0xfc000000 755 vbic.i32 q11,#0xfc000000 756 757 bls .Lskip_loop 758 759 vld4.32 {d0[1],d1[1],d2[1],d3[1]},[r7]! @ load r^2 760 vld4.32 {d0[0],d1[0],d2[0],d3[0]},[r6]! @ load r^4 761 vld4.32 {d4[1],d5[1],d6[1],d7[1]},[r7]! 762 vld4.32 {d4[0],d5[0],d6[0],d7[0]},[r6]! 763 b .Loop_neon 764 765.align 5 766.Loop_neon: 767 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 768 @ ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2 769 @ ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r 770 @ ___________________/ 771 @ ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2 772 @ ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r 773 @ ___________________/ ____________________/ 774 @ 775 @ Note that we start with inp[2:3]*r^2. This is because it 776 @ doesn't depend on reduction in previous iteration. 777 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 778 @ d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4 779 @ d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4 780 @ d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4 781 @ d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4 782 @ d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4 783 784 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 785 @ inp[2:3]*r^2 786 787 vadd.i32 d24,d24,d14 @ accumulate inp[0:1] 788 vmull.u32 q7,d25,d0[1] 789 vadd.i32 d20,d20,d10 790 vmull.u32 q5,d21,d0[1] 791 vadd.i32 d26,d26,d16 792 vmull.u32 q8,d27,d0[1] 793 vmlal.u32 q7,d23,d1[1] 794 vadd.i32 d22,d22,d12 795 vmull.u32 q6,d23,d0[1] 796 797 vadd.i32 d28,d28,d18 798 vmull.u32 q9,d29,d0[1] 799 subs r2,r2,#64 800 vmlal.u32 q5,d29,d2[1] 801 it lo 802 movlo r4,r5 803 vmlal.u32 q8,d25,d1[1] 804 vld1.32 d8[1],[r7,:32] 805 vmlal.u32 q6,d21,d1[1] 806 vmlal.u32 q9,d27,d1[1] 807 808 vmlal.u32 q5,d27,d4[1] 809 vmlal.u32 q8,d23,d3[1] 810 vmlal.u32 q9,d25,d3[1] 811 vmlal.u32 q6,d29,d4[1] 812 vmlal.u32 q7,d21,d3[1] 813 814 vmlal.u32 q8,d21,d5[1] 815 vmlal.u32 q5,d25,d6[1] 816 vmlal.u32 q9,d23,d5[1] 817 vmlal.u32 q6,d27,d6[1] 818 vmlal.u32 q7,d29,d6[1] 819 820 vmlal.u32 q8,d29,d8[1] 821 vmlal.u32 q5,d23,d8[1] 822 vmlal.u32 q9,d21,d7[1] 823 vmlal.u32 q6,d25,d8[1] 824 vmlal.u32 q7,d27,d8[1] 825 826 vld4.32 {d21,d23,d25,d27},[r4] @ inp[2:3] (or 0) 827 add r4,r4,#64 828 829 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 830 @ (hash+inp[0:1])*r^4 and accumulate 831 832 vmlal.u32 q8,d26,d0[0] 833 vmlal.u32 q5,d20,d0[0] 834 vmlal.u32 q9,d28,d0[0] 835 vmlal.u32 q6,d22,d0[0] 836 vmlal.u32 q7,d24,d0[0] 837 vld1.32 d8[0],[r6,:32] 838 839 vmlal.u32 q8,d24,d1[0] 840 vmlal.u32 q5,d28,d2[0] 841 vmlal.u32 q9,d26,d1[0] 842 vmlal.u32 q6,d20,d1[0] 843 vmlal.u32 q7,d22,d1[0] 844 845 vmlal.u32 q8,d22,d3[0] 846 vmlal.u32 q5,d26,d4[0] 847 vmlal.u32 q9,d24,d3[0] 848 vmlal.u32 q6,d28,d4[0] 849 vmlal.u32 q7,d20,d3[0] 850 851 vmlal.u32 q8,d20,d5[0] 852 vmlal.u32 q5,d24,d6[0] 853 vmlal.u32 q9,d22,d5[0] 854 vmlal.u32 q6,d26,d6[0] 855 vmlal.u32 q8,d28,d8[0] 856 857 vmlal.u32 q7,d28,d6[0] 858 vmlal.u32 q5,d22,d8[0] 859 vmlal.u32 q9,d20,d7[0] 860 vmov.i32 q14,#1<<24 @ padbit, yes, always 861 vmlal.u32 q6,d24,d8[0] 862 vmlal.u32 q7,d26,d8[0] 863 864 vld4.32 {d20,d22,d24,d26},[r1] @ inp[0:1] 865 add r1,r1,#64 866# ifdef __ARMEB__ 867 vrev32.8 q10,q10 868 vrev32.8 q11,q11 869 vrev32.8 q12,q12 870 vrev32.8 q13,q13 871# endif 872 873 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 874 @ lazy reduction interleaved with base 2^32 -> base 2^26 of 875 @ inp[0:3] previously loaded to q10-q13 and smashed to q10-q14. 876 877 vshr.u64 q15,q8,#26 878 vmovn.i64 d16,q8 879 vshr.u64 q4,q5,#26 880 vmovn.i64 d10,q5 881 vadd.i64 q9,q9,q15 @ h3 -> h4 882 vbic.i32 d16,#0xfc000000 883 vsri.u32 q14,q13,#8 @ base 2^32 -> base 2^26 884 vadd.i64 q6,q6,q4 @ h0 -> h1 885 vshl.u32 q13,q13,#18 886 vbic.i32 d10,#0xfc000000 887 888 vshrn.u64 d30,q9,#26 889 vmovn.i64 d18,q9 890 vshr.u64 q4,q6,#26 891 vmovn.i64 d12,q6 892 vadd.i64 q7,q7,q4 @ h1 -> h2 893 vsri.u32 q13,q12,#14 894 vbic.i32 d18,#0xfc000000 895 vshl.u32 q12,q12,#12 896 vbic.i32 d12,#0xfc000000 897 898 vadd.i32 d10,d10,d30 899 vshl.u32 d30,d30,#2 900 vbic.i32 q13,#0xfc000000 901 vshrn.u64 d8,q7,#26 902 vmovn.i64 d14,q7 903 vaddl.u32 q5,d10,d30 @ h4 -> h0 [widen for a sec] 904 vsri.u32 q12,q11,#20 905 vadd.i32 d16,d16,d8 @ h2 -> h3 906 vshl.u32 q11,q11,#6 907 vbic.i32 d14,#0xfc000000 908 vbic.i32 q12,#0xfc000000 909 910 vshrn.u64 d30,q5,#26 @ re-narrow 911 vmovn.i64 d10,q5 912 vsri.u32 q11,q10,#26 913 vbic.i32 q10,#0xfc000000 914 vshr.u32 d8,d16,#26 915 vbic.i32 d16,#0xfc000000 916 vbic.i32 d10,#0xfc000000 917 vadd.i32 d12,d12,d30 @ h0 -> h1 918 vadd.i32 d18,d18,d8 @ h3 -> h4 919 vbic.i32 q11,#0xfc000000 920 921 bhi .Loop_neon 922 923.Lskip_loop: 924 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 925 @ multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1 926 927 add r7,r0,#(48+0*9*4) 928 add r6,r0,#(48+1*9*4) 929 adds r2,r2,#32 930 it ne 931 movne r2,#0 932 bne .Long_tail 933 934 vadd.i32 d25,d24,d14 @ add hash value and move to #hi 935 vadd.i32 d21,d20,d10 936 vadd.i32 d27,d26,d16 937 vadd.i32 d23,d22,d12 938 vadd.i32 d29,d28,d18 939 940.Long_tail: 941 vld4.32 {d0[1],d1[1],d2[1],d3[1]},[r7]! @ load r^1 942 vld4.32 {d0[0],d1[0],d2[0],d3[0]},[r6]! @ load r^2 943 944 vadd.i32 d24,d24,d14 @ can be redundant 945 vmull.u32 q7,d25,d0 946 vadd.i32 d20,d20,d10 947 vmull.u32 q5,d21,d0 948 vadd.i32 d26,d26,d16 949 vmull.u32 q8,d27,d0 950 vadd.i32 d22,d22,d12 951 vmull.u32 q6,d23,d0 952 vadd.i32 d28,d28,d18 953 vmull.u32 q9,d29,d0 954 955 vmlal.u32 q5,d29,d2 956 vld4.32 {d4[1],d5[1],d6[1],d7[1]},[r7]! 957 vmlal.u32 q8,d25,d1 958 vld4.32 {d4[0],d5[0],d6[0],d7[0]},[r6]! 959 vmlal.u32 q6,d21,d1 960 vmlal.u32 q9,d27,d1 961 vmlal.u32 q7,d23,d1 962 963 vmlal.u32 q8,d23,d3 964 vld1.32 d8[1],[r7,:32] 965 vmlal.u32 q5,d27,d4 966 vld1.32 d8[0],[r6,:32] 967 vmlal.u32 q9,d25,d3 968 vmlal.u32 q6,d29,d4 969 vmlal.u32 q7,d21,d3 970 971 vmlal.u32 q8,d21,d5 972 it ne 973 addne r7,r0,#(48+2*9*4) 974 vmlal.u32 q5,d25,d6 975 it ne 976 addne r6,r0,#(48+3*9*4) 977 vmlal.u32 q9,d23,d5 978 vmlal.u32 q6,d27,d6 979 vmlal.u32 q7,d29,d6 980 981 vmlal.u32 q8,d29,d8 982 vorn q0,q0,q0 @ all-ones, can be redundant 983 vmlal.u32 q5,d23,d8 984 vshr.u64 q0,q0,#38 985 vmlal.u32 q9,d21,d7 986 vmlal.u32 q6,d25,d8 987 vmlal.u32 q7,d27,d8 988 989 beq .Lshort_tail 990 991 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 992 @ (hash+inp[0:1])*r^4:r^3 and accumulate 993 994 vld4.32 {d0[1],d1[1],d2[1],d3[1]},[r7]! @ load r^3 995 vld4.32 {d0[0],d1[0],d2[0],d3[0]},[r6]! @ load r^4 996 997 vmlal.u32 q7,d24,d0 998 vmlal.u32 q5,d20,d0 999 vmlal.u32 q8,d26,d0 1000 vmlal.u32 q6,d22,d0 1001 vmlal.u32 q9,d28,d0 1002 1003 vmlal.u32 q5,d28,d2 1004 vld4.32 {d4[1],d5[1],d6[1],d7[1]},[r7]! 1005 vmlal.u32 q8,d24,d1 1006 vld4.32 {d4[0],d5[0],d6[0],d7[0]},[r6]! 1007 vmlal.u32 q6,d20,d1 1008 vmlal.u32 q9,d26,d1 1009 vmlal.u32 q7,d22,d1 1010 1011 vmlal.u32 q8,d22,d3 1012 vld1.32 d8[1],[r7,:32] 1013 vmlal.u32 q5,d26,d4 1014 vld1.32 d8[0],[r6,:32] 1015 vmlal.u32 q9,d24,d3 1016 vmlal.u32 q6,d28,d4 1017 vmlal.u32 q7,d20,d3 1018 1019 vmlal.u32 q8,d20,d5 1020 vmlal.u32 q5,d24,d6 1021 vmlal.u32 q9,d22,d5 1022 vmlal.u32 q6,d26,d6 1023 vmlal.u32 q7,d28,d6 1024 1025 vmlal.u32 q8,d28,d8 1026 vorn q0,q0,q0 @ all-ones 1027 vmlal.u32 q5,d22,d8 1028 vshr.u64 q0,q0,#38 1029 vmlal.u32 q9,d20,d7 1030 vmlal.u32 q6,d24,d8 1031 vmlal.u32 q7,d26,d8 1032 1033.Lshort_tail: 1034 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1035 @ horizontal addition 1036 1037 vadd.i64 d16,d16,d17 1038 vadd.i64 d10,d10,d11 1039 vadd.i64 d18,d18,d19 1040 vadd.i64 d12,d12,d13 1041 vadd.i64 d14,d14,d15 1042 1043 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1044 @ lazy reduction, but without narrowing 1045 1046 vshr.u64 q15,q8,#26 1047 vand.i64 q8,q8,q0 1048 vshr.u64 q4,q5,#26 1049 vand.i64 q5,q5,q0 1050 vadd.i64 q9,q9,q15 @ h3 -> h4 1051 vadd.i64 q6,q6,q4 @ h0 -> h1 1052 1053 vshr.u64 q15,q9,#26 1054 vand.i64 q9,q9,q0 1055 vshr.u64 q4,q6,#26 1056 vand.i64 q6,q6,q0 1057 vadd.i64 q7,q7,q4 @ h1 -> h2 1058 1059 vadd.i64 q5,q5,q15 1060 vshl.u64 q15,q15,#2 1061 vshr.u64 q4,q7,#26 1062 vand.i64 q7,q7,q0 1063 vadd.i64 q5,q5,q15 @ h4 -> h0 1064 vadd.i64 q8,q8,q4 @ h2 -> h3 1065 1066 vshr.u64 q15,q5,#26 1067 vand.i64 q5,q5,q0 1068 vshr.u64 q4,q8,#26 1069 vand.i64 q8,q8,q0 1070 vadd.i64 q6,q6,q15 @ h0 -> h1 1071 vadd.i64 q9,q9,q4 @ h3 -> h4 1072 1073 cmp r2,#0 1074 bne .Leven 1075 1076 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1077 @ store hash value 1078 1079 vst4.32 {d10[0],d12[0],d14[0],d16[0]},[r0]! 1080 vst1.32 {d18[0]},[r0] 1081 1082 vldmia sp!,{d8-d15} @ epilogue 1083 ldmia sp!,{r4-r7} 1084.Lno_data_neon: 1085 bx lr @ bx lr 1086.size poly1305_blocks_neon,.-poly1305_blocks_neon 1087 1088.type poly1305_emit_neon,%function 1089.align 5 1090poly1305_emit_neon: 1091.Lpoly1305_emit_neon: 1092 ldr ip,[r0,#36] @ is_base2_26 1093 1094 stmdb sp!,{r4-r11} 1095 1096 tst ip,ip 1097 beq .Lpoly1305_emit_enter 1098 1099 ldmia r0,{r3-r7} 1100 eor r8,r8,r8 1101 1102 adds r3,r3,r4,lsl#26 @ base 2^26 -> base 2^32 1103 mov r4,r4,lsr#6 1104 adcs r4,r4,r5,lsl#20 1105 mov r5,r5,lsr#12 1106 adcs r5,r5,r6,lsl#14 1107 mov r6,r6,lsr#18 1108 adcs r6,r6,r7,lsl#8 1109 adc r7,r8,r7,lsr#24 @ can be partially reduced ... 1110 1111 and r8,r7,#-4 @ ... so reduce 1112 and r7,r6,#3 1113 add r8,r8,r8,lsr#2 @ *= 5 1114 adds r3,r3,r8 1115 adcs r4,r4,#0 1116 adcs r5,r5,#0 1117 adcs r6,r6,#0 1118 adc r7,r7,#0 1119 1120 adds r8,r3,#5 @ compare to modulus 1121 adcs r9,r4,#0 1122 adcs r10,r5,#0 1123 adcs r11,r6,#0 1124 adc r7,r7,#0 1125 tst r7,#4 @ did it carry/borrow? 1126 1127 it ne 1128 movne r3,r8 1129 ldr r8,[r2,#0] 1130 it ne 1131 movne r4,r9 1132 ldr r9,[r2,#4] 1133 it ne 1134 movne r5,r10 1135 ldr r10,[r2,#8] 1136 it ne 1137 movne r6,r11 1138 ldr r11,[r2,#12] 1139 1140 adds r3,r3,r8 @ accumulate nonce 1141 adcs r4,r4,r9 1142 adcs r5,r5,r10 1143 adc r6,r6,r11 1144 1145# ifdef __ARMEB__ 1146 rev r3,r3 1147 rev r4,r4 1148 rev r5,r5 1149 rev r6,r6 1150# endif 1151 str r3,[r1,#0] @ store the result 1152 str r4,[r1,#4] 1153 str r5,[r1,#8] 1154 str r6,[r1,#12] 1155 1156 ldmia sp!,{r4-r11} 1157 bx lr @ bx lr 1158.size poly1305_emit_neon,.-poly1305_emit_neon 1159 1160.align 5 1161.Lzeros: 1162.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1163.LOPENSSL_armcap: 1164.word OPENSSL_armcap_P-.Lpoly1305_init 1165#endif 1166.asciz "Poly1305 for ARMv4/NEON, CRYPTOGAMS by <appro@openssl.org>" 1167.align 2 1168#if __ARM_MAX_ARCH__>=7 1169.comm OPENSSL_armcap_P,4,4 1170#endif 1171