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