1274 lines
24 KiB
Perl
1274 lines
24 KiB
Perl
|
#!/usr/bin/env perl
|
||
|
# SPDX-License-Identifier: GPL-1.0+ OR BSD-3-Clause
|
||
|
#
|
||
|
# ====================================================================
|
||
|
# Written by Andy Polyakov, @dot-asm, originally for the OpenSSL
|
||
|
# project.
|
||
|
# ====================================================================
|
||
|
|
||
|
# Poly1305 hash for MIPS.
|
||
|
#
|
||
|
# May 2016
|
||
|
#
|
||
|
# Numbers are cycles per processed byte with poly1305_blocks alone.
|
||
|
#
|
||
|
# IALU/gcc
|
||
|
# R1x000 ~5.5/+130% (big-endian)
|
||
|
# Octeon II 2.50/+70% (little-endian)
|
||
|
#
|
||
|
# March 2019
|
||
|
#
|
||
|
# Add 32-bit code path.
|
||
|
#
|
||
|
# October 2019
|
||
|
#
|
||
|
# Modulo-scheduling reduction allows to omit dependency chain at the
|
||
|
# end of inner loop and improve performance. Also optimize MIPS32R2
|
||
|
# code path for MIPS 1004K core. Per René von Dorst's suggestions.
|
||
|
#
|
||
|
# IALU/gcc
|
||
|
# R1x000 ~9.8/? (big-endian)
|
||
|
# Octeon II 3.65/+140% (little-endian)
|
||
|
# MT7621/1004K 4.75/? (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>
|
||
|
#
|
||
|
######################################################################
|
||
|
|
||
|
$flavour = shift || "64"; # supported flavours are o32,n32,64,nubi32,nubi64
|
||
|
|
||
|
$v0 = ($flavour =~ /nubi/i) ? $a0 : $t0;
|
||
|
|
||
|
if ($flavour =~ /64|n32/i) {{{
|
||
|
######################################################################
|
||
|
# 64-bit code path
|
||
|
#
|
||
|
|
||
|
my ($ctx,$inp,$len,$padbit) = ($a0,$a1,$a2,$a3);
|
||
|
my ($in0,$in1,$tmp0,$tmp1,$tmp2,$tmp3,$tmp4) = ($a4,$a5,$a6,$a7,$at,$t0,$t1);
|
||
|
|
||
|
$code.=<<___;
|
||
|
#if (defined(_MIPS_ARCH_MIPS64R3) || defined(_MIPS_ARCH_MIPS64R5) || \\
|
||
|
defined(_MIPS_ARCH_MIPS64R6)) \\
|
||
|
&& !defined(_MIPS_ARCH_MIPS64R2)
|
||
|
# define _MIPS_ARCH_MIPS64R2
|
||
|
#endif
|
||
|
|
||
|
#if defined(_MIPS_ARCH_MIPS64R6)
|
||
|
# define dmultu(rs,rt)
|
||
|
# define mflo(rd,rs,rt) dmulu rd,rs,rt
|
||
|
# define mfhi(rd,rs,rt) dmuhu rd,rs,rt
|
||
|
#else
|
||
|
# define dmultu(rs,rt) dmultu rs,rt
|
||
|
# define mflo(rd,rs,rt) mflo rd
|
||
|
# define mfhi(rd,rs,rt) mfhi rd
|
||
|
#endif
|
||
|
|
||
|
#ifdef __KERNEL__
|
||
|
# define poly1305_init poly1305_init_mips
|
||
|
# define poly1305_blocks poly1305_blocks_mips
|
||
|
# define poly1305_emit poly1305_emit_mips
|
||
|
#endif
|
||
|
|
||
|
#if defined(__MIPSEB__) && !defined(MIPSEB)
|
||
|
# define MIPSEB
|
||
|
#endif
|
||
|
|
||
|
#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)
|
||
|
andi $tmp0,$inp,7 # $inp % 8
|
||
|
dsubu $inp,$inp,$tmp0 # align $inp
|
||
|
sll $tmp0,$tmp0,3 # byte to bit offset
|
||
|
ld $in0,0($inp)
|
||
|
ld $in1,8($inp)
|
||
|
beqz $tmp0,.Laligned_key
|
||
|
ld $tmp2,16($inp)
|
||
|
|
||
|
subu $tmp1,$zero,$tmp0
|
||
|
# ifdef MIPSEB
|
||
|
dsllv $in0,$in0,$tmp0
|
||
|
dsrlv $tmp3,$in1,$tmp1
|
||
|
dsllv $in1,$in1,$tmp0
|
||
|
dsrlv $tmp2,$tmp2,$tmp1
|
||
|
# else
|
||
|
dsrlv $in0,$in0,$tmp0
|
||
|
dsllv $tmp3,$in1,$tmp1
|
||
|
dsrlv $in1,$in1,$tmp0
|
||
|
dsllv $tmp2,$tmp2,$tmp1
|
||
|
# endif
|
||
|
or $in0,$in0,$tmp3
|
||
|
or $in1,$in1,$tmp2
|
||
|
.Laligned_key:
|
||
|
#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 # 0x0000000100000000
|
||
|
daddiu $tmp0,-63 # 0x00000000ffffffc1
|
||
|
dsll $tmp0,28 # 0x0ffffffc10000000
|
||
|
daddiu $tmp0,-1 # 0x0ffffffc0fffffff
|
||
|
|
||
|
and $in0,$tmp0
|
||
|
daddiu $tmp0,-3 # 0x0ffffffc0ffffffc
|
||
|
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 $SAVED_REGS_MASK = ($flavour =~ /nubi/i) ? "0x0003f000" : "0x00030000";
|
||
|
|
||
|
my ($h0,$h1,$h2,$r0,$r1,$rs1,$d0,$d1,$d2) =
|
||
|
($s0,$s1,$s2,$s3,$s4,$s5,$in0,$in1,$t2);
|
||
|
my ($shr,$shl) = ($s6,$s7); # used on R6
|
||
|
|
||
|
$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:
|
||
|
.set noreorder
|
||
|
#if defined(_MIPS_ARCH_MIPS64R6)
|
||
|
.frame $sp,8*8,$ra
|
||
|
.mask $SAVED_REGS_MASK|0x000c0000,-8
|
||
|
dsubu $sp,8*8
|
||
|
sd $s7,56($sp)
|
||
|
sd $s6,48($sp)
|
||
|
#else
|
||
|
.frame $sp,6*8,$ra
|
||
|
.mask $SAVED_REGS_MASK,-8
|
||
|
dsubu $sp,6*8
|
||
|
#endif
|
||
|
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
|
||
|
|
||
|
#if defined(_MIPS_ARCH_MIPS64R6)
|
||
|
andi $shr,$inp,7
|
||
|
dsubu $inp,$inp,$shr # align $inp
|
||
|
sll $shr,$shr,3 # byte to bit offset
|
||
|
subu $shl,$zero,$shr
|
||
|
#endif
|
||
|
|
||
|
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 $rs1,40($ctx)
|
||
|
|
||
|
dsll $len,4
|
||
|
daddu $len,$inp # end of buffer
|
||
|
b .Loop
|
||
|
|
||
|
.align 4
|
||
|
.Loop:
|
||
|
#if defined(_MIPS_ARCH_MIPS64R6)
|
||
|
ld $in0,0($inp) # load input
|
||
|
ld $in1,8($inp)
|
||
|
beqz $shr,.Laligned_inp
|
||
|
|
||
|
ld $tmp2,16($inp)
|
||
|
# ifdef MIPSEB
|
||
|
dsllv $in0,$in0,$shr
|
||
|
dsrlv $tmp3,$in1,$shl
|
||
|
dsllv $in1,$in1,$shr
|
||
|
dsrlv $tmp2,$tmp2,$shl
|
||
|
# else
|
||
|
dsrlv $in0,$in0,$shr
|
||
|
dsllv $tmp3,$in1,$shl
|
||
|
dsrlv $in1,$in1,$shr
|
||
|
dsllv $tmp2,$tmp2,$shl
|
||
|
# endif
|
||
|
or $in0,$in0,$tmp3
|
||
|
or $in1,$in1,$tmp2
|
||
|
.Laligned_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 $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
|
||
|
dsrl $tmp1,$h2,2 # modulo-scheduled reduction
|
||
|
andi $h2,$h2,3
|
||
|
dsll $tmp0,$tmp1,2
|
||
|
|
||
|
daddu $d0,$h0,$in0 # accumulate input
|
||
|
daddu $tmp1,$tmp0
|
||
|
sltu $tmp0,$d0,$h0
|
||
|
daddu $d0,$d0,$tmp1 # ... and residue
|
||
|
sltu $tmp1,$d0,$tmp1
|
||
|
daddu $d1,$h1,$in1
|
||
|
daddu $tmp0,$tmp1
|
||
|
sltu $tmp1,$d1,$h1
|
||
|
daddu $d1,$tmp0
|
||
|
|
||
|
dmultu ($r0,$d0) # h0*r0
|
||
|
daddu $d2,$h2,$padbit
|
||
|
sltu $tmp0,$d1,$tmp0
|
||
|
mflo ($h0,$r0,$d0)
|
||
|
mfhi ($h1,$r0,$d0)
|
||
|
|
||
|
dmultu ($rs1,$d1) # h1*5*r1
|
||
|
daddu $d2,$tmp1
|
||
|
daddu $d2,$tmp0
|
||
|
mflo ($tmp0,$rs1,$d1)
|
||
|
mfhi ($tmp1,$rs1,$d1)
|
||
|
|
||
|
dmultu ($r1,$d0) # h0*r1
|
||
|
mflo ($tmp2,$r1,$d0)
|
||
|
mfhi ($h2,$r1,$d0)
|
||
|
daddu $h0,$tmp0
|
||
|
daddu $h1,$tmp1
|
||
|
sltu $tmp0,$h0,$tmp0
|
||
|
|
||
|
dmultu ($r0,$d1) # h1*r0
|
||
|
daddu $h1,$tmp0
|
||
|
daddu $h1,$tmp2
|
||
|
mflo ($tmp0,$r0,$d1)
|
||
|
mfhi ($tmp1,$r0,$d1)
|
||
|
|
||
|
dmultu ($rs1,$d2) # h2*5*r1
|
||
|
sltu $tmp2,$h1,$tmp2
|
||
|
daddu $h2,$tmp2
|
||
|
mflo ($tmp2,$rs1,$d2)
|
||
|
|
||
|
dmultu ($r0,$d2) # h2*r0
|
||
|
daddu $h1,$tmp0
|
||
|
daddu $h2,$tmp1
|
||
|
mflo ($tmp3,$r0,$d2)
|
||
|
sltu $tmp0,$h1,$tmp0
|
||
|
daddu $h2,$tmp0
|
||
|
|
||
|
daddu $h1,$tmp2
|
||
|
sltu $tmp2,$h1,$tmp2
|
||
|
daddu $h2,$tmp2
|
||
|
daddu $h2,$tmp3
|
||
|
|
||
|
bne $inp,$len,.Loop
|
||
|
|
||
|
sd $h0,0($ctx) # store hash value
|
||
|
sd $h1,8($ctx)
|
||
|
sd $h2,16($ctx)
|
||
|
|
||
|
.set noreorder
|
||
|
#if defined(_MIPS_ARCH_MIPS64R6)
|
||
|
ld $s7,56($sp)
|
||
|
ld $s6,48($sp)
|
||
|
#endif
|
||
|
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
|
||
|
#if defined(_MIPS_ARCH_MIPS64R6)
|
||
|
daddu $sp,8*8
|
||
|
#else
|
||
|
daddu $sp,6*8
|
||
|
#endif
|
||
|
.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 $tmp2,16($ctx)
|
||
|
ld $tmp0,0($ctx)
|
||
|
ld $tmp1,8($ctx)
|
||
|
|
||
|
li $in0,-4 # final reduction
|
||
|
dsrl $in1,$tmp2,2
|
||
|
and $in0,$tmp2
|
||
|
andi $tmp2,$tmp2,3
|
||
|
daddu $in0,$in1
|
||
|
|
||
|
daddu $tmp0,$tmp0,$in0
|
||
|
sltu $in1,$tmp0,$in0
|
||
|
daddiu $in0,$tmp0,5 # compare to modulus
|
||
|
daddu $tmp1,$tmp1,$in1
|
||
|
sltiu $tmp3,$in0,5
|
||
|
sltu $tmp4,$tmp1,$in1
|
||
|
daddu $in1,$tmp1,$tmp3
|
||
|
daddu $tmp2,$tmp2,$tmp4
|
||
|
sltu $tmp3,$in1,$tmp3
|
||
|
daddu $tmp2,$tmp2,$tmp3
|
||
|
|
||
|
dsrl $tmp2,2 # see if it carried/borrowed
|
||
|
dsubu $tmp2,$zero,$tmp2
|
||
|
|
||
|
xor $in0,$tmp0
|
||
|
xor $in1,$tmp1
|
||
|
and $in0,$tmp2
|
||
|
and $in1,$tmp2
|
||
|
xor $in0,$tmp0
|
||
|
xor $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 \@dot-asm"
|
||
|
.align 2
|
||
|
___
|
||
|
}
|
||
|
}}} else {{{
|
||
|
######################################################################
|
||
|
# 32-bit code path
|
||
|
#
|
||
|
|
||
|
my ($ctx,$inp,$len,$padbit) = ($a0,$a1,$a2,$a3);
|
||
|
my ($in0,$in1,$in2,$in3,$tmp0,$tmp1,$tmp2,$tmp3) =
|
||
|
($a4,$a5,$a6,$a7,$at,$t0,$t1,$t2);
|
||
|
|
||
|
$code.=<<___;
|
||
|
#if (defined(_MIPS_ARCH_MIPS32R3) || defined(_MIPS_ARCH_MIPS32R5) || \\
|
||
|
defined(_MIPS_ARCH_MIPS32R6)) \\
|
||
|
&& !defined(_MIPS_ARCH_MIPS32R2)
|
||
|
# define _MIPS_ARCH_MIPS32R2
|
||
|
#endif
|
||
|
|
||
|
#if defined(_MIPS_ARCH_MIPS32R6)
|
||
|
# define multu(rs,rt)
|
||
|
# define mflo(rd,rs,rt) mulu rd,rs,rt
|
||
|
# define mfhi(rd,rs,rt) muhu rd,rs,rt
|
||
|
#else
|
||
|
# define multu(rs,rt) multu rs,rt
|
||
|
# define mflo(rd,rs,rt) mflo rd
|
||
|
# define mfhi(rd,rs,rt) mfhi rd
|
||
|
#endif
|
||
|
|
||
|
#ifdef __KERNEL__
|
||
|
# define poly1305_init poly1305_init_mips
|
||
|
# define poly1305_blocks poly1305_blocks_mips
|
||
|
# define poly1305_emit poly1305_emit_mips
|
||
|
#endif
|
||
|
|
||
|
#if defined(__MIPSEB__) && !defined(MIPSEB)
|
||
|
# define MIPSEB
|
||
|
#endif
|
||
|
|
||
|
#ifdef MIPSEB
|
||
|
# define MSB 0
|
||
|
# define LSB 3
|
||
|
#else
|
||
|
# define MSB 3
|
||
|
# 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
|
||
|
|
||
|
sw $zero,0($ctx)
|
||
|
sw $zero,4($ctx)
|
||
|
sw $zero,8($ctx)
|
||
|
sw $zero,12($ctx)
|
||
|
sw $zero,16($ctx)
|
||
|
|
||
|
beqz $inp,.Lno_key
|
||
|
|
||
|
#if defined(_MIPS_ARCH_MIPS32R6)
|
||
|
andi $tmp0,$inp,3 # $inp % 4
|
||
|
subu $inp,$inp,$tmp0 # align $inp
|
||
|
sll $tmp0,$tmp0,3 # byte to bit offset
|
||
|
lw $in0,0($inp)
|
||
|
lw $in1,4($inp)
|
||
|
lw $in2,8($inp)
|
||
|
lw $in3,12($inp)
|
||
|
beqz $tmp0,.Laligned_key
|
||
|
|
||
|
lw $tmp2,16($inp)
|
||
|
subu $tmp1,$zero,$tmp0
|
||
|
# ifdef MIPSEB
|
||
|
sllv $in0,$in0,$tmp0
|
||
|
srlv $tmp3,$in1,$tmp1
|
||
|
sllv $in1,$in1,$tmp0
|
||
|
or $in0,$in0,$tmp3
|
||
|
srlv $tmp3,$in2,$tmp1
|
||
|
sllv $in2,$in2,$tmp0
|
||
|
or $in1,$in1,$tmp3
|
||
|
srlv $tmp3,$in3,$tmp1
|
||
|
sllv $in3,$in3,$tmp0
|
||
|
or $in2,$in2,$tmp3
|
||
|
srlv $tmp2,$tmp2,$tmp1
|
||
|
or $in3,$in3,$tmp2
|
||
|
# else
|
||
|
srlv $in0,$in0,$tmp0
|
||
|
sllv $tmp3,$in1,$tmp1
|
||
|
srlv $in1,$in1,$tmp0
|
||
|
or $in0,$in0,$tmp3
|
||
|
sllv $tmp3,$in2,$tmp1
|
||
|
srlv $in2,$in2,$tmp0
|
||
|
or $in1,$in1,$tmp3
|
||
|
sllv $tmp3,$in3,$tmp1
|
||
|
srlv $in3,$in3,$tmp0
|
||
|
or $in2,$in2,$tmp3
|
||
|
sllv $tmp2,$tmp2,$tmp1
|
||
|
or $in3,$in3,$tmp2
|
||
|
# endif
|
||
|
.Laligned_key:
|
||
|
#else
|
||
|
lwl $in0,0+MSB($inp)
|
||
|
lwl $in1,4+MSB($inp)
|
||
|
lwl $in2,8+MSB($inp)
|
||
|
lwl $in3,12+MSB($inp)
|
||
|
lwr $in0,0+LSB($inp)
|
||
|
lwr $in1,4+LSB($inp)
|
||
|
lwr $in2,8+LSB($inp)
|
||
|
lwr $in3,12+LSB($inp)
|
||
|
#endif
|
||
|
#ifdef MIPSEB
|
||
|
# if defined(_MIPS_ARCH_MIPS32R2)
|
||
|
wsbh $in0,$in0 # byte swap
|
||
|
wsbh $in1,$in1
|
||
|
wsbh $in2,$in2
|
||
|
wsbh $in3,$in3
|
||
|
rotr $in0,$in0,16
|
||
|
rotr $in1,$in1,16
|
||
|
rotr $in2,$in2,16
|
||
|
rotr $in3,$in3,16
|
||
|
# else
|
||
|
srl $tmp0,$in0,24 # byte swap
|
||
|
srl $tmp1,$in0,8
|
||
|
andi $tmp2,$in0,0xFF00
|
||
|
sll $in0,$in0,24
|
||
|
andi $tmp1,0xFF00
|
||
|
sll $tmp2,$tmp2,8
|
||
|
or $in0,$tmp0
|
||
|
srl $tmp0,$in1,24
|
||
|
or $tmp1,$tmp2
|
||
|
srl $tmp2,$in1,8
|
||
|
or $in0,$tmp1
|
||
|
andi $tmp1,$in1,0xFF00
|
||
|
sll $in1,$in1,24
|
||
|
andi $tmp2,0xFF00
|
||
|
sll $tmp1,$tmp1,8
|
||
|
or $in1,$tmp0
|
||
|
srl $tmp0,$in2,24
|
||
|
or $tmp2,$tmp1
|
||
|
srl $tmp1,$in2,8
|
||
|
or $in1,$tmp2
|
||
|
andi $tmp2,$in2,0xFF00
|
||
|
sll $in2,$in2,24
|
||
|
andi $tmp1,0xFF00
|
||
|
sll $tmp2,$tmp2,8
|
||
|
or $in2,$tmp0
|
||
|
srl $tmp0,$in3,24
|
||
|
or $tmp1,$tmp2
|
||
|
srl $tmp2,$in3,8
|
||
|
or $in2,$tmp1
|
||
|
andi $tmp1,$in3,0xFF00
|
||
|
sll $in3,$in3,24
|
||
|
andi $tmp2,0xFF00
|
||
|
sll $tmp1,$tmp1,8
|
||
|
or $in3,$tmp0
|
||
|
or $tmp2,$tmp1
|
||
|
or $in3,$tmp2
|
||
|
# endif
|
||
|
#endif
|
||
|
lui $tmp0,0x0fff
|
||
|
ori $tmp0,0xffff # 0x0fffffff
|
||
|
and $in0,$in0,$tmp0
|
||
|
subu $tmp0,3 # 0x0ffffffc
|
||
|
and $in1,$in1,$tmp0
|
||
|
and $in2,$in2,$tmp0
|
||
|
and $in3,$in3,$tmp0
|
||
|
|
||
|
sw $in0,20($ctx)
|
||
|
sw $in1,24($ctx)
|
||
|
sw $in2,28($ctx)
|
||
|
sw $in3,32($ctx)
|
||
|
|
||
|
srl $tmp1,$in1,2
|
||
|
srl $tmp2,$in2,2
|
||
|
srl $tmp3,$in3,2
|
||
|
addu $in1,$in1,$tmp1 # s1 = r1 + (r1 >> 2)
|
||
|
addu $in2,$in2,$tmp2
|
||
|
addu $in3,$in3,$tmp3
|
||
|
sw $in1,36($ctx)
|
||
|
sw $in2,40($ctx)
|
||
|
sw $in3,44($ctx)
|
||
|
.Lno_key:
|
||
|
li $v0,0
|
||
|
jr $ra
|
||
|
.end poly1305_init
|
||
|
___
|
||
|
{
|
||
|
my $SAVED_REGS_MASK = ($flavour =~ /nubi/i) ? "0x00fff000" : "0x00ff0000";
|
||
|
|
||
|
my ($h0,$h1,$h2,$h3,$h4, $r0,$r1,$r2,$r3, $rs1,$rs2,$rs3) =
|
||
|
($s0,$s1,$s2,$s3,$s4, $s5,$s6,$s7,$s8, $s9,$s10,$s11);
|
||
|
my ($d0,$d1,$d2,$d3) =
|
||
|
($a4,$a5,$a6,$a7);
|
||
|
my $shr = $t2; # used on R6
|
||
|
my $one = $t2; # used on R2
|
||
|
|
||
|
$code.=<<___;
|
||
|
.globl poly1305_blocks
|
||
|
.align 5
|
||
|
.ent poly1305_blocks
|
||
|
poly1305_blocks:
|
||
|
.frame $sp,16*4,$ra
|
||
|
.mask $SAVED_REGS_MASK,-4
|
||
|
.set noreorder
|
||
|
subu $sp, $sp,4*12
|
||
|
sw $s11,4*11($sp)
|
||
|
sw $s10,4*10($sp)
|
||
|
sw $s9, 4*9($sp)
|
||
|
sw $s8, 4*8($sp)
|
||
|
sw $s7, 4*7($sp)
|
||
|
sw $s6, 4*6($sp)
|
||
|
sw $s5, 4*5($sp)
|
||
|
sw $s4, 4*4($sp)
|
||
|
___
|
||
|
$code.=<<___ if ($flavour =~ /nubi/i); # optimize non-nubi prologue
|
||
|
sw $s3, 4*3($sp)
|
||
|
sw $s2, 4*2($sp)
|
||
|
sw $s1, 4*1($sp)
|
||
|
sw $s0, 4*0($sp)
|
||
|
___
|
||
|
$code.=<<___;
|
||
|
.set reorder
|
||
|
|
||
|
srl $len,4 # number of complete blocks
|
||
|
li $one,1
|
||
|
beqz $len,.Labort
|
||
|
|
||
|
#if defined(_MIPS_ARCH_MIPS32R6)
|
||
|
andi $shr,$inp,3
|
||
|
subu $inp,$inp,$shr # align $inp
|
||
|
sll $shr,$shr,3 # byte to bit offset
|
||
|
#endif
|
||
|
|
||
|
lw $h0,0($ctx) # load hash value
|
||
|
lw $h1,4($ctx)
|
||
|
lw $h2,8($ctx)
|
||
|
lw $h3,12($ctx)
|
||
|
lw $h4,16($ctx)
|
||
|
|
||
|
lw $r0,20($ctx) # load key
|
||
|
lw $r1,24($ctx)
|
||
|
lw $r2,28($ctx)
|
||
|
lw $r3,32($ctx)
|
||
|
lw $rs1,36($ctx)
|
||
|
lw $rs2,40($ctx)
|
||
|
lw $rs3,44($ctx)
|
||
|
|
||
|
sll $len,4
|
||
|
addu $len,$len,$inp # end of buffer
|
||
|
b .Loop
|
||
|
|
||
|
.align 4
|
||
|
.Loop:
|
||
|
#if defined(_MIPS_ARCH_MIPS32R6)
|
||
|
lw $d0,0($inp) # load input
|
||
|
lw $d1,4($inp)
|
||
|
lw $d2,8($inp)
|
||
|
lw $d3,12($inp)
|
||
|
beqz $shr,.Laligned_inp
|
||
|
|
||
|
lw $t0,16($inp)
|
||
|
subu $t1,$zero,$shr
|
||
|
# ifdef MIPSEB
|
||
|
sllv $d0,$d0,$shr
|
||
|
srlv $at,$d1,$t1
|
||
|
sllv $d1,$d1,$shr
|
||
|
or $d0,$d0,$at
|
||
|
srlv $at,$d2,$t1
|
||
|
sllv $d2,$d2,$shr
|
||
|
or $d1,$d1,$at
|
||
|
srlv $at,$d3,$t1
|
||
|
sllv $d3,$d3,$shr
|
||
|
or $d2,$d2,$at
|
||
|
srlv $t0,$t0,$t1
|
||
|
or $d3,$d3,$t0
|
||
|
# else
|
||
|
srlv $d0,$d0,$shr
|
||
|
sllv $at,$d1,$t1
|
||
|
srlv $d1,$d1,$shr
|
||
|
or $d0,$d0,$at
|
||
|
sllv $at,$d2,$t1
|
||
|
srlv $d2,$d2,$shr
|
||
|
or $d1,$d1,$at
|
||
|
sllv $at,$d3,$t1
|
||
|
srlv $d3,$d3,$shr
|
||
|
or $d2,$d2,$at
|
||
|
sllv $t0,$t0,$t1
|
||
|
or $d3,$d3,$t0
|
||
|
# endif
|
||
|
.Laligned_inp:
|
||
|
#else
|
||
|
lwl $d0,0+MSB($inp) # load input
|
||
|
lwl $d1,4+MSB($inp)
|
||
|
lwl $d2,8+MSB($inp)
|
||
|
lwl $d3,12+MSB($inp)
|
||
|
lwr $d0,0+LSB($inp)
|
||
|
lwr $d1,4+LSB($inp)
|
||
|
lwr $d2,8+LSB($inp)
|
||
|
lwr $d3,12+LSB($inp)
|
||
|
#endif
|
||
|
#ifdef MIPSEB
|
||
|
# if defined(_MIPS_ARCH_MIPS32R2)
|
||
|
wsbh $d0,$d0 # byte swap
|
||
|
wsbh $d1,$d1
|
||
|
wsbh $d2,$d2
|
||
|
wsbh $d3,$d3
|
||
|
rotr $d0,$d0,16
|
||
|
rotr $d1,$d1,16
|
||
|
rotr $d2,$d2,16
|
||
|
rotr $d3,$d3,16
|
||
|
# else
|
||
|
srl $at,$d0,24 # byte swap
|
||
|
srl $t0,$d0,8
|
||
|
andi $t1,$d0,0xFF00
|
||
|
sll $d0,$d0,24
|
||
|
andi $t0,0xFF00
|
||
|
sll $t1,$t1,8
|
||
|
or $d0,$at
|
||
|
srl $at,$d1,24
|
||
|
or $t0,$t1
|
||
|
srl $t1,$d1,8
|
||
|
or $d0,$t0
|
||
|
andi $t0,$d1,0xFF00
|
||
|
sll $d1,$d1,24
|
||
|
andi $t1,0xFF00
|
||
|
sll $t0,$t0,8
|
||
|
or $d1,$at
|
||
|
srl $at,$d2,24
|
||
|
or $t1,$t0
|
||
|
srl $t0,$d2,8
|
||
|
or $d1,$t1
|
||
|
andi $t1,$d2,0xFF00
|
||
|
sll $d2,$d2,24
|
||
|
andi $t0,0xFF00
|
||
|
sll $t1,$t1,8
|
||
|
or $d2,$at
|
||
|
srl $at,$d3,24
|
||
|
or $t0,$t1
|
||
|
srl $t1,$d3,8
|
||
|
or $d2,$t0
|
||
|
andi $t0,$d3,0xFF00
|
||
|
sll $d3,$d3,24
|
||
|
andi $t1,0xFF00
|
||
|
sll $t0,$t0,8
|
||
|
or $d3,$at
|
||
|
or $t1,$t0
|
||
|
or $d3,$t1
|
||
|
# endif
|
||
|
#endif
|
||
|
srl $t0,$h4,2 # modulo-scheduled reduction
|
||
|
andi $h4,$h4,3
|
||
|
sll $at,$t0,2
|
||
|
|
||
|
addu $d0,$d0,$h0 # accumulate input
|
||
|
addu $t0,$t0,$at
|
||
|
sltu $h0,$d0,$h0
|
||
|
addu $d0,$d0,$t0 # ... and residue
|
||
|
sltu $at,$d0,$t0
|
||
|
|
||
|
addu $d1,$d1,$h1
|
||
|
addu $h0,$h0,$at # carry
|
||
|
sltu $h1,$d1,$h1
|
||
|
addu $d1,$d1,$h0
|
||
|
sltu $h0,$d1,$h0
|
||
|
|
||
|
addu $d2,$d2,$h2
|
||
|
addu $h1,$h1,$h0 # carry
|
||
|
sltu $h2,$d2,$h2
|
||
|
addu $d2,$d2,$h1
|
||
|
sltu $h1,$d2,$h1
|
||
|
|
||
|
addu $d3,$d3,$h3
|
||
|
addu $h2,$h2,$h1 # carry
|
||
|
sltu $h3,$d3,$h3
|
||
|
addu $d3,$d3,$h2
|
||
|
|
||
|
#if defined(_MIPS_ARCH_MIPS32R2) && !defined(_MIPS_ARCH_MIPS32R6)
|
||
|
multu $r0,$d0 # d0*r0
|
||
|
sltu $h2,$d3,$h2
|
||
|
maddu $rs3,$d1 # d1*s3
|
||
|
addu $h3,$h3,$h2 # carry
|
||
|
maddu $rs2,$d2 # d2*s2
|
||
|
addu $h4,$h4,$padbit
|
||
|
maddu $rs1,$d3 # d3*s1
|
||
|
addu $h4,$h4,$h3
|
||
|
mfhi $at
|
||
|
mflo $h0
|
||
|
|
||
|
multu $r1,$d0 # d0*r1
|
||
|
maddu $r0,$d1 # d1*r0
|
||
|
maddu $rs3,$d2 # d2*s3
|
||
|
maddu $rs2,$d3 # d3*s2
|
||
|
maddu $rs1,$h4 # h4*s1
|
||
|
maddu $at,$one # hi*1
|
||
|
mfhi $at
|
||
|
mflo $h1
|
||
|
|
||
|
multu $r2,$d0 # d0*r2
|
||
|
maddu $r1,$d1 # d1*r1
|
||
|
maddu $r0,$d2 # d2*r0
|
||
|
maddu $rs3,$d3 # d3*s3
|
||
|
maddu $rs2,$h4 # h4*s2
|
||
|
maddu $at,$one # hi*1
|
||
|
mfhi $at
|
||
|
mflo $h2
|
||
|
|
||
|
mul $t0,$r0,$h4 # h4*r0
|
||
|
|
||
|
multu $r3,$d0 # d0*r3
|
||
|
maddu $r2,$d1 # d1*r2
|
||
|
maddu $r1,$d2 # d2*r1
|
||
|
maddu $r0,$d3 # d3*r0
|
||
|
maddu $rs3,$h4 # h4*s3
|
||
|
maddu $at,$one # hi*1
|
||
|
mfhi $at
|
||
|
mflo $h3
|
||
|
|
||
|
addiu $inp,$inp,16
|
||
|
|
||
|
addu $h4,$t0,$at
|
||
|
#else
|
||
|
multu ($r0,$d0) # d0*r0
|
||
|
mflo ($h0,$r0,$d0)
|
||
|
mfhi ($h1,$r0,$d0)
|
||
|
|
||
|
sltu $h2,$d3,$h2
|
||
|
addu $h3,$h3,$h2 # carry
|
||
|
|
||
|
multu ($rs3,$d1) # d1*s3
|
||
|
mflo ($at,$rs3,$d1)
|
||
|
mfhi ($t0,$rs3,$d1)
|
||
|
|
||
|
addu $h4,$h4,$padbit
|
||
|
addiu $inp,$inp,16
|
||
|
addu $h4,$h4,$h3
|
||
|
|
||
|
multu ($rs2,$d2) # d2*s2
|
||
|
mflo ($a3,$rs2,$d2)
|
||
|
mfhi ($t1,$rs2,$d2)
|
||
|
addu $h0,$h0,$at
|
||
|
addu $h1,$h1,$t0
|
||
|
multu ($rs1,$d3) # d3*s1
|
||
|
sltu $at,$h0,$at
|
||
|
addu $h1,$h1,$at
|
||
|
|
||
|
mflo ($at,$rs1,$d3)
|
||
|
mfhi ($t0,$rs1,$d3)
|
||
|
addu $h0,$h0,$a3
|
||
|
addu $h1,$h1,$t1
|
||
|
multu ($r1,$d0) # d0*r1
|
||
|
sltu $a3,$h0,$a3
|
||
|
addu $h1,$h1,$a3
|
||
|
|
||
|
|
||
|
mflo ($a3,$r1,$d0)
|
||
|
mfhi ($h2,$r1,$d0)
|
||
|
addu $h0,$h0,$at
|
||
|
addu $h1,$h1,$t0
|
||
|
multu ($r0,$d1) # d1*r0
|
||
|
sltu $at,$h0,$at
|
||
|
addu $h1,$h1,$at
|
||
|
|
||
|
mflo ($at,$r0,$d1)
|
||
|
mfhi ($t0,$r0,$d1)
|
||
|
addu $h1,$h1,$a3
|
||
|
sltu $a3,$h1,$a3
|
||
|
multu ($rs3,$d2) # d2*s3
|
||
|
addu $h2,$h2,$a3
|
||
|
|
||
|
mflo ($a3,$rs3,$d2)
|
||
|
mfhi ($t1,$rs3,$d2)
|
||
|
addu $h1,$h1,$at
|
||
|
addu $h2,$h2,$t0
|
||
|
multu ($rs2,$d3) # d3*s2
|
||
|
sltu $at,$h1,$at
|
||
|
addu $h2,$h2,$at
|
||
|
|
||
|
mflo ($at,$rs2,$d3)
|
||
|
mfhi ($t0,$rs2,$d3)
|
||
|
addu $h1,$h1,$a3
|
||
|
addu $h2,$h2,$t1
|
||
|
multu ($rs1,$h4) # h4*s1
|
||
|
sltu $a3,$h1,$a3
|
||
|
addu $h2,$h2,$a3
|
||
|
|
||
|
mflo ($a3,$rs1,$h4)
|
||
|
addu $h1,$h1,$at
|
||
|
addu $h2,$h2,$t0
|
||
|
multu ($r2,$d0) # d0*r2
|
||
|
sltu $at,$h1,$at
|
||
|
addu $h2,$h2,$at
|
||
|
|
||
|
|
||
|
mflo ($at,$r2,$d0)
|
||
|
mfhi ($h3,$r2,$d0)
|
||
|
addu $h1,$h1,$a3
|
||
|
sltu $a3,$h1,$a3
|
||
|
multu ($r1,$d1) # d1*r1
|
||
|
addu $h2,$h2,$a3
|
||
|
|
||
|
mflo ($a3,$r1,$d1)
|
||
|
mfhi ($t1,$r1,$d1)
|
||
|
addu $h2,$h2,$at
|
||
|
sltu $at,$h2,$at
|
||
|
multu ($r0,$d2) # d2*r0
|
||
|
addu $h3,$h3,$at
|
||
|
|
||
|
mflo ($at,$r0,$d2)
|
||
|
mfhi ($t0,$r0,$d2)
|
||
|
addu $h2,$h2,$a3
|
||
|
addu $h3,$h3,$t1
|
||
|
multu ($rs3,$d3) # d3*s3
|
||
|
sltu $a3,$h2,$a3
|
||
|
addu $h3,$h3,$a3
|
||
|
|
||
|
mflo ($a3,$rs3,$d3)
|
||
|
mfhi ($t1,$rs3,$d3)
|
||
|
addu $h2,$h2,$at
|
||
|
addu $h3,$h3,$t0
|
||
|
multu ($rs2,$h4) # h4*s2
|
||
|
sltu $at,$h2,$at
|
||
|
addu $h3,$h3,$at
|
||
|
|
||
|
mflo ($at,$rs2,$h4)
|
||
|
addu $h2,$h2,$a3
|
||
|
addu $h3,$h3,$t1
|
||
|
multu ($r3,$d0) # d0*r3
|
||
|
sltu $a3,$h2,$a3
|
||
|
addu $h3,$h3,$a3
|
||
|
|
||
|
|
||
|
mflo ($a3,$r3,$d0)
|
||
|
mfhi ($t1,$r3,$d0)
|
||
|
addu $h2,$h2,$at
|
||
|
sltu $at,$h2,$at
|
||
|
multu ($r2,$d1) # d1*r2
|
||
|
addu $h3,$h3,$at
|
||
|
|
||
|
mflo ($at,$r2,$d1)
|
||
|
mfhi ($t0,$r2,$d1)
|
||
|
addu $h3,$h3,$a3
|
||
|
sltu $a3,$h3,$a3
|
||
|
multu ($r0,$d3) # d3*r0
|
||
|
addu $t1,$t1,$a3
|
||
|
|
||
|
mflo ($a3,$r0,$d3)
|
||
|
mfhi ($d3,$r0,$d3)
|
||
|
addu $h3,$h3,$at
|
||
|
addu $t1,$t1,$t0
|
||
|
multu ($r1,$d2) # d2*r1
|
||
|
sltu $at,$h3,$at
|
||
|
addu $t1,$t1,$at
|
||
|
|
||
|
mflo ($at,$r1,$d2)
|
||
|
mfhi ($t0,$r1,$d2)
|
||
|
addu $h3,$h3,$a3
|
||
|
addu $t1,$t1,$d3
|
||
|
multu ($rs3,$h4) # h4*s3
|
||
|
sltu $a3,$h3,$a3
|
||
|
addu $t1,$t1,$a3
|
||
|
|
||
|
mflo ($a3,$rs3,$h4)
|
||
|
addu $h3,$h3,$at
|
||
|
addu $t1,$t1,$t0
|
||
|
multu ($r0,$h4) # h4*r0
|
||
|
sltu $at,$h3,$at
|
||
|
addu $t1,$t1,$at
|
||
|
|
||
|
|
||
|
mflo ($h4,$r0,$h4)
|
||
|
addu $h3,$h3,$a3
|
||
|
sltu $a3,$h3,$a3
|
||
|
addu $t1,$t1,$a3
|
||
|
addu $h4,$h4,$t1
|
||
|
|
||
|
li $padbit,1 # if we loop, padbit is 1
|
||
|
#endif
|
||
|
bne $inp,$len,.Loop
|
||
|
|
||
|
sw $h0,0($ctx) # store hash value
|
||
|
sw $h1,4($ctx)
|
||
|
sw $h2,8($ctx)
|
||
|
sw $h3,12($ctx)
|
||
|
sw $h4,16($ctx)
|
||
|
|
||
|
.set noreorder
|
||
|
.Labort:
|
||
|
lw $s11,4*11($sp)
|
||
|
lw $s10,4*10($sp)
|
||
|
lw $s9, 4*9($sp)
|
||
|
lw $s8, 4*8($sp)
|
||
|
lw $s7, 4*7($sp)
|
||
|
lw $s6, 4*6($sp)
|
||
|
lw $s5, 4*5($sp)
|
||
|
lw $s4, 4*4($sp)
|
||
|
___
|
||
|
$code.=<<___ if ($flavour =~ /nubi/i); # optimize non-nubi prologue
|
||
|
lw $s3, 4*3($sp)
|
||
|
lw $s2, 4*2($sp)
|
||
|
lw $s1, 4*1($sp)
|
||
|
lw $s0, 4*0($sp)
|
||
|
___
|
||
|
$code.=<<___;
|
||
|
jr $ra
|
||
|
addu $sp,$sp,4*12
|
||
|
.end poly1305_blocks
|
||
|
___
|
||
|
}
|
||
|
{
|
||
|
my ($ctx,$mac,$nonce,$tmp4) = ($a0,$a1,$a2,$a3);
|
||
|
|
||
|
$code.=<<___;
|
||
|
.align 5
|
||
|
.globl poly1305_emit
|
||
|
.ent poly1305_emit
|
||
|
poly1305_emit:
|
||
|
.frame $sp,0,$ra
|
||
|
.set reorder
|
||
|
|
||
|
lw $tmp4,16($ctx)
|
||
|
lw $tmp0,0($ctx)
|
||
|
lw $tmp1,4($ctx)
|
||
|
lw $tmp2,8($ctx)
|
||
|
lw $tmp3,12($ctx)
|
||
|
|
||
|
li $in0,-4 # final reduction
|
||
|
srl $ctx,$tmp4,2
|
||
|
and $in0,$in0,$tmp4
|
||
|
andi $tmp4,$tmp4,3
|
||
|
addu $ctx,$ctx,$in0
|
||
|
|
||
|
addu $tmp0,$tmp0,$ctx
|
||
|
sltu $ctx,$tmp0,$ctx
|
||
|
addiu $in0,$tmp0,5 # compare to modulus
|
||
|
addu $tmp1,$tmp1,$ctx
|
||
|
sltiu $in1,$in0,5
|
||
|
sltu $ctx,$tmp1,$ctx
|
||
|
addu $in1,$in1,$tmp1
|
||
|
addu $tmp2,$tmp2,$ctx
|
||
|
sltu $in2,$in1,$tmp1
|
||
|
sltu $ctx,$tmp2,$ctx
|
||
|
addu $in2,$in2,$tmp2
|
||
|
addu $tmp3,$tmp3,$ctx
|
||
|
sltu $in3,$in2,$tmp2
|
||
|
sltu $ctx,$tmp3,$ctx
|
||
|
addu $in3,$in3,$tmp3
|
||
|
addu $tmp4,$tmp4,$ctx
|
||
|
sltu $ctx,$in3,$tmp3
|
||
|
addu $ctx,$tmp4
|
||
|
|
||
|
srl $ctx,2 # see if it carried/borrowed
|
||
|
subu $ctx,$zero,$ctx
|
||
|
|
||
|
xor $in0,$tmp0
|
||
|
xor $in1,$tmp1
|
||
|
xor $in2,$tmp2
|
||
|
xor $in3,$tmp3
|
||
|
and $in0,$ctx
|
||
|
and $in1,$ctx
|
||
|
and $in2,$ctx
|
||
|
and $in3,$ctx
|
||
|
xor $in0,$tmp0
|
||
|
xor $in1,$tmp1
|
||
|
xor $in2,$tmp2
|
||
|
xor $in3,$tmp3
|
||
|
|
||
|
lw $tmp0,0($nonce) # load nonce
|
||
|
lw $tmp1,4($nonce)
|
||
|
lw $tmp2,8($nonce)
|
||
|
lw $tmp3,12($nonce)
|
||
|
|
||
|
addu $in0,$tmp0 # accumulate nonce
|
||
|
sltu $ctx,$in0,$tmp0
|
||
|
|
||
|
addu $in1,$tmp1
|
||
|
sltu $tmp1,$in1,$tmp1
|
||
|
addu $in1,$ctx
|
||
|
sltu $ctx,$in1,$ctx
|
||
|
addu $ctx,$tmp1
|
||
|
|
||
|
addu $in2,$tmp2
|
||
|
sltu $tmp2,$in2,$tmp2
|
||
|
addu $in2,$ctx
|
||
|
sltu $ctx,$in2,$ctx
|
||
|
addu $ctx,$tmp2
|
||
|
|
||
|
addu $in3,$tmp3
|
||
|
addu $in3,$ctx
|
||
|
|
||
|
srl $tmp0,$in0,8 # write mac value
|
||
|
srl $tmp1,$in0,16
|
||
|
srl $tmp2,$in0,24
|
||
|
sb $in0, 0($mac)
|
||
|
sb $tmp0,1($mac)
|
||
|
srl $tmp0,$in1,8
|
||
|
sb $tmp1,2($mac)
|
||
|
srl $tmp1,$in1,16
|
||
|
sb $tmp2,3($mac)
|
||
|
srl $tmp2,$in1,24
|
||
|
sb $in1, 4($mac)
|
||
|
sb $tmp0,5($mac)
|
||
|
srl $tmp0,$in2,8
|
||
|
sb $tmp1,6($mac)
|
||
|
srl $tmp1,$in2,16
|
||
|
sb $tmp2,7($mac)
|
||
|
srl $tmp2,$in2,24
|
||
|
sb $in2, 8($mac)
|
||
|
sb $tmp0,9($mac)
|
||
|
srl $tmp0,$in3,8
|
||
|
sb $tmp1,10($mac)
|
||
|
srl $tmp1,$in3,16
|
||
|
sb $tmp2,11($mac)
|
||
|
srl $tmp2,$in3,24
|
||
|
sb $in3, 12($mac)
|
||
|
sb $tmp0,13($mac)
|
||
|
sb $tmp1,14($mac)
|
||
|
sb $tmp2,15($mac)
|
||
|
|
||
|
jr $ra
|
||
|
.end poly1305_emit
|
||
|
.rdata
|
||
|
.asciiz "Poly1305 for MIPS32, CRYPTOGAMS by \@dot-asm"
|
||
|
.align 2
|
||
|
___
|
||
|
}
|
||
|
}}}
|
||
|
|
||
|
$output=pop and open STDOUT,">$output";
|
||
|
print $code;
|
||
|
close STDOUT;
|