Rename des_SPtrans to DES_SPtrans to differentiate from libdes and avoid certain...
[openssl.git] / crypto / des / asm / des686.pl
1 #!/usr/local/bin/perl
2
3 $prog="des686.pl";
4
5 # base code is in microsft
6 # op dest, source
7 # format.
8 #
9
10 # WILL NOT WORK ANYMORE WITH desboth.pl
11 require "desboth.pl";
12
13 if (    ($ARGV[0] eq "elf"))
14         { require "x86unix.pl"; }
15 elsif ( ($ARGV[0] eq "a.out"))
16         { $aout=1; require "x86unix.pl"; }
17 elsif ( ($ARGV[0] eq "sol"))
18         { $sol=1; require "x86unix.pl"; }
19 elsif ( ($ARGV[0] eq "cpp"))
20         { $cpp=1; require "x86unix.pl"; }
21 elsif ( ($ARGV[0] eq "win32"))
22         { require "x86ms.pl"; }
23 else
24         {
25         print STDERR <<"EOF";
26 Pick one target type from
27         elf     - linux, FreeBSD etc
28         a.out   - old linux
29         sol     - x86 solaris
30         cpp     - format so x86unix.cpp can be used
31         win32   - Windows 95/Windows NT
32 EOF
33         exit(1);
34         }
35
36 &comment("Don't even think of reading this code");
37 &comment("It was automatically generated by $prog");
38 &comment("Which is a perl program used to generate the x86 assember for");
39 &comment("any of elf, a.out, Win32, or Solaris");
40 &comment("It can be found in SSLeay 0.6.5+ or in libdes 3.26+");
41 &comment("eric <eay\@cryptsoft.com>");
42 &comment("");
43
44 &file("dx86xxxx");
45
46 $L="edi";
47 $R="esi";
48
49 &DES_encrypt("DES_encrypt1",1);
50 &DES_encrypt("DES_encrypt2",0);
51
52 &DES_encrypt3("DES_encrypt3",1);
53 &DES_encrypt3("DES_decrypt3",0);
54
55 &file_end();
56
57 sub DES_encrypt
58         {
59         local($name,$do_ip)=@_;
60
61         &function_begin($name,"EXTRN   _DES_SPtrans:DWORD");
62
63         &comment("");
64         &comment("Load the 2 words");
65         &mov("eax",&wparam(0));
66         &mov($L,&DWP(0,"eax","",0));
67         &mov($R,&DWP(4,"eax","",0));
68
69         $ksp=&wparam(1);
70
71         if ($do_ip)
72                 {
73                 &comment("");
74                 &comment("IP");
75                 &IP_new($L,$R,"eax");
76                 }
77
78         &comment("");
79         &comment("fixup rotate");
80         &rotl($R,3);
81         &rotl($L,3);
82         &exch($L,$R);
83
84         &comment("");
85         &comment("load counter, key_schedule and enc flag");
86         &mov("eax",&wparam(2)); # get encrypt flag
87         &mov("ebp",&wparam(1)); # get ks
88         &cmp("eax","0");
89         &je(&label("start_decrypt"));
90
91         # encrypting part
92
93         for ($i=0; $i<16; $i+=2)
94                 {
95                 &comment("");
96                 &comment("Round $i");
97                 &D_ENCRYPT($L,$R,$i*2,"ebp","DES_SPtrans","ecx","edx","eax","ebx");
98
99                 &comment("");
100                 &comment("Round ".sprintf("%d",$i+1));
101                 &D_ENCRYPT($R,$L,($i+1)*2,"ebp","DES_SPtrans","ecx","edx","eax","ebx");
102                 }
103         &jmp(&label("end"));
104
105         &set_label("start_decrypt");
106
107         for ($i=15; $i>0; $i-=2)
108                 {
109                 &comment("");
110                 &comment("Round $i");
111                 &D_ENCRYPT($L,$R,$i*2,"ebp","DES_SPtrans","ecx","edx","eax","ebx");
112                 &comment("");
113                 &comment("Round ".sprintf("%d",$i-1));
114                 &D_ENCRYPT($R,$L,($i-1)*2,"ebp","DES_SPtrans","ecx","edx","eax","ebx");
115                 }
116
117         &set_label("end");
118
119         &comment("");
120         &comment("Fixup");
121         &rotr($L,3);            # r
122         &rotr($R,3);            # l
123
124         if ($do_ip)
125                 {
126                 &comment("");
127                 &comment("FP");
128                 &FP_new($R,$L,"eax");
129                 }
130
131         &mov("eax",&wparam(0));
132         &mov(&DWP(0,"eax","",0),$L);
133         &mov(&DWP(4,"eax","",0),$R);
134
135         &function_end($name);
136         }
137
138
139 # The logic is to load R into 2 registers and operate on both at the same time.
140 # We also load the 2 R's into 2 more registers so we can do the 'move word down a byte'
141 # while also masking the other copy and doing a lookup.  We then also accumulate the
142 # L value in 2 registers then combine them at the end.
143 sub D_ENCRYPT
144         {
145         local($L,$R,$S,$ks,$desSP,$u,$t,$tmp1,$tmp2,$tmp3)=@_;
146
147         &mov(   $u,             &DWP(&n2a($S*4),$ks,"",0));
148         &mov(   $t,             &DWP(&n2a(($S+1)*4),$ks,"",0));
149         &xor(   $u,             $R              );
150         &xor(   $t,             $R              );
151         &rotr(  $t,             4               );
152
153         # the numbers at the end of the line are origional instruction order
154         &mov(   $tmp2,          $u              );                      # 1 2
155         &mov(   $tmp1,          $t              );                      # 1 1
156         &and(   $tmp2,          "0xfc"          );                      # 1 4
157         &and(   $tmp1,          "0xfc"          );                      # 1 3
158         &shr(   $t,             8               );                      # 1 5
159         &xor(   $L,             &DWP("0x100+$desSP",$tmp1,"",0));       # 1 7
160         &shr(   $u,             8               );                      # 1 6
161         &mov(   $tmp1,          &DWP("      $desSP",$tmp2,"",0));       # 1 8
162
163         &mov(   $tmp2,          $u              );                      # 2 2
164         &xor(   $L,             $tmp1           );                      # 1 9
165         &and(   $tmp2,          "0xfc"          );                      # 2 4
166         &mov(   $tmp1,          $t              );                      # 2 1
167         &and(   $tmp1,          "0xfc"          );                      # 2 3
168         &shr(   $t,             8               );                      # 2 5
169         &xor(   $L,             &DWP("0x300+$desSP",$tmp1,"",0));       # 2 7
170         &shr(   $u,             8               );                      # 2 6
171         &mov(   $tmp1,          &DWP("0x200+$desSP",$tmp2,"",0));       # 2 8
172         &mov(   $tmp2,          $u              );                      # 3 2
173
174         &xor(   $L,             $tmp1           );                      # 2 9
175         &and(   $tmp2,          "0xfc"          );                      # 3 4
176
177         &mov(   $tmp1,          $t              );                      # 3 1 
178         &shr(   $u,             8               );                      # 3 6
179         &and(   $tmp1,          "0xfc"          );                      # 3 3
180         &shr(   $t,             8               );                      # 3 5
181         &xor(   $L,             &DWP("0x500+$desSP",$tmp1,"",0));       # 3 7
182         &mov(   $tmp1,          &DWP("0x400+$desSP",$tmp2,"",0));       # 3 8
183
184         &and(   $t,             "0xfc"          );                      # 4 1
185         &xor(   $L,             $tmp1           );                      # 3 9
186
187         &and(   $u,             "0xfc"          );                      # 4 2
188         &xor(   $L,             &DWP("0x700+$desSP",$t,"",0));          # 4 3
189         &xor(   $L,             &DWP("0x600+$desSP",$u,"",0));          # 4 4
190         }
191
192 sub PERM_OP
193         {
194         local($a,$b,$tt,$shift,$mask)=@_;
195
196         &mov(   $tt,            $a              );
197         &shr(   $tt,            $shift          );
198         &xor(   $tt,            $b              );
199         &and(   $tt,            $mask           );
200         &xor(   $b,             $tt             );
201         &shl(   $tt,            $shift          );
202         &xor(   $a,             $tt             );
203         }
204
205 sub IP_new
206         {
207         local($l,$r,$tt)=@_;
208
209         &PERM_OP($r,$l,$tt, 4,"0x0f0f0f0f");
210         &PERM_OP($l,$r,$tt,16,"0x0000ffff");
211         &PERM_OP($r,$l,$tt, 2,"0x33333333");
212         &PERM_OP($l,$r,$tt, 8,"0x00ff00ff");
213         &PERM_OP($r,$l,$tt, 1,"0x55555555");
214         }
215
216 sub FP_new
217         {
218         local($l,$r,$tt)=@_;
219
220         &PERM_OP($l,$r,$tt, 1,"0x55555555");
221         &PERM_OP($r,$l,$tt, 8,"0x00ff00ff");
222         &PERM_OP($l,$r,$tt, 2,"0x33333333");
223         &PERM_OP($r,$l,$tt,16,"0x0000ffff");
224         &PERM_OP($l,$r,$tt, 4,"0x0f0f0f0f");
225         }
226
227 sub n2a
228         {
229         sprintf("%d",$_[0]);
230         }