1238384Sjkim#!/usr/bin/env perl
2238384Sjkim
3238384Sjkim# ====================================================================
4238384Sjkim# Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
5238384Sjkim# project. The module is, however, dual licensed under OpenSSL and
6238384Sjkim# CRYPTOGAMS licenses depending on where you obtain it. For further
7238384Sjkim# details see http://www.openssl.org/~appro/cryptogams/.
8238384Sjkim# ====================================================================
9238384Sjkim
10238384Sjkim# I let hardware handle unaligned input, except on page boundaries
11238384Sjkim# (see below for details). Otherwise straightforward implementation
12238384Sjkim# with X vector in register bank. The module is big-endian [which is
13238384Sjkim# not big deal as there're no little-endian targets left around].
14238384Sjkim
15238384Sjkim#			sha256		|	sha512
16238384Sjkim# 			-m64	-m32	|	-m64	-m32
17238384Sjkim# --------------------------------------+-----------------------
18238384Sjkim# PPC970,gcc-4.0.0	+50%	+38%	|	+40%	+410%(*)
19238384Sjkim# Power6,xlc-7		+150%	+90%	|	+100%	+430%(*)
20238384Sjkim#
21238384Sjkim# (*)	64-bit code in 32-bit application context, which actually is
22238384Sjkim#	on TODO list. It should be noted that for safe deployment in
23238384Sjkim#	32-bit *mutli-threaded* context asyncronous signals should be
24238384Sjkim#	blocked upon entry to SHA512 block routine. This is because
25238384Sjkim#	32-bit signaling procedure invalidates upper halves of GPRs.
26238384Sjkim#	Context switch procedure preserves them, but not signaling:-(
27238384Sjkim
28238384Sjkim# Second version is true multi-thread safe. Trouble with the original
29238384Sjkim# version was that it was using thread local storage pointer register.
30238384Sjkim# Well, it scrupulously preserved it, but the problem would arise the
31238384Sjkim# moment asynchronous signal was delivered and signal handler would
32238384Sjkim# dereference the TLS pointer. While it's never the case in openssl
33238384Sjkim# application or test suite, we have to respect this scenario and not
34238384Sjkim# use TLS pointer register. Alternative would be to require caller to
35238384Sjkim# block signals prior calling this routine. For the record, in 32-bit
36238384Sjkim# context R2 serves as TLS pointer, while in 64-bit context - R13.
37238384Sjkim
38238384Sjkim$flavour=shift;
39238384Sjkim$output =shift;
40238384Sjkim
41238384Sjkimif ($flavour =~ /64/) {
42238384Sjkim	$SIZE_T=8;
43238384Sjkim	$LRSAVE=2*$SIZE_T;
44238384Sjkim	$STU="stdu";
45238384Sjkim	$UCMP="cmpld";
46238384Sjkim	$SHL="sldi";
47238384Sjkim	$POP="ld";
48238384Sjkim	$PUSH="std";
49238384Sjkim} elsif ($flavour =~ /32/) {
50238384Sjkim	$SIZE_T=4;
51238384Sjkim	$LRSAVE=$SIZE_T;
52238384Sjkim	$STU="stwu";
53238384Sjkim	$UCMP="cmplw";
54238384Sjkim	$SHL="slwi";
55238384Sjkim	$POP="lwz";
56238384Sjkim	$PUSH="stw";
57238384Sjkim} else { die "nonsense $flavour"; }
58238384Sjkim
59238384Sjkim$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
60238384Sjkim( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
61238384Sjkim( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
62238384Sjkimdie "can't locate ppc-xlate.pl";
63238384Sjkim
64238384Sjkimopen STDOUT,"| $^X $xlate $flavour $output" || die "can't call $xlate: $!";
65238384Sjkim
66238384Sjkimif ($output =~ /512/) {
67238384Sjkim	$func="sha512_block_data_order";
68238384Sjkim	$SZ=8;
69238384Sjkim	@Sigma0=(28,34,39);
70238384Sjkim	@Sigma1=(14,18,41);
71238384Sjkim	@sigma0=(1,  8, 7);
72238384Sjkim	@sigma1=(19,61, 6);
73238384Sjkim	$rounds=80;
74238384Sjkim	$LD="ld";
75238384Sjkim	$ST="std";
76238384Sjkim	$ROR="rotrdi";
77238384Sjkim	$SHR="srdi";
78238384Sjkim} else {
79238384Sjkim	$func="sha256_block_data_order";
80238384Sjkim	$SZ=4;
81238384Sjkim	@Sigma0=( 2,13,22);
82238384Sjkim	@Sigma1=( 6,11,25);
83238384Sjkim	@sigma0=( 7,18, 3);
84238384Sjkim	@sigma1=(17,19,10);
85238384Sjkim	$rounds=64;
86238384Sjkim	$LD="lwz";
87238384Sjkim	$ST="stw";
88238384Sjkim	$ROR="rotrwi";
89238384Sjkim	$SHR="srwi";
90238384Sjkim}
91238384Sjkim
92238384Sjkim$FRAME=32*$SIZE_T+16*$SZ;
93238384Sjkim$LOCALS=6*$SIZE_T;
94238384Sjkim
95238384Sjkim$sp ="r1";
96238384Sjkim$toc="r2";
97238384Sjkim$ctx="r3";	# zapped by $a0
98238384Sjkim$inp="r4";	# zapped by $a1
99238384Sjkim$num="r5";	# zapped by $t0
100238384Sjkim
101238384Sjkim$T  ="r0";
102238384Sjkim$a0 ="r3";
103238384Sjkim$a1 ="r4";
104238384Sjkim$t0 ="r5";
105238384Sjkim$t1 ="r6";
106238384Sjkim$Tbl="r7";
107238384Sjkim
108238384Sjkim$A  ="r8";
109238384Sjkim$B  ="r9";
110238384Sjkim$C  ="r10";
111238384Sjkim$D  ="r11";
112238384Sjkim$E  ="r12";
113238384Sjkim$F  ="r13";	$F="r2" if ($SIZE_T==8);# reassigned to exempt TLS pointer
114238384Sjkim$G  ="r14";
115238384Sjkim$H  ="r15";
116238384Sjkim
117238384Sjkim@V=($A,$B,$C,$D,$E,$F,$G,$H);
118238384Sjkim@X=("r16","r17","r18","r19","r20","r21","r22","r23",
119238384Sjkim    "r24","r25","r26","r27","r28","r29","r30","r31");
120238384Sjkim
121238384Sjkim$inp="r31";	# reassigned $inp! aliases with @X[15]
122238384Sjkim
123238384Sjkimsub ROUND_00_15 {
124238384Sjkimmy ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_;
125238384Sjkim$code.=<<___;
126238384Sjkim	$LD	$T,`$i*$SZ`($Tbl)
127238384Sjkim	$ROR	$a0,$e,$Sigma1[0]
128238384Sjkim	$ROR	$a1,$e,$Sigma1[1]
129238384Sjkim	and	$t0,$f,$e
130238384Sjkim	andc	$t1,$g,$e
131238384Sjkim	add	$T,$T,$h
132238384Sjkim	xor	$a0,$a0,$a1
133238384Sjkim	$ROR	$a1,$a1,`$Sigma1[2]-$Sigma1[1]`
134238384Sjkim	or	$t0,$t0,$t1		; Ch(e,f,g)
135238384Sjkim	add	$T,$T,@X[$i]
136238384Sjkim	xor	$a0,$a0,$a1		; Sigma1(e)
137238384Sjkim	add	$T,$T,$t0
138238384Sjkim	add	$T,$T,$a0
139238384Sjkim
140238384Sjkim	$ROR	$a0,$a,$Sigma0[0]
141238384Sjkim	$ROR	$a1,$a,$Sigma0[1]
142238384Sjkim	and	$t0,$a,$b
143238384Sjkim	and	$t1,$a,$c
144238384Sjkim	xor	$a0,$a0,$a1
145238384Sjkim	$ROR	$a1,$a1,`$Sigma0[2]-$Sigma0[1]`
146238384Sjkim	xor	$t0,$t0,$t1
147238384Sjkim	and	$t1,$b,$c
148238384Sjkim	xor	$a0,$a0,$a1		; Sigma0(a)
149238384Sjkim	add	$d,$d,$T
150238384Sjkim	xor	$t0,$t0,$t1		; Maj(a,b,c)
151238384Sjkim	add	$h,$T,$a0
152238384Sjkim	add	$h,$h,$t0
153238384Sjkim
154238384Sjkim___
155238384Sjkim}
156238384Sjkim
157238384Sjkimsub ROUND_16_xx {
158238384Sjkimmy ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_;
159238384Sjkim$i-=16;
160238384Sjkim$code.=<<___;
161238384Sjkim	$ROR	$a0,@X[($i+1)%16],$sigma0[0]
162238384Sjkim	$ROR	$a1,@X[($i+1)%16],$sigma0[1]
163238384Sjkim	$ROR	$t0,@X[($i+14)%16],$sigma1[0]
164238384Sjkim	$ROR	$t1,@X[($i+14)%16],$sigma1[1]
165238384Sjkim	xor	$a0,$a0,$a1
166238384Sjkim	$SHR	$a1,@X[($i+1)%16],$sigma0[2]
167238384Sjkim	xor	$t0,$t0,$t1
168238384Sjkim	$SHR	$t1,@X[($i+14)%16],$sigma1[2]
169238384Sjkim	add	@X[$i],@X[$i],@X[($i+9)%16]
170238384Sjkim	xor	$a0,$a0,$a1		; sigma0(X[(i+1)&0x0f])
171238384Sjkim	xor	$t0,$t0,$t1		; sigma1(X[(i+14)&0x0f])
172238384Sjkim	add	@X[$i],@X[$i],$a0
173238384Sjkim	add	@X[$i],@X[$i],$t0
174238384Sjkim___
175238384Sjkim&ROUND_00_15($i,$a,$b,$c,$d,$e,$f,$g,$h);
176238384Sjkim}
177238384Sjkim
178238384Sjkim$code=<<___;
179238384Sjkim.machine	"any"
180238384Sjkim.text
181238384Sjkim
182238384Sjkim.globl	$func
183238384Sjkim.align	6
184238384Sjkim$func:
185238384Sjkim	$STU	$sp,-$FRAME($sp)
186238384Sjkim	mflr	r0
187238384Sjkim	$SHL	$num,$num,`log(16*$SZ)/log(2)`
188238384Sjkim
189238384Sjkim	$PUSH	$ctx,`$FRAME-$SIZE_T*22`($sp)
190238384Sjkim
191238384Sjkim	$PUSH	$toc,`$FRAME-$SIZE_T*20`($sp)
192238384Sjkim	$PUSH	r13,`$FRAME-$SIZE_T*19`($sp)
193238384Sjkim	$PUSH	r14,`$FRAME-$SIZE_T*18`($sp)
194238384Sjkim	$PUSH	r15,`$FRAME-$SIZE_T*17`($sp)
195238384Sjkim	$PUSH	r16,`$FRAME-$SIZE_T*16`($sp)
196238384Sjkim	$PUSH	r17,`$FRAME-$SIZE_T*15`($sp)
197238384Sjkim	$PUSH	r18,`$FRAME-$SIZE_T*14`($sp)
198238384Sjkim	$PUSH	r19,`$FRAME-$SIZE_T*13`($sp)
199238384Sjkim	$PUSH	r20,`$FRAME-$SIZE_T*12`($sp)
200238384Sjkim	$PUSH	r21,`$FRAME-$SIZE_T*11`($sp)
201238384Sjkim	$PUSH	r22,`$FRAME-$SIZE_T*10`($sp)
202238384Sjkim	$PUSH	r23,`$FRAME-$SIZE_T*9`($sp)
203238384Sjkim	$PUSH	r24,`$FRAME-$SIZE_T*8`($sp)
204238384Sjkim	$PUSH	r25,`$FRAME-$SIZE_T*7`($sp)
205238384Sjkim	$PUSH	r26,`$FRAME-$SIZE_T*6`($sp)
206238384Sjkim	$PUSH	r27,`$FRAME-$SIZE_T*5`($sp)
207238384Sjkim	$PUSH	r28,`$FRAME-$SIZE_T*4`($sp)
208238384Sjkim	$PUSH	r29,`$FRAME-$SIZE_T*3`($sp)
209238384Sjkim	$PUSH	r30,`$FRAME-$SIZE_T*2`($sp)
210238384Sjkim	$PUSH	r31,`$FRAME-$SIZE_T*1`($sp)
211238384Sjkim	$PUSH	r0,`$FRAME+$LRSAVE`($sp)
212238384Sjkim
213238384Sjkim	$LD	$A,`0*$SZ`($ctx)
214238384Sjkim	mr	$inp,r4				; incarnate $inp
215238384Sjkim	$LD	$B,`1*$SZ`($ctx)
216238384Sjkim	$LD	$C,`2*$SZ`($ctx)
217238384Sjkim	$LD	$D,`3*$SZ`($ctx)
218238384Sjkim	$LD	$E,`4*$SZ`($ctx)
219238384Sjkim	$LD	$F,`5*$SZ`($ctx)
220238384Sjkim	$LD	$G,`6*$SZ`($ctx)
221238384Sjkim	$LD	$H,`7*$SZ`($ctx)
222238384Sjkim
223238384Sjkim	bl	LPICmeup
224238384SjkimLPICedup:
225238384Sjkim	andi.	r0,$inp,3
226238384Sjkim	bne	Lunaligned
227238384SjkimLaligned:
228238384Sjkim	add	$num,$inp,$num
229238384Sjkim	$PUSH	$num,`$FRAME-$SIZE_T*24`($sp)	; end pointer
230238384Sjkim	$PUSH	$inp,`$FRAME-$SIZE_T*23`($sp)	; inp pointer
231238384Sjkim	bl	Lsha2_block_private
232238384Sjkim	b	Ldone
233238384Sjkim
234238384Sjkim; PowerPC specification allows an implementation to be ill-behaved
235238384Sjkim; upon unaligned access which crosses page boundary. "Better safe
236238384Sjkim; than sorry" principle makes me treat it specially. But I don't
237238384Sjkim; look for particular offending word, but rather for the input
238238384Sjkim; block which crosses the boundary. Once found that block is aligned
239238384Sjkim; and hashed separately...
240238384Sjkim.align	4
241238384SjkimLunaligned:
242238384Sjkim	subfic	$t1,$inp,4096
243238384Sjkim	andi.	$t1,$t1,`4096-16*$SZ`	; distance to closest page boundary
244238384Sjkim	beq	Lcross_page
245238384Sjkim	$UCMP	$num,$t1
246238384Sjkim	ble-	Laligned		; didn't cross the page boundary
247238384Sjkim	subfc	$num,$t1,$num
248238384Sjkim	add	$t1,$inp,$t1
249238384Sjkim	$PUSH	$num,`$FRAME-$SIZE_T*25`($sp)	; save real remaining num
250238384Sjkim	$PUSH	$t1,`$FRAME-$SIZE_T*24`($sp)	; intermediate end pointer
251238384Sjkim	$PUSH	$inp,`$FRAME-$SIZE_T*23`($sp)	; inp pointer
252238384Sjkim	bl	Lsha2_block_private
253238384Sjkim	; $inp equals to the intermediate end pointer here
254238384Sjkim	$POP	$num,`$FRAME-$SIZE_T*25`($sp)	; restore real remaining num
255238384SjkimLcross_page:
256238384Sjkim	li	$t1,`16*$SZ/4`
257238384Sjkim	mtctr	$t1
258238384Sjkim	addi	r20,$sp,$LOCALS			; aligned spot below the frame
259238384SjkimLmemcpy:
260238384Sjkim	lbz	r16,0($inp)
261238384Sjkim	lbz	r17,1($inp)
262238384Sjkim	lbz	r18,2($inp)
263238384Sjkim	lbz	r19,3($inp)
264238384Sjkim	addi	$inp,$inp,4
265238384Sjkim	stb	r16,0(r20)
266238384Sjkim	stb	r17,1(r20)
267238384Sjkim	stb	r18,2(r20)
268238384Sjkim	stb	r19,3(r20)
269238384Sjkim	addi	r20,r20,4
270238384Sjkim	bdnz	Lmemcpy
271238384Sjkim
272238384Sjkim	$PUSH	$inp,`$FRAME-$SIZE_T*26`($sp)	; save real inp
273238384Sjkim	addi	$t1,$sp,`$LOCALS+16*$SZ`	; fictitious end pointer
274238384Sjkim	addi	$inp,$sp,$LOCALS		; fictitious inp pointer
275238384Sjkim	$PUSH	$num,`$FRAME-$SIZE_T*25`($sp)	; save real num
276238384Sjkim	$PUSH	$t1,`$FRAME-$SIZE_T*24`($sp)	; end pointer
277238384Sjkim	$PUSH	$inp,`$FRAME-$SIZE_T*23`($sp)	; inp pointer
278238384Sjkim	bl	Lsha2_block_private
279238384Sjkim	$POP	$inp,`$FRAME-$SIZE_T*26`($sp)	; restore real inp
280238384Sjkim	$POP	$num,`$FRAME-$SIZE_T*25`($sp)	; restore real num
281238384Sjkim	addic.	$num,$num,`-16*$SZ`		; num--
282238384Sjkim	bne-	Lunaligned
283238384Sjkim
284238384SjkimLdone:
285238384Sjkim	$POP	r0,`$FRAME+$LRSAVE`($sp)
286238384Sjkim	$POP	$toc,`$FRAME-$SIZE_T*20`($sp)
287238384Sjkim	$POP	r13,`$FRAME-$SIZE_T*19`($sp)
288238384Sjkim	$POP	r14,`$FRAME-$SIZE_T*18`($sp)
289238384Sjkim	$POP	r15,`$FRAME-$SIZE_T*17`($sp)
290238384Sjkim	$POP	r16,`$FRAME-$SIZE_T*16`($sp)
291238384Sjkim	$POP	r17,`$FRAME-$SIZE_T*15`($sp)
292238384Sjkim	$POP	r18,`$FRAME-$SIZE_T*14`($sp)
293238384Sjkim	$POP	r19,`$FRAME-$SIZE_T*13`($sp)
294238384Sjkim	$POP	r20,`$FRAME-$SIZE_T*12`($sp)
295238384Sjkim	$POP	r21,`$FRAME-$SIZE_T*11`($sp)
296238384Sjkim	$POP	r22,`$FRAME-$SIZE_T*10`($sp)
297238384Sjkim	$POP	r23,`$FRAME-$SIZE_T*9`($sp)
298238384Sjkim	$POP	r24,`$FRAME-$SIZE_T*8`($sp)
299238384Sjkim	$POP	r25,`$FRAME-$SIZE_T*7`($sp)
300238384Sjkim	$POP	r26,`$FRAME-$SIZE_T*6`($sp)
301238384Sjkim	$POP	r27,`$FRAME-$SIZE_T*5`($sp)
302238384Sjkim	$POP	r28,`$FRAME-$SIZE_T*4`($sp)
303238384Sjkim	$POP	r29,`$FRAME-$SIZE_T*3`($sp)
304238384Sjkim	$POP	r30,`$FRAME-$SIZE_T*2`($sp)
305238384Sjkim	$POP	r31,`$FRAME-$SIZE_T*1`($sp)
306238384Sjkim	mtlr	r0
307238384Sjkim	addi	$sp,$sp,$FRAME
308238384Sjkim	blr
309238384Sjkim	.long	0
310238384Sjkim	.byte	0,12,4,1,0x80,18,3,0
311238384Sjkim	.long	0
312238384Sjkim
313238384Sjkim.align	4
314238384SjkimLsha2_block_private:
315238384Sjkim___
316238384Sjkimfor($i=0;$i<16;$i++) {
317238384Sjkim$code.=<<___ if ($SZ==4);
318238384Sjkim	lwz	@X[$i],`$i*$SZ`($inp)
319238384Sjkim___
320238384Sjkim# 64-bit loads are split to 2x32-bit ones, as CPU can't handle
321238384Sjkim# unaligned 64-bit loads, only 32-bit ones...
322238384Sjkim$code.=<<___ if ($SZ==8);
323238384Sjkim	lwz	$t0,`$i*$SZ`($inp)
324238384Sjkim	lwz	@X[$i],`$i*$SZ+4`($inp)
325238384Sjkim	insrdi	@X[$i],$t0,32,0
326238384Sjkim___
327238384Sjkim	&ROUND_00_15($i,@V);
328238384Sjkim	unshift(@V,pop(@V));
329238384Sjkim}
330238384Sjkim$code.=<<___;
331238384Sjkim	li	$T,`$rounds/16-1`
332238384Sjkim	mtctr	$T
333238384Sjkim.align	4
334238384SjkimLrounds:
335238384Sjkim	addi	$Tbl,$Tbl,`16*$SZ`
336238384Sjkim___
337238384Sjkimfor(;$i<32;$i++) {
338238384Sjkim	&ROUND_16_xx($i,@V);
339238384Sjkim	unshift(@V,pop(@V));
340238384Sjkim}
341238384Sjkim$code.=<<___;
342238384Sjkim	bdnz-	Lrounds
343238384Sjkim
344238384Sjkim	$POP	$ctx,`$FRAME-$SIZE_T*22`($sp)
345238384Sjkim	$POP	$inp,`$FRAME-$SIZE_T*23`($sp)	; inp pointer
346238384Sjkim	$POP	$num,`$FRAME-$SIZE_T*24`($sp)	; end pointer
347238384Sjkim	subi	$Tbl,$Tbl,`($rounds-16)*$SZ`	; rewind Tbl
348238384Sjkim
349238384Sjkim	$LD	r16,`0*$SZ`($ctx)
350238384Sjkim	$LD	r17,`1*$SZ`($ctx)
351238384Sjkim	$LD	r18,`2*$SZ`($ctx)
352238384Sjkim	$LD	r19,`3*$SZ`($ctx)
353238384Sjkim	$LD	r20,`4*$SZ`($ctx)
354238384Sjkim	$LD	r21,`5*$SZ`($ctx)
355238384Sjkim	$LD	r22,`6*$SZ`($ctx)
356238384Sjkim	addi	$inp,$inp,`16*$SZ`		; advance inp
357238384Sjkim	$LD	r23,`7*$SZ`($ctx)
358238384Sjkim	add	$A,$A,r16
359238384Sjkim	add	$B,$B,r17
360238384Sjkim	$PUSH	$inp,`$FRAME-$SIZE_T*23`($sp)
361238384Sjkim	add	$C,$C,r18
362238384Sjkim	$ST	$A,`0*$SZ`($ctx)
363238384Sjkim	add	$D,$D,r19
364238384Sjkim	$ST	$B,`1*$SZ`($ctx)
365238384Sjkim	add	$E,$E,r20
366238384Sjkim	$ST	$C,`2*$SZ`($ctx)
367238384Sjkim	add	$F,$F,r21
368238384Sjkim	$ST	$D,`3*$SZ`($ctx)
369238384Sjkim	add	$G,$G,r22
370238384Sjkim	$ST	$E,`4*$SZ`($ctx)
371238384Sjkim	add	$H,$H,r23
372238384Sjkim	$ST	$F,`5*$SZ`($ctx)
373238384Sjkim	$ST	$G,`6*$SZ`($ctx)
374238384Sjkim	$UCMP	$inp,$num
375238384Sjkim	$ST	$H,`7*$SZ`($ctx)
376238384Sjkim	bne	Lsha2_block_private
377238384Sjkim	blr
378238384Sjkim	.long	0
379238384Sjkim	.byte	0,12,0x14,0,0,0,0,0
380238384Sjkim___
381238384Sjkim
382238384Sjkim# Ugly hack here, because PPC assembler syntax seem to vary too
383238384Sjkim# much from platforms to platform...
384238384Sjkim$code.=<<___;
385238384Sjkim.align	6
386238384SjkimLPICmeup:
387238384Sjkim	mflr	r0
388238384Sjkim	bcl	20,31,\$+4
389238384Sjkim	mflr	$Tbl	; vvvvvv "distance" between . and 1st data entry
390238384Sjkim	addi	$Tbl,$Tbl,`64-8`
391238384Sjkim	mtlr	r0
392238384Sjkim	blr
393238384Sjkim	.long	0
394238384Sjkim	.byte	0,12,0x14,0,0,0,0,0
395238384Sjkim	.space	`64-9*4`
396238384Sjkim___
397238384Sjkim$code.=<<___ if ($SZ==8);
398238384Sjkim	.long	0x428a2f98,0xd728ae22,0x71374491,0x23ef65cd
399238384Sjkim	.long	0xb5c0fbcf,0xec4d3b2f,0xe9b5dba5,0x8189dbbc
400238384Sjkim	.long	0x3956c25b,0xf348b538,0x59f111f1,0xb605d019
401238384Sjkim	.long	0x923f82a4,0xaf194f9b,0xab1c5ed5,0xda6d8118
402238384Sjkim	.long	0xd807aa98,0xa3030242,0x12835b01,0x45706fbe
403238384Sjkim	.long	0x243185be,0x4ee4b28c,0x550c7dc3,0xd5ffb4e2
404238384Sjkim	.long	0x72be5d74,0xf27b896f,0x80deb1fe,0x3b1696b1
405238384Sjkim	.long	0x9bdc06a7,0x25c71235,0xc19bf174,0xcf692694
406238384Sjkim	.long	0xe49b69c1,0x9ef14ad2,0xefbe4786,0x384f25e3
407238384Sjkim	.long	0x0fc19dc6,0x8b8cd5b5,0x240ca1cc,0x77ac9c65
408238384Sjkim	.long	0x2de92c6f,0x592b0275,0x4a7484aa,0x6ea6e483
409238384Sjkim	.long	0x5cb0a9dc,0xbd41fbd4,0x76f988da,0x831153b5
410238384Sjkim	.long	0x983e5152,0xee66dfab,0xa831c66d,0x2db43210
411238384Sjkim	.long	0xb00327c8,0x98fb213f,0xbf597fc7,0xbeef0ee4
412238384Sjkim	.long	0xc6e00bf3,0x3da88fc2,0xd5a79147,0x930aa725
413238384Sjkim	.long	0x06ca6351,0xe003826f,0x14292967,0x0a0e6e70
414238384Sjkim	.long	0x27b70a85,0x46d22ffc,0x2e1b2138,0x5c26c926
415238384Sjkim	.long	0x4d2c6dfc,0x5ac42aed,0x53380d13,0x9d95b3df
416238384Sjkim	.long	0x650a7354,0x8baf63de,0x766a0abb,0x3c77b2a8
417238384Sjkim	.long	0x81c2c92e,0x47edaee6,0x92722c85,0x1482353b
418238384Sjkim	.long	0xa2bfe8a1,0x4cf10364,0xa81a664b,0xbc423001
419238384Sjkim	.long	0xc24b8b70,0xd0f89791,0xc76c51a3,0x0654be30
420238384Sjkim	.long	0xd192e819,0xd6ef5218,0xd6990624,0x5565a910
421238384Sjkim	.long	0xf40e3585,0x5771202a,0x106aa070,0x32bbd1b8
422238384Sjkim	.long	0x19a4c116,0xb8d2d0c8,0x1e376c08,0x5141ab53
423238384Sjkim	.long	0x2748774c,0xdf8eeb99,0x34b0bcb5,0xe19b48a8
424238384Sjkim	.long	0x391c0cb3,0xc5c95a63,0x4ed8aa4a,0xe3418acb
425238384Sjkim	.long	0x5b9cca4f,0x7763e373,0x682e6ff3,0xd6b2b8a3
426238384Sjkim	.long	0x748f82ee,0x5defb2fc,0x78a5636f,0x43172f60
427238384Sjkim	.long	0x84c87814,0xa1f0ab72,0x8cc70208,0x1a6439ec
428238384Sjkim	.long	0x90befffa,0x23631e28,0xa4506ceb,0xde82bde9
429238384Sjkim	.long	0xbef9a3f7,0xb2c67915,0xc67178f2,0xe372532b
430238384Sjkim	.long	0xca273ece,0xea26619c,0xd186b8c7,0x21c0c207
431238384Sjkim	.long	0xeada7dd6,0xcde0eb1e,0xf57d4f7f,0xee6ed178
432238384Sjkim	.long	0x06f067aa,0x72176fba,0x0a637dc5,0xa2c898a6
433238384Sjkim	.long	0x113f9804,0xbef90dae,0x1b710b35,0x131c471b
434238384Sjkim	.long	0x28db77f5,0x23047d84,0x32caab7b,0x40c72493
435238384Sjkim	.long	0x3c9ebe0a,0x15c9bebc,0x431d67c4,0x9c100d4c
436238384Sjkim	.long	0x4cc5d4be,0xcb3e42b6,0x597f299c,0xfc657e2a
437238384Sjkim	.long	0x5fcb6fab,0x3ad6faec,0x6c44198c,0x4a475817
438238384Sjkim___
439238384Sjkim$code.=<<___ if ($SZ==4);
440238384Sjkim	.long	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
441238384Sjkim	.long	0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
442238384Sjkim	.long	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
443238384Sjkim	.long	0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
444238384Sjkim	.long	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
445238384Sjkim	.long	0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
446238384Sjkim	.long	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
447238384Sjkim	.long	0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
448238384Sjkim	.long	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
449238384Sjkim	.long	0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
450238384Sjkim	.long	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
451238384Sjkim	.long	0xd192e819,0xd6990624,0xf40e3585,0x106aa070
452238384Sjkim	.long	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
453238384Sjkim	.long	0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
454238384Sjkim	.long	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
455238384Sjkim	.long	0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
456238384Sjkim___
457238384Sjkim
458238384Sjkim$code =~ s/\`([^\`]*)\`/eval $1/gem;
459238384Sjkimprint $code;
460238384Sjkimclose STDOUT;
461