456a46967917117952d44cda94bf7104654a9715
[openssl.git] / crypto / aes / asm / aes-armv4.pl
1 #! /usr/bin/env perl
2 # Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.
3 #
4 # Licensed under the Apache License 2.0 (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@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
17 # AES for ARMv4
18
19 # January 2007.
20 #
21 # Code uses single 1K S-box and is >2 times faster than code generated
22 # by gcc-3.4.1. This is thanks to unique feature of ARMv4 ISA, which
23 # allows to merge logical or arithmetic operation with shift or rotate
24 # in one instruction and emit combined result every cycle. The module
25 # is endian-neutral. The performance is ~42 cycles/byte for 128-bit
26 # key [on single-issue Xscale PXA250 core].
27
28 # May 2007.
29 #
30 # AES_set_[en|de]crypt_key is added.
31
32 # July 2010.
33 #
34 # Rescheduling for dual-issue pipeline resulted in 12% improvement on
35 # Cortex A8 core and ~25 cycles per byte processed with 128-bit key.
36
37 # February 2011.
38 #
39 # Profiler-assisted and platform-specific optimization resulted in 16%
40 # improvement on Cortex A8 core and ~21.5 cycles per byte.
41
42 $flavour = shift;
43 if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
44 else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
45
46 if ($flavour && $flavour ne "void") {
47     $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
48     ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
49     ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
50     die "can't locate arm-xlate.pl";
51
52     open STDOUT,"| \"$^X\" $xlate $flavour $output";
53 } else {
54     open STDOUT,">$output";
55 }
56
57 $s0="r0";
58 $s1="r1";
59 $s2="r2";
60 $s3="r3";
61 $t1="r4";
62 $t2="r5";
63 $t3="r6";
64 $i1="r7";
65 $i2="r8";
66 $i3="r9";
67
68 $tbl="r10";
69 $key="r11";
70 $rounds="r12";
71
72 $code=<<___;
73 #ifndef __KERNEL__
74 # include "arm_arch.h"
75 #else
76 # define __ARM_ARCH__ __LINUX_ARM_ARCH__
77 #endif
78
79 #if defined(__thumb2__) && !defined(__APPLE__)
80 .syntax unified
81 .thumb
82 #else
83 .code   32
84 #undef __thumb2__
85 #endif
86
87 .text
88
89 .type   AES_Te,%object
90 .align  5
91 AES_Te:
92 .word   0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d
93 .word   0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554
94 .word   0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d
95 .word   0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a
96 .word   0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87
97 .word   0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b
98 .word   0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea
99 .word   0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b
100 .word   0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a
101 .word   0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f
102 .word   0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108
103 .word   0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f
104 .word   0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e
105 .word   0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5
106 .word   0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d
107 .word   0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f
108 .word   0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e
109 .word   0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb
110 .word   0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce
111 .word   0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497
112 .word   0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c
113 .word   0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed
114 .word   0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b
115 .word   0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a
116 .word   0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16
117 .word   0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594
118 .word   0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81
119 .word   0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3
120 .word   0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a
121 .word   0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504
122 .word   0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163
123 .word   0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d
124 .word   0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f
125 .word   0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739
126 .word   0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47
127 .word   0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395
128 .word   0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f
129 .word   0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883
130 .word   0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c
131 .word   0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76
132 .word   0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e
133 .word   0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4
134 .word   0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6
135 .word   0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b
136 .word   0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7
137 .word   0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0
138 .word   0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25
139 .word   0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818
140 .word   0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72
141 .word   0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651
142 .word   0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21
143 .word   0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85
144 .word   0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa
145 .word   0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12
146 .word   0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0
147 .word   0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9
148 .word   0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133
149 .word   0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7
150 .word   0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920
151 .word   0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a
152 .word   0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17
153 .word   0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8
154 .word   0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11
155 .word   0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a
156 @ Te4[256]
157 .byte   0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5
158 .byte   0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76
159 .byte   0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0
160 .byte   0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0
161 .byte   0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc
162 .byte   0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15
163 .byte   0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a
164 .byte   0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75
165 .byte   0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0
166 .byte   0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84
167 .byte   0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b
168 .byte   0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf
169 .byte   0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85
170 .byte   0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8
171 .byte   0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5
172 .byte   0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2
173 .byte   0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17
174 .byte   0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73
175 .byte   0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88
176 .byte   0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb
177 .byte   0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c
178 .byte   0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79
179 .byte   0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9
180 .byte   0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08
181 .byte   0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6
182 .byte   0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a
183 .byte   0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e
184 .byte   0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e
185 .byte   0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94
186 .byte   0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf
187 .byte   0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68
188 .byte   0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
189 @ rcon[]
190 .word   0x01000000, 0x02000000, 0x04000000, 0x08000000
191 .word   0x10000000, 0x20000000, 0x40000000, 0x80000000
192 .word   0x1B000000, 0x36000000, 0, 0, 0, 0, 0, 0
193 .size   AES_Te,.-AES_Te
194
195 @ void AES_encrypt(const unsigned char *in, unsigned char *out,
196 @                const AES_KEY *key) {
197 .global AES_encrypt
198 .type   AES_encrypt,%function
199 .align  5
200 AES_encrypt:
201 #ifndef __thumb2__
202         sub     r3,pc,#8                @ AES_encrypt
203 #else
204         adr     r3,.
205 #endif
206         stmdb   sp!,{r1,r4-r12,lr}
207 #if defined(__thumb2__) || defined(__APPLE__)
208         adr     $tbl,AES_Te
209 #else
210         sub     $tbl,r3,#AES_encrypt-AES_Te     @ Te
211 #endif
212         mov     $rounds,r0              @ inp
213         mov     $key,r2
214 #if __ARM_ARCH__<7
215         ldrb    $s0,[$rounds,#3]        @ load input data in endian-neutral
216         ldrb    $t1,[$rounds,#2]        @ manner...
217         ldrb    $t2,[$rounds,#1]
218         ldrb    $t3,[$rounds,#0]
219         orr     $s0,$s0,$t1,lsl#8
220         ldrb    $s1,[$rounds,#7]
221         orr     $s0,$s0,$t2,lsl#16
222         ldrb    $t1,[$rounds,#6]
223         orr     $s0,$s0,$t3,lsl#24
224         ldrb    $t2,[$rounds,#5]
225         ldrb    $t3,[$rounds,#4]
226         orr     $s1,$s1,$t1,lsl#8
227         ldrb    $s2,[$rounds,#11]
228         orr     $s1,$s1,$t2,lsl#16
229         ldrb    $t1,[$rounds,#10]
230         orr     $s1,$s1,$t3,lsl#24
231         ldrb    $t2,[$rounds,#9]
232         ldrb    $t3,[$rounds,#8]
233         orr     $s2,$s2,$t1,lsl#8
234         ldrb    $s3,[$rounds,#15]
235         orr     $s2,$s2,$t2,lsl#16
236         ldrb    $t1,[$rounds,#14]
237         orr     $s2,$s2,$t3,lsl#24
238         ldrb    $t2,[$rounds,#13]
239         ldrb    $t3,[$rounds,#12]
240         orr     $s3,$s3,$t1,lsl#8
241         orr     $s3,$s3,$t2,lsl#16
242         orr     $s3,$s3,$t3,lsl#24
243 #else
244         ldr     $s0,[$rounds,#0]
245         ldr     $s1,[$rounds,#4]
246         ldr     $s2,[$rounds,#8]
247         ldr     $s3,[$rounds,#12]
248 #ifdef __ARMEL__
249         rev     $s0,$s0
250         rev     $s1,$s1
251         rev     $s2,$s2
252         rev     $s3,$s3
253 #endif
254 #endif
255         bl      _armv4_AES_encrypt
256
257         ldr     $rounds,[sp],#4         @ pop out
258 #if __ARM_ARCH__>=7
259 #ifdef __ARMEL__
260         rev     $s0,$s0
261         rev     $s1,$s1
262         rev     $s2,$s2
263         rev     $s3,$s3
264 #endif
265         str     $s0,[$rounds,#0]
266         str     $s1,[$rounds,#4]
267         str     $s2,[$rounds,#8]
268         str     $s3,[$rounds,#12]
269 #else
270         mov     $t1,$s0,lsr#24          @ write output in endian-neutral
271         mov     $t2,$s0,lsr#16          @ manner...
272         mov     $t3,$s0,lsr#8
273         strb    $t1,[$rounds,#0]
274         strb    $t2,[$rounds,#1]
275         mov     $t1,$s1,lsr#24
276         strb    $t3,[$rounds,#2]
277         mov     $t2,$s1,lsr#16
278         strb    $s0,[$rounds,#3]
279         mov     $t3,$s1,lsr#8
280         strb    $t1,[$rounds,#4]
281         strb    $t2,[$rounds,#5]
282         mov     $t1,$s2,lsr#24
283         strb    $t3,[$rounds,#6]
284         mov     $t2,$s2,lsr#16
285         strb    $s1,[$rounds,#7]
286         mov     $t3,$s2,lsr#8
287         strb    $t1,[$rounds,#8]
288         strb    $t2,[$rounds,#9]
289         mov     $t1,$s3,lsr#24
290         strb    $t3,[$rounds,#10]
291         mov     $t2,$s3,lsr#16
292         strb    $s2,[$rounds,#11]
293         mov     $t3,$s3,lsr#8
294         strb    $t1,[$rounds,#12]
295         strb    $t2,[$rounds,#13]
296         strb    $t3,[$rounds,#14]
297         strb    $s3,[$rounds,#15]
298 #endif
299 #if __ARM_ARCH__>=5
300         ldmia   sp!,{r4-r12,pc}
301 #else
302         ldmia   sp!,{r4-r12,lr}
303         tst     lr,#1
304         moveq   pc,lr                   @ be binary compatible with V4, yet
305         bx      lr                      @ interoperable with Thumb ISA:-)
306 #endif
307 .size   AES_encrypt,.-AES_encrypt
308
309 .type   _armv4_AES_encrypt,%function
310 .align  2
311 _armv4_AES_encrypt:
312         str     lr,[sp,#-4]!            @ push lr
313         ldmia   $key!,{$t1-$i1}
314         eor     $s0,$s0,$t1
315         ldr     $rounds,[$key,#240-16]
316         eor     $s1,$s1,$t2
317         eor     $s2,$s2,$t3
318         eor     $s3,$s3,$i1
319         sub     $rounds,$rounds,#1
320         mov     lr,#255
321
322         and     $i1,lr,$s0
323         and     $i2,lr,$s0,lsr#8
324         and     $i3,lr,$s0,lsr#16
325         mov     $s0,$s0,lsr#24
326 .Lenc_loop:
327         ldr     $t1,[$tbl,$i1,lsl#2]    @ Te3[s0>>0]
328         and     $i1,lr,$s1,lsr#16       @ i0
329         ldr     $t2,[$tbl,$i2,lsl#2]    @ Te2[s0>>8]
330         and     $i2,lr,$s1
331         ldr     $t3,[$tbl,$i3,lsl#2]    @ Te1[s0>>16]
332         and     $i3,lr,$s1,lsr#8
333         ldr     $s0,[$tbl,$s0,lsl#2]    @ Te0[s0>>24]
334         mov     $s1,$s1,lsr#24
335
336         ldr     $i1,[$tbl,$i1,lsl#2]    @ Te1[s1>>16]
337         ldr     $i2,[$tbl,$i2,lsl#2]    @ Te3[s1>>0]
338         ldr     $i3,[$tbl,$i3,lsl#2]    @ Te2[s1>>8]
339         eor     $s0,$s0,$i1,ror#8
340         ldr     $s1,[$tbl,$s1,lsl#2]    @ Te0[s1>>24]
341         and     $i1,lr,$s2,lsr#8        @ i0
342         eor     $t2,$t2,$i2,ror#8
343         and     $i2,lr,$s2,lsr#16       @ i1
344         eor     $t3,$t3,$i3,ror#8
345         and     $i3,lr,$s2
346         ldr     $i1,[$tbl,$i1,lsl#2]    @ Te2[s2>>8]
347         eor     $s1,$s1,$t1,ror#24
348         ldr     $i2,[$tbl,$i2,lsl#2]    @ Te1[s2>>16]
349         mov     $s2,$s2,lsr#24
350
351         ldr     $i3,[$tbl,$i3,lsl#2]    @ Te3[s2>>0]
352         eor     $s0,$s0,$i1,ror#16
353         ldr     $s2,[$tbl,$s2,lsl#2]    @ Te0[s2>>24]
354         and     $i1,lr,$s3              @ i0
355         eor     $s1,$s1,$i2,ror#8
356         and     $i2,lr,$s3,lsr#8        @ i1
357         eor     $t3,$t3,$i3,ror#16
358         and     $i3,lr,$s3,lsr#16       @ i2
359         ldr     $i1,[$tbl,$i1,lsl#2]    @ Te3[s3>>0]
360         eor     $s2,$s2,$t2,ror#16
361         ldr     $i2,[$tbl,$i2,lsl#2]    @ Te2[s3>>8]
362         mov     $s3,$s3,lsr#24
363
364         ldr     $i3,[$tbl,$i3,lsl#2]    @ Te1[s3>>16]
365         eor     $s0,$s0,$i1,ror#24
366         ldr     $i1,[$key],#16
367         eor     $s1,$s1,$i2,ror#16
368         ldr     $s3,[$tbl,$s3,lsl#2]    @ Te0[s3>>24]
369         eor     $s2,$s2,$i3,ror#8
370         ldr     $t1,[$key,#-12]
371         eor     $s3,$s3,$t3,ror#8
372
373         ldr     $t2,[$key,#-8]
374         eor     $s0,$s0,$i1
375         ldr     $t3,[$key,#-4]
376         and     $i1,lr,$s0
377         eor     $s1,$s1,$t1
378         and     $i2,lr,$s0,lsr#8
379         eor     $s2,$s2,$t2
380         and     $i3,lr,$s0,lsr#16
381         eor     $s3,$s3,$t3
382         mov     $s0,$s0,lsr#24
383
384         subs    $rounds,$rounds,#1
385         bne     .Lenc_loop
386
387         add     $tbl,$tbl,#2
388
389         ldrb    $t1,[$tbl,$i1,lsl#2]    @ Te4[s0>>0]
390         and     $i1,lr,$s1,lsr#16       @ i0
391         ldrb    $t2,[$tbl,$i2,lsl#2]    @ Te4[s0>>8]
392         and     $i2,lr,$s1
393         ldrb    $t3,[$tbl,$i3,lsl#2]    @ Te4[s0>>16]
394         and     $i3,lr,$s1,lsr#8
395         ldrb    $s0,[$tbl,$s0,lsl#2]    @ Te4[s0>>24]
396         mov     $s1,$s1,lsr#24
397
398         ldrb    $i1,[$tbl,$i1,lsl#2]    @ Te4[s1>>16]
399         ldrb    $i2,[$tbl,$i2,lsl#2]    @ Te4[s1>>0]
400         ldrb    $i3,[$tbl,$i3,lsl#2]    @ Te4[s1>>8]
401         eor     $s0,$i1,$s0,lsl#8
402         ldrb    $s1,[$tbl,$s1,lsl#2]    @ Te4[s1>>24]
403         and     $i1,lr,$s2,lsr#8        @ i0
404         eor     $t2,$i2,$t2,lsl#8
405         and     $i2,lr,$s2,lsr#16       @ i1
406         eor     $t3,$i3,$t3,lsl#8
407         and     $i3,lr,$s2
408         ldrb    $i1,[$tbl,$i1,lsl#2]    @ Te4[s2>>8]
409         eor     $s1,$t1,$s1,lsl#24
410         ldrb    $i2,[$tbl,$i2,lsl#2]    @ Te4[s2>>16]
411         mov     $s2,$s2,lsr#24
412
413         ldrb    $i3,[$tbl,$i3,lsl#2]    @ Te4[s2>>0]
414         eor     $s0,$i1,$s0,lsl#8
415         ldrb    $s2,[$tbl,$s2,lsl#2]    @ Te4[s2>>24]
416         and     $i1,lr,$s3              @ i0
417         eor     $s1,$s1,$i2,lsl#16
418         and     $i2,lr,$s3,lsr#8        @ i1
419         eor     $t3,$i3,$t3,lsl#8
420         and     $i3,lr,$s3,lsr#16       @ i2
421         ldrb    $i1,[$tbl,$i1,lsl#2]    @ Te4[s3>>0]
422         eor     $s2,$t2,$s2,lsl#24
423         ldrb    $i2,[$tbl,$i2,lsl#2]    @ Te4[s3>>8]
424         mov     $s3,$s3,lsr#24
425
426         ldrb    $i3,[$tbl,$i3,lsl#2]    @ Te4[s3>>16]
427         eor     $s0,$i1,$s0,lsl#8
428         ldr     $i1,[$key,#0]
429         ldrb    $s3,[$tbl,$s3,lsl#2]    @ Te4[s3>>24]
430         eor     $s1,$s1,$i2,lsl#8
431         ldr     $t1,[$key,#4]
432         eor     $s2,$s2,$i3,lsl#16
433         ldr     $t2,[$key,#8]
434         eor     $s3,$t3,$s3,lsl#24
435         ldr     $t3,[$key,#12]
436
437         eor     $s0,$s0,$i1
438         eor     $s1,$s1,$t1
439         eor     $s2,$s2,$t2
440         eor     $s3,$s3,$t3
441
442         sub     $tbl,$tbl,#2
443         ldr     pc,[sp],#4              @ pop and return
444 .size   _armv4_AES_encrypt,.-_armv4_AES_encrypt
445
446 .global AES_set_encrypt_key
447 .type   AES_set_encrypt_key,%function
448 .align  5
449 AES_set_encrypt_key:
450 _armv4_AES_set_encrypt_key:
451 #ifndef __thumb2__
452         sub     r3,pc,#8                @ AES_set_encrypt_key
453 #else
454         adr     r3,.
455 #endif
456         teq     r0,#0
457 #ifdef  __thumb2__
458         itt     eq                      @ Thumb2 thing, sanity check in ARM
459 #endif
460         moveq   r0,#-1
461         beq     .Labrt
462         teq     r2,#0
463 #ifdef  __thumb2__
464         itt     eq                      @ Thumb2 thing, sanity check in ARM
465 #endif
466         moveq   r0,#-1
467         beq     .Labrt
468
469         teq     r1,#128
470         beq     .Lok
471         teq     r1,#192
472         beq     .Lok
473         teq     r1,#256
474 #ifdef  __thumb2__
475         itt     ne                      @ Thumb2 thing, sanity check in ARM
476 #endif
477         movne   r0,#-1
478         bne     .Labrt
479
480 .Lok:   stmdb   sp!,{r4-r12,lr}
481         mov     $rounds,r0              @ inp
482         mov     lr,r1                   @ bits
483         mov     $key,r2                 @ key
484
485 #if defined(__thumb2__) || defined(__APPLE__)
486         adr     $tbl,AES_Te+1024                                @ Te4
487 #else
488         sub     $tbl,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024 @ Te4
489 #endif
490
491 #if __ARM_ARCH__<7
492         ldrb    $s0,[$rounds,#3]        @ load input data in endian-neutral
493         ldrb    $t1,[$rounds,#2]        @ manner...
494         ldrb    $t2,[$rounds,#1]
495         ldrb    $t3,[$rounds,#0]
496         orr     $s0,$s0,$t1,lsl#8
497         ldrb    $s1,[$rounds,#7]
498         orr     $s0,$s0,$t2,lsl#16
499         ldrb    $t1,[$rounds,#6]
500         orr     $s0,$s0,$t3,lsl#24
501         ldrb    $t2,[$rounds,#5]
502         ldrb    $t3,[$rounds,#4]
503         orr     $s1,$s1,$t1,lsl#8
504         ldrb    $s2,[$rounds,#11]
505         orr     $s1,$s1,$t2,lsl#16
506         ldrb    $t1,[$rounds,#10]
507         orr     $s1,$s1,$t3,lsl#24
508         ldrb    $t2,[$rounds,#9]
509         ldrb    $t3,[$rounds,#8]
510         orr     $s2,$s2,$t1,lsl#8
511         ldrb    $s3,[$rounds,#15]
512         orr     $s2,$s2,$t2,lsl#16
513         ldrb    $t1,[$rounds,#14]
514         orr     $s2,$s2,$t3,lsl#24
515         ldrb    $t2,[$rounds,#13]
516         ldrb    $t3,[$rounds,#12]
517         orr     $s3,$s3,$t1,lsl#8
518         str     $s0,[$key],#16
519         orr     $s3,$s3,$t2,lsl#16
520         str     $s1,[$key,#-12]
521         orr     $s3,$s3,$t3,lsl#24
522         str     $s2,[$key,#-8]
523         str     $s3,[$key,#-4]
524 #else
525         ldr     $s0,[$rounds,#0]
526         ldr     $s1,[$rounds,#4]
527         ldr     $s2,[$rounds,#8]
528         ldr     $s3,[$rounds,#12]
529 #ifdef __ARMEL__
530         rev     $s0,$s0
531         rev     $s1,$s1
532         rev     $s2,$s2
533         rev     $s3,$s3
534 #endif
535         str     $s0,[$key],#16
536         str     $s1,[$key,#-12]
537         str     $s2,[$key,#-8]
538         str     $s3,[$key,#-4]
539 #endif
540
541         teq     lr,#128
542         bne     .Lnot128
543         mov     $rounds,#10
544         str     $rounds,[$key,#240-16]
545         add     $t3,$tbl,#256                   @ rcon
546         mov     lr,#255
547
548 .L128_loop:
549         and     $t2,lr,$s3,lsr#24
550         and     $i1,lr,$s3,lsr#16
551         ldrb    $t2,[$tbl,$t2]
552         and     $i2,lr,$s3,lsr#8
553         ldrb    $i1,[$tbl,$i1]
554         and     $i3,lr,$s3
555         ldrb    $i2,[$tbl,$i2]
556         orr     $t2,$t2,$i1,lsl#24
557         ldrb    $i3,[$tbl,$i3]
558         orr     $t2,$t2,$i2,lsl#16
559         ldr     $t1,[$t3],#4                    @ rcon[i++]
560         orr     $t2,$t2,$i3,lsl#8
561         eor     $t2,$t2,$t1
562         eor     $s0,$s0,$t2                     @ rk[4]=rk[0]^...
563         eor     $s1,$s1,$s0                     @ rk[5]=rk[1]^rk[4]
564         str     $s0,[$key],#16
565         eor     $s2,$s2,$s1                     @ rk[6]=rk[2]^rk[5]
566         str     $s1,[$key,#-12]
567         eor     $s3,$s3,$s2                     @ rk[7]=rk[3]^rk[6]
568         str     $s2,[$key,#-8]
569         subs    $rounds,$rounds,#1
570         str     $s3,[$key,#-4]
571         bne     .L128_loop
572         sub     r2,$key,#176
573         b       .Ldone
574
575 .Lnot128:
576 #if __ARM_ARCH__<7
577         ldrb    $i2,[$rounds,#19]
578         ldrb    $t1,[$rounds,#18]
579         ldrb    $t2,[$rounds,#17]
580         ldrb    $t3,[$rounds,#16]
581         orr     $i2,$i2,$t1,lsl#8
582         ldrb    $i3,[$rounds,#23]
583         orr     $i2,$i2,$t2,lsl#16
584         ldrb    $t1,[$rounds,#22]
585         orr     $i2,$i2,$t3,lsl#24
586         ldrb    $t2,[$rounds,#21]
587         ldrb    $t3,[$rounds,#20]
588         orr     $i3,$i3,$t1,lsl#8
589         orr     $i3,$i3,$t2,lsl#16
590         str     $i2,[$key],#8
591         orr     $i3,$i3,$t3,lsl#24
592         str     $i3,[$key,#-4]
593 #else
594         ldr     $i2,[$rounds,#16]
595         ldr     $i3,[$rounds,#20]
596 #ifdef __ARMEL__
597         rev     $i2,$i2
598         rev     $i3,$i3
599 #endif
600         str     $i2,[$key],#8
601         str     $i3,[$key,#-4]
602 #endif
603
604         teq     lr,#192
605         bne     .Lnot192
606         mov     $rounds,#12
607         str     $rounds,[$key,#240-24]
608         add     $t3,$tbl,#256                   @ rcon
609         mov     lr,#255
610         mov     $rounds,#8
611
612 .L192_loop:
613         and     $t2,lr,$i3,lsr#24
614         and     $i1,lr,$i3,lsr#16
615         ldrb    $t2,[$tbl,$t2]
616         and     $i2,lr,$i3,lsr#8
617         ldrb    $i1,[$tbl,$i1]
618         and     $i3,lr,$i3
619         ldrb    $i2,[$tbl,$i2]
620         orr     $t2,$t2,$i1,lsl#24
621         ldrb    $i3,[$tbl,$i3]
622         orr     $t2,$t2,$i2,lsl#16
623         ldr     $t1,[$t3],#4                    @ rcon[i++]
624         orr     $t2,$t2,$i3,lsl#8
625         eor     $i3,$t2,$t1
626         eor     $s0,$s0,$i3                     @ rk[6]=rk[0]^...
627         eor     $s1,$s1,$s0                     @ rk[7]=rk[1]^rk[6]
628         str     $s0,[$key],#24
629         eor     $s2,$s2,$s1                     @ rk[8]=rk[2]^rk[7]
630         str     $s1,[$key,#-20]
631         eor     $s3,$s3,$s2                     @ rk[9]=rk[3]^rk[8]
632         str     $s2,[$key,#-16]
633         subs    $rounds,$rounds,#1
634         str     $s3,[$key,#-12]
635 #ifdef  __thumb2__
636         itt     eq                              @ Thumb2 thing, sanity check in ARM
637 #endif
638         subeq   r2,$key,#216
639         beq     .Ldone
640
641         ldr     $i1,[$key,#-32]
642         ldr     $i2,[$key,#-28]
643         eor     $i1,$i1,$s3                     @ rk[10]=rk[4]^rk[9]
644         eor     $i3,$i2,$i1                     @ rk[11]=rk[5]^rk[10]
645         str     $i1,[$key,#-8]
646         str     $i3,[$key,#-4]
647         b       .L192_loop
648
649 .Lnot192:
650 #if __ARM_ARCH__<7
651         ldrb    $i2,[$rounds,#27]
652         ldrb    $t1,[$rounds,#26]
653         ldrb    $t2,[$rounds,#25]
654         ldrb    $t3,[$rounds,#24]
655         orr     $i2,$i2,$t1,lsl#8
656         ldrb    $i3,[$rounds,#31]
657         orr     $i2,$i2,$t2,lsl#16
658         ldrb    $t1,[$rounds,#30]
659         orr     $i2,$i2,$t3,lsl#24
660         ldrb    $t2,[$rounds,#29]
661         ldrb    $t3,[$rounds,#28]
662         orr     $i3,$i3,$t1,lsl#8
663         orr     $i3,$i3,$t2,lsl#16
664         str     $i2,[$key],#8
665         orr     $i3,$i3,$t3,lsl#24
666         str     $i3,[$key,#-4]
667 #else
668         ldr     $i2,[$rounds,#24]
669         ldr     $i3,[$rounds,#28]
670 #ifdef __ARMEL__
671         rev     $i2,$i2
672         rev     $i3,$i3
673 #endif
674         str     $i2,[$key],#8
675         str     $i3,[$key,#-4]
676 #endif
677
678         mov     $rounds,#14
679         str     $rounds,[$key,#240-32]
680         add     $t3,$tbl,#256                   @ rcon
681         mov     lr,#255
682         mov     $rounds,#7
683
684 .L256_loop:
685         and     $t2,lr,$i3,lsr#24
686         and     $i1,lr,$i3,lsr#16
687         ldrb    $t2,[$tbl,$t2]
688         and     $i2,lr,$i3,lsr#8
689         ldrb    $i1,[$tbl,$i1]
690         and     $i3,lr,$i3
691         ldrb    $i2,[$tbl,$i2]
692         orr     $t2,$t2,$i1,lsl#24
693         ldrb    $i3,[$tbl,$i3]
694         orr     $t2,$t2,$i2,lsl#16
695         ldr     $t1,[$t3],#4                    @ rcon[i++]
696         orr     $t2,$t2,$i3,lsl#8
697         eor     $i3,$t2,$t1
698         eor     $s0,$s0,$i3                     @ rk[8]=rk[0]^...
699         eor     $s1,$s1,$s0                     @ rk[9]=rk[1]^rk[8]
700         str     $s0,[$key],#32
701         eor     $s2,$s2,$s1                     @ rk[10]=rk[2]^rk[9]
702         str     $s1,[$key,#-28]
703         eor     $s3,$s3,$s2                     @ rk[11]=rk[3]^rk[10]
704         str     $s2,[$key,#-24]
705         subs    $rounds,$rounds,#1
706         str     $s3,[$key,#-20]
707 #ifdef  __thumb2__
708         itt     eq                              @ Thumb2 thing, sanity check in ARM
709 #endif
710         subeq   r2,$key,#256
711         beq     .Ldone
712
713         and     $t2,lr,$s3
714         and     $i1,lr,$s3,lsr#8
715         ldrb    $t2,[$tbl,$t2]
716         and     $i2,lr,$s3,lsr#16
717         ldrb    $i1,[$tbl,$i1]
718         and     $i3,lr,$s3,lsr#24
719         ldrb    $i2,[$tbl,$i2]
720         orr     $t2,$t2,$i1,lsl#8
721         ldrb    $i3,[$tbl,$i3]
722         orr     $t2,$t2,$i2,lsl#16
723         ldr     $t1,[$key,#-48]
724         orr     $t2,$t2,$i3,lsl#24
725
726         ldr     $i1,[$key,#-44]
727         ldr     $i2,[$key,#-40]
728         eor     $t1,$t1,$t2                     @ rk[12]=rk[4]^...
729         ldr     $i3,[$key,#-36]
730         eor     $i1,$i1,$t1                     @ rk[13]=rk[5]^rk[12]
731         str     $t1,[$key,#-16]
732         eor     $i2,$i2,$i1                     @ rk[14]=rk[6]^rk[13]
733         str     $i1,[$key,#-12]
734         eor     $i3,$i3,$i2                     @ rk[15]=rk[7]^rk[14]
735         str     $i2,[$key,#-8]
736         str     $i3,[$key,#-4]
737         b       .L256_loop
738
739 .align  2
740 .Ldone: mov     r0,#0
741         ldmia   sp!,{r4-r12,lr}
742 .Labrt:
743 #if __ARM_ARCH__>=5
744         ret                             @ bx lr
745 #else
746         tst     lr,#1
747         moveq   pc,lr                   @ be binary compatible with V4, yet
748         bx      lr                      @ interoperable with Thumb ISA:-)
749 #endif
750 .size   AES_set_encrypt_key,.-AES_set_encrypt_key
751
752 .global AES_set_decrypt_key
753 .type   AES_set_decrypt_key,%function
754 .align  5
755 AES_set_decrypt_key:
756         str     lr,[sp,#-4]!            @ push lr
757         bl      _armv4_AES_set_encrypt_key
758         teq     r0,#0
759         ldr     lr,[sp],#4              @ pop lr
760         bne     .Labrt
761
762         mov     r0,r2                   @ AES_set_encrypt_key preserves r2,
763         mov     r1,r2                   @ which is AES_KEY *key
764         b       _armv4_AES_set_enc2dec_key
765 .size   AES_set_decrypt_key,.-AES_set_decrypt_key
766
767 @ void AES_set_enc2dec_key(const AES_KEY *inp,AES_KEY *out)
768 .global AES_set_enc2dec_key
769 .type   AES_set_enc2dec_key,%function
770 .align  5
771 AES_set_enc2dec_key:
772 _armv4_AES_set_enc2dec_key:
773         stmdb   sp!,{r4-r12,lr}
774
775         ldr     $rounds,[r0,#240]
776         mov     $i1,r0                  @ input
777         add     $i2,r0,$rounds,lsl#4
778         mov     $key,r1                 @ output
779         add     $tbl,r1,$rounds,lsl#4
780         str     $rounds,[r1,#240]
781
782 .Linv:  ldr     $s0,[$i1],#16
783         ldr     $s1,[$i1,#-12]
784         ldr     $s2,[$i1,#-8]
785         ldr     $s3,[$i1,#-4]
786         ldr     $t1,[$i2],#-16
787         ldr     $t2,[$i2,#16+4]
788         ldr     $t3,[$i2,#16+8]
789         ldr     $i3,[$i2,#16+12]
790         str     $s0,[$tbl],#-16
791         str     $s1,[$tbl,#16+4]
792         str     $s2,[$tbl,#16+8]
793         str     $s3,[$tbl,#16+12]
794         str     $t1,[$key],#16
795         str     $t2,[$key,#-12]
796         str     $t3,[$key,#-8]
797         str     $i3,[$key,#-4]
798         teq     $i1,$i2
799         bne     .Linv
800
801         ldr     $s0,[$i1]
802         ldr     $s1,[$i1,#4]
803         ldr     $s2,[$i1,#8]
804         ldr     $s3,[$i1,#12]
805         str     $s0,[$key]
806         str     $s1,[$key,#4]
807         str     $s2,[$key,#8]
808         str     $s3,[$key,#12]
809         sub     $key,$key,$rounds,lsl#3
810 ___
811 $mask80=$i1;
812 $mask1b=$i2;
813 $mask7f=$i3;
814 $code.=<<___;
815         ldr     $s0,[$key,#16]!         @ prefetch tp1
816         mov     $mask80,#0x80
817         mov     $mask1b,#0x1b
818         orr     $mask80,$mask80,#0x8000
819         orr     $mask1b,$mask1b,#0x1b00
820         orr     $mask80,$mask80,$mask80,lsl#16
821         orr     $mask1b,$mask1b,$mask1b,lsl#16
822         sub     $rounds,$rounds,#1
823         mvn     $mask7f,$mask80
824         mov     $rounds,$rounds,lsl#2   @ (rounds-1)*4
825
826 .Lmix:  and     $t1,$s0,$mask80
827         and     $s1,$s0,$mask7f
828         sub     $t1,$t1,$t1,lsr#7
829         and     $t1,$t1,$mask1b
830         eor     $s1,$t1,$s1,lsl#1       @ tp2
831
832         and     $t1,$s1,$mask80
833         and     $s2,$s1,$mask7f
834         sub     $t1,$t1,$t1,lsr#7
835         and     $t1,$t1,$mask1b
836         eor     $s2,$t1,$s2,lsl#1       @ tp4
837
838         and     $t1,$s2,$mask80
839         and     $s3,$s2,$mask7f
840         sub     $t1,$t1,$t1,lsr#7
841         and     $t1,$t1,$mask1b
842         eor     $s3,$t1,$s3,lsl#1       @ tp8
843
844         eor     $t1,$s1,$s2
845         eor     $t2,$s0,$s3             @ tp9
846         eor     $t1,$t1,$s3             @ tpe
847         eor     $t1,$t1,$s1,ror#24
848         eor     $t1,$t1,$t2,ror#24      @ ^= ROTATE(tpb=tp9^tp2,8)
849         eor     $t1,$t1,$s2,ror#16
850         eor     $t1,$t1,$t2,ror#16      @ ^= ROTATE(tpd=tp9^tp4,16)
851         eor     $t1,$t1,$t2,ror#8       @ ^= ROTATE(tp9,24)
852
853         ldr     $s0,[$key,#4]           @ prefetch tp1
854         str     $t1,[$key],#4
855         subs    $rounds,$rounds,#1
856         bne     .Lmix
857
858         mov     r0,#0
859 #if __ARM_ARCH__>=5
860         ldmia   sp!,{r4-r12,pc}
861 #else
862         ldmia   sp!,{r4-r12,lr}
863         tst     lr,#1
864         moveq   pc,lr                   @ be binary compatible with V4, yet
865         bx      lr                      @ interoperable with Thumb ISA:-)
866 #endif
867 .size   AES_set_enc2dec_key,.-AES_set_enc2dec_key
868
869 .type   AES_Td,%object
870 .align  5
871 AES_Td:
872 .word   0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96
873 .word   0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393
874 .word   0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25
875 .word   0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f
876 .word   0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1
877 .word   0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6
878 .word   0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da
879 .word   0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844
880 .word   0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd
881 .word   0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4
882 .word   0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45
883 .word   0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94
884 .word   0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7
885 .word   0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a
886 .word   0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5
887 .word   0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c
888 .word   0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1
889 .word   0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a
890 .word   0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75
891 .word   0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051
892 .word   0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46
893 .word   0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff
894 .word   0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77
895 .word   0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb
896 .word   0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000
897 .word   0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e
898 .word   0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927
899 .word   0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a
900 .word   0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e
901 .word   0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16
902 .word   0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d
903 .word   0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8
904 .word   0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd
905 .word   0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34
906 .word   0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163
907 .word   0xd731dcca, 0x42638510, 0x13972240, 0x84c61120
908 .word   0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d
909 .word   0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0
910 .word   0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422
911 .word   0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef
912 .word   0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36
913 .word   0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4
914 .word   0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662
915 .word   0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5
916 .word   0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3
917 .word   0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b
918 .word   0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8
919 .word   0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6
920 .word   0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6
921 .word   0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0
922 .word   0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815
923 .word   0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f
924 .word   0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df
925 .word   0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f
926 .word   0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e
927 .word   0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713
928 .word   0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89
929 .word   0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c
930 .word   0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf
931 .word   0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86
932 .word   0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f
933 .word   0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541
934 .word   0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190
935 .word   0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742
936 @ Td4[256]
937 .byte   0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38
938 .byte   0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb
939 .byte   0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87
940 .byte   0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb
941 .byte   0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d
942 .byte   0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e
943 .byte   0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2
944 .byte   0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25
945 .byte   0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16
946 .byte   0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92
947 .byte   0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda
948 .byte   0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84
949 .byte   0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a
950 .byte   0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06
951 .byte   0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02
952 .byte   0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b
953 .byte   0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea
954 .byte   0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73
955 .byte   0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85
956 .byte   0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e
957 .byte   0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89
958 .byte   0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b
959 .byte   0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20
960 .byte   0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4
961 .byte   0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31
962 .byte   0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f
963 .byte   0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d
964 .byte   0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef
965 .byte   0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0
966 .byte   0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61
967 .byte   0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26
968 .byte   0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
969 .size   AES_Td,.-AES_Td
970
971 @ void AES_decrypt(const unsigned char *in, unsigned char *out,
972 @                const AES_KEY *key) {
973 .global AES_decrypt
974 .type   AES_decrypt,%function
975 .align  5
976 AES_decrypt:
977 #ifndef __thumb2__
978         sub     r3,pc,#8                @ AES_decrypt
979 #else
980         adr     r3,.
981 #endif
982         stmdb   sp!,{r1,r4-r12,lr}
983 #if defined(__thumb2__) || defined(__APPLE__)
984         adr     $tbl,AES_Td
985 #else
986         sub     $tbl,r3,#AES_decrypt-AES_Td     @ Td
987 #endif
988         mov     $rounds,r0              @ inp
989         mov     $key,r2
990 #if __ARM_ARCH__<7
991         ldrb    $s0,[$rounds,#3]        @ load input data in endian-neutral
992         ldrb    $t1,[$rounds,#2]        @ manner...
993         ldrb    $t2,[$rounds,#1]
994         ldrb    $t3,[$rounds,#0]
995         orr     $s0,$s0,$t1,lsl#8
996         ldrb    $s1,[$rounds,#7]
997         orr     $s0,$s0,$t2,lsl#16
998         ldrb    $t1,[$rounds,#6]
999         orr     $s0,$s0,$t3,lsl#24
1000         ldrb    $t2,[$rounds,#5]
1001         ldrb    $t3,[$rounds,#4]
1002         orr     $s1,$s1,$t1,lsl#8
1003         ldrb    $s2,[$rounds,#11]
1004         orr     $s1,$s1,$t2,lsl#16
1005         ldrb    $t1,[$rounds,#10]
1006         orr     $s1,$s1,$t3,lsl#24
1007         ldrb    $t2,[$rounds,#9]
1008         ldrb    $t3,[$rounds,#8]
1009         orr     $s2,$s2,$t1,lsl#8
1010         ldrb    $s3,[$rounds,#15]
1011         orr     $s2,$s2,$t2,lsl#16
1012         ldrb    $t1,[$rounds,#14]
1013         orr     $s2,$s2,$t3,lsl#24
1014         ldrb    $t2,[$rounds,#13]
1015         ldrb    $t3,[$rounds,#12]
1016         orr     $s3,$s3,$t1,lsl#8
1017         orr     $s3,$s3,$t2,lsl#16
1018         orr     $s3,$s3,$t3,lsl#24
1019 #else
1020         ldr     $s0,[$rounds,#0]
1021         ldr     $s1,[$rounds,#4]
1022         ldr     $s2,[$rounds,#8]
1023         ldr     $s3,[$rounds,#12]
1024 #ifdef __ARMEL__
1025         rev     $s0,$s0
1026         rev     $s1,$s1
1027         rev     $s2,$s2
1028         rev     $s3,$s3
1029 #endif
1030 #endif
1031         bl      _armv4_AES_decrypt
1032
1033         ldr     $rounds,[sp],#4         @ pop out
1034 #if __ARM_ARCH__>=7
1035 #ifdef __ARMEL__
1036         rev     $s0,$s0
1037         rev     $s1,$s1
1038         rev     $s2,$s2
1039         rev     $s3,$s3
1040 #endif
1041         str     $s0,[$rounds,#0]
1042         str     $s1,[$rounds,#4]
1043         str     $s2,[$rounds,#8]
1044         str     $s3,[$rounds,#12]
1045 #else
1046         mov     $t1,$s0,lsr#24          @ write output in endian-neutral
1047         mov     $t2,$s0,lsr#16          @ manner...
1048         mov     $t3,$s0,lsr#8
1049         strb    $t1,[$rounds,#0]
1050         strb    $t2,[$rounds,#1]
1051         mov     $t1,$s1,lsr#24
1052         strb    $t3,[$rounds,#2]
1053         mov     $t2,$s1,lsr#16
1054         strb    $s0,[$rounds,#3]
1055         mov     $t3,$s1,lsr#8
1056         strb    $t1,[$rounds,#4]
1057         strb    $t2,[$rounds,#5]
1058         mov     $t1,$s2,lsr#24
1059         strb    $t3,[$rounds,#6]
1060         mov     $t2,$s2,lsr#16
1061         strb    $s1,[$rounds,#7]
1062         mov     $t3,$s2,lsr#8
1063         strb    $t1,[$rounds,#8]
1064         strb    $t2,[$rounds,#9]
1065         mov     $t1,$s3,lsr#24
1066         strb    $t3,[$rounds,#10]
1067         mov     $t2,$s3,lsr#16
1068         strb    $s2,[$rounds,#11]
1069         mov     $t3,$s3,lsr#8
1070         strb    $t1,[$rounds,#12]
1071         strb    $t2,[$rounds,#13]
1072         strb    $t3,[$rounds,#14]
1073         strb    $s3,[$rounds,#15]
1074 #endif
1075 #if __ARM_ARCH__>=5
1076         ldmia   sp!,{r4-r12,pc}
1077 #else
1078         ldmia   sp!,{r4-r12,lr}
1079         tst     lr,#1
1080         moveq   pc,lr                   @ be binary compatible with V4, yet
1081         bx      lr                      @ interoperable with Thumb ISA:-)
1082 #endif
1083 .size   AES_decrypt,.-AES_decrypt
1084
1085 .type   _armv4_AES_decrypt,%function
1086 .align  2
1087 _armv4_AES_decrypt:
1088         str     lr,[sp,#-4]!            @ push lr
1089         ldmia   $key!,{$t1-$i1}
1090         eor     $s0,$s0,$t1
1091         ldr     $rounds,[$key,#240-16]
1092         eor     $s1,$s1,$t2
1093         eor     $s2,$s2,$t3
1094         eor     $s3,$s3,$i1
1095         sub     $rounds,$rounds,#1
1096         mov     lr,#255
1097
1098         and     $i1,lr,$s0,lsr#16
1099         and     $i2,lr,$s0,lsr#8
1100         and     $i3,lr,$s0
1101         mov     $s0,$s0,lsr#24
1102 .Ldec_loop:
1103         ldr     $t1,[$tbl,$i1,lsl#2]    @ Td1[s0>>16]
1104         and     $i1,lr,$s1              @ i0
1105         ldr     $t2,[$tbl,$i2,lsl#2]    @ Td2[s0>>8]
1106         and     $i2,lr,$s1,lsr#16
1107         ldr     $t3,[$tbl,$i3,lsl#2]    @ Td3[s0>>0]
1108         and     $i3,lr,$s1,lsr#8
1109         ldr     $s0,[$tbl,$s0,lsl#2]    @ Td0[s0>>24]
1110         mov     $s1,$s1,lsr#24
1111
1112         ldr     $i1,[$tbl,$i1,lsl#2]    @ Td3[s1>>0]
1113         ldr     $i2,[$tbl,$i2,lsl#2]    @ Td1[s1>>16]
1114         ldr     $i3,[$tbl,$i3,lsl#2]    @ Td2[s1>>8]
1115         eor     $s0,$s0,$i1,ror#24
1116         ldr     $s1,[$tbl,$s1,lsl#2]    @ Td0[s1>>24]
1117         and     $i1,lr,$s2,lsr#8        @ i0
1118         eor     $t2,$i2,$t2,ror#8
1119         and     $i2,lr,$s2              @ i1
1120         eor     $t3,$i3,$t3,ror#8
1121         and     $i3,lr,$s2,lsr#16
1122         ldr     $i1,[$tbl,$i1,lsl#2]    @ Td2[s2>>8]
1123         eor     $s1,$s1,$t1,ror#8
1124         ldr     $i2,[$tbl,$i2,lsl#2]    @ Td3[s2>>0]
1125         mov     $s2,$s2,lsr#24
1126
1127         ldr     $i3,[$tbl,$i3,lsl#2]    @ Td1[s2>>16]
1128         eor     $s0,$s0,$i1,ror#16
1129         ldr     $s2,[$tbl,$s2,lsl#2]    @ Td0[s2>>24]
1130         and     $i1,lr,$s3,lsr#16       @ i0
1131         eor     $s1,$s1,$i2,ror#24
1132         and     $i2,lr,$s3,lsr#8        @ i1
1133         eor     $t3,$i3,$t3,ror#8
1134         and     $i3,lr,$s3              @ i2
1135         ldr     $i1,[$tbl,$i1,lsl#2]    @ Td1[s3>>16]
1136         eor     $s2,$s2,$t2,ror#8
1137         ldr     $i2,[$tbl,$i2,lsl#2]    @ Td2[s3>>8]
1138         mov     $s3,$s3,lsr#24
1139
1140         ldr     $i3,[$tbl,$i3,lsl#2]    @ Td3[s3>>0]
1141         eor     $s0,$s0,$i1,ror#8
1142         ldr     $i1,[$key],#16
1143         eor     $s1,$s1,$i2,ror#16
1144         ldr     $s3,[$tbl,$s3,lsl#2]    @ Td0[s3>>24]
1145         eor     $s2,$s2,$i3,ror#24
1146
1147         ldr     $t1,[$key,#-12]
1148         eor     $s0,$s0,$i1
1149         ldr     $t2,[$key,#-8]
1150         eor     $s3,$s3,$t3,ror#8
1151         ldr     $t3,[$key,#-4]
1152         and     $i1,lr,$s0,lsr#16
1153         eor     $s1,$s1,$t1
1154         and     $i2,lr,$s0,lsr#8
1155         eor     $s2,$s2,$t2
1156         and     $i3,lr,$s0
1157         eor     $s3,$s3,$t3
1158         mov     $s0,$s0,lsr#24
1159
1160         subs    $rounds,$rounds,#1
1161         bne     .Ldec_loop
1162
1163         add     $tbl,$tbl,#1024
1164
1165         ldr     $t2,[$tbl,#0]           @ prefetch Td4
1166         ldr     $t3,[$tbl,#32]
1167         ldr     $t1,[$tbl,#64]
1168         ldr     $t2,[$tbl,#96]
1169         ldr     $t3,[$tbl,#128]
1170         ldr     $t1,[$tbl,#160]
1171         ldr     $t2,[$tbl,#192]
1172         ldr     $t3,[$tbl,#224]
1173
1174         ldrb    $s0,[$tbl,$s0]          @ Td4[s0>>24]
1175         ldrb    $t1,[$tbl,$i1]          @ Td4[s0>>16]
1176         and     $i1,lr,$s1              @ i0
1177         ldrb    $t2,[$tbl,$i2]          @ Td4[s0>>8]
1178         and     $i2,lr,$s1,lsr#16
1179         ldrb    $t3,[$tbl,$i3]          @ Td4[s0>>0]
1180         and     $i3,lr,$s1,lsr#8
1181
1182         add     $s1,$tbl,$s1,lsr#24
1183         ldrb    $i1,[$tbl,$i1]          @ Td4[s1>>0]
1184         ldrb    $s1,[$s1]               @ Td4[s1>>24]
1185         ldrb    $i2,[$tbl,$i2]          @ Td4[s1>>16]
1186         eor     $s0,$i1,$s0,lsl#24
1187         ldrb    $i3,[$tbl,$i3]          @ Td4[s1>>8]
1188         eor     $s1,$t1,$s1,lsl#8
1189         and     $i1,lr,$s2,lsr#8        @ i0
1190         eor     $t2,$t2,$i2,lsl#8
1191         and     $i2,lr,$s2              @ i1
1192         ldrb    $i1,[$tbl,$i1]          @ Td4[s2>>8]
1193         eor     $t3,$t3,$i3,lsl#8
1194         ldrb    $i2,[$tbl,$i2]          @ Td4[s2>>0]
1195         and     $i3,lr,$s2,lsr#16
1196
1197         add     $s2,$tbl,$s2,lsr#24
1198         ldrb    $s2,[$s2]               @ Td4[s2>>24]
1199         eor     $s0,$s0,$i1,lsl#8
1200         ldrb    $i3,[$tbl,$i3]          @ Td4[s2>>16]
1201         eor     $s1,$i2,$s1,lsl#16
1202         and     $i1,lr,$s3,lsr#16       @ i0
1203         eor     $s2,$t2,$s2,lsl#16
1204         and     $i2,lr,$s3,lsr#8        @ i1
1205         ldrb    $i1,[$tbl,$i1]          @ Td4[s3>>16]
1206         eor     $t3,$t3,$i3,lsl#16
1207         ldrb    $i2,[$tbl,$i2]          @ Td4[s3>>8]
1208         and     $i3,lr,$s3              @ i2
1209
1210         add     $s3,$tbl,$s3,lsr#24
1211         ldrb    $i3,[$tbl,$i3]          @ Td4[s3>>0]
1212         ldrb    $s3,[$s3]               @ Td4[s3>>24]
1213         eor     $s0,$s0,$i1,lsl#16
1214         ldr     $i1,[$key,#0]
1215         eor     $s1,$s1,$i2,lsl#8
1216         ldr     $t1,[$key,#4]
1217         eor     $s2,$i3,$s2,lsl#8
1218         ldr     $t2,[$key,#8]
1219         eor     $s3,$t3,$s3,lsl#24
1220         ldr     $t3,[$key,#12]
1221
1222         eor     $s0,$s0,$i1
1223         eor     $s1,$s1,$t1
1224         eor     $s2,$s2,$t2
1225         eor     $s3,$s3,$t3
1226
1227         sub     $tbl,$tbl,#1024
1228         ldr     pc,[sp],#4              @ pop and return
1229 .size   _armv4_AES_decrypt,.-_armv4_AES_decrypt
1230 .asciz  "AES for ARMv4, CRYPTOGAMS by <appro\@openssl.org>"
1231 .align  2
1232 ___
1233
1234 $code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm;    # make it possible to compile with -march=armv4
1235 $code =~ s/\bret\b/bx\tlr/gm;
1236
1237 open SELF,$0;
1238 while(<SELF>) {
1239         next if (/^#!/);
1240         last if (!s/^#/@/ and !/^$/);
1241         print;
1242 }
1243 close SELF;
1244
1245 print $code;
1246 close STDOUT;   # enforce flush