3 # ====================================================================
4 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
5 # project. The module is, however, dual licensed under OpenSSL and
6 # CRYPTOGAMS licenses depending on where you obtain it. For further
7 # details see http://www.openssl.org/~appro/cryptogams/.
8 # ====================================================================
10 # This module implements Poly1305 hash for PowerPC.
14 # Numbers are cycles per processed byte with poly1305_blocks alone,
15 # and improvement coefficients relative to gcc-generated code.
19 # Freescale e300 14.8/+80% -
21 # PPC970 7.20/+114% 3.51/+205%
22 # POWER6 3.96/+250% 2.02/+170%
23 # POWER7 3.67/+260% 1.87/+100%
26 # Do we need floating-point implementation for PPC? Results presented
27 # in poly1305_ieee754.c are tricky to compare to, because they are for
28 # compiler-generated code. On the other hand it's known that floating-
29 # point performance can be dominated by FPU latency, which means that
30 # there is limit even for ideally optimized (and even vectorized) code.
31 # And this limit is estimated to be higher than above -m64 results. Or
32 # in other words floating-point implementation can be meaningful to
33 # consider only in 32-bit application context. We probably have to
34 # recognize that 32-bit builds are getting less popular on high-end
35 # systems and therefore tend to target embedded ones, which might not
38 # On side note, Power ISA 2.07 enables vector base 2^26 implementation,
39 # and POWER8 might have capacity to break 1.0 cycle per byte barrier...
43 if ($flavour =~ /64/) {
50 } elsif ($flavour =~ /32/) {
57 } else { die "nonsense $flavour"; }
59 # Define endianess based on flavour
61 $LITTLE_ENDIAN = ($flavour=~/le$/) ? $SIZE_T : 0;
63 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
64 ( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
65 ( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
66 die "can't locate ppc-xlate.pl";
68 open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
73 my ($ctx,$inp,$len,$padbit) = map("r$_",(3..6));
74 my ($mac,$nonce)=($inp,$len);
81 if ($flavour =~ /64/) {
82 ###############################################################################
83 # base 2^64 implementation
85 my ($h0,$h1,$h2,$d0,$d1,$d2, $r0,$r1,$s1, $t0,$t1) = map("r$_",(7..12,27..31));
88 .globl .poly1305_init_int
92 std r0,0($ctx) # zero hash value
99 $code.=<<___ if ($LITTLE_ENDIAN);
100 ld $d0,0($inp) # load key material
103 $code.=<<___ if (!$LITTLE_ENDIAN);
105 lwbrx $d0,0,$inp # load key material
115 lis $h1,0xfff # 0x0fff0000
116 ori $h1,$h1,0xfffc # 0x0ffffffc
117 insrdi $h1,$h1,32,0 # 0x0ffffffc0ffffffc
118 ori $h0,$h1,3 # 0x0ffffffc0fffffff
123 std $d0,32($ctx) # store key
130 .byte 0,12,0x14,0,0,0,2,0
131 .size .poly1305_init_int,.-.poly1305_init_int
133 .globl .poly1305_blocks
139 $STU $sp,-$FRAME($sp)
141 $PUSH r27,`$FRAME-$SIZE_T*5`($sp)
142 $PUSH r28,`$FRAME-$SIZE_T*4`($sp)
143 $PUSH r29,`$FRAME-$SIZE_T*3`($sp)
144 $PUSH r30,`$FRAME-$SIZE_T*2`($sp)
145 $PUSH r31,`$FRAME-$SIZE_T*1`($sp)
146 $PUSH r0,`$FRAME+$LRSAVE`($sp)
148 ld $r0,32($ctx) # load key
151 ld $h0,0($ctx) # load hash value
157 add $s1,$s1,$r1 # s1 = r1 + r1>>2
164 $code.=<<___ if ($LITTLE_ENDIAN);
165 ld $t0,0($inp) # load input
168 $code.=<<___ if (!$LITTLE_ENDIAN);
170 lwbrx $t0,0,$inp # load input
182 addc $h0,$h0,$t0 # accumulate input
185 mulld $d0,$h0,$r0 # h0*r0
189 mulld $t0,$h1,$s1 # h1*5*r1
194 mulld $t0,$h0,$r1 # h0*r1
199 mulld $t0,$h1,$r0 # h1*r0
204 mulld $t0,$h2,$s1 # h2*5*r1
205 mulld $t1,$h2,$r0 # h2*r0
209 andc $t0,$d2,$mask # final reduction step
218 std $h0,0($ctx) # store hash value
222 $POP r27,`$FRAME-$SIZE_T*5`($sp)
223 $POP r28,`$FRAME-$SIZE_T*4`($sp)
224 $POP r29,`$FRAME-$SIZE_T*3`($sp)
225 $POP r30,`$FRAME-$SIZE_T*2`($sp)
226 $POP r31,`$FRAME-$SIZE_T*1`($sp)
231 .byte 0,12,4,1,0x80,5,4,0
232 .size .poly1305_blocks,.-.poly1305_blocks
234 .globl .poly1305_emit
237 ld $h0,0($ctx) # load hash
240 ld $padbit,0($nonce) # load nonce
243 addic $d0,$h0,5 # compare to modulus
247 srdi $mask,$d2,2 # did it carry/borrow?
257 $code.=<<___ if (!$LITTLE_ENDIAN);
258 rotldi $padbit,$padbit,32 # flip nonce words
259 rotldi $nonce,$nonce,32
262 addc $h0,$h0,$padbit # accumulate nonce
265 $code.=<<___ if ($LITTLE_ENDIAN);
266 std $h0,0($mac) # write result
269 $code.=<<___ if (!$LITTLE_ENDIAN);
272 stwbrx $h0,0,$mac # write result
283 .byte 0,12,0x14,0,0,0,3,0
284 .size .poly1305_emit,.-.poly1305_emit
287 ###############################################################################
288 # base 2^32 implementation
290 my ($h0,$h1,$h2,$h3,$h4, $r0,$r1,$r2,$r3, $s1,$s2,$s3,
291 $t0,$t1,$t2,$t3, $D0,$D1,$D2,$D3, $d0,$d1,$d2,$d3
292 ) = map("r$_",(7..12,14..31));
295 .globl .poly1305_init_int
299 stw r0,0($ctx) # zero hash value
308 $code.=<<___ if ($LITTLE_ENDIAN);
309 lw $h0,0($inp) # load key material
314 $code.=<<___ if (!$LITTLE_ENDIAN);
316 lwbrx $h0,0,$inp # load key material
324 lis $mask,0xf000 # 0xf0000000
326 andc $r0,$r0,$mask # 0x0ffffffc
333 stw $h0,32($ctx) # store key
342 .byte 0,12,0x14,0,0,0,2,0
343 .size .poly1305_init_int,.-.poly1305_init_int
345 .globl .poly1305_blocks
351 $STU $sp,-$FRAME($sp)
353 $PUSH r14,`$FRAME-$SIZE_T*18`($sp)
354 $PUSH r15,`$FRAME-$SIZE_T*17`($sp)
355 $PUSH r16,`$FRAME-$SIZE_T*16`($sp)
356 $PUSH r17,`$FRAME-$SIZE_T*15`($sp)
357 $PUSH r18,`$FRAME-$SIZE_T*14`($sp)
358 $PUSH r19,`$FRAME-$SIZE_T*13`($sp)
359 $PUSH r20,`$FRAME-$SIZE_T*12`($sp)
360 $PUSH r21,`$FRAME-$SIZE_T*11`($sp)
361 $PUSH r22,`$FRAME-$SIZE_T*10`($sp)
362 $PUSH r23,`$FRAME-$SIZE_T*9`($sp)
363 $PUSH r24,`$FRAME-$SIZE_T*8`($sp)
364 $PUSH r25,`$FRAME-$SIZE_T*7`($sp)
365 $PUSH r26,`$FRAME-$SIZE_T*6`($sp)
366 $PUSH r27,`$FRAME-$SIZE_T*5`($sp)
367 $PUSH r28,`$FRAME-$SIZE_T*4`($sp)
368 $PUSH r29,`$FRAME-$SIZE_T*3`($sp)
369 $PUSH r30,`$FRAME-$SIZE_T*2`($sp)
370 $PUSH r31,`$FRAME-$SIZE_T*1`($sp)
371 $PUSH r0,`$FRAME+$LRSAVE`($sp)
373 lwz $r0,32($ctx) # load key
378 lwz $h0,0($ctx) # load hash value
387 add $s1,$s1,$r1 # si = ri + ri>>2
397 $code.=<<___ if ($LITTLE_ENDIAN);
398 lwz $d0,0($inp) # load input
403 $code.=<<___ if (!$LITTLE_ENDIAN);
405 lwbrx $d0,0,$inp # load input
415 addc $h0,$h0,$d0 # accumulate input
419 mullw $d0,$h0,$r0 # h0*r0
422 mullw $d1,$h0,$r1 # h0*r1
425 mullw $d2,$h0,$r2 # h0*r2
431 mullw $d3,$h0,$r3 # h0*r3
434 mullw $t0,$h1,$s3 # h1*s3
437 mullw $t2,$h1,$r0 # h1*r0
442 mullw $t0,$h1,$r1 # h1*r1
447 mullw $t2,$h1,$r2 # h1*r2
452 mullw $t0,$h2,$s2 # h2*s2
457 mullw $t2,$h2,$s3 # h2*s3
462 mullw $t0,$h2,$r0 # h2*r0
467 mullw $t2,$h2,$r1 # h2*r1
472 mullw $t0,$h3,$s1 # h3*s1
477 mullw $t2,$h3,$s2 # h3*s2
482 mullw $t0,$h3,$s3 # h3*s3
487 mullw $t2,$h3,$r0 # h3*r0
492 mullw $t0,$h4,$s1 # h4*s1
497 mullw $t1,$h4,$s2 # h4*s2
502 mullw $t2,$h4,$s3 # h4*s3
506 mullw $h4,$h4,$r0 # h4*r0
513 andc $D0,$h4,$mask # final reduction step
524 stw $h0,0($ctx) # store hash value
530 $POP r14,`$FRAME-$SIZE_T*18`($sp)
531 $POP r15,`$FRAME-$SIZE_T*17`($sp)
532 $POP r16,`$FRAME-$SIZE_T*16`($sp)
533 $POP r17,`$FRAME-$SIZE_T*15`($sp)
534 $POP r18,`$FRAME-$SIZE_T*14`($sp)
535 $POP r19,`$FRAME-$SIZE_T*13`($sp)
536 $POP r20,`$FRAME-$SIZE_T*12`($sp)
537 $POP r21,`$FRAME-$SIZE_T*11`($sp)
538 $POP r22,`$FRAME-$SIZE_T*10`($sp)
539 $POP r23,`$FRAME-$SIZE_T*9`($sp)
540 $POP r24,`$FRAME-$SIZE_T*8`($sp)
541 $POP r25,`$FRAME-$SIZE_T*7`($sp)
542 $POP r26,`$FRAME-$SIZE_T*6`($sp)
543 $POP r27,`$FRAME-$SIZE_T*5`($sp)
544 $POP r28,`$FRAME-$SIZE_T*4`($sp)
545 $POP r29,`$FRAME-$SIZE_T*3`($sp)
546 $POP r30,`$FRAME-$SIZE_T*2`($sp)
547 $POP r31,`$FRAME-$SIZE_T*1`($sp)
552 .byte 0,12,4,1,0x80,18,4,0
553 .size .poly1305_blocks,.-.poly1305_blocks
555 .globl .poly1305_emit
558 $STU $sp,-$FRAME($sp)
560 $PUSH r28,`$FRAME-$SIZE_T*4`($sp)
561 $PUSH r29,`$FRAME-$SIZE_T*3`($sp)
562 $PUSH r30,`$FRAME-$SIZE_T*2`($sp)
563 $PUSH r31,`$FRAME-$SIZE_T*1`($sp)
564 $PUSH r0,`$FRAME+$LRSAVE`($sp)
566 lwz $h0,0($ctx) # load hash
572 addic $d0,$h0,5 # compare to modulus
578 srwi $mask,$mask,2 # did it carry/borrow?
586 lwz $d0,0($nonce) # load nonce
598 addc $h0,$h0,$d0 # accumulate nonce
603 $code.=<<___ if ($LITTLE_ENDIAN);
604 stw $h0,0($mac) # write result
609 $code.=<<___ if (!$LITTLE_ENDIAN);
611 stwbrx $h0,0,$mac # write result
619 $POP r28,`$FRAME-$SIZE_T*4`($sp)
620 $POP r29,`$FRAME-$SIZE_T*3`($sp)
621 $POP r30,`$FRAME-$SIZE_T*2`($sp)
622 $POP r31,`$FRAME-$SIZE_T*1`($sp)
626 .byte 0,12,4,1,0x80,4,3,0
627 .size .poly1305_emit,.-.poly1305_emit
631 .asciz "Poly1305 for PPC, CRYPTOGAMS by <appro\@openssl.org>"
634 $code =~ s/\`([^\`]*)\`/eval $1/gem;