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