aest4-sparcv9.pl: split it to AES-specific and reusable part.
[openssl.git] / crypto / perlasm / sparcv9_modes.pl
1 #!/usr/bin/env perl
2
3 # Specific mode implementations for SPARC T4 modules.
4
5 my ($inp,$out,$len,$key,$ivec,$enc)=map("%i$_",(0..5));
6 my ($ileft,$iright,$ooff,$omask,$ivoff)=map("%l$_",(1..7));
7
8 sub alg_cbc_encrypt_implement {
9 my ($alg,$bits) = @_;
10
11 $::code.=<<___;
12 .globl  ${alg}${bits}_t4_cbc_encrypt
13 .align  32
14 ${alg}${bits}_t4_cbc_encrypt:
15         save            %sp, -$::frame, %sp
16 ___
17 $::code.=<<___ if (!$::evp);
18         andcc           $ivec, 7, $ivoff
19         alignaddr       $ivec, %g0, $ivec
20
21         ldd             [$ivec + 0], %f0        ! load ivec
22         bz,pt           %icc, 1f
23         ldd             [$ivec + 8], %f2
24         ldd             [$ivec + 16], %f4
25         faligndata      %f0, %f2, %f0
26         faligndata      %f2, %f4, %f2
27 1:
28 ___
29 $::code.=<<___ if ($::evp);
30         ld              [$ivec + 0], %f0
31         ld              [$ivec + 4], %f1
32         ld              [$ivec + 8], %f2
33         ld              [$ivec + 12], %f3
34 ___
35 $::code.=<<___;
36         call            _${alg}${bits}_load_enckey
37         srlx            $len, 4, $len
38         and             $inp, 7, $ileft
39         andn            $inp, 7, $inp
40         sll             $ileft, 3, $ileft
41         mov             64, $iright
42         mov             0xff, $omask
43         sub             $iright, $ileft, $iright
44         and             $out, 7, $ooff
45         alignaddrl      $out, %g0, $out
46         srl             $omask, $ooff, $omask
47
48 .L${bits}_cbc_enc_loop:
49         ldx             [$inp + 0], %o0
50         brz,pt          $ileft, 4f
51         ldx             [$inp + 8], %o1
52
53         ldx             [$inp + 16], %o2
54         sllx            %o0, $ileft, %o0
55         srlx            %o1, $iright, %g1
56         sllx            %o1, $ileft, %o1
57         or              %g1, %o0, %o0
58         srlx            %o2, $iright, %o2
59         or              %o2, %o1, %o1
60 4:
61         xor             %g4, %o0, %o0           ! ^= rk[0]
62         xor             %g5, %o1, %o1
63         movxtod         %o0, %f12
64         movxtod         %o1, %f14
65
66         fxor            %f12, %f0, %f0          ! ^= ivec
67         fxor            %f14, %f2, %f2
68         call            _${alg}${bits}_encrypt_1x
69         add             $inp, 16, $inp
70
71         brnz,pn         $ooff, 2f
72         sub             $len, 1, $len
73                 
74         std             %f0, [$out + 0]
75         std             %f2, [$out + 8]
76         brnz,pt         $len, .L${bits}_cbc_enc_loop
77         add             $out, 16, $out
78 ___
79 $::code.=<<___ if ($::evp);
80         st              %f0, [$ivec + 0]
81         st              %f1, [$ivec + 4]
82         st              %f2, [$ivec + 8]
83         st              %f3, [$ivec + 12]
84 ___
85 $::code.=<<___ if (!$::evp);
86         brnz,pn         $ivoff, 3f
87         nop
88
89         std             %f0, [$ivec + 0]        ! write out ivec
90         std             %f2, [$ivec + 8]
91 ___
92 $::code.=<<___;
93         ret
94         restore
95
96 .align  16
97 2:      ldxa            [$inp]0x82, %o0         ! avoid read-after-write hazard
98                                                 ! and ~3x deterioration
99                                                 ! in inp==out case
100         faligndata      %f0, %f0, %f4           ! handle unaligned output
101         faligndata      %f0, %f2, %f6
102         faligndata      %f2, %f2, %f8
103
104         stda            %f4, [$out + $omask]0xc0        ! partial store
105         std             %f6, [$out + 8]
106         add             $out, 16, $out
107         orn             %g0, $omask, $omask
108         stda            %f8, [$out + $omask]0xc0        ! partial store
109
110         brnz,pt         $len, .L${bits}_cbc_enc_loop+4
111         orn             %g0, $omask, $omask
112 ___
113 $::code.=<<___ if ($::evp);
114         st              %f0, [$ivec + 0]
115         st              %f1, [$ivec + 4]
116         st              %f2, [$ivec + 8]
117         st              %f3, [$ivec + 12]
118 ___
119 $::code.=<<___ if (!$::evp);
120         brnz,pn         $ivoff, 3f
121         nop
122
123         std             %f0, [$ivec + 0]        ! write out ivec
124         std             %f2, [$ivec + 8]
125         ret
126         restore
127
128 .align  16
129 3:      alignaddrl      $ivec, $ivoff, %g0      ! handle unaligned ivec
130         mov             0xff, $omask
131         srl             $omask, $ivoff, $omask
132         faligndata      %f0, %f0, %f4
133         faligndata      %f0, %f2, %f6
134         faligndata      %f2, %f2, %f8
135         stda            %f4, [$ivec + $omask]0xc0
136         std             %f6, [$ivec + 8]
137         add             $ivec, 16, $ivec
138         orn             %g0, $omask, $omask
139         stda            %f8, [$ivec + $omask]0xc0
140 ___
141 $::code.=<<___;
142         ret
143         restore
144 .type   ${alg}${bits}_t4_cbc_encrypt,#function
145 .size   ${alg}${bits}_t4_cbc_encrypt,.-${alg}${bits}_t4_cbc_encrypt
146 ___
147 }
148
149 sub alg_cbc_decrypt_implement {
150 my ($alg,$bits) = @_;
151
152 $::code.=<<___;
153 .globl  ${alg}${bits}_t4_cbc_decrypt
154 .align  32
155 ${alg}${bits}_t4_cbc_decrypt:
156         save            %sp, -$::frame, %sp
157 ___
158 $::code.=<<___ if (!$::evp);
159         andcc           $ivec, 7, $ivoff
160         alignaddr       $ivec, %g0, $ivec
161
162         ldd             [$ivec + 0], %f12       ! load ivec
163         bz,pt           %icc, 1f
164         ldd             [$ivec + 8], %f14
165         ldd             [$ivec + 16], %f0
166         faligndata      %f12, %f14, %f12
167         faligndata      %f14, %f0, %f14
168 1:
169 ___
170 $::code.=<<___ if ($::evp);
171         ld              [$ivec + 0], %f12       ! load ivec
172         ld              [$ivec + 4], %f13
173         ld              [$ivec + 8], %f14
174         ld              [$ivec + 12], %f15
175 ___
176 $::code.=<<___;
177         call            _${alg}${bits}_load_deckey
178         srlx            $len, 4, $len
179         andcc           $len, 1, %g0            ! is number of blocks even?
180         and             $inp, 7, $ileft
181         andn            $inp, 7, $inp
182         sll             $ileft, 3, $ileft
183         mov             64, $iright
184         mov             0xff, $omask
185         sub             $iright, $ileft, $iright
186         and             $out, 7, $ooff
187         alignaddrl      $out, %g0, $out
188         bz              %icc, .L${bits}_cbc_dec_loop2x
189         srl             $omask, $ooff, $omask
190 .L${bits}_cbc_dec_loop:
191         ldx             [$inp + 0], %o0
192         brz,pt          $ileft, 4f
193         ldx             [$inp + 8], %o1
194
195         ldx             [$inp + 16], %o2
196         sllx            %o0, $ileft, %o0
197         srlx            %o1, $iright, %g1
198         sllx            %o1, $ileft, %o1
199         or              %g1, %o0, %o0
200         srlx            %o2, $iright, %o2
201         or              %o2, %o1, %o1
202 4:
203         xor             %g4, %o0, %o2           ! ^= rk[0]
204         xor             %g5, %o1, %o3
205         movxtod         %o2, %f0
206         movxtod         %o3, %f2
207
208         call            _${alg}${bits}_decrypt_1x
209         add             $inp, 16, $inp
210
211         fxor            %f12, %f0, %f0          ! ^= ivec
212         fxor            %f14, %f2, %f2
213         movxtod         %o0, %f12
214         movxtod         %o1, %f14
215
216         brnz,pn         $ooff, 2f
217         sub             $len, 1, $len
218                 
219         std             %f0, [$out + 0]
220         std             %f2, [$out + 8]
221         brnz,pt         $len, .L${bits}_cbc_dec_loop2x
222         add             $out, 16, $out
223 ___
224 $::code.=<<___ if ($::evp);
225         st              %f12, [$ivec + 0]
226         st              %f13, [$ivec + 4]
227         st              %f14, [$ivec + 8]
228         st              %f15, [$ivec + 12]
229 ___
230 $::code.=<<___ if (!$::evp);
231         brnz,pn         $ivoff, .L${bits}_cbc_dec_unaligned_ivec
232         nop
233
234         std             %f12, [$ivec + 0]       ! write out ivec
235         std             %f14, [$ivec + 8]
236 ___
237 $::code.=<<___;
238         ret
239         restore
240
241 .align  16
242 2:      ldxa            [$inp]0x82, %o0         ! avoid read-after-write hazard
243                                                 ! and ~3x deterioration
244                                                 ! in inp==out case
245         faligndata      %f0, %f0, %f4           ! handle unaligned output
246         faligndata      %f0, %f2, %f6
247         faligndata      %f2, %f2, %f8
248
249         stda            %f4, [$out + $omask]0xc0        ! partial store
250         std             %f6, [$out + 8]
251         add             $out, 16, $out
252         orn             %g0, $omask, $omask
253         stda            %f8, [$out + $omask]0xc0        ! partial store
254
255         brnz,pt         $len, .L${bits}_cbc_dec_loop2x+4
256         orn             %g0, $omask, $omask
257 ___
258 $::code.=<<___ if ($::evp);
259         st              %f12, [$ivec + 0]
260         st              %f13, [$ivec + 4]
261         st              %f14, [$ivec + 8]
262         st              %f15, [$ivec + 12]
263 ___
264 $::code.=<<___ if (!$::evp);
265         brnz,pn         $ivoff, .L${bits}_cbc_dec_unaligned_ivec
266         nop
267
268         std             %f12, [$ivec + 0]       ! write out ivec
269         std             %f14, [$ivec + 8]
270 ___
271 $::code.=<<___;
272         ret
273         restore
274
275 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
276 .align  32
277 .L${bits}_cbc_dec_loop2x:
278         ldx             [$inp + 0], %o0
279         ldx             [$inp + 8], %o1
280         ldx             [$inp + 16], %o2
281         brz,pt          $ileft, 4f
282         ldx             [$inp + 24], %o3
283
284         ldx             [$inp + 32], %o4
285         sllx            %o0, $ileft, %o0
286         srlx            %o1, $iright, %g1
287         or              %g1, %o0, %o0
288         sllx            %o1, $ileft, %o1
289         srlx            %o2, $iright, %g1
290         or              %g1, %o1, %o1
291         sllx            %o2, $ileft, %o2
292         srlx            %o3, $iright, %g1
293         or              %g1, %o2, %o2
294         sllx            %o3, $ileft, %o3
295         srlx            %o4, $iright, %o4
296         or              %o4, %o3, %o3
297 4:
298         xor             %g4, %o0, %o4           ! ^= rk[0]
299         xor             %g5, %o1, %o5
300         movxtod         %o4, %f0
301         movxtod         %o5, %f2
302         xor             %g4, %o2, %o4
303         xor             %g5, %o3, %o5
304         movxtod         %o4, %f4
305         movxtod         %o5, %f6
306
307         call            _${alg}${bits}_decrypt_2x
308         add             $inp, 32, $inp
309
310         movxtod         %o0, %f8
311         movxtod         %o1, %f10
312         fxor            %f12, %f0, %f0          ! ^= ivec
313         fxor            %f14, %f2, %f2
314         movxtod         %o2, %f12
315         movxtod         %o3, %f14
316         fxor            %f8, %f4, %f4
317         fxor            %f10, %f6, %f6
318
319         brnz,pn         $ooff, 2f
320         sub             $len, 2, $len
321                 
322         std             %f0, [$out + 0]
323         std             %f2, [$out + 8]
324         std             %f4, [$out + 16]
325         std             %f6, [$out + 24]
326         brnz,pt         $len, .L${bits}_cbc_dec_loop2x
327         add             $out, 32, $out
328 ___
329 $::code.=<<___ if ($::evp);
330         st              %f12, [$ivec + 0]
331         st              %f13, [$ivec + 4]
332         st              %f14, [$ivec + 8]
333         st              %f15, [$ivec + 12]
334 ___
335 $::code.=<<___ if (!$::evp);
336         brnz,pn         $ivoff, .L${bits}_cbc_dec_unaligned_ivec
337         nop
338
339         std             %f12, [$ivec + 0]       ! write out ivec
340         std             %f14, [$ivec + 8]
341 ___
342 $::code.=<<___;
343         ret
344         restore
345
346 .align  16
347 2:      ldxa            [$inp]0x82, %o0         ! avoid read-after-write hazard
348                                                 ! and ~3x deterioration
349                                                 ! in inp==out case
350         faligndata      %f0, %f0, %f8           ! handle unaligned output
351         faligndata      %f0, %f2, %f0
352         faligndata      %f2, %f4, %f2
353         faligndata      %f4, %f6, %f4
354         faligndata      %f6, %f6, %f6
355         stda            %f8, [$out + $omask]0xc0        ! partial store
356         std             %f0, [$out + 8]
357         std             %f2, [$out + 16]
358         std             %f4, [$out + 24]
359         add             $out, 32, $out
360         orn             %g0, $omask, $omask
361         stda            %f6, [$out + $omask]0xc0        ! partial store
362
363         brnz,pt         $len, .L${bits}_cbc_dec_loop2x+4
364         orn             %g0, $omask, $omask
365 ___
366 $::code.=<<___ if ($::evp);
367         st              %f12, [$ivec + 0]
368         st              %f13, [$ivec + 4]
369         st              %f14, [$ivec + 8]
370         st              %f15, [$ivec + 12]
371 ___
372 $::code.=<<___ if (!$::evp);
373         brnz,pn         $ivoff, .L${bits}_cbc_dec_unaligned_ivec
374         nop
375
376         std             %f12, [$ivec + 0]       ! write out ivec
377         std             %f14, [$ivec + 8]
378         ret
379         restore
380
381 .align  16
382 .L${bits}_cbc_dec_unaligned_ivec:
383         alignaddrl      $ivec, $ivoff, %g0      ! handle unaligned ivec
384         mov             0xff, $omask
385         srl             $omask, $ivoff, $omask
386         faligndata      %f12, %f12, %f0
387         faligndata      %f12, %f14, %f2
388         faligndata      %f14, %f14, %f4
389         stda            %f0, [$ivec + $omask]0xc0
390         std             %f2, [$ivec + 8]
391         add             $ivec, 16, $ivec
392         orn             %g0, $omask, $omask
393         stda            %f4, [$ivec + $omask]0xc0
394 ___
395 $::code.=<<___;
396         ret
397         restore
398 .type   ${alg}${bits}_t4_cbc_decrypt,#function
399 .size   ${alg}${bits}_t4_cbc_decrypt,.-${alg}${bits}_t4_cbc_decrypt
400 ___
401 }
402
403 sub alg_ctr32_implement {
404 my ($alg,$bits) = @_;
405
406 $::code.=<<___;
407 .globl  ${alg}${bits}_t4_ctr32_encrypt
408 .align  32
409 ${alg}${bits}_t4_ctr32_encrypt:
410         save            %sp, -$::frame, %sp
411
412         call            _${alg}${bits}_load_enckey
413         nop
414
415         ld              [$ivec + 0], %l4        ! counter
416         ld              [$ivec + 4], %l5
417         ld              [$ivec + 8], %l6
418         ld              [$ivec + 12], %l7
419
420         sllx            %l4, 32, %o5
421         or              %l5, %o5, %o5
422         sllx            %l6, 32, %g1
423         xor             %o5, %g4, %g4           ! ^= rk[0]
424         xor             %g1, %g5, %g5
425         movxtod         %g4, %f14               ! most significant 64 bits
426
427         andcc           $len, 1, %g0            ! is number of blocks even?
428         and             $inp, 7, $ileft
429         andn            $inp, 7, $inp
430         sll             $ileft, 3, $ileft
431         mov             64, $iright
432         mov             0xff, $omask
433         sub             $iright, $ileft, $iright
434         and             $out, 7, $ooff
435         alignaddrl      $out, %g0, $out
436         bz              %icc, .L${bits}_ctr32_loop2x
437         srl             $omask, $ooff, $omask
438 .L${bits}_ctr32_loop:
439         ldx             [$inp + 0], %o0
440         brz,pt          $ileft, 4f
441         ldx             [$inp + 8], %o1
442
443         ldx             [$inp + 16], %o2
444         sllx            %o0, $ileft, %o0
445         srlx            %o1, $iright, %g1
446         sllx            %o1, $ileft, %o1
447         or              %g1, %o0, %o0
448         srlx            %o2, $iright, %o2
449         or              %o2, %o1, %o1
450 4:
451         xor             %g5, %l7, %g1           ! ^= rk[0]
452         add             %l7, 1, %l7
453         movxtod         %g1, %f2
454         srl             %l7, 0, %l7             ! clruw
455 ___
456 $::code.=<<___ if ($alg eq "aes");
457         aes_eround01    %f16, %f14, %f2, %f4
458         aes_eround23    %f18, %f14, %f2, %f2
459 ___
460 $::code.=<<___ if ($alg eq "cmll");
461         camellia_f      %f16, %f2, %f14, %f2
462         camellia_f      %f18, %f14, %f2, %f0
463 ___
464 $::code.=<<___;
465         call            _${alg}${bits}_encrypt_1x+8
466         add             $inp, 16, $inp
467
468         movxtod         %o0, %f10
469         movxtod         %o1, %f12
470         fxor            %f10, %f0, %f0          ! ^= inp
471         fxor            %f12, %f2, %f2
472
473         brnz,pn         $ooff, 2f
474         sub             $len, 1, $len
475                 
476         std             %f0, [$out + 0]
477         std             %f2, [$out + 8]
478         brnz,pt         $len, .L${bits}_ctr32_loop2x
479         add             $out, 16, $out
480
481         ret
482         restore
483
484 .align  16
485 2:      ldxa            [$inp]0x82, %o0         ! avoid read-after-write hazard
486                                                 ! and ~3x deterioration
487                                                 ! in inp==out case
488         faligndata      %f0, %f0, %f4           ! handle unaligned output
489         faligndata      %f0, %f2, %f6
490         faligndata      %f2, %f2, %f8
491         stda            %f4, [$out + $omask]0xc0        ! partial store
492         std             %f6, [$out + 8]
493         add             $out, 16, $out
494         orn             %g0, $omask, $omask
495         stda            %f8, [$out + $omask]0xc0        ! partial store
496
497         brnz,pt         $len, .L${bits}_ctr32_loop2x+4
498         orn             %g0, $omask, $omask
499
500         ret
501         restore
502
503 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
504 .align  32
505 .L${bits}_ctr32_loop2x:
506         ldx             [$inp + 0], %o0
507         ldx             [$inp + 8], %o1
508         ldx             [$inp + 16], %o2
509         brz,pt          $ileft, 4f
510         ldx             [$inp + 24], %o3
511
512         ldx             [$inp + 32], %o4
513         sllx            %o0, $ileft, %o0
514         srlx            %o1, $iright, %g1
515         or              %g1, %o0, %o0
516         sllx            %o1, $ileft, %o1
517         srlx            %o2, $iright, %g1
518         or              %g1, %o1, %o1
519         sllx            %o2, $ileft, %o2
520         srlx            %o3, $iright, %g1
521         or              %g1, %o2, %o2
522         sllx            %o3, $ileft, %o3
523         srlx            %o4, $iright, %o4
524         or              %o4, %o3, %o3
525 4:
526         xor             %g5, %l7, %g1           ! ^= rk[0]
527         add             %l7, 1, %l7
528         movxtod         %g1, %f2
529         srl             %l7, 0, %l7             ! clruw
530         xor             %g5, %l7, %g1
531         add             %l7, 1, %l7
532         movxtod         %g1, %f6
533         srl             %l7, 0, %l7             ! clruw
534
535 ___
536 $::code.=<<___ if ($alg eq "aes");
537         aes_eround01    %f16, %f14, %f2, %f8
538         aes_eround23    %f18, %f14, %f2, %f2
539         aes_eround01    %f16, %f14, %f6, %f10
540         aes_eround23    %f18, %f14, %f6, %f6
541 ___
542 $::code.=<<___ if ($alg eq "cmll");
543         camellia_f      %f16, %f2, %f14, %f2
544         camellia_f      %f16, %f6, %f14, %f6
545         camellia_f      %f18, %f14, %f2, %f0
546         camellia_f      %f18, %f14, %f6, %f4
547 ___
548 $::code.=<<___;
549         call            _${alg}${bits}_encrypt_2x+16
550         add             $inp, 32, $inp
551
552         movxtod         %o0, %f8
553         movxtod         %o1, %f10
554         movxtod         %o2, %f12
555         fxor            %f8, %f0, %f0           ! ^= inp
556         movxtod         %o3, %f8
557         fxor            %f10, %f2, %f2
558         fxor            %f12, %f4, %f4
559         fxor            %f8, %f6, %f6
560
561         brnz,pn         $ooff, 2f
562         sub             $len, 2, $len
563                 
564         std             %f0, [$out + 0]
565         std             %f2, [$out + 8]
566         std             %f4, [$out + 16]
567         std             %f6, [$out + 24]
568         brnz,pt         $len, .L${bits}_ctr32_loop2x
569         add             $out, 32, $out
570
571         ret
572         restore
573
574 .align  16
575 2:      ldxa            [$inp]0x82, %o0         ! avoid read-after-write hazard
576                                                 ! and ~3x deterioration
577                                                 ! in inp==out case
578         faligndata      %f0, %f0, %f8           ! handle unaligned output
579         faligndata      %f0, %f2, %f0
580         faligndata      %f2, %f4, %f2
581         faligndata      %f4, %f6, %f4
582         faligndata      %f6, %f6, %f6
583
584         stda            %f8, [$out + $omask]0xc0        ! partial store
585         std             %f0, [$out + 8]
586         std             %f2, [$out + 16]
587         std             %f4, [$out + 24]
588         add             $out, 32, $out
589         orn             %g0, $omask, $omask
590         stda            %f6, [$out + $omask]0xc0        ! partial store
591
592         brnz,pt         $len, .L${bits}_ctr32_loop2x+4
593         orn             %g0, $omask, $omask
594
595         ret
596         restore
597 .type   ${alg}${bits}_t4_ctr32_encrypt,#function
598 .size   ${alg}${bits}_t4_ctr32_encrypt,.-${alg}${bits}_t4_ctr32_encrypt
599 ___
600 }
601
602 # Purpose of these subroutines is to explicitly encode VIS instructions,
603 # so that one can compile the module without having to specify VIS
604 # extentions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a.
605 # Idea is to reserve for option to produce "universal" binary and let
606 # programmer detect if current CPU is VIS capable at run-time.
607 sub unvis {
608 my ($mnemonic,$rs1,$rs2,$rd)=@_;
609 my ($ref,$opf);
610 my %visopf = (  "faligndata"    => 0x048,
611                 "fnot2"         => 0x066,
612                 "fxor"          => 0x06c,
613                 "fsrc2"         => 0x078        );
614
615     $ref = "$mnemonic\t$rs1,$rs2,$rd";
616
617     if ($opf=$visopf{$mnemonic}) {
618         foreach ($rs1,$rs2,$rd) {
619             return $ref if (!/%f([0-9]{1,2})/);
620             $_=$1;
621             if ($1>=32) {
622                 return $ref if ($1&1);
623                 # re-encode for upper double register addressing
624                 $_=($1|$1>>5)&31;
625             }
626         }
627
628         return  sprintf ".word\t0x%08x !%s",
629                         0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2,
630                         $ref;
631     } else {
632         return $ref;
633     }
634 }
635 sub unalignaddr {
636 my ($mnemonic,$rs1,$rs2,$rd)=@_;
637 my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 );
638 my $ref = "$mnemonic\t$rs1,$rs2,$rd";
639 my $opf = $mnemonic =~ /l$/ ? 0x01a :0x18;
640
641     foreach ($rs1,$rs2,$rd) {
642         if (/%([goli])([0-7])/) { $_=$bias{$1}+$2; }
643         else                    { return $ref; }
644     }
645     return  sprintf ".word\t0x%08x !%s",
646                     0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2,
647                     $ref;
648 }
649
650 sub unaes_round {       # 4-argument instructions
651 my ($mnemonic,$rs1,$rs2,$rs3,$rd)=@_;
652 my ($ref,$opf);
653 my %aesopf = (  "aes_eround01"  => 0,
654                 "aes_eround23"  => 1,
655                 "aes_dround01"  => 2,
656                 "aes_dround23"  => 3,
657                 "aes_eround01_l"=> 4,
658                 "aes_eround23_l"=> 5,
659                 "aes_dround01_l"=> 6,
660                 "aes_dround23_l"=> 7,
661                 "aes_kexpand1"  => 8    );
662
663     $ref = "$mnemonic\t$rs1,$rs2,$rs3,$rd";
664
665     if (defined($opf=$aesopf{$mnemonic})) {
666         $rs3 = ($rs3 =~ /%f([0-6]*[02468])/) ? (($1|$1>>5)&31) : $rs3;
667         foreach ($rs1,$rs2,$rd) {
668             return $ref if (!/%f([0-9]{1,2})/);
669             $_=$1;
670             if ($1>=32) {
671                 return $ref if ($1&1);
672                 # re-encode for upper double register addressing
673                 $_=($1|$1>>5)&31;
674             }
675         }
676
677         return  sprintf ".word\t0x%08x !%s",
678                         2<<30|$rd<<25|0x19<<19|$rs1<<14|$rs3<<9|$opf<<5|$rs2,
679                         $ref;
680     } else {
681         return $ref;
682     }
683 }
684
685 sub unaes_kexpand {     # 3-argument instructions
686 my ($mnemonic,$rs1,$rs2,$rd)=@_;
687 my ($ref,$opf);
688 my %aesopf = (  "aes_kexpand0"  => 0x130,
689                 "aes_kexpand2"  => 0x131        );
690
691     $ref = "$mnemonic\t$rs1,$rs2,$rd";
692
693     if (defined($opf=$aesopf{$mnemonic})) {
694         foreach ($rs1,$rs2,$rd) {
695             return $ref if (!/%f([0-9]{1,2})/);
696             $_=$1;
697             if ($1>=32) {
698                 return $ref if ($1&1);
699                 # re-encode for upper double register addressing
700                 $_=($1|$1>>5)&31;
701             }
702         }
703
704         return  sprintf ".word\t0x%08x !%s",
705                         2<<30|$rd<<25|0x36<<19|$rs1<<14|$opf<<5|$rs2,
706                         $ref;
707     } else {
708         return $ref;
709     }
710 }
711
712 sub uncamellia_f {      # 4-argument instructions
713 my ($mnemonic,$rs1,$rs2,$rs3,$rd)=@_;
714 my ($ref,$opf);
715
716     $ref = "$mnemonic\t$rs1,$rs2,$rs3,$rd";
717
718     if (1) {
719         $rs3 = ($rs3 =~ /%f([0-6]*[02468])/) ? (($1|$1>>5)&31) : $rs3;
720         foreach ($rs1,$rs2,$rd) {
721             return $ref if (!/%f([0-9]{1,2})/);
722             $_=$1;
723             if ($1>=32) {
724                 return $ref if ($1&1);
725                 # re-encode for upper double register addressing
726                 $_=($1|$1>>5)&31;
727             }
728         }
729
730         return  sprintf ".word\t0x%08x !%s",
731                         2<<30|$rd<<25|0x19<<19|$rs1<<14|$rs3<<9|0xc<<5|$rs2,
732                         $ref;
733     } else {
734         return $ref;
735     }
736 }
737
738 sub uncamellia3 {       # 3-argument instructions
739 my ($mnemonic,$rs1,$rs2,$rd)=@_;
740 my ($ref,$opf);
741 my %cmllopf = ( "camellia_fl"   => 0x13c,
742                 "camellia_fli"  => 0x13d        );
743
744     $ref = "$mnemonic\t$rs1,$rs2,$rd";
745
746     if (defined($opf=$cmllopf{$mnemonic})) {
747         foreach ($rs1,$rs2,$rd) {
748             return $ref if (!/%f([0-9]{1,2})/);
749             $_=$1;
750             if ($1>=32) {
751                 return $ref if ($1&1);
752                 # re-encode for upper double register addressing
753                 $_=($1|$1>>5)&31;
754             }
755         }
756
757         return  sprintf ".word\t0x%08x !%s",
758                         2<<30|$rd<<25|0x36<<19|$rs1<<14|$opf<<5|$rs2,
759                         $ref;
760     } else {
761         return $ref;
762     }
763 }
764
765 sub unmovxtox {         # 2-argument instructions
766 my ($mnemonic,$rs,$rd)=@_;
767 my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24, "f" => 0 );
768 my ($ref,$opf);
769 my %movxopf = ( "movdtox"       => 0x110,
770                 "movstouw"      => 0x111,
771                 "movstosw"      => 0x113,
772                 "movxtod"       => 0x118,
773                 "movwtos"       => 0x119        );
774
775     $ref = "$mnemonic\t$rs,$rd";
776
777     if (defined($opf=$movxopf{$mnemonic})) {
778         foreach ($rs,$rd) {
779             return $ref if (!/%([fgoli])([0-9]{1,2})/);
780             $_=$bias{$1}+$2;
781             if ($2>=32) {
782                 return $ref if ($2&1);
783                 # re-encode for upper double register addressing
784                 $_=($2|$2>>5)&31;
785             }
786         }
787
788         return  sprintf ".word\t0x%08x !%s",
789                         2<<30|$rd<<25|0x36<<19|$opf<<5|$rs,
790                         $ref;
791     } else {
792         return $ref;
793     }
794 }
795
796 sub emit_assembler {
797     foreach (split("\n",$::code)) {
798         s/\`([^\`]*)\`/eval $1/ge;
799
800         s/\b(f[a-z]+2[sd]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})\s*$/$1\t%f0,$2,$3/g;
801
802         s/\b(aes_[edk][^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*([%fx0-9]+),\s*(%f[0-9]{1,2})/
803                 &unaes_round($1,$2,$3,$4,$5)
804          /ge or
805         s/\b(aes_kexpand[02])\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/
806                 &unaes_kexpand($1,$2,$3,$4)
807          /ge or
808         s/\b(camellia_f)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*([%fx0-9]+),\s*(%f[0-9]{1,2})/
809                 &uncamellia_f($1,$2,$3,$4,$5)
810          /ge or
811         s/\b(camellia_[^s]+)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/
812                 &uncamellia3($1,$2,$3,$4)
813          /ge or
814         s/\b(mov[ds]to\w+)\s+(%f[0-9]{1,2}),\s*(%[goli][0-7])/
815                 &unmovxtox($1,$2,$3)
816          /ge or
817         s/\b(mov[xw]to[ds])\s+(%[goli][0-7]),\s*(%f[0-9]{1,2})/
818                 &unmovxtox($1,$2,$3)
819          /ge or
820         s/\b(f[^\s]*)\s+(%f[0-9]{1,2}),\s*(%f[0-9]{1,2}),\s*(%f[0-9]{1,2})/
821                 &unvis($1,$2,$3,$4)
822          /ge or
823         s/\b(alignaddr[l]*)\s+(%[goli][0-7]),\s*(%[goli][0-7]),\s*(%[goli][0-7])/
824                 &unalignaddr($1,$2,$3,$4)
825          /ge;
826
827         print $_,"\n";
828     }
829 }
830
831 1;