MIPS assembly pack: fix MIPS64 assembler warnings.
[openssl.git] / crypto / sha / asm / sha1-mips.pl
index a2f7aaddc11003f70da2844ecde562a4d0337d6a..0141bcca801aef6d4b8ef3ec99d6a20653303fe4 100644 (file)
 # vectorized Xupdate on MIPSIII/IV, but the goal was to code MIPS32-
 # compatible subroutine. There is room for minor optimization on
 # little-endian platforms...
+
+# September 2012.
+#
+# Add MIPS32r2 code (>25% less instructions).
+
+######################################################################
+# There is a number of MIPS ABI in use, O32 and N32/64 are most
+# widely used. Then there is a new contender: NUBI. It appears that if
+# one picks the latter, it's possible to arrange code in ABI neutral
+# manner. Therefore let's stick to NUBI register layout:
+#
+($zero,$at,$t0,$t1,$t2)=map("\$$_",(0..2,24,25));
+($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$$_",(4..11));
+($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7,$s8,$s9,$s10,$s11)=map("\$$_",(12..23));
+($gp,$tp,$sp,$fp,$ra)=map("\$$_",(3,28..31));
+#
+# The return value is placed in $a0. Following coding rules facilitate
+# interoperability:
+#
+# - never ever touch $tp, "thread pointer", former $gp;
+# - copy return value to $t0, former $v0 [or to $a0 if you're adapting
+#   old code];
+# - on O32 populate $a4-$a7 with 'lw $aN,4*N($sp)' if necessary;
+#
+# For reference here is register layout for N32/64 MIPS ABIs:
+#
+# ($zero,$at,$v0,$v1)=map("\$$_",(0..3));
+# ($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$$_",(4..11));
+# ($t0,$t1,$t2,$t3,$t8,$t9)=map("\$$_",(12..15,24,25));
+# ($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7)=map("\$$_",(16..23));
+# ($gp,$sp,$fp,$ra)=map("\$$_",(28..31));
+#
+$flavour = shift || "o32"; # supported flavours are o32,n32,64,nubi32,nubi64
+
+if ($flavour =~ /64|n32/i) {
+       $PTR_ADD="dadd";        # incidentally works even on n32
+       $PTR_SUB="dsub";        # incidentally works even on n32
+       $REG_S="sd";
+       $REG_L="ld";
+       $PTR_SLL="dsll";        # incidentally works even on n32
+       $SZREG=8;
+} else {
+       $PTR_ADD="add";
+       $PTR_SUB="sub";
+       $REG_S="sw";
+       $REG_L="lw";
+       $PTR_SLL="sll";
+       $SZREG=4;
+}
+#
+# <appro@openssl.org>
 #
-# The code is somewhat IRIX-centric, i.e. is likely to require minor
-# adaptations for other OSes...
+######################################################################
+
+$big_endian=(`echo MIPSEL | $ENV{CC} -E -`=~/MIPSEL/)?1:0 if ($ENV{CC});
+
+for (@ARGV) {  $output=$_ if (/\w[\w\-]*\.\w+$/);   }
+open STDOUT,">$output";
 
-for (@ARGV) {   $big_endian=1 if (/\-DB_ENDIAN/);
-                $big_endian=0 if (/\-DL_ENDIAN/);   }
 if (!defined($big_endian))
             {   $big_endian=(unpack('L',pack('N',1))==1);   }
 
@@ -27,27 +80,29 @@ if (!defined($big_endian))
 $MSB=$big_endian?0:3;
 $LSB=3&~$MSB;
 
-@X=(   "\$8",  "\$9",  "\$10", "\$11", "\$12", "\$13", "\$14", "\$15",
-       "\$16", "\$17", "\$18", "\$19", "\$20", "\$21", "\$22", "\$23");
-$ctx="\$4";    # a0
-$inp="\$5";    # a1
-$num="\$6";    # a2
+@X=map("\$$_",(8..23));        # a4-a7,s0-s11
+
+$ctx=$a0;
+$inp=$a1;
+$num=$a2;
 $A="\$1";
 $B="\$2";
 $C="\$3";
 $D="\$7";
 $E="\$24";     @V=($A,$B,$C,$D,$E);
-$t0="\$25";    # jp,t9
-$t1="\$28";    # gp
-$t2="\$30";    # fp,s8
+$t0="\$25";
+$t1=$num;      # $num is offloaded to stack
+$t2="\$30";    # fp
 $K="\$31";     # ra
 
-$FRAMESIZE=16;
-
 sub BODY_00_14 {
 my ($i,$a,$b,$c,$d,$e)=@_;
 my $j=$i+1;
 $code.=<<___   if (!$big_endian);
+#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
+       wsbh    @X[$i],@X[$i]   # byte swap($i)
+       rotr    @X[$i],@X[$i],16
+#else
        srl     $t0,@X[$i],24   # byte swap($i)
        srl     $t1,@X[$i],8
        andi    $t2,@X[$i],0xFF00
@@ -55,10 +110,24 @@ $code.=<<___       if (!$big_endian);
        andi    $t1,0xFF00
        sll     $t2,$t2,8
        or      @X[$i],$t0
+       or      $t1,$t2
        or      @X[$i],$t1
-       or      @X[$i],$t2
+#endif
 ___
 $code.=<<___;
+#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
+       addu    $e,$K           # $i
+       xor     $t0,$c,$d
+       rotr    $t1,$a,27
+        lwl    @X[$j],$j*4+$MSB($inp)
+       and     $t0,$b
+       addu    $e,$t1
+        lwr    @X[$j],$j*4+$LSB($inp)
+       xor     $t0,$d
+       addu    $e,@X[$i]
+       rotr    $b,$b,2
+       addu    $e,$t0
+#else
         lwl    @X[$j],$j*4+$MSB($inp)
        sll     $t0,$a,5        # $i
        addu    $e,$K
@@ -74,6 +143,7 @@ $code.=<<___;
        addu    $e,@X[$i]
        or      $b,$t2
        addu    $e,$t0
+#endif
 ___
 }
 
@@ -82,6 +152,10 @@ my ($i,$a,$b,$c,$d,$e)=@_;
 my $j=$i+1;
 
 $code.=<<___   if (!$big_endian && $i==15);
+#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
+       wsbh    @X[$i],@X[$i]   # byte swap($i)
+       rotr    @X[$i],@X[$i],16
+#else
        srl     $t0,@X[$i],24   # byte swap($i)
        srl     $t1,@X[$i],8
        andi    $t2,@X[$i],0xFF00
@@ -91,8 +165,24 @@ $code.=<<___        if (!$big_endian && $i==15);
        or      @X[$i],$t0
        or      @X[$i],$t1
        or      @X[$i],$t2
+#endif
 ___
 $code.=<<___;
+#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
+       addu    $e,$K           # $i
+        xor    @X[$j%16],@X[($j+2)%16]
+       xor     $t0,$c,$d
+       rotr    $t1,$a,27
+        xor    @X[$j%16],@X[($j+8)%16]
+       and     $t0,$b
+       addu    $e,$t1
+        xor    @X[$j%16],@X[($j+13)%16]
+       xor     $t0,$d
+       addu    $e,@X[$i%16]
+        rotr   @X[$j%16],@X[$j%16],31
+       rotr    $b,$b,2
+       addu    $e,$t0
+#else
         xor    @X[$j%16],@X[($j+2)%16]
        sll     $t0,$a,5        # $i
        addu    $e,$K
@@ -112,6 +202,7 @@ $code.=<<___;
        addu    $e,@X[$i%16]
        or      $b,$t2
        addu    $e,$t0
+#endif
 ___
 }
 
@@ -119,6 +210,20 @@ sub BODY_20_39 {
 my ($i,$a,$b,$c,$d,$e)=@_;
 my $j=$i+1;
 $code.=<<___ if ($i<79);
+#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
+        xor    @X[$j%16],@X[($j+2)%16]
+       addu    $e,$K           # $i
+       rotr    $t1,$a,27
+        xor    @X[$j%16],@X[($j+8)%16]
+       xor     $t0,$c,$d
+       addu    $e,$t1
+        xor    @X[$j%16],@X[($j+13)%16]
+       xor     $t0,$b
+       addu    $e,@X[$i%16]
+        rotr   @X[$j%16],@X[$j%16],31
+       rotr    $b,$b,2
+       addu    $e,$t0
+#else
         xor    @X[$j%16],@X[($j+2)%16]
        sll     $t0,$a,5        # $i
        addu    $e,$K
@@ -137,8 +242,24 @@ $code.=<<___ if ($i<79);
         or     @X[$j%16],$t1
        or      $b,$t2
        addu    $e,$t0
+#endif
 ___
 $code.=<<___ if ($i==79);
+#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
+        lw     @X[0],0($ctx)
+       addu    $e,$K           # $i
+        lw     @X[1],4($ctx)
+       rotr    $t1,$a,27
+        lw     @X[2],8($ctx)
+       xor     $t0,$c,$d
+       addu    $e,$t1
+        lw     @X[3],12($ctx)
+       xor     $t0,$b
+       addu    $e,@X[$i%16]
+        lw     @X[4],16($ctx)
+       rotr    $b,$b,2
+       addu    $e,$t0
+#else
         lw     @X[0],0($ctx)
        sll     $t0,$a,5        # $i
        addu    $e,$K
@@ -156,6 +277,7 @@ $code.=<<___ if ($i==79);
        addu    $e,@X[$i%16]
        or      $b,$t2
        addu    $e,$t0
+#endif
 ___
 }
 
@@ -163,6 +285,22 @@ sub BODY_40_59 {
 my ($i,$a,$b,$c,$d,$e)=@_;
 my $j=$i+1;
 $code.=<<___ if ($i<79);
+#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
+       addu    $e,$K           # $i
+       and     $t0,$c,$d
+        xor    @X[$j%16],@X[($j+2)%16]
+       rotr    $t1,$a,27
+       addu    $e,$t0
+        xor    @X[$j%16],@X[($j+8)%16]
+       xor     $t0,$c,$d
+       addu    $e,$t1
+        xor    @X[$j%16],@X[($j+13)%16]
+       and     $t0,$b
+       addu    $e,@X[$i%16]
+        rotr   @X[$j%16],@X[$j%16],31
+       rotr    $b,$b,2
+       addu    $e,$t0
+#else
         xor    @X[$j%16],@X[($j+2)%16]
        sll     $t0,$a,5        # $i
        addu    $e,$K
@@ -183,12 +321,21 @@ $code.=<<___ if ($i<79);
        addu    $e,@X[$i%16]
        or      $b,$t2
        addu    $e,$t0
+#endif
 ___
 }
 
+$FRAMESIZE=16; # large enough to accommodate NUBI saved registers
+$SAVED_REGS_MASK = ($flavour =~ /nubi/i) ? "0xc0fff008" : "0xc0ff0000";
+
 $code=<<___;
-#include <asm.h>
-#include <regdef.h>
+#ifdef OPENSSL_FIPSCANISTER
+# include <openssl/fipssyms.h>
+#endif
+
+#if defined(__mips_smartmips) && !defined(_MIPS_ARCH_MIPS32R2)
+#define _MIPS_ARCH_MIPS32R2
+#endif
 
 .text
 
@@ -198,22 +345,32 @@ $code=<<___;
 .globl sha1_block_data_order
 .ent   sha1_block_data_order
 sha1_block_data_order:
-       .frame  sp,$FRAMESIZE*SZREG,zero
-       .mask   0xd0ff0000,-$FRAMESIZE*SZREG
+       .frame  $sp,$FRAMESIZE*$SZREG,$ra
+       .mask   $SAVED_REGS_MASK,-$SZREG
        .set    noreorder
-       PTR_SUB sp,$FRAMESIZE*SZREG
-       REG_S   \$31,($FRAMESIZE-1)*SZREG(sp)
-       REG_S   \$30,($FRAMESIZE-2)*SZREG(sp)
-       REG_S   \$28,($FRAMESIZE-3)*SZREG(sp)
-       REG_S   \$23,($FRAMESIZE-4)*SZREG(sp)
-       REG_S   \$22,($FRAMESIZE-5)*SZREG(sp)
-       REG_S   \$21,($FRAMESIZE-6)*SZREG(sp)
-       REG_S   \$20,($FRAMESIZE-7)*SZREG(sp)
-       REG_S   \$19,($FRAMESIZE-8)*SZREG(sp)
-       REG_S   \$18,($FRAMESIZE-9)*SZREG(sp)
-       REG_S   \$17,($FRAMESIZE-10)*SZREG(sp)
-       REG_S   \$16,($FRAMESIZE-11)*SZREG(sp)
-
+       $PTR_SUB $sp,$FRAMESIZE*$SZREG
+       $REG_S  $ra,($FRAMESIZE-1)*$SZREG($sp)
+       $REG_S  $fp,($FRAMESIZE-2)*$SZREG($sp)
+       $REG_S  $s11,($FRAMESIZE-3)*$SZREG($sp)
+       $REG_S  $s10,($FRAMESIZE-4)*$SZREG($sp)
+       $REG_S  $s9,($FRAMESIZE-5)*$SZREG($sp)
+       $REG_S  $s8,($FRAMESIZE-6)*$SZREG($sp)
+       $REG_S  $s7,($FRAMESIZE-7)*$SZREG($sp)
+       $REG_S  $s6,($FRAMESIZE-8)*$SZREG($sp)
+       $REG_S  $s5,($FRAMESIZE-9)*$SZREG($sp)
+       $REG_S  $s4,($FRAMESIZE-10)*$SZREG($sp)
+___
+$code.=<<___ if ($flavour =~ /nubi/i); # optimize non-nubi prologue
+       $REG_S  $s3,($FRAMESIZE-11)*$SZREG($sp)
+       $REG_S  $s2,($FRAMESIZE-12)*$SZREG($sp)
+       $REG_S  $s1,($FRAMESIZE-13)*$SZREG($sp)
+       $REG_S  $s0,($FRAMESIZE-14)*$SZREG($sp)
+       $REG_S  $gp,($FRAMESIZE-15)*$SZREG($sp)
+___
+$code.=<<___;
+       $PTR_SLL $num,6
+       $PTR_ADD $num,$inp
+       $REG_S  $num,0($sp)
        lw      $A,0($ctx)
        lw      $B,4($ctx)
        lw      $C,8($ctx)
@@ -246,6 +403,9 @@ $code.=<<___;
 ___
 for (;$i<80;$i++)      { &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
 $code.=<<___;
+       $PTR_ADD $inp,64
+       $REG_L  $num,0($sp)
+
        addu    $A,$X[0]
        addu    $B,$X[1]
        sw      $A,0($ctx)
@@ -253,29 +413,38 @@ $code.=<<___;
        addu    $D,$X[3]
        sw      $B,4($ctx)
        addu    $E,$X[4]
-       PTR_SUB $num,1
        sw      $C,8($ctx)
        sw      $D,12($ctx)
        sw      $E,16($ctx)
        .set    noreorder
-       bnez    $num,.Loop
-       PTR_ADD $inp,64
+       bne     $inp,$num,.Loop
+       nop
 
        .set    noreorder
-       REG_L   \$31,($FRAMESIZE-1)*SZREG(sp)
-       REG_L   \$30,($FRAMESIZE-2)*SZREG(sp)
-       REG_L   \$28,($FRAMESIZE-3)*SZREG(sp)
-       REG_L   \$23,($FRAMESIZE-4)*SZREG(sp)
-       REG_L   \$22,($FRAMESIZE-5)*SZREG(sp)
-       REG_L   \$21,($FRAMESIZE-6)*SZREG(sp)
-       REG_L   \$20,($FRAMESIZE-7)*SZREG(sp)
-       REG_L   \$19,($FRAMESIZE-8)*SZREG(sp)
-       REG_L   \$18,($FRAMESIZE-9)*SZREG(sp)
-       REG_L   \$17,($FRAMESIZE-10)*SZREG(sp)
-       REG_L   \$16,($FRAMESIZE-11)*SZREG(sp)
-       jr      ra
-       PTR_ADD sp,$FRAMESIZE*SZREG
+       $REG_L  $ra,($FRAMESIZE-1)*$SZREG($sp)
+       $REG_L  $fp,($FRAMESIZE-2)*$SZREG($sp)
+       $REG_L  $s11,($FRAMESIZE-3)*$SZREG($sp)
+       $REG_L  $s10,($FRAMESIZE-4)*$SZREG($sp)
+       $REG_L  $s9,($FRAMESIZE-5)*$SZREG($sp)
+       $REG_L  $s8,($FRAMESIZE-6)*$SZREG($sp)
+       $REG_L  $s7,($FRAMESIZE-7)*$SZREG($sp)
+       $REG_L  $s6,($FRAMESIZE-8)*$SZREG($sp)
+       $REG_L  $s5,($FRAMESIZE-9)*$SZREG($sp)
+       $REG_L  $s4,($FRAMESIZE-10)*$SZREG($sp)
+___
+$code.=<<___ if ($flavour =~ /nubi/i);
+       $REG_L  $s3,($FRAMESIZE-11)*$SZREG($sp)
+       $REG_L  $s2,($FRAMESIZE-12)*$SZREG($sp)
+       $REG_L  $s1,($FRAMESIZE-13)*$SZREG($sp)
+       $REG_L  $s0,($FRAMESIZE-14)*$SZREG($sp)
+       $REG_L  $gp,($FRAMESIZE-15)*$SZREG($sp)
+___
+$code.=<<___;
+       jr      $ra
+       $PTR_ADD $sp,$FRAMESIZE*$SZREG
 .end   sha1_block_data_order
+.rdata
+.asciiz        "SHA1 for MIPS, CRYPTOGAMS by <appro\@openssl.org>"
 ___
 print $code;
 close STDOUT;