Home | History | Annotate | Download | only in asm
      1 #!/usr/bin/env perl
      2 
      3 # ====================================================================
      4 # Written by Andy Polyakov <appro (at] openssl.org> 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 # September 2010.
     11 #
     12 # The module implements "4-bit" GCM GHASH function and underlying
     13 # single multiplication operation in GF(2^128). "4-bit" means that it
     14 # uses 256 bytes per-key table [+128 bytes shared table]. Performance
     15 # was measured to be ~18 cycles per processed byte on z10, which is
     16 # almost 40% better than gcc-generated code. It should be noted that
     17 # 18 cycles is worse result than expected: loop is scheduled for 12
     18 # and the result should be close to 12. In the lack of instruction-
     19 # level profiling data it's impossible to tell why...
     20 
     21 # November 2010.
     22 #
     23 # Adapt for -m31 build. If kernel supports what's called "highgprs"
     24 # feature on Linux [see /proc/cpuinfo], it's possible to use 64-bit
     25 # instructions and achieve "64-bit" performance even in 31-bit legacy
     26 # application context. The feature is not specific to any particular
     27 # processor, as long as it's "z-CPU". Latter implies that the code
     28 # remains z/Architecture specific. On z990 it was measured to perform
     29 # 2.8x better than 32-bit code generated by gcc 4.3.
     30 
     31 # March 2011.
     32 #
     33 # Support for hardware KIMD-GHASH is verified to produce correct
     34 # result and therefore is engaged. On z196 it was measured to process
     35 # 8KB buffer ~7 faster than software implementation. It's not as
     36 # impressive for smaller buffer sizes and for smallest 16-bytes buffer
     37 # it's actually almost 2 times slower. Which is the reason why
     38 # KIMD-GHASH is not used in gcm_gmult_4bit.
     39 
     40 $flavour = shift;
     41 
     42 if ($flavour =~ /3[12]/) {
     43 	$SIZE_T=4;
     44 	$g="";
     45 } else {
     46 	$SIZE_T=8;
     47 	$g="g";
     48 }
     49 
     50 while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
     51 open STDOUT,">$output";
     52 
     53 $softonly=0;
     54 
     55 $Zhi="%r0";
     56 $Zlo="%r1";
     57 
     58 $Xi="%r2";	# argument block
     59 $Htbl="%r3";
     60 $inp="%r4";
     61 $len="%r5";
     62 
     63 $rem0="%r6";	# variables
     64 $rem1="%r7";
     65 $nlo="%r8";
     66 $nhi="%r9";
     67 $xi="%r10";
     68 $cnt="%r11";
     69 $tmp="%r12";
     70 $x78="%r13";
     71 $rem_4bit="%r14";
     72 
     73 $sp="%r15";
     74 
     75 $code.=<<___;
     76 .text
     77 
     78 .globl	gcm_gmult_4bit
     79 .align	32
     80 gcm_gmult_4bit:
     81 ___
     82 $code.=<<___ if(!$softonly && 0);	# hardware is slow for single block...
     83 	larl	%r1,OPENSSL_s390xcap_P
     84 	lg	%r0,0(%r1)
     85 	tmhl	%r0,0x4000	# check for message-security-assist
     86 	jz	.Lsoft_gmult
     87 	lghi	%r0,0
     88 	la	%r1,16($sp)
     89 	.long	0xb93e0004	# kimd %r0,%r4
     90 	lg	%r1,24($sp)
     91 	tmhh	%r1,0x4000	# check for function 65
     92 	jz	.Lsoft_gmult
     93 	stg	%r0,16($sp)	# arrange 16 bytes of zero input
     94 	stg	%r0,24($sp)
     95 	lghi	%r0,65		# function 65
     96 	la	%r1,0($Xi)	# H lies right after Xi in gcm128_context
     97 	la	$inp,16($sp)
     98 	lghi	$len,16
     99 	.long	0xb93e0004	# kimd %r0,$inp
    100 	brc	1,.-4		# pay attention to "partial completion"
    101 	br	%r14
    102 .align	32
    103 .Lsoft_gmult:
    104 ___
    105 $code.=<<___;
    106 	stm${g}	%r6,%r14,6*$SIZE_T($sp)
    107 
    108 	aghi	$Xi,-1
    109 	lghi	$len,1
    110 	lghi	$x78,`0xf<<3`
    111 	larl	$rem_4bit,rem_4bit
    112 
    113 	lg	$Zlo,8+1($Xi)		# Xi
    114 	j	.Lgmult_shortcut
    115 .type	gcm_gmult_4bit,\@function
    116 .size	gcm_gmult_4bit,(.-gcm_gmult_4bit)
    117 
    118 .globl	gcm_ghash_4bit
    119 .align	32
    120 gcm_ghash_4bit:
    121 ___
    122 $code.=<<___ if(!$softonly);
    123 	larl	%r1,OPENSSL_s390xcap_P
    124 	lg	%r0,0(%r1)
    125 	tmhl	%r0,0x4000	# check for message-security-assist
    126 	jz	.Lsoft_ghash
    127 	lghi	%r0,0
    128 	la	%r1,16($sp)
    129 	.long	0xb93e0004	# kimd %r0,%r4
    130 	lg	%r1,24($sp)
    131 	tmhh	%r1,0x4000	# check for function 65
    132 	jz	.Lsoft_ghash
    133 	lghi	%r0,65		# function 65
    134 	la	%r1,0($Xi)	# H lies right after Xi in gcm128_context
    135 	.long	0xb93e0004	# kimd %r0,$inp
    136 	brc	1,.-4		# pay attention to "partial completion"
    137 	br	%r14
    138 .align	32
    139 .Lsoft_ghash:
    140 ___
    141 $code.=<<___ if ($flavour =~ /3[12]/);
    142 	llgfr	$len,$len
    143 ___
    144 $code.=<<___;
    145 	stm${g}	%r6,%r14,6*$SIZE_T($sp)
    146 
    147 	aghi	$Xi,-1
    148 	srlg	$len,$len,4
    149 	lghi	$x78,`0xf<<3`
    150 	larl	$rem_4bit,rem_4bit
    151 
    152 	lg	$Zlo,8+1($Xi)		# Xi
    153 	lg	$Zhi,0+1($Xi)
    154 	lghi	$tmp,0
    155 .Louter:
    156 	xg	$Zhi,0($inp)		# Xi ^= inp 
    157 	xg	$Zlo,8($inp)
    158 	xgr	$Zhi,$tmp
    159 	stg	$Zlo,8+1($Xi)
    160 	stg	$Zhi,0+1($Xi)
    161 
    162 .Lgmult_shortcut:
    163 	lghi	$tmp,0xf0
    164 	sllg	$nlo,$Zlo,4
    165 	srlg	$xi,$Zlo,8		# extract second byte
    166 	ngr	$nlo,$tmp
    167 	lgr	$nhi,$Zlo
    168 	lghi	$cnt,14
    169 	ngr	$nhi,$tmp
    170 
    171 	lg	$Zlo,8($nlo,$Htbl)
    172 	lg	$Zhi,0($nlo,$Htbl)
    173 
    174 	sllg	$nlo,$xi,4
    175 	sllg	$rem0,$Zlo,3
    176 	ngr	$nlo,$tmp
    177 	ngr	$rem0,$x78
    178 	ngr	$xi,$tmp
    179 
    180 	sllg	$tmp,$Zhi,60
    181 	srlg	$Zlo,$Zlo,4
    182 	srlg	$Zhi,$Zhi,4
    183 	xg	$Zlo,8($nhi,$Htbl)
    184 	xg	$Zhi,0($nhi,$Htbl)
    185 	lgr	$nhi,$xi
    186 	sllg	$rem1,$Zlo,3
    187 	xgr	$Zlo,$tmp
    188 	ngr	$rem1,$x78
    189 	j	.Lghash_inner
    190 .align	16
    191 .Lghash_inner:
    192 	srlg	$Zlo,$Zlo,4
    193 	sllg	$tmp,$Zhi,60
    194 	xg	$Zlo,8($nlo,$Htbl)
    195 	srlg	$Zhi,$Zhi,4
    196 	llgc	$xi,0($cnt,$Xi)
    197 	xg	$Zhi,0($nlo,$Htbl)
    198 	sllg	$nlo,$xi,4
    199 	xg	$Zhi,0($rem0,$rem_4bit)
    200 	nill	$nlo,0xf0
    201 	sllg	$rem0,$Zlo,3
    202 	xgr	$Zlo,$tmp
    203 	ngr	$rem0,$x78
    204 	nill	$xi,0xf0
    205 
    206 	sllg	$tmp,$Zhi,60
    207 	srlg	$Zlo,$Zlo,4
    208 	srlg	$Zhi,$Zhi,4
    209 	xg	$Zlo,8($nhi,$Htbl)
    210 	xg	$Zhi,0($nhi,$Htbl)
    211 	lgr	$nhi,$xi
    212 	xg	$Zhi,0($rem1,$rem_4bit)
    213 	sllg	$rem1,$Zlo,3
    214 	xgr	$Zlo,$tmp
    215 	ngr	$rem1,$x78
    216 	brct	$cnt,.Lghash_inner
    217 
    218 	sllg	$tmp,$Zhi,60
    219 	srlg	$Zlo,$Zlo,4
    220 	srlg	$Zhi,$Zhi,4
    221 	xg	$Zlo,8($nlo,$Htbl)
    222 	xg	$Zhi,0($nlo,$Htbl)
    223 	sllg	$xi,$Zlo,3
    224 	xg	$Zhi,0($rem0,$rem_4bit)
    225 	xgr	$Zlo,$tmp
    226 	ngr	$xi,$x78
    227 
    228 	sllg	$tmp,$Zhi,60
    229 	srlg	$Zlo,$Zlo,4
    230 	srlg	$Zhi,$Zhi,4
    231 	xg	$Zlo,8($nhi,$Htbl)
    232 	xg	$Zhi,0($nhi,$Htbl)
    233 	xgr	$Zlo,$tmp
    234 	xg	$Zhi,0($rem1,$rem_4bit)
    235 
    236 	lg	$tmp,0($xi,$rem_4bit)
    237 	la	$inp,16($inp)
    238 	sllg	$tmp,$tmp,4		# correct last rem_4bit[rem]
    239 	brctg	$len,.Louter
    240 
    241 	xgr	$Zhi,$tmp
    242 	stg	$Zlo,8+1($Xi)
    243 	stg	$Zhi,0+1($Xi)
    244 	lm${g}	%r6,%r14,6*$SIZE_T($sp)
    245 	br	%r14
    246 .type	gcm_ghash_4bit,\@function
    247 .size	gcm_ghash_4bit,(.-gcm_ghash_4bit)
    248 
    249 .align	64
    250 rem_4bit:
    251 	.long	`0x0000<<12`,0,`0x1C20<<12`,0,`0x3840<<12`,0,`0x2460<<12`,0
    252 	.long	`0x7080<<12`,0,`0x6CA0<<12`,0,`0x48C0<<12`,0,`0x54E0<<12`,0
    253 	.long	`0xE100<<12`,0,`0xFD20<<12`,0,`0xD940<<12`,0,`0xC560<<12`,0
    254 	.long	`0x9180<<12`,0,`0x8DA0<<12`,0,`0xA9C0<<12`,0,`0xB5E0<<12`,0
    255 .type	rem_4bit,\@object
    256 .size	rem_4bit,(.-rem_4bit)
    257 .string	"GHASH for s390x, CRYPTOGAMS by <appro\@openssl.org>"
    258 ___
    259 
    260 $code =~ s/\`([^\`]*)\`/eval $1/gem;
    261 print $code;
    262 close STDOUT;
    263