More testing for sign/verify through `dgst` and `pkeyutl`
[openssl.git] / crypto / sha / asm / sha512-parisc.pl
1 #! /usr/bin/env perl
2 # Copyright 2009-2018 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 # ====================================================================
11 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
12 # project. The module is, however, dual licensed under OpenSSL and
13 # CRYPTOGAMS licenses depending on where you obtain it. For further
14 # details see http://www.openssl.org/~appro/cryptogams/.
15 # ====================================================================
16
17 # SHA256/512 block procedure for PA-RISC.
18
19 # June 2009.
20 #
21 # SHA256 performance is >75% better than gcc 3.2 generated code on
22 # PA-7100LC. Compared to code generated by vendor compiler this
23 # implementation is almost 70% faster in 64-bit build, but delivers
24 # virtually same performance in 32-bit build on PA-8600.
25 #
26 # SHA512 performance is >2.9x better than gcc 3.2 generated code on
27 # PA-7100LC, PA-RISC 1.1 processor. Then implementation detects if the
28 # code is executed on PA-RISC 2.0 processor and switches to 64-bit
29 # code path delivering adequate performance even in "blended" 32-bit
30 # build. Though 64-bit code is not any faster than code generated by
31 # vendor compiler on PA-8600...
32 #
33 # Special thanks to polarhome.com for providing HP-UX account.
34
35 # $output is the last argument if it looks like a file (it has an extension)
36 # $flavour is the first argument if it doesn't look like a file
37 $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
38 $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
39
40 $output and open STDOUT,">$output";
41
42 if ($flavour =~ /64/) {
43         $LEVEL          ="2.0W";
44         $SIZE_T         =8;
45         $FRAME_MARKER   =80;
46         $SAVED_RP       =16;
47         $PUSH           ="std";
48         $PUSHMA         ="std,ma";
49         $POP            ="ldd";
50         $POPMB          ="ldd,mb";
51 } else {
52         $LEVEL          ="1.0";
53         $SIZE_T         =4;
54         $FRAME_MARKER   =48;
55         $SAVED_RP       =20;
56         $PUSH           ="stw";
57         $PUSHMA         ="stwm";
58         $POP            ="ldw";
59         $POPMB          ="ldwm";
60 }
61
62 if ($output =~ /512/) {
63         $func="sha512_block_data_order";
64         $SZ=8;
65         @Sigma0=(28,34,39);
66         @Sigma1=(14,18,41);
67         @sigma0=(1,  8, 7);
68         @sigma1=(19,61, 6);
69         $rounds=80;
70         $LAST10BITS=0x017;
71         $LD="ldd";
72         $LDM="ldd,ma";
73         $ST="std";
74 } else {
75         $func="sha256_block_data_order";
76         $SZ=4;
77         @Sigma0=( 2,13,22);
78         @Sigma1=( 6,11,25);
79         @sigma0=( 7,18, 3);
80         @sigma1=(17,19,10);
81         $rounds=64;
82         $LAST10BITS=0x0f2;
83         $LD="ldw";
84         $LDM="ldwm";
85         $ST="stw";
86 }
87
88 $FRAME=16*$SIZE_T+$FRAME_MARKER;# 16 saved regs + frame marker
89                                 #                 [+ argument transfer]
90 $XOFF=16*$SZ+32;                # local variables
91 $FRAME+=$XOFF;
92 $XOFF+=$FRAME_MARKER;           # distance between %sp and local variables
93
94 $ctx="%r26";    # zapped by $a0
95 $inp="%r25";    # zapped by $a1
96 $num="%r24";    # zapped by $t0
97
98 $a0 ="%r26";
99 $a1 ="%r25";
100 $t0 ="%r24";
101 $t1 ="%r29";
102 $Tbl="%r31";
103
104 @V=($A,$B,$C,$D,$E,$F,$G,$H)=("%r17","%r18","%r19","%r20","%r21","%r22","%r23","%r28");
105
106 @X=("%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", "%r8",
107     "%r9", "%r10","%r11","%r12","%r13","%r14","%r15","%r16",$inp);
108
109 sub ROUND_00_15 {
110 my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_;
111 $code.=<<___;
112         _ror    $e,$Sigma1[0],$a0
113         and     $f,$e,$t0
114         _ror    $e,$Sigma1[1],$a1
115         addl    $t1,$h,$h
116         andcm   $g,$e,$t1
117         xor     $a1,$a0,$a0
118         _ror    $a1,`$Sigma1[2]-$Sigma1[1]`,$a1
119         or      $t0,$t1,$t1             ; Ch(e,f,g)
120         addl    @X[$i%16],$h,$h
121         xor     $a0,$a1,$a1             ; Sigma1(e)
122         addl    $t1,$h,$h
123         _ror    $a,$Sigma0[0],$a0
124         addl    $a1,$h,$h
125
126         _ror    $a,$Sigma0[1],$a1
127         and     $a,$b,$t0
128         and     $a,$c,$t1
129         xor     $a1,$a0,$a0
130         _ror    $a1,`$Sigma0[2]-$Sigma0[1]`,$a1
131         xor     $t1,$t0,$t0
132         and     $b,$c,$t1
133         xor     $a0,$a1,$a1             ; Sigma0(a)
134         addl    $h,$d,$d
135         xor     $t1,$t0,$t0             ; Maj(a,b,c)
136         `"$LDM  $SZ($Tbl),$t1" if ($i<15)`
137         addl    $a1,$h,$h
138         addl    $t0,$h,$h
139
140 ___
141 }
142
143 sub ROUND_16_xx {
144 my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_;
145 $i-=16;
146 $code.=<<___;
147         _ror    @X[($i+1)%16],$sigma0[0],$a0
148         _ror    @X[($i+1)%16],$sigma0[1],$a1
149         addl    @X[($i+9)%16],@X[$i],@X[$i]
150         _ror    @X[($i+14)%16],$sigma1[0],$t0
151         _ror    @X[($i+14)%16],$sigma1[1],$t1
152         xor     $a1,$a0,$a0
153         _shr    @X[($i+1)%16],$sigma0[2],$a1
154         xor     $t1,$t0,$t0
155         _shr    @X[($i+14)%16],$sigma1[2],$t1
156         xor     $a1,$a0,$a0             ; sigma0(X[(i+1)&0x0f])
157         xor     $t1,$t0,$t0             ; sigma1(X[(i+14)&0x0f])
158         $LDM    $SZ($Tbl),$t1
159         addl    $a0,@X[$i],@X[$i]
160         addl    $t0,@X[$i],@X[$i]
161 ___
162 $code.=<<___ if ($i==15);
163         extru   $t1,31,10,$a1
164         comiclr,<> $LAST10BITS,$a1,%r0
165         ldo     1($Tbl),$Tbl            ; signal end of $Tbl
166 ___
167 &ROUND_00_15($i+16,$a,$b,$c,$d,$e,$f,$g,$h);
168 }
169
170 $code=<<___;
171         .LEVEL  $LEVEL
172         .SPACE  \$TEXT\$
173         .SUBSPA \$CODE\$,QUAD=0,ALIGN=8,ACCESS=0x2C,CODE_ONLY
174
175         .ALIGN  64
176 L\$table
177 ___
178 $code.=<<___ if ($SZ==8);
179         .WORD   0x428a2f98,0xd728ae22,0x71374491,0x23ef65cd
180         .WORD   0xb5c0fbcf,0xec4d3b2f,0xe9b5dba5,0x8189dbbc
181         .WORD   0x3956c25b,0xf348b538,0x59f111f1,0xb605d019
182         .WORD   0x923f82a4,0xaf194f9b,0xab1c5ed5,0xda6d8118
183         .WORD   0xd807aa98,0xa3030242,0x12835b01,0x45706fbe
184         .WORD   0x243185be,0x4ee4b28c,0x550c7dc3,0xd5ffb4e2
185         .WORD   0x72be5d74,0xf27b896f,0x80deb1fe,0x3b1696b1
186         .WORD   0x9bdc06a7,0x25c71235,0xc19bf174,0xcf692694
187         .WORD   0xe49b69c1,0x9ef14ad2,0xefbe4786,0x384f25e3
188         .WORD   0x0fc19dc6,0x8b8cd5b5,0x240ca1cc,0x77ac9c65
189         .WORD   0x2de92c6f,0x592b0275,0x4a7484aa,0x6ea6e483
190         .WORD   0x5cb0a9dc,0xbd41fbd4,0x76f988da,0x831153b5
191         .WORD   0x983e5152,0xee66dfab,0xa831c66d,0x2db43210
192         .WORD   0xb00327c8,0x98fb213f,0xbf597fc7,0xbeef0ee4
193         .WORD   0xc6e00bf3,0x3da88fc2,0xd5a79147,0x930aa725
194         .WORD   0x06ca6351,0xe003826f,0x14292967,0x0a0e6e70
195         .WORD   0x27b70a85,0x46d22ffc,0x2e1b2138,0x5c26c926
196         .WORD   0x4d2c6dfc,0x5ac42aed,0x53380d13,0x9d95b3df
197         .WORD   0x650a7354,0x8baf63de,0x766a0abb,0x3c77b2a8
198         .WORD   0x81c2c92e,0x47edaee6,0x92722c85,0x1482353b
199         .WORD   0xa2bfe8a1,0x4cf10364,0xa81a664b,0xbc423001
200         .WORD   0xc24b8b70,0xd0f89791,0xc76c51a3,0x0654be30
201         .WORD   0xd192e819,0xd6ef5218,0xd6990624,0x5565a910
202         .WORD   0xf40e3585,0x5771202a,0x106aa070,0x32bbd1b8
203         .WORD   0x19a4c116,0xb8d2d0c8,0x1e376c08,0x5141ab53
204         .WORD   0x2748774c,0xdf8eeb99,0x34b0bcb5,0xe19b48a8
205         .WORD   0x391c0cb3,0xc5c95a63,0x4ed8aa4a,0xe3418acb
206         .WORD   0x5b9cca4f,0x7763e373,0x682e6ff3,0xd6b2b8a3
207         .WORD   0x748f82ee,0x5defb2fc,0x78a5636f,0x43172f60
208         .WORD   0x84c87814,0xa1f0ab72,0x8cc70208,0x1a6439ec
209         .WORD   0x90befffa,0x23631e28,0xa4506ceb,0xde82bde9
210         .WORD   0xbef9a3f7,0xb2c67915,0xc67178f2,0xe372532b
211         .WORD   0xca273ece,0xea26619c,0xd186b8c7,0x21c0c207
212         .WORD   0xeada7dd6,0xcde0eb1e,0xf57d4f7f,0xee6ed178
213         .WORD   0x06f067aa,0x72176fba,0x0a637dc5,0xa2c898a6
214         .WORD   0x113f9804,0xbef90dae,0x1b710b35,0x131c471b
215         .WORD   0x28db77f5,0x23047d84,0x32caab7b,0x40c72493
216         .WORD   0x3c9ebe0a,0x15c9bebc,0x431d67c4,0x9c100d4c
217         .WORD   0x4cc5d4be,0xcb3e42b6,0x597f299c,0xfc657e2a
218         .WORD   0x5fcb6fab,0x3ad6faec,0x6c44198c,0x4a475817
219 ___
220 $code.=<<___ if ($SZ==4);
221         .WORD   0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
222         .WORD   0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
223         .WORD   0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
224         .WORD   0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
225         .WORD   0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
226         .WORD   0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
227         .WORD   0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
228         .WORD   0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
229         .WORD   0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
230         .WORD   0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
231         .WORD   0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
232         .WORD   0xd192e819,0xd6990624,0xf40e3585,0x106aa070
233         .WORD   0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
234         .WORD   0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
235         .WORD   0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
236         .WORD   0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
237 ___
238 $code.=<<___;
239
240         .EXPORT $func,ENTRY,ARGW0=GR,ARGW1=GR,ARGW2=GR
241         .ALIGN  64
242 $func
243         .PROC
244         .CALLINFO       FRAME=`$FRAME-16*$SIZE_T`,NO_CALLS,SAVE_RP,ENTRY_GR=18
245         .ENTRY
246         $PUSH   %r2,-$SAVED_RP(%sp)     ; standard prologue
247         $PUSHMA %r3,$FRAME(%sp)
248         $PUSH   %r4,`-$FRAME+1*$SIZE_T`(%sp)
249         $PUSH   %r5,`-$FRAME+2*$SIZE_T`(%sp)
250         $PUSH   %r6,`-$FRAME+3*$SIZE_T`(%sp)
251         $PUSH   %r7,`-$FRAME+4*$SIZE_T`(%sp)
252         $PUSH   %r8,`-$FRAME+5*$SIZE_T`(%sp)
253         $PUSH   %r9,`-$FRAME+6*$SIZE_T`(%sp)
254         $PUSH   %r10,`-$FRAME+7*$SIZE_T`(%sp)
255         $PUSH   %r11,`-$FRAME+8*$SIZE_T`(%sp)
256         $PUSH   %r12,`-$FRAME+9*$SIZE_T`(%sp)
257         $PUSH   %r13,`-$FRAME+10*$SIZE_T`(%sp)
258         $PUSH   %r14,`-$FRAME+11*$SIZE_T`(%sp)
259         $PUSH   %r15,`-$FRAME+12*$SIZE_T`(%sp)
260         $PUSH   %r16,`-$FRAME+13*$SIZE_T`(%sp)
261         $PUSH   %r17,`-$FRAME+14*$SIZE_T`(%sp)
262         $PUSH   %r18,`-$FRAME+15*$SIZE_T`(%sp)
263
264         _shl    $num,`log(16*$SZ)/log(2)`,$num
265         addl    $inp,$num,$num          ; $num to point at the end of $inp
266
267         $PUSH   $num,`-$FRAME_MARKER-4*$SIZE_T`(%sp)    ; save arguments
268         $PUSH   $inp,`-$FRAME_MARKER-3*$SIZE_T`(%sp)
269         $PUSH   $ctx,`-$FRAME_MARKER-2*$SIZE_T`(%sp)
270
271         blr     %r0,$Tbl
272         ldi     3,$t1
273 L\$pic
274         andcm   $Tbl,$t1,$Tbl           ; wipe privilege level
275         ldo     L\$table-L\$pic($Tbl),$Tbl
276 ___
277 $code.=<<___ if ($SZ==8 && $SIZE_T==4);
278         ldi     31,$t1
279         mtctl   $t1,%cr11
280         extrd,u,*= $t1,%sar,1,$t1       ; executes on PA-RISC 1.0
281         b       L\$parisc1
282         nop
283 ___
284 $code.=<<___;
285         $LD     `0*$SZ`($ctx),$A        ; load context
286         $LD     `1*$SZ`($ctx),$B
287         $LD     `2*$SZ`($ctx),$C
288         $LD     `3*$SZ`($ctx),$D
289         $LD     `4*$SZ`($ctx),$E
290         $LD     `5*$SZ`($ctx),$F
291         $LD     `6*$SZ`($ctx),$G
292         $LD     `7*$SZ`($ctx),$H
293
294         extru   $inp,31,`log($SZ)/log(2)`,$t0
295         sh3addl $t0,%r0,$t0
296         subi    `8*$SZ`,$t0,$t0
297         mtctl   $t0,%cr11               ; load %sar with align factor
298
299 L\$oop
300         ldi     `$SZ-1`,$t0
301         $LDM    $SZ($Tbl),$t1
302         andcm   $inp,$t0,$t0            ; align $inp
303 ___
304         for ($i=0;$i<15;$i++) {         # load input block
305         $code.="\t$LD   `$SZ*$i`($t0),@X[$i]\n";                }
306 $code.=<<___;
307         cmpb,*= $inp,$t0,L\$aligned
308         $LD     `$SZ*15`($t0),@X[15]
309         $LD     `$SZ*16`($t0),@X[16]
310 ___
311         for ($i=0;$i<16;$i++) {         # align data
312         $code.="\t_align        @X[$i],@X[$i+1],@X[$i]\n";      }
313 $code.=<<___;
314 L\$aligned
315         nop     ; otherwise /usr/ccs/bin/as is confused by below .WORD
316 ___
317
318 for($i=0;$i<16;$i++)    { &ROUND_00_15($i,@V); unshift(@V,pop(@V)); }
319 $code.=<<___;
320 L\$rounds
321         nop     ; otherwise /usr/ccs/bin/as is confused by below .WORD
322 ___
323 for(;$i<32;$i++)        { &ROUND_16_xx($i,@V); unshift(@V,pop(@V)); }
324 $code.=<<___;
325         bb,>=   $Tbl,31,L\$rounds       ; end of $Tbl signalled?
326         nop
327
328         $POP    `-$FRAME_MARKER-2*$SIZE_T`(%sp),$ctx    ; restore arguments
329         $POP    `-$FRAME_MARKER-3*$SIZE_T`(%sp),$inp
330         $POP    `-$FRAME_MARKER-4*$SIZE_T`(%sp),$num
331         ldo     `-$rounds*$SZ-1`($Tbl),$Tbl             ; rewind $Tbl
332
333         $LD     `0*$SZ`($ctx),@X[0]     ; load context
334         $LD     `1*$SZ`($ctx),@X[1]
335         $LD     `2*$SZ`($ctx),@X[2]
336         $LD     `3*$SZ`($ctx),@X[3]
337         $LD     `4*$SZ`($ctx),@X[4]
338         $LD     `5*$SZ`($ctx),@X[5]
339         addl    @X[0],$A,$A
340         $LD     `6*$SZ`($ctx),@X[6]
341         addl    @X[1],$B,$B
342         $LD     `7*$SZ`($ctx),@X[7]
343         ldo     `16*$SZ`($inp),$inp     ; advance $inp
344
345         $ST     $A,`0*$SZ`($ctx)        ; save context
346         addl    @X[2],$C,$C
347         $ST     $B,`1*$SZ`($ctx)
348         addl    @X[3],$D,$D
349         $ST     $C,`2*$SZ`($ctx)
350         addl    @X[4],$E,$E
351         $ST     $D,`3*$SZ`($ctx)
352         addl    @X[5],$F,$F
353         $ST     $E,`4*$SZ`($ctx)
354         addl    @X[6],$G,$G
355         $ST     $F,`5*$SZ`($ctx)
356         addl    @X[7],$H,$H
357         $ST     $G,`6*$SZ`($ctx)
358         $ST     $H,`7*$SZ`($ctx)
359
360         cmpb,*<>,n $inp,$num,L\$oop
361         $PUSH   $inp,`-$FRAME_MARKER-3*$SIZE_T`(%sp)    ; save $inp
362 ___
363 if ($SZ==8 && $SIZE_T==4)       # SHA512 for 32-bit PA-RISC 1.0
364 {{
365 $code.=<<___;
366         b       L\$done
367         nop
368
369         .ALIGN  64
370 L\$parisc1
371 ___
372
373 @V=(  $Ahi,  $Alo,  $Bhi,  $Blo,  $Chi,  $Clo,  $Dhi,  $Dlo,
374       $Ehi,  $Elo,  $Fhi,  $Flo,  $Ghi,  $Glo,  $Hhi,  $Hlo) =
375    ( "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", "%r8",
376      "%r9","%r10","%r11","%r12","%r13","%r14","%r15","%r16");
377 $a0 ="%r17";
378 $a1 ="%r18";
379 $a2 ="%r19";
380 $a3 ="%r20";
381 $t0 ="%r21";
382 $t1 ="%r22";
383 $t2 ="%r28";
384 $t3 ="%r29";
385 $Tbl="%r31";
386
387 @X=("%r23","%r24","%r25","%r26");       # zaps $num,$inp,$ctx
388
389 sub ROUND_00_15_pa1 {
390 my ($i,$ahi,$alo,$bhi,$blo,$chi,$clo,$dhi,$dlo,
391        $ehi,$elo,$fhi,$flo,$ghi,$glo,$hhi,$hlo,$flag)=@_;
392 my ($Xhi,$Xlo,$Xnhi,$Xnlo) = @X;
393
394 $code.=<<___ if (!$flag);
395         ldw     `-$XOFF+8*(($i+1)%16)`(%sp),$Xnhi
396         ldw     `-$XOFF+8*(($i+1)%16)+4`(%sp),$Xnlo     ; load X[i+1]
397 ___
398 $code.=<<___;
399         shd     $ehi,$elo,$Sigma1[0],$t0
400          add    $Xlo,$hlo,$hlo
401         shd     $elo,$ehi,$Sigma1[0],$t1
402          addc   $Xhi,$hhi,$hhi          ; h += X[i]
403         shd     $ehi,$elo,$Sigma1[1],$t2
404          ldwm   8($Tbl),$Xhi
405         shd     $elo,$ehi,$Sigma1[1],$t3
406          ldw    -4($Tbl),$Xlo           ; load K[i]
407         xor     $t2,$t0,$t0
408         xor     $t3,$t1,$t1
409          and    $flo,$elo,$a0
410          and    $fhi,$ehi,$a1
411         shd     $ehi,$elo,$Sigma1[2],$t2
412          andcm  $glo,$elo,$a2
413         shd     $elo,$ehi,$Sigma1[2],$t3
414          andcm  $ghi,$ehi,$a3
415         xor     $t2,$t0,$t0
416         xor     $t3,$t1,$t1             ; Sigma1(e)
417         add     $Xlo,$hlo,$hlo
418          xor    $a2,$a0,$a0
419         addc    $Xhi,$hhi,$hhi          ; h += K[i]
420          xor    $a3,$a1,$a1             ; Ch(e,f,g)
421
422          add    $t0,$hlo,$hlo
423         shd     $ahi,$alo,$Sigma0[0],$t0
424          addc   $t1,$hhi,$hhi           ; h += Sigma1(e)
425         shd     $alo,$ahi,$Sigma0[0],$t1
426          add    $a0,$hlo,$hlo
427         shd     $ahi,$alo,$Sigma0[1],$t2
428          addc   $a1,$hhi,$hhi           ; h += Ch(e,f,g)
429         shd     $alo,$ahi,$Sigma0[1],$t3
430
431         xor     $t2,$t0,$t0
432         xor     $t3,$t1,$t1
433         shd     $ahi,$alo,$Sigma0[2],$t2
434         and     $alo,$blo,$a0
435         shd     $alo,$ahi,$Sigma0[2],$t3
436         and     $ahi,$bhi,$a1
437         xor     $t2,$t0,$t0
438         xor     $t3,$t1,$t1             ; Sigma0(a)
439
440         and     $alo,$clo,$a2
441         and     $ahi,$chi,$a3
442         xor     $a2,$a0,$a0
443          add    $hlo,$dlo,$dlo
444         xor     $a3,$a1,$a1
445          addc   $hhi,$dhi,$dhi          ; d += h
446         and     $blo,$clo,$a2
447          add    $t0,$hlo,$hlo
448         and     $bhi,$chi,$a3
449          addc   $t1,$hhi,$hhi           ; h += Sigma0(a)
450         xor     $a2,$a0,$a0
451          add    $a0,$hlo,$hlo
452         xor     $a3,$a1,$a1             ; Maj(a,b,c)
453          addc   $a1,$hhi,$hhi           ; h += Maj(a,b,c)
454
455 ___
456 $code.=<<___ if ($i==15 && $flag);
457         extru   $Xlo,31,10,$Xlo
458         comiclr,= $LAST10BITS,$Xlo,%r0
459         b       L\$rounds_pa1
460         nop
461 ___
462 push(@X,shift(@X)); push(@X,shift(@X));
463 }
464
465 sub ROUND_16_xx_pa1 {
466 my ($Xhi,$Xlo,$Xnhi,$Xnlo) = @X;
467 my ($i)=shift;
468 $i-=16;
469 $code.=<<___;
470         ldw     `-$XOFF+8*(($i+1)%16)`(%sp),$Xnhi
471         ldw     `-$XOFF+8*(($i+1)%16)+4`(%sp),$Xnlo     ; load X[i+1]
472         ldw     `-$XOFF+8*(($i+9)%16)`(%sp),$a1
473         ldw     `-$XOFF+8*(($i+9)%16)+4`(%sp),$a0       ; load X[i+9]
474         ldw     `-$XOFF+8*(($i+14)%16)`(%sp),$a3
475         ldw     `-$XOFF+8*(($i+14)%16)+4`(%sp),$a2      ; load X[i+14]
476         shd     $Xnhi,$Xnlo,$sigma0[0],$t0
477         shd     $Xnlo,$Xnhi,$sigma0[0],$t1
478          add    $a0,$Xlo,$Xlo
479         shd     $Xnhi,$Xnlo,$sigma0[1],$t2
480          addc   $a1,$Xhi,$Xhi
481         shd     $Xnlo,$Xnhi,$sigma0[1],$t3
482         xor     $t2,$t0,$t0
483         shd     $Xnhi,$Xnlo,$sigma0[2],$t2
484         xor     $t3,$t1,$t1
485         extru   $Xnhi,`31-$sigma0[2]`,`32-$sigma0[2]`,$t3
486         xor     $t2,$t0,$t0
487          shd    $a3,$a2,$sigma1[0],$a0
488         xor     $t3,$t1,$t1             ; sigma0(X[i+1)&0x0f])
489          shd    $a2,$a3,$sigma1[0],$a1
490         add     $t0,$Xlo,$Xlo
491          shd    $a3,$a2,$sigma1[1],$t2
492         addc    $t1,$Xhi,$Xhi
493          shd    $a2,$a3,$sigma1[1],$t3
494         xor     $t2,$a0,$a0
495         shd     $a3,$a2,$sigma1[2],$t2
496         xor     $t3,$a1,$a1
497         extru   $a3,`31-$sigma1[2]`,`32-$sigma1[2]`,$t3
498         xor     $t2,$a0,$a0
499         xor     $t3,$a1,$a1             ; sigma0(X[i+14)&0x0f])
500         add     $a0,$Xlo,$Xlo
501         addc    $a1,$Xhi,$Xhi
502
503         stw     $Xhi,`-$XOFF+8*($i%16)`(%sp)
504         stw     $Xlo,`-$XOFF+8*($i%16)+4`(%sp)
505 ___
506 &ROUND_00_15_pa1($i,@_,1);
507 }
508 $code.=<<___;
509         ldw     `0*4`($ctx),$Ahi                ; load context
510         ldw     `1*4`($ctx),$Alo
511         ldw     `2*4`($ctx),$Bhi
512         ldw     `3*4`($ctx),$Blo
513         ldw     `4*4`($ctx),$Chi
514         ldw     `5*4`($ctx),$Clo
515         ldw     `6*4`($ctx),$Dhi
516         ldw     `7*4`($ctx),$Dlo
517         ldw     `8*4`($ctx),$Ehi
518         ldw     `9*4`($ctx),$Elo
519         ldw     `10*4`($ctx),$Fhi
520         ldw     `11*4`($ctx),$Flo
521         ldw     `12*4`($ctx),$Ghi
522         ldw     `13*4`($ctx),$Glo
523         ldw     `14*4`($ctx),$Hhi
524         ldw     `15*4`($ctx),$Hlo
525
526         extru   $inp,31,2,$t0
527         sh3addl $t0,%r0,$t0
528         subi    32,$t0,$t0
529         mtctl   $t0,%cr11               ; load %sar with align factor
530
531 L\$oop_pa1
532         extru   $inp,31,2,$a3
533         comib,= 0,$a3,L\$aligned_pa1
534         sub     $inp,$a3,$inp
535
536         ldw     `0*4`($inp),$X[0]
537         ldw     `1*4`($inp),$X[1]
538         ldw     `2*4`($inp),$t2
539         ldw     `3*4`($inp),$t3
540         ldw     `4*4`($inp),$a0
541         ldw     `5*4`($inp),$a1
542         ldw     `6*4`($inp),$a2
543         ldw     `7*4`($inp),$a3
544         vshd    $X[0],$X[1],$X[0]
545         vshd    $X[1],$t2,$X[1]
546         stw     $X[0],`-$XOFF+0*4`(%sp)
547         ldw     `8*4`($inp),$t0
548         vshd    $t2,$t3,$t2
549         stw     $X[1],`-$XOFF+1*4`(%sp)
550         ldw     `9*4`($inp),$t1
551         vshd    $t3,$a0,$t3
552 ___
553 {
554 my @t=($t2,$t3,$a0,$a1,$a2,$a3,$t0,$t1);
555 for ($i=2;$i<=(128/4-8);$i++) {
556 $code.=<<___;
557         stw     $t[0],`-$XOFF+$i*4`(%sp)
558         ldw     `(8+$i)*4`($inp),$t[0]
559         vshd    $t[1],$t[2],$t[1]
560 ___
561 push(@t,shift(@t));
562 }
563 for (;$i<(128/4-1);$i++) {
564 $code.=<<___;
565         stw     $t[0],`-$XOFF+$i*4`(%sp)
566         vshd    $t[1],$t[2],$t[1]
567 ___
568 push(@t,shift(@t));
569 }
570 $code.=<<___;
571         b       L\$collected_pa1
572         stw     $t[0],`-$XOFF+$i*4`(%sp)
573
574 ___
575 }
576 $code.=<<___;
577 L\$aligned_pa1
578         ldw     `0*4`($inp),$X[0]
579         ldw     `1*4`($inp),$X[1]
580         ldw     `2*4`($inp),$t2
581         ldw     `3*4`($inp),$t3
582         ldw     `4*4`($inp),$a0
583         ldw     `5*4`($inp),$a1
584         ldw     `6*4`($inp),$a2
585         ldw     `7*4`($inp),$a3
586         stw     $X[0],`-$XOFF+0*4`(%sp)
587         ldw     `8*4`($inp),$t0
588         stw     $X[1],`-$XOFF+1*4`(%sp)
589         ldw     `9*4`($inp),$t1
590 ___
591 {
592 my @t=($t2,$t3,$a0,$a1,$a2,$a3,$t0,$t1);
593 for ($i=2;$i<(128/4-8);$i++) {
594 $code.=<<___;
595         stw     $t[0],`-$XOFF+$i*4`(%sp)
596         ldw     `(8+$i)*4`($inp),$t[0]
597 ___
598 push(@t,shift(@t));
599 }
600 for (;$i<128/4;$i++) {
601 $code.=<<___;
602         stw     $t[0],`-$XOFF+$i*4`(%sp)
603 ___
604 push(@t,shift(@t));
605 }
606 $code.="L\$collected_pa1\n";
607 }
608
609 for($i=0;$i<16;$i++)    { &ROUND_00_15_pa1($i,@V); unshift(@V,pop(@V)); unshift(@V,pop(@V)); }
610 $code.="L\$rounds_pa1\n";
611 for(;$i<32;$i++)        { &ROUND_16_xx_pa1($i,@V); unshift(@V,pop(@V)); unshift(@V,pop(@V)); }
612
613 $code.=<<___;
614         $POP    `-$FRAME_MARKER-2*$SIZE_T`(%sp),$ctx    ; restore arguments
615         $POP    `-$FRAME_MARKER-3*$SIZE_T`(%sp),$inp
616         $POP    `-$FRAME_MARKER-4*$SIZE_T`(%sp),$num
617         ldo     `-$rounds*$SZ`($Tbl),$Tbl               ; rewind $Tbl
618
619         ldw     `0*4`($ctx),$t1         ; update context
620         ldw     `1*4`($ctx),$t0
621         ldw     `2*4`($ctx),$t3
622         ldw     `3*4`($ctx),$t2
623         ldw     `4*4`($ctx),$a1
624         ldw     `5*4`($ctx),$a0
625         ldw     `6*4`($ctx),$a3
626         add     $t0,$Alo,$Alo
627         ldw     `7*4`($ctx),$a2
628         addc    $t1,$Ahi,$Ahi
629         ldw     `8*4`($ctx),$t1
630         add     $t2,$Blo,$Blo
631         ldw     `9*4`($ctx),$t0
632         addc    $t3,$Bhi,$Bhi
633         ldw     `10*4`($ctx),$t3
634         add     $a0,$Clo,$Clo
635         ldw     `11*4`($ctx),$t2
636         addc    $a1,$Chi,$Chi
637         ldw     `12*4`($ctx),$a1
638         add     $a2,$Dlo,$Dlo
639         ldw     `13*4`($ctx),$a0
640         addc    $a3,$Dhi,$Dhi
641         ldw     `14*4`($ctx),$a3
642         add     $t0,$Elo,$Elo
643         ldw     `15*4`($ctx),$a2
644         addc    $t1,$Ehi,$Ehi
645         stw     $Ahi,`0*4`($ctx)
646         add     $t2,$Flo,$Flo
647         stw     $Alo,`1*4`($ctx)
648         addc    $t3,$Fhi,$Fhi
649         stw     $Bhi,`2*4`($ctx)
650         add     $a0,$Glo,$Glo
651         stw     $Blo,`3*4`($ctx)
652         addc    $a1,$Ghi,$Ghi
653         stw     $Chi,`4*4`($ctx)
654         add     $a2,$Hlo,$Hlo
655         stw     $Clo,`5*4`($ctx)
656         addc    $a3,$Hhi,$Hhi
657         stw     $Dhi,`6*4`($ctx)
658         ldo     `16*$SZ`($inp),$inp     ; advance $inp
659         stw     $Dlo,`7*4`($ctx)
660         stw     $Ehi,`8*4`($ctx)
661         stw     $Elo,`9*4`($ctx)
662         stw     $Fhi,`10*4`($ctx)
663         stw     $Flo,`11*4`($ctx)
664         stw     $Ghi,`12*4`($ctx)
665         stw     $Glo,`13*4`($ctx)
666         stw     $Hhi,`14*4`($ctx)
667         comb,=  $inp,$num,L\$done
668         stw     $Hlo,`15*4`($ctx)
669         b       L\$oop_pa1
670         $PUSH   $inp,`-$FRAME_MARKER-3*$SIZE_T`(%sp)    ; save $inp
671 L\$done
672 ___
673 }}
674 $code.=<<___;
675         $POP    `-$FRAME-$SAVED_RP`(%sp),%r2            ; standard epilogue
676         $POP    `-$FRAME+1*$SIZE_T`(%sp),%r4
677         $POP    `-$FRAME+2*$SIZE_T`(%sp),%r5
678         $POP    `-$FRAME+3*$SIZE_T`(%sp),%r6
679         $POP    `-$FRAME+4*$SIZE_T`(%sp),%r7
680         $POP    `-$FRAME+5*$SIZE_T`(%sp),%r8
681         $POP    `-$FRAME+6*$SIZE_T`(%sp),%r9
682         $POP    `-$FRAME+7*$SIZE_T`(%sp),%r10
683         $POP    `-$FRAME+8*$SIZE_T`(%sp),%r11
684         $POP    `-$FRAME+9*$SIZE_T`(%sp),%r12
685         $POP    `-$FRAME+10*$SIZE_T`(%sp),%r13
686         $POP    `-$FRAME+11*$SIZE_T`(%sp),%r14
687         $POP    `-$FRAME+12*$SIZE_T`(%sp),%r15
688         $POP    `-$FRAME+13*$SIZE_T`(%sp),%r16
689         $POP    `-$FRAME+14*$SIZE_T`(%sp),%r17
690         $POP    `-$FRAME+15*$SIZE_T`(%sp),%r18
691         bv      (%r2)
692         .EXIT
693         $POPMB  -$FRAME(%sp),%r3
694         .PROCEND
695         .STRINGZ "SHA`64*$SZ` block transform for PA-RISC, CRYPTOGAMS by <appro\@openssl.org>"
696 ___
697
698 # Explicitly encode PA-RISC 2.0 instructions used in this module, so
699 # that it can be compiled with .LEVEL 1.0. It should be noted that I
700 # wouldn't have to do this, if GNU assembler understood .ALLOW 2.0
701 # directive...
702
703 my $ldd = sub {
704   my ($mod,$args) = @_;
705   my $orig = "ldd$mod\t$args";
706
707     if ($args =~ /(\-?[0-9]+)\(%r([0-9]+)\),%r([0-9]+)/) # format 3 suffices
708     {   my $opcode=(0x14<<26)|($2<<21)|($3<<16)|(($1&0x1FF8)<<1)|(($1>>13)&1);
709         $opcode|=(1<<3) if ($mod =~ /^,m/);
710         $opcode|=(1<<2) if ($mod =~ /^,mb/);
711         sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig;
712     }
713     else { "\t".$orig; }
714 };
715
716 my $std = sub {
717   my ($mod,$args) = @_;
718   my $orig = "std$mod\t$args";
719
720     if ($args =~ /%r([0-9]+),(\-?[0-9]+)\(%r([0-9]+)\)/) # format 3 suffices
721     {   my $opcode=(0x1c<<26)|($3<<21)|($1<<16)|(($2&0x1FF8)<<1)|(($2>>13)&1);
722         sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig;
723     }
724     else { "\t".$orig; }
725 };
726
727 my $extrd = sub {
728   my ($mod,$args) = @_;
729   my $orig = "extrd$mod\t$args";
730
731     # I only have ",u" completer, it's implicitly encoded...
732     if ($args =~ /%r([0-9]+),([0-9]+),([0-9]+),%r([0-9]+)/)     # format 15
733     {   my $opcode=(0x36<<26)|($1<<21)|($4<<16);
734         my $len=32-$3;
735         $opcode |= (($2&0x20)<<6)|(($2&0x1f)<<5);               # encode pos
736         $opcode |= (($len&0x20)<<7)|($len&0x1f);                # encode len
737         sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig;
738     }
739     elsif ($args =~ /%r([0-9]+),%sar,([0-9]+),%r([0-9]+)/)      # format 12
740     {   my $opcode=(0x34<<26)|($1<<21)|($3<<16)|(2<<11)|(1<<9);
741         my $len=32-$2;
742         $opcode |= (($len&0x20)<<3)|($len&0x1f);                # encode len
743         $opcode |= (1<<13) if ($mod =~ /,\**=/);
744         sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig;
745     }
746     else { "\t".$orig; }
747 };
748
749 my $shrpd = sub {
750   my ($mod,$args) = @_;
751   my $orig = "shrpd$mod\t$args";
752
753     if ($args =~ /%r([0-9]+),%r([0-9]+),([0-9]+),%r([0-9]+)/)   # format 14
754     {   my $opcode=(0x34<<26)|($2<<21)|($1<<16)|(1<<10)|$4;
755         my $cpos=63-$3;
756         $opcode |= (($cpos&0x20)<<6)|(($cpos&0x1f)<<5);         # encode sa
757         sprintf "\t.WORD\t0x%08x\t; %s",$opcode,$orig;
758     }
759     elsif ($args =~ /%r([0-9]+),%r([0-9]+),%sar,%r([0-9]+)/)    # format 11
760     {   sprintf "\t.WORD\t0x%08x\t; %s",
761                 (0x34<<26)|($2<<21)|($1<<16)|(1<<9)|$3,$orig;
762     }
763     else { "\t".$orig; }
764 };
765
766 sub assemble {
767   my ($mnemonic,$mod,$args)=@_;
768   my $opcode = eval("\$$mnemonic");
769
770     ref($opcode) eq 'CODE' ? &$opcode($mod,$args) : "\t$mnemonic$mod\t$args";
771 }
772
773 if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
774         =~ /GNU assembler/) {
775     $gnuas = 1;
776 }
777
778 foreach (split("\n",$code)) {
779         s/\`([^\`]*)\`/eval $1/ge;
780
781         s/shd\s+(%r[0-9]+),(%r[0-9]+),([0-9]+)/
782                 $3>31 ? sprintf("shd\t%$2,%$1,%d",$3-32)        # rotation for >=32
783                 :       sprintf("shd\t%$1,%$2,%d",$3)/e                 or
784         # translate made up instructions: _ror, _shr, _align, _shl
785         s/_ror(\s+)(%r[0-9]+),/
786                 ($SZ==4 ? "shd" : "shrpd")."$1$2,$2,"/e                 or
787
788         s/_shr(\s+%r[0-9]+),([0-9]+),/
789                 $SZ==4 ? sprintf("extru%s,%d,%d,",$1,31-$2,32-$2)
790                 :        sprintf("extrd,u%s,%d,%d,",$1,63-$2,64-$2)/e   or
791
792         s/_align(\s+%r[0-9]+,%r[0-9]+),/
793                 ($SZ==4 ? "vshd$1," : "shrpd$1,%sar,")/e                or
794
795         s/_shl(\s+%r[0-9]+),([0-9]+),/
796                 $SIZE_T==4 ? sprintf("zdep%s,%d,%d,",$1,31-$2,32-$2)
797                 :            sprintf("depd,z%s,%d,%d,",$1,63-$2,64-$2)/e;
798
799         s/^\s+([a-z]+)([\S]*)\s+([\S]*)/&assemble($1,$2,$3)/e if ($SIZE_T==4);
800
801         s/(\.LEVEL\s+2\.0)W/$1w/        if ($gnuas && $SIZE_T==8);
802         s/\.SPACE\s+\$TEXT\$/.text/     if ($gnuas && $SIZE_T==8);
803         s/\.SUBSPA.*//                  if ($gnuas && $SIZE_T==8);
804         s/cmpb,\*/comb,/                if ($SIZE_T==4);
805         s/\bbv\b/bve/                   if ($SIZE_T==8);
806
807         print $_,"\n";
808 }
809
810 close STDOUT;