1#!/usr/bin/env perl
2#
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# ====================================================================
9#
10# GHASH for for PowerISA v2.07.
11#
12# July 2014
13#
14# Accurate performance measurements are problematic, because it's
15# always virtualized setup with possibly throttled processor.
16# Relative comparison is therefore more informative. This initial
17# version is ~2.1x slower than hardware-assisted AES-128-CTR, ~12x
18# faster than "4-bit" integer-only compiler-generated 64-bit code.
19# "Initial version" means that there is room for futher improvement.
20
21$flavour=shift;
22$output =shift;
23
24if ($flavour =~ /64/) {
25	$SIZE_T=8;
26	$LRSAVE=2*$SIZE_T;
27	$STU="stdu";
28	$POP="ld";
29	$PUSH="std";
30} elsif ($flavour =~ /32/) {
31	$SIZE_T=4;
32	$LRSAVE=$SIZE_T;
33	$STU="stwu";
34	$POP="lwz";
35	$PUSH="stw";
36} else { die "nonsense $flavour"; }
37
38$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
39( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
40( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
41die "can't locate ppc-xlate.pl";
42
43open STDOUT,"| $^X $xlate $flavour $output" || die "can't call $xlate: $!";
44
45my ($Xip,$Htbl,$inp,$len)=map("r$_",(3..6));	# argument block
46
47my ($Xl,$Xm,$Xh,$IN)=map("v$_",(0..3));
48my ($zero,$t0,$t1,$t2,$xC2,$H,$Hh,$Hl,$lemask)=map("v$_",(4..12));
49my $vrsave="r12";
50
51$code=<<___;
52.machine	"any"
53
54.text
55
56.globl	.gcm_init_p8
57	lis		r0,0xfff0
58	li		r8,0x10
59	mfspr		$vrsave,256
60	li		r9,0x20
61	mtspr		256,r0
62	li		r10,0x30
63	lvx_u		$H,0,r4			# load H
64
65	vspltisb	$xC2,-16		# 0xf0
66	vspltisb	$t0,1			# one
67	vaddubm		$xC2,$xC2,$xC2		# 0xe0
68	vxor		$zero,$zero,$zero
69	vor		$xC2,$xC2,$t0		# 0xe1
70	vsldoi		$xC2,$xC2,$zero,15	# 0xe1...
71	vsldoi		$t1,$zero,$t0,1		# ...1
72	vaddubm		$xC2,$xC2,$xC2		# 0xc2...
73	vspltisb	$t2,7
74	vor		$xC2,$xC2,$t1		# 0xc2....01
75	vspltb		$t1,$H,0		# most significant byte
76	vsl		$H,$H,$t0		# H<<=1
77	vsrab		$t1,$t1,$t2		# broadcast carry bit
78	vand		$t1,$t1,$xC2
79	vxor		$H,$H,$t1		# twisted H
80
81	vsldoi		$H,$H,$H,8		# twist even more ...
82	vsldoi		$xC2,$zero,$xC2,8	# 0xc2.0
83	vsldoi		$Hl,$zero,$H,8		# ... and split
84	vsldoi		$Hh,$H,$zero,8
85
86	stvx_u		$xC2,0,r3		# save pre-computed table
87	stvx_u		$Hl,r8,r3
88	stvx_u		$H, r9,r3
89	stvx_u		$Hh,r10,r3
90
91	mtspr		256,$vrsave
92	blr
93	.long		0
94	.byte		0,12,0x14,0,0,0,2,0
95	.long		0
96.size	.gcm_init_p8,.-.gcm_init_p8
97
98.globl	.gcm_gmult_p8
99	lis		r0,0xfff8
100	li		r8,0x10
101	mfspr		$vrsave,256
102	li		r9,0x20
103	mtspr		256,r0
104	li		r10,0x30
105	lvx_u		$IN,0,$Xip		# load Xi
106
107	lvx_u		$Hl,r8,$Htbl		# load pre-computed table
108	 le?lvsl	$lemask,r0,r0
109	lvx_u		$H, r9,$Htbl
110	 le?vspltisb	$t0,0x07
111	lvx_u		$Hh,r10,$Htbl
112	 le?vxor	$lemask,$lemask,$t0
113	lvx_u		$xC2,0,$Htbl
114	 le?vperm	$IN,$IN,$IN,$lemask
115	vxor		$zero,$zero,$zero
116
117	vpmsumd		$Xl,$IN,$Hl		# H.lo�Xi.lo
118	vpmsumd		$Xm,$IN,$H		# H.hi�Xi.lo+H.lo�Xi.hi
119	vpmsumd		$Xh,$IN,$Hh		# H.hi�Xi.hi
120
121	vpmsumd		$t2,$Xl,$xC2		# 1st phase
122
123	vsldoi		$t0,$Xm,$zero,8
124	vsldoi		$t1,$zero,$Xm,8
125	vxor		$Xl,$Xl,$t0
126	vxor		$Xh,$Xh,$t1
127
128	vsldoi		$Xl,$Xl,$Xl,8
129	vxor		$Xl,$Xl,$t2
130
131	vsldoi		$t1,$Xl,$Xl,8		# 2nd phase
132	vpmsumd		$Xl,$Xl,$xC2
133	vxor		$t1,$t1,$Xh
134	vxor		$Xl,$Xl,$t1
135
136	le?vperm	$Xl,$Xl,$Xl,$lemask
137	stvx_u		$Xl,0,$Xip		# write out Xi
138
139	mtspr		256,$vrsave
140	blr
141	.long		0
142	.byte		0,12,0x14,0,0,0,2,0
143	.long		0
144.size	.gcm_gmult_p8,.-.gcm_gmult_p8
145
146.globl	.gcm_ghash_p8
147	lis		r0,0xfff8
148	li		r8,0x10
149	mfspr		$vrsave,256
150	li		r9,0x20
151	mtspr		256,r0
152	li		r10,0x30
153	lvx_u		$Xl,0,$Xip		# load Xi
154
155	lvx_u		$Hl,r8,$Htbl		# load pre-computed table
156	 le?lvsl	$lemask,r0,r0
157	lvx_u		$H, r9,$Htbl
158	 le?vspltisb	$t0,0x07
159	lvx_u		$Hh,r10,$Htbl
160	 le?vxor	$lemask,$lemask,$t0
161	lvx_u		$xC2,0,$Htbl
162	 le?vperm	$Xl,$Xl,$Xl,$lemask
163	vxor		$zero,$zero,$zero
164
165	lvx_u		$IN,0,$inp
166	addi		$inp,$inp,16
167	subi		$len,$len,16
168	 le?vperm	$IN,$IN,$IN,$lemask
169	vxor		$IN,$IN,$Xl
170	b		Loop
171
172.align	5
173Loop:
174	 subic		$len,$len,16
175	vpmsumd		$Xl,$IN,$Hl		# H.lo�Xi.lo
176	 subfe.		r0,r0,r0		# borrow?-1:0
177	vpmsumd		$Xm,$IN,$H		# H.hi�Xi.lo+H.lo�Xi.hi
178	 and		r0,r0,$len
179	vpmsumd		$Xh,$IN,$Hh		# H.hi�Xi.hi
180	 add		$inp,$inp,r0
181
182	vpmsumd		$t2,$Xl,$xC2		# 1st phase
183
184	vsldoi		$t0,$Xm,$zero,8
185	vsldoi		$t1,$zero,$Xm,8
186	vxor		$Xl,$Xl,$t0
187	vxor		$Xh,$Xh,$t1
188
189	vsldoi		$Xl,$Xl,$Xl,8
190	vxor		$Xl,$Xl,$t2
191	 lvx_u		$IN,0,$inp
192	 addi		$inp,$inp,16
193
194	vsldoi		$t1,$Xl,$Xl,8		# 2nd phase
195	vpmsumd		$Xl,$Xl,$xC2
196	 le?vperm	$IN,$IN,$IN,$lemask
197	vxor		$t1,$t1,$Xh
198	vxor		$IN,$IN,$t1
199	vxor		$IN,$IN,$Xl
200	beq		Loop			# did $len-=16 borrow?
201
202	vxor		$Xl,$Xl,$t1
203	le?vperm	$Xl,$Xl,$Xl,$lemask
204	stvx_u		$Xl,0,$Xip		# write out Xi
205
206	mtspr		256,$vrsave
207	blr
208	.long		0
209	.byte		0,12,0x14,0,0,0,4,0
210	.long		0
211.size	.gcm_ghash_p8,.-.gcm_ghash_p8
212
213.asciz  "GHASH for PowerISA 2.07, CRYPTOGAMS by <appro\@openssl.org>"
214.align  2
215___
216
217foreach (split("\n",$code)) {
218	if ($flavour =~ /le$/o) {	# little-endian
219	    s/le\?//o		or
220	    s/be\?/#be#/o;
221	} else {
222	    s/le\?/#le#/o	or
223	    s/be\?//o;
224	}
225	print $_,"\n";
226}
227
228close STDOUT; # enforce flush
229