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