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{
60my $inp="%r26";
61my $len="%r25";
62
63$code.=<<___;
64	.EXPORT	OPENSSL_cleanse,ENTRY,ARGW0=GR,ARGW1=GR
65	.ALIGN	8
66OPENSSL_cleanse
67	.PROC
68	.CALLINFO	NO_CALLS
69	.ENTRY
70	cmpib,*=	0,$len,L\$done
71	nop
72	cmpib,*>>=	15,$len,L\$ittle
73	ldi		$SIZE_T-1,%r1
74
75L\$align
76	and,*<>		$inp,%r1,%r28
77	b,n		L\$aligned
78	stb		%r0,0($inp)
79	ldo		-1($len),$len
80	b		L\$align
81	ldo		1($inp),$inp
82
83L\$aligned
84	andcm		$len,%r1,%r28
85L\$ot
86	$ST		%r0,0($inp)
87	addib,*<>	-$SIZE_T,%r28,L\$ot
88	ldo		$SIZE_T($inp),$inp
89
90	and,*<>		$len,%r1,$len
91	b,n		L\$done
92L\$ittle
93	stb		%r0,0($inp)
94	addib,*<>	-1,$len,L\$ittle
95	ldo		1($inp),$inp
96L\$done
97	bv		($rp)
98	.EXIT
99	nop
100	.PROCEND
101___
102}
103{
104my ($in1,$in2,$len)=("%r26","%r25","%r24");
105
106$code.=<<___;
107	.EXPORT	CRYPTO_memcmp,ENTRY,ARGW0=GR,ARGW1=GR,ARGW1=GR
108	.ALIGN	8
109CRYPTO_memcmp
110	.PROC
111	.CALLINFO	NO_CALLS
112	.ENTRY
113	cmpib,*=	0,$len,L\$no_data
114	xor		$rv,$rv,$rv
115
116L\$oop_cmp
117	ldb		0($in1),%r19
118	ldb		0($in2),%r20
119	ldo		1($in1),$in1
120	ldo		1($in2),$in2
121	xor		%r19,%r20,%r29
122	addib,*<>	-1,$len,L\$oop_cmp
123	or		%r29,$rv,$rv
124
125	sub		%r0,$rv,%r29
126	extru		%r29,0,1,$rv
127L\$no_data
128	bv		($rp)
129	.EXIT
130	nop
131	.PROCEND
132___
133}
134{
135my ($out,$cnt,$max)=("%r26","%r25","%r24");
136my ($tick,$lasttick)=("%r23","%r22");
137my ($diff,$lastdiff)=("%r21","%r20");
138
139$code.=<<___;
140	.EXPORT	OPENSSL_instrument_bus,ENTRY,ARGW0=GR,ARGW1=GR
141	.ALIGN	8
142OPENSSL_instrument_bus
143	.PROC
144	.CALLINFO	NO_CALLS
145	.ENTRY
146	copy		$cnt,$rv
147	mfctl		%cr16,$tick
148	copy		$tick,$lasttick
149	ldi		0,$diff
150
151	fdc		0($out)
152	ldw		0($out),$tick
153	add		$diff,$tick,$tick
154	stw		$tick,0($out)
155L\$oop
156	mfctl		%cr16,$tick
157	sub		$tick,$lasttick,$diff
158	copy		$tick,$lasttick
159
160	fdc		0($out)
161	ldw		0($out),$tick
162	add		$diff,$tick,$tick
163	stw		$tick,0($out)
164
165	addib,<>	-1,$cnt,L\$oop
166	addi		4,$out,$out
167
168	bv		($rp)
169	.EXIT
170	sub		$rv,$cnt,$rv
171	.PROCEND
172
173	.EXPORT	OPENSSL_instrument_bus2,ENTRY,ARGW0=GR,ARGW1=GR
174	.ALIGN	8
175OPENSSL_instrument_bus2
176	.PROC
177	.CALLINFO	NO_CALLS
178	.ENTRY
179	copy		$cnt,$rv
180	sub		%r0,$cnt,$cnt
181
182	mfctl		%cr16,$tick
183	copy		$tick,$lasttick
184	ldi		0,$diff
185
186	fdc		0($out)
187	ldw		0($out),$tick
188	add		$diff,$tick,$tick
189	stw		$tick,0($out)
190
191	mfctl		%cr16,$tick
192	sub		$tick,$lasttick,$diff
193	copy		$tick,$lasttick
194L\$oop2
195	copy		$diff,$lastdiff
196	fdc		0($out)
197	ldw		0($out),$tick
198	add		$diff,$tick,$tick
199	stw		$tick,0($out)
200
201	addib,=		-1,$max,L\$done2
202	nop
203
204	mfctl		%cr16,$tick
205	sub		$tick,$lasttick,$diff
206	copy		$tick,$lasttick
207	cmpclr,<>	$lastdiff,$diff,$tick
208	ldi		1,$tick
209
210	ldi		1,%r1
211	xor		%r1,$tick,$tick
212	addb,<>		$tick,$cnt,L\$oop2
213	shladd,l	$tick,2,$out,$out
214L\$done2
215	bv		($rp)
216	.EXIT
217	add		$rv,$cnt,$rv
218	.PROCEND
219___
220}
221
222if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
223	=~ /GNU assembler/) {
224    $gnuas = 1;
225}
226
227foreach(split("\n",$code)) {
228
229	s/(\.LEVEL\s+2\.0)W/$1w/	if ($gnuas && $SIZE_T==8);
230	s/\.SPACE\s+\$TEXT\$/.text/	if ($gnuas && $SIZE_T==8);
231	s/\.SUBSPA.*//			if ($gnuas && $SIZE_T==8);
232	s/cmpib,\*/comib,/		if ($SIZE_T==4);
233	s/,\*/,/			if ($SIZE_T==4);
234	s/\bbv\b/bve/			if ($SIZE_T==8);
235
236	print $_,"\n";
237}
238close STDOUT or die "error closing STDOUT: $!";
239
240