Home | History | Annotate | Download | only in asm
      1 #!/usr/bin/env perl
      2 
      3 # ====================================================================
      4 # Written by Andy Polyakov <appro (at] fy.chalmers.se> for the OpenSSL
      5 # project. The module is, however, dual licensed under OpenSSL and
      6 # CRYPTOGAMS licenses depending on where you obtain it. For further
      7 # details see http://www.openssl.org/~appro/cryptogams/.
      8 # ====================================================================
      9 
     10 # sha1_block procedure for ARMv4.
     11 #
     12 # January 2007.
     13 
     14 # Size/performance trade-off
     15 # ====================================================================
     16 # impl		size in bytes	comp cycles[*]	measured performance
     17 # ====================================================================
     18 # thumb		304		3212		4420
     19 # armv4-small	392/+29%	1958/+64%	2250/+96%
     20 # armv4-compact	740/+89%	1552/+26%	1840/+22%
     21 # armv4-large	1420/+92%	1307/+19%	1370/+34%[***]
     22 # full unroll	~5100/+260%	~1260/+4%	~1300/+5%
     23 # ====================================================================
     24 # thumb		= same as 'small' but in Thumb instructions[**] and
     25 #		  with recurring code in two private functions;
     26 # small		= detached Xload/update, loops are folded;
     27 # compact	= detached Xload/update, 5x unroll;
     28 # large		= interleaved Xload/update, 5x unroll;
     29 # full unroll	= interleaved Xload/update, full unroll, estimated[!];
     30 #
     31 # [*]	Manually counted instructions in "grand" loop body. Measured
     32 #	performance is affected by prologue and epilogue overhead,
     33 #	i-cache availability, branch penalties, etc.
     34 # [**]	While each Thumb instruction is twice smaller, they are not as
     35 #	diverse as ARM ones: e.g., there are only two arithmetic
     36 #	instructions with 3 arguments, no [fixed] rotate, addressing
     37 #	modes are limited. As result it takes more instructions to do
     38 #	the same job in Thumb, therefore the code is never twice as
     39 #	small and always slower.
     40 # [***]	which is also ~35% better than compiler generated code. Dual-
     41 #	issue Cortex A8 core was measured to process input block in
     42 #	~990 cycles.
     43 
     44 # August 2010.
     45 #
     46 # Rescheduling for dual-issue pipeline resulted in 13% improvement on
     47 # Cortex A8 core and in absolute terms ~870 cycles per input block
     48 # [or 13.6 cycles per byte].
     49 
     50 
     51 while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
     52 open STDOUT,">$output";
     53 
     54 $ctx="r0";
     55 $inp="r1";
     56 $len="r2";
     57 $a="r3";
     58 $b="r4";
     59 $c="r5";
     60 $d="r6";
     61 $e="r7";
     62 $K="r8";
     63 $t0="r9";
     64 $t1="r10";
     65 $t2="r11";
     66 $t3="r12";
     67 $Xi="r14";
     68 @V=($a,$b,$c,$d,$e);
     69 
     70 sub Xupdate {
     71 my ($a,$b,$c,$d,$e,$opt1,$opt2)=@_;
     72 $code.=<<___;
     73 	ldr	$t0,[$Xi,#15*4]
     74 	ldr	$t1,[$Xi,#13*4]
     75 	ldr	$t2,[$Xi,#7*4]
     76 	add	$e,$K,$e,ror#2			@ E+=K_xx_xx
     77 	ldr	$t3,[$Xi,#2*4]
     78 	eor	$t0,$t0,$t1
     79 	eor	$t2,$t2,$t3
     80 	eor	$t1,$c,$d			@ F_xx_xx
     81 	mov	$t0,$t0,ror#31
     82 	add	$e,$e,$a,ror#27			@ E+=ROR(A,27)
     83 	eor	$t0,$t0,$t2,ror#31
     84 	$opt1					@ F_xx_xx
     85 	$opt2					@ F_xx_xx
     86 	add	$e,$e,$t0			@ E+=X[i]
     87 	str	$t0,[$Xi,#-4]!
     88 ___
     89 }
     90 
     91 sub BODY_00_15 {
     92 my ($a,$b,$c,$d,$e)=@_;
     93 $code.=<<___;
     94 	ldrb	$t0,[$inp],#4
     95 	ldrb	$t1,[$inp,#-1]
     96 	ldrb	$t2,[$inp,#-2]
     97 	add	$e,$K,$e,ror#2			@ E+=K_00_19
     98 	ldrb	$t3,[$inp,#-3]
     99 	add	$e,$e,$a,ror#27			@ E+=ROR(A,27)
    100 	orr	$t0,$t1,$t0,lsl#24
    101 	eor	$t1,$c,$d			@ F_xx_xx
    102 	orr	$t0,$t0,$t2,lsl#8
    103 	orr	$t0,$t0,$t3,lsl#16
    104 	and	$t1,$b,$t1,ror#2
    105 	add	$e,$e,$t0			@ E+=X[i]
    106 	eor	$t1,$t1,$d,ror#2		@ F_00_19(B,C,D)
    107 	str	$t0,[$Xi,#-4]!
    108 	add	$e,$e,$t1			@ E+=F_00_19(B,C,D)
    109 ___
    110 }
    111 
    112 sub BODY_16_19 {
    113 my ($a,$b,$c,$d,$e)=@_;
    114 	&Xupdate(@_,"and $t1,$b,$t1,ror#2");
    115 $code.=<<___;
    116 	eor	$t1,$t1,$d,ror#2		@ F_00_19(B,C,D)
    117 	add	$e,$e,$t1			@ E+=F_00_19(B,C,D)
    118 ___
    119 }
    120 
    121 sub BODY_20_39 {
    122 my ($a,$b,$c,$d,$e)=@_;
    123 	&Xupdate(@_,"eor $t1,$b,$t1,ror#2");
    124 $code.=<<___;
    125 	add	$e,$e,$t1			@ E+=F_20_39(B,C,D)
    126 ___
    127 }
    128 
    129 sub BODY_40_59 {
    130 my ($a,$b,$c,$d,$e)=@_;
    131 	&Xupdate(@_,"and $t1,$b,$t1,ror#2","and $t2,$c,$d");
    132 $code.=<<___;
    133 	add	$e,$e,$t1			@ E+=F_40_59(B,C,D)
    134 	add	$e,$e,$t2,ror#2
    135 ___
    136 }
    137 
    138 $code=<<___;
    139 .text
    140 
    141 .global	sha1_block_data_order
    142 .type	sha1_block_data_order,%function
    143 
    144 .align	2
    145 sha1_block_data_order:
    146 	stmdb	sp!,{r4-r12,lr}
    147 	add	$len,$inp,$len,lsl#6	@ $len to point at the end of $inp
    148 	ldmia	$ctx,{$a,$b,$c,$d,$e}
    149 .Lloop:
    150 	ldr	$K,.LK_00_19
    151 	mov	$Xi,sp
    152 	sub	sp,sp,#15*4
    153 	mov	$c,$c,ror#30
    154 	mov	$d,$d,ror#30
    155 	mov	$e,$e,ror#30		@ [6]
    156 .L_00_15:
    157 ___
    158 for($i=0;$i<5;$i++) {
    159 	&BODY_00_15(@V);	unshift(@V,pop(@V));
    160 }
    161 $code.=<<___;
    162 	teq	$Xi,sp
    163 	bne	.L_00_15		@ [((11+4)*5+2)*3]
    164 	sub	sp,sp,#5*4
    165 ___
    166 	&BODY_00_15(@V);	unshift(@V,pop(@V));
    167 	&BODY_16_19(@V);	unshift(@V,pop(@V));
    168 	&BODY_16_19(@V);	unshift(@V,pop(@V));
    169 	&BODY_16_19(@V);	unshift(@V,pop(@V));
    170 	&BODY_16_19(@V);	unshift(@V,pop(@V));
    171 $code.=<<___;
    172 
    173 	ldr	$K,.LK_20_39		@ [+15+16*4]
    174 	sub	sp,sp,#20*4
    175 	cmn	sp,#0			@ [+3], clear carry to denote 20_39
    176 .L_20_39_or_60_79:
    177 ___
    178 for($i=0;$i<5;$i++) {
    179 	&BODY_20_39(@V);	unshift(@V,pop(@V));
    180 }
    181 $code.=<<___;
    182 	teq	$Xi,sp			@ preserve carry
    183 	bne	.L_20_39_or_60_79	@ [+((12+3)*5+2)*4]
    184 	bcs	.L_done			@ [+((12+3)*5+2)*4], spare 300 bytes
    185 
    186 	ldr	$K,.LK_40_59
    187 	sub	sp,sp,#20*4		@ [+2]
    188 .L_40_59:
    189 ___
    190 for($i=0;$i<5;$i++) {
    191 	&BODY_40_59(@V);	unshift(@V,pop(@V));
    192 }
    193 $code.=<<___;
    194 	teq	$Xi,sp
    195 	bne	.L_40_59		@ [+((12+5)*5+2)*4]
    196 
    197 	ldr	$K,.LK_60_79
    198 	sub	sp,sp,#20*4
    199 	cmp	sp,#0			@ set carry to denote 60_79
    200 	b	.L_20_39_or_60_79	@ [+4], spare 300 bytes
    201 .L_done:
    202 	add	sp,sp,#80*4		@ "deallocate" stack frame
    203 	ldmia	$ctx,{$K,$t0,$t1,$t2,$t3}
    204 	add	$a,$K,$a
    205 	add	$b,$t0,$b
    206 	add	$c,$t1,$c,ror#2
    207 	add	$d,$t2,$d,ror#2
    208 	add	$e,$t3,$e,ror#2
    209 	stmia	$ctx,{$a,$b,$c,$d,$e}
    210 	teq	$inp,$len
    211 	bne	.Lloop			@ [+18], total 1307
    212 
    213 	ldmia	sp!,{r4-r12,lr}
    214 	tst	lr,#1
    215 	moveq	pc,lr			@ be binary compatible with V4, yet
    216 	bx	lr			@ interoperable with Thumb ISA:-)
    217 .align	2
    218 .LK_00_19:	.word	0x5a827999
    219 .LK_20_39:	.word	0x6ed9eba1
    220 .LK_40_59:	.word	0x8f1bbcdc
    221 .LK_60_79:	.word	0xca62c1d6
    222 .size	sha1_block_data_order,.-sha1_block_data_order
    223 .asciz	"SHA1 block transform for ARMv4, CRYPTOGAMS by <appro\@openssl.org>"
    224 .align	2
    225 ___
    226 
    227 $code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm;	# make it possible to compile with -march=armv4
    228 print $code;
    229 close STDOUT; # enforce flush
    230