ecc: Fix ec_mulm_25519.
[libgcrypt.git] / cipher / rijndael-arm.S
1 /* rijndael-arm.S  -  ARM assembly implementation of AES cipher
2  *
3  * Copyright (C) 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
4  *
5  * This file is part of Libgcrypt.
6  *
7  * Libgcrypt is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * Libgcrypt is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22
23 #if defined(__ARMEL__)
24 #ifdef HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS
25
26 .text
27
28 .syntax unified
29 .arm
30
31 /* register macros */
32 #define CTX     %r0
33 #define RTAB    %lr
34 #define RMASK   %ip
35
36 #define RA      %r4
37 #define RB      %r5
38 #define RC      %r6
39 #define RD      %r7
40
41 #define RNA     %r8
42 #define RNB     %r9
43 #define RNC     %r10
44 #define RND     %r11
45
46 #define RT0     %r1
47 #define RT1     %r2
48 #define RT2     %r3
49
50 /* helper macros */
51 #define ldr_unaligned_le(rout, rsrc, offs, rtmp) \
52         ldrb rout, [rsrc, #((offs) + 0)]; \
53         ldrb rtmp, [rsrc, #((offs) + 1)]; \
54         orr rout, rout, rtmp, lsl #8; \
55         ldrb rtmp, [rsrc, #((offs) + 2)]; \
56         orr rout, rout, rtmp, lsl #16; \
57         ldrb rtmp, [rsrc, #((offs) + 3)]; \
58         orr rout, rout, rtmp, lsl #24;
59
60 #define str_unaligned_le(rin, rdst, offs, rtmp0, rtmp1) \
61         mov rtmp0, rin, lsr #8; \
62         strb rin, [rdst, #((offs) + 0)]; \
63         mov rtmp1, rin, lsr #16; \
64         strb rtmp0, [rdst, #((offs) + 1)]; \
65         mov rtmp0, rin, lsr #24; \
66         strb rtmp1, [rdst, #((offs) + 2)]; \
67         strb rtmp0, [rdst, #((offs) + 3)];
68
69 /***********************************************************************
70  * ARM assembly implementation of the AES cipher
71  ***********************************************************************/
72 #define preload_first_key(round, ra) \
73         ldr ra, [CTX, #(((round) * 16) + 0 * 4)];
74
75 #define dummy(round, ra) /* nothing */
76
77 #define addroundkey(ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
78         ldm CTX, {rna, rnb, rnc, rnd}; \
79         eor ra, rna; \
80         eor rb, rnb; \
81         eor rc, rnc; \
82         preload_key(1, rna); \
83         eor rd, rnd;
84
85 #define do_encround(next_r, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
86         ldr rnb, [CTX, #(((next_r) * 16) + 1 * 4)]; \
87         \
88         and RT0, RMASK, ra, lsl#2; \
89         ldr rnc, [CTX, #(((next_r) * 16) + 2 * 4)]; \
90         and RT1, RMASK, ra, lsr#(8 - 2); \
91         ldr rnd, [CTX, #(((next_r) * 16) + 3 * 4)]; \
92         and RT2, RMASK, ra, lsr#(16 - 2); \
93         ldr RT0, [RTAB, RT0]; \
94         and ra,  RMASK, ra, lsr#(24 - 2); \
95         \
96         ldr RT1, [RTAB, RT1]; \
97         eor rna, rna, RT0; \
98         ldr RT2, [RTAB, RT2]; \
99         and RT0, RMASK, rd, lsl#2; \
100         ldr ra,  [RTAB, ra]; \
101         \
102         eor rnd, rnd, RT1, ror #24; \
103         and RT1, RMASK, rd, lsr#(8 - 2); \
104         eor rnc, rnc, RT2, ror #16; \
105         and RT2, RMASK, rd, lsr#(16 - 2); \
106         eor rnb, rnb, ra, ror #8; \
107         ldr RT0, [RTAB, RT0]; \
108         and rd,  RMASK, rd, lsr#(24 - 2); \
109         \
110         ldr RT1, [RTAB, RT1]; \
111         eor rnd, rnd, RT0; \
112         ldr RT2, [RTAB, RT2]; \
113         and RT0, RMASK, rc, lsl#2; \
114         ldr rd,  [RTAB, rd]; \
115         \
116         eor rnc, rnc, RT1, ror #24; \
117         and RT1, RMASK, rc, lsr#(8 - 2); \
118         eor rnb, rnb, RT2, ror #16; \
119         and RT2, RMASK, rc, lsr#(16 - 2); \
120         eor rna, rna, rd, ror #8; \
121         ldr RT0, [RTAB, RT0]; \
122         and rc,  RMASK, rc, lsr#(24 - 2); \
123         \
124         ldr RT1, [RTAB, RT1]; \
125         eor rnc, rnc, RT0; \
126         ldr RT2, [RTAB, RT2]; \
127         and RT0, RMASK, rb, lsl#2; \
128         ldr rc,  [RTAB, rc]; \
129         \
130         eor rnb, rnb, RT1, ror #24; \
131         and RT1, RMASK, rb, lsr#(8 - 2); \
132         eor rna, rna, RT2, ror #16; \
133         and RT2, RMASK, rb, lsr#(16 - 2); \
134         eor rnd, rnd, rc, ror #8; \
135         ldr RT0, [RTAB, RT0]; \
136         and rb,  RMASK, rb, lsr#(24 - 2); \
137         \
138         ldr RT1, [RTAB, RT1]; \
139         eor rnb, rnb, RT0; \
140         ldr RT2, [RTAB, RT2]; \
141         eor rna, rna, RT1, ror #24; \
142         ldr rb,  [RTAB, rb]; \
143         \
144         eor rnd, rnd, RT2, ror #16; \
145         preload_key((next_r) + 1, ra); \
146         eor rnc, rnc, rb, ror #8;
147
148 #define do_lastencround(ra, rb, rc, rd, rna, rnb, rnc, rnd) \
149         and RT0, RMASK, ra, lsl#2; \
150         and RT1, RMASK, ra, lsr#(8 - 2); \
151         and RT2, RMASK, ra, lsr#(16 - 2); \
152         ldrb rna, [RTAB, RT0]; \
153         and ra,  RMASK, ra, lsr#(24 - 2); \
154         ldrb rnd, [RTAB, RT1]; \
155         and RT0, RMASK, rd, lsl#2; \
156         ldrb rnc, [RTAB, RT2]; \
157         mov rnd, rnd, ror #24; \
158         ldrb rnb, [RTAB, ra]; \
159         and RT1, RMASK, rd, lsr#(8 - 2); \
160         mov rnc, rnc, ror #16; \
161         and RT2, RMASK, rd, lsr#(16 - 2); \
162         mov rnb, rnb, ror #8; \
163         ldrb RT0, [RTAB, RT0]; \
164         and rd,  RMASK, rd, lsr#(24 - 2); \
165         ldrb RT1, [RTAB, RT1]; \
166         \
167         orr rnd, rnd, RT0; \
168         ldrb RT2, [RTAB, RT2]; \
169         and RT0, RMASK, rc, lsl#2; \
170         ldrb rd,  [RTAB, rd]; \
171         orr rnc, rnc, RT1, ror #24; \
172         and RT1, RMASK, rc, lsr#(8 - 2); \
173         orr rnb, rnb, RT2, ror #16; \
174         and RT2, RMASK, rc, lsr#(16 - 2); \
175         orr rna, rna, rd, ror #8; \
176         ldrb RT0, [RTAB, RT0]; \
177         and rc,  RMASK, rc, lsr#(24 - 2); \
178         ldrb RT1, [RTAB, RT1]; \
179         \
180         orr rnc, rnc, RT0; \
181         ldrb RT2, [RTAB, RT2]; \
182         and RT0, RMASK, rb, lsl#2; \
183         ldrb rc,  [RTAB, rc]; \
184         orr rnb, rnb, RT1, ror #24; \
185         and RT1, RMASK, rb, lsr#(8 - 2); \
186         orr rna, rna, RT2, ror #16; \
187         ldrb RT0, [RTAB, RT0]; \
188         and RT2, RMASK, rb, lsr#(16 - 2); \
189         ldrb RT1, [RTAB, RT1]; \
190         orr rnd, rnd, rc, ror #8; \
191         ldrb RT2, [RTAB, RT2]; \
192         and rb,  RMASK, rb, lsr#(24 - 2); \
193         ldrb rb,  [RTAB, rb]; \
194         \
195         orr rnb, rnb, RT0; \
196         orr rna, rna, RT1, ror #24; \
197         orr rnd, rnd, RT2, ror #16; \
198         orr rnc, rnc, rb, ror #8;
199
200 #define firstencround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
201         addroundkey(ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_first_key); \
202         do_encround((round) + 1, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_first_key);
203
204 #define encround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
205         do_encround((round) + 1, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key);
206
207 #define lastencround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
208         add CTX, #(((round) + 1) * 16); \
209         add RTAB, #1; \
210         do_lastencround(ra, rb, rc, rd, rna, rnb, rnc, rnd); \
211         addroundkey(rna, rnb, rnc, rnd, ra, rb, rc, rd, dummy);
212
213 .align 3
214 .globl _gcry_aes_arm_encrypt_block
215 .type   _gcry_aes_arm_encrypt_block,%function;
216
217 _gcry_aes_arm_encrypt_block:
218         /* input:
219          *      %r0: keysched, CTX
220          *      %r1: dst
221          *      %r2: src
222          *      %r3: number of rounds.. 10, 12 or 14
223          *      %st+0: encryption table
224          */
225         push {%r4-%r11, %ip, %lr};
226
227         /* read input block */
228
229         /* test if src is unaligned */
230         tst     %r2, #3;
231         beq     1f;
232
233         /* unaligned load */
234         ldr_unaligned_le(RA, %r2, 0, RNA);
235         ldr_unaligned_le(RB, %r2, 4, RNB);
236         ldr_unaligned_le(RC, %r2, 8, RNA);
237         ldr_unaligned_le(RD, %r2, 12, RNB);
238         b       2f;
239 .ltorg
240 1:
241         /* aligned load */
242         ldm     %r2, {RA, RB, RC, RD};
243 #ifndef __ARMEL__
244         rev     RA, RA;
245         rev     RB, RB;
246         rev     RC, RC;
247         rev     RD, RD;
248 #endif
249 2:
250         ldr     RTAB, [%sp, #40];
251         sub     %sp, #16;
252
253         str     %r1, [%sp, #4];         /* dst */
254         mov     RMASK, #0xff;
255         str     %r3, [%sp, #8];         /* nrounds */
256         mov     RMASK, RMASK, lsl#2;    /* byte mask */
257
258         firstencround(0, RA, RB, RC, RD, RNA, RNB, RNC, RND);
259         encround(1, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
260         encround(2, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
261         encround(3, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
262         encround(4, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
263         encround(5, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
264         encround(6, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
265         encround(7, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
266
267         ldr     RT0, [%sp, #8];         /* nrounds */
268         cmp     RT0, #12;
269         bge     .Lenc_not_128;
270
271         encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
272         lastencround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD);
273
274 .Lenc_done:
275         ldr     RT0, [%sp, #4];         /* dst */
276         add     %sp, #16;
277
278         /* store output block */
279
280         /* test if dst is unaligned */
281         tst     RT0, #3;
282         beq     1f;
283
284         /* unaligned store */
285         str_unaligned_le(RA, RT0, 0, RNA, RNB);
286         str_unaligned_le(RB, RT0, 4, RNA, RNB);
287         str_unaligned_le(RC, RT0, 8, RNA, RNB);
288         str_unaligned_le(RD, RT0, 12, RNA, RNB);
289         b       2f;
290 .ltorg
291 1:
292         /* aligned store */
293 #ifndef __ARMEL__
294         rev     RA, RA;
295         rev     RB, RB;
296         rev     RC, RC;
297         rev     RD, RD;
298 #endif
299         /* write output block */
300         stm     RT0, {RA, RB, RC, RD};
301 2:
302
303         mov     r0, #(10 * 4);
304         pop {%r4-%r11, %ip, %pc};
305
306 .ltorg
307 .Lenc_not_128:
308         beq .Lenc_192
309
310         encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
311         encround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
312         encround(10, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
313         encround(11, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
314         encround(12, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
315         lastencround(13, RNA, RNB, RNC, RND, RA, RB, RC, RD);
316
317         b .Lenc_done;
318
319 .ltorg
320 .Lenc_192:
321         encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
322         encround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
323         encround(10, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
324         lastencround(11, RNA, RNB, RNC, RND, RA, RB, RC, RD);
325
326         b .Lenc_done;
327 .size _gcry_aes_arm_encrypt_block,.-_gcry_aes_arm_encrypt_block;
328
329 #define addroundkey_dec(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
330         ldr rna, [CTX, #(((round) * 16) + 0 * 4)]; \
331         ldr rnb, [CTX, #(((round) * 16) + 1 * 4)]; \
332         eor ra, rna; \
333         ldr rnc, [CTX, #(((round) * 16) + 2 * 4)]; \
334         eor rb, rnb; \
335         ldr rnd, [CTX, #(((round) * 16) + 3 * 4)]; \
336         eor rc, rnc; \
337         preload_first_key((round) - 1, rna); \
338         eor rd, rnd;
339
340 #define do_decround(next_r, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
341         ldr rnb, [CTX, #(((next_r) * 16) + 1 * 4)]; \
342         \
343         and RT0, RMASK, ra, lsl#2; \
344         ldr rnc, [CTX, #(((next_r) * 16) + 2 * 4)]; \
345         and RT1, RMASK, ra, lsr#(8 - 2); \
346         ldr rnd, [CTX, #(((next_r) * 16) + 3 * 4)]; \
347         and RT2, RMASK, ra, lsr#(16 - 2); \
348         ldr RT0, [RTAB, RT0]; \
349         and ra,  RMASK, ra, lsr#(24 - 2); \
350         \
351         ldr RT1, [RTAB, RT1]; \
352         eor rna, rna, RT0; \
353         ldr RT2, [RTAB, RT2]; \
354         and RT0, RMASK, rb, lsl#2; \
355         ldr ra,  [RTAB, ra]; \
356         \
357         eor rnb, rnb, RT1, ror #24; \
358         and RT1, RMASK, rb, lsr#(8 - 2); \
359         eor rnc, rnc, RT2, ror #16; \
360         and RT2, RMASK, rb, lsr#(16 - 2); \
361         eor rnd, rnd, ra, ror #8; \
362         ldr RT0, [RTAB, RT0]; \
363         and rb,  RMASK, rb, lsr#(24 - 2); \
364         \
365         ldr RT1, [RTAB, RT1]; \
366         eor rnb, rnb, RT0; \
367         ldr RT2, [RTAB, RT2]; \
368         and RT0, RMASK, rc, lsl#2; \
369         ldr rb,  [RTAB, rb]; \
370         \
371         eor rnc, rnc, RT1, ror #24; \
372         and RT1, RMASK, rc, lsr#(8 - 2); \
373         eor rnd, rnd, RT2, ror #16; \
374         and RT2, RMASK, rc, lsr#(16 - 2); \
375         eor rna, rna, rb, ror #8; \
376         ldr RT0, [RTAB, RT0]; \
377         and rc,  RMASK, rc, lsr#(24 - 2); \
378         \
379         ldr RT1, [RTAB, RT1]; \
380         eor rnc, rnc, RT0; \
381         ldr RT2, [RTAB, RT2]; \
382         and RT0, RMASK, rd, lsl#2; \
383         ldr rc,  [RTAB, rc]; \
384         \
385         eor rnd, rnd, RT1, ror #24; \
386         and RT1, RMASK, rd, lsr#(8 - 2); \
387         eor rna, rna, RT2, ror #16; \
388         and RT2, RMASK, rd, lsr#(16 - 2); \
389         eor rnb, rnb, rc, ror #8; \
390         ldr RT0, [RTAB, RT0]; \
391         and rd,  RMASK, rd, lsr#(24 - 2); \
392         \
393         ldr RT1, [RTAB, RT1]; \
394         eor rnd, rnd, RT0; \
395         ldr RT2, [RTAB, RT2]; \
396         eor rna, rna, RT1, ror #24; \
397         ldr rd,  [RTAB, rd]; \
398         \
399         eor rnb, rnb, RT2, ror #16; \
400         preload_key((next_r) - 1, ra); \
401         eor rnc, rnc, rd, ror #8;
402
403 #define do_lastdecround(ra, rb, rc, rd, rna, rnb, rnc, rnd) \
404         and RT0, RMASK, ra; \
405         and RT1, RMASK, ra, lsr#8; \
406         and RT2, RMASK, ra, lsr#16; \
407         ldrb rna, [RTAB, RT0]; \
408         mov ra,  ra, lsr#24; \
409         ldrb rnb, [RTAB, RT1]; \
410         and RT0, RMASK, rb; \
411         ldrb rnc, [RTAB, RT2]; \
412         mov rnb, rnb, ror #24; \
413         ldrb rnd, [RTAB, ra]; \
414         and RT1, RMASK, rb, lsr#8; \
415         mov rnc, rnc, ror #16; \
416         and RT2, RMASK, rb, lsr#16; \
417         mov rnd, rnd, ror #8; \
418         ldrb RT0, [RTAB, RT0]; \
419         mov rb,  rb, lsr#24; \
420         ldrb RT1, [RTAB, RT1]; \
421         \
422         orr rnb, rnb, RT0; \
423         ldrb RT2, [RTAB, RT2]; \
424         and RT0, RMASK, rc; \
425         ldrb rb,  [RTAB, rb]; \
426         orr rnc, rnc, RT1, ror #24; \
427         and RT1, RMASK, rc, lsr#8; \
428         orr rnd, rnd, RT2, ror #16; \
429         and RT2, RMASK, rc, lsr#16; \
430         orr rna, rna, rb, ror #8; \
431         ldrb RT0, [RTAB, RT0]; \
432         mov rc,  rc, lsr#24; \
433         ldrb RT1, [RTAB, RT1]; \
434         \
435         orr rnc, rnc, RT0; \
436         ldrb RT2, [RTAB, RT2]; \
437         and RT0, RMASK, rd; \
438         ldrb rc,  [RTAB, rc]; \
439         orr rnd, rnd, RT1, ror #24; \
440         and RT1, RMASK, rd, lsr#8; \
441         orr rna, rna, RT2, ror #16; \
442         ldrb RT0, [RTAB, RT0]; \
443         and RT2, RMASK, rd, lsr#16; \
444         ldrb RT1, [RTAB, RT1]; \
445         orr rnb, rnb, rc, ror #8; \
446         ldrb RT2, [RTAB, RT2]; \
447         mov rd,  rd, lsr#24; \
448         ldrb rd,  [RTAB, rd]; \
449         \
450         orr rnd, rnd, RT0; \
451         orr rna, rna, RT1, ror #24; \
452         orr rnb, rnb, RT2, ror #16; \
453         orr rnc, rnc, rd, ror #8;
454
455 #define firstdecround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
456         addroundkey_dec(((round) + 1), ra, rb, rc, rd, rna, rnb, rnc, rnd); \
457         do_decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_first_key);
458
459 #define decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
460         do_decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key);
461
462 #define set_last_round_rmask(_, __) \
463         mov RMASK, #0xff;
464
465 #define lastdecround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
466         add RTAB, #(4 * 256); \
467         do_lastdecround(ra, rb, rc, rd, rna, rnb, rnc, rnd); \
468         addroundkey(rna, rnb, rnc, rnd, ra, rb, rc, rd, dummy);
469
470 .align 3
471 .globl _gcry_aes_arm_decrypt_block
472 .type   _gcry_aes_arm_decrypt_block,%function;
473
474 _gcry_aes_arm_decrypt_block:
475         /* input:
476          *      %r0: keysched, CTX
477          *      %r1: dst
478          *      %r2: src
479          *      %r3: number of rounds.. 10, 12 or 14
480          *      %st+0: decryption table
481          */
482         push {%r4-%r11, %ip, %lr};
483
484         /* read input block */
485
486         /* test if src is unaligned */
487         tst     %r2, #3;
488         beq     1f;
489
490         /* unaligned load */
491         ldr_unaligned_le(RA, %r2, 0, RNA);
492         ldr_unaligned_le(RB, %r2, 4, RNB);
493         ldr_unaligned_le(RC, %r2, 8, RNA);
494         ldr_unaligned_le(RD, %r2, 12, RNB);
495         b       2f;
496 .ltorg
497 1:
498         /* aligned load */
499         ldm     %r2, {RA, RB, RC, RD};
500 #ifndef __ARMEL__
501         rev     RA, RA;
502         rev     RB, RB;
503         rev     RC, RC;
504         rev     RD, RD;
505 #endif
506 2:
507         ldr     RTAB, [%sp, #40];
508         sub     %sp, #16;
509
510         mov     RMASK, #0xff;
511         str     %r1, [%sp, #4];         /* dst */
512         mov     RMASK, RMASK, lsl#2;    /* byte mask */
513
514         cmp     %r3, #12;
515         bge     .Ldec_256;
516
517         firstdecround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND);
518 .Ldec_tail:
519         decround(8, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
520         decround(7, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
521         decround(6, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
522         decround(5, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
523         decround(4, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
524         decround(3, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
525         decround(2, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
526         decround(1, RA, RB, RC, RD, RNA, RNB, RNC, RND, set_last_round_rmask);
527         lastdecround(0, RNA, RNB, RNC, RND, RA, RB, RC, RD);
528
529         ldr     RT0, [%sp, #4];         /* dst */
530         add     %sp, #16;
531
532         /* store output block */
533
534         /* test if dst is unaligned */
535         tst     RT0, #3;
536         beq     1f;
537
538         /* unaligned store */
539         str_unaligned_le(RA, RT0, 0, RNA, RNB);
540         str_unaligned_le(RB, RT0, 4, RNA, RNB);
541         str_unaligned_le(RC, RT0, 8, RNA, RNB);
542         str_unaligned_le(RD, RT0, 12, RNA, RNB);
543         b       2f;
544 .ltorg
545 1:
546         /* aligned store */
547 #ifndef __ARMEL__
548         rev     RA, RA;
549         rev     RB, RB;
550         rev     RC, RC;
551         rev     RD, RD;
552 #endif
553         /* write output block */
554         stm     RT0, {RA, RB, RC, RD};
555 2:
556         mov     r0, #(10 * 4);
557         pop {%r4-%r11, %ip, %pc};
558
559 .ltorg
560 .Ldec_256:
561         beq .Ldec_192;
562
563         firstdecround(13, RA, RB, RC, RD, RNA, RNB, RNC, RND);
564         decround(12, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
565         decround(11, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
566         decround(10, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
567         decround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
568
569         b .Ldec_tail;
570
571 .ltorg
572 .Ldec_192:
573         firstdecround(11, RA, RB, RC, RD, RNA, RNB, RNC, RND);
574         decround(10, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
575         decround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
576
577         b .Ldec_tail;
578 .size _gcry_aes_arm_encrypt_block,.-_gcry_aes_arm_encrypt_block;
579
580 #endif /*HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS*/
581 #endif /*__ARMEL__ */