c1f5d51b6d725c33f79b84c3c29581e080d6348b
[platform/upstream/nettle.git] / sparc32 / aes-encrypt-internal.asm
1 C sparc32/aes-encrypt-internal.asm
2
3 ifelse(<
4    Copyright (C) 2002, 2005, 2013 Niels Möller
5
6    This file is part of GNU Nettle.
7
8    GNU Nettle is free software: you can redistribute it and/or
9    modify it under the terms of either:
10
11      * the GNU Lesser General Public License as published by the Free
12        Software Foundation; either version 3 of the License, or (at your
13        option) any later version.
14
15    or
16
17      * the GNU General Public License as published by the Free
18        Software Foundation; either version 2 of the License, or (at your
19        option) any later version.
20
21    or both in parallel, as here.
22
23    GNU Nettle is distributed in the hope that it will be useful,
24    but WITHOUT ANY WARRANTY; without even the implied warranty of
25    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26    General Public License for more details.
27
28    You should have received copies of the GNU General Public License and
29    the GNU Lesser General Public License along with this program.  If
30    not, see http://www.gnu.org/licenses/.
31 >)
32
33 include_src(<sparc32/aes.m4>)
34
35 C       Arguments
36 define(<ROUNDS>,<%i0>)
37 define(<KEYS>,  <%i1>)
38 define(<T>,     <%i2>)
39 define(<LENGTH>,<%i3>)
40 define(<DST>,   <%i4>)
41 define(<SRC>,   <%i5>)
42
43 C       AES state, two copies for unrolling
44
45 define(<W0>,    <%l0>)
46 define(<W1>,    <%l1>)
47 define(<W2>,    <%l2>)
48 define(<W3>,    <%l3>)
49
50 define(<X0>,    <%l4>)
51 define(<X1>,    <%l5>)
52 define(<X2>,    <%l6>)
53 define(<X3>,    <%l7>)
54
55 C       %o0-%03 are used for loop invariants T0-T3
56 define(<KEY>,   <%o4>)
57 define(<COUNT>, <%o5>)
58
59 C %g1, %g2, %g3 are TMP1, TMP2 and TMP3
60
61 C I'm still slightly confused by the frame layout, specified in
62 C "SYSTEM V APPLICATION BINARY INTERFACE SPARC Processor Supplement".
63 C However, Sun's cc generates a 104 byte stack frame for a function
64 C with no local variables, so that should be good enough for us too.
65
66 C The sparc32 stack frame looks like
67 C
68 C %fp -   4: OS-dependent link field
69 C %fp -   8: OS-dependent link field
70 C %fp - 104: OS register save area 
71 define(<FRAME_SIZE>, 104)
72
73         .file "aes-encrypt-internal.asm"
74
75         C _aes_encrypt(unsigned rounds, const uint32_t *keys,
76         C              const struct aes_table *T,
77         C              size_t length, uint8_t *dst,
78         C              uint8_t *src)
79
80         .section        ".text"
81         .align 16
82         .proc   020
83         
84 PROLOGUE(_nettle_aes_encrypt)
85
86         save    %sp, -FRAME_SIZE, %sp
87         cmp     LENGTH, 0
88         be      .Lend
89
90         C       Loop invariants
91         add     T, AES_TABLE0, T0
92         add     T, AES_TABLE1, T1
93         add     T, AES_TABLE2, T2
94         add     T, AES_TABLE3, T3
95
96         C       Must be even, and includes the final round
97         srl     ROUNDS, 1, ROUNDS
98         C       Last two rounds handled specially
99         sub     ROUNDS, 1, ROUNDS
100
101 .Lblock_loop:
102         C  Read src, and add initial subkey
103         mov     KEYS, KEY
104         AES_LOAD(0, SRC, KEY, W0)
105         AES_LOAD(1, SRC, KEY, W1)
106         AES_LOAD(2, SRC, KEY, W2)
107         AES_LOAD(3, SRC, KEY, W3)
108
109         mov     ROUNDS, COUNT
110         add     SRC, 16, SRC
111         add     KEY, 16, KEY
112
113 .Lround_loop:
114         C The AES_ROUND macro uses T0,... T3
115         C       Transform W -> X
116         AES_ROUND(0, W0, W1, W2, W3, KEY, X0)
117         AES_ROUND(1, W1, W2, W3, W0, KEY, X1)
118         AES_ROUND(2, W2, W3, W0, W1, KEY, X2)
119         AES_ROUND(3, W3, W0, W1, W2, KEY, X3)
120
121         C       Transform X -> W
122         AES_ROUND(4, X0, X1, X2, X3, KEY, W0)
123         AES_ROUND(5, X1, X2, X3, X0, KEY, W1)
124         AES_ROUND(6, X2, X3, X0, X1, KEY, W2)
125         AES_ROUND(7, X3, X0, X1, X2, KEY, W3)
126
127         subcc   COUNT, 1, COUNT
128         bne     .Lround_loop
129         add     KEY, 32, KEY
130
131         C       Penultimate round
132         AES_ROUND(0, W0, W1, W2, W3, KEY, X0)
133         AES_ROUND(1, W1, W2, W3, W0, KEY, X1)
134         AES_ROUND(2, W2, W3, W0, W1, KEY, X2)
135         AES_ROUND(3, W3, W0, W1, W2, KEY, X3)
136
137         add     KEY, 16, KEY
138         C       Final round
139         AES_FINAL_ROUND(0, T, X0, X1, X2, X3, KEY, DST)
140         AES_FINAL_ROUND(1, T, X1, X2, X3, X0, KEY, DST)
141         AES_FINAL_ROUND(2, T, X2, X3, X0, X1, KEY, DST)
142         AES_FINAL_ROUND(3, T, X3, X0, X1, X2, KEY, DST)
143
144         subcc   LENGTH, 16, LENGTH
145         bne     .Lblock_loop
146         add     DST, 16, DST
147
148 .Lend:
149         ret
150         restore
151 EPILOGUE(_nettle_aes_encrypt)
152
153 C Some stats from adriana.lysator.liu.se (SS1000$, 85 MHz), for AES 128
154
155 C 1:    nettle-1.13 C-code
156 C 2:    nettle-1.13 assembler
157 C 3:    New C-code
158 C 4:    New assembler, first correct version
159 C 5:    New assembler, with basic scheduling of AES_ROUND.
160 C 6:    New assembpler, with loop invariants T0-T3.
161 C 7:    New assembler, with basic scheduling also of AES_FINAL_ROUND.
162         
163 C       MB/s    cycles/block    Code size (bytes)
164 C 1     1.2     1107            592
165 C 2     2.3     572             1032
166 C 3     2.1     627
167 C 4     1.8     722
168 C 5     2.6     496
169 C 6     3.0     437
170 C 7     3.1     415             1448