Blame crypto/poly1305/asm/poly1305-ppc.pl

Packit c4476c
#! /usr/bin/env perl
Packit c4476c
# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
Packit c4476c
#
Packit c4476c
# Licensed under the OpenSSL license (the "License").  You may not use
Packit c4476c
# this file except in compliance with the License.  You can obtain a copy
Packit c4476c
# in the file LICENSE in the source distribution or at
Packit c4476c
# https://www.openssl.org/source/license.html
Packit c4476c
Packit c4476c
#
Packit c4476c
# ====================================================================
Packit c4476c
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
Packit c4476c
# project. The module is, however, dual licensed under OpenSSL and
Packit c4476c
# CRYPTOGAMS licenses depending on where you obtain it. For further
Packit c4476c
# details see http://www.openssl.org/~appro/cryptogams/.
Packit c4476c
# ====================================================================
Packit c4476c
#
Packit c4476c
# This module implements Poly1305 hash for PowerPC.
Packit c4476c
#
Packit c4476c
# June 2015
Packit c4476c
#
Packit c4476c
# Numbers are cycles per processed byte with poly1305_blocks alone,
Packit c4476c
# and improvement coefficients relative to gcc-generated code.
Packit c4476c
#
Packit c4476c
#			-m32		-m64
Packit c4476c
#
Packit c4476c
# Freescale e300	14.8/+80%	-
Packit c4476c
# PPC74x0		7.60/+60%	-
Packit c4476c
# PPC970		7.00/+114%	3.51/+205%
Packit c4476c
# POWER7		3.75/+260%	1.93/+100%
Packit c4476c
# POWER8		-		2.03/+200%
Packit c4476c
# POWER9		-		2.00/+150%
Packit c4476c
#
Packit c4476c
# Do we need floating-point implementation for PPC? Results presented
Packit c4476c
# in poly1305_ieee754.c are tricky to compare to, because they are for
Packit c4476c
# compiler-generated code. On the other hand it's known that floating-
Packit c4476c
# point performance can be dominated by FPU latency, which means that
Packit c4476c
# there is limit even for ideally optimized (and even vectorized) code.
Packit c4476c
# And this limit is estimated to be higher than above -m64 results. Or
Packit c4476c
# in other words floating-point implementation can be meaningful to
Packit c4476c
# consider only in 32-bit application context. We probably have to
Packit c4476c
# recognize that 32-bit builds are getting less popular on high-end
Packit c4476c
# systems and therefore tend to target embedded ones, which might not
Packit c4476c
# even have FPU...
Packit c4476c
#
Packit c4476c
# On side note, Power ISA 2.07 enables vector base 2^26 implementation,
Packit c4476c
# and POWER8 might have capacity to break 1.0 cycle per byte barrier...
Packit c4476c
Packit c4476c
$flavour = shift;
Packit c4476c
Packit c4476c
if ($flavour =~ /64/) {
Packit c4476c
	$SIZE_T	=8;
Packit c4476c
	$LRSAVE	=2*$SIZE_T;
Packit c4476c
	$UCMP	="cmpld";
Packit c4476c
	$STU	="stdu";
Packit c4476c
	$POP	="ld";
Packit c4476c
	$PUSH	="std";
Packit c4476c
} elsif ($flavour =~ /32/) {
Packit c4476c
	$SIZE_T	=4;
Packit c4476c
	$LRSAVE	=$SIZE_T;
Packit c4476c
	$UCMP	="cmplw";
Packit c4476c
	$STU	="stwu";
Packit c4476c
	$POP	="lwz";
Packit c4476c
	$PUSH	="stw";
Packit c4476c
} else { die "nonsense $flavour"; }
Packit c4476c
Packit c4476c
# Define endianness based on flavour
Packit c4476c
# i.e.: linux64le
Packit c4476c
$LITTLE_ENDIAN = ($flavour=~/le$/) ? $SIZE_T : 0;
Packit c4476c
Packit c4476c
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
Packit c4476c
( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
Packit c4476c
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
Packit c4476c
die "can't locate ppc-xlate.pl";
Packit c4476c
Packit c4476c
open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
Packit c4476c
Packit c4476c
$FRAME=24*$SIZE_T;
Packit c4476c
Packit c4476c
$sp="r1";
Packit c4476c
my ($ctx,$inp,$len,$padbit) = map("r$_",(3..6));
Packit c4476c
my ($mac,$nonce)=($inp,$len);
Packit c4476c
my $mask = "r0";
Packit c4476c
Packit c4476c
$code=<<___;
Packit c4476c
.machine	"any"
Packit c4476c
.text
Packit c4476c
___
Packit c4476c
							if ($flavour =~ /64/) {
Packit c4476c
###############################################################################
Packit c4476c
# base 2^64 implementation
Packit c4476c
Packit c4476c
my ($h0,$h1,$h2,$d0,$d1,$d2, $r0,$r1,$s1, $t0,$t1) = map("r$_",(7..12,27..31));
Packit c4476c
Packit c4476c
$code.=<<___;
Packit c4476c
.globl	.poly1305_init_int
Packit c4476c
.align	4
Packit c4476c
.poly1305_init_int:
Packit c4476c
	xor	r0,r0,r0
Packit c4476c
	std	r0,0($ctx)		# zero hash value
Packit c4476c
	std	r0,8($ctx)
Packit c4476c
	std	r0,16($ctx)
Packit c4476c
Packit c4476c
	$UCMP	$inp,r0
Packit c4476c
	beq-	Lno_key
Packit c4476c
___
Packit c4476c
$code.=<<___	if ($LITTLE_ENDIAN);
Packit c4476c
	ld	$d0,0($inp)		# load key material
Packit c4476c
	ld	$d1,8($inp)
Packit c4476c
___
Packit c4476c
$code.=<<___	if (!$LITTLE_ENDIAN);
Packit c4476c
	li	$h0,4
Packit c4476c
	lwbrx	$d0,0,$inp		# load key material
Packit c4476c
	li	$d1,8
Packit c4476c
	lwbrx	$h0,$h0,$inp
Packit c4476c
	li	$h1,12
Packit c4476c
	lwbrx	$d1,$d1,$inp
Packit c4476c
	lwbrx	$h1,$h1,$inp
Packit c4476c
	insrdi	$d0,$h0,32,0
Packit c4476c
	insrdi	$d1,$h1,32,0
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	lis	$h1,0xfff		# 0x0fff0000
Packit c4476c
	ori	$h1,$h1,0xfffc		# 0x0ffffffc
Packit c4476c
	insrdi	$h1,$h1,32,0		# 0x0ffffffc0ffffffc
Packit c4476c
	ori	$h0,$h1,3		# 0x0ffffffc0fffffff
Packit c4476c
Packit c4476c
	and	$d0,$d0,$h0
Packit c4476c
	and	$d1,$d1,$h1
Packit c4476c
Packit c4476c
	std	$d0,32($ctx)		# store key
Packit c4476c
	std	$d1,40($ctx)
Packit c4476c
Packit c4476c
Lno_key:
Packit c4476c
	xor	r3,r3,r3
Packit c4476c
	blr
Packit c4476c
	.long	0
Packit c4476c
	.byte	0,12,0x14,0,0,0,2,0
Packit c4476c
.size	.poly1305_init_int,.-.poly1305_init_int
Packit c4476c
Packit c4476c
.globl	.poly1305_blocks
Packit c4476c
.align	4
Packit c4476c
.poly1305_blocks:
Packit c4476c
	srdi.	$len,$len,4
Packit c4476c
	beq-	Labort
Packit c4476c
Packit c4476c
	$STU	$sp,-$FRAME($sp)
Packit c4476c
	mflr	r0
Packit c4476c
	$PUSH	r27,`$FRAME-$SIZE_T*5`($sp)
Packit c4476c
	$PUSH	r28,`$FRAME-$SIZE_T*4`($sp)
Packit c4476c
	$PUSH	r29,`$FRAME-$SIZE_T*3`($sp)
Packit c4476c
	$PUSH	r30,`$FRAME-$SIZE_T*2`($sp)
Packit c4476c
	$PUSH	r31,`$FRAME-$SIZE_T*1`($sp)
Packit c4476c
	$PUSH	r0,`$FRAME+$LRSAVE`($sp)
Packit c4476c
Packit c4476c
	ld	$r0,32($ctx)		# load key
Packit c4476c
	ld	$r1,40($ctx)
Packit c4476c
Packit c4476c
	ld	$h0,0($ctx)		# load hash value
Packit c4476c
	ld	$h1,8($ctx)
Packit c4476c
	ld	$h2,16($ctx)
Packit c4476c
Packit c4476c
	srdi	$s1,$r1,2
Packit c4476c
	mtctr	$len
Packit c4476c
	add	$s1,$s1,$r1		# s1 = r1 + r1>>2
Packit c4476c
	li	$mask,3
Packit c4476c
	b	Loop
Packit c4476c
Packit c4476c
.align	4
Packit c4476c
Loop:
Packit c4476c
___
Packit c4476c
$code.=<<___	if ($LITTLE_ENDIAN);
Packit c4476c
	ld	$t0,0($inp)		# load input
Packit c4476c
	ld	$t1,8($inp)
Packit c4476c
___
Packit c4476c
$code.=<<___	if (!$LITTLE_ENDIAN);
Packit c4476c
	li	$d0,4
Packit c4476c
	lwbrx	$t0,0,$inp		# load input
Packit c4476c
	li	$t1,8
Packit c4476c
	lwbrx	$d0,$d0,$inp
Packit c4476c
	li	$d1,12
Packit c4476c
	lwbrx	$t1,$t1,$inp
Packit c4476c
	lwbrx	$d1,$d1,$inp
Packit c4476c
	insrdi	$t0,$d0,32,0
Packit c4476c
	insrdi	$t1,$d1,32,0
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	addi	$inp,$inp,16
Packit c4476c
Packit c4476c
	addc	$h0,$h0,$t0		# accumulate input
Packit c4476c
	adde	$h1,$h1,$t1
Packit c4476c
Packit c4476c
	mulld	$d0,$h0,$r0		# h0*r0
Packit c4476c
	mulhdu	$d1,$h0,$r0
Packit c4476c
	adde	$h2,$h2,$padbit
Packit c4476c
Packit c4476c
	mulld	$t0,$h1,$s1		# h1*5*r1
Packit c4476c
	mulhdu	$t1,$h1,$s1
Packit c4476c
	addc	$d0,$d0,$t0
Packit c4476c
	adde	$d1,$d1,$t1
Packit c4476c
Packit c4476c
	mulld	$t0,$h0,$r1		# h0*r1
Packit c4476c
	mulhdu	$d2,$h0,$r1
Packit c4476c
	addc	$d1,$d1,$t0
Packit c4476c
	addze	$d2,$d2
Packit c4476c
Packit c4476c
	mulld	$t0,$h1,$r0		# h1*r0
Packit c4476c
	mulhdu	$t1,$h1,$r0
Packit c4476c
	addc	$d1,$d1,$t0
Packit c4476c
	adde	$d2,$d2,$t1
Packit c4476c
Packit c4476c
	mulld	$t0,$h2,$s1		# h2*5*r1
Packit c4476c
	mulld	$t1,$h2,$r0		# h2*r0
Packit c4476c
	addc	$d1,$d1,$t0
Packit c4476c
	adde	$d2,$d2,$t1
Packit c4476c
Packit c4476c
	andc	$t0,$d2,$mask		# final reduction step
Packit c4476c
	and	$h2,$d2,$mask
Packit c4476c
	srdi	$t1,$t0,2
Packit c4476c
	add	$t0,$t0,$t1
Packit c4476c
	addc	$h0,$d0,$t0
Packit c4476c
	addze	$h1,$d1
Packit c4476c
	addze	$h2,$h2
Packit c4476c
Packit c4476c
	bdnz	Loop
Packit c4476c
Packit c4476c
	std	$h0,0($ctx)		# store hash value
Packit c4476c
	std	$h1,8($ctx)
Packit c4476c
	std	$h2,16($ctx)
Packit c4476c
Packit c4476c
	$POP	r27,`$FRAME-$SIZE_T*5`($sp)
Packit c4476c
	$POP	r28,`$FRAME-$SIZE_T*4`($sp)
Packit c4476c
	$POP	r29,`$FRAME-$SIZE_T*3`($sp)
Packit c4476c
	$POP	r30,`$FRAME-$SIZE_T*2`($sp)
Packit c4476c
	$POP	r31,`$FRAME-$SIZE_T*1`($sp)
Packit c4476c
	addi	$sp,$sp,$FRAME
Packit c4476c
Labort:
Packit c4476c
	blr
Packit c4476c
	.long	0
Packit c4476c
	.byte	0,12,4,1,0x80,5,4,0
Packit c4476c
.size	.poly1305_blocks,.-.poly1305_blocks
Packit c4476c
Packit c4476c
.globl	.poly1305_emit
Packit c4476c
.align	4
Packit c4476c
.poly1305_emit:
Packit c4476c
	ld	$h0,0($ctx)		# load hash
Packit c4476c
	ld	$h1,8($ctx)
Packit c4476c
	ld	$h2,16($ctx)
Packit c4476c
	ld	$padbit,0($nonce)	# load nonce
Packit c4476c
	ld	$nonce,8($nonce)
Packit c4476c
Packit c4476c
	addic	$d0,$h0,5		# compare to modulus
Packit c4476c
	addze	$d1,$h1
Packit c4476c
	addze	$d2,$h2
Packit c4476c
Packit c4476c
	srdi	$mask,$d2,2		# did it carry/borrow?
Packit c4476c
	neg	$mask,$mask
Packit c4476c
Packit c4476c
	andc	$h0,$h0,$mask
Packit c4476c
	and	$d0,$d0,$mask
Packit c4476c
	andc	$h1,$h1,$mask
Packit c4476c
	and	$d1,$d1,$mask
Packit c4476c
	or	$h0,$h0,$d0
Packit c4476c
	or	$h1,$h1,$d1
Packit c4476c
___
Packit c4476c
$code.=<<___	if (!$LITTLE_ENDIAN);
Packit c4476c
	rotldi	$padbit,$padbit,32	# flip nonce words
Packit c4476c
	rotldi	$nonce,$nonce,32
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	addc	$h0,$h0,$padbit		# accumulate nonce
Packit c4476c
	adde	$h1,$h1,$nonce
Packit c4476c
___
Packit c4476c
$code.=<<___	if ($LITTLE_ENDIAN);
Packit c4476c
	std	$h0,0($mac)		# write result
Packit c4476c
	std	$h1,8($mac)
Packit c4476c
___
Packit c4476c
$code.=<<___	if (!$LITTLE_ENDIAN);
Packit c4476c
	extrdi	r0,$h0,32,0
Packit c4476c
	li	$d0,4
Packit c4476c
	stwbrx	$h0,0,$mac		# write result
Packit c4476c
	extrdi	$h0,$h1,32,0
Packit c4476c
	li	$d1,8
Packit c4476c
	stwbrx	r0,$d0,$mac
Packit c4476c
	li	$d2,12
Packit c4476c
	stwbrx	$h1,$d1,$mac
Packit c4476c
	stwbrx	$h0,$d2,$mac
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	blr
Packit c4476c
	.long	0
Packit c4476c
	.byte	0,12,0x14,0,0,0,3,0
Packit c4476c
.size	.poly1305_emit,.-.poly1305_emit
Packit c4476c
___
Packit c4476c
							} else {
Packit c4476c
###############################################################################
Packit c4476c
# base 2^32 implementation
Packit c4476c
Packit c4476c
my ($h0,$h1,$h2,$h3,$h4, $r0,$r1,$r2,$r3, $s1,$s2,$s3,
Packit c4476c
    $t0,$t1,$t2,$t3, $D0,$D1,$D2,$D3, $d0,$d1,$d2,$d3
Packit c4476c
   ) = map("r$_",(7..12,14..31));
Packit c4476c
Packit c4476c
$code.=<<___;
Packit c4476c
.globl	.poly1305_init_int
Packit c4476c
.align	4
Packit c4476c
.poly1305_init_int:
Packit c4476c
	xor	r0,r0,r0
Packit c4476c
	stw	r0,0($ctx)		# zero hash value
Packit c4476c
	stw	r0,4($ctx)
Packit c4476c
	stw	r0,8($ctx)
Packit c4476c
	stw	r0,12($ctx)
Packit c4476c
	stw	r0,16($ctx)
Packit c4476c
Packit c4476c
	$UCMP	$inp,r0
Packit c4476c
	beq-	Lno_key
Packit c4476c
___
Packit c4476c
$code.=<<___	if ($LITTLE_ENDIAN);
Packit c4476c
	lw	$h0,0($inp)		# load key material
Packit c4476c
	lw	$h1,4($inp)
Packit c4476c
	lw	$h2,8($inp)
Packit c4476c
	lw	$h3,12($inp)
Packit c4476c
___
Packit c4476c
$code.=<<___	if (!$LITTLE_ENDIAN);
Packit c4476c
	li	$h1,4
Packit c4476c
	lwbrx	$h0,0,$inp		# load key material
Packit c4476c
	li	$h2,8
Packit c4476c
	lwbrx	$h1,$h1,$inp
Packit c4476c
	li	$h3,12
Packit c4476c
	lwbrx	$h2,$h2,$inp
Packit c4476c
	lwbrx	$h3,$h3,$inp
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	lis	$mask,0xf000		# 0xf0000000
Packit c4476c
	li	$r0,-4
Packit c4476c
	andc	$r0,$r0,$mask		# 0x0ffffffc
Packit c4476c
Packit c4476c
	andc	$h0,$h0,$mask
Packit c4476c
	and	$h1,$h1,$r0
Packit c4476c
	and	$h2,$h2,$r0
Packit c4476c
	and	$h3,$h3,$r0
Packit c4476c
Packit c4476c
	stw	$h0,32($ctx)		# store key
Packit c4476c
	stw	$h1,36($ctx)
Packit c4476c
	stw	$h2,40($ctx)
Packit c4476c
	stw	$h3,44($ctx)
Packit c4476c
Packit c4476c
Lno_key:
Packit c4476c
	xor	r3,r3,r3
Packit c4476c
	blr
Packit c4476c
	.long	0
Packit c4476c
	.byte	0,12,0x14,0,0,0,2,0
Packit c4476c
.size	.poly1305_init_int,.-.poly1305_init_int
Packit c4476c
Packit c4476c
.globl	.poly1305_blocks
Packit c4476c
.align	4
Packit c4476c
.poly1305_blocks:
Packit c4476c
	srwi.	$len,$len,4
Packit c4476c
	beq-	Labort
Packit c4476c
Packit c4476c
	$STU	$sp,-$FRAME($sp)
Packit c4476c
	mflr	r0
Packit c4476c
	$PUSH	r14,`$FRAME-$SIZE_T*18`($sp)
Packit c4476c
	$PUSH	r15,`$FRAME-$SIZE_T*17`($sp)
Packit c4476c
	$PUSH	r16,`$FRAME-$SIZE_T*16`($sp)
Packit c4476c
	$PUSH	r17,`$FRAME-$SIZE_T*15`($sp)
Packit c4476c
	$PUSH	r18,`$FRAME-$SIZE_T*14`($sp)
Packit c4476c
	$PUSH	r19,`$FRAME-$SIZE_T*13`($sp)
Packit c4476c
	$PUSH	r20,`$FRAME-$SIZE_T*12`($sp)
Packit c4476c
	$PUSH	r21,`$FRAME-$SIZE_T*11`($sp)
Packit c4476c
	$PUSH	r22,`$FRAME-$SIZE_T*10`($sp)
Packit c4476c
	$PUSH	r23,`$FRAME-$SIZE_T*9`($sp)
Packit c4476c
	$PUSH	r24,`$FRAME-$SIZE_T*8`($sp)
Packit c4476c
	$PUSH	r25,`$FRAME-$SIZE_T*7`($sp)
Packit c4476c
	$PUSH	r26,`$FRAME-$SIZE_T*6`($sp)
Packit c4476c
	$PUSH	r27,`$FRAME-$SIZE_T*5`($sp)
Packit c4476c
	$PUSH	r28,`$FRAME-$SIZE_T*4`($sp)
Packit c4476c
	$PUSH	r29,`$FRAME-$SIZE_T*3`($sp)
Packit c4476c
	$PUSH	r30,`$FRAME-$SIZE_T*2`($sp)
Packit c4476c
	$PUSH	r31,`$FRAME-$SIZE_T*1`($sp)
Packit c4476c
	$PUSH	r0,`$FRAME+$LRSAVE`($sp)
Packit c4476c
Packit c4476c
	lwz	$r0,32($ctx)		# load key
Packit c4476c
	lwz	$r1,36($ctx)
Packit c4476c
	lwz	$r2,40($ctx)
Packit c4476c
	lwz	$r3,44($ctx)
Packit c4476c
Packit c4476c
	lwz	$h0,0($ctx)		# load hash value
Packit c4476c
	lwz	$h1,4($ctx)
Packit c4476c
	lwz	$h2,8($ctx)
Packit c4476c
	lwz	$h3,12($ctx)
Packit c4476c
	lwz	$h4,16($ctx)
Packit c4476c
Packit c4476c
	srwi	$s1,$r1,2
Packit c4476c
	srwi	$s2,$r2,2
Packit c4476c
	srwi	$s3,$r3,2
Packit c4476c
	add	$s1,$s1,$r1		# si = ri + ri>>2
Packit c4476c
	add	$s2,$s2,$r2
Packit c4476c
	add	$s3,$s3,$r3
Packit c4476c
	mtctr	$len
Packit c4476c
	li	$mask,3
Packit c4476c
	b	Loop
Packit c4476c
Packit c4476c
.align	4
Packit c4476c
Loop:
Packit c4476c
___
Packit c4476c
$code.=<<___	if ($LITTLE_ENDIAN);
Packit c4476c
	lwz	$d0,0($inp)		# load input
Packit c4476c
	lwz	$d1,4($inp)
Packit c4476c
	lwz	$d2,8($inp)
Packit c4476c
	lwz	$d3,12($inp)
Packit c4476c
___
Packit c4476c
$code.=<<___	if (!$LITTLE_ENDIAN);
Packit c4476c
	li	$d1,4
Packit c4476c
	lwbrx	$d0,0,$inp		# load input
Packit c4476c
	li	$d2,8
Packit c4476c
	lwbrx	$d1,$d1,$inp
Packit c4476c
	li	$d3,12
Packit c4476c
	lwbrx	$d2,$d2,$inp
Packit c4476c
	lwbrx	$d3,$d3,$inp
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	addi	$inp,$inp,16
Packit c4476c
Packit c4476c
	addc	$h0,$h0,$d0		# accumulate input
Packit c4476c
	adde	$h1,$h1,$d1
Packit c4476c
	adde	$h2,$h2,$d2
Packit c4476c
Packit c4476c
	mullw	$d0,$h0,$r0		# h0*r0
Packit c4476c
	mulhwu	$D0,$h0,$r0
Packit c4476c
Packit c4476c
	mullw	$d1,$h0,$r1		# h0*r1
Packit c4476c
	mulhwu	$D1,$h0,$r1
Packit c4476c
Packit c4476c
	mullw	$d2,$h0,$r2		# h0*r2
Packit c4476c
	mulhwu	$D2,$h0,$r2
Packit c4476c
Packit c4476c
	 adde	$h3,$h3,$d3
Packit c4476c
	 adde	$h4,$h4,$padbit
Packit c4476c
Packit c4476c
	mullw	$d3,$h0,$r3		# h0*r3
Packit c4476c
	mulhwu	$D3,$h0,$r3
Packit c4476c
Packit c4476c
	mullw	$t0,$h1,$s3		# h1*s3
Packit c4476c
	mulhwu	$t1,$h1,$s3
Packit c4476c
Packit c4476c
	mullw	$t2,$h1,$r0		# h1*r0
Packit c4476c
	mulhwu	$t3,$h1,$r0
Packit c4476c
	 addc	$d0,$d0,$t0
Packit c4476c
	 adde	$D0,$D0,$t1
Packit c4476c
Packit c4476c
	mullw	$t0,$h1,$r1		# h1*r1
Packit c4476c
	mulhwu	$t1,$h1,$r1
Packit c4476c
	 addc	$d1,$d1,$t2
Packit c4476c
	 adde	$D1,$D1,$t3
Packit c4476c
Packit c4476c
	mullw	$t2,$h1,$r2		# h1*r2
Packit c4476c
	mulhwu	$t3,$h1,$r2
Packit c4476c
	 addc	$d2,$d2,$t0
Packit c4476c
	 adde	$D2,$D2,$t1
Packit c4476c
Packit c4476c
	mullw	$t0,$h2,$s2		# h2*s2
Packit c4476c
	mulhwu	$t1,$h2,$s2
Packit c4476c
	 addc	$d3,$d3,$t2
Packit c4476c
	 adde	$D3,$D3,$t3
Packit c4476c
Packit c4476c
	mullw	$t2,$h2,$s3		# h2*s3
Packit c4476c
	mulhwu	$t3,$h2,$s3
Packit c4476c
	 addc	$d0,$d0,$t0
Packit c4476c
	 adde	$D0,$D0,$t1
Packit c4476c
Packit c4476c
	mullw	$t0,$h2,$r0		# h2*r0
Packit c4476c
	mulhwu	$t1,$h2,$r0
Packit c4476c
	 addc	$d1,$d1,$t2
Packit c4476c
	 adde	$D1,$D1,$t3
Packit c4476c
Packit c4476c
	mullw	$t2,$h2,$r1		# h2*r1
Packit c4476c
	mulhwu	$t3,$h2,$r1
Packit c4476c
	 addc	$d2,$d2,$t0
Packit c4476c
	 adde	$D2,$D2,$t1
Packit c4476c
Packit c4476c
	mullw	$t0,$h3,$s1		# h3*s1
Packit c4476c
	mulhwu	$t1,$h3,$s1
Packit c4476c
	 addc	$d3,$d3,$t2
Packit c4476c
	 adde	$D3,$D3,$t3
Packit c4476c
Packit c4476c
	mullw	$t2,$h3,$s2		# h3*s2
Packit c4476c
	mulhwu	$t3,$h3,$s2
Packit c4476c
	 addc	$d0,$d0,$t0
Packit c4476c
	 adde	$D0,$D0,$t1
Packit c4476c
Packit c4476c
	mullw	$t0,$h3,$s3		# h3*s3
Packit c4476c
	mulhwu	$t1,$h3,$s3
Packit c4476c
	 addc	$d1,$d1,$t2
Packit c4476c
	 adde	$D1,$D1,$t3
Packit c4476c
Packit c4476c
	mullw	$t2,$h3,$r0		# h3*r0
Packit c4476c
	mulhwu	$t3,$h3,$r0
Packit c4476c
	 addc	$d2,$d2,$t0
Packit c4476c
	 adde	$D2,$D2,$t1
Packit c4476c
Packit c4476c
	mullw	$t0,$h4,$s1		# h4*s1
Packit c4476c
	 addc	$d3,$d3,$t2
Packit c4476c
	 adde	$D3,$D3,$t3
Packit c4476c
	addc	$d1,$d1,$t0
Packit c4476c
Packit c4476c
	mullw	$t1,$h4,$s2		# h4*s2
Packit c4476c
	 addze	$D1,$D1
Packit c4476c
	addc	$d2,$d2,$t1
Packit c4476c
	addze	$D2,$D2
Packit c4476c
Packit c4476c
	mullw	$t2,$h4,$s3		# h4*s3
Packit c4476c
	addc	$d3,$d3,$t2
Packit c4476c
	addze	$D3,$D3
Packit c4476c
Packit c4476c
	mullw	$h4,$h4,$r0		# h4*r0
Packit c4476c
Packit c4476c
	addc	$h1,$d1,$D0
Packit c4476c
	adde	$h2,$d2,$D1
Packit c4476c
	adde	$h3,$d3,$D2
Packit c4476c
	adde	$h4,$h4,$D3
Packit c4476c
Packit c4476c
	andc	$D0,$h4,$mask		# final reduction step
Packit c4476c
	and	$h4,$h4,$mask
Packit c4476c
	srwi	$D1,$D0,2
Packit c4476c
	add	$D0,$D0,$D1
Packit c4476c
	addc	$h0,$d0,$D0
Packit c4476c
	addze	$h1,$h1
Packit c4476c
	addze	$h2,$h2
Packit c4476c
	addze	$h3,$h3
Packit c4476c
	addze	$h4,$h4
Packit c4476c
Packit c4476c
	bdnz	Loop
Packit c4476c
Packit c4476c
	stw	$h0,0($ctx)		# store hash value
Packit c4476c
	stw	$h1,4($ctx)
Packit c4476c
	stw	$h2,8($ctx)
Packit c4476c
	stw	$h3,12($ctx)
Packit c4476c
	stw	$h4,16($ctx)
Packit c4476c
Packit c4476c
	$POP	r14,`$FRAME-$SIZE_T*18`($sp)
Packit c4476c
	$POP	r15,`$FRAME-$SIZE_T*17`($sp)
Packit c4476c
	$POP	r16,`$FRAME-$SIZE_T*16`($sp)
Packit c4476c
	$POP	r17,`$FRAME-$SIZE_T*15`($sp)
Packit c4476c
	$POP	r18,`$FRAME-$SIZE_T*14`($sp)
Packit c4476c
	$POP	r19,`$FRAME-$SIZE_T*13`($sp)
Packit c4476c
	$POP	r20,`$FRAME-$SIZE_T*12`($sp)
Packit c4476c
	$POP	r21,`$FRAME-$SIZE_T*11`($sp)
Packit c4476c
	$POP	r22,`$FRAME-$SIZE_T*10`($sp)
Packit c4476c
	$POP	r23,`$FRAME-$SIZE_T*9`($sp)
Packit c4476c
	$POP	r24,`$FRAME-$SIZE_T*8`($sp)
Packit c4476c
	$POP	r25,`$FRAME-$SIZE_T*7`($sp)
Packit c4476c
	$POP	r26,`$FRAME-$SIZE_T*6`($sp)
Packit c4476c
	$POP	r27,`$FRAME-$SIZE_T*5`($sp)
Packit c4476c
	$POP	r28,`$FRAME-$SIZE_T*4`($sp)
Packit c4476c
	$POP	r29,`$FRAME-$SIZE_T*3`($sp)
Packit c4476c
	$POP	r30,`$FRAME-$SIZE_T*2`($sp)
Packit c4476c
	$POP	r31,`$FRAME-$SIZE_T*1`($sp)
Packit c4476c
	addi	$sp,$sp,$FRAME
Packit c4476c
Labort:
Packit c4476c
	blr
Packit c4476c
	.long	0
Packit c4476c
	.byte	0,12,4,1,0x80,18,4,0
Packit c4476c
.size	.poly1305_blocks,.-.poly1305_blocks
Packit c4476c
Packit c4476c
.globl	.poly1305_emit
Packit c4476c
.align	4
Packit c4476c
.poly1305_emit:
Packit c4476c
	$STU	$sp,-$FRAME($sp)
Packit c4476c
	mflr	r0
Packit c4476c
	$PUSH	r28,`$FRAME-$SIZE_T*4`($sp)
Packit c4476c
	$PUSH	r29,`$FRAME-$SIZE_T*3`($sp)
Packit c4476c
	$PUSH	r30,`$FRAME-$SIZE_T*2`($sp)
Packit c4476c
	$PUSH	r31,`$FRAME-$SIZE_T*1`($sp)
Packit c4476c
	$PUSH	r0,`$FRAME+$LRSAVE`($sp)
Packit c4476c
Packit c4476c
	lwz	$h0,0($ctx)		# load hash
Packit c4476c
	lwz	$h1,4($ctx)
Packit c4476c
	lwz	$h2,8($ctx)
Packit c4476c
	lwz	$h3,12($ctx)
Packit c4476c
	lwz	$h4,16($ctx)
Packit c4476c
Packit c4476c
	addic	$d0,$h0,5		# compare to modulus
Packit c4476c
	addze	$d1,$h1
Packit c4476c
	addze	$d2,$h2
Packit c4476c
	addze	$d3,$h3
Packit c4476c
	addze	$mask,$h4
Packit c4476c
Packit c4476c
	srwi	$mask,$mask,2		# did it carry/borrow?
Packit c4476c
	neg	$mask,$mask
Packit c4476c
Packit c4476c
	andc	$h0,$h0,$mask
Packit c4476c
	and	$d0,$d0,$mask
Packit c4476c
	andc	$h1,$h1,$mask
Packit c4476c
	and	$d1,$d1,$mask
Packit c4476c
	or	$h0,$h0,$d0
Packit c4476c
	lwz	$d0,0($nonce)		# load nonce
Packit c4476c
	andc	$h2,$h2,$mask
Packit c4476c
	and	$d2,$d2,$mask
Packit c4476c
	or	$h1,$h1,$d1
Packit c4476c
	lwz	$d1,4($nonce)
Packit c4476c
	andc	$h3,$h3,$mask
Packit c4476c
	and	$d3,$d3,$mask
Packit c4476c
	or	$h2,$h2,$d2
Packit c4476c
	lwz	$d2,8($nonce)
Packit c4476c
	or	$h3,$h3,$d3
Packit c4476c
	lwz	$d3,12($nonce)
Packit c4476c
Packit c4476c
	addc	$h0,$h0,$d0		# accumulate nonce
Packit c4476c
	adde	$h1,$h1,$d1
Packit c4476c
	adde	$h2,$h2,$d2
Packit c4476c
	adde	$h3,$h3,$d3
Packit c4476c
___
Packit c4476c
$code.=<<___	if ($LITTLE_ENDIAN);
Packit c4476c
	stw	$h0,0($mac)		# write result
Packit c4476c
	stw	$h1,4($mac)
Packit c4476c
	stw	$h2,8($mac)
Packit c4476c
	stw	$h3,12($mac)
Packit c4476c
___
Packit c4476c
$code.=<<___	if (!$LITTLE_ENDIAN);
Packit c4476c
	li	$d1,4
Packit c4476c
	stwbrx	$h0,0,$mac		# write result
Packit c4476c
	li	$d2,8
Packit c4476c
	stwbrx	$h1,$d1,$mac
Packit c4476c
	li	$d3,12
Packit c4476c
	stwbrx	$h2,$d2,$mac
Packit c4476c
	stwbrx	$h3,$d3,$mac
Packit c4476c
___
Packit c4476c
$code.=<<___;
Packit c4476c
	$POP	r28,`$FRAME-$SIZE_T*4`($sp)
Packit c4476c
	$POP	r29,`$FRAME-$SIZE_T*3`($sp)
Packit c4476c
	$POP	r30,`$FRAME-$SIZE_T*2`($sp)
Packit c4476c
	$POP	r31,`$FRAME-$SIZE_T*1`($sp)
Packit c4476c
	addi	$sp,$sp,$FRAME
Packit c4476c
	blr
Packit c4476c
	.long	0
Packit c4476c
	.byte	0,12,4,1,0x80,4,3,0
Packit c4476c
.size	.poly1305_emit,.-.poly1305_emit
Packit c4476c
___
Packit c4476c
							}
Packit c4476c
$code.=<<___;
Packit c4476c
.asciz	"Poly1305 for PPC, CRYPTOGAMS by <appro\@openssl.org>"
Packit c4476c
___
Packit c4476c
Packit c4476c
$code =~ s/\`([^\`]*)\`/eval $1/gem;
Packit c4476c
print $code;
Packit c4476c
close STDOUT or die "error closing STDOUT: $!";