Throw in x86_64 AT&T to MASM assembler converter to facilitate development
[openssl.git] / crypto / rc4 / asm / rc4-amd64.pl
1 #!/usr/bin/env perl
2 #
3 # ====================================================================
4 # Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
5 # project. Rights for redistribution and usage in source and binary
6 # forms are granted according to the OpenSSL license.
7 # ====================================================================
8 #
9 # 2.22x RC4 tune-up:-) It should be noted though that my hand [as in
10 # "hand-coded assembler"] doesn't stand for the whole improvement
11 # coefficient. It turned out that eliminating RC4_CHAR from config
12 # line results in ~40% improvement (yes, even for C implementation).
13 # Presumably it has everything to do with AMD cache architecture and
14 # RAW or whatever penalties. Once again! The module *requires* config
15 # line *without* RC4_CHAR! As for coding "secret," I bet on partial
16 # register arithmetics. For example instead of 'inc %r8; and $255,%r8'
17 # I simply 'inc %r8b'. Even though optimization manual discourages
18 # to operate on partial registers, it turned out to be the best bet.
19 # At least for AMD... How IA32E would perform remains to be seen...
20
21 # As was shown by Marc Bevand reordering of couple of load operations
22 # results in even higher performance gain of 3.3x:-) At least on
23 # Opteron... For reference, 1x in this case is RC4_CHAR C-code
24 # compiled with gcc 3.3.2, which performs at ~54MBps per 1GHz clock.
25 # Latter means that if you want to *estimate* what to expect from
26 # *your* CPU, then multiply 54 by 3.3 and clock frequency in GHz.
27
28 # Intel P4 EM64T core was found to run the AMD64 code really slow...
29 # The only way to achieve comparable performance on P4 is to keep
30 # RC4_CHAR. Kind of ironic, huh? As it's apparently impossible to
31 # compose blended code, which would perform even within 30% marginal
32 # on either AMD and Intel platforms, I implement both cases. See
33 # rc4_skey.c for further details... This applies to 0.9.8 and later.
34 # In 0.9.7 context RC4_CHAR codepath is never engaged and ~70 bytes
35 # of code remain redundant.
36
37 $output=shift;
38 open STDOUT,"| $^X ../perlasm/x86_64-xlate.pl $output";
39
40 $dat="%rdi";        # arg1
41 $len="%rsi";        # arg2
42 $inp="%rdx";        # arg3
43 $out="%rcx";        # arg4
44
45 $XX="%r10";
46 $TX="%r8";
47 $YY="%r11";
48 $TY="%r9";
49
50 $code=<<___;
51 .text
52
53 .globl  RC4
54 .type   RC4,\@function,4
55 .align  16
56 RC4:    or      $len,$len
57         jne     .Lentry
58         ret
59 .Lentry:
60         add     \$8,$dat
61         movl    -8($dat),$XX#d
62         movl    -4($dat),$YY#d
63         cmpl    \$-1,256($dat)
64         je      .LRC4_CHAR
65         test    \$-8,$len
66         jz      .Lloop1
67 .align  16
68 .Lloop8:
69         inc     $XX#b
70         movl    ($dat,$XX,4),$TX#d
71         add     $TX#b,$YY#b
72         movl    ($dat,$YY,4),$TY#d
73         movl    $TX#d,($dat,$YY,4)
74         movl    $TY#d,($dat,$XX,4)
75         add     $TX#b,$TY#b
76         inc     $XX#b
77         movl    ($dat,$XX,4),$TX#d
78         movb    ($dat,$TY,4),%al
79 ___
80 for ($i=1;$i<=6;$i++) {
81 $code.=<<___;
82         add     $TX#b,$YY#b
83         ror     \$8,%rax
84         movl    ($dat,$YY,4),$TY#d
85         movl    $TX#d,($dat,$YY,4)
86         movl    $TY#d,($dat,$XX,4)
87         add     $TX#b,$TY#b
88         inc     $XX#b
89         movl    ($dat,$XX,4),$TX#d
90         movb    ($dat,$TY,4),%al
91 ___
92 }
93 $code.=<<___;
94         add     $TX#b,$YY#b
95         ror     \$8,%rax
96         movl    ($dat,$YY,4),$TY#d
97         movl    $TX#d,($dat,$YY,4)
98         movl    $TY#d,($dat,$XX,4)
99         sub     \$8,$len
100         add     $TY#b,$TX#b
101         movb    ($dat,$TX,4),%al
102         ror     \$8,%rax
103         add     \$8,$inp
104         add     \$8,$out
105
106         xor     -8($inp),%rax
107         mov     %rax,-8($out)
108
109         test    \$-8,$len
110         jnz     .Lloop8
111         cmp     \$0,$len
112         jne     .Lloop1
113 .Lexit:
114         movl    $XX#d,-8($dat)
115         movl    $YY#d,-4($dat)
116         ret
117 .align  16
118 .Lloop1:
119         movzb   ($inp),%eax
120         inc     $XX#b
121         movl    ($dat,$XX,4),$TX#d
122         add     $TX#b,$YY#b
123         movl    ($dat,$YY,4),$TY#d
124         movl    $TX#d,($dat,$YY,4)
125         movl    $TY#d,($dat,$XX,4)
126         add     $TY#b,$TX#b
127         movl    ($dat,$TX,4),$TY#d
128         xor     $TY,%rax
129         inc     $inp
130         movb    %al,($out)
131         inc     $out
132         dec     $len
133         jnz     .Lloop1
134         jmp     .Lexit
135
136 .align  16
137 .LRC4_CHAR:
138         add     \$1,$XX#b
139         movzb   ($dat,$XX),$TX#d
140         add     $TX#b,$YY#b
141         movzb   ($dat,$YY),$TY#d
142         movb    $TX#b,($dat,$YY)
143         movb    $TY#b,($dat,$XX)
144         add     $TX#b,$TY#b
145         movzb   ($dat,$TY),$TY#d
146         xorb    ($inp),$TY#b
147         movb    $TY#b,($out)
148         lea     1($inp),$inp
149         lea     1($out),$out
150         sub     \$1,$len
151         jnz     .LRC4_CHAR
152         jmp     .Lexit
153 .size   RC4,.-RC4
154 ___
155
156 $code =~ s/#([bwd])/$1/gm;
157
158 print $code;
159
160 close STDOUT;