f78e713f707af4962230ab62df01afac57a95cae
[openssl.git] / crypto / aes / asm / vpaes-ppc.pl
1 #!/usr/bin/env perl
2
3 ######################################################################
4 ## Constant-time SSSE3 AES core implementation.
5 ## version 0.1
6 ##
7 ## By Mike Hamburg (Stanford University), 2009
8 ## Public domain.
9 ##
10 ## For details see http://shiftleft.org/papers/vector_aes/ and
11 ## http://crypto.stanford.edu/vpaes/.
12
13 # CBC encrypt/decrypt performance in cycles per byte processed with
14 # 128-bit key.
15 #
16 #               aes-ppc.pl              this
17 # G4e           35.5/52.1/(23.8)        11.9(*)/15.4
18 # POWER6        42.7/54.3/(28.2)        63.0/92.8(**)
19 # POWER7        32.3/42.9/(18.4)        18.5/23.3
20 #
21 # (*)   This is ~10% worse than reported in paper. The reason is
22 #       twofold. This module doesn't make any assumption about
23 #       key schedule (or data for that matter) alignment and handles
24 #       it in-line. Secondly it, being transliterated from
25 #       vpaes-x86_64.pl, relies on "nested inversion" better suited
26 #       for Intel CPUs.
27 # (**)  Inadequate POWER6 performance is due to astronomic AltiVec
28 #       latency, 9 cycles per simple logical operation.
29
30 $flavour = shift;
31
32 if ($flavour =~ /64/) {
33         $SIZE_T =8;
34         $LRSAVE =2*$SIZE_T;
35         $STU    ="stdu";
36         $POP    ="ld";
37         $PUSH   ="std";
38 } elsif ($flavour =~ /32/) {
39         $SIZE_T =4;
40         $LRSAVE =$SIZE_T;
41         $STU    ="stwu";
42         $POP    ="lwz";
43         $PUSH   ="stw";
44 } else { die "nonsense $flavour"; }
45
46 $sp="r1";
47 $FRAME=6*$SIZE_T+13*16; # 13*16 is for v20-v31 offload
48
49 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
50 ( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
51 ( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
52 die "can't locate ppc-xlate.pl";
53
54 open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
55
56 $code.=<<___;
57 .machine        "any"
58
59 .text
60
61 .align  7       # totally strategic alignment
62 _vpaes_consts:
63 Lk_mc_forward:  # mc_forward
64         .long   0x01020300, 0x05060704, 0x090a0b08, 0x0d0e0f0c  ?inv
65         .long   0x05060704, 0x090a0b08, 0x0d0e0f0c, 0x01020300  ?inv
66         .long   0x090a0b08, 0x0d0e0f0c, 0x01020300, 0x05060704  ?inv
67         .long   0x0d0e0f0c, 0x01020300, 0x05060704, 0x090a0b08  ?inv
68 Lk_mc_backward: # mc_backward
69         .long   0x03000102, 0x07040506, 0x0b08090a, 0x0f0c0d0e  ?inv
70         .long   0x0f0c0d0e, 0x03000102, 0x07040506, 0x0b08090a  ?inv
71         .long   0x0b08090a, 0x0f0c0d0e, 0x03000102, 0x07040506  ?inv
72         .long   0x07040506, 0x0b08090a, 0x0f0c0d0e, 0x03000102  ?inv
73 Lk_sr:          # sr
74         .long   0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f  ?inv
75         .long   0x00050a0f, 0x04090e03, 0x080d0207, 0x0c01060b  ?inv
76         .long   0x0009020b, 0x040d060f, 0x08010a03, 0x0c050e07  ?inv
77         .long   0x000d0a07, 0x04010e0b, 0x0805020f, 0x0c090603  ?inv
78
79 ##
80 ## "Hot" constants
81 ##
82 Lk_inv:         # inv, inva
83         .long   0xf001080d, 0x0f06050e, 0x020c0b0a, 0x09030704  ?rev
84         .long   0xf0070b0f, 0x060a0401, 0x09080502, 0x0c0e0d03  ?rev
85 Lk_ipt:         # input transform (lo, hi)
86         .long   0x00702a5a, 0x98e8b2c2, 0x08782252, 0x90e0baca  ?rev
87         .long   0x004d7c31, 0x7d30014c, 0x81ccfdb0, 0xfcb180cd  ?rev
88 Lk_sbo:         # sbou, sbot
89         .long   0x00c7bd6f, 0x176dd2d0, 0x78a802c5, 0x7abfaa15  ?rev
90         .long   0x006abb5f, 0xa574e4cf, 0xfa352b41, 0xd1901e8e  ?rev
91 Lk_sb1:         # sb1u, sb1t
92         .long   0x0023e2fa, 0x15d41836, 0xefd92e0d, 0xc1ccf73b  ?rev
93         .long   0x003e50cb, 0x8fe19bb1, 0x44f52a14, 0x6e7adfa5  ?rev
94 Lk_sb2:         # sb2u, sb2t
95         .long   0x0029e10a, 0x4088eb69, 0x4a2382ab, 0xc863a1c2  ?rev
96         .long   0x0024710b, 0xc6937ae2, 0xcd2f98bc, 0x55e9b75e  ?rev
97
98 ##
99 ##  Decryption stuff
100 ##
101 Lk_dipt:        # decryption input transform
102         .long   0x005f540b, 0x045b500f, 0x1a454e11, 0x1e414a15  ?rev
103         .long   0x00650560, 0xe683e386, 0x94f191f4, 0x72177712  ?rev
104 Lk_dsbo:        # decryption sbox final output
105         .long   0x0040f97e, 0x53ea8713, 0x2d3e94d4, 0xb96daac7  ?rev
106         .long   0x001d4493, 0x0f56d712, 0x9c8ec5d8, 0x59814bca  ?rev
107 Lk_dsb9:        # decryption sbox output *9*u, *9*t
108         .long   0x00d6869a, 0x53031c85, 0xc94c994f, 0x501fd5ca  ?rev
109         .long   0x0049d7ec, 0x89173bc0, 0x65a5fbb2, 0x9e2c5e72  ?rev
110 Lk_dsbd:        # decryption sbox output *D*u, *D*t
111         .long   0x00a2b1e6, 0xdfcc577d, 0x39442a88, 0x139b6ef5  ?rev
112         .long   0x00cbc624, 0xf7fae23c, 0xd3efde15, 0x0d183129  ?rev
113 Lk_dsbb:        # decryption sbox output *B*u, *B*t
114         .long   0x0042b496, 0x926422d0, 0x04d4f2b0, 0xf6462660  ?rev
115         .long   0x006759cd, 0xa69894c1, 0x6baa5532, 0x3e0cfff3  ?rev
116 Lk_dsbe:        # decryption sbox output *E*u, *E*t
117         .long   0x00d0d426, 0x9692f246, 0xb0f6b464, 0x04604222  ?rev
118         .long   0x00c1aaff, 0xcda6550c, 0x323e5998, 0x6bf36794  ?rev
119
120 ##
121 ##  Key schedule constants
122 ##
123 Lk_dksd:        # decryption key schedule: invskew x*D
124         .long   0x0047e4a3, 0x5d1ab9fe, 0xf9be1d5a, 0xa4e34007  ?rev
125         .long   0x008336b5, 0xf477c241, 0x1e9d28ab, 0xea69dc5f  ?rev
126 Lk_dksb:        # decryption key schedule: invskew x*B
127         .long   0x00d55085, 0x1fca4f9a, 0x994cc91c, 0x8653d603  ?rev
128         .long   0x004afcb6, 0xa7ed5b11, 0xc882347e, 0x6f2593d9  ?rev
129 Lk_dkse:        # decryption key schedule: invskew x*E + 0x63
130         .long   0x00d6c91f, 0xca1c03d5, 0x86504f99, 0x4c9a8553  ?rev
131         .long   0xe87bdc4f, 0x059631a2, 0x8714b320, 0x6af95ecd  ?rev
132 Lk_dks9:        # decryption key schedule: invskew x*9
133         .long   0x00a7d97e, 0xc86f11b6, 0xfc5b2582, 0x3493ed4a  ?rev
134         .long   0x00331427, 0x62517645, 0xcefddae9, 0xac9fb88b  ?rev
135
136 Lk_rcon:        # rcon
137         .long   0xb6ee9daf, 0xb991831f, 0x817d7c4d, 0x08982a70  ?asis
138 Lk_s63:
139         .long   0x5b5b5b5b, 0x5b5b5b5b, 0x5b5b5b5b, 0x5b5b5b5b  ?asis
140
141 Lk_opt:         # output transform
142         .long   0x0060b6d6, 0x29499fff, 0x0868bede, 0x214197f7  ?rev
143         .long   0x00ecbc50, 0x51bded01, 0xe00c5cb0, 0xb15d0de1  ?rev
144 Lk_deskew:      # deskew tables: inverts the sbox's "skew"
145         .long   0x00e3a447, 0x40a3e407, 0x1af9be5d, 0x5ab9fe1d  ?rev
146         .long   0x0069ea83, 0xdcb5365f, 0x771e9df4, 0xabc24128  ?rev
147 .align  5
148 Lconsts:
149         mflr    r0
150         bcl     20,31,\$+4
151         mflr    r12     #vvvvv "distance between . and _vpaes_consts
152         addi    r12,r12,-0x308
153         mtlr    r0
154         blr
155         .long   0
156         .byte   0,12,0x14,0,0,0,0,0
157 .asciz  "Vector Permutaion AES for AltiVec, Mike Hamburg (Stanford University)"
158 .align  6
159 ___
160 \f
161 my ($inptail,$inpperm,$outhead,$outperm,$outmask,$keyperm) = map("v$_",(26..31));
162 {
163 my ($inp,$out,$key) = map("r$_",(3..5));
164
165 my ($invlo,$invhi,$iptlo,$ipthi,$sbou,$sbot) = map("v$_",(10..15));
166 my ($sb1u,$sb1t,$sb2u,$sb2t) = map("v$_",(16..19));
167 my ($sb9u,$sb9t,$sbdu,$sbdt,$sbbu,$sbbt,$sbeu,$sbet)=map("v$_",(16..23));
168
169 $code.=<<___;
170 ##
171 ##  _aes_preheat
172 ##
173 ##  Fills register %r10 -> .aes_consts (so you can -fPIC)
174 ##  and %xmm9-%xmm15 as specified below.
175 ##
176 .align  4
177 _vpaes_encrypt_preheat:
178         mflr    r8
179         bl      Lconsts
180         mtlr    r8
181         li      r11, 0xc0               # Lk_inv
182         li      r10, 0xd0
183         li      r9,  0xe0               # Lk_ipt
184         li      r8,  0xf0
185         vxor    v7, v7, v7              # 0x00..00
186         vspltisb        v8,4            # 0x04..04
187         vspltisb        v9,0x0f         # 0x0f..0f
188         lvx     $invlo, r12, r11
189         li      r11, 0x100
190         lvx     $invhi, r12, r10
191         li      r10, 0x110
192         lvx     $iptlo, r12, r9
193         li      r9,  0x120
194         lvx     $ipthi, r12, r8
195         li      r8,  0x130
196         lvx     $sbou, r12, r11
197         li      r11, 0x140
198         lvx     $sbot, r12, r10
199         li      r10, 0x150
200         lvx     $sb1u, r12, r9
201         lvx     $sb1t, r12, r8
202         lvx     $sb2u, r12, r11
203         lvx     $sb2t, r12, r10
204         blr
205         .long   0
206         .byte   0,12,0x14,0,0,0,0,0
207
208 ##
209 ##  _aes_encrypt_core
210 ##
211 ##  AES-encrypt %xmm0.
212 ##
213 ##  Inputs:
214 ##     %xmm0 = input
215 ##     %xmm9-%xmm15 as in _vpaes_preheat
216 ##    (%rdx) = scheduled keys
217 ##
218 ##  Output in %xmm0
219 ##  Clobbers  %xmm1-%xmm6, %r9, %r10, %r11, %rax
220 ##
221 ##
222 .align 5
223 _vpaes_encrypt_core:
224         lwz     r8, 240($key)           # pull rounds
225         li      r9, 16
226         lvx     v5, 0, $key             # vmovdqu       (%r9),  %xmm5           # round0 key
227         li      r11, 0x10
228         lvx     v6, r9, $key
229         addi    r9, r9, 16
230         ?vperm  v5, v5, v6, $keyperm    # align round key
231         addi    r10, r11, 0x40
232         vsrb    v1, v0, v8              # vpsrlb        \$4,    %xmm0,  %xmm0
233         vperm   v0, $iptlo, $iptlo, v0  # vpshufb       %xmm1,  %xmm2,  %xmm1
234         vperm   v1, $ipthi, $ipthi, v1  # vpshufb       %xmm0,  %xmm3,  %xmm2
235         vxor    v0, v0, v5              # vpxor %xmm5,  %xmm1,  %xmm0
236         vxor    v0, v0, v1              # vpxor %xmm2,  %xmm0,  %xmm0
237         mtctr   r8
238         b       Lenc_entry
239
240 .align 4
241 Lenc_loop:
242         # middle of middle round
243         vperm   v4, $sb1t, v7, v2       # vpshufb       %xmm2,  %xmm13, %xmm4   # 4 = sb1u
244         lvx     v1, r12, r11            # vmovdqa       -0x40(%r11,%r10), %xmm1 # .Lk_mc_forward[]
245         addi    r11, r11, 16
246         vperm   v0, $sb1u, v7, v3       # vpshufb       %xmm3,  %xmm12, %xmm0   # 0 = sb1t
247         vxor    v4, v4, v5              # vpxor         %xmm5,  %xmm4,  %xmm4   # 4 = sb1u + k
248         andi.   r11, r11, 0x30          # and           \$0x30, %r11    # ... mod 4
249         vperm   v5, $sb2t, v7, v2       # vpshufb       %xmm2,  %xmm15, %xmm5   # 4 = sb2u
250         vxor    v0, v0, v4              # vpxor         %xmm4,  %xmm0,  %xmm0   # 0 = A
251         vperm   v2, $sb2u, v7, v3       # vpshufb       %xmm3,  %xmm14, %xmm2   # 2 = sb2t
252         lvx     v4, r12, r10            # vmovdqa       (%r11,%r10), %xmm4      # .Lk_mc_backward[]
253         addi    r10, r11, 0x40
254         vperm   v3, v0, v7, v1          # vpshufb       %xmm1,  %xmm0,  %xmm3   # 0 = B
255         vxor    v2, v2, v5              # vpxor         %xmm5,  %xmm2,  %xmm2   # 2 = 2A
256         vperm   v0, v0, v7, v4          # vpshufb       %xmm4,  %xmm0,  %xmm0   # 3 = D
257         vxor    v3, v3, v2              # vpxor         %xmm2,  %xmm3,  %xmm3   # 0 = 2A+B
258         vperm   v4, v3, v7, v1          # vpshufb       %xmm1,  %xmm3,  %xmm4   # 0 = 2B+C
259         vxor    v0, v0, v3              # vpxor         %xmm3,  %xmm0,  %xmm0   # 3 = 2A+B+D
260         vxor    v0, v0, v4              # vpxor         %xmm4,  %xmm0, %xmm0    # 0 = 2A+3B+C+D
261
262 Lenc_entry:
263         # top of round
264         vsrb    v1, v0, v8              # vpsrlb        \$4,    %xmm0,  %xmm0   # 1 = i
265         vperm   v5, $invhi, $invhi, v0  # vpshufb       %xmm1,  %xmm11, %xmm5   # 2 = a/k
266         vxor    v0, v0, v1              # vpxor         %xmm0,  %xmm1,  %xmm1   # 0 = j
267         vperm   v3, $invlo, $invlo, v1  # vpshufb       %xmm0,  %xmm10, %xmm3   # 3 = 1/i
268         vperm   v4, $invlo, $invlo, v0  # vpshufb       %xmm1,  %xmm10, %xmm4   # 4 = 1/j
269         vand    v0, v0, v9
270         vxor    v3, v3, v5              # vpxor         %xmm5,  %xmm3,  %xmm3   # 3 = iak = 1/i + a/k
271         vxor    v4, v4, v5              # vpxor         %xmm5,  %xmm4,  %xmm4   # 4 = jak = 1/j + a/k
272         vperm   v2, $invlo, v7, v3      # vpshufb       %xmm3,  %xmm10, %xmm2   # 2 = 1/iak
273         vmr     v5, v6
274         lvx     v6, r9, $key            # vmovdqu       (%r9), %xmm5
275         vperm   v3, $invlo, v7, v4      # vpshufb       %xmm4,  %xmm10, %xmm3   # 3 = 1/jak
276         addi    r9, r9, 16
277         vxor    v2, v2, v0              # vpxor         %xmm1,  %xmm2,  %xmm2   # 2 = io
278         ?vperm  v5, v5, v6, $keyperm    # align round key
279         vxor    v3, v3, v1              # vpxor         %xmm0,  %xmm3,  %xmm3   # 3 = jo
280         bdnz    Lenc_loop
281
282         # middle of last round
283         addi    r10, r11, 0x80
284                                         # vmovdqa       -0x60(%r10), %xmm4      # 3 : sbou      .Lk_sbo
285                                         # vmovdqa       -0x50(%r10), %xmm0      # 0 : sbot      .Lk_sbo+16
286         vperm   v4, $sbou, v7, v2       # vpshufb       %xmm2,  %xmm4,  %xmm4   # 4 = sbou
287         lvx     v1, r12, r10            # vmovdqa       0x40(%r11,%r10), %xmm1  # .Lk_sr[]
288         vperm   v0, $sbot, v7, v3       # vpshufb       %xmm3,  %xmm0,  %xmm0   # 0 = sb1t
289         vxor    v4, v4, v5              # vpxor         %xmm5,  %xmm4,  %xmm4   # 4 = sb1u + k
290         vxor    v0, v0, v4              # vpxor         %xmm4,  %xmm0,  %xmm0   # 0 = A
291         vperm   v0, v0, v7, v1          # vpshufb       %xmm1,  %xmm0,  %xmm0
292         blr
293         .long   0
294         .byte   0,12,0x14,0,0,0,0,0
295
296 .globl  .vpaes_encrypt
297 .align  5
298 .vpaes_encrypt:
299         $STU    $sp,-$FRAME($sp)
300         li      r10,`15+6*$SIZE_T`
301         li      r11,`31+6*$SIZE_T`
302         mflr    r6
303         mfspr   r7, 256                 # save vrsave
304         stvx    v20,r10,$sp
305         addi    r10,r10,16
306         stvx    v21,r11,$sp
307         addi    r11,r11,16
308         stvx    v22,r10,$sp
309         addi    r10,r10,16
310         stvx    v23,r11,$sp
311         addi    r11,r11,16
312         stvx    v24,r10,$sp
313         addi    r10,r10,16
314         stvx    v25,r11,$sp
315         addi    r11,r11,16
316         stvx    v26,r10,$sp
317         addi    r10,r10,16
318         stvx    v27,r11,$sp
319         addi    r11,r11,16
320         stvx    v28,r10,$sp
321         addi    r10,r10,16
322         stvx    v29,r11,$sp
323         addi    r11,r11,16
324         stvx    v30,r10,$sp
325         stvx    v31,r11,$sp
326         lwz     r7,`$FRAME-4`($sp)      # save vrsave
327         li      r0, -1
328         $PUSH   r6,`$FRAME+$LRSAVE`($sp)
329         mtspr   256, r0                 # preserve all AltiVec registers
330
331         bl      _vpaes_encrypt_preheat
332
333         ?lvsl   $inpperm, 0, $inp       # prepare for unaligned access
334         lvx     v0, 0, $inp
335         addi    $inp, $inp, 15          # 15 is not a typo
336          ?lvsr  $outperm, 0, $out
337         ?lvsl   $keyperm, 0, $key       # prepare for unaligned access
338          vnor   $outmask, v7, v7        # 0xff..ff
339         lvx     $inptail, 0, $inp       # redundant in aligned case
340          ?vperm $outmask, v7, $outmask, $outperm
341          lvx    $outhead, 0, $out
342         ?vperm  v0, v0, $inptail, $inpperm
343
344         bl      _vpaes_encrypt_core
345
346         vperm   v0, v0, v0, $outperm    # rotate right/left
347         vsel    v1, $outhead, v0, $outmask
348         vmr     $outhead, v0
349         stvx    v1, 0, $out
350         addi    $out, $out, 15          # 15 is not a typo
351         ########
352
353         lvx     v1, 0, $out             # redundant in aligned case
354         vsel    v1, $outhead, v1, $outmask
355         stvx    v1, 0, $out
356
357         li      r10,`15+6*$SIZE_T`
358         li      r11,`31+6*$SIZE_T`
359         mtlr    r6
360         mtspr   256, r7                 # restore vrsave
361         lvx     v20,r10,$sp
362         addi    r10,r10,16
363         lvx     v21,r11,$sp
364         addi    r11,r11,16
365         lvx     v22,r10,$sp
366         addi    r10,r10,16
367         lvx     v23,r11,$sp
368         addi    r11,r11,16
369         lvx     v24,r10,$sp
370         addi    r10,r10,16
371         lvx     v25,r11,$sp
372         addi    r11,r11,16
373         lvx     v26,r10,$sp
374         addi    r10,r10,16
375         lvx     v27,r11,$sp
376         addi    r11,r11,16
377         lvx     v28,r10,$sp
378         addi    r10,r10,16
379         lvx     v29,r11,$sp
380         addi    r11,r11,16
381         lvx     v30,r10,$sp
382         lvx     v31,r11,$sp
383         addi    $sp,$sp,$FRAME
384         blr
385         .long   0
386         .byte   0,12,0x04,1,0x80,0,3,0
387         .long   0
388 .size   .vpaes_encrypt,.-.vpaes_encrypt
389
390 .align  4
391 _vpaes_decrypt_preheat:
392         mflr    r8
393         bl      Lconsts
394         mtlr    r8
395         li      r11, 0xc0               # Lk_inv
396         li      r10, 0xd0
397         li      r9,  0x160              # Ldipt
398         li      r8,  0x170
399         vxor    v7, v7, v7              # 0x00..00
400         vspltisb        v8,4            # 0x04..04
401         vspltisb        v9,0x0f         # 0x0f..0f
402         lvx     $invlo, r12, r11
403         li      r11, 0x180
404         lvx     $invhi, r12, r10
405         li      r10, 0x190
406         lvx     $iptlo, r12, r9
407         li      r9,  0x1a0
408         lvx     $ipthi, r12, r8
409         li      r8,  0x1b0
410         lvx     $sbou, r12, r11
411         li      r11, 0x1c0
412         lvx     $sbot, r12, r10
413         li      r10, 0x1d0
414         lvx     $sb9u, r12, r9
415         li      r9,  0x1e0
416         lvx     $sb9t, r12, r8
417         li      r8,  0x1f0
418         lvx     $sbdu, r12, r11
419         li      r11, 0x200
420         lvx     $sbdt, r12, r10
421         li      r10, 0x210
422         lvx     $sbbu, r12, r9
423         lvx     $sbbt, r12, r8
424         lvx     $sbeu, r12, r11
425         lvx     $sbet, r12, r10
426         blr
427         .long   0
428         .byte   0,12,0x14,0,0,0,0,0
429
430 ##
431 ##  Decryption core
432 ##
433 ##  Same API as encryption core.
434 ##
435 .align  4
436 _vpaes_decrypt_core:
437         lwz     r8, 240($key)           # pull rounds
438         li      r9, 16
439         lvx     v5, 0, $key             # vmovdqu       (%r9),  %xmm4           # round0 key
440         li      r11, 0x30
441         lvx     v6, r9, $key
442         addi    r9, r9, 16
443         ?vperm  v5, v5, v6, $keyperm    # align round key
444         vsrb    v1, v0, v8              # vpsrlb        \$4,    %xmm0,  %xmm0
445         vperm   v0, $iptlo, $iptlo, v0  # vpshufb       %xmm1,  %xmm2,  %xmm2
446         vperm   v1, $ipthi, $ipthi, v1  # vpshufb       %xmm0,  %xmm1,  %xmm0
447         vxor    v0, v0, v5              # vpxor %xmm4,  %xmm2,  %xmm2
448         vxor    v0, v0, v1              # vpxor %xmm2,  %xmm0,  %xmm0
449         mtctr   r8
450         b       Ldec_entry
451
452 .align 4
453 Ldec_loop:
454 #
455 #  Inverse mix columns
456 #
457         lvx     v0, r12, r11            # v5 and v0 are flipped
458                                         # vmovdqa       -0x20(%r10),%xmm4               # 4 : sb9u
459                                         # vmovdqa       -0x10(%r10),%xmm1               # 0 : sb9t
460         vperm   v4, $sb9u, v7, v2       # vpshufb       %xmm2,  %xmm4,  %xmm4           # 4 = sb9u
461         subi    r11, r11, 16
462         vperm   v1, $sb9t, v7, v3       # vpshufb       %xmm3,  %xmm1,  %xmm1           # 0 = sb9t
463         andi.   r11, r11, 0x30
464         vxor    v5, v5, v4              # vpxor         %xmm4,  %xmm0,  %xmm0
465                                         # vmovdqa       0x00(%r10),%xmm4                # 4 : sbdu
466         vxor    v5, v5, v1              # vpxor         %xmm1,  %xmm0,  %xmm0           # 0 = ch
467                                         # vmovdqa       0x10(%r10),%xmm1                # 0 : sbdt
468
469         vperm   v4, $sbdu, v7, v2       # vpshufb       %xmm2,  %xmm4,  %xmm4           # 4 = sbdu
470         vperm   v5, v5, v7, v0          # vpshufb       %xmm5,  %xmm0,  %xmm0           # MC ch
471         vperm   v1, $sbdt, v7, v3       # vpshufb       %xmm3,  %xmm1,  %xmm1           # 0 = sbdt
472         vxor    v5, v5, v4              # vpxor         %xmm4,  %xmm0,  %xmm0           # 4 = ch
473                                         # vmovdqa       0x20(%r10),     %xmm4           # 4 : sbbu
474         vxor    v5, v5, v1              # vpxor         %xmm1,  %xmm0,  %xmm0           # 0 = ch
475                                         # vmovdqa       0x30(%r10),     %xmm1           # 0 : sbbt
476
477         vperm   v4, $sbbu, v7, v2       # vpshufb       %xmm2,  %xmm4,  %xmm4           # 4 = sbbu
478         vperm   v5, v5, v7, v0          # vpshufb       %xmm5,  %xmm0,  %xmm0           # MC ch
479         vperm   v1, $sbbt, v7, v3       # vpshufb       %xmm3,  %xmm1,  %xmm1           # 0 = sbbt
480         vxor    v5, v5, v4              # vpxor         %xmm4,  %xmm0,  %xmm0           # 4 = ch
481                                         # vmovdqa       0x40(%r10),     %xmm4           # 4 : sbeu
482         vxor    v5, v5, v1              # vpxor         %xmm1,  %xmm0,  %xmm0           # 0 = ch
483                                         # vmovdqa       0x50(%r10),     %xmm1           # 0 : sbet
484
485         vperm   v4, $sbeu, v7, v2       # vpshufb       %xmm2,  %xmm4,  %xmm4           # 4 = sbeu
486         vperm   v5, v5, v7, v0          # vpshufb       %xmm5,  %xmm0,  %xmm0           # MC ch
487         vperm   v1, $sbet, v7, v3       # vpshufb       %xmm3,  %xmm1,  %xmm1           # 0 = sbet
488         vxor    v0, v5, v4              # vpxor         %xmm4,  %xmm0,  %xmm0           # 4 = ch
489         vxor    v0, v0, v1              # vpxor         %xmm1,  %xmm0,  %xmm0           # 0 = ch
490
491 Ldec_entry:
492         # top of round
493         vsrb    v1, v0, v8              # vpsrlb        \$4,    %xmm0,  %xmm0   # 1 = i
494         vperm   v2, $invhi, $invhi, v0  # vpshufb       %xmm1,  %xmm11, %xmm2   # 2 = a/k
495         vxor    v0, v0, v1              # vpxor         %xmm0,  %xmm1,  %xmm1   # 0 = j
496         vperm   v3, $invlo, $invlo, v1  # vpshufb       %xmm0,  %xmm10, %xmm3   # 3 = 1/i
497         vperm   v4, $invlo, $invlo, v0  # vpshufb       %xmm1,  %xmm10, %xmm4   # 4 = 1/j
498         vand    v0, v0, v9
499         vxor    v3, v3, v2              # vpxor         %xmm2,  %xmm3,  %xmm3   # 3 = iak = 1/i + a/k
500         vxor    v4, v4, v2              # vpxor         %xmm2,  %xmm4,  %xmm4   # 4 = jak = 1/j + a/k
501         vperm   v2, $invlo, v7, v3      # vpshufb       %xmm3,  %xmm10, %xmm2   # 2 = 1/iak
502         vmr     v5, v6
503         lvx     v6, r9, $key            # vmovdqu       (%r9),  %xmm0
504         vperm   v3, $invlo, v7, v4      # vpshufb       %xmm4,  %xmm10, %xmm3   # 3 = 1/jak
505         addi    r9, r9, 16
506         vxor    v2, v2, v0              # vpxor         %xmm1,  %xmm2,  %xmm2   # 2 = io
507         ?vperm  v5, v5, v6, $keyperm    # align round key
508         vxor    v3, v3, v1              # vpxor         %xmm0,  %xmm3,  %xmm3   # 3 = jo
509         bdnz    Ldec_loop
510
511         # middle of last round
512         addi    r10, r11, 0x80
513                                         # vmovdqa       0x60(%r10),     %xmm4   # 3 : sbou
514         vperm   v4, $sbou, v7, v2       # vpshufb       %xmm2,  %xmm4,  %xmm4   # 4 = sbou
515                                         # vmovdqa       0x70(%r10),     %xmm1   # 0 : sbot
516         lvx     v2, r12, r10            # vmovdqa       -0x160(%r11),   %xmm2   # .Lk_sr-.Lk_dsbd=-0x160
517         vperm   v1, $sbot, v7, v3       # vpshufb       %xmm3,  %xmm1,  %xmm1   # 0 = sb1t
518         vxor    v4, v4, v5              # vpxor         %xmm0,  %xmm4,  %xmm4   # 4 = sb1u + k
519         vxor    v0, v1, v4              # vpxor         %xmm4,  %xmm1,  %xmm0   # 0 = A
520         vperm   v0, v0, v7, v2          # vpshufb       %xmm2,  %xmm0,  %xmm0
521         blr
522         .long   0
523         .byte   0,12,0x14,0,0,0,0,0
524
525 .globl  .vpaes_decrypt
526 .align  5
527 .vpaes_decrypt:
528         $STU    $sp,-$FRAME($sp)
529         li      r10,`15+6*$SIZE_T`
530         li      r11,`31+6*$SIZE_T`
531         mflr    r6
532         mfspr   r7, 256                 # save vrsave
533         stvx    v20,r10,$sp
534         addi    r10,r10,16
535         stvx    v21,r11,$sp
536         addi    r11,r11,16
537         stvx    v22,r10,$sp
538         addi    r10,r10,16
539         stvx    v23,r11,$sp
540         addi    r11,r11,16
541         stvx    v24,r10,$sp
542         addi    r10,r10,16
543         stvx    v25,r11,$sp
544         addi    r11,r11,16
545         stvx    v26,r10,$sp
546         addi    r10,r10,16
547         stvx    v27,r11,$sp
548         addi    r11,r11,16
549         stvx    v28,r10,$sp
550         addi    r10,r10,16
551         stvx    v29,r11,$sp
552         addi    r11,r11,16
553         stvx    v30,r10,$sp
554         stvx    v31,r11,$sp
555         lwz     r7,`$FRAME-4`($sp)      # save vrsave
556         li      r0, -1
557         $PUSH   r6,`$FRAME+$LRSAVE`($sp)
558         mtspr   256, r0                 # preserve all AltiVec registers
559
560         bl      _vpaes_decrypt_preheat
561
562         ?lvsl   $inpperm, 0, $inp       # prepare for unaligned access
563         lvx     v0, 0, $inp
564         addi    $inp, $inp, 15          # 15 is not a typo
565          ?lvsr  $outperm, 0, $out
566         ?lvsl   $keyperm, 0, $key
567          vnor   $outmask, v7, v7        # 0xff..ff
568         lvx     $inptail, 0, $inp       # redundant in aligned case
569          ?vperm $outmask, v7, $outmask, $outperm
570          lvx    $outhead, 0, $out
571         ?vperm  v0, v0, $inptail, $inpperm
572
573         bl      _vpaes_decrypt_core
574
575         vperm   v0, v0, v0, $outperm    # rotate right/left
576         vsel    v1, $outhead, v0, $outmask
577         vmr     $outhead, v0
578         stvx    v1, 0, $out
579         addi    $out, $out, 15          # 15 is not a typo
580         ########
581
582         lvx     v1, 0, $out             # redundant in aligned case
583         vsel    v1, $outhead, v1, $outmask
584         stvx    v1, 0, $out
585
586         li      r10,`15+6*$SIZE_T`
587         li      r11,`31+6*$SIZE_T`
588         mtlr    r6
589         mtspr   256, r7                 # restore vrsave
590         lvx     v20,r10,$sp
591         addi    r10,r10,16
592         lvx     v21,r11,$sp
593         addi    r11,r11,16
594         lvx     v22,r10,$sp
595         addi    r10,r10,16
596         lvx     v23,r11,$sp
597         addi    r11,r11,16
598         lvx     v24,r10,$sp
599         addi    r10,r10,16
600         lvx     v25,r11,$sp
601         addi    r11,r11,16
602         lvx     v26,r10,$sp
603         addi    r10,r10,16
604         lvx     v27,r11,$sp
605         addi    r11,r11,16
606         lvx     v28,r10,$sp
607         addi    r10,r10,16
608         lvx     v29,r11,$sp
609         addi    r11,r11,16
610         lvx     v30,r10,$sp
611         lvx     v31,r11,$sp
612         addi    $sp,$sp,$FRAME
613         blr
614         .long   0
615         .byte   0,12,0x04,1,0x80,0,3,0
616         .long   0
617 .size   .vpaes_decrypt,.-.vpaes_decrypt
618
619 .globl  .vpaes_cbc_encrypt
620 .align  5
621 .vpaes_cbc_encrypt:
622         $STU    $sp,-`($FRAME+2*$SIZE_T)`($sp)
623         mflr    r0
624         li      r10,`15+6*$SIZE_T`
625         li      r11,`31+6*$SIZE_T`
626         mfspr   r12, 256
627         stvx    v20,r10,$sp
628         addi    r10,r10,16
629         stvx    v21,r11,$sp
630         addi    r11,r11,16
631         stvx    v22,r10,$sp
632         addi    r10,r10,16
633         stvx    v23,r11,$sp
634         addi    r11,r11,16
635         stvx    v24,r10,$sp
636         addi    r10,r10,16
637         stvx    v25,r11,$sp
638         addi    r11,r11,16
639         stvx    v26,r10,$sp
640         addi    r10,r10,16
641         stvx    v27,r11,$sp
642         addi    r11,r11,16
643         stvx    v28,r10,$sp
644         addi    r10,r10,16
645         stvx    v29,r11,$sp
646         addi    r11,r11,16
647         stvx    v30,r10,$sp
648         stvx    v31,r11,$sp
649         lwz     r12,`$FRAME-4`($sp)     # save vrsave
650         $PUSH   r30,`$FRAME+$SIZE_T*0`($sp)
651         $PUSH   r31,`$FRAME+$SIZE_T*1`($sp)
652         li      r9, 16
653         $PUSH   r0, `$FRAME+$SIZE_T*2+$LRSAVE`($sp)
654
655         sub.    r30, r5, r9             # copy length-16
656         mr      r5, r6                  # copy pointer to key
657         mr      r31, r7                 # copy pointer to iv
658         blt     Lcbc_abort
659         cmpwi   r8, 0                   # test direction
660         li      r6, -1
661         mr      r7, r12                 # copy vrsave
662         mtspr   256, r6                 # preserve all AltiVec registers
663
664         lvx     v24, 0, r31             # load [potentially unaligned] iv
665         li      r9, 15
666         ?lvsl   $inpperm, 0, r31
667         lvx     v25, r9, r31
668         ?vperm  v24, v24, v25, $inpperm
669
670         neg     r8, $inp                # prepare for unaligned access
671          vxor   v7, v7, v7
672         ?lvsl   $keyperm, 0, $key
673          ?lvsr  $outperm, 0, $out
674         ?lvsr   $inpperm, 0, r8         # -$inp
675          vnor   $outmask, v7, v7        # 0xff..ff
676         lvx     $inptail, 0, $inp
677          ?vperm $outmask, v7, $outmask, $outperm
678         addi    $inp, $inp, 15          # 15 is not a typo
679          lvx    $outhead, 0, $out
680
681         beq     Lcbc_decrypt
682
683         bl      _vpaes_encrypt_preheat
684         li      r0, 16
685
686 Lcbc_enc_loop:
687         vmr     v0, $inptail
688         lvx     $inptail, 0, $inp
689         addi    $inp, $inp, 16
690         ?vperm  v0, v0, $inptail, $inpperm
691         vxor    v0, v0, v24             # ^= iv
692
693         bl      _vpaes_encrypt_core
694
695         vmr     v24, v0                 # put aside iv
696         sub.    r30, r30, r0            # len -= 16
697         vperm   v0, v0, v0, $outperm    # rotate right/left
698         vsel    v1, $outhead, v0, $outmask
699         vmr     $outhead, v0
700         stvx    v1, 0, $out
701         addi    $out, $out, 16
702         bge     Lcbc_enc_loop
703
704         b       Lcbc_done
705
706 .align  5
707 Lcbc_decrypt:
708         bl      _vpaes_decrypt_preheat
709         li      r0, 16
710
711 Lcbc_dec_loop:
712         vmr     v0, $inptail
713         lvx     $inptail, 0, $inp
714         addi    $inp, $inp, 16
715         ?vperm  v0, v0, $inptail, $inpperm
716         vmr     v25, v0                 # put aside input
717
718         bl      _vpaes_decrypt_core
719
720         vxor    v0, v0, v24             # ^= iv
721         vmr     v24, v25
722         sub.    r30, r30, r0            # len -= 16
723         vperm   v0, v0, v0, $outperm    # rotate right/left
724         vsel    v1, $outhead, v0, $outmask
725         vmr     $outhead, v0
726         stvx    v1, 0, $out
727         addi    $out, $out, 16
728         bge     Lcbc_dec_loop
729
730 Lcbc_done:
731         addi    $out, $out, -1
732         lvx     v1, 0, $out             # redundant in aligned case
733         vsel    v1, $outhead, v1, $outmask
734         stvx    v1, 0, $out
735
736         neg     r8, r31                 # write [potentially unaligned] iv
737         ?lvsl   $outperm, 0, r8
738         li      r6, 15
739         vnor    $outmask, v7, v7        # 0xff..ff
740         ?vperm  $outmask, v7, $outmask, $outperm
741         lvx     $outhead, 0, r31
742         vperm   v24, v24, v24, $outperm # rotate right/left
743         vsel    v0, $outhead, v24, $outmask
744         lvx     v1, r6, r31
745         stvx    v0, 0, r31
746         vsel    v1, v24, v1, $outmask
747         stvx    v1, r6, r31
748
749         mtspr   256, r7                 # restore vrsave
750         li      r10,`15+6*$SIZE_T`
751         li      r11,`31+6*$SIZE_T`
752         lvx     v20,r10,$sp
753         addi    r10,r10,16
754         lvx     v21,r11,$sp
755         addi    r11,r11,16
756         lvx     v22,r10,$sp
757         addi    r10,r10,16
758         lvx     v23,r11,$sp
759         addi    r11,r11,16
760         lvx     v24,r10,$sp
761         addi    r10,r10,16
762         lvx     v25,r11,$sp
763         addi    r11,r11,16
764         lvx     v26,r10,$sp
765         addi    r10,r10,16
766         lvx     v27,r11,$sp
767         addi    r11,r11,16
768         lvx     v28,r10,$sp
769         addi    r10,r10,16
770         lvx     v29,r11,$sp
771         addi    r11,r11,16
772         lvx     v30,r10,$sp
773         lvx     v31,r11,$sp
774 Lcbc_abort:
775         $POP    r0, `$FRAME+$SIZE_T*2+$LRSAVE`($sp)
776         $POP    r30,`$FRAME+$SIZE_T*0`($sp)
777         $POP    r31,`$FRAME+$SIZE_T*1`($sp)
778         mtlr    r0
779         addi    $sp,$sp,`$FRAME+$SIZE_T*2`
780         blr
781         .long   0
782         .byte   0,12,0x04,1,0x80,2,6,0
783         .long   0
784 .size   .vpaes_cbc_encrypt,.-.vpaes_cbc_encrypt
785 ___
786 }\f
787 {
788 my ($inp,$bits,$out)=map("r$_",(3..5));
789 my $dir="cr1";
790 my ($invlo,$invhi,$iptlo,$ipthi,$rcon) = map("v$_",(10..13,24));
791
792 $code.=<<___;
793 ########################################################
794 ##                                                    ##
795 ##                  AES key schedule                  ##
796 ##                                                    ##
797 ########################################################
798 .align  4
799 _vpaes_key_preheat:
800         mflr    r8
801         bl      Lconsts
802         mtlr    r8
803         li      r11, 0xc0               # Lk_inv
804         li      r10, 0xd0
805         li      r9,  0xe0               # L_ipt
806         li      r8,  0xf0
807
808         vspltisb        v8,4            # 0x04..04
809         vxor    v9,v9,v9                # 0x00..00
810         lvx     $invlo, r12, r11        # Lk_inv
811         li      r11, 0x120
812         lvx     $invhi, r12, r10
813         li      r10, 0x130
814         lvx     $iptlo, r12, r9         # Lk_ipt
815         li      r9, 0x220
816         lvx     $ipthi, r12, r8
817         li      r8, 0x230
818
819         lvx     v14, r12, r11           # Lk_sb1
820         li      r11, 0x240
821         lvx     v15, r12, r10
822         li      r10, 0x250
823
824         lvx     v16, r12, r9            # Lk_dksd
825         li      r9, 0x260
826         lvx     v17, r12, r8
827         li      r8, 0x270
828         lvx     v18, r12, r11           # Lk_dksb
829         li      r11, 0x280
830         lvx     v19, r12, r10
831         li      r10, 0x290
832         lvx     v20, r12, r9            # Lk_dkse
833         li      r9, 0x2a0
834         lvx     v21, r12, r8
835         li      r8, 0x2b0
836         lvx     v22, r12, r11           # Lk_dks9
837         lvx     v23, r12, r10
838
839         lvx     v24, r12, r9            # Lk_rcon
840         lvx     v25, 0, r12             # Lk_mc_forward[0]
841         lvx     v26, r12, r8            # Lks63
842         blr
843         .long   0
844         .byte   0,12,0x14,0,0,0,0,0
845
846 .align  4
847 _vpaes_schedule_core:
848         mflr    r7
849
850         bl      _vpaes_key_preheat      # load the tables
851
852         #lvx    v0, 0, $inp             # vmovdqu       (%rdi), %xmm0           # load key (unaligned)
853         neg     r8, $inp                # prepare for unaligned access
854         lvx     v0, 0, $inp
855         addi    $inp, $inp, 15          # 15 is not typo
856         ?lvsr   $inpperm, 0, r8         # -$inp
857         lvx     v6, 0, $inp             # v6 serves as inptail
858         addi    $inp, $inp, 8
859         ?vperm  v0, v0, v6, $inpperm
860
861         # input transform
862         vmr     v3, v0                  # vmovdqa       %xmm0,  %xmm3
863         bl      _vpaes_schedule_transform
864         vmr     v7, v0                  # vmovdqa       %xmm0,  %xmm7
865
866         bne     $dir, Lschedule_am_decrypting
867
868         # encrypting, output zeroth round key after transform
869         li      r8, 0x30                # mov   \$0x30,%r8d
870         addi    r10, r12, 0x80          # lea   .Lk_sr(%rip),%r10
871
872         ?lvsr   $outperm, 0, $out       # prepare for unaligned access
873         vnor    $outmask, v9, v9        # 0xff..ff
874         lvx     $outhead, 0, $out
875         ?vperm  $outmask, v9, $outmask, $outperm
876
877         #stvx   v0, 0, $out             # vmovdqu       %xmm0,  (%rdx)
878         vperm   v1, v0, v0, $outperm    # rotate right/left
879         vsel    v2, $outhead, v1, $outmask
880         vmr     $outhead, v1
881         stvx    v2, 0, $out
882         b       Lschedule_go
883
884 Lschedule_am_decrypting:
885         srwi    r8, $bits, 1            # shr   \$1,%r8d
886         andi.   r8, r8, 32              # and   \$32,%r8d
887         xori    r8, r8, 32              # xor   \$32,%r8d       # nbits==192?0:32
888         addi    r10, r12, 0x80          # lea   .Lk_sr(%rip),%r10
889         # decrypting, output zeroth round key after shiftrows
890         lvx     v1, r8, r10             # vmovdqa       (%r8,%r10),     %xmm1
891         vperm   v4, v3, v3, v1          # vpshufb       %xmm1,  %xmm3,  %xmm3
892
893         neg     r0, $out                # prepare for unaligned access
894         ?lvsl   $outperm, 0, r0
895         addi    $out, $out, 15          # 15 is not typo
896         vnor    $outmask, v9, v9        # 0xff..ff
897         lvx     $outhead, 0, $out
898         ?vperm  $outmask, $outmask, v9, $outperm
899
900         #stvx   v4, 0, $out             # vmovdqu       %xmm3,  (%rdx)
901         vperm   v4, v4, v4, $outperm    # rotate right/left
902         vsel    v2, $outhead, v4, $outmask
903         vmr     $outhead, v4
904         stvx    v2, 0, $out
905         xori    r8, r8, 0x30            # xor   \$0x30, %r8
906
907 Lschedule_go:
908         cmplwi  $bits, 192              # cmp   \$192,  %esi
909         bgt     Lschedule_256
910         beq     Lschedule_192
911         # 128: fall though
912
913 ##
914 ##  .schedule_128
915 ##
916 ##  128-bit specific part of key schedule.
917 ##
918 ##  This schedule is really simple, because all its parts
919 ##  are accomplished by the subroutines.
920 ##
921 Lschedule_128:
922         li      r0, 10                  # mov   \$10, %esi
923         mtctr   r0
924
925 Loop_schedule_128:
926         bl      _vpaes_schedule_round
927         bdz     Lschedule_mangle_last   # dec   %esi
928         bl      _vpaes_schedule_mangle  # write output
929         b       Loop_schedule_128
930
931 ##
932 ##  .aes_schedule_192
933 ##
934 ##  192-bit specific part of key schedule.
935 ##
936 ##  The main body of this schedule is the same as the 128-bit
937 ##  schedule, but with more smearing.  The long, high side is
938 ##  stored in %xmm7 as before, and the short, low side is in
939 ##  the high bits of %xmm6.
940 ##
941 ##  This schedule is somewhat nastier, however, because each
942 ##  round produces 192 bits of key material, or 1.5 round keys.
943 ##  Therefore, on each cycle we do 2 rounds and produce 3 round
944 ##  keys.
945 ##
946 .align  4
947 Lschedule_192:
948         li      r0, 4                   # mov   \$4,    %esi
949         lvx     v0, 0, $inp
950         ?vperm  v0, v6, v0, $inpperm
951         ?vsldoi v0, v3, v0, 8           # vmovdqu       8(%rdi),%xmm0           # load key part 2 (very unaligned)
952         bl      _vpaes_schedule_transform       # input transform
953         ?vsldoi v6, v0, v9, 8
954         ?vsldoi v6, v9, v6, 8           # clobber "low" side with zeros
955         mtctr   r0
956
957 Loop_schedule_192:
958         bl      _vpaes_schedule_round
959         ?vsldoi v0, v6, v0, 8           # vpalignr      \$8,%xmm6,%xmm0,%xmm0
960         bl      _vpaes_schedule_mangle  # save key n
961         bl      _vpaes_schedule_192_smear
962         bl      _vpaes_schedule_mangle  # save key n+1
963         bl      _vpaes_schedule_round
964         bdz     Lschedule_mangle_last   # dec   %esi
965         bl      _vpaes_schedule_mangle  # save key n+2
966         bl      _vpaes_schedule_192_smear
967         b       Loop_schedule_192
968
969 ##
970 ##  .aes_schedule_256
971 ##
972 ##  256-bit specific part of key schedule.
973 ##
974 ##  The structure here is very similar to the 128-bit
975 ##  schedule, but with an additional "low side" in
976 ##  %xmm6.  The low side's rounds are the same as the
977 ##  high side's, except no rcon and no rotation.
978 ##
979 .align  4
980 Lschedule_256:
981         li      r0, 7                   # mov   \$7, %esi
982         addi    $inp, $inp, 8
983         lvx     v0, 0, $inp             # vmovdqu       16(%rdi),%xmm0          # load key part 2 (unaligned)
984         ?vperm  v0, v6, v0, $inpperm
985         bl      _vpaes_schedule_transform       # input transform
986         mtctr   r0
987
988 Loop_schedule_256:
989         bl      _vpaes_schedule_mangle  # output low result
990         vmr     v6, v0                  # vmovdqa       %xmm0,  %xmm6           # save cur_lo in xmm6
991
992         # high round
993         bl      _vpaes_schedule_round
994         bdz     Lschedule_mangle_last   # dec   %esi
995         bl      _vpaes_schedule_mangle  
996
997         # low round. swap xmm7 and xmm6
998         ?vspltw v0, v0, 3               # vpshufd       \$0xFF, %xmm0,  %xmm0
999         vmr     v5, v7                  # vmovdqa       %xmm7,  %xmm5
1000         vmr     v7, v6                  # vmovdqa       %xmm6,  %xmm7
1001         bl      _vpaes_schedule_low_round
1002         vmr     v7, v5                  # vmovdqa       %xmm5,  %xmm7
1003         
1004         b       Loop_schedule_256
1005 ##
1006 ##  .aes_schedule_mangle_last
1007 ##
1008 ##  Mangler for last round of key schedule
1009 ##  Mangles %xmm0
1010 ##    when encrypting, outputs out(%xmm0) ^ 63
1011 ##    when decrypting, outputs unskew(%xmm0)
1012 ##
1013 ##  Always called right before return... jumps to cleanup and exits
1014 ##
1015 .align  4
1016 Lschedule_mangle_last:
1017         # schedule last round key from xmm0
1018         li      r11, 0x2e0              # lea   .Lk_deskew(%rip),%r11
1019         li      r9,  0x2f0
1020         bne     $dir, Lschedule_mangle_last_dec
1021
1022         # encrypting
1023         lvx     v1, r8, r10             # vmovdqa       (%r8,%r10),%xmm1
1024         li      r11, 0x2c0              # lea           .Lk_opt(%rip),  %r11    # prepare to output transform
1025         li      r9,  0x2d0              # prepare to output transform
1026         vperm   v0, v0, v0, v1          # vpshufb       %xmm1,  %xmm0,  %xmm0   # output permute
1027
1028         lvx     $iptlo, r11, r12        # reload $ipt
1029         lvx     $ipthi, r9, r12
1030         addi    $out, $out, 16          # add   \$16,   %rdx
1031         vxor    v0, v0, v26             # vpxor         .Lk_s63(%rip),  %xmm0,  %xmm0
1032         bl      _vpaes_schedule_transform       # output transform
1033
1034         #stvx   v0, r0, $out            # vmovdqu       %xmm0,  (%rdx)          # save last key
1035         vperm   v0, v0, v0, $outperm    # rotate right/left
1036         vsel    v2, $outhead, v0, $outmask
1037         vmr     $outhead, v0
1038         stvx    v2, 0, $out
1039
1040         addi    $out, $out, 15          # 15 is not typo
1041         lvx     v1, 0, $out             # redundant in aligned case
1042         vsel    v1, $outhead, v1, $outmask
1043         stvx    v1, 0, $out
1044         b       Lschedule_mangle_done
1045
1046 .align  4
1047 Lschedule_mangle_last_dec:
1048         lvx     $iptlo, r11, r12        # reload $ipt
1049         lvx     $ipthi, r9,  r12
1050         addi    $out, $out, -16         # add   \$-16,  %rdx 
1051         vxor    v0, v0, v26             # vpxor .Lk_s63(%rip),  %xmm0,  %xmm0
1052         bl      _vpaes_schedule_transform       # output transform
1053
1054         #stvx   v0, r0, $out            # vmovdqu       %xmm0,  (%rdx)          # save last key
1055         vperm   v0, v0, v0, $outperm    # rotate right/left
1056         vsel    v2, $outhead, v0, $outmask
1057         vmr     $outhead, v0
1058         stvx    v2, 0, $out
1059
1060         addi    $out, $out, -15         # -15 is not typo
1061         lvx     v1, 0, $out             # redundant in aligned case
1062         vsel    v1, $outhead, v1, $outmask
1063         stvx    v1, 0, $out
1064
1065 Lschedule_mangle_done:
1066         mtlr    r7
1067         # cleanup
1068         vxor    v0, v0, v0              # vpxor         %xmm0,  %xmm0,  %xmm0
1069         vxor    v1, v1, v1              # vpxor         %xmm1,  %xmm1,  %xmm1
1070         vxor    v2, v2, v2              # vpxor         %xmm2,  %xmm2,  %xmm2
1071         vxor    v3, v3, v3              # vpxor         %xmm3,  %xmm3,  %xmm3
1072         vxor    v4, v4, v4              # vpxor         %xmm4,  %xmm4,  %xmm4
1073         vxor    v5, v5, v5              # vpxor         %xmm5,  %xmm5,  %xmm5
1074         vxor    v6, v6, v6              # vpxor         %xmm6,  %xmm6,  %xmm6
1075         vxor    v7, v7, v7              # vpxor         %xmm7,  %xmm7,  %xmm7
1076
1077         blr
1078         .long   0
1079         .byte   0,12,0x14,0,0,0,0,0
1080
1081 ##
1082 ##  .aes_schedule_192_smear
1083 ##
1084 ##  Smear the short, low side in the 192-bit key schedule.
1085 ##
1086 ##  Inputs:
1087 ##    %xmm7: high side, b  a  x  y
1088 ##    %xmm6:  low side, d  c  0  0
1089 ##    %xmm13: 0
1090 ##
1091 ##  Outputs:
1092 ##    %xmm6: b+c+d  b+c  0  0
1093 ##    %xmm0: b+c+d  b+c  b  a
1094 ##
1095 .align  4
1096 _vpaes_schedule_192_smear:
1097         ?vspltw v0, v7, 3
1098         ?vsldoi v1, v9, v6, 12          # vpshufd       \$0x80, %xmm6,  %xmm1   # d c 0 0 -> c 0 0 0
1099         ?vsldoi v0, v7, v0, 8           # vpshufd       \$0xFE, %xmm7,  %xmm0   # b a _ _ -> b b b a
1100         vxor    v6, v6, v1              # vpxor         %xmm1,  %xmm6,  %xmm6   # -> c+d c 0 0
1101         vxor    v6, v6, v0              # vpxor         %xmm0,  %xmm6,  %xmm6   # -> b+c+d b+c b a
1102         vmr     v0, v6
1103         ?vsldoi v6, v6, v9, 8
1104         ?vsldoi v6, v9, v6, 8           # clobber low side with zeros
1105         blr
1106         .long   0
1107         .byte   0,12,0x14,0,0,0,0,0
1108
1109 ##
1110 ##  .aes_schedule_round
1111 ##
1112 ##  Runs one main round of the key schedule on %xmm0, %xmm7
1113 ##
1114 ##  Specifically, runs subbytes on the high dword of %xmm0
1115 ##  then rotates it by one byte and xors into the low dword of
1116 ##  %xmm7.
1117 ##
1118 ##  Adds rcon from low byte of %xmm8, then rotates %xmm8 for
1119 ##  next rcon.
1120 ##
1121 ##  Smears the dwords of %xmm7 by xoring the low into the
1122 ##  second low, result into third, result into highest.
1123 ##
1124 ##  Returns results in %xmm7 = %xmm0.
1125 ##  Clobbers %xmm1-%xmm4, %r11.
1126 ##
1127 .align  4
1128 _vpaes_schedule_round:
1129         # extract rcon from xmm8
1130         #vxor   v4, v4, v4              # vpxor         %xmm4,  %xmm4,  %xmm4
1131         ?vsldoi v1, $rcon, v9, 15       # vpalignr      \$15,   %xmm8,  %xmm4,  %xmm1
1132         ?vsldoi $rcon, $rcon, $rcon, 15 # vpalignr      \$15,   %xmm8,  %xmm8,  %xmm8
1133         vxor    v7, v7, v1              # vpxor         %xmm1,  %xmm7,  %xmm7
1134
1135         # rotate
1136         ?vspltw v0, v0, 3               # vpshufd       \$0xFF, %xmm0,  %xmm0
1137         ?vsldoi v0, v0, v0, 1           # vpalignr      \$1,    %xmm0,  %xmm0,  %xmm0
1138
1139         # fall through...
1140
1141         # low round: same as high round, but no rotation and no rcon.
1142 _vpaes_schedule_low_round:
1143         # smear xmm7
1144         ?vsldoi v1, v9, v7, 12          # vpslldq       \$4,    %xmm7,  %xmm1
1145         vxor    v7, v7, v1              # vpxor         %xmm1,  %xmm7,  %xmm7
1146         vspltisb        v1, 0x0f        # 0x0f..0f
1147         ?vsldoi v4, v9, v7, 8           # vpslldq       \$8,    %xmm7,  %xmm4
1148
1149         # subbytes
1150         vand    v1, v1, v0              # vpand         %xmm9,  %xmm0,  %xmm1           # 0 = k
1151         vsrb    v0, v0, v8              # vpsrlb        \$4,    %xmm0,  %xmm0           # 1 = i
1152          vxor   v7, v7, v4              # vpxor         %xmm4,  %xmm7,  %xmm7
1153         vperm   v2, $invhi, v9, v1      # vpshufb       %xmm1,  %xmm11, %xmm2           # 2 = a/k
1154         vxor    v1, v1, v0              # vpxor         %xmm0,  %xmm1,  %xmm1           # 0 = j
1155         vperm   v3, $invlo, v9, v0      # vpshufb       %xmm0,  %xmm10, %xmm3           # 3 = 1/i
1156         vxor    v3, v3, v2              # vpxor         %xmm2,  %xmm3,  %xmm3           # 3 = iak = 1/i + a/k
1157         vperm   v4, $invlo, v9, v1      # vpshufb       %xmm1,  %xmm10, %xmm4           # 4 = 1/j
1158          vxor   v7, v7, v26             # vpxor         .Lk_s63(%rip),  %xmm7,  %xmm7
1159         vperm   v3, $invlo, v9, v3      # vpshufb       %xmm3,  %xmm10, %xmm3           # 2 = 1/iak
1160         vxor    v4, v4, v2              # vpxor         %xmm2,  %xmm4,  %xmm4           # 4 = jak = 1/j + a/k
1161         vperm   v2, $invlo, v9, v4      # vpshufb       %xmm4,  %xmm10, %xmm2           # 3 = 1/jak
1162         vxor    v3, v3, v1              # vpxor         %xmm1,  %xmm3,  %xmm3           # 2 = io
1163         vxor    v2, v2, v0              # vpxor         %xmm0,  %xmm2,  %xmm2           # 3 = jo
1164         vperm   v4, v15, v9, v3         # vpshufb       %xmm3,  %xmm13, %xmm4           # 4 = sbou
1165         vperm   v1, v14, v9, v2         # vpshufb       %xmm2,  %xmm12, %xmm1           # 0 = sb1t
1166         vxor    v1, v1, v4              # vpxor         %xmm4,  %xmm1,  %xmm1           # 0 = sbox output
1167
1168         # add in smeared stuff
1169         vxor    v0, v1, v7              # vpxor         %xmm7,  %xmm1,  %xmm0
1170         vxor    v7, v1, v7              # vmovdqa       %xmm0,  %xmm7
1171         blr
1172         .long   0
1173         .byte   0,12,0x14,0,0,0,0,0
1174
1175 ##
1176 ##  .aes_schedule_transform
1177 ##
1178 ##  Linear-transform %xmm0 according to tables at (%r11)
1179 ##
1180 ##  Requires that %xmm9 = 0x0F0F... as in preheat
1181 ##  Output in %xmm0
1182 ##  Clobbers %xmm2
1183 ##
1184 .align  4
1185 _vpaes_schedule_transform:
1186         #vand   v1, v0, v9              # vpand         %xmm9,  %xmm0,  %xmm1
1187         vsrb    v2, v0, v8              # vpsrlb        \$4,    %xmm0,  %xmm0
1188                                         # vmovdqa       (%r11), %xmm2   # lo
1189         vperm   v0, $iptlo, $iptlo, v0  # vpshufb       %xmm1,  %xmm2,  %xmm2
1190                                         # vmovdqa       16(%r11),       %xmm1 # hi
1191         vperm   v2, $ipthi, $ipthi, v2  # vpshufb       %xmm0,  %xmm1,  %xmm0
1192         vxor    v0, v0, v2              # vpxor         %xmm2,  %xmm0,  %xmm0
1193         blr
1194         .long   0
1195         .byte   0,12,0x14,0,0,0,0,0
1196
1197 ##
1198 ##  .aes_schedule_mangle
1199 ##
1200 ##  Mangle xmm0 from (basis-transformed) standard version
1201 ##  to our version.
1202 ##
1203 ##  On encrypt,
1204 ##    xor with 0x63
1205 ##    multiply by circulant 0,1,1,1
1206 ##    apply shiftrows transform
1207 ##
1208 ##  On decrypt,
1209 ##    xor with 0x63
1210 ##    multiply by "inverse mixcolumns" circulant E,B,D,9
1211 ##    deskew
1212 ##    apply shiftrows transform
1213 ##
1214 ##
1215 ##  Writes out to (%rdx), and increments or decrements it
1216 ##  Keeps track of round number mod 4 in %r8
1217 ##  Preserves xmm0
1218 ##  Clobbers xmm1-xmm5
1219 ##
1220 .align  4
1221 _vpaes_schedule_mangle:
1222         #vmr    v4, v0                  # vmovdqa       %xmm0,  %xmm4   # save xmm0 for later
1223                                         # vmovdqa       .Lk_mc_forward(%rip),%xmm5
1224         bne     $dir, Lschedule_mangle_dec
1225
1226         # encrypting
1227         vxor    v4, v0, v26             # vpxor .Lk_s63(%rip),  %xmm0,  %xmm4
1228         addi    $out, $out, 16          # add   \$16,   %rdx
1229         vperm   v4, v4, v4, v25         # vpshufb       %xmm5,  %xmm4,  %xmm4
1230         vperm   v1, v4, v4, v25         # vpshufb       %xmm5,  %xmm4,  %xmm1
1231         vperm   v3, v1, v1, v25         # vpshufb       %xmm5,  %xmm1,  %xmm3
1232         vxor    v4, v4, v1              # vpxor         %xmm1,  %xmm4,  %xmm4
1233         lvx     v1, r8, r10             # vmovdqa       (%r8,%r10),     %xmm1
1234         vxor    v3, v3, v4              # vpxor         %xmm4,  %xmm3,  %xmm3
1235
1236         vperm   v3, v3, v3, v1          # vpshufb       %xmm1,  %xmm3,  %xmm3
1237         addi    r8, r8, -16             # add   \$-16,  %r8
1238         andi.   r8, r8, 0x30            # and   \$0x30, %r8
1239
1240         #stvx   v3, 0, $out             # vmovdqu       %xmm3,  (%rdx)
1241         vperm   v1, v3, v3, $outperm    # rotate right/left
1242         vsel    v2, $outhead, v1, $outmask
1243         vmr     $outhead, v1
1244         stvx    v2, 0, $out
1245         blr
1246
1247 .align  4
1248 Lschedule_mangle_dec:
1249         # inverse mix columns
1250                                         # lea   .Lk_dksd(%rip),%r11
1251         vsrb    v1, v0, v8              # vpsrlb        \$4,    %xmm4,  %xmm1   # 1 = hi
1252         #and    v4, v0, v9              # vpand         %xmm9,  %xmm4,  %xmm4   # 4 = lo
1253
1254                                         # vmovdqa       0x00(%r11),     %xmm2
1255         vperm   v2, v16, v16, v0        # vpshufb       %xmm4,  %xmm2,  %xmm2
1256                                         # vmovdqa       0x10(%r11),     %xmm3
1257         vperm   v3, v17, v17, v1        # vpshufb       %xmm1,  %xmm3,  %xmm3
1258         vxor    v3, v3, v2              # vpxor         %xmm2,  %xmm3,  %xmm3
1259         vperm   v3, v3, v9, v25         # vpshufb       %xmm5,  %xmm3,  %xmm3
1260
1261                                         # vmovdqa       0x20(%r11),     %xmm2
1262         vperm   v2, v18, v18, v0        # vpshufb       %xmm4,  %xmm2,  %xmm2
1263         vxor    v2, v2, v3              # vpxor         %xmm3,  %xmm2,  %xmm2
1264                                         # vmovdqa       0x30(%r11),     %xmm3
1265         vperm   v3, v19, v19, v1        # vpshufb       %xmm1,  %xmm3,  %xmm3
1266         vxor    v3, v3, v2              # vpxor         %xmm2,  %xmm3,  %xmm3
1267         vperm   v3, v3, v9, v25         # vpshufb       %xmm5,  %xmm3,  %xmm3
1268
1269                                         # vmovdqa       0x40(%r11),     %xmm2
1270         vperm   v2, v20, v20, v0        # vpshufb       %xmm4,  %xmm2,  %xmm2
1271         vxor    v2, v2, v3              # vpxor         %xmm3,  %xmm2,  %xmm2
1272                                         # vmovdqa       0x50(%r11),     %xmm3
1273         vperm   v3, v21, v21, v1        # vpshufb       %xmm1,  %xmm3,  %xmm3
1274         vxor    v3, v3, v2              # vpxor         %xmm2,  %xmm3,  %xmm3
1275
1276                                         # vmovdqa       0x60(%r11),     %xmm2
1277         vperm   v2, v22, v22, v0        # vpshufb       %xmm4,  %xmm2,  %xmm2
1278         vperm   v3, v3, v9, v25         # vpshufb       %xmm5,  %xmm3,  %xmm3
1279                                         # vmovdqa       0x70(%r11),     %xmm4
1280         vperm   v4, v23, v23, v1        # vpshufb       %xmm1,  %xmm4,  %xmm4
1281         lvx     v1, r8, r10             # vmovdqa       (%r8,%r10),     %xmm1
1282         vxor    v2, v2, v3              # vpxor         %xmm3,  %xmm2,  %xmm2
1283         vxor    v3, v4, v2              # vpxor         %xmm2,  %xmm4,  %xmm3
1284
1285         addi    $out, $out, -16         # add   \$-16,  %rdx
1286
1287         vperm   v3, v3, v3, v1          # vpshufb       %xmm1,  %xmm3,  %xmm3
1288         addi    r8, r8, -16             # add   \$-16,  %r8
1289         andi.   r8, r8, 0x30            # and   \$0x30, %r8
1290
1291         #stvx   v3, 0, $out             # vmovdqu       %xmm3,  (%rdx)
1292         vperm   v1, v3, v3, $outperm    # rotate right/left
1293         vsel    v2, $outhead, v1, $outmask
1294         vmr     $outhead, v1
1295         stvx    v2, 0, $out
1296         blr
1297         .long   0
1298         .byte   0,12,0x14,0,0,0,0,0
1299
1300 .globl  .vpaes_set_encrypt_key
1301 .align  5
1302 .vpaes_set_encrypt_key:
1303         $STU    $sp,-$FRAME($sp)
1304         li      r10,`15+6*$SIZE_T`
1305         li      r11,`31+6*$SIZE_T`
1306         mflr    r0
1307         mfspr   r6, 256                 # save vrsave
1308         stvx    v20,r10,$sp
1309         addi    r10,r10,16
1310         stvx    v21,r11,$sp
1311         addi    r11,r11,16
1312         stvx    v22,r10,$sp
1313         addi    r10,r10,16
1314         stvx    v23,r11,$sp
1315         addi    r11,r11,16
1316         stvx    v24,r10,$sp
1317         addi    r10,r10,16
1318         stvx    v25,r11,$sp
1319         addi    r11,r11,16
1320         stvx    v26,r10,$sp
1321         addi    r10,r10,16
1322         stvx    v27,r11,$sp
1323         addi    r11,r11,16
1324         stvx    v28,r10,$sp
1325         addi    r10,r10,16
1326         stvx    v29,r11,$sp
1327         addi    r11,r11,16
1328         stvx    v30,r10,$sp
1329         stvx    v31,r11,$sp
1330         lwz     r6,`$FRAME-4`($sp)      # save vrsave
1331         li      r7, -1
1332         $PUSH   r0, `$FRAME+$LRSAVE`($sp)
1333         mtspr   256, r7                 # preserve all AltiVec registers
1334
1335         srwi    r9, $bits, 5            # shr   \$5,%eax
1336         addi    r9, r9, 6               # add   \$5,%eax
1337         stw     r9, 240($out)           # mov   %eax,240(%rdx)  # AES_KEY->rounds = nbits/32+5;
1338
1339         cmplw   $dir, $bits, $bits      # set encrypt direction
1340         li      r8, 0x30                # mov   \$0x30,%r8d
1341         bl      _vpaes_schedule_core
1342
1343         $POP    r0, `$FRAME+$LRSAVE`($sp)
1344         li      r10,`15+6*$SIZE_T`
1345         li      r11,`31+6*$SIZE_T`
1346         mtspr   256, r6                 # restore vrsave
1347         mtlr    r0
1348         xor     r3, r3, r3
1349         lvx     v20,r10,$sp
1350         addi    r10,r10,16
1351         lvx     v21,r11,$sp
1352         addi    r11,r11,16
1353         lvx     v22,r10,$sp
1354         addi    r10,r10,16
1355         lvx     v23,r11,$sp
1356         addi    r11,r11,16
1357         lvx     v24,r10,$sp
1358         addi    r10,r10,16
1359         lvx     v25,r11,$sp
1360         addi    r11,r11,16
1361         lvx     v26,r10,$sp
1362         addi    r10,r10,16
1363         lvx     v27,r11,$sp
1364         addi    r11,r11,16
1365         lvx     v28,r10,$sp
1366         addi    r10,r10,16
1367         lvx     v29,r11,$sp
1368         addi    r11,r11,16
1369         lvx     v30,r10,$sp
1370         lvx     v31,r11,$sp
1371         addi    $sp,$sp,$FRAME
1372         blr
1373         .long   0
1374         .byte   0,12,0x04,1,0x80,3,0
1375         .long   0
1376 .size   .vpaes_set_encrypt_key,.-.vpaes_set_encrypt_key
1377
1378 .globl  .vpaes_set_decrypt_key
1379 .align  4
1380 .vpaes_set_decrypt_key:
1381         $STU    $sp,-$FRAME($sp)
1382         li      r10,`15+6*$SIZE_T`
1383         li      r11,`31+6*$SIZE_T`
1384         mflr    r0
1385         mfspr   r6, 256                 # save vrsave
1386         stvx    v20,r10,$sp
1387         addi    r10,r10,16
1388         stvx    v21,r11,$sp
1389         addi    r11,r11,16
1390         stvx    v22,r10,$sp
1391         addi    r10,r10,16
1392         stvx    v23,r11,$sp
1393         addi    r11,r11,16
1394         stvx    v24,r10,$sp
1395         addi    r10,r10,16
1396         stvx    v25,r11,$sp
1397         addi    r11,r11,16
1398         stvx    v26,r10,$sp
1399         addi    r10,r10,16
1400         stvx    v27,r11,$sp
1401         addi    r11,r11,16
1402         stvx    v28,r10,$sp
1403         addi    r10,r10,16
1404         stvx    v29,r11,$sp
1405         addi    r11,r11,16
1406         stvx    v30,r10,$sp
1407         stvx    v31,r11,$sp
1408         lwz     r6,`$FRAME-4`($sp)      # save vrsave
1409         li      r7, -1
1410         $PUSH   r0, `$FRAME+$LRSAVE`($sp)
1411         mtspr   256, r7                 # preserve all AltiVec registers
1412
1413         srwi    r9, $bits, 5            # shr   \$5,%eax
1414         addi    r9, r9, 6               # add   \$5,%eax
1415         stw     r9, 240($out)           # mov   %eax,240(%rdx)  # AES_KEY->rounds = nbits/32+5;
1416
1417         slwi    r9, r9, 4               # shl   \$4,%eax
1418         add     $out, $out, r9          # lea   (%rdx,%rax),%rdx
1419
1420         cmplwi  $dir, $bits, 0          # set decrypt direction
1421         srwi    r8, $bits, 1            # shr   \$1,%r8d
1422         andi.   r8, r8, 32              # and   \$32,%r8d
1423         xori    r8, r8, 32              # xor   \$32,%r8d       # nbits==192?0:32
1424         bl      _vpaes_schedule_core
1425
1426         $POP    r0,  `$FRAME+$LRSAVE`($sp)
1427         li      r10,`15+6*$SIZE_T`
1428         li      r11,`31+6*$SIZE_T`
1429         mtspr   256, r6                 # restore vrsave
1430         mtlr    r0
1431         xor     r3, r3, r3
1432         lvx     v20,r10,$sp
1433         addi    r10,r10,16
1434         lvx     v21,r11,$sp
1435         addi    r11,r11,16
1436         lvx     v22,r10,$sp
1437         addi    r10,r10,16
1438         lvx     v23,r11,$sp
1439         addi    r11,r11,16
1440         lvx     v24,r10,$sp
1441         addi    r10,r10,16
1442         lvx     v25,r11,$sp
1443         addi    r11,r11,16
1444         lvx     v26,r10,$sp
1445         addi    r10,r10,16
1446         lvx     v27,r11,$sp
1447         addi    r11,r11,16
1448         lvx     v28,r10,$sp
1449         addi    r10,r10,16
1450         lvx     v29,r11,$sp
1451         addi    r11,r11,16
1452         lvx     v30,r10,$sp
1453         lvx     v31,r11,$sp
1454         addi    $sp,$sp,$FRAME
1455         blr
1456         .long   0
1457         .byte   0,12,0x04,1,0x80,3,0
1458         .long   0
1459 .size   .vpaes_set_decrypt_key,.-.vpaes_set_decrypt_key
1460 ___
1461 }
1462
1463 my $consts=1;
1464 foreach  (split("\n",$code)) {
1465         s/\`([^\`]*)\`/eval $1/geo;
1466
1467         # constants table endian-specific conversion
1468         if ($consts && m/\.long\s+(.+)\s+(\?[a-z]*)$/o) {
1469             my $conv=$2;
1470             my @bytes=();
1471
1472             # convert to endian-agnostic format
1473             foreach (split(/,\s+/,$1)) {
1474                 my $l = /^0/?oct:int;
1475                 push @bytes,($l>>24)&0xff,($l>>16)&0xff,($l>>8)&0xff,$l&0xff;
1476             }
1477
1478             # little-endian conversion
1479             if ($flavour =~ /le$/o) {
1480                 SWITCH: for($conv)  {
1481                     /\?inv/ && do   { @bytes=map($_^0xf,@bytes); last; };
1482                     /\?rev/ && do   { @bytes=reverse(@bytes);    last; }; 
1483                 }
1484             }
1485
1486             #emit
1487             print ".byte\t",join(',',map (sprintf("0x%02x",$_),@bytes)),"\n";
1488             next;
1489         }
1490         $consts=0 if (m/Lconsts:/o);    # end of table
1491
1492         # instructions prefixed with '?' are endian-specific and need
1493         # to be adjusted accordingly...
1494         if ($flavour =~ /le$/o) {       # little-endian
1495             s/\?lvsr/lvsl/o or
1496             s/\?lvsl/lvsr/o or
1497             s/\?(vperm\s+v[0-9]+,\s*)(v[0-9]+,\s*)(v[0-9]+,\s*)(v[0-9]+)/$1$3$2$4/o or
1498             s/\?(vsldoi\s+v[0-9]+,\s*)(v[0-9]+,)\s*(v[0-9]+,\s*)([0-9]+)/$1$3$2 16-$4/o or
1499             s/\?(vspltw\s+v[0-9]+,\s*)(v[0-9]+,)\s*([0-9])/$1$2 3-$3/o;
1500         } else {                        # big-endian
1501             s/\?([a-z]+)/$1/o;
1502         }
1503
1504         print $_,"\n";
1505 }
1506
1507 close STDOUT;