~ubuntu-branches/ubuntu/dapper/nettle/dapper

« back to all changes in this revision

Viewing changes to sparc/aes.asm

  • Committer: Bazaar Package Importer
  • Author(s): Marek Habersack
  • Date: 2004-05-04 15:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20040504155602-7jbhw5mabvwksl3j
Tags: upstream-1.10
Import upstream version 1.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
! -*- mode: asm; asm-comment-char: ?!; -*-  
 
2
! nettle, low-level cryptographics library
 
3
 
4
! Copyright (C) 2002 Niels M�ller
 
5
!  
 
6
! The nettle library is free software; you can redistribute it and/or modify
 
7
! it under the terms of the GNU Lesser General Public License as published by
 
8
! the Free Software Foundation; either version 2.1 of the License, or (at your
 
9
! option) any later version.
 
10
 
11
! The nettle library is distributed in the hope that it will be useful, but
 
12
! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
13
! or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 
14
! License for more details.
 
15
 
16
! You should have received a copy of the GNU Lesser General Public License
 
17
! along with the nettle library; see the file COPYING.LIB.  If not, write to
 
18
! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 
19
! MA 02111-1307, USA.
 
20
 
 
21
! FIXME: For improved ultra sparc performance, we should avoid ALU
 
22
! instructions that use the result of an immediately preceeding ALU
 
23
! instruction. It is also a good idea to have a greater distance than
 
24
! one instruction between a load and use of its value, as that reduces
 
25
! the penalty for cache misses. Such instruction sequences are marked
 
26
! with !U comments.
 
27
 
 
28
! NOTE: Some of the %g registers are reserved for operating system etc
 
29
! (see gcc/config/sparc.h). The only %g registers that seems safe to
 
30
! use are %g1-%g3.
 
31
        
 
32
        ! Used registers:       %l0,1,2,3,4,5,6,7
 
33
        !                       %i0,1,2,3,4 (%i6=%fp, %i7 = return)
 
34
        !                       %o0,1,2,3,4 (%o6=%sp)
 
35
        !                       
 
36
        
 
37
        .file   "aes.asm"
 
38
 
 
39
! Arguments
 
40
define(ctx, %i0)
 
41
define(T, %i1)
 
42
define(length, %i2)
 
43
define(dst, %i3)
 
44
define(src, %i4)
 
45
 
 
46
! Loop invariants
 
47
define(wtxt, %l0)
 
48
define(tmp, %l1)
 
49
define(diff, %l2)
 
50
define(nrounds, %l3)
 
51
 
 
52
! Further loop invariants
 
53
define(T0, %l4)
 
54
define(T1, %l5)
 
55
define(T2, %l6)
 
56
define(T3, %l7)
 
57
        
 
58
! Teporaries
 
59
define(t0, %o0)
 
60
define(t1, %o1)
 
61
define(t2, %o2)
 
62
 
 
63
! Loop variables
 
64
define(round, %o3)
 
65
define(key, %o4)
 
66
 
 
67
C IDX1 cointains the permutation values * 4 + 2
 
68
define(IDX1, <T + AES_SIDX1 >)
 
69
C IDX3 cointains the permutation values * 4
 
70
define(IDX3, <T + AES_SIDX3 >)
 
71
 
 
72
 
 
73
C AES_LOAD(i)
 
74
C Get one word of input, XOR with first subkey, store in wtxt
 
75
define(<AES_LOAD>, <
 
76
        ldub    [src+$1], t0
 
77
        ldub    [src+$1+1], t1
 
78
        ldub    [src+$1+2], t2
 
79
        sll     t1, 8, t1
 
80
        
 
81
        or      t0, t1, t0      ! U
 
82
        ldub    [src+$1+3], t1
 
83
        sll     t2, 16, t2
 
84
        or      t0, t2, t0
 
85
        
 
86
        sll     t1, 24, t1
 
87
        ! Get subkey
 
88
        ld      [ctx + $1], t2
 
89
        or      t0, t1, t0
 
90
        xor     t0, t2, t0
 
91
        
 
92
        st      t0, [wtxt+$1]>)dnl
 
93
 
 
94
C AES_ROUND(i)
 
95
C Compute one word in the round function. 
 
96
C Input in wtxt, output stored in tmp + i.
 
97
C
 
98
C The comments mark which j in T->table[j][ Bj(wtxt[IDXi(i)]) ]
 
99
C the instruction is a part of. 
 
100
define(<AES_ROUND>, <
 
101
        ld      [IDX1+$1], t1           ! 1
 
102
        ldub    [wtxt+$1+3], t0         ! 0
 
103
        ldub    [wtxt+t1], t1           ! 1
 
104
        sll     t0, 2, t0               ! 0
 
105
        
 
106
        ld      [T0+t0], t0             ! 0
 
107
        sll     t1, 2, t1               ! 1
 
108
        ld      [T1+t1], t1             ! 1 !U
 
109
        ld      [IDX3+$1], t2           ! 3
 
110
        
 
111
        xor     t0, t1, t0              ! 0, 1
 
112
        ! IDX2(j) = j XOR 2
 
113
        ldub    [wtxt+eval($1 ^ 8)+1], t1       ! 2
 
114
        ldub    [wtxt+t2], t2           ! 3
 
115
        sll     t1, 2, t1               ! 2
 
116
        
 
117
        ld      [T2+t1], t1             ! 2     !U
 
118
        sll     t2, 2, t2               ! 3
 
119
        ld      [T3+t2], t2             ! 3     !U
 
120
        xor     t0, t1, t0              ! 0, 1, 2
 
121
        
 
122
        ! Fetch roundkey
 
123
        ld      [key + $1], t1
 
124
        xor     t0, t2, t0              ! 0, 1, 2, 3
 
125
        xor     t0, t1, t0              !U
 
126
        st      t0, [tmp + $1]>)dnl
 
127
 
 
128
C AES_FINAL_ROUND(i)
 
129
C Compute one word in the final round function. 
 
130
C Input in wtxt, output converted to an octet string and stored at dst. 
 
131
C
 
132
C The comments mark which j in T->table[j][ Bj(wtxt[IDXi(i)]) ]
 
133
C the instruction is a part of. 
 
134
define(<AES_FINAL_ROUND>, <
 
135
        ld      [IDX1+$1], t1           ! 1
 
136
        ldub    [wtxt+$1+3], t0         ! 0
 
137
        ldub    [wtxt+t1], t1           ! 1
 
138
        ldub    [T+t0], t0              ! 0
 
139
        
 
140
        ldub    [T+t1], t1              ! 1
 
141
        ld      [IDX3 + $1], t2         ! 3
 
142
        sll     t1, 8, t1               ! 1
 
143
        or      t0, t1, t0              ! 0, 1 !U
 
144
        
 
145
        ! IDX2(j) = j XOR 2
 
146
        ldub    [wtxt+eval($1 ^ 8)+1], t1       ! 2
 
147
        ldub    [wtxt+t2], t2           ! 3
 
148
        ldub    [T+t1], t1              ! 2
 
149
        ldub    [T+t2], t2              ! 3
 
150
        
 
151
        sll     t1, 16, t1              ! 2
 
152
        or      t0, t1, t0              ! 0, 1, 2 !U
 
153
        sll     t2, 24, t2              ! 3
 
154
        ld      [key + $1], t1
 
155
        
 
156
        or      t0, t2, t0              ! 0, 1, 2, 3
 
157
        xor     t0, t1, t0              !U
 
158
        srl     t0, 24, t1              !U
 
159
        stb     t1, [dst+$1+3]          !U
 
160
        
 
161
        srl     t0, 16, t1
 
162
        stb     t1, [dst+$1+2]          !U
 
163
        srl     t0, 8, t1
 
164
        stb     t1, [dst+$1+1]          !U
 
165
        
 
166
        stb     t0, [dst+$1]>)dnl
 
167
        
 
168
C The stack frame looks like
 
169
C
 
170
C %fp -   4: OS-dependent link field
 
171
C %fp -   8: OS-dependent link field
 
172
C %fp -  24: tmp, uint32_t[4]
 
173
C %fp -  40: wtxt, uint32_t[4]
 
174
C %fp - 136: OS register save area. 
 
175
define(<FRAME_SIZE>, 136)
 
176
 
 
177
        .section        ".text"
 
178
        .align 16
 
179
        .global _nettle_aes_crypt
 
180
        .type   _nettle_aes_crypt,#function
 
181
        .proc   020
 
182
        
 
183
_nettle_aes_crypt:
 
184
        save    %sp, -FRAME_SIZE, %sp
 
185
        cmp     length, 0
 
186
        be      .Lend
 
187
        ! wtxt
 
188
        add     %fp, -24, wtxt
 
189
        
 
190
        add     %fp, -40, tmp
 
191
        ld      [ctx + AES_NROUNDS], nrounds
 
192
        ! Compute xor, so that we can swap efficiently.
 
193
        xor     wtxt, tmp, diff
 
194
        ! The loop variable will be multiplied by 16.
 
195
        ! More loop invariants
 
196
        add     T, AES_TABLE0, T0
 
197
        
 
198
        add     T, AES_TABLE1, T1
 
199
        add     T, AES_TABLE2, T2
 
200
        add     T, AES_TABLE3, T3
 
201
        nop
 
202
        
 
203
.Lblock_loop:
 
204
        C  Read src, and add initial subkey
 
205
        AES_LOAD(0)     ! i = 0
 
206
        AES_LOAD(4)     ! i = 1
 
207
        AES_LOAD(8)     ! i = 2
 
208
        AES_LOAD(12)    ! i = 3
 
209
        add     src, 16, src
 
210
 
 
211
        sub     nrounds, 1, round
 
212
        add     ctx, 16, key
 
213
        nop
 
214
.Lround_loop:
 
215
 
 
216
        AES_ROUND(0)    ! i = 0
 
217
        AES_ROUND(4)    ! i = 1
 
218
        AES_ROUND(8)    ! i = 2
 
219
        AES_ROUND(12)   ! i = 3
 
220
                        
 
221
        ! switch roles for tmp and wtxt
 
222
        xor     wtxt, diff, wtxt
 
223
        xor     tmp, diff, tmp
 
224
        subcc   round, 1, round
 
225
        bne     .Lround_loop
 
226
 
 
227
        add     key, 16, key
 
228
 
 
229
        C Final round, and storage of the output
 
230
 
 
231
        AES_FINAL_ROUND(0)      ! i = 0
 
232
        AES_FINAL_ROUND(4)      ! i = 1
 
233
        AES_FINAL_ROUND(8)      ! i = 2
 
234
        AES_FINAL_ROUND(12)     ! i = 3
 
235
                
 
236
        addcc   length, -16, length
 
237
        bne     .Lblock_loop
 
238
        add     dst, 16, dst
 
239
 
 
240
.Lend:
 
241
        ret
 
242
        restore
 
243
.Leord:
 
244
        .size   _nettle_aes_crypt,.Leord-_nettle_aes_crypt
 
245
 
 
246
        ! Benchmarks on my slow sparcstation:   
 
247
        ! Original C code       
 
248
        ! aes128 (ECB encrypt): 14.36s, 0.696MB/s
 
249
        ! aes128 (ECB decrypt): 17.19s, 0.582MB/s
 
250
        ! aes128 (CBC encrypt): 16.08s, 0.622MB/s
 
251
        ! aes128 ((CBC decrypt)): 18.79s, 0.532MB/s
 
252
        ! 
 
253
        ! aes192 (ECB encrypt): 16.85s, 0.593MB/s
 
254
        ! aes192 (ECB decrypt): 19.64s, 0.509MB/s
 
255
        ! aes192 (CBC encrypt): 18.43s, 0.543MB/s
 
256
        ! aes192 (CBC decrypt): 20.76s, 0.482MB/s
 
257
        ! 
 
258
        ! aes256 (ECB encrypt): 19.12s, 0.523MB/s
 
259
        ! aes256 (ECB decrypt): 22.57s, 0.443MB/s
 
260
        ! aes256 (CBC encrypt): 20.92s, 0.478MB/s
 
261
        ! aes256 (CBC decrypt): 23.22s, 0.431MB/s
 
262
 
 
263
        ! After unrolling key_addition32, and getting rid of
 
264
        ! some sll x, 2, x, encryption speed is 0.760 MB/s.
 
265
 
 
266
        ! Next, the C code was optimized to use larger tables and
 
267
        ! no rotates. New timings:
 
268
        ! aes128 (ECB encrypt): 13.10s, 0.763MB/s
 
269
        ! aes128 (ECB decrypt): 11.51s, 0.869MB/s
 
270
        ! aes128 (CBC encrypt): 15.15s, 0.660MB/s
 
271
        ! aes128 (CBC decrypt): 13.10s, 0.763MB/s
 
272
        ! 
 
273
        ! aes192 (ECB encrypt): 15.68s, 0.638MB/s
 
274
        ! aes192 (ECB decrypt): 13.59s, 0.736MB/s
 
275
        ! aes192 (CBC encrypt): 17.65s, 0.567MB/s
 
276
        ! aes192 (CBC decrypt): 15.31s, 0.653MB/s
 
277
        ! 
 
278
        ! aes256 (ECB encrypt): 17.95s, 0.557MB/s
 
279
        ! aes256 (ECB decrypt): 15.90s, 0.629MB/s
 
280
        ! aes256 (CBC encrypt): 20.16s, 0.496MB/s
 
281
        ! aes256 (CBC decrypt): 17.47s, 0.572MB/s
 
282
 
 
283
        ! After optimization using pre-shifted indices
 
284
        ! (AES_SIDX[1-3]): 
 
285
        ! aes128 (ECB encrypt): 12.46s, 0.803MB/s
 
286
        ! aes128 (ECB decrypt): 10.74s, 0.931MB/s
 
287
        ! aes128 (CBC encrypt): 17.74s, 0.564MB/s
 
288
        ! aes128 (CBC decrypt): 12.43s, 0.805MB/s
 
289
        ! 
 
290
        ! aes192 (ECB encrypt): 14.59s, 0.685MB/s
 
291
        ! aes192 (ECB decrypt): 12.76s, 0.784MB/s
 
292
        ! aes192 (CBC encrypt): 19.97s, 0.501MB/s
 
293
        ! aes192 (CBC decrypt): 14.46s, 0.692MB/s
 
294
        ! 
 
295
        ! aes256 (ECB encrypt): 17.00s, 0.588MB/s
 
296
        ! aes256 (ECB decrypt): 14.81s, 0.675MB/s
 
297
        ! aes256 (CBC encrypt): 22.65s, 0.442MB/s
 
298
        ! aes256 (CBC decrypt): 16.46s, 0.608MB/s
 
299
 
 
300
        ! After implementing double buffering
 
301
        ! aes128 (ECB encrypt): 12.59s, 0.794MB/s
 
302
        ! aes128 (ECB decrypt): 10.56s, 0.947MB/s
 
303
        ! aes128 (CBC encrypt): 17.91s, 0.558MB/s
 
304
        ! aes128 (CBC decrypt): 12.30s, 0.813MB/s
 
305
        ! 
 
306
        ! aes192 (ECB encrypt): 15.03s, 0.665MB/s
 
307
        ! aes192 (ECB decrypt): 12.56s, 0.796MB/s
 
308
        ! aes192 (CBC encrypt): 20.30s, 0.493MB/s
 
309
        ! aes192 (CBC decrypt): 14.26s, 0.701MB/s
 
310
        ! 
 
311
        ! aes256 (ECB encrypt): 17.30s, 0.578MB/s
 
312
        ! aes256 (ECB decrypt): 14.51s, 0.689MB/s
 
313
        ! aes256 (CBC encrypt): 22.75s, 0.440MB/s
 
314
        ! aes256 (CBC decrypt): 16.35s, 0.612MB/s
 
315
        
 
316
        ! After reordering aes-encrypt.c and aes-decypt.c
 
317
        ! (the order probably causes strange cache-effects):
 
318
        ! aes128 (ECB encrypt): 9.21s, 1.086MB/s
 
319
        ! aes128 (ECB decrypt): 11.13s, 0.898MB/s
 
320
        ! aes128 (CBC encrypt): 14.12s, 0.708MB/s
 
321
        ! aes128 (CBC decrypt): 13.77s, 0.726MB/s
 
322
        ! 
 
323
        ! aes192 (ECB encrypt): 10.86s, 0.921MB/s
 
324
        ! aes192 (ECB decrypt): 13.17s, 0.759MB/s
 
325
        ! aes192 (CBC encrypt): 15.74s, 0.635MB/s
 
326
        ! aes192 (CBC decrypt): 15.91s, 0.629MB/s
 
327
        ! 
 
328
        ! aes256 (ECB encrypt): 12.71s, 0.787MB/s
 
329
        ! aes256 (ECB decrypt): 15.38s, 0.650MB/s
 
330
        ! aes256 (CBC encrypt): 17.49s, 0.572MB/s
 
331
        ! aes256 (CBC decrypt): 17.87s, 0.560MB/s
 
332
 
 
333
        ! After further optimizations of the initial and final loops,
 
334
        ! source_loop and final_loop. 
 
335
        ! aes128 (ECB encrypt): 8.07s, 1.239MB/s
 
336
        ! aes128 (ECB decrypt): 9.48s, 1.055MB/s
 
337
        ! aes128 (CBC encrypt): 12.76s, 0.784MB/s
 
338
        ! aes128 (CBC decrypt): 12.15s, 0.823MB/s
 
339
        ! 
 
340
        ! aes192 (ECB encrypt): 9.43s, 1.060MB/s
 
341
        ! aes192 (ECB decrypt): 11.20s, 0.893MB/s
 
342
        ! aes192 (CBC encrypt): 14.19s, 0.705MB/s
 
343
        ! aes192 (CBC decrypt): 13.97s, 0.716MB/s
 
344
        ! 
 
345
        ! aes256 (ECB encrypt): 10.81s, 0.925MB/s
 
346
        ! aes256 (ECB decrypt): 12.92s, 0.774MB/s
 
347
        ! aes256 (CBC encrypt): 15.59s, 0.641MB/s
 
348
        ! aes256 (CBC decrypt): 15.76s, 0.635MB/s
 
349
        
 
350
        ! After unrolling loops, and other optimizations suggested by
 
351
        ! Marcus: 
 
352
        ! aes128 (ECB encrypt): 6.40s, 1.562MB/s
 
353
        ! aes128 (ECB decrypt): 8.17s, 1.224MB/s
 
354
        ! aes128 (CBC encrypt): 13.11s, 0.763MB/s
 
355
        ! aes128 (CBC decrypt): 10.05s, 0.995MB/s
 
356
        ! 
 
357
        ! aes192 (ECB encrypt): 7.43s, 1.346MB/s
 
358
        ! aes192 (ECB decrypt): 9.51s, 1.052MB/s
 
359
        ! aes192 (CBC encrypt): 14.09s, 0.710MB/s
 
360
        ! aes192 (CBC decrypt): 11.58s, 0.864MB/s
 
361
        ! 
 
362
        ! aes256 (ECB encrypt): 8.57s, 1.167MB/s
 
363
        ! aes256 (ECB decrypt): 11.13s, 0.898MB/s
 
364
        ! aes256 (CBC encrypt): 15.30s, 0.654MB/s
 
365
        ! aes256 (CBC decrypt): 12.93s, 0.773MB/s