sha1-mips.pl 10.5 KB
Newer Older
R
Rich Salz 已提交
1
#! /usr/bin/env perl
M
Matt Caswell 已提交
2
# Copyright 2009-2018 The OpenSSL Project Authors. All Rights Reserved.
R
Rich Salz 已提交
3 4 5 6 7 8
#
# Licensed under the OpenSSL license (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

9 10

# ====================================================================
11
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
12 13 14 15 16 17 18 19 20 21 22 23
# 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/.
# ====================================================================

# SHA1 block procedure for MIPS.

# Performance improvement is 30% on unaligned input. The "secret" is
# to deploy lwl/lwr pair to load unaligned input. One could have
# vectorized Xupdate on MIPSIII/IV, but the goal was to code MIPS32-
# compatible subroutine. There is room for minor optimization on
# little-endian platforms...
24

25 26
# September 2012.
#
27
# Add MIPS32r2 code (>25% less instructions).
28

29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
######################################################################
# 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));
#
56
$flavour = shift || "o32"; # supported flavours are o32,n32,64,nubi32,nubi64
57 58

if ($flavour =~ /64|n32/i) {
59 60
	$PTR_ADD="daddu";	# incidentally works even on n32
	$PTR_SUB="dsubu";	# incidentally works even on n32
61 62 63 64 65
	$REG_S="sd";
	$REG_L="ld";
	$PTR_SLL="dsll";	# incidentally works even on n32
	$SZREG=8;
} else {
66 67
	$PTR_ADD="addu";
	$PTR_SUB="subu";
68 69 70 71 72 73 74
	$REG_S="sw";
	$REG_L="lw";
	$PTR_SLL="sll";
	$SZREG=4;
}
#
# <appro@openssl.org>
75
#
76 77
######################################################################

78
$big_endian=(`echo MIPSEB | $ENV{CC} -E -`=~/MIPSEB/)?0:1 if ($ENV{CC});
79

80
for (@ARGV) {	$output=$_ if (/\w[\w\-]*\.\w+$/);   }
81
open STDOUT,">$output";
82 83 84 85 86 87 88 89

if (!defined($big_endian))
            {   $big_endian=(unpack('L',pack('N',1))==1);   }

# offsets of the Most and Least Significant Bytes
$MSB=$big_endian?0:3;
$LSB=3&~$MSB;

90 91 92 93 94
@X=map("\$$_",(8..23));	# a4-a7,s0-s11

$ctx=$a0;
$inp=$a1;
$num=$a2;
95 96 97 98 99
$A="\$1";
$B="\$2";
$C="\$3";
$D="\$7";
$E="\$24";	@V=($A,$B,$C,$D,$E);
100 101 102
$t0="\$25";
$t1=$num;	# $num is offloaded to stack
$t2="\$30";	# fp
103 104 105 106 107 108
$K="\$31";	# ra

sub BODY_00_14 {
my ($i,$a,$b,$c,$d,$e)=@_;
my $j=$i+1;
$code.=<<___	if (!$big_endian);
109 110 111 112
#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
	wsbh	@X[$i],@X[$i]	# byte swap($i)
	rotr	@X[$i],@X[$i],16
#else
113 114 115 116 117 118 119
	srl	$t0,@X[$i],24	# byte swap($i)
	srl	$t1,@X[$i],8
	andi	$t2,@X[$i],0xFF00
	sll	@X[$i],@X[$i],24
	andi	$t1,0xFF00
	sll	$t2,$t2,8
	or	@X[$i],$t0
120
	or	$t1,$t2
121
	or	@X[$i],$t1
122
#endif
123 124
___
$code.=<<___;
125 126 127 128 129 130
#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
	addu	$e,$K		# $i
	xor	$t0,$c,$d
	rotr	$t1,$a,27
	and	$t0,$b
	addu	$e,$t1
131 132 133 134
#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6)
	 lw	@X[$j],$j*4($inp)
#else
	 lwl	@X[$j],$j*4+$MSB($inp)
135
	 lwr	@X[$j],$j*4+$LSB($inp)
136
#endif
137 138 139 140 141
	xor	$t0,$d
	addu	$e,@X[$i]
	rotr	$b,$b,2
	addu	$e,$t0
#else
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
	 lwl	@X[$j],$j*4+$MSB($inp)
	sll	$t0,$a,5	# $i
	addu	$e,$K
	 lwr	@X[$j],$j*4+$LSB($inp)
	srl	$t1,$a,27
	addu	$e,$t0
	xor	$t0,$c,$d
	addu	$e,$t1
	sll	$t2,$b,30
	and	$t0,$b
	srl	$b,$b,2
	xor	$t0,$d
	addu	$e,@X[$i]
	or	$b,$t2
	addu	$e,$t0
157
#endif
158 159 160 161 162 163 164 165
___
}

sub BODY_15_19 {
my ($i,$a,$b,$c,$d,$e)=@_;
my $j=$i+1;

$code.=<<___	if (!$big_endian && $i==15);
166 167 168 169
#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
	wsbh	@X[$i],@X[$i]	# byte swap($i)
	rotr	@X[$i],@X[$i],16
#else
170 171 172 173 174 175 176 177 178
	srl	$t0,@X[$i],24	# byte swap($i)
	srl	$t1,@X[$i],8
	andi	$t2,@X[$i],0xFF00
	sll	@X[$i],@X[$i],24
	andi	$t1,0xFF00
	sll	$t2,$t2,8
	or	@X[$i],$t0
	or	@X[$i],$t1
	or	@X[$i],$t2
179
#endif
180 181
___
$code.=<<___;
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
#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
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
	 xor	@X[$j%16],@X[($j+2)%16]
	sll	$t0,$a,5	# $i
	addu	$e,$K
	srl	$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]
	sll	$t2,$b,30
	and	$t0,$b
	 srl	$t1,@X[$j%16],31
	 addu	@X[$j%16],@X[$j%16]
	srl	$b,$b,2
	xor	$t0,$d
	 or	@X[$j%16],$t1
	addu	$e,@X[$i%16]
	or	$b,$t2
	addu	$e,$t0
216
#endif
217 218 219 220 221 222 223
___
}

sub BODY_20_39 {
my ($i,$a,$b,$c,$d,$e)=@_;
my $j=$i+1;
$code.=<<___ if ($i<79);
224 225 226 227 228 229 230 231 232 233 234 235 236 237
#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
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
	 xor	@X[$j%16],@X[($j+2)%16]
	sll	$t0,$a,5	# $i
	addu	$e,$K
	srl	$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]
	sll	$t2,$b,30
	xor	$t0,$b
	 srl	$t1,@X[$j%16],31
	 addu	@X[$j%16],@X[$j%16]
	srl	$b,$b,2
	addu	$e,@X[$i%16]
	 or	@X[$j%16],$t1
	or	$b,$t2
	addu	$e,$t0
256
#endif
257 258
___
$code.=<<___ if ($i==79);
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
#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
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
	 lw	@X[0],0($ctx)
	sll	$t0,$a,5	# $i
	addu	$e,$K
	 lw	@X[1],4($ctx)
	srl	$t1,$a,27
	addu	$e,$t0
	 lw	@X[2],8($ctx)
	xor	$t0,$c,$d
	addu	$e,$t1
	 lw	@X[3],12($ctx)
	sll	$t2,$b,30
	xor	$t0,$b
	 lw	@X[4],16($ctx)
	srl	$b,$b,2
	addu	$e,@X[$i%16]
	or	$b,$t2
	addu	$e,$t0
291
#endif
292 293 294 295 296 297 298
___
}

sub BODY_40_59 {
my ($i,$a,$b,$c,$d,$e)=@_;
my $j=$i+1;
$code.=<<___ if ($i<79);
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
#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
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
	 xor	@X[$j%16],@X[($j+2)%16]
	sll	$t0,$a,5	# $i
	addu	$e,$K
	srl	$t1,$a,27
	addu	$e,$t0
	 xor	@X[$j%16],@X[($j+8)%16]
	and	$t0,$c,$d
	addu	$e,$t1
	 xor	@X[$j%16],@X[($j+13)%16]
	sll	$t2,$b,30
	addu	$e,$t0
	 srl	$t1,@X[$j%16],31
	xor	$t0,$c,$d
	 addu	@X[$j%16],@X[$j%16]
	and	$t0,$b
	srl	$b,$b,2
	 or	@X[$j%16],$t1
	addu	$e,@X[$i%16]
	or	$b,$t2
	addu	$e,$t0
335
#endif
336 337 338
___
}

F
FdaSilvaYY 已提交
339
$FRAMESIZE=16;	# large enough to accommodate NUBI saved registers
340
$SAVED_REGS_MASK = ($flavour =~ /nubi/i) ? "0xc0fff008" : "0xc0ff0000";
341

342
$code=<<___;
343 344
#include "mips_arch.h"

345 346 347 348 349 350 351 352
.text

.set	noat
.set	noreorder
.align	5
.globl	sha1_block_data_order
.ent	sha1_block_data_order
sha1_block_data_order:
353
	.frame	$sp,$FRAMESIZE*$SZREG,$ra
354
	.mask	$SAVED_REGS_MASK,-$SZREG
355
	.set	noreorder
356 357 358 359 360 361 362 363 364 365 366 367
	$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)
___
368
$code.=<<___ if ($flavour =~ /nubi/i);	# optimize non-nubi prologue
369 370 371 372 373 374 375 376 377 378
	$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)
379 380 381 382 383 384 385 386 387
	lw	$A,0($ctx)
	lw	$B,4($ctx)
	lw	$C,8($ctx)
	lw	$D,12($ctx)
	b	.Loop
	lw	$E,16($ctx)
.align	4
.Loop:
	.set	reorder
388 389 390 391 392
#if defined(_MIPS_ARCH_MIPS32R6) || defined(_MIPS_ARCH_MIPS64R6)
	lui	$K,0x5a82
	lw	@X[0],($inp)
	ori	$K,0x7999	# K_00_19
#else
393 394 395 396
	lwl	@X[0],$MSB($inp)
	lui	$K,0x5a82
	lwr	@X[0],$LSB($inp)
	ori	$K,0x7999	# K_00_19
397
#endif
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
___
for ($i=0;$i<15;$i++)	{ &BODY_00_14($i,@V); unshift(@V,pop(@V)); }
for (;$i<20;$i++)	{ &BODY_15_19($i,@V); unshift(@V,pop(@V)); }
$code.=<<___;
	lui	$K,0x6ed9
	ori	$K,0xeba1	# K_20_39
___
for (;$i<40;$i++)	{ &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
$code.=<<___;
	lui	$K,0x8f1b
	ori	$K,0xbcdc	# K_40_59
___
for (;$i<60;$i++)	{ &BODY_40_59($i,@V); unshift(@V,pop(@V)); }
$code.=<<___;
	lui	$K,0xca62
	ori	$K,0xc1d6	# K_60_79
___
for (;$i<80;$i++)	{ &BODY_20_39($i,@V); unshift(@V,pop(@V)); }
$code.=<<___;
417 418 419
	$PTR_ADD $inp,64
	$REG_L	$num,0($sp)

420 421 422 423 424 425 426 427 428 429 430
	addu	$A,$X[0]
	addu	$B,$X[1]
	sw	$A,0($ctx)
	addu	$C,$X[2]
	addu	$D,$X[3]
	sw	$B,4($ctx)
	addu	$E,$X[4]
	sw	$C,8($ctx)
	sw	$D,12($ctx)
	sw	$E,16($ctx)
	.set	noreorder
431 432
	bne	$inp,$num,.Loop
	nop
433 434

	.set	noreorder
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
	$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
456
.end	sha1_block_data_order
457 458
.rdata
.asciiz	"SHA1 for MIPS, CRYPTOGAMS by <appro\@openssl.org>"
459 460 461
___
print $code;
close STDOUT;