1#! /usr/bin/env perl
2# Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
3#
4# Licensed under the Apache License 2.0 (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# $output is the last argument if it looks like a file (it has an extension)
11# $flavour is the first argument if it doesn't look like a file
12$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
13$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
14
15$output and open STDOUT,">$output";
16
17if ($flavour =~ /64/) {
18	$LEVEL		="2.0W";
19	$SIZE_T		=8;
20	$ST		="std";
21} else {
22	$LEVEL		="1.1";
23	$SIZE_T		=4;
24	$ST		="stw";
25}
26
27$rp="%r2";
28$sp="%r30";
29$rv="%r28";
30
31$code=<<___;
32	.LEVEL	$LEVEL
33	.SPACE	\$TEXT\$
34	.SUBSPA	\$CODE\$,QUAD=0,ALIGN=8,ACCESS=0x2C,CODE_ONLY
35
36	.EXPORT	OPENSSL_cpuid_setup,ENTRY
37	.ALIGN	8
38OPENSSL_cpuid_setup
39	.PROC
40	.CALLINFO	NO_CALLS
41	.ENTRY
42	bv	($rp)
43	.EXIT
44	nop
45	.PROCEND
46
47	.EXPORT	OPENSSL_rdtsc,ENTRY
48	.ALIGN	8
49OPENSSL_rdtsc
50	.PROC
51	.CALLINFO	NO_CALLS
52	.ENTRY
53	mfctl	%cr16,$rv
54	bv	($rp)
55	.EXIT
56	nop
57	.PROCEND
58
59	.EXPORT	OPENSSL_wipe_cpu,ENTRY
60	.ALIGN	8
61OPENSSL_wipe_cpu
62	.PROC
63	.CALLINFO	NO_CALLS
64	.ENTRY
65	xor		%r0,%r0,%r1
66	fcpy,dbl	%fr0,%fr4
67	xor		%r0,%r0,%r19
68	fcpy,dbl	%fr0,%fr5
69	xor		%r0,%r0,%r20
70	fcpy,dbl	%fr0,%fr6
71	xor		%r0,%r0,%r21
72	fcpy,dbl	%fr0,%fr7
73	xor		%r0,%r0,%r22
74	fcpy,dbl	%fr0,%fr8
75	xor		%r0,%r0,%r23
76	fcpy,dbl	%fr0,%fr9
77	xor		%r0,%r0,%r24
78	fcpy,dbl	%fr0,%fr10
79	xor		%r0,%r0,%r25
80	fcpy,dbl	%fr0,%fr11
81	xor		%r0,%r0,%r26
82	fcpy,dbl	%fr0,%fr22
83	xor		%r0,%r0,%r29
84	fcpy,dbl	%fr0,%fr23
85	xor		%r0,%r0,%r31
86	fcpy,dbl	%fr0,%fr24
87	fcpy,dbl	%fr0,%fr25
88	fcpy,dbl	%fr0,%fr26
89	fcpy,dbl	%fr0,%fr27
90	fcpy,dbl	%fr0,%fr28
91	fcpy,dbl	%fr0,%fr29
92	fcpy,dbl	%fr0,%fr30
93	fcpy,dbl	%fr0,%fr31
94	bv		($rp)
95	.EXIT
96	ldo		0($sp),$rv
97	.PROCEND
98___
99{
100my $inp="%r26";
101my $len="%r25";
102
103$code.=<<___;
104	.EXPORT	OPENSSL_cleanse,ENTRY,ARGW0=GR,ARGW1=GR
105	.ALIGN	8
106OPENSSL_cleanse
107	.PROC
108	.CALLINFO	NO_CALLS
109	.ENTRY
110	cmpib,*=	0,$len,L\$done
111	nop
112	cmpib,*>>=	15,$len,L\$ittle
113	ldi		$SIZE_T-1,%r1
114
115L\$align
116	and,*<>		$inp,%r1,%r28
117	b,n		L\$aligned
118	stb		%r0,0($inp)
119	ldo		-1($len),$len
120	b		L\$align
121	ldo		1($inp),$inp
122
123L\$aligned
124	andcm		$len,%r1,%r28
125L\$ot
126	$ST		%r0,0($inp)
127	addib,*<>	-$SIZE_T,%r28,L\$ot
128	ldo		$SIZE_T($inp),$inp
129
130	and,*<>		$len,%r1,$len
131	b,n		L\$done
132L\$ittle
133	stb		%r0,0($inp)
134	addib,*<>	-1,$len,L\$ittle
135	ldo		1($inp),$inp
136L\$done
137	bv		($rp)
138	.EXIT
139	nop
140	.PROCEND
141___
142}
143{
144my ($in1,$in2,$len)=("%r26","%r25","%r24");
145
146$code.=<<___;
147	.EXPORT	CRYPTO_memcmp,ENTRY,ARGW0=GR,ARGW1=GR,ARGW1=GR
148	.ALIGN	8
149CRYPTO_memcmp
150	.PROC
151	.CALLINFO	NO_CALLS
152	.ENTRY
153	cmpib,*=	0,$len,L\$no_data
154	xor		$rv,$rv,$rv
155
156L\$oop_cmp
157	ldb		0($in1),%r19
158	ldb		0($in2),%r20
159	ldo		1($in1),$in1
160	ldo		1($in2),$in2
161	xor		%r19,%r20,%r29
162	addib,*<>	-1,$len,L\$oop_cmp
163	or		%r29,$rv,$rv
164
165	sub		%r0,$rv,%r29
166	extru		%r29,0,1,$rv
167L\$no_data
168	bv		($rp)
169	.EXIT
170	nop
171	.PROCEND
172___
173}
174{
175my ($out,$cnt,$max)=("%r26","%r25","%r24");
176my ($tick,$lasttick)=("%r23","%r22");
177my ($diff,$lastdiff)=("%r21","%r20");
178
179$code.=<<___;
180	.EXPORT	OPENSSL_instrument_bus,ENTRY,ARGW0=GR,ARGW1=GR
181	.ALIGN	8
182OPENSSL_instrument_bus
183	.PROC
184	.CALLINFO	NO_CALLS
185	.ENTRY
186	copy		$cnt,$rv
187	mfctl		%cr16,$tick
188	copy		$tick,$lasttick
189	ldi		0,$diff
190
191	fdc		0($out)
192	ldw		0($out),$tick
193	add		$diff,$tick,$tick
194	stw		$tick,0($out)
195L\$oop
196	mfctl		%cr16,$tick
197	sub		$tick,$lasttick,$diff
198	copy		$tick,$lasttick
199
200	fdc		0($out)
201	ldw		0($out),$tick
202	add		$diff,$tick,$tick
203	stw		$tick,0($out)
204
205	addib,<>	-1,$cnt,L\$oop
206	addi		4,$out,$out
207
208	bv		($rp)
209	.EXIT
210	sub		$rv,$cnt,$rv
211	.PROCEND
212
213	.EXPORT	OPENSSL_instrument_bus2,ENTRY,ARGW0=GR,ARGW1=GR
214	.ALIGN	8
215OPENSSL_instrument_bus2
216	.PROC
217	.CALLINFO	NO_CALLS
218	.ENTRY
219	copy		$cnt,$rv
220	sub		%r0,$cnt,$cnt
221
222	mfctl		%cr16,$tick
223	copy		$tick,$lasttick
224	ldi		0,$diff
225
226	fdc		0($out)
227	ldw		0($out),$tick
228	add		$diff,$tick,$tick
229	stw		$tick,0($out)
230
231	mfctl		%cr16,$tick
232	sub		$tick,$lasttick,$diff
233	copy		$tick,$lasttick
234L\$oop2
235	copy		$diff,$lastdiff
236	fdc		0($out)
237	ldw		0($out),$tick
238	add		$diff,$tick,$tick
239	stw		$tick,0($out)
240
241	addib,=		-1,$max,L\$done2
242	nop
243
244	mfctl		%cr16,$tick
245	sub		$tick,$lasttick,$diff
246	copy		$tick,$lasttick
247	cmpclr,<>	$lastdiff,$diff,$tick
248	ldi		1,$tick
249
250	ldi		1,%r1
251	xor		%r1,$tick,$tick
252	addb,<>		$tick,$cnt,L\$oop2
253	shladd,l	$tick,2,$out,$out
254L\$done2
255	bv		($rp)
256	.EXIT
257	add		$rv,$cnt,$rv
258	.PROCEND
259___
260}
261
262if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
263	=~ /GNU assembler/) {
264    $gnuas = 1;
265}
266
267foreach(split("\n",$code)) {
268
269	s/(\.LEVEL\s+2\.0)W/$1w/	if ($gnuas && $SIZE_T==8);
270	s/\.SPACE\s+\$TEXT\$/.text/	if ($gnuas && $SIZE_T==8);
271	s/\.SUBSPA.*//			if ($gnuas && $SIZE_T==8);
272	s/cmpib,\*/comib,/		if ($SIZE_T==4);
273	s/,\*/,/			if ($SIZE_T==4);
274	s/\bbv\b/bve/			if ($SIZE_T==8);
275
276	print $_,"\n";
277}
278close STDOUT or die "error closing STDOUT: $!";
279
280