bufhelp: use one-byte aligned type for unaligned memory accesses
[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 #ifndef __ARM_FEATURE_UNALIGNED
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 #endif
242         /* aligned load */
243         ldm     %r2, {RA, RB, RC, RD};
244 #ifndef __ARMEL__
245         rev     RA, RA;
246         rev     RB, RB;
247         rev     RC, RC;
248         rev     RD, RD;
249 #endif
250 2:
251         ldr     RTAB, [%sp, #40];
252         sub     %sp, #16;
253
254         str     %r1, [%sp, #4];         /* dst */
255         mov     RMASK, #0xff;
256         str     %r3, [%sp, #8];         /* nrounds */
257         mov     RMASK, RMASK, lsl#2;    /* byte mask */
258
259         firstencround(0, RA, RB, RC, RD, RNA, RNB, RNC, RND);
260         encround(1, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
261         encround(2, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
262         encround(3, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
263         encround(4, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
264         encround(5, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
265         encround(6, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
266         encround(7, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
267
268         ldr     RT0, [%sp, #8];         /* nrounds */
269         cmp     RT0, #12;
270         bge     .Lenc_not_128;
271
272         encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
273         lastencround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD);
274
275 .Lenc_done:
276         ldr     RT0, [%sp, #4];         /* dst */
277         add     %sp, #16;
278
279         /* store output block */
280 #ifndef __ARM_FEATURE_UNALIGNED
281         /* test if dst is unaligned */
282         tst     RT0, #3;
283         beq     1f;
284
285         /* unaligned store */
286         str_unaligned_le(RA, RT0, 0, RNA, RNB);
287         str_unaligned_le(RB, RT0, 4, RNA, RNB);
288         str_unaligned_le(RC, RT0, 8, RNA, RNB);
289         str_unaligned_le(RD, RT0, 12, RNA, RNB);
290         b       2f;
291 .ltorg
292 1:
293 #endif
294         /* aligned store */
295 #ifndef __ARMEL__
296         rev     RA, RA;
297         rev     RB, RB;
298         rev     RC, RC;
299         rev     RD, RD;
300 #endif
301         /* write output block */
302         stm     RT0, {RA, RB, RC, RD};
303 2:
304
305         mov     r0, #(10 * 4);
306         pop {%r4-%r11, %ip, %pc};
307
308 .ltorg
309 .Lenc_not_128:
310         beq .Lenc_192
311
312         encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
313         encround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
314         encround(10, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
315         encround(11, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
316         encround(12, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
317         lastencround(13, RNA, RNB, RNC, RND, RA, RB, RC, RD);
318
319         b .Lenc_done;
320
321 .ltorg
322 .Lenc_192:
323         encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
324         encround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
325         encround(10, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
326         lastencround(11, RNA, RNB, RNC, RND, RA, RB, RC, RD);
327
328         b .Lenc_done;
329 .size _gcry_aes_arm_encrypt_block,.-_gcry_aes_arm_encrypt_block;
330
331 #define addroundkey_dec(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
332         ldr rna, [CTX, #(((round) * 16) + 0 * 4)]; \
333         ldr rnb, [CTX, #(((round) * 16) + 1 * 4)]; \
334         eor ra, rna; \
335         ldr rnc, [CTX, #(((round) * 16) + 2 * 4)]; \
336         eor rb, rnb; \
337         ldr rnd, [CTX, #(((round) * 16) + 3 * 4)]; \
338         eor rc, rnc; \
339         preload_first_key((round) - 1, rna); \
340         eor rd, rnd;
341
342 #define do_decround(next_r, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
343         ldr rnb, [CTX, #(((next_r) * 16) + 1 * 4)]; \
344         \
345         and RT0, RMASK, ra, lsl#2; \
346         ldr rnc, [CTX, #(((next_r) * 16) + 2 * 4)]; \
347         and RT1, RMASK, ra, lsr#(8 - 2); \
348         ldr rnd, [CTX, #(((next_r) * 16) + 3 * 4)]; \
349         and RT2, RMASK, ra, lsr#(16 - 2); \
350         ldr RT0, [RTAB, RT0]; \
351         and ra,  RMASK, ra, lsr#(24 - 2); \
352         \
353         ldr RT1, [RTAB, RT1]; \
354         eor rna, rna, RT0; \
355         ldr RT2, [RTAB, RT2]; \
356         and RT0, RMASK, rb, lsl#2; \
357         ldr ra,  [RTAB, ra]; \
358         \
359         eor rnb, rnb, RT1, ror #24; \
360         and RT1, RMASK, rb, lsr#(8 - 2); \
361         eor rnc, rnc, RT2, ror #16; \
362         and RT2, RMASK, rb, lsr#(16 - 2); \
363         eor rnd, rnd, ra, ror #8; \
364         ldr RT0, [RTAB, RT0]; \
365         and rb,  RMASK, rb, lsr#(24 - 2); \
366         \
367         ldr RT1, [RTAB, RT1]; \
368         eor rnb, rnb, RT0; \
369         ldr RT2, [RTAB, RT2]; \
370         and RT0, RMASK, rc, lsl#2; \
371         ldr rb,  [RTAB, rb]; \
372         \
373         eor rnc, rnc, RT1, ror #24; \
374         and RT1, RMASK, rc, lsr#(8 - 2); \
375         eor rnd, rnd, RT2, ror #16; \
376         and RT2, RMASK, rc, lsr#(16 - 2); \
377         eor rna, rna, rb, ror #8; \
378         ldr RT0, [RTAB, RT0]; \
379         and rc,  RMASK, rc, lsr#(24 - 2); \
380         \
381         ldr RT1, [RTAB, RT1]; \
382         eor rnc, rnc, RT0; \
383         ldr RT2, [RTAB, RT2]; \
384         and RT0, RMASK, rd, lsl#2; \
385         ldr rc,  [RTAB, rc]; \
386         \
387         eor rnd, rnd, RT1, ror #24; \
388         and RT1, RMASK, rd, lsr#(8 - 2); \
389         eor rna, rna, RT2, ror #16; \
390         and RT2, RMASK, rd, lsr#(16 - 2); \
391         eor rnb, rnb, rc, ror #8; \
392         ldr RT0, [RTAB, RT0]; \
393         and rd,  RMASK, rd, lsr#(24 - 2); \
394         \
395         ldr RT1, [RTAB, RT1]; \
396         eor rnd, rnd, RT0; \
397         ldr RT2, [RTAB, RT2]; \
398         eor rna, rna, RT1, ror #24; \
399         ldr rd,  [RTAB, rd]; \
400         \
401         eor rnb, rnb, RT2, ror #16; \
402         preload_key((next_r) - 1, ra); \
403         eor rnc, rnc, rd, ror #8;
404
405 #define do_lastdecround(ra, rb, rc, rd, rna, rnb, rnc, rnd) \
406         and RT0, RMASK, ra; \
407         and RT1, RMASK, ra, lsr#8; \
408         and RT2, RMASK, ra, lsr#16; \
409         ldrb rna, [RTAB, RT0]; \
410         mov ra,  ra, lsr#24; \
411         ldrb rnb, [RTAB, RT1]; \
412         and RT0, RMASK, rb; \
413         ldrb rnc, [RTAB, RT2]; \
414         mov rnb, rnb, ror #24; \
415         ldrb rnd, [RTAB, ra]; \
416         and RT1, RMASK, rb, lsr#8; \
417         mov rnc, rnc, ror #16; \
418         and RT2, RMASK, rb, lsr#16; \
419         mov rnd, rnd, ror #8; \
420         ldrb RT0, [RTAB, RT0]; \
421         mov rb,  rb, lsr#24; \
422         ldrb RT1, [RTAB, RT1]; \
423         \
424         orr rnb, rnb, RT0; \
425         ldrb RT2, [RTAB, RT2]; \
426         and RT0, RMASK, rc; \
427         ldrb rb,  [RTAB, rb]; \
428         orr rnc, rnc, RT1, ror #24; \
429         and RT1, RMASK, rc, lsr#8; \
430         orr rnd, rnd, RT2, ror #16; \
431         and RT2, RMASK, rc, lsr#16; \
432         orr rna, rna, rb, ror #8; \
433         ldrb RT0, [RTAB, RT0]; \
434         mov rc,  rc, lsr#24; \
435         ldrb RT1, [RTAB, RT1]; \
436         \
437         orr rnc, rnc, RT0; \
438         ldrb RT2, [RTAB, RT2]; \
439         and RT0, RMASK, rd; \
440         ldrb rc,  [RTAB, rc]; \
441         orr rnd, rnd, RT1, ror #24; \
442         and RT1, RMASK, rd, lsr#8; \
443         orr rna, rna, RT2, ror #16; \
444         ldrb RT0, [RTAB, RT0]; \
445         and RT2, RMASK, rd, lsr#16; \
446         ldrb RT1, [RTAB, RT1]; \
447         orr rnb, rnb, rc, ror #8; \
448         ldrb RT2, [RTAB, RT2]; \
449         mov rd,  rd, lsr#24; \
450         ldrb rd,  [RTAB, rd]; \
451         \
452         orr rnd, rnd, RT0; \
453         orr rna, rna, RT1, ror #24; \
454         orr rnb, rnb, RT2, ror #16; \
455         orr rnc, rnc, rd, ror #8;
456
457 #define firstdecround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
458         addroundkey_dec(((round) + 1), ra, rb, rc, rd, rna, rnb, rnc, rnd); \
459         do_decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_first_key);
460
461 #define decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
462         do_decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key);
463
464 #define set_last_round_rmask(_, __) \
465         mov RMASK, #0xff;
466
467 #define lastdecround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
468         add RTAB, #(4 * 256); \
469         do_lastdecround(ra, rb, rc, rd, rna, rnb, rnc, rnd); \
470         addroundkey(rna, rnb, rnc, rnd, ra, rb, rc, rd, dummy);
471
472 .align 3
473 .globl _gcry_aes_arm_decrypt_block
474 .type   _gcry_aes_arm_decrypt_block,%function;
475
476 _gcry_aes_arm_decrypt_block:
477         /* input:
478          *      %r0: keysched, CTX
479          *      %r1: dst
480          *      %r2: src
481          *      %r3: number of rounds.. 10, 12 or 14
482          *      %st+0: decryption table
483          */
484         push {%r4-%r11, %ip, %lr};
485
486         /* read input block */
487 #ifndef __ARM_FEATURE_UNALIGNED
488         /* test if src is unaligned */
489         tst     %r2, #3;
490         beq     1f;
491
492         /* unaligned load */
493         ldr_unaligned_le(RA, %r2, 0, RNA);
494         ldr_unaligned_le(RB, %r2, 4, RNB);
495         ldr_unaligned_le(RC, %r2, 8, RNA);
496         ldr_unaligned_le(RD, %r2, 12, RNB);
497         b       2f;
498 .ltorg
499 1:
500 #endif
501         /* aligned load */
502         ldm     %r2, {RA, RB, RC, RD};
503 #ifndef __ARMEL__
504         rev     RA, RA;
505         rev     RB, RB;
506         rev     RC, RC;
507         rev     RD, RD;
508 #endif
509 2:
510         ldr     RTAB, [%sp, #40];
511         sub     %sp, #16;
512
513         mov     RMASK, #0xff;
514         str     %r1, [%sp, #4];         /* dst */
515         mov     RMASK, RMASK, lsl#2;    /* byte mask */
516
517         cmp     %r3, #12;
518         bge     .Ldec_256;
519
520         firstdecround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND);
521 .Ldec_tail:
522         decround(8, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
523         decround(7, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
524         decround(6, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
525         decround(5, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
526         decround(4, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
527         decround(3, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
528         decround(2, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
529         decround(1, RA, RB, RC, RD, RNA, RNB, RNC, RND, set_last_round_rmask);
530         lastdecround(0, RNA, RNB, RNC, RND, RA, RB, RC, RD);
531
532         ldr     RT0, [%sp, #4];         /* dst */
533         add     %sp, #16;
534
535         /* store output block */
536 #ifndef __ARM_FEATURE_UNALIGNED
537         /* test if dst is unaligned */
538         tst     RT0, #3;
539         beq     1f;
540
541         /* unaligned store */
542         str_unaligned_le(RA, RT0, 0, RNA, RNB);
543         str_unaligned_le(RB, RT0, 4, RNA, RNB);
544         str_unaligned_le(RC, RT0, 8, RNA, RNB);
545         str_unaligned_le(RD, RT0, 12, RNA, RNB);
546         b       2f;
547 .ltorg
548 1:
549 #endif
550         /* aligned store */
551 #ifndef __ARMEL__
552         rev     RA, RA;
553         rev     RB, RB;
554         rev     RC, RC;
555         rev     RD, RD;
556 #endif
557         /* write output block */
558         stm     RT0, {RA, RB, RC, RD};
559 2:
560         mov     r0, #(10 * 4);
561         pop {%r4-%r11, %ip, %pc};
562
563 .ltorg
564 .Ldec_256:
565         beq .Ldec_192;
566
567         firstdecround(13, RA, RB, RC, RD, RNA, RNB, RNC, RND);
568         decround(12, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
569         decround(11, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
570         decround(10, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
571         decround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
572
573         b .Ldec_tail;
574
575 .ltorg
576 .Ldec_192:
577         firstdecround(11, RA, RB, RC, RD, RNA, RNB, RNC, RND);
578         decround(10, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
579         decround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
580
581         b .Ldec_tail;
582 .size _gcry_aes_arm_encrypt_block,.-_gcry_aes_arm_encrypt_block;
583
584 #endif /*HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS*/
585 #endif /*__ARMEL__ */