Viewing file:      poly1305-mips.pl (9.13 KB)      -rwxr-xr-x Select action/file-type:    (+) |   (+) |   (+) | Code (+) | Session (+) |   (+) | SDB (+) |   (+) |   (+) |   (+) |   (+) |   (+) |
 
#! /usr/bin/env perl # Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License").  You may not use # this file except in compliance with the License.  You can obtain a copy # in the file LICENSE in the source distribution or at # https://www.openssl.org/source/license.html
 
  # ==================================================================== # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL # project. The module is, however, dual licensed under OpenSSL and # CRYPTOGAMS licenses depending on where you obtain it. For further # details see http://www.openssl.org/~appro/cryptogams/. # ====================================================================
  # Poly1305 hash for MIPS64. # # May 2016 # # Numbers are cycles per processed byte with poly1305_blocks alone. # #        IALU/gcc # R1x000    5.64/+120%    (big-endian) # Octeon II    3.80/+280%    (little-endian)
  ###################################################################### # 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 [o32 can be #   excluded from the rule, because it's specified volatile]; # - 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)); # # <appro@openssl.org> # ######################################################################
  # $output is the last argument if it looks like a file (it has an extension) # $flavour is the first argument if it doesn't look like a file $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; # supported flavours are o32,n32,64,nubi32,nubi64, default is o32 $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : "o32";
  die "MIPS64 only" unless ($flavour =~ /64|n32/i);
  $v0 = ($flavour =~ /nubi/i) ? $a0 : $t0; $SAVED_REGS_MASK = ($flavour =~ /nubi/i) ? "0x0003f000" : "0x00030000";
  ($ctx,$inp,$len,$padbit) = ($a0,$a1,$a2,$a3); ($in0,$in1,$tmp0,$tmp1,$tmp2,$tmp3,$tmp4) = ($a4,$a5,$a6,$a7,$at,$t0,$t1);
  $code.=<<___; #include "mips_arch.h"
  #ifdef MIPSEB # define MSB 0 # define LSB 7 #else # define MSB 7 # define LSB 0 #endif
  .text .set    noat .set    noreorder
  .align    5 .globl    poly1305_init .ent    poly1305_init poly1305_init:     .frame    $sp,0,$ra     .set    reorder
      sd    $zero,0($ctx)     sd    $zero,8($ctx)     sd    $zero,16($ctx)
      beqz    $inp,.Lno_key
  #if defined(_MIPS_ARCH_MIPS64R6)     ld    $in0,0($inp)     ld    $in1,8($inp) #else     ldl    $in0,0+MSB($inp)     ldl    $in1,8+MSB($inp)     ldr    $in0,0+LSB($inp)     ldr    $in1,8+LSB($inp) #endif #ifdef    MIPSEB # if defined(_MIPS_ARCH_MIPS64R2)     dsbh    $in0,$in0        # byte swap      dsbh    $in1,$in1     dshd    $in0,$in0      dshd    $in1,$in1 # else     ori    $tmp0,$zero,0xFF     dsll    $tmp2,$tmp0,32     or    $tmp0,$tmp2        # 0x000000FF000000FF
      and    $tmp1,$in0,$tmp0    # byte swap      and    $tmp3,$in1,$tmp0     dsrl    $tmp2,$in0,24      dsrl    $tmp4,$in1,24     dsll    $tmp1,24      dsll    $tmp3,24     and    $tmp2,$tmp0      and    $tmp4,$tmp0     dsll    $tmp0,8            # 0x0000FF000000FF00     or    $tmp1,$tmp2      or    $tmp3,$tmp4     and    $tmp2,$in0,$tmp0      and    $tmp4,$in1,$tmp0     dsrl    $in0,8      dsrl    $in1,8     dsll    $tmp2,8      dsll    $tmp4,8     and    $in0,$tmp0      and    $in1,$tmp0     or    $tmp1,$tmp2      or    $tmp3,$tmp4     or    $in0,$tmp1      or    $in1,$tmp3     dsrl    $tmp1,$in0,32      dsrl    $tmp3,$in1,32     dsll    $in0,32      dsll    $in1,32     or    $in0,$tmp1      or    $in1,$tmp3 # endif #endif     li    $tmp0,1     dsll    $tmp0,32     daddiu    $tmp0,-63     dsll    $tmp0,28     daddiu    $tmp0,-1        # 0ffffffc0fffffff
      and    $in0,$tmp0     daddiu    $tmp0,-3        # 0ffffffc0ffffffc     and    $in1,$tmp0
      sd    $in0,24($ctx)     dsrl    $tmp0,$in1,2     sd    $in1,32($ctx)     daddu    $tmp0,$in1        # s1 = r1 + (r1 >> 2)     sd    $tmp0,40($ctx)
  .Lno_key:     li    $v0,0            # return 0     jr    $ra .end    poly1305_init ___ { my ($h0,$h1,$h2,$r0,$r1,$s1,$d0,$d1,$d2) =    ($s0,$s1,$s2,$s3,$s4,$s5,$in0,$in1,$t2);
  $code.=<<___; .align    5 .globl    poly1305_blocks .ent    poly1305_blocks poly1305_blocks:     .set    noreorder     dsrl    $len,4            # number of complete blocks     bnez    $len,poly1305_blocks_internal     nop     jr    $ra     nop .end    poly1305_blocks
  .align    5 .ent    poly1305_blocks_internal poly1305_blocks_internal:     .frame    $sp,6*8,$ra     .mask    $SAVED_REGS_MASK,-8     .set    noreorder     dsubu    $sp,6*8     sd    $s5,40($sp)     sd    $s4,32($sp) ___ $code.=<<___ if ($flavour =~ /nubi/i);    # optimize non-nubi prologue     sd    $s3,24($sp)     sd    $s2,16($sp)     sd    $s1,8($sp)     sd    $s0,0($sp) ___ $code.=<<___;     .set    reorder
      ld    $h0,0($ctx)        # load hash value     ld    $h1,8($ctx)     ld    $h2,16($ctx)
      ld    $r0,24($ctx)        # load key     ld    $r1,32($ctx)     ld    $s1,40($ctx)
  .Loop: #if defined(_MIPS_ARCH_MIPS64R6)     ld    $in0,0($inp)        # load input     ld    $in1,8($inp) #else     ldl    $in0,0+MSB($inp)    # load input     ldl    $in1,8+MSB($inp)     ldr    $in0,0+LSB($inp)     ldr    $in1,8+LSB($inp) #endif     daddiu    $len,-1     daddiu    $inp,16 #ifdef    MIPSEB # if defined(_MIPS_ARCH_MIPS64R2)     dsbh    $in0,$in0        # byte swap      dsbh    $in1,$in1     dshd    $in0,$in0      dshd    $in1,$in1 # else     ori    $tmp0,$zero,0xFF     dsll    $tmp2,$tmp0,32     or    $tmp0,$tmp2        # 0x000000FF000000FF
      and    $tmp1,$in0,$tmp0    # byte swap      and    $tmp3,$in1,$tmp0     dsrl    $tmp2,$in0,24      dsrl    $tmp4,$in1,24     dsll    $tmp1,24      dsll    $tmp3,24     and    $tmp2,$tmp0      and    $tmp4,$tmp0     dsll    $tmp0,8            # 0x0000FF000000FF00     or    $tmp1,$tmp2      or    $tmp3,$tmp4     and    $tmp2,$in0,$tmp0      and    $tmp4,$in1,$tmp0     dsrl    $in0,8      dsrl    $in1,8     dsll    $tmp2,8      dsll    $tmp4,8     and    $in0,$tmp0      and    $in1,$tmp0     or    $tmp1,$tmp2      or    $tmp3,$tmp4     or    $in0,$tmp1      or    $in1,$tmp3     dsrl    $tmp1,$in0,32      dsrl    $tmp3,$in1,32     dsll    $in0,32      dsll    $in1,32     or    $in0,$tmp1      or    $in1,$tmp3 # endif #endif     daddu    $h0,$in0        # accumulate input     daddu    $h1,$in1     sltu    $tmp0,$h0,$in0     sltu    $tmp1,$h1,$in1     daddu    $h1,$tmp0
      dmultu    ($r0,$h0)        # h0*r0      daddu    $h2,$padbit      sltu    $tmp0,$h1,$tmp0     mflo    ($d0,$r0,$h0)     mfhi    ($d1,$r0,$h0)
      dmultu    ($s1,$h1)        # h1*5*r1      daddu    $tmp0,$tmp1      daddu    $h2,$tmp0     mflo    ($tmp0,$s1,$h1)     mfhi    ($tmp1,$s1,$h1)
      dmultu    ($r1,$h0)        # h0*r1      daddu    $d0,$tmp0      daddu    $d1,$tmp1     mflo    ($tmp2,$r1,$h0)     mfhi    ($d2,$r1,$h0)      sltu    $tmp0,$d0,$tmp0      daddu    $d1,$tmp0
      dmultu    ($r0,$h1)        # h1*r0      daddu    $d1,$tmp2      sltu    $tmp2,$d1,$tmp2     mflo    ($tmp0,$r0,$h1)     mfhi    ($tmp1,$r0,$h1)      daddu    $d2,$tmp2
      dmultu    ($s1,$h2)        # h2*5*r1      daddu    $d1,$tmp0      daddu    $d2,$tmp1     mflo    ($tmp2,$s1,$h2)
      dmultu    ($r0,$h2)        # h2*r0      sltu    $tmp0,$d1,$tmp0      daddu    $d2,$tmp0     mflo    ($tmp3,$r0,$h2)
      daddu    $d1,$tmp2     daddu    $d2,$tmp3     sltu    $tmp2,$d1,$tmp2     daddu    $d2,$tmp2
      li    $tmp0,-4        # final reduction     and    $tmp0,$d2     dsrl    $tmp1,$d2,2     andi    $h2,$d2,3     daddu    $tmp0,$tmp1     daddu    $h0,$d0,$tmp0     sltu    $tmp0,$h0,$tmp0     daddu    $h1,$d1,$tmp0     sltu    $tmp0,$h1,$tmp0     daddu    $h2,$h2,$tmp0
      bnez    $len,.Loop
      sd    $h0,0($ctx)        # store hash value     sd    $h1,8($ctx)     sd    $h2,16($ctx)
      .set    noreorder     ld    $s5,40($sp)        # epilogue     ld    $s4,32($sp) ___ $code.=<<___ if ($flavour =~ /nubi/i);    # optimize non-nubi epilogue     ld    $s3,24($sp)     ld    $s2,16($sp)     ld    $s1,8($sp)     ld    $s0,0($sp) ___ $code.=<<___;     jr    $ra     daddu    $sp,6*8 .end    poly1305_blocks_internal ___ } { my ($ctx,$mac,$nonce) = ($a0,$a1,$a2);
  $code.=<<___; .align    5 .globl    poly1305_emit .ent    poly1305_emit poly1305_emit:     .frame    $sp,0,$ra     .set    reorder
      ld    $tmp0,0($ctx)     ld    $tmp1,8($ctx)     ld    $tmp2,16($ctx)
      daddiu    $in0,$tmp0,5        # compare to modulus     sltiu    $tmp3,$in0,5     daddu    $in1,$tmp1,$tmp3     sltu    $tmp3,$in1,$tmp3     daddu    $tmp2,$tmp2,$tmp3
      dsrl    $tmp2,2            # see if it carried/borrowed     dsubu    $tmp2,$zero,$tmp2     nor    $tmp3,$zero,$tmp2
      and    $in0,$tmp2     and    $tmp0,$tmp3     and    $in1,$tmp2     and    $tmp1,$tmp3     or    $in0,$tmp0     or    $in1,$tmp1
      lwu    $tmp0,0($nonce)        # load nonce     lwu    $tmp1,4($nonce)     lwu    $tmp2,8($nonce)     lwu    $tmp3,12($nonce)     dsll    $tmp1,32     dsll    $tmp3,32     or    $tmp0,$tmp1     or    $tmp2,$tmp3
      daddu    $in0,$tmp0        # accumulate nonce     daddu    $in1,$tmp2     sltu    $tmp0,$in0,$tmp0     daddu    $in1,$tmp0
      dsrl    $tmp0,$in0,8        # write mac value     dsrl    $tmp1,$in0,16     dsrl    $tmp2,$in0,24     sb    $in0,0($mac)     dsrl    $tmp3,$in0,32     sb    $tmp0,1($mac)     dsrl    $tmp0,$in0,40     sb    $tmp1,2($mac)     dsrl    $tmp1,$in0,48     sb    $tmp2,3($mac)     dsrl    $tmp2,$in0,56     sb    $tmp3,4($mac)     dsrl    $tmp3,$in1,8     sb    $tmp0,5($mac)     dsrl    $tmp0,$in1,16     sb    $tmp1,6($mac)     dsrl    $tmp1,$in1,24     sb    $tmp2,7($mac)
      sb    $in1,8($mac)     dsrl    $tmp2,$in1,32     sb    $tmp3,9($mac)     dsrl    $tmp3,$in1,40     sb    $tmp0,10($mac)     dsrl    $tmp0,$in1,48     sb    $tmp1,11($mac)     dsrl    $tmp1,$in1,56     sb    $tmp2,12($mac)     sb    $tmp3,13($mac)     sb    $tmp0,14($mac)     sb    $tmp1,15($mac)
      jr    $ra .end    poly1305_emit .rdata .asciiz    "Poly1305 for MIPS64, CRYPTOGAMS by <appro\@openssl.org>" .align    2 ___ }
  $output and open STDOUT,">$output"; print $code; close STDOUT or die "error closing STDOUT: $!";
  
  |