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 # Specific modes and adaptation for Linux kernel by Ard Biesheuvel
     10 # <ard.biesheuvel (at] linaro.org>. Permission to use under GPL terms is
     11 # granted.
     12 # ====================================================================
     13 
     14 # Bit-sliced AES for ARM NEON
     15 #
     16 # February 2012.
     17 #
     18 # This implementation is direct adaptation of bsaes-x86_64 module for
     19 # ARM NEON. Except that this module is endian-neutral [in sense that
     20 # it can be compiled for either endianness] by courtesy of vld1.8's
     21 # neutrality. Initial version doesn't implement interface to OpenSSL,
     22 # only low-level primitives and unsupported entry points, just enough
     23 # to collect performance results, which for Cortex-A8 core are:
     24 #
     25 # encrypt	19.5 cycles per byte processed with 128-bit key
     26 # decrypt	22.1 cycles per byte processed with 128-bit key
     27 # key conv.	440  cycles per 128-bit key/0.18 of 8x block
     28 #
     29 # Snapdragon S4 encrypts byte in 17.6 cycles and decrypts in 19.7,
     30 # which is [much] worse than anticipated (for further details see
     31 # http://www.openssl.org/~appro/Snapdragon-S4.html).
     32 #
     33 # Cortex-A15 manages in 14.2/16.1 cycles [when integer-only code
     34 # manages in 20.0 cycles].
     35 #
     36 # When comparing to x86_64 results keep in mind that NEON unit is
     37 # [mostly] single-issue and thus can't [fully] benefit from
     38 # instruction-level parallelism. And when comparing to aes-armv4
     39 # results keep in mind key schedule conversion overhead (see
     40 # bsaes-x86_64.pl for further details)...
     41 #
     42 #						<appro (at] openssl.org>
     43 
     44 # April-August 2013
     45 #
     46 # Add CBC, CTR and XTS subroutines, adapt for kernel use.
     47 #
     48 #					<ard.biesheuvel (at] linaro.org>
     49 
     50 $flavour = shift;
     51 if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
     52 else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
     53 
     54 if ($flavour && $flavour ne "void") {
     55     $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
     56     ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
     57     ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
     58     die "can't locate arm-xlate.pl";
     59 
     60     open STDOUT,"| \"$^X\" $xlate $flavour $output";
     61 } else {
     62     open STDOUT,">$output";
     63 }
     64 
     65 my ($inp,$out,$len,$key)=("r0","r1","r2","r3");
     66 my @XMM=map("q$_",(0..15));
     67 
     68 {
     69 my ($key,$rounds,$const)=("r4","r5","r6");
     70 
     71 sub Dlo()   { shift=~m|q([1]?[0-9])|?"d".($1*2):"";     }
     72 sub Dhi()   { shift=~m|q([1]?[0-9])|?"d".($1*2+1):"";   }
     73 
     74 sub Sbox {
     75 # input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
     76 # output in lsb > [b0, b1, b4, b6, b3, b7, b2, b5] < msb
     77 my @b=@_[0..7];
     78 my @t=@_[8..11];
     79 my @s=@_[12..15];
     80 	&InBasisChange	(@b);
     81 	&Inv_GF256	(@b[6,5,0,3,7,1,4,2],@t,@s);
     82 	&OutBasisChange	(@b[7,1,4,2,6,5,0,3]);
     83 }
     84 
     85 sub InBasisChange {
     86 # input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
     87 # output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb 
     88 my @b=@_[0..7];
     89 $code.=<<___;
     90 	veor	@b[2], @b[2], @b[1]
     91 	veor	@b[5], @b[5], @b[6]
     92 	veor	@b[3], @b[3], @b[0]
     93 	veor	@b[6], @b[6], @b[2]
     94 	veor	@b[5], @b[5], @b[0]
     95 
     96 	veor	@b[6], @b[6], @b[3]
     97 	veor	@b[3], @b[3], @b[7]
     98 	veor	@b[7], @b[7], @b[5]
     99 	veor	@b[3], @b[3], @b[4]
    100 	veor	@b[4], @b[4], @b[5]
    101 
    102 	veor	@b[2], @b[2], @b[7]
    103 	veor	@b[3], @b[3], @b[1]
    104 	veor	@b[1], @b[1], @b[5]
    105 ___
    106 }
    107 
    108 sub OutBasisChange {
    109 # input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
    110 # output in lsb > [b6, b1, b2, b4, b7, b0, b3, b5] < msb
    111 my @b=@_[0..7];
    112 $code.=<<___;
    113 	veor	@b[0], @b[0], @b[6]
    114 	veor	@b[1], @b[1], @b[4]
    115 	veor	@b[4], @b[4], @b[6]
    116 	veor	@b[2], @b[2], @b[0]
    117 	veor	@b[6], @b[6], @b[1]
    118 
    119 	veor	@b[1], @b[1], @b[5]
    120 	veor	@b[5], @b[5], @b[3]
    121 	veor	@b[3], @b[3], @b[7]
    122 	veor	@b[7], @b[7], @b[5]
    123 	veor	@b[2], @b[2], @b[5]
    124 
    125 	veor	@b[4], @b[4], @b[7]
    126 ___
    127 }
    128 
    129 sub InvSbox {
    130 # input in lsb 	> [b0, b1, b2, b3, b4, b5, b6, b7] < msb
    131 # output in lsb	> [b0, b1, b6, b4, b2, b7, b3, b5] < msb
    132 my @b=@_[0..7];
    133 my @t=@_[8..11];
    134 my @s=@_[12..15];
    135 	&InvInBasisChange	(@b);
    136 	&Inv_GF256		(@b[5,1,2,6,3,7,0,4],@t,@s);
    137 	&InvOutBasisChange	(@b[3,7,0,4,5,1,2,6]);
    138 }
    139 
    140 sub InvInBasisChange {		# OutBasisChange in reverse (with twist)
    141 my @b=@_[5,1,2,6,3,7,0,4];
    142 $code.=<<___
    143 	 veor	@b[1], @b[1], @b[7]
    144 	veor	@b[4], @b[4], @b[7]
    145 
    146 	veor	@b[7], @b[7], @b[5]
    147 	 veor	@b[1], @b[1], @b[3]
    148 	veor	@b[2], @b[2], @b[5]
    149 	veor	@b[3], @b[3], @b[7]
    150 
    151 	veor	@b[6], @b[6], @b[1]
    152 	veor	@b[2], @b[2], @b[0]
    153 	 veor	@b[5], @b[5], @b[3]
    154 	veor	@b[4], @b[4], @b[6]
    155 	veor	@b[0], @b[0], @b[6]
    156 	veor	@b[1], @b[1], @b[4]
    157 ___
    158 }
    159 
    160 sub InvOutBasisChange {		# InBasisChange in reverse
    161 my @b=@_[2,5,7,3,6,1,0,4];
    162 $code.=<<___;
    163 	veor	@b[1], @b[1], @b[5]
    164 	veor	@b[2], @b[2], @b[7]
    165 
    166 	veor	@b[3], @b[3], @b[1]
    167 	veor	@b[4], @b[4], @b[5]
    168 	veor	@b[7], @b[7], @b[5]
    169 	veor	@b[3], @b[3], @b[4]
    170 	 veor 	@b[5], @b[5], @b[0]
    171 	veor	@b[3], @b[3], @b[7]
    172 	 veor	@b[6], @b[6], @b[2]
    173 	 veor	@b[2], @b[2], @b[1]
    174 	veor	@b[6], @b[6], @b[3]
    175 
    176 	veor	@b[3], @b[3], @b[0]
    177 	veor	@b[5], @b[5], @b[6]
    178 ___
    179 }
    180 
    181 sub Mul_GF4 {
    182 #;*************************************************************
    183 #;* Mul_GF4: Input x0-x1,y0-y1 Output x0-x1 Temp t0 (8) *
    184 #;*************************************************************
    185 my ($x0,$x1,$y0,$y1,$t0,$t1)=@_;
    186 $code.=<<___;
    187 	veor 	$t0, $y0, $y1
    188 	vand	$t0, $t0, $x0
    189 	veor	$x0, $x0, $x1
    190 	vand	$t1, $x1, $y0
    191 	vand	$x0, $x0, $y1
    192 	veor	$x1, $t1, $t0
    193 	veor	$x0, $x0, $t1
    194 ___
    195 }
    196 
    197 sub Mul_GF4_N {				# not used, see next subroutine
    198 # multiply and scale by N
    199 my ($x0,$x1,$y0,$y1,$t0)=@_;
    200 $code.=<<___;
    201 	veor	$t0, $y0, $y1
    202 	vand	$t0, $t0, $x0
    203 	veor	$x0, $x0, $x1
    204 	vand	$x1, $x1, $y0
    205 	vand	$x0, $x0, $y1
    206 	veor	$x1, $x1, $x0
    207 	veor	$x0, $x0, $t0
    208 ___
    209 }
    210 
    211 sub Mul_GF4_N_GF4 {
    212 # interleaved Mul_GF4_N and Mul_GF4
    213 my ($x0,$x1,$y0,$y1,$t0,
    214     $x2,$x3,$y2,$y3,$t1)=@_;
    215 $code.=<<___;
    216 	veor	$t0, $y0, $y1
    217 	 veor 	$t1, $y2, $y3
    218 	vand	$t0, $t0, $x0
    219 	 vand	$t1, $t1, $x2
    220 	veor	$x0, $x0, $x1
    221 	 veor	$x2, $x2, $x3
    222 	vand	$x1, $x1, $y0
    223 	 vand	$x3, $x3, $y2
    224 	vand	$x0, $x0, $y1
    225 	 vand	$x2, $x2, $y3
    226 	veor	$x1, $x1, $x0
    227 	 veor	$x2, $x2, $x3
    228 	veor	$x0, $x0, $t0
    229 	 veor	$x3, $x3, $t1
    230 ___
    231 }
    232 sub Mul_GF16_2 {
    233 my @x=@_[0..7];
    234 my @y=@_[8..11];
    235 my @t=@_[12..15];
    236 $code.=<<___;
    237 	veor	@t[0], @x[0], @x[2]
    238 	veor	@t[1], @x[1], @x[3]
    239 ___
    240 	&Mul_GF4  	(@x[0], @x[1], @y[0], @y[1], @t[2..3]);
    241 $code.=<<___;
    242 	veor	@y[0], @y[0], @y[2]
    243 	veor	@y[1], @y[1], @y[3]
    244 ___
    245 	Mul_GF4_N_GF4	(@t[0], @t[1], @y[0], @y[1], @t[3],
    246 			 @x[2], @x[3], @y[2], @y[3], @t[2]);
    247 $code.=<<___;
    248 	veor	@x[0], @x[0], @t[0]
    249 	veor	@x[2], @x[2], @t[0]
    250 	veor	@x[1], @x[1], @t[1]
    251 	veor	@x[3], @x[3], @t[1]
    252 
    253 	veor	@t[0], @x[4], @x[6]
    254 	veor	@t[1], @x[5], @x[7]
    255 ___
    256 	&Mul_GF4_N_GF4	(@t[0], @t[1], @y[0], @y[1], @t[3],
    257 			 @x[6], @x[7], @y[2], @y[3], @t[2]);
    258 $code.=<<___;
    259 	veor	@y[0], @y[0], @y[2]
    260 	veor	@y[1], @y[1], @y[3]
    261 ___
    262 	&Mul_GF4  	(@x[4], @x[5], @y[0], @y[1], @t[2..3]);
    263 $code.=<<___;
    264 	veor	@x[4], @x[4], @t[0]
    265 	veor	@x[6], @x[6], @t[0]
    266 	veor	@x[5], @x[5], @t[1]
    267 	veor	@x[7], @x[7], @t[1]
    268 ___
    269 }
    270 sub Inv_GF256 {
    271 #;********************************************************************
    272 #;* Inv_GF256: Input x0-x7 Output x0-x7 Temp t0-t3,s0-s3 (144)       *
    273 #;********************************************************************
    274 my @x=@_[0..7];
    275 my @t=@_[8..11];
    276 my @s=@_[12..15];
    277 # direct optimizations from hardware
    278 $code.=<<___;
    279 	veor	@t[3], @x[4], @x[6]
    280 	veor	@t[2], @x[5], @x[7]
    281 	veor	@t[1], @x[1], @x[3]
    282 	veor	@s[1], @x[7], @x[6]
    283 	 vmov	@t[0], @t[2]
    284 	veor	@s[0], @x[0], @x[2]
    285 
    286 	vorr	@t[2], @t[2], @t[1]
    287 	veor	@s[3], @t[3], @t[0]
    288 	vand	@s[2], @t[3], @s[0]
    289 	vorr	@t[3], @t[3], @s[0]
    290 	veor	@s[0], @s[0], @t[1]
    291 	vand	@t[0], @t[0], @t[1]
    292 	veor	@t[1], @x[3], @x[2]
    293 	vand	@s[3], @s[3], @s[0]
    294 	vand	@s[1], @s[1], @t[1]
    295 	veor	@t[1], @x[4], @x[5]
    296 	veor	@s[0], @x[1], @x[0]
    297 	veor	@t[3], @t[3], @s[1]
    298 	veor	@t[2], @t[2], @s[1]
    299 	vand	@s[1], @t[1], @s[0]
    300 	vorr	@t[1], @t[1], @s[0]
    301 	veor	@t[3], @t[3], @s[3]
    302 	veor	@t[0], @t[0], @s[1]
    303 	veor	@t[2], @t[2], @s[2]
    304 	veor	@t[1], @t[1], @s[3]
    305 	veor	@t[0], @t[0], @s[2]
    306 	vand	@s[0], @x[7], @x[3]
    307 	veor	@t[1], @t[1], @s[2]
    308 	vand	@s[1], @x[6], @x[2]
    309 	vand	@s[2], @x[5], @x[1]
    310 	vorr	@s[3], @x[4], @x[0]
    311 	veor	@t[3], @t[3], @s[0]
    312 	veor	@t[1], @t[1], @s[2]
    313 	veor	@t[0], @t[0], @s[3]
    314 	veor	@t[2], @t[2], @s[1]
    315 
    316 	@ Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3
    317 
    318 	@ new smaller inversion
    319 
    320 	vand	@s[2], @t[3], @t[1]
    321 	vmov	@s[0], @t[0]
    322 
    323 	veor	@s[1], @t[2], @s[2]
    324 	veor	@s[3], @t[0], @s[2]
    325 	veor	@s[2], @t[0], @s[2]	@ @s[2]=@s[3]
    326 
    327 	vbsl	@s[1], @t[1], @t[0]
    328 	vbsl	@s[3], @t[3], @t[2]
    329 	veor	@t[3], @t[3], @t[2]
    330 
    331 	vbsl	@s[0], @s[1], @s[2]
    332 	vbsl	@t[0], @s[2], @s[1]
    333 
    334 	vand	@s[2], @s[0], @s[3]
    335 	veor	@t[1], @t[1], @t[0]
    336 
    337 	veor	@s[2], @s[2], @t[3]
    338 ___
    339 # output in s3, s2, s1, t1
    340 
    341 # Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \t2, \t3, \t0, \t1, \s0, \s1, \s2, \s3
    342 
    343 # Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \s3, \s2, \s1, \t1, \s0, \t0, \t2, \t3
    344 	&Mul_GF16_2(@x,@s[3,2,1],@t[1],@s[0],@t[0,2,3]);
    345 
    346 ### output msb > [x3,x2,x1,x0,x7,x6,x5,x4] < lsb
    347 }
    348 
    349 # AES linear components
    350 
    351 sub ShiftRows {
    352 my @x=@_[0..7];
    353 my @t=@_[8..11];
    354 my $mask=pop;
    355 $code.=<<___;
    356 	vldmia	$key!, {@t[0]-@t[3]}
    357 	veor	@t[0], @t[0], @x[0]
    358 	veor	@t[1], @t[1], @x[1]
    359 	vtbl.8	`&Dlo(@x[0])`, {@t[0]}, `&Dlo($mask)`
    360 	vtbl.8	`&Dhi(@x[0])`, {@t[0]}, `&Dhi($mask)`
    361 	vldmia	$key!, {@t[0]}
    362 	veor	@t[2], @t[2], @x[2]
    363 	vtbl.8	`&Dlo(@x[1])`, {@t[1]}, `&Dlo($mask)`
    364 	vtbl.8	`&Dhi(@x[1])`, {@t[1]}, `&Dhi($mask)`
    365 	vldmia	$key!, {@t[1]}
    366 	veor	@t[3], @t[3], @x[3]
    367 	vtbl.8	`&Dlo(@x[2])`, {@t[2]}, `&Dlo($mask)`
    368 	vtbl.8	`&Dhi(@x[2])`, {@t[2]}, `&Dhi($mask)`
    369 	vldmia	$key!, {@t[2]}
    370 	vtbl.8	`&Dlo(@x[3])`, {@t[3]}, `&Dlo($mask)`
    371 	vtbl.8	`&Dhi(@x[3])`, {@t[3]}, `&Dhi($mask)`
    372 	vldmia	$key!, {@t[3]}
    373 	veor	@t[0], @t[0], @x[4]
    374 	veor	@t[1], @t[1], @x[5]
    375 	vtbl.8	`&Dlo(@x[4])`, {@t[0]}, `&Dlo($mask)`
    376 	vtbl.8	`&Dhi(@x[4])`, {@t[0]}, `&Dhi($mask)`
    377 	veor	@t[2], @t[2], @x[6]
    378 	vtbl.8	`&Dlo(@x[5])`, {@t[1]}, `&Dlo($mask)`
    379 	vtbl.8	`&Dhi(@x[5])`, {@t[1]}, `&Dhi($mask)`
    380 	veor	@t[3], @t[3], @x[7]
    381 	vtbl.8	`&Dlo(@x[6])`, {@t[2]}, `&Dlo($mask)`
    382 	vtbl.8	`&Dhi(@x[6])`, {@t[2]}, `&Dhi($mask)`
    383 	vtbl.8	`&Dlo(@x[7])`, {@t[3]}, `&Dlo($mask)`
    384 	vtbl.8	`&Dhi(@x[7])`, {@t[3]}, `&Dhi($mask)`
    385 ___
    386 }
    387 
    388 sub MixColumns {
    389 # modified to emit output in order suitable for feeding back to aesenc[last]
    390 my @x=@_[0..7];
    391 my @t=@_[8..15];
    392 my $inv=@_[16];	# optional
    393 $code.=<<___;
    394 	vext.8	@t[0], @x[0], @x[0], #12	@ x0 <<< 32
    395 	vext.8	@t[1], @x[1], @x[1], #12
    396 	 veor	@x[0], @x[0], @t[0]		@ x0 ^ (x0 <<< 32)
    397 	vext.8	@t[2], @x[2], @x[2], #12
    398 	 veor	@x[1], @x[1], @t[1]
    399 	vext.8	@t[3], @x[3], @x[3], #12
    400 	 veor	@x[2], @x[2], @t[2]
    401 	vext.8	@t[4], @x[4], @x[4], #12
    402 	 veor	@x[3], @x[3], @t[3]
    403 	vext.8	@t[5], @x[5], @x[5], #12
    404 	 veor	@x[4], @x[4], @t[4]
    405 	vext.8	@t[6], @x[6], @x[6], #12
    406 	 veor	@x[5], @x[5], @t[5]
    407 	vext.8	@t[7], @x[7], @x[7], #12
    408 	 veor	@x[6], @x[6], @t[6]
    409 
    410 	veor	@t[1], @t[1], @x[0]
    411 	 veor	@x[7], @x[7], @t[7]
    412 	 vext.8	@x[0], @x[0], @x[0], #8		@ (x0 ^ (x0 <<< 32)) <<< 64)
    413 	veor	@t[2], @t[2], @x[1]
    414 	veor	@t[0], @t[0], @x[7]
    415 	veor	@t[1], @t[1], @x[7]
    416 	 vext.8	@x[1], @x[1], @x[1], #8
    417 	veor	@t[5], @t[5], @x[4]
    418 	 veor	@x[0], @x[0], @t[0]
    419 	veor	@t[6], @t[6], @x[5]
    420 	 veor	@x[1], @x[1], @t[1]
    421 	 vext.8	@t[0], @x[4], @x[4], #8
    422 	veor	@t[4], @t[4], @x[3]
    423 	 vext.8	@t[1], @x[5], @x[5], #8
    424 	veor	@t[7], @t[7], @x[6]
    425 	 vext.8	@x[4], @x[3], @x[3], #8
    426 	veor	@t[3], @t[3], @x[2]
    427 	 vext.8	@x[5], @x[7], @x[7], #8
    428 	veor	@t[4], @t[4], @x[7]
    429 	 vext.8	@x[3], @x[6], @x[6], #8
    430 	veor	@t[3], @t[3], @x[7]
    431 	 vext.8	@x[6], @x[2], @x[2], #8
    432 	veor	@x[7], @t[1], @t[5]
    433 ___
    434 $code.=<<___ if (!$inv);
    435 	veor	@x[2], @t[0], @t[4]
    436 	veor	@x[4], @x[4], @t[3]
    437 	veor	@x[5], @x[5], @t[7]
    438 	veor	@x[3], @x[3], @t[6]
    439 	 @ vmov	@x[2], @t[0]
    440 	veor	@x[6], @x[6], @t[2]
    441 	 @ vmov	@x[7], @t[1]
    442 ___
    443 $code.=<<___ if ($inv);
    444 	veor	@t[3], @t[3], @x[4]
    445 	veor	@x[5], @x[5], @t[7]
    446 	veor	@x[2], @x[3], @t[6]
    447 	veor	@x[3], @t[0], @t[4]
    448 	veor	@x[4], @x[6], @t[2]
    449 	vmov	@x[6], @t[3]
    450 	 @ vmov	@x[7], @t[1]
    451 ___
    452 }
    453 
    454 sub InvMixColumns_orig {
    455 my @x=@_[0..7];
    456 my @t=@_[8..15];
    457 
    458 $code.=<<___;
    459 	@ multiplication by 0x0e
    460 	vext.8	@t[7], @x[7], @x[7], #12
    461 	vmov	@t[2], @x[2]
    462 	veor	@x[2], @x[2], @x[5]		@ 2 5
    463 	veor	@x[7], @x[7], @x[5]		@ 7 5
    464 	vext.8	@t[0], @x[0], @x[0], #12
    465 	vmov	@t[5], @x[5]
    466 	veor	@x[5], @x[5], @x[0]		@ 5 0		[1]
    467 	veor	@x[0], @x[0], @x[1]		@ 0 1
    468 	vext.8	@t[1], @x[1], @x[1], #12
    469 	veor	@x[1], @x[1], @x[2]		@ 1 25
    470 	veor	@x[0], @x[0], @x[6]		@ 01 6		[2]
    471 	vext.8	@t[3], @x[3], @x[3], #12
    472 	veor	@x[1], @x[1], @x[3]		@ 125 3		[4]
    473 	veor	@x[2], @x[2], @x[0]		@ 25 016	[3]
    474 	veor	@x[3], @x[3], @x[7]		@ 3 75
    475 	veor	@x[7], @x[7], @x[6]		@ 75 6		[0]
    476 	vext.8	@t[6], @x[6], @x[6], #12
    477 	vmov	@t[4], @x[4]
    478 	veor	@x[6], @x[6], @x[4]		@ 6 4
    479 	veor	@x[4], @x[4], @x[3]		@ 4 375		[6]
    480 	veor	@x[3], @x[3], @x[7]		@ 375 756=36
    481 	veor	@x[6], @x[6], @t[5]		@ 64 5		[7]
    482 	veor	@x[3], @x[3], @t[2]		@ 36 2
    483 	vext.8	@t[5], @t[5], @t[5], #12
    484 	veor	@x[3], @x[3], @t[4]		@ 362 4		[5]
    485 ___
    486 					my @y = @x[7,5,0,2,1,3,4,6];
    487 $code.=<<___;
    488 	@ multiplication by 0x0b
    489 	veor	@y[1], @y[1], @y[0]
    490 	veor	@y[0], @y[0], @t[0]
    491 	vext.8	@t[2], @t[2], @t[2], #12
    492 	veor	@y[1], @y[1], @t[1]
    493 	veor	@y[0], @y[0], @t[5]
    494 	vext.8	@t[4], @t[4], @t[4], #12
    495 	veor	@y[1], @y[1], @t[6]
    496 	veor	@y[0], @y[0], @t[7]
    497 	veor	@t[7], @t[7], @t[6]		@ clobber t[7]
    498 
    499 	veor	@y[3], @y[3], @t[0]
    500 	 veor	@y[1], @y[1], @y[0]
    501 	vext.8	@t[0], @t[0], @t[0], #12
    502 	veor	@y[2], @y[2], @t[1]
    503 	veor	@y[4], @y[4], @t[1]
    504 	vext.8	@t[1], @t[1], @t[1], #12
    505 	veor	@y[2], @y[2], @t[2]
    506 	veor	@y[3], @y[3], @t[2]
    507 	veor	@y[5], @y[5], @t[2]
    508 	veor	@y[2], @y[2], @t[7]
    509 	vext.8	@t[2], @t[2], @t[2], #12
    510 	veor	@y[3], @y[3], @t[3]
    511 	veor	@y[6], @y[6], @t[3]
    512 	veor	@y[4], @y[4], @t[3]
    513 	veor	@y[7], @y[7], @t[4]
    514 	vext.8	@t[3], @t[3], @t[3], #12
    515 	veor	@y[5], @y[5], @t[4]
    516 	veor	@y[7], @y[7], @t[7]
    517 	veor	@t[7], @t[7], @t[5]		@ clobber t[7] even more
    518 	veor	@y[3], @y[3], @t[5]
    519 	veor	@y[4], @y[4], @t[4]
    520 
    521 	veor	@y[5], @y[5], @t[7]
    522 	vext.8	@t[4], @t[4], @t[4], #12
    523 	veor	@y[6], @y[6], @t[7]
    524 	veor	@y[4], @y[4], @t[7]
    525 
    526 	veor	@t[7], @t[7], @t[5]
    527 	vext.8	@t[5], @t[5], @t[5], #12
    528 
    529 	@ multiplication by 0x0d
    530 	veor	@y[4], @y[4], @y[7]
    531 	 veor	@t[7], @t[7], @t[6]		@ restore t[7]
    532 	veor	@y[7], @y[7], @t[4]
    533 	vext.8	@t[6], @t[6], @t[6], #12
    534 	veor	@y[2], @y[2], @t[0]
    535 	veor	@y[7], @y[7], @t[5]
    536 	vext.8	@t[7], @t[7], @t[7], #12
    537 	veor	@y[2], @y[2], @t[2]
    538 
    539 	veor	@y[3], @y[3], @y[1]
    540 	veor	@y[1], @y[1], @t[1]
    541 	veor	@y[0], @y[0], @t[0]
    542 	veor	@y[3], @y[3], @t[0]
    543 	veor	@y[1], @y[1], @t[5]
    544 	veor	@y[0], @y[0], @t[5]
    545 	vext.8	@t[0], @t[0], @t[0], #12
    546 	veor	@y[1], @y[1], @t[7]
    547 	veor	@y[0], @y[0], @t[6]
    548 	veor	@y[3], @y[3], @y[1]
    549 	veor	@y[4], @y[4], @t[1]
    550 	vext.8	@t[1], @t[1], @t[1], #12
    551 
    552 	veor	@y[7], @y[7], @t[7]
    553 	veor	@y[4], @y[4], @t[2]
    554 	veor	@y[5], @y[5], @t[2]
    555 	veor	@y[2], @y[2], @t[6]
    556 	veor	@t[6], @t[6], @t[3]		@ clobber t[6]
    557 	vext.8	@t[2], @t[2], @t[2], #12
    558 	veor	@y[4], @y[4], @y[7]
    559 	veor	@y[3], @y[3], @t[6]
    560 
    561 	veor	@y[6], @y[6], @t[6]
    562 	veor	@y[5], @y[5], @t[5]
    563 	vext.8	@t[5], @t[5], @t[5], #12
    564 	veor	@y[6], @y[6], @t[4]
    565 	vext.8	@t[4], @t[4], @t[4], #12
    566 	veor	@y[5], @y[5], @t[6]
    567 	veor	@y[6], @y[6], @t[7]
    568 	vext.8	@t[7], @t[7], @t[7], #12
    569 	veor	@t[6], @t[6], @t[3]		@ restore t[6]
    570 	vext.8	@t[3], @t[3], @t[3], #12
    571 
    572 	@ multiplication by 0x09
    573 	veor	@y[4], @y[4], @y[1]
    574 	veor	@t[1], @t[1], @y[1]		@ t[1]=y[1]
    575 	veor	@t[0], @t[0], @t[5]		@ clobber t[0]
    576 	vext.8	@t[6], @t[6], @t[6], #12
    577 	veor	@t[1], @t[1], @t[5]
    578 	veor	@y[3], @y[3], @t[0]
    579 	veor	@t[0], @t[0], @y[0]		@ t[0]=y[0]
    580 	veor	@t[1], @t[1], @t[6]
    581 	veor	@t[6], @t[6], @t[7]		@ clobber t[6]
    582 	veor	@y[4], @y[4], @t[1]
    583 	veor	@y[7], @y[7], @t[4]
    584 	veor	@y[6], @y[6], @t[3]
    585 	veor	@y[5], @y[5], @t[2]
    586 	veor	@t[4], @t[4], @y[4]		@ t[4]=y[4]
    587 	veor	@t[3], @t[3], @y[3]		@ t[3]=y[3]
    588 	veor	@t[5], @t[5], @y[5]		@ t[5]=y[5]
    589 	veor	@t[2], @t[2], @y[2]		@ t[2]=y[2]
    590 	veor	@t[3], @t[3], @t[7]
    591 	veor	@XMM[5], @t[5], @t[6]
    592 	veor	@XMM[6], @t[6], @y[6]		@ t[6]=y[6]
    593 	veor	@XMM[2], @t[2], @t[6]
    594 	veor	@XMM[7], @t[7], @y[7]		@ t[7]=y[7]
    595 
    596 	vmov	@XMM[0], @t[0]
    597 	vmov	@XMM[1], @t[1]
    598 	@ vmov	@XMM[2], @t[2]
    599 	vmov	@XMM[3], @t[3]
    600 	vmov	@XMM[4], @t[4]
    601 	@ vmov	@XMM[5], @t[5]
    602 	@ vmov	@XMM[6], @t[6]
    603 	@ vmov	@XMM[7], @t[7]
    604 ___
    605 }
    606 
    607 sub InvMixColumns {
    608 my @x=@_[0..7];
    609 my @t=@_[8..15];
    610 
    611 # Thanks to Jussi Kivilinna for providing pointer to
    612 #
    613 # | 0e 0b 0d 09 |   | 02 03 01 01 |   | 05 00 04 00 |
    614 # | 09 0e 0b 0d | = | 01 02 03 01 | x | 00 05 00 04 |
    615 # | 0d 09 0e 0b |   | 01 01 02 03 |   | 04 00 05 00 |
    616 # | 0b 0d 09 0e |   | 03 01 01 02 |   | 00 04 00 05 |
    617 
    618 $code.=<<___;
    619 	@ multiplication by 0x05-0x00-0x04-0x00
    620 	vext.8	@t[0], @x[0], @x[0], #8
    621 	vext.8	@t[6], @x[6], @x[6], #8
    622 	vext.8	@t[7], @x[7], @x[7], #8
    623 	veor	@t[0], @t[0], @x[0]
    624 	vext.8	@t[1], @x[1], @x[1], #8
    625 	veor	@t[6], @t[6], @x[6]
    626 	vext.8	@t[2], @x[2], @x[2], #8
    627 	veor	@t[7], @t[7], @x[7]
    628 	vext.8	@t[3], @x[3], @x[3], #8
    629 	veor	@t[1], @t[1], @x[1]
    630 	vext.8	@t[4], @x[4], @x[4], #8
    631 	veor	@t[2], @t[2], @x[2]
    632 	vext.8	@t[5], @x[5], @x[5], #8
    633 	veor	@t[3], @t[3], @x[3]
    634 	veor	@t[4], @t[4], @x[4]
    635 	veor	@t[5], @t[5], @x[5]
    636 
    637 	 veor	@x[0], @x[0], @t[6]
    638 	 veor	@x[1], @x[1], @t[6]
    639 	 veor	@x[2], @x[2], @t[0]
    640 	 veor	@x[4], @x[4], @t[2]
    641 	 veor	@x[3], @x[3], @t[1]
    642 	 veor	@x[1], @x[1], @t[7]
    643 	 veor	@x[2], @x[2], @t[7]
    644 	 veor	@x[4], @x[4], @t[6]
    645 	 veor	@x[5], @x[5], @t[3]
    646 	 veor	@x[3], @x[3], @t[6]
    647 	 veor	@x[6], @x[6], @t[4]
    648 	 veor	@x[4], @x[4], @t[7]
    649 	 veor	@x[5], @x[5], @t[7]
    650 	 veor	@x[7], @x[7], @t[5]
    651 ___
    652 	&MixColumns	(@x,@t,1);	# flipped 2<->3 and 4<->6
    653 }
    654 
    655 sub swapmove {
    656 my ($a,$b,$n,$mask,$t)=@_;
    657 $code.=<<___;
    658 	vshr.u64	$t, $b, #$n
    659 	veor		$t, $t, $a
    660 	vand		$t, $t, $mask
    661 	veor		$a, $a, $t
    662 	vshl.u64	$t, $t, #$n
    663 	veor		$b, $b, $t
    664 ___
    665 }
    666 sub swapmove2x {
    667 my ($a0,$b0,$a1,$b1,$n,$mask,$t0,$t1)=@_;
    668 $code.=<<___;
    669 	vshr.u64	$t0, $b0, #$n
    670 	 vshr.u64	$t1, $b1, #$n
    671 	veor		$t0, $t0, $a0
    672 	 veor		$t1, $t1, $a1
    673 	vand		$t0, $t0, $mask
    674 	 vand		$t1, $t1, $mask
    675 	veor		$a0, $a0, $t0
    676 	vshl.u64	$t0, $t0, #$n
    677 	 veor		$a1, $a1, $t1
    678 	 vshl.u64	$t1, $t1, #$n
    679 	veor		$b0, $b0, $t0
    680 	 veor		$b1, $b1, $t1
    681 ___
    682 }
    683 
    684 sub bitslice {
    685 my @x=reverse(@_[0..7]);
    686 my ($t0,$t1,$t2,$t3)=@_[8..11];
    687 $code.=<<___;
    688 	vmov.i8	$t0,#0x55			@ compose .LBS0
    689 	vmov.i8	$t1,#0x33			@ compose .LBS1
    690 ___
    691 	&swapmove2x(@x[0,1,2,3],1,$t0,$t2,$t3);
    692 	&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
    693 $code.=<<___;
    694 	vmov.i8	$t0,#0x0f			@ compose .LBS2
    695 ___
    696 	&swapmove2x(@x[0,2,1,3],2,$t1,$t2,$t3);
    697 	&swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
    698 
    699 	&swapmove2x(@x[0,4,1,5],4,$t0,$t2,$t3);
    700 	&swapmove2x(@x[2,6,3,7],4,$t0,$t2,$t3);
    701 }
    702 
    703 $code.=<<___;
    704 #ifndef __KERNEL__
    705 # include <openssl/arm_arch.h>
    706 
    707 # define VFP_ABI_PUSH	vstmdb	sp!,{d8-d15}
    708 # define VFP_ABI_POP	vldmia	sp!,{d8-d15}
    709 # define VFP_ABI_FRAME	0x40
    710 #else
    711 # define VFP_ABI_PUSH
    712 # define VFP_ABI_POP
    713 # define VFP_ABI_FRAME	0
    714 # define BSAES_ASM_EXTENDED_KEY
    715 # define XTS_CHAIN_TWEAK
    716 # define __ARM_ARCH__ __LINUX_ARM_ARCH__
    717 # define __ARM_MAX_ARCH__ 7
    718 #endif
    719 
    720 #ifdef __thumb__
    721 # define adrl adr
    722 #endif
    723 
    724 #if __ARM_MAX_ARCH__>=7
    725 .arch	armv7-a
    726 .fpu	neon
    727 
    728 .text
    729 .syntax	unified 	@ ARMv7-capable assembler is expected to handle this
    730 #if defined(__thumb2__) && !defined(__APPLE__)
    731 .thumb
    732 #else
    733 .code   32
    734 #endif
    735 
    736 .type	_bsaes_decrypt8,%function
    737 .align	4
    738 _bsaes_decrypt8:
    739 	adr	$const,_bsaes_decrypt8
    740 	vldmia	$key!, {@XMM[9]}		@ round 0 key
    741 #ifdef	__APPLE__
    742 	adr	$const,.LM0ISR
    743 #else
    744 	add	$const,$const,#.LM0ISR-_bsaes_decrypt8
    745 #endif
    746 
    747 	vldmia	$const!, {@XMM[8]}		@ .LM0ISR
    748 	veor	@XMM[10], @XMM[0], @XMM[9]	@ xor with round0 key
    749 	veor	@XMM[11], @XMM[1], @XMM[9]
    750 	 vtbl.8	`&Dlo(@XMM[0])`, {@XMM[10]}, `&Dlo(@XMM[8])`
    751 	 vtbl.8	`&Dhi(@XMM[0])`, {@XMM[10]}, `&Dhi(@XMM[8])`
    752 	veor	@XMM[12], @XMM[2], @XMM[9]
    753 	 vtbl.8	`&Dlo(@XMM[1])`, {@XMM[11]}, `&Dlo(@XMM[8])`
    754 	 vtbl.8	`&Dhi(@XMM[1])`, {@XMM[11]}, `&Dhi(@XMM[8])`
    755 	veor	@XMM[13], @XMM[3], @XMM[9]
    756 	 vtbl.8	`&Dlo(@XMM[2])`, {@XMM[12]}, `&Dlo(@XMM[8])`
    757 	 vtbl.8	`&Dhi(@XMM[2])`, {@XMM[12]}, `&Dhi(@XMM[8])`
    758 	veor	@XMM[14], @XMM[4], @XMM[9]
    759 	 vtbl.8	`&Dlo(@XMM[3])`, {@XMM[13]}, `&Dlo(@XMM[8])`
    760 	 vtbl.8	`&Dhi(@XMM[3])`, {@XMM[13]}, `&Dhi(@XMM[8])`
    761 	veor	@XMM[15], @XMM[5], @XMM[9]
    762 	 vtbl.8	`&Dlo(@XMM[4])`, {@XMM[14]}, `&Dlo(@XMM[8])`
    763 	 vtbl.8	`&Dhi(@XMM[4])`, {@XMM[14]}, `&Dhi(@XMM[8])`
    764 	veor	@XMM[10], @XMM[6], @XMM[9]
    765 	 vtbl.8	`&Dlo(@XMM[5])`, {@XMM[15]}, `&Dlo(@XMM[8])`
    766 	 vtbl.8	`&Dhi(@XMM[5])`, {@XMM[15]}, `&Dhi(@XMM[8])`
    767 	veor	@XMM[11], @XMM[7], @XMM[9]
    768 	 vtbl.8	`&Dlo(@XMM[6])`, {@XMM[10]}, `&Dlo(@XMM[8])`
    769 	 vtbl.8	`&Dhi(@XMM[6])`, {@XMM[10]}, `&Dhi(@XMM[8])`
    770 	 vtbl.8	`&Dlo(@XMM[7])`, {@XMM[11]}, `&Dlo(@XMM[8])`
    771 	 vtbl.8	`&Dhi(@XMM[7])`, {@XMM[11]}, `&Dhi(@XMM[8])`
    772 ___
    773 	&bitslice	(@XMM[0..7, 8..11]);
    774 $code.=<<___;
    775 	sub	$rounds,$rounds,#1
    776 	b	.Ldec_sbox
    777 .align	4
    778 .Ldec_loop:
    779 ___
    780 	&ShiftRows	(@XMM[0..7, 8..12]);
    781 $code.=".Ldec_sbox:\n";
    782 	&InvSbox	(@XMM[0..7, 8..15]);
    783 $code.=<<___;
    784 	subs	$rounds,$rounds,#1
    785 	bcc	.Ldec_done
    786 ___
    787 	&InvMixColumns	(@XMM[0,1,6,4,2,7,3,5, 8..15]);
    788 $code.=<<___;
    789 	vldmia	$const, {@XMM[12]}		@ .LISR
    790 	ite	eq				@ Thumb2 thing, sanity check in ARM
    791 	addeq	$const,$const,#0x10
    792 	bne	.Ldec_loop
    793 	vldmia	$const, {@XMM[12]}		@ .LISRM0
    794 	b	.Ldec_loop
    795 .align	4
    796 .Ldec_done:
    797 ___
    798 	&bitslice	(@XMM[0,1,6,4,2,7,3,5, 8..11]);
    799 $code.=<<___;
    800 	vldmia	$key, {@XMM[8]}			@ last round key
    801 	veor	@XMM[6], @XMM[6], @XMM[8]
    802 	veor	@XMM[4], @XMM[4], @XMM[8]
    803 	veor	@XMM[2], @XMM[2], @XMM[8]
    804 	veor	@XMM[7], @XMM[7], @XMM[8]
    805 	veor	@XMM[3], @XMM[3], @XMM[8]
    806 	veor	@XMM[5], @XMM[5], @XMM[8]
    807 	veor	@XMM[0], @XMM[0], @XMM[8]
    808 	veor	@XMM[1], @XMM[1], @XMM[8]
    809 	bx	lr
    810 .size	_bsaes_decrypt8,.-_bsaes_decrypt8
    811 
    812 .type	_bsaes_const,%object
    813 .align	6
    814 _bsaes_const:
    815 .LM0ISR:	@ InvShiftRows constants
    816 	.quad	0x0a0e0206070b0f03, 0x0004080c0d010509
    817 .LISR:
    818 	.quad	0x0504070602010003, 0x0f0e0d0c080b0a09
    819 .LISRM0:
    820 	.quad	0x01040b0e0205080f, 0x0306090c00070a0d
    821 .LM0SR:		@ ShiftRows constants
    822 	.quad	0x0a0e02060f03070b, 0x0004080c05090d01
    823 .LSR:
    824 	.quad	0x0504070600030201, 0x0f0e0d0c0a09080b
    825 .LSRM0:
    826 	.quad	0x0304090e00050a0f, 0x01060b0c0207080d
    827 .LM0:
    828 	.quad	0x02060a0e03070b0f, 0x0004080c0105090d
    829 .LREVM0SR:
    830 	.quad	0x090d01050c000408, 0x03070b0f060a0e02
    831 .asciz	"Bit-sliced AES for NEON, CRYPTOGAMS by <appro\@openssl.org>"
    832 .align	6
    833 .size	_bsaes_const,.-_bsaes_const
    834 
    835 .type	_bsaes_encrypt8,%function
    836 .align	4
    837 _bsaes_encrypt8:
    838 	adr	$const,_bsaes_encrypt8
    839 	vldmia	$key!, {@XMM[9]}		@ round 0 key
    840 #ifdef	__APPLE__
    841 	adr	$const,.LM0SR
    842 #else
    843 	sub	$const,$const,#_bsaes_encrypt8-.LM0SR
    844 #endif
    845 
    846 	vldmia	$const!, {@XMM[8]}		@ .LM0SR
    847 _bsaes_encrypt8_alt:
    848 	veor	@XMM[10], @XMM[0], @XMM[9]	@ xor with round0 key
    849 	veor	@XMM[11], @XMM[1], @XMM[9]
    850 	 vtbl.8	`&Dlo(@XMM[0])`, {@XMM[10]}, `&Dlo(@XMM[8])`
    851 	 vtbl.8	`&Dhi(@XMM[0])`, {@XMM[10]}, `&Dhi(@XMM[8])`
    852 	veor	@XMM[12], @XMM[2], @XMM[9]
    853 	 vtbl.8	`&Dlo(@XMM[1])`, {@XMM[11]}, `&Dlo(@XMM[8])`
    854 	 vtbl.8	`&Dhi(@XMM[1])`, {@XMM[11]}, `&Dhi(@XMM[8])`
    855 	veor	@XMM[13], @XMM[3], @XMM[9]
    856 	 vtbl.8	`&Dlo(@XMM[2])`, {@XMM[12]}, `&Dlo(@XMM[8])`
    857 	 vtbl.8	`&Dhi(@XMM[2])`, {@XMM[12]}, `&Dhi(@XMM[8])`
    858 	veor	@XMM[14], @XMM[4], @XMM[9]
    859 	 vtbl.8	`&Dlo(@XMM[3])`, {@XMM[13]}, `&Dlo(@XMM[8])`
    860 	 vtbl.8	`&Dhi(@XMM[3])`, {@XMM[13]}, `&Dhi(@XMM[8])`
    861 	veor	@XMM[15], @XMM[5], @XMM[9]
    862 	 vtbl.8	`&Dlo(@XMM[4])`, {@XMM[14]}, `&Dlo(@XMM[8])`
    863 	 vtbl.8	`&Dhi(@XMM[4])`, {@XMM[14]}, `&Dhi(@XMM[8])`
    864 	veor	@XMM[10], @XMM[6], @XMM[9]
    865 	 vtbl.8	`&Dlo(@XMM[5])`, {@XMM[15]}, `&Dlo(@XMM[8])`
    866 	 vtbl.8	`&Dhi(@XMM[5])`, {@XMM[15]}, `&Dhi(@XMM[8])`
    867 	veor	@XMM[11], @XMM[7], @XMM[9]
    868 	 vtbl.8	`&Dlo(@XMM[6])`, {@XMM[10]}, `&Dlo(@XMM[8])`
    869 	 vtbl.8	`&Dhi(@XMM[6])`, {@XMM[10]}, `&Dhi(@XMM[8])`
    870 	 vtbl.8	`&Dlo(@XMM[7])`, {@XMM[11]}, `&Dlo(@XMM[8])`
    871 	 vtbl.8	`&Dhi(@XMM[7])`, {@XMM[11]}, `&Dhi(@XMM[8])`
    872 _bsaes_encrypt8_bitslice:
    873 ___
    874 	&bitslice	(@XMM[0..7, 8..11]);
    875 $code.=<<___;
    876 	sub	$rounds,$rounds,#1
    877 	b	.Lenc_sbox
    878 .align	4
    879 .Lenc_loop:
    880 ___
    881 	&ShiftRows	(@XMM[0..7, 8..12]);
    882 $code.=".Lenc_sbox:\n";
    883 	&Sbox		(@XMM[0..7, 8..15]);
    884 $code.=<<___;
    885 	subs	$rounds,$rounds,#1
    886 	bcc	.Lenc_done
    887 ___
    888 	&MixColumns	(@XMM[0,1,4,6,3,7,2,5, 8..15]);
    889 $code.=<<___;
    890 	vldmia	$const, {@XMM[12]}		@ .LSR
    891 	ite	eq				@ Thumb2 thing, samity check in ARM
    892 	addeq	$const,$const,#0x10
    893 	bne	.Lenc_loop
    894 	vldmia	$const, {@XMM[12]}		@ .LSRM0
    895 	b	.Lenc_loop
    896 .align	4
    897 .Lenc_done:
    898 ___
    899 	# output in lsb > [t0, t1, t4, t6, t3, t7, t2, t5] < msb
    900 	&bitslice	(@XMM[0,1,4,6,3,7,2,5, 8..11]);
    901 $code.=<<___;
    902 	vldmia	$key, {@XMM[8]}			@ last round key
    903 	veor	@XMM[4], @XMM[4], @XMM[8]
    904 	veor	@XMM[6], @XMM[6], @XMM[8]
    905 	veor	@XMM[3], @XMM[3], @XMM[8]
    906 	veor	@XMM[7], @XMM[7], @XMM[8]
    907 	veor	@XMM[2], @XMM[2], @XMM[8]
    908 	veor	@XMM[5], @XMM[5], @XMM[8]
    909 	veor	@XMM[0], @XMM[0], @XMM[8]
    910 	veor	@XMM[1], @XMM[1], @XMM[8]
    911 	bx	lr
    912 .size	_bsaes_encrypt8,.-_bsaes_encrypt8
    913 ___
    914 }
    915 {
    916 my ($out,$inp,$rounds,$const)=("r12","r4","r5","r6");
    917 
    918 sub bitslice_key {
    919 my @x=reverse(@_[0..7]);
    920 my ($bs0,$bs1,$bs2,$t2,$t3)=@_[8..12];
    921 
    922 	&swapmove	(@x[0,1],1,$bs0,$t2,$t3);
    923 $code.=<<___;
    924 	@ &swapmove(@x[2,3],1,$t0,$t2,$t3);
    925 	vmov	@x[2], @x[0]
    926 	vmov	@x[3], @x[1]
    927 ___
    928 	#&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
    929 
    930 	&swapmove2x	(@x[0,2,1,3],2,$bs1,$t2,$t3);
    931 $code.=<<___;
    932 	@ &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
    933 	vmov	@x[4], @x[0]
    934 	vmov	@x[6], @x[2]
    935 	vmov	@x[5], @x[1]
    936 	vmov	@x[7], @x[3]
    937 ___
    938 	&swapmove2x	(@x[0,4,1,5],4,$bs2,$t2,$t3);
    939 	&swapmove2x	(@x[2,6,3,7],4,$bs2,$t2,$t3);
    940 }
    941 
    942 $code.=<<___;
    943 .type	_bsaes_key_convert,%function
    944 .align	4
    945 _bsaes_key_convert:
    946 	adr	$const,_bsaes_key_convert
    947 	vld1.8	{@XMM[7]},  [$inp]!		@ load round 0 key
    948 #ifdef	__APPLE__
    949 	adr	$const,.LM0
    950 #else
    951 	sub	$const,$const,#_bsaes_key_convert-.LM0
    952 #endif
    953 	vld1.8	{@XMM[15]}, [$inp]!		@ load round 1 key
    954 
    955 	vmov.i8	@XMM[8],  #0x01			@ bit masks
    956 	vmov.i8	@XMM[9],  #0x02
    957 	vmov.i8	@XMM[10], #0x04
    958 	vmov.i8	@XMM[11], #0x08
    959 	vmov.i8	@XMM[12], #0x10
    960 	vmov.i8	@XMM[13], #0x20
    961 	vldmia	$const, {@XMM[14]}		@ .LM0
    962 
    963 #ifdef __ARMEL__
    964 	vrev32.8	@XMM[7],  @XMM[7]
    965 	vrev32.8	@XMM[15], @XMM[15]
    966 #endif
    967 	sub	$rounds,$rounds,#1
    968 	vstmia	$out!, {@XMM[7]}		@ save round 0 key
    969 	b	.Lkey_loop
    970 
    971 .align	4
    972 .Lkey_loop:
    973 	vtbl.8	`&Dlo(@XMM[7])`,{@XMM[15]},`&Dlo(@XMM[14])`
    974 	vtbl.8	`&Dhi(@XMM[7])`,{@XMM[15]},`&Dhi(@XMM[14])`
    975 	vmov.i8	@XMM[6],  #0x40
    976 	vmov.i8	@XMM[15], #0x80
    977 
    978 	vtst.8	@XMM[0], @XMM[7], @XMM[8]
    979 	vtst.8	@XMM[1], @XMM[7], @XMM[9]
    980 	vtst.8	@XMM[2], @XMM[7], @XMM[10]
    981 	vtst.8	@XMM[3], @XMM[7], @XMM[11]
    982 	vtst.8	@XMM[4], @XMM[7], @XMM[12]
    983 	vtst.8	@XMM[5], @XMM[7], @XMM[13]
    984 	vtst.8	@XMM[6], @XMM[7], @XMM[6]
    985 	vtst.8	@XMM[7], @XMM[7], @XMM[15]
    986 	vld1.8	{@XMM[15]}, [$inp]!		@ load next round key
    987 	vmvn	@XMM[0], @XMM[0]		@ "pnot"
    988 	vmvn	@XMM[1], @XMM[1]
    989 	vmvn	@XMM[5], @XMM[5]
    990 	vmvn	@XMM[6], @XMM[6]
    991 #ifdef __ARMEL__
    992 	vrev32.8	@XMM[15], @XMM[15]
    993 #endif
    994 	subs	$rounds,$rounds,#1
    995 	vstmia	$out!,{@XMM[0]-@XMM[7]}		@ write bit-sliced round key
    996 	bne	.Lkey_loop
    997 
    998 	vmov.i8	@XMM[7],#0x63			@ compose .L63
    999 	@ don't save last round key
   1000 	bx	lr
   1001 .size	_bsaes_key_convert,.-_bsaes_key_convert
   1002 ___
   1003 }
   1004 
   1005 if (0) {		# following four functions are unsupported interface
   1006 			# used for benchmarking...
   1007 $code.=<<___;
   1008 .globl	bsaes_enc_key_convert
   1009 .hidden	bsaes_enc_key_convert
   1010 .type	bsaes_enc_key_convert,%function
   1011 .align	4
   1012 bsaes_enc_key_convert:
   1013 	stmdb	sp!,{r4-r6,lr}
   1014 	vstmdb	sp!,{d8-d15}		@ ABI specification says so
   1015 
   1016 	ldr	r5,[$inp,#240]			@ pass rounds
   1017 	mov	r4,$inp				@ pass key
   1018 	mov	r12,$out			@ pass key schedule
   1019 	bl	_bsaes_key_convert
   1020 	veor	@XMM[7],@XMM[7],@XMM[15]	@ fix up last round key
   1021 	vstmia	r12, {@XMM[7]}			@ save last round key
   1022 
   1023 	vldmia	sp!,{d8-d15}
   1024 	ldmia	sp!,{r4-r6,pc}
   1025 .size	bsaes_enc_key_convert,.-bsaes_enc_key_convert
   1026 
   1027 .globl	bsaes_encrypt_128
   1028 .hidden	bsaes_encrypt_128
   1029 .type	bsaes_encrypt_128,%function
   1030 .align	4
   1031 bsaes_encrypt_128:
   1032 	stmdb	sp!,{r4-r6,lr}
   1033 	vstmdb	sp!,{d8-d15}		@ ABI specification says so
   1034 .Lenc128_loop:
   1035 	vld1.8	{@XMM[0]-@XMM[1]}, [$inp]!	@ load input
   1036 	vld1.8	{@XMM[2]-@XMM[3]}, [$inp]!
   1037 	mov	r4,$key				@ pass the key
   1038 	vld1.8	{@XMM[4]-@XMM[5]}, [$inp]!
   1039 	mov	r5,#10				@ pass rounds
   1040 	vld1.8	{@XMM[6]-@XMM[7]}, [$inp]!
   1041 
   1042 	bl	_bsaes_encrypt8
   1043 
   1044 	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
   1045 	vst1.8	{@XMM[4]}, [$out]!
   1046 	vst1.8	{@XMM[6]}, [$out]!
   1047 	vst1.8	{@XMM[3]}, [$out]!
   1048 	vst1.8	{@XMM[7]}, [$out]!
   1049 	vst1.8	{@XMM[2]}, [$out]!
   1050 	subs	$len,$len,#0x80
   1051 	vst1.8	{@XMM[5]}, [$out]!
   1052 	bhi	.Lenc128_loop
   1053 
   1054 	vldmia	sp!,{d8-d15}
   1055 	ldmia	sp!,{r4-r6,pc}
   1056 .size	bsaes_encrypt_128,.-bsaes_encrypt_128
   1057 
   1058 .globl	bsaes_dec_key_convert
   1059 .hidden	bsaes_dec_key_convert
   1060 .type	bsaes_dec_key_convert,%function
   1061 .align	4
   1062 bsaes_dec_key_convert:
   1063 	stmdb	sp!,{r4-r6,lr}
   1064 	vstmdb	sp!,{d8-d15}		@ ABI specification says so
   1065 
   1066 	ldr	r5,[$inp,#240]			@ pass rounds
   1067 	mov	r4,$inp				@ pass key
   1068 	mov	r12,$out			@ pass key schedule
   1069 	bl	_bsaes_key_convert
   1070 	vldmia	$out, {@XMM[6]}
   1071 	vstmia	r12,  {@XMM[15]}		@ save last round key
   1072 	veor	@XMM[7], @XMM[7], @XMM[6]	@ fix up round 0 key
   1073 	vstmia	$out, {@XMM[7]}
   1074 
   1075 	vldmia	sp!,{d8-d15}
   1076 	ldmia	sp!,{r4-r6,pc}
   1077 .size	bsaes_dec_key_convert,.-bsaes_dec_key_convert
   1078 
   1079 .globl	bsaes_decrypt_128
   1080 .hidden	bsaes_decrypt_128
   1081 .type	bsaes_decrypt_128,%function
   1082 .align	4
   1083 bsaes_decrypt_128:
   1084 	stmdb	sp!,{r4-r6,lr}
   1085 	vstmdb	sp!,{d8-d15}		@ ABI specification says so
   1086 .Ldec128_loop:
   1087 	vld1.8	{@XMM[0]-@XMM[1]}, [$inp]!	@ load input
   1088 	vld1.8	{@XMM[2]-@XMM[3]}, [$inp]!
   1089 	mov	r4,$key				@ pass the key
   1090 	vld1.8	{@XMM[4]-@XMM[5]}, [$inp]!
   1091 	mov	r5,#10				@ pass rounds
   1092 	vld1.8	{@XMM[6]-@XMM[7]}, [$inp]!
   1093 
   1094 	bl	_bsaes_decrypt8
   1095 
   1096 	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
   1097 	vst1.8	{@XMM[6]}, [$out]!
   1098 	vst1.8	{@XMM[4]}, [$out]!
   1099 	vst1.8	{@XMM[2]}, [$out]!
   1100 	vst1.8	{@XMM[7]}, [$out]!
   1101 	vst1.8	{@XMM[3]}, [$out]!
   1102 	subs	$len,$len,#0x80
   1103 	vst1.8	{@XMM[5]}, [$out]!
   1104 	bhi	.Ldec128_loop
   1105 
   1106 	vldmia	sp!,{d8-d15}
   1107 	ldmia	sp!,{r4-r6,pc}
   1108 .size	bsaes_decrypt_128,.-bsaes_decrypt_128
   1109 ___
   1110 }
   1111 {
   1112 my ($inp,$out,$len,$key, $ivp,$fp,$rounds)=map("r$_",(0..3,8..10));
   1113 my ($keysched)=("sp");
   1114 
   1115 $code.=<<___;
   1116 .extern AES_cbc_encrypt
   1117 .extern AES_decrypt
   1118 
   1119 .global	bsaes_cbc_encrypt
   1120 .hidden	bsaes_cbc_encrypt
   1121 .type	bsaes_cbc_encrypt,%function
   1122 .align	5
   1123 bsaes_cbc_encrypt:
   1124 #ifndef	__KERNEL__
   1125 	cmp	$len, #128
   1126 #ifndef	__thumb__
   1127 	blo	AES_cbc_encrypt
   1128 #else
   1129 	bhs	1f
   1130 	b	AES_cbc_encrypt
   1131 1:
   1132 #endif
   1133 #endif
   1134 
   1135 	@ it is up to the caller to make sure we are called with enc == 0
   1136 
   1137 	mov	ip, sp
   1138 	stmdb	sp!, {r4-r10, lr}
   1139 	VFP_ABI_PUSH
   1140 	ldr	$ivp, [ip]			@ IV is 1st arg on the stack
   1141 	mov	$len, $len, lsr#4		@ len in 16 byte blocks
   1142 	sub	sp, #0x10			@ scratch space to carry over the IV
   1143 	mov	$fp, sp				@ save sp
   1144 
   1145 	ldr	$rounds, [$key, #240]		@ get # of rounds
   1146 #ifndef	BSAES_ASM_EXTENDED_KEY
   1147 	@ allocate the key schedule on the stack
   1148 	sub	r12, sp, $rounds, lsl#7		@ 128 bytes per inner round key
   1149 	add	r12, #`128-32`			@ sifze of bit-slices key schedule
   1150 
   1151 	@ populate the key schedule
   1152 	mov	r4, $key			@ pass key
   1153 	mov	r5, $rounds			@ pass # of rounds
   1154 	mov	sp, r12				@ sp is $keysched
   1155 	bl	_bsaes_key_convert
   1156 	vldmia	$keysched, {@XMM[6]}
   1157 	vstmia	r12,  {@XMM[15]}		@ save last round key
   1158 	veor	@XMM[7], @XMM[7], @XMM[6]	@ fix up round 0 key
   1159 	vstmia	$keysched, {@XMM[7]}
   1160 #else
   1161 	ldr	r12, [$key, #244]
   1162 	eors	r12, #1
   1163 	beq	0f
   1164 
   1165 	@ populate the key schedule
   1166 	str	r12, [$key, #244]
   1167 	mov	r4, $key			@ pass key
   1168 	mov	r5, $rounds			@ pass # of rounds
   1169 	add	r12, $key, #248			@ pass key schedule
   1170 	bl	_bsaes_key_convert
   1171 	add	r4, $key, #248
   1172 	vldmia	r4, {@XMM[6]}
   1173 	vstmia	r12, {@XMM[15]}			@ save last round key
   1174 	veor	@XMM[7], @XMM[7], @XMM[6]	@ fix up round 0 key
   1175 	vstmia	r4, {@XMM[7]}
   1176 
   1177 .align	2
   1178 0:
   1179 #endif
   1180 
   1181 	vld1.8	{@XMM[15]}, [$ivp]		@ load IV
   1182 	b	.Lcbc_dec_loop
   1183 
   1184 .align	4
   1185 .Lcbc_dec_loop:
   1186 	subs	$len, $len, #0x8
   1187 	bmi	.Lcbc_dec_loop_finish
   1188 
   1189 	vld1.8	{@XMM[0]-@XMM[1]}, [$inp]!	@ load input
   1190 	vld1.8	{@XMM[2]-@XMM[3]}, [$inp]!
   1191 #ifndef	BSAES_ASM_EXTENDED_KEY
   1192 	mov	r4, $keysched			@ pass the key
   1193 #else
   1194 	add	r4, $key, #248
   1195 #endif
   1196 	vld1.8	{@XMM[4]-@XMM[5]}, [$inp]!
   1197 	mov	r5, $rounds
   1198 	vld1.8	{@XMM[6]-@XMM[7]}, [$inp]
   1199 	sub	$inp, $inp, #0x60
   1200 	vstmia	$fp, {@XMM[15]}			@ put aside IV
   1201 
   1202 	bl	_bsaes_decrypt8
   1203 
   1204 	vldmia	$fp, {@XMM[14]}			@ reload IV
   1205 	vld1.8	{@XMM[8]-@XMM[9]}, [$inp]!	@ reload input
   1206 	veor	@XMM[0], @XMM[0], @XMM[14]	@ ^= IV
   1207 	vld1.8	{@XMM[10]-@XMM[11]}, [$inp]!
   1208 	veor	@XMM[1], @XMM[1], @XMM[8]
   1209 	veor	@XMM[6], @XMM[6], @XMM[9]
   1210 	vld1.8	{@XMM[12]-@XMM[13]}, [$inp]!
   1211 	veor	@XMM[4], @XMM[4], @XMM[10]
   1212 	veor	@XMM[2], @XMM[2], @XMM[11]
   1213 	vld1.8	{@XMM[14]-@XMM[15]}, [$inp]!
   1214 	veor	@XMM[7], @XMM[7], @XMM[12]
   1215 	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
   1216 	veor	@XMM[3], @XMM[3], @XMM[13]
   1217 	vst1.8	{@XMM[6]}, [$out]!
   1218 	veor	@XMM[5], @XMM[5], @XMM[14]
   1219 	vst1.8	{@XMM[4]}, [$out]!
   1220 	vst1.8	{@XMM[2]}, [$out]!
   1221 	vst1.8	{@XMM[7]}, [$out]!
   1222 	vst1.8	{@XMM[3]}, [$out]!
   1223 	vst1.8	{@XMM[5]}, [$out]!
   1224 
   1225 	b	.Lcbc_dec_loop
   1226 
   1227 .Lcbc_dec_loop_finish:
   1228 	adds	$len, $len, #8
   1229 	beq	.Lcbc_dec_done
   1230 
   1231 	vld1.8	{@XMM[0]}, [$inp]!		@ load input
   1232 	cmp	$len, #2
   1233 	blo	.Lcbc_dec_one
   1234 	vld1.8	{@XMM[1]}, [$inp]!
   1235 #ifndef	BSAES_ASM_EXTENDED_KEY
   1236 	mov	r4, $keysched			@ pass the key
   1237 #else
   1238 	add	r4, $key, #248
   1239 #endif
   1240 	mov	r5, $rounds
   1241 	vstmia	$fp, {@XMM[15]}			@ put aside IV
   1242 	beq	.Lcbc_dec_two
   1243 	vld1.8	{@XMM[2]}, [$inp]!
   1244 	cmp	$len, #4
   1245 	blo	.Lcbc_dec_three
   1246 	vld1.8	{@XMM[3]}, [$inp]!
   1247 	beq	.Lcbc_dec_four
   1248 	vld1.8	{@XMM[4]}, [$inp]!
   1249 	cmp	$len, #6
   1250 	blo	.Lcbc_dec_five
   1251 	vld1.8	{@XMM[5]}, [$inp]!
   1252 	beq	.Lcbc_dec_six
   1253 	vld1.8	{@XMM[6]}, [$inp]!
   1254 	sub	$inp, $inp, #0x70
   1255 
   1256 	bl	_bsaes_decrypt8
   1257 
   1258 	vldmia	$fp, {@XMM[14]}			@ reload IV
   1259 	vld1.8	{@XMM[8]-@XMM[9]}, [$inp]!	@ reload input
   1260 	veor	@XMM[0], @XMM[0], @XMM[14]	@ ^= IV
   1261 	vld1.8	{@XMM[10]-@XMM[11]}, [$inp]!
   1262 	veor	@XMM[1], @XMM[1], @XMM[8]
   1263 	veor	@XMM[6], @XMM[6], @XMM[9]
   1264 	vld1.8	{@XMM[12]-@XMM[13]}, [$inp]!
   1265 	veor	@XMM[4], @XMM[4], @XMM[10]
   1266 	veor	@XMM[2], @XMM[2], @XMM[11]
   1267 	vld1.8	{@XMM[15]}, [$inp]!
   1268 	veor	@XMM[7], @XMM[7], @XMM[12]
   1269 	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
   1270 	veor	@XMM[3], @XMM[3], @XMM[13]
   1271 	vst1.8	{@XMM[6]}, [$out]!
   1272 	vst1.8	{@XMM[4]}, [$out]!
   1273 	vst1.8	{@XMM[2]}, [$out]!
   1274 	vst1.8	{@XMM[7]}, [$out]!
   1275 	vst1.8	{@XMM[3]}, [$out]!
   1276 	b	.Lcbc_dec_done
   1277 .align	4
   1278 .Lcbc_dec_six:
   1279 	sub	$inp, $inp, #0x60
   1280 	bl	_bsaes_decrypt8
   1281 	vldmia	$fp,{@XMM[14]}			@ reload IV
   1282 	vld1.8	{@XMM[8]-@XMM[9]}, [$inp]!	@ reload input
   1283 	veor	@XMM[0], @XMM[0], @XMM[14]	@ ^= IV
   1284 	vld1.8	{@XMM[10]-@XMM[11]}, [$inp]!
   1285 	veor	@XMM[1], @XMM[1], @XMM[8]
   1286 	veor	@XMM[6], @XMM[6], @XMM[9]
   1287 	vld1.8	{@XMM[12]}, [$inp]!
   1288 	veor	@XMM[4], @XMM[4], @XMM[10]
   1289 	veor	@XMM[2], @XMM[2], @XMM[11]
   1290 	vld1.8	{@XMM[15]}, [$inp]!
   1291 	veor	@XMM[7], @XMM[7], @XMM[12]
   1292 	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
   1293 	vst1.8	{@XMM[6]}, [$out]!
   1294 	vst1.8	{@XMM[4]}, [$out]!
   1295 	vst1.8	{@XMM[2]}, [$out]!
   1296 	vst1.8	{@XMM[7]}, [$out]!
   1297 	b	.Lcbc_dec_done
   1298 .align	4
   1299 .Lcbc_dec_five:
   1300 	sub	$inp, $inp, #0x50
   1301 	bl	_bsaes_decrypt8
   1302 	vldmia	$fp, {@XMM[14]}			@ reload IV
   1303 	vld1.8	{@XMM[8]-@XMM[9]}, [$inp]!	@ reload input
   1304 	veor	@XMM[0], @XMM[0], @XMM[14]	@ ^= IV
   1305 	vld1.8	{@XMM[10]-@XMM[11]}, [$inp]!
   1306 	veor	@XMM[1], @XMM[1], @XMM[8]
   1307 	veor	@XMM[6], @XMM[6], @XMM[9]
   1308 	vld1.8	{@XMM[15]}, [$inp]!
   1309 	veor	@XMM[4], @XMM[4], @XMM[10]
   1310 	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
   1311 	veor	@XMM[2], @XMM[2], @XMM[11]
   1312 	vst1.8	{@XMM[6]}, [$out]!
   1313 	vst1.8	{@XMM[4]}, [$out]!
   1314 	vst1.8	{@XMM[2]}, [$out]!
   1315 	b	.Lcbc_dec_done
   1316 .align	4
   1317 .Lcbc_dec_four:
   1318 	sub	$inp, $inp, #0x40
   1319 	bl	_bsaes_decrypt8
   1320 	vldmia	$fp, {@XMM[14]}			@ reload IV
   1321 	vld1.8	{@XMM[8]-@XMM[9]}, [$inp]!	@ reload input
   1322 	veor	@XMM[0], @XMM[0], @XMM[14]	@ ^= IV
   1323 	vld1.8	{@XMM[10]}, [$inp]!
   1324 	veor	@XMM[1], @XMM[1], @XMM[8]
   1325 	veor	@XMM[6], @XMM[6], @XMM[9]
   1326 	vld1.8	{@XMM[15]}, [$inp]!
   1327 	veor	@XMM[4], @XMM[4], @XMM[10]
   1328 	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
   1329 	vst1.8	{@XMM[6]}, [$out]!
   1330 	vst1.8	{@XMM[4]}, [$out]!
   1331 	b	.Lcbc_dec_done
   1332 .align	4
   1333 .Lcbc_dec_three:
   1334 	sub	$inp, $inp, #0x30
   1335 	bl	_bsaes_decrypt8
   1336 	vldmia	$fp, {@XMM[14]}			@ reload IV
   1337 	vld1.8	{@XMM[8]-@XMM[9]}, [$inp]!	@ reload input
   1338 	veor	@XMM[0], @XMM[0], @XMM[14]	@ ^= IV
   1339 	vld1.8	{@XMM[15]}, [$inp]!
   1340 	veor	@XMM[1], @XMM[1], @XMM[8]
   1341 	veor	@XMM[6], @XMM[6], @XMM[9]
   1342 	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
   1343 	vst1.8	{@XMM[6]}, [$out]!
   1344 	b	.Lcbc_dec_done
   1345 .align	4
   1346 .Lcbc_dec_two:
   1347 	sub	$inp, $inp, #0x20
   1348 	bl	_bsaes_decrypt8
   1349 	vldmia	$fp, {@XMM[14]}			@ reload IV
   1350 	vld1.8	{@XMM[8]}, [$inp]!		@ reload input
   1351 	veor	@XMM[0], @XMM[0], @XMM[14]	@ ^= IV
   1352 	vld1.8	{@XMM[15]}, [$inp]!		@ reload input
   1353 	veor	@XMM[1], @XMM[1], @XMM[8]
   1354 	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
   1355 	b	.Lcbc_dec_done
   1356 .align	4
   1357 .Lcbc_dec_one:
   1358 	sub	$inp, $inp, #0x10
   1359 	mov	$rounds, $out			@ save original out pointer
   1360 	mov	$out, $fp			@ use the iv scratch space as out buffer
   1361 	mov	r2, $key
   1362 	vmov	@XMM[4],@XMM[15]		@ just in case ensure that IV
   1363 	vmov	@XMM[5],@XMM[0]			@ and input are preserved
   1364 	bl	AES_decrypt
   1365 	vld1.8	{@XMM[0]}, [$fp,:64]		@ load result
   1366 	veor	@XMM[0], @XMM[0], @XMM[4]	@ ^= IV
   1367 	vmov	@XMM[15], @XMM[5]		@ @XMM[5] holds input
   1368 	vst1.8	{@XMM[0]}, [$rounds]		@ write output
   1369 
   1370 .Lcbc_dec_done:
   1371 #ifndef	BSAES_ASM_EXTENDED_KEY
   1372 	vmov.i32	q0, #0
   1373 	vmov.i32	q1, #0
   1374 .Lcbc_dec_bzero:				@ wipe key schedule [if any]
   1375 	vstmia		$keysched!, {q0-q1}
   1376 	cmp		$keysched, $fp
   1377 	bne		.Lcbc_dec_bzero
   1378 #endif
   1379 
   1380 	mov	sp, $fp
   1381 	add	sp, #0x10			@ add sp,$fp,#0x10 is no good for thumb
   1382 	vst1.8	{@XMM[15]}, [$ivp]		@ return IV
   1383 	VFP_ABI_POP
   1384 	ldmia	sp!, {r4-r10, pc}
   1385 .size	bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
   1386 ___
   1387 }
   1388 {
   1389 my ($inp,$out,$len,$key, $ctr,$fp,$rounds)=(map("r$_",(0..3,8..10)));
   1390 my $const = "r6";	# shared with _bsaes_encrypt8_alt
   1391 my $keysched = "sp";
   1392 
   1393 $code.=<<___;
   1394 .extern	AES_encrypt
   1395 .global	bsaes_ctr32_encrypt_blocks
   1396 .hidden	bsaes_ctr32_encrypt_blocks
   1397 .type	bsaes_ctr32_encrypt_blocks,%function
   1398 .align	5
   1399 bsaes_ctr32_encrypt_blocks:
   1400 	cmp	$len, #8			@ use plain AES for
   1401 	blo	.Lctr_enc_short			@ small sizes
   1402 
   1403 	mov	ip, sp
   1404 	stmdb	sp!, {r4-r10, lr}
   1405 	VFP_ABI_PUSH
   1406 	ldr	$ctr, [ip]			@ ctr is 1st arg on the stack
   1407 	sub	sp, sp, #0x10			@ scratch space to carry over the ctr
   1408 	mov	$fp, sp				@ save sp
   1409 
   1410 	ldr	$rounds, [$key, #240]		@ get # of rounds
   1411 #ifndef	BSAES_ASM_EXTENDED_KEY
   1412 	@ allocate the key schedule on the stack
   1413 	sub	r12, sp, $rounds, lsl#7		@ 128 bytes per inner round key
   1414 	add	r12, #`128-32`			@ size of bit-sliced key schedule
   1415 
   1416 	@ populate the key schedule
   1417 	mov	r4, $key			@ pass key
   1418 	mov	r5, $rounds			@ pass # of rounds
   1419 	mov	sp, r12				@ sp is $keysched
   1420 	bl	_bsaes_key_convert
   1421 	veor	@XMM[7],@XMM[7],@XMM[15]	@ fix up last round key
   1422 	vstmia	r12, {@XMM[7]}			@ save last round key
   1423 
   1424 	vld1.8	{@XMM[0]}, [$ctr]		@ load counter
   1425 #ifdef	__APPLE__
   1426 	mov	$ctr, #:lower16:(.LREVM0SR-.LM0)
   1427 	add	$ctr, $const, $ctr
   1428 #else
   1429 	add	$ctr, $const, #.LREVM0SR-.LM0	@ borrow $ctr
   1430 #endif
   1431 	vldmia	$keysched, {@XMM[4]}		@ load round0 key
   1432 #else
   1433 	ldr	r12, [$key, #244]
   1434 	eors	r12, #1
   1435 	beq	0f
   1436 
   1437 	@ populate the key schedule
   1438 	str	r12, [$key, #244]
   1439 	mov	r4, $key			@ pass key
   1440 	mov	r5, $rounds			@ pass # of rounds
   1441 	add	r12, $key, #248			@ pass key schedule
   1442 	bl	_bsaes_key_convert
   1443 	veor	@XMM[7],@XMM[7],@XMM[15]	@ fix up last round key
   1444 	vstmia	r12, {@XMM[7]}			@ save last round key
   1445 
   1446 .align	2
   1447 0:	add	r12, $key, #248
   1448 	vld1.8	{@XMM[0]}, [$ctr]		@ load counter
   1449 	adrl	$ctr, .LREVM0SR			@ borrow $ctr
   1450 	vldmia	r12, {@XMM[4]}			@ load round0 key
   1451 	sub	sp, #0x10			@ place for adjusted round0 key
   1452 #endif
   1453 
   1454 	vmov.i32	@XMM[8],#1		@ compose 1<<96
   1455 	veor		@XMM[9],@XMM[9],@XMM[9]
   1456 	vrev32.8	@XMM[0],@XMM[0]
   1457 	vext.8		@XMM[8],@XMM[9],@XMM[8],#4
   1458 	vrev32.8	@XMM[4],@XMM[4]
   1459 	vadd.u32	@XMM[9],@XMM[8],@XMM[8]	@ compose 2<<96
   1460 	vstmia	$keysched, {@XMM[4]}		@ save adjusted round0 key
   1461 	b	.Lctr_enc_loop
   1462 
   1463 .align	4
   1464 .Lctr_enc_loop:
   1465 	vadd.u32	@XMM[10], @XMM[8], @XMM[9]	@ compose 3<<96
   1466 	vadd.u32	@XMM[1], @XMM[0], @XMM[8]	@ +1
   1467 	vadd.u32	@XMM[2], @XMM[0], @XMM[9]	@ +2
   1468 	vadd.u32	@XMM[3], @XMM[0], @XMM[10]	@ +3
   1469 	vadd.u32	@XMM[4], @XMM[1], @XMM[10]
   1470 	vadd.u32	@XMM[5], @XMM[2], @XMM[10]
   1471 	vadd.u32	@XMM[6], @XMM[3], @XMM[10]
   1472 	vadd.u32	@XMM[7], @XMM[4], @XMM[10]
   1473 	vadd.u32	@XMM[10], @XMM[5], @XMM[10]	@ next counter
   1474 
   1475 	@ Borrow prologue from _bsaes_encrypt8 to use the opportunity
   1476 	@ to flip byte order in 32-bit counter
   1477 
   1478 	vldmia		$keysched, {@XMM[9]}		@ load round0 key
   1479 #ifndef	BSAES_ASM_EXTENDED_KEY
   1480 	add		r4, $keysched, #0x10		@ pass next round key
   1481 #else
   1482 	add		r4, $key, #`248+16`
   1483 #endif
   1484 	vldmia		$ctr, {@XMM[8]}			@ .LREVM0SR
   1485 	mov		r5, $rounds			@ pass rounds
   1486 	vstmia		$fp, {@XMM[10]}			@ save next counter
   1487 #ifdef	__APPLE__
   1488 	mov		$const, #:lower16:(.LREVM0SR-.LSR)
   1489 	sub		$const, $ctr, $const
   1490 #else
   1491 	sub		$const, $ctr, #.LREVM0SR-.LSR	@ pass constants
   1492 #endif
   1493 
   1494 	bl		_bsaes_encrypt8_alt
   1495 
   1496 	subs		$len, $len, #8
   1497 	blo		.Lctr_enc_loop_done
   1498 
   1499 	vld1.8		{@XMM[8]-@XMM[9]}, [$inp]!	@ load input
   1500 	vld1.8		{@XMM[10]-@XMM[11]}, [$inp]!
   1501 	veor		@XMM[0], @XMM[8]
   1502 	veor		@XMM[1], @XMM[9]
   1503 	vld1.8		{@XMM[12]-@XMM[13]}, [$inp]!
   1504 	veor		@XMM[4], @XMM[10]
   1505 	veor		@XMM[6], @XMM[11]
   1506 	vld1.8		{@XMM[14]-@XMM[15]}, [$inp]!
   1507 	veor		@XMM[3], @XMM[12]
   1508 	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!	@ write output
   1509 	veor		@XMM[7], @XMM[13]
   1510 	veor		@XMM[2], @XMM[14]
   1511 	vst1.8		{@XMM[4]}, [$out]!
   1512 	veor		@XMM[5], @XMM[15]
   1513 	vst1.8		{@XMM[6]}, [$out]!
   1514 	vmov.i32	@XMM[8], #1			@ compose 1<<96
   1515 	vst1.8		{@XMM[3]}, [$out]!
   1516 	veor		@XMM[9], @XMM[9], @XMM[9]
   1517 	vst1.8		{@XMM[7]}, [$out]!
   1518 	vext.8		@XMM[8], @XMM[9], @XMM[8], #4
   1519 	vst1.8		{@XMM[2]}, [$out]!
   1520 	vadd.u32	@XMM[9],@XMM[8],@XMM[8]		@ compose 2<<96
   1521 	vst1.8		{@XMM[5]}, [$out]!
   1522 	vldmia		$fp, {@XMM[0]}			@ load counter
   1523 
   1524 	bne		.Lctr_enc_loop
   1525 	b		.Lctr_enc_done
   1526 
   1527 .align	4
   1528 .Lctr_enc_loop_done:
   1529 	add		$len, $len, #8
   1530 	vld1.8		{@XMM[8]}, [$inp]!	@ load input
   1531 	veor		@XMM[0], @XMM[8]
   1532 	vst1.8		{@XMM[0]}, [$out]!	@ write output
   1533 	cmp		$len, #2
   1534 	blo		.Lctr_enc_done
   1535 	vld1.8		{@XMM[9]}, [$inp]!
   1536 	veor		@XMM[1], @XMM[9]
   1537 	vst1.8		{@XMM[1]}, [$out]!
   1538 	beq		.Lctr_enc_done
   1539 	vld1.8		{@XMM[10]}, [$inp]!
   1540 	veor		@XMM[4], @XMM[10]
   1541 	vst1.8		{@XMM[4]}, [$out]!
   1542 	cmp		$len, #4
   1543 	blo		.Lctr_enc_done
   1544 	vld1.8		{@XMM[11]}, [$inp]!
   1545 	veor		@XMM[6], @XMM[11]
   1546 	vst1.8		{@XMM[6]}, [$out]!
   1547 	beq		.Lctr_enc_done
   1548 	vld1.8		{@XMM[12]}, [$inp]!
   1549 	veor		@XMM[3], @XMM[12]
   1550 	vst1.8		{@XMM[3]}, [$out]!
   1551 	cmp		$len, #6
   1552 	blo		.Lctr_enc_done
   1553 	vld1.8		{@XMM[13]}, [$inp]!
   1554 	veor		@XMM[7], @XMM[13]
   1555 	vst1.8		{@XMM[7]}, [$out]!
   1556 	beq		.Lctr_enc_done
   1557 	vld1.8		{@XMM[14]}, [$inp]
   1558 	veor		@XMM[2], @XMM[14]
   1559 	vst1.8		{@XMM[2]}, [$out]!
   1560 
   1561 .Lctr_enc_done:
   1562 	vmov.i32	q0, #0
   1563 	vmov.i32	q1, #0
   1564 #ifndef	BSAES_ASM_EXTENDED_KEY
   1565 .Lctr_enc_bzero:			@ wipe key schedule [if any]
   1566 	vstmia		$keysched!, {q0-q1}
   1567 	cmp		$keysched, $fp
   1568 	bne		.Lctr_enc_bzero
   1569 #else
   1570 	vstmia		$keysched, {q0-q1}
   1571 #endif
   1572 
   1573 	mov	sp, $fp
   1574 	add	sp, #0x10		@ add sp,$fp,#0x10 is no good for thumb
   1575 	VFP_ABI_POP
   1576 	ldmia	sp!, {r4-r10, pc}	@ return
   1577 
   1578 .align	4
   1579 .Lctr_enc_short:
   1580 	ldr	ip, [sp]		@ ctr pointer is passed on stack
   1581 	stmdb	sp!, {r4-r8, lr}
   1582 
   1583 	mov	r4, $inp		@ copy arguments
   1584 	mov	r5, $out
   1585 	mov	r6, $len
   1586 	mov	r7, $key
   1587 	ldr	r8, [ip, #12]		@ load counter LSW
   1588 	vld1.8	{@XMM[1]}, [ip]		@ load whole counter value
   1589 #ifdef __ARMEL__
   1590 	rev	r8, r8
   1591 #endif
   1592 	sub	sp, sp, #0x10
   1593 	vst1.8	{@XMM[1]}, [sp]		@ copy counter value
   1594 	sub	sp, sp, #0x10
   1595 
   1596 .Lctr_enc_short_loop:
   1597 	add	r0, sp, #0x10		@ input counter value
   1598 	mov	r1, sp			@ output on the stack
   1599 	mov	r2, r7			@ key
   1600 
   1601 	bl	AES_encrypt
   1602 
   1603 	vld1.8	{@XMM[0]}, [r4]!	@ load input
   1604 	vld1.8	{@XMM[1]}, [sp]		@ load encrypted counter
   1605 	add	r8, r8, #1
   1606 #ifdef __ARMEL__
   1607 	rev	r0, r8
   1608 	str	r0, [sp, #0x1c]		@ next counter value
   1609 #else
   1610 	str	r8, [sp, #0x1c]		@ next counter value
   1611 #endif
   1612 	veor	@XMM[0],@XMM[0],@XMM[1]
   1613 	vst1.8	{@XMM[0]}, [r5]!	@ store output
   1614 	subs	r6, r6, #1
   1615 	bne	.Lctr_enc_short_loop
   1616 
   1617 	vmov.i32	q0, #0
   1618 	vmov.i32	q1, #0
   1619 	vstmia		sp!, {q0-q1}
   1620 
   1621 	ldmia	sp!, {r4-r8, pc}
   1622 .size	bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
   1623 ___
   1624 }
   1625 {
   1626 ######################################################################
   1627 # void bsaes_xts_[en|de]crypt(const char *inp,char *out,size_t len,
   1628 #	const AES_KEY *key1, const AES_KEY *key2,
   1629 #	const unsigned char iv[16]);
   1630 #
   1631 my ($inp,$out,$len,$key,$rounds,$magic,$fp)=(map("r$_",(7..10,1..3)));
   1632 my $const="r6";		# returned by _bsaes_key_convert
   1633 my $twmask=@XMM[5];
   1634 my @T=@XMM[6..7];
   1635 
   1636 $code.=<<___;
   1637 .globl	bsaes_xts_encrypt
   1638 .hidden	bsaes_xts_encrypt
   1639 .type	bsaes_xts_encrypt,%function
   1640 .align	4
   1641 bsaes_xts_encrypt:
   1642 	mov	ip, sp
   1643 	stmdb	sp!, {r4-r10, lr}		@ 0x20
   1644 	VFP_ABI_PUSH
   1645 	mov	r6, sp				@ future $fp
   1646 
   1647 	mov	$inp, r0
   1648 	mov	$out, r1
   1649 	mov	$len, r2
   1650 	mov	$key, r3
   1651 
   1652 	sub	r0, sp, #0x10			@ 0x10
   1653 	bic	r0, #0xf			@ align at 16 bytes
   1654 	mov	sp, r0
   1655 
   1656 #ifdef	XTS_CHAIN_TWEAK
   1657 	ldr	r0, [ip]			@ pointer to input tweak
   1658 #else
   1659 	@ generate initial tweak
   1660 	ldr	r0, [ip, #4]			@ iv[]
   1661 	mov	r1, sp
   1662 	ldr	r2, [ip, #0]			@ key2
   1663 	bl	AES_encrypt
   1664 	mov	r0,sp				@ pointer to initial tweak
   1665 #endif
   1666 
   1667 	ldr	$rounds, [$key, #240]		@ get # of rounds
   1668 	mov	$fp, r6
   1669 #ifndef	BSAES_ASM_EXTENDED_KEY
   1670 	@ allocate the key schedule on the stack
   1671 	sub	r12, sp, $rounds, lsl#7		@ 128 bytes per inner round key
   1672 	@ add	r12, #`128-32`			@ size of bit-sliced key schedule
   1673 	sub	r12, #`32+16`			@ place for tweak[9]
   1674 
   1675 	@ populate the key schedule
   1676 	mov	r4, $key			@ pass key
   1677 	mov	r5, $rounds			@ pass # of rounds
   1678 	mov	sp, r12
   1679 	add	r12, #0x90			@ pass key schedule
   1680 	bl	_bsaes_key_convert
   1681 	veor	@XMM[7], @XMM[7], @XMM[15]	@ fix up last round key
   1682 	vstmia	r12, {@XMM[7]}			@ save last round key
   1683 #else
   1684 	ldr	r12, [$key, #244]
   1685 	eors	r12, #1
   1686 	beq	0f
   1687 
   1688 	str	r12, [$key, #244]
   1689 	mov	r4, $key			@ pass key
   1690 	mov	r5, $rounds			@ pass # of rounds
   1691 	add	r12, $key, #248			@ pass key schedule
   1692 	bl	_bsaes_key_convert
   1693 	veor	@XMM[7], @XMM[7], @XMM[15]	@ fix up last round key
   1694 	vstmia	r12, {@XMM[7]}
   1695 
   1696 .align	2
   1697 0:	sub	sp, #0x90			@ place for tweak[9]
   1698 #endif
   1699 
   1700 	vld1.8	{@XMM[8]}, [r0]			@ initial tweak
   1701 	adr	$magic, .Lxts_magic
   1702 
   1703 	subs	$len, #0x80
   1704 	blo	.Lxts_enc_short
   1705 	b	.Lxts_enc_loop
   1706 
   1707 .align	4
   1708 .Lxts_enc_loop:
   1709 	vldmia		$magic, {$twmask}	@ load XTS magic
   1710 	vshr.s64	@T[0], @XMM[8], #63
   1711 	mov		r0, sp
   1712 	vand		@T[0], @T[0], $twmask
   1713 ___
   1714 for($i=9;$i<16;$i++) {
   1715 $code.=<<___;
   1716 	vadd.u64	@XMM[$i], @XMM[$i-1], @XMM[$i-1]
   1717 	vst1.64		{@XMM[$i-1]}, [r0,:128]!
   1718 	vswp		`&Dhi("@T[0]")`,`&Dlo("@T[0]")`
   1719 	vshr.s64	@T[1], @XMM[$i], #63
   1720 	veor		@XMM[$i], @XMM[$i], @T[0]
   1721 	vand		@T[1], @T[1], $twmask
   1722 ___
   1723 	@T=reverse(@T);
   1724 
   1725 $code.=<<___ if ($i>=10);
   1726 	vld1.8		{@XMM[$i-10]}, [$inp]!
   1727 ___
   1728 $code.=<<___ if ($i>=11);
   1729 	veor		@XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
   1730 ___
   1731 }
   1732 $code.=<<___;
   1733 	vadd.u64	@XMM[8], @XMM[15], @XMM[15]
   1734 	vst1.64		{@XMM[15]}, [r0,:128]!
   1735 	vswp		`&Dhi("@T[0]")`,`&Dlo("@T[0]")`
   1736 	veor		@XMM[8], @XMM[8], @T[0]
   1737 	vst1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
   1738 
   1739 	vld1.8		{@XMM[6]-@XMM[7]}, [$inp]!
   1740 	veor		@XMM[5], @XMM[5], @XMM[13]
   1741 #ifndef	BSAES_ASM_EXTENDED_KEY
   1742 	add		r4, sp, #0x90			@ pass key schedule
   1743 #else
   1744 	add		r4, $key, #248			@ pass key schedule
   1745 #endif
   1746 	veor		@XMM[6], @XMM[6], @XMM[14]
   1747 	mov		r5, $rounds			@ pass rounds
   1748 	veor		@XMM[7], @XMM[7], @XMM[15]
   1749 	mov		r0, sp
   1750 
   1751 	bl		_bsaes_encrypt8
   1752 
   1753 	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
   1754 	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
   1755 	veor		@XMM[0], @XMM[0], @XMM[ 8]
   1756 	vld1.64		{@XMM[12]-@XMM[13]}, [r0,:128]!
   1757 	veor		@XMM[1], @XMM[1], @XMM[ 9]
   1758 	veor		@XMM[8], @XMM[4], @XMM[10]
   1759 	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
   1760 	veor		@XMM[9], @XMM[6], @XMM[11]
   1761 	vld1.64		{@XMM[14]-@XMM[15]}, [r0,:128]!
   1762 	veor		@XMM[10], @XMM[3], @XMM[12]
   1763 	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
   1764 	veor		@XMM[11], @XMM[7], @XMM[13]
   1765 	veor		@XMM[12], @XMM[2], @XMM[14]
   1766 	vst1.8		{@XMM[10]-@XMM[11]}, [$out]!
   1767 	veor		@XMM[13], @XMM[5], @XMM[15]
   1768 	vst1.8		{@XMM[12]-@XMM[13]}, [$out]!
   1769 
   1770 	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
   1771 
   1772 	subs		$len, #0x80
   1773 	bpl		.Lxts_enc_loop
   1774 
   1775 .Lxts_enc_short:
   1776 	adds		$len, #0x70
   1777 	bmi		.Lxts_enc_done
   1778 
   1779 	vldmia		$magic, {$twmask}	@ load XTS magic
   1780 	vshr.s64	@T[0], @XMM[8], #63
   1781 	mov		r0, sp
   1782 	vand		@T[0], @T[0], $twmask
   1783 ___
   1784 for($i=9;$i<16;$i++) {
   1785 $code.=<<___;
   1786 	vadd.u64	@XMM[$i], @XMM[$i-1], @XMM[$i-1]
   1787 	vst1.64		{@XMM[$i-1]}, [r0,:128]!
   1788 	vswp		`&Dhi("@T[0]")`,`&Dlo("@T[0]")`
   1789 	vshr.s64	@T[1], @XMM[$i], #63
   1790 	veor		@XMM[$i], @XMM[$i], @T[0]
   1791 	vand		@T[1], @T[1], $twmask
   1792 ___
   1793 	@T=reverse(@T);
   1794 
   1795 $code.=<<___ if ($i>=10);
   1796 	vld1.8		{@XMM[$i-10]}, [$inp]!
   1797 	subs		$len, #0x10
   1798 	bmi		.Lxts_enc_`$i-9`
   1799 ___
   1800 $code.=<<___ if ($i>=11);
   1801 	veor		@XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
   1802 ___
   1803 }
   1804 $code.=<<___;
   1805 	sub		$len, #0x10
   1806 	vst1.64		{@XMM[15]}, [r0,:128]		@ next round tweak
   1807 
   1808 	vld1.8		{@XMM[6]}, [$inp]!
   1809 	veor		@XMM[5], @XMM[5], @XMM[13]
   1810 #ifndef	BSAES_ASM_EXTENDED_KEY
   1811 	add		r4, sp, #0x90			@ pass key schedule
   1812 #else
   1813 	add		r4, $key, #248			@ pass key schedule
   1814 #endif
   1815 	veor		@XMM[6], @XMM[6], @XMM[14]
   1816 	mov		r5, $rounds			@ pass rounds
   1817 	mov		r0, sp
   1818 
   1819 	bl		_bsaes_encrypt8
   1820 
   1821 	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
   1822 	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
   1823 	veor		@XMM[0], @XMM[0], @XMM[ 8]
   1824 	vld1.64		{@XMM[12]-@XMM[13]}, [r0,:128]!
   1825 	veor		@XMM[1], @XMM[1], @XMM[ 9]
   1826 	veor		@XMM[8], @XMM[4], @XMM[10]
   1827 	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
   1828 	veor		@XMM[9], @XMM[6], @XMM[11]
   1829 	vld1.64		{@XMM[14]}, [r0,:128]!
   1830 	veor		@XMM[10], @XMM[3], @XMM[12]
   1831 	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
   1832 	veor		@XMM[11], @XMM[7], @XMM[13]
   1833 	veor		@XMM[12], @XMM[2], @XMM[14]
   1834 	vst1.8		{@XMM[10]-@XMM[11]}, [$out]!
   1835 	vst1.8		{@XMM[12]}, [$out]!
   1836 
   1837 	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
   1838 	b		.Lxts_enc_done
   1839 .align	4
   1840 .Lxts_enc_6:
   1841 	vst1.64		{@XMM[14]}, [r0,:128]		@ next round tweak
   1842 
   1843 	veor		@XMM[4], @XMM[4], @XMM[12]
   1844 #ifndef	BSAES_ASM_EXTENDED_KEY
   1845 	add		r4, sp, #0x90			@ pass key schedule
   1846 #else
   1847 	add		r4, $key, #248			@ pass key schedule
   1848 #endif
   1849 	veor		@XMM[5], @XMM[5], @XMM[13]
   1850 	mov		r5, $rounds			@ pass rounds
   1851 	mov		r0, sp
   1852 
   1853 	bl		_bsaes_encrypt8
   1854 
   1855 	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
   1856 	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
   1857 	veor		@XMM[0], @XMM[0], @XMM[ 8]
   1858 	vld1.64		{@XMM[12]-@XMM[13]}, [r0,:128]!
   1859 	veor		@XMM[1], @XMM[1], @XMM[ 9]
   1860 	veor		@XMM[8], @XMM[4], @XMM[10]
   1861 	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
   1862 	veor		@XMM[9], @XMM[6], @XMM[11]
   1863 	veor		@XMM[10], @XMM[3], @XMM[12]
   1864 	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
   1865 	veor		@XMM[11], @XMM[7], @XMM[13]
   1866 	vst1.8		{@XMM[10]-@XMM[11]}, [$out]!
   1867 
   1868 	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
   1869 	b		.Lxts_enc_done
   1870 
   1871 @ put this in range for both ARM and Thumb mode adr instructions
   1872 .align	5
   1873 .Lxts_magic:
   1874 	.quad	1, 0x87
   1875 
   1876 .align	5
   1877 .Lxts_enc_5:
   1878 	vst1.64		{@XMM[13]}, [r0,:128]		@ next round tweak
   1879 
   1880 	veor		@XMM[3], @XMM[3], @XMM[11]
   1881 #ifndef	BSAES_ASM_EXTENDED_KEY
   1882 	add		r4, sp, #0x90			@ pass key schedule
   1883 #else
   1884 	add		r4, $key, #248			@ pass key schedule
   1885 #endif
   1886 	veor		@XMM[4], @XMM[4], @XMM[12]
   1887 	mov		r5, $rounds			@ pass rounds
   1888 	mov		r0, sp
   1889 
   1890 	bl		_bsaes_encrypt8
   1891 
   1892 	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
   1893 	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
   1894 	veor		@XMM[0], @XMM[0], @XMM[ 8]
   1895 	vld1.64		{@XMM[12]}, [r0,:128]!
   1896 	veor		@XMM[1], @XMM[1], @XMM[ 9]
   1897 	veor		@XMM[8], @XMM[4], @XMM[10]
   1898 	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
   1899 	veor		@XMM[9], @XMM[6], @XMM[11]
   1900 	veor		@XMM[10], @XMM[3], @XMM[12]
   1901 	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
   1902 	vst1.8		{@XMM[10]}, [$out]!
   1903 
   1904 	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
   1905 	b		.Lxts_enc_done
   1906 .align	4
   1907 .Lxts_enc_4:
   1908 	vst1.64		{@XMM[12]}, [r0,:128]		@ next round tweak
   1909 
   1910 	veor		@XMM[2], @XMM[2], @XMM[10]
   1911 #ifndef	BSAES_ASM_EXTENDED_KEY
   1912 	add		r4, sp, #0x90			@ pass key schedule
   1913 #else
   1914 	add		r4, $key, #248			@ pass key schedule
   1915 #endif
   1916 	veor		@XMM[3], @XMM[3], @XMM[11]
   1917 	mov		r5, $rounds			@ pass rounds
   1918 	mov		r0, sp
   1919 
   1920 	bl		_bsaes_encrypt8
   1921 
   1922 	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
   1923 	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
   1924 	veor		@XMM[0], @XMM[0], @XMM[ 8]
   1925 	veor		@XMM[1], @XMM[1], @XMM[ 9]
   1926 	veor		@XMM[8], @XMM[4], @XMM[10]
   1927 	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
   1928 	veor		@XMM[9], @XMM[6], @XMM[11]
   1929 	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
   1930 
   1931 	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
   1932 	b		.Lxts_enc_done
   1933 .align	4
   1934 .Lxts_enc_3:
   1935 	vst1.64		{@XMM[11]}, [r0,:128]		@ next round tweak
   1936 
   1937 	veor		@XMM[1], @XMM[1], @XMM[9]
   1938 #ifndef	BSAES_ASM_EXTENDED_KEY
   1939 	add		r4, sp, #0x90			@ pass key schedule
   1940 #else
   1941 	add		r4, $key, #248			@ pass key schedule
   1942 #endif
   1943 	veor		@XMM[2], @XMM[2], @XMM[10]
   1944 	mov		r5, $rounds			@ pass rounds
   1945 	mov		r0, sp
   1946 
   1947 	bl		_bsaes_encrypt8
   1948 
   1949 	vld1.64		{@XMM[8]-@XMM[9]}, [r0,:128]!
   1950 	vld1.64		{@XMM[10]}, [r0,:128]!
   1951 	veor		@XMM[0], @XMM[0], @XMM[ 8]
   1952 	veor		@XMM[1], @XMM[1], @XMM[ 9]
   1953 	veor		@XMM[8], @XMM[4], @XMM[10]
   1954 	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
   1955 	vst1.8		{@XMM[8]}, [$out]!
   1956 
   1957 	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
   1958 	b		.Lxts_enc_done
   1959 .align	4
   1960 .Lxts_enc_2:
   1961 	vst1.64		{@XMM[10]}, [r0,:128]		@ next round tweak
   1962 
   1963 	veor		@XMM[0], @XMM[0], @XMM[8]
   1964 #ifndef	BSAES_ASM_EXTENDED_KEY
   1965 	add		r4, sp, #0x90			@ pass key schedule
   1966 #else
   1967 	add		r4, $key, #248			@ pass key schedule
   1968 #endif
   1969 	veor		@XMM[1], @XMM[1], @XMM[9]
   1970 	mov		r5, $rounds			@ pass rounds
   1971 	mov		r0, sp
   1972 
   1973 	bl		_bsaes_encrypt8
   1974 
   1975 	vld1.64		{@XMM[8]-@XMM[9]}, [r0,:128]!
   1976 	veor		@XMM[0], @XMM[0], @XMM[ 8]
   1977 	veor		@XMM[1], @XMM[1], @XMM[ 9]
   1978 	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
   1979 
   1980 	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
   1981 	b		.Lxts_enc_done
   1982 .align	4
   1983 .Lxts_enc_1:
   1984 	mov		r0, sp
   1985 	veor		@XMM[0], @XMM[8]
   1986 	mov		r1, sp
   1987 	vst1.8		{@XMM[0]}, [sp,:128]
   1988 	mov		r2, $key
   1989 	mov		r4, $fp				@ preserve fp
   1990 
   1991 	bl		AES_encrypt
   1992 
   1993 	vld1.8		{@XMM[0]}, [sp,:128]
   1994 	veor		@XMM[0], @XMM[0], @XMM[8]
   1995 	vst1.8		{@XMM[0]}, [$out]!
   1996 	mov		$fp, r4
   1997 
   1998 	vmov		@XMM[8], @XMM[9]		@ next round tweak
   1999 
   2000 .Lxts_enc_done:
   2001 #ifndef	XTS_CHAIN_TWEAK
   2002 	adds		$len, #0x10
   2003 	beq		.Lxts_enc_ret
   2004 	sub		r6, $out, #0x10
   2005 
   2006 .Lxts_enc_steal:
   2007 	ldrb		r0, [$inp], #1
   2008 	ldrb		r1, [$out, #-0x10]
   2009 	strb		r0, [$out, #-0x10]
   2010 	strb		r1, [$out], #1
   2011 
   2012 	subs		$len, #1
   2013 	bhi		.Lxts_enc_steal
   2014 
   2015 	vld1.8		{@XMM[0]}, [r6]
   2016 	mov		r0, sp
   2017 	veor		@XMM[0], @XMM[0], @XMM[8]
   2018 	mov		r1, sp
   2019 	vst1.8		{@XMM[0]}, [sp,:128]
   2020 	mov		r2, $key
   2021 	mov		r4, $fp			@ preserve fp
   2022 
   2023 	bl		AES_encrypt
   2024 
   2025 	vld1.8		{@XMM[0]}, [sp,:128]
   2026 	veor		@XMM[0], @XMM[0], @XMM[8]
   2027 	vst1.8		{@XMM[0]}, [r6]
   2028 	mov		$fp, r4
   2029 #endif
   2030 
   2031 .Lxts_enc_ret:
   2032 	bic		r0, $fp, #0xf
   2033 	vmov.i32	q0, #0
   2034 	vmov.i32	q1, #0
   2035 #ifdef	XTS_CHAIN_TWEAK
   2036 	ldr		r1, [$fp, #0x20+VFP_ABI_FRAME]	@ chain tweak
   2037 #endif
   2038 .Lxts_enc_bzero:				@ wipe key schedule [if any]
   2039 	vstmia		sp!, {q0-q1}
   2040 	cmp		sp, r0
   2041 	bne		.Lxts_enc_bzero
   2042 
   2043 	mov		sp, $fp
   2044 #ifdef	XTS_CHAIN_TWEAK
   2045 	vst1.8		{@XMM[8]}, [r1]
   2046 #endif
   2047 	VFP_ABI_POP
   2048 	ldmia		sp!, {r4-r10, pc}	@ return
   2049 
   2050 .size	bsaes_xts_encrypt,.-bsaes_xts_encrypt
   2051 
   2052 .globl	bsaes_xts_decrypt
   2053 .hidden	bsaes_xts_decrypt
   2054 .type	bsaes_xts_decrypt,%function
   2055 .align	4
   2056 bsaes_xts_decrypt:
   2057 	mov	ip, sp
   2058 	stmdb	sp!, {r4-r10, lr}		@ 0x20
   2059 	VFP_ABI_PUSH
   2060 	mov	r6, sp				@ future $fp
   2061 
   2062 	mov	$inp, r0
   2063 	mov	$out, r1
   2064 	mov	$len, r2
   2065 	mov	$key, r3
   2066 
   2067 	sub	r0, sp, #0x10			@ 0x10
   2068 	bic	r0, #0xf			@ align at 16 bytes
   2069 	mov	sp, r0
   2070 
   2071 #ifdef	XTS_CHAIN_TWEAK
   2072 	ldr	r0, [ip]			@ pointer to input tweak
   2073 #else
   2074 	@ generate initial tweak
   2075 	ldr	r0, [ip, #4]			@ iv[]
   2076 	mov	r1, sp
   2077 	ldr	r2, [ip, #0]			@ key2
   2078 	bl	AES_encrypt
   2079 	mov	r0, sp				@ pointer to initial tweak
   2080 #endif
   2081 
   2082 	ldr	$rounds, [$key, #240]		@ get # of rounds
   2083 	mov	$fp, r6
   2084 #ifndef	BSAES_ASM_EXTENDED_KEY
   2085 	@ allocate the key schedule on the stack
   2086 	sub	r12, sp, $rounds, lsl#7		@ 128 bytes per inner round key
   2087 	@ add	r12, #`128-32`			@ size of bit-sliced key schedule
   2088 	sub	r12, #`32+16`			@ place for tweak[9]
   2089 
   2090 	@ populate the key schedule
   2091 	mov	r4, $key			@ pass key
   2092 	mov	r5, $rounds			@ pass # of rounds
   2093 	mov	sp, r12
   2094 	add	r12, #0x90			@ pass key schedule
   2095 	bl	_bsaes_key_convert
   2096 	add	r4, sp, #0x90
   2097 	vldmia	r4, {@XMM[6]}
   2098 	vstmia	r12,  {@XMM[15]}		@ save last round key
   2099 	veor	@XMM[7], @XMM[7], @XMM[6]	@ fix up round 0 key
   2100 	vstmia	r4, {@XMM[7]}
   2101 #else
   2102 	ldr	r12, [$key, #244]
   2103 	eors	r12, #1
   2104 	beq	0f
   2105 
   2106 	str	r12, [$key, #244]
   2107 	mov	r4, $key			@ pass key
   2108 	mov	r5, $rounds			@ pass # of rounds
   2109 	add	r12, $key, #248			@ pass key schedule
   2110 	bl	_bsaes_key_convert
   2111 	add	r4, $key, #248
   2112 	vldmia	r4, {@XMM[6]}
   2113 	vstmia	r12,  {@XMM[15]}		@ save last round key
   2114 	veor	@XMM[7], @XMM[7], @XMM[6]	@ fix up round 0 key
   2115 	vstmia	r4, {@XMM[7]}
   2116 
   2117 .align	2
   2118 0:	sub	sp, #0x90			@ place for tweak[9]
   2119 #endif
   2120 	vld1.8	{@XMM[8]}, [r0]			@ initial tweak
   2121 	adr	$magic, .Lxts_magic
   2122 
   2123 #ifndef	XTS_CHAIN_TWEAK
   2124 	tst	$len, #0xf			@ if not multiple of 16
   2125 	it	ne				@ Thumb2 thing, sanity check in ARM
   2126 	subne	$len, #0x10			@ subtract another 16 bytes
   2127 #endif
   2128 	subs	$len, #0x80
   2129 
   2130 	blo	.Lxts_dec_short
   2131 	b	.Lxts_dec_loop
   2132 
   2133 .align	4
   2134 .Lxts_dec_loop:
   2135 	vldmia		$magic, {$twmask}	@ load XTS magic
   2136 	vshr.s64	@T[0], @XMM[8], #63
   2137 	mov		r0, sp
   2138 	vand		@T[0], @T[0], $twmask
   2139 ___
   2140 for($i=9;$i<16;$i++) {
   2141 $code.=<<___;
   2142 	vadd.u64	@XMM[$i], @XMM[$i-1], @XMM[$i-1]
   2143 	vst1.64		{@XMM[$i-1]}, [r0,:128]!
   2144 	vswp		`&Dhi("@T[0]")`,`&Dlo("@T[0]")`
   2145 	vshr.s64	@T[1], @XMM[$i], #63
   2146 	veor		@XMM[$i], @XMM[$i], @T[0]
   2147 	vand		@T[1], @T[1], $twmask
   2148 ___
   2149 	@T=reverse(@T);
   2150 
   2151 $code.=<<___ if ($i>=10);
   2152 	vld1.8		{@XMM[$i-10]}, [$inp]!
   2153 ___
   2154 $code.=<<___ if ($i>=11);
   2155 	veor		@XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
   2156 ___
   2157 }
   2158 $code.=<<___;
   2159 	vadd.u64	@XMM[8], @XMM[15], @XMM[15]
   2160 	vst1.64		{@XMM[15]}, [r0,:128]!
   2161 	vswp		`&Dhi("@T[0]")`,`&Dlo("@T[0]")`
   2162 	veor		@XMM[8], @XMM[8], @T[0]
   2163 	vst1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
   2164 
   2165 	vld1.8		{@XMM[6]-@XMM[7]}, [$inp]!
   2166 	veor		@XMM[5], @XMM[5], @XMM[13]
   2167 #ifndef	BSAES_ASM_EXTENDED_KEY
   2168 	add		r4, sp, #0x90			@ pass key schedule
   2169 #else
   2170 	add		r4, $key, #248			@ pass key schedule
   2171 #endif
   2172 	veor		@XMM[6], @XMM[6], @XMM[14]
   2173 	mov		r5, $rounds			@ pass rounds
   2174 	veor		@XMM[7], @XMM[7], @XMM[15]
   2175 	mov		r0, sp
   2176 
   2177 	bl		_bsaes_decrypt8
   2178 
   2179 	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
   2180 	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
   2181 	veor		@XMM[0], @XMM[0], @XMM[ 8]
   2182 	vld1.64		{@XMM[12]-@XMM[13]}, [r0,:128]!
   2183 	veor		@XMM[1], @XMM[1], @XMM[ 9]
   2184 	veor		@XMM[8], @XMM[6], @XMM[10]
   2185 	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
   2186 	veor		@XMM[9], @XMM[4], @XMM[11]
   2187 	vld1.64		{@XMM[14]-@XMM[15]}, [r0,:128]!
   2188 	veor		@XMM[10], @XMM[2], @XMM[12]
   2189 	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
   2190 	veor		@XMM[11], @XMM[7], @XMM[13]
   2191 	veor		@XMM[12], @XMM[3], @XMM[14]
   2192 	vst1.8		{@XMM[10]-@XMM[11]}, [$out]!
   2193 	veor		@XMM[13], @XMM[5], @XMM[15]
   2194 	vst1.8		{@XMM[12]-@XMM[13]}, [$out]!
   2195 
   2196 	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
   2197 
   2198 	subs		$len, #0x80
   2199 	bpl		.Lxts_dec_loop
   2200 
   2201 .Lxts_dec_short:
   2202 	adds		$len, #0x70
   2203 	bmi		.Lxts_dec_done
   2204 
   2205 	vldmia		$magic, {$twmask}	@ load XTS magic
   2206 	vshr.s64	@T[0], @XMM[8], #63
   2207 	mov		r0, sp
   2208 	vand		@T[0], @T[0], $twmask
   2209 ___
   2210 for($i=9;$i<16;$i++) {
   2211 $code.=<<___;
   2212 	vadd.u64	@XMM[$i], @XMM[$i-1], @XMM[$i-1]
   2213 	vst1.64		{@XMM[$i-1]}, [r0,:128]!
   2214 	vswp		`&Dhi("@T[0]")`,`&Dlo("@T[0]")`
   2215 	vshr.s64	@T[1], @XMM[$i], #63
   2216 	veor		@XMM[$i], @XMM[$i], @T[0]
   2217 	vand		@T[1], @T[1], $twmask
   2218 ___
   2219 	@T=reverse(@T);
   2220 
   2221 $code.=<<___ if ($i>=10);
   2222 	vld1.8		{@XMM[$i-10]}, [$inp]!
   2223 	subs		$len, #0x10
   2224 	bmi		.Lxts_dec_`$i-9`
   2225 ___
   2226 $code.=<<___ if ($i>=11);
   2227 	veor		@XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
   2228 ___
   2229 }
   2230 $code.=<<___;
   2231 	sub		$len, #0x10
   2232 	vst1.64		{@XMM[15]}, [r0,:128]		@ next round tweak
   2233 
   2234 	vld1.8		{@XMM[6]}, [$inp]!
   2235 	veor		@XMM[5], @XMM[5], @XMM[13]
   2236 #ifndef	BSAES_ASM_EXTENDED_KEY
   2237 	add		r4, sp, #0x90			@ pass key schedule
   2238 #else
   2239 	add		r4, $key, #248			@ pass key schedule
   2240 #endif
   2241 	veor		@XMM[6], @XMM[6], @XMM[14]
   2242 	mov		r5, $rounds			@ pass rounds
   2243 	mov		r0, sp
   2244 
   2245 	bl		_bsaes_decrypt8
   2246 
   2247 	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
   2248 	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
   2249 	veor		@XMM[0], @XMM[0], @XMM[ 8]
   2250 	vld1.64		{@XMM[12]-@XMM[13]}, [r0,:128]!
   2251 	veor		@XMM[1], @XMM[1], @XMM[ 9]
   2252 	veor		@XMM[8], @XMM[6], @XMM[10]
   2253 	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
   2254 	veor		@XMM[9], @XMM[4], @XMM[11]
   2255 	vld1.64		{@XMM[14]}, [r0,:128]!
   2256 	veor		@XMM[10], @XMM[2], @XMM[12]
   2257 	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
   2258 	veor		@XMM[11], @XMM[7], @XMM[13]
   2259 	veor		@XMM[12], @XMM[3], @XMM[14]
   2260 	vst1.8		{@XMM[10]-@XMM[11]}, [$out]!
   2261 	vst1.8		{@XMM[12]}, [$out]!
   2262 
   2263 	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
   2264 	b		.Lxts_dec_done
   2265 .align	4
   2266 .Lxts_dec_6:
   2267 	vst1.64		{@XMM[14]}, [r0,:128]		@ next round tweak
   2268 
   2269 	veor		@XMM[4], @XMM[4], @XMM[12]
   2270 #ifndef	BSAES_ASM_EXTENDED_KEY
   2271 	add		r4, sp, #0x90			@ pass key schedule
   2272 #else
   2273 	add		r4, $key, #248			@ pass key schedule
   2274 #endif
   2275 	veor		@XMM[5], @XMM[5], @XMM[13]
   2276 	mov		r5, $rounds			@ pass rounds
   2277 	mov		r0, sp
   2278 
   2279 	bl		_bsaes_decrypt8
   2280 
   2281 	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
   2282 	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
   2283 	veor		@XMM[0], @XMM[0], @XMM[ 8]
   2284 	vld1.64		{@XMM[12]-@XMM[13]}, [r0,:128]!
   2285 	veor		@XMM[1], @XMM[1], @XMM[ 9]
   2286 	veor		@XMM[8], @XMM[6], @XMM[10]
   2287 	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
   2288 	veor		@XMM[9], @XMM[4], @XMM[11]
   2289 	veor		@XMM[10], @XMM[2], @XMM[12]
   2290 	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
   2291 	veor		@XMM[11], @XMM[7], @XMM[13]
   2292 	vst1.8		{@XMM[10]-@XMM[11]}, [$out]!
   2293 
   2294 	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
   2295 	b		.Lxts_dec_done
   2296 .align	4
   2297 .Lxts_dec_5:
   2298 	vst1.64		{@XMM[13]}, [r0,:128]		@ next round tweak
   2299 
   2300 	veor		@XMM[3], @XMM[3], @XMM[11]
   2301 #ifndef	BSAES_ASM_EXTENDED_KEY
   2302 	add		r4, sp, #0x90			@ pass key schedule
   2303 #else
   2304 	add		r4, $key, #248			@ pass key schedule
   2305 #endif
   2306 	veor		@XMM[4], @XMM[4], @XMM[12]
   2307 	mov		r5, $rounds			@ pass rounds
   2308 	mov		r0, sp
   2309 
   2310 	bl		_bsaes_decrypt8
   2311 
   2312 	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
   2313 	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
   2314 	veor		@XMM[0], @XMM[0], @XMM[ 8]
   2315 	vld1.64		{@XMM[12]}, [r0,:128]!
   2316 	veor		@XMM[1], @XMM[1], @XMM[ 9]
   2317 	veor		@XMM[8], @XMM[6], @XMM[10]
   2318 	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
   2319 	veor		@XMM[9], @XMM[4], @XMM[11]
   2320 	veor		@XMM[10], @XMM[2], @XMM[12]
   2321 	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
   2322 	vst1.8		{@XMM[10]}, [$out]!
   2323 
   2324 	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
   2325 	b		.Lxts_dec_done
   2326 .align	4
   2327 .Lxts_dec_4:
   2328 	vst1.64		{@XMM[12]}, [r0,:128]		@ next round tweak
   2329 
   2330 	veor		@XMM[2], @XMM[2], @XMM[10]
   2331 #ifndef	BSAES_ASM_EXTENDED_KEY
   2332 	add		r4, sp, #0x90			@ pass key schedule
   2333 #else
   2334 	add		r4, $key, #248			@ pass key schedule
   2335 #endif
   2336 	veor		@XMM[3], @XMM[3], @XMM[11]
   2337 	mov		r5, $rounds			@ pass rounds
   2338 	mov		r0, sp
   2339 
   2340 	bl		_bsaes_decrypt8
   2341 
   2342 	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
   2343 	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
   2344 	veor		@XMM[0], @XMM[0], @XMM[ 8]
   2345 	veor		@XMM[1], @XMM[1], @XMM[ 9]
   2346 	veor		@XMM[8], @XMM[6], @XMM[10]
   2347 	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
   2348 	veor		@XMM[9], @XMM[4], @XMM[11]
   2349 	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
   2350 
   2351 	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
   2352 	b		.Lxts_dec_done
   2353 .align	4
   2354 .Lxts_dec_3:
   2355 	vst1.64		{@XMM[11]}, [r0,:128]		@ next round tweak
   2356 
   2357 	veor		@XMM[1], @XMM[1], @XMM[9]
   2358 #ifndef	BSAES_ASM_EXTENDED_KEY
   2359 	add		r4, sp, #0x90			@ pass key schedule
   2360 #else
   2361 	add		r4, $key, #248			@ pass key schedule
   2362 #endif
   2363 	veor		@XMM[2], @XMM[2], @XMM[10]
   2364 	mov		r5, $rounds			@ pass rounds
   2365 	mov		r0, sp
   2366 
   2367 	bl		_bsaes_decrypt8
   2368 
   2369 	vld1.64		{@XMM[8]-@XMM[9]}, [r0,:128]!
   2370 	vld1.64		{@XMM[10]}, [r0,:128]!
   2371 	veor		@XMM[0], @XMM[0], @XMM[ 8]
   2372 	veor		@XMM[1], @XMM[1], @XMM[ 9]
   2373 	veor		@XMM[8], @XMM[6], @XMM[10]
   2374 	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
   2375 	vst1.8		{@XMM[8]}, [$out]!
   2376 
   2377 	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
   2378 	b		.Lxts_dec_done
   2379 .align	4
   2380 .Lxts_dec_2:
   2381 	vst1.64		{@XMM[10]}, [r0,:128]		@ next round tweak
   2382 
   2383 	veor		@XMM[0], @XMM[0], @XMM[8]
   2384 #ifndef	BSAES_ASM_EXTENDED_KEY
   2385 	add		r4, sp, #0x90			@ pass key schedule
   2386 #else
   2387 	add		r4, $key, #248			@ pass key schedule
   2388 #endif
   2389 	veor		@XMM[1], @XMM[1], @XMM[9]
   2390 	mov		r5, $rounds			@ pass rounds
   2391 	mov		r0, sp
   2392 
   2393 	bl		_bsaes_decrypt8
   2394 
   2395 	vld1.64		{@XMM[8]-@XMM[9]}, [r0,:128]!
   2396 	veor		@XMM[0], @XMM[0], @XMM[ 8]
   2397 	veor		@XMM[1], @XMM[1], @XMM[ 9]
   2398 	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
   2399 
   2400 	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
   2401 	b		.Lxts_dec_done
   2402 .align	4
   2403 .Lxts_dec_1:
   2404 	mov		r0, sp
   2405 	veor		@XMM[0], @XMM[8]
   2406 	mov		r1, sp
   2407 	vst1.8		{@XMM[0]}, [sp,:128]
   2408 	mov		r2, $key
   2409 	mov		r4, $fp				@ preserve fp
   2410 	mov		r5, $magic			@ preserve magic
   2411 
   2412 	bl		AES_decrypt
   2413 
   2414 	vld1.8		{@XMM[0]}, [sp,:128]
   2415 	veor		@XMM[0], @XMM[0], @XMM[8]
   2416 	vst1.8		{@XMM[0]}, [$out]!
   2417 	mov		$fp, r4
   2418 	mov		$magic, r5
   2419 
   2420 	vmov		@XMM[8], @XMM[9]		@ next round tweak
   2421 
   2422 .Lxts_dec_done:
   2423 #ifndef	XTS_CHAIN_TWEAK
   2424 	adds		$len, #0x10
   2425 	beq		.Lxts_dec_ret
   2426 
   2427 	@ calculate one round of extra tweak for the stolen ciphertext
   2428 	vldmia		$magic, {$twmask}
   2429 	vshr.s64	@XMM[6], @XMM[8], #63
   2430 	vand		@XMM[6], @XMM[6], $twmask
   2431 	vadd.u64	@XMM[9], @XMM[8], @XMM[8]
   2432 	vswp		`&Dhi("@XMM[6]")`,`&Dlo("@XMM[6]")`
   2433 	veor		@XMM[9], @XMM[9], @XMM[6]
   2434 
   2435 	@ perform the final decryption with the last tweak value
   2436 	vld1.8		{@XMM[0]}, [$inp]!
   2437 	mov		r0, sp
   2438 	veor		@XMM[0], @XMM[0], @XMM[9]
   2439 	mov		r1, sp
   2440 	vst1.8		{@XMM[0]}, [sp,:128]
   2441 	mov		r2, $key
   2442 	mov		r4, $fp			@ preserve fp
   2443 
   2444 	bl		AES_decrypt
   2445 
   2446 	vld1.8		{@XMM[0]}, [sp,:128]
   2447 	veor		@XMM[0], @XMM[0], @XMM[9]
   2448 	vst1.8		{@XMM[0]}, [$out]
   2449 
   2450 	mov		r6, $out
   2451 .Lxts_dec_steal:
   2452 	ldrb		r1, [$out]
   2453 	ldrb		r0, [$inp], #1
   2454 	strb		r1, [$out, #0x10]
   2455 	strb		r0, [$out], #1
   2456 
   2457 	subs		$len, #1
   2458 	bhi		.Lxts_dec_steal
   2459 
   2460 	vld1.8		{@XMM[0]}, [r6]
   2461 	mov		r0, sp
   2462 	veor		@XMM[0], @XMM[8]
   2463 	mov		r1, sp
   2464 	vst1.8		{@XMM[0]}, [sp,:128]
   2465 	mov		r2, $key
   2466 
   2467 	bl		AES_decrypt
   2468 
   2469 	vld1.8		{@XMM[0]}, [sp,:128]
   2470 	veor		@XMM[0], @XMM[0], @XMM[8]
   2471 	vst1.8		{@XMM[0]}, [r6]
   2472 	mov		$fp, r4
   2473 #endif
   2474 
   2475 .Lxts_dec_ret:
   2476 	bic		r0, $fp, #0xf
   2477 	vmov.i32	q0, #0
   2478 	vmov.i32	q1, #0
   2479 #ifdef	XTS_CHAIN_TWEAK
   2480 	ldr		r1, [$fp, #0x20+VFP_ABI_FRAME]	@ chain tweak
   2481 #endif
   2482 .Lxts_dec_bzero:				@ wipe key schedule [if any]
   2483 	vstmia		sp!, {q0-q1}
   2484 	cmp		sp, r0
   2485 	bne		.Lxts_dec_bzero
   2486 
   2487 	mov		sp, $fp
   2488 #ifdef	XTS_CHAIN_TWEAK
   2489 	vst1.8		{@XMM[8]}, [r1]
   2490 #endif
   2491 	VFP_ABI_POP
   2492 	ldmia		sp!, {r4-r10, pc}	@ return
   2493 
   2494 .size	bsaes_xts_decrypt,.-bsaes_xts_decrypt
   2495 ___
   2496 }
   2497 $code.=<<___;
   2498 #endif
   2499 ___
   2500 
   2501 $code =~ s/\`([^\`]*)\`/eval($1)/gem;
   2502 
   2503 open SELF,$0;
   2504 while(<SELF>) {
   2505 	next if (/^#!/);
   2506         last if (!s/^#/@/ and !/^$/);
   2507         print;
   2508 }
   2509 close SELF;
   2510 
   2511 print $code;
   2512 
   2513 close STDOUT;
   2514