efaef87a0b0f0d2ac120a5b5daff666c0bbc2624
[openssl.git] / crypto / perlasm / x86unix.pl
1 #!/usr/local/bin/perl
2
3 # Because the bswapl instruction is not supported for old assembers
4 # (it was a new instruction for the 486), I've added .byte xxxx code
5 # to put it in.
6 # eric 24-Apr-1998
7 #
8
9 package x86unix;
10
11 $label="L000";
12
13 $align=($main'aout)?"4":"16";
14 $under=($main'aout)?"_":"";
15 $com_start=($main'sol)?"/":"#";
16
17 sub main'asm_init_output { @out=(); }
18 sub main'asm_get_output { return(@out); }
19 sub main'get_labels { return(@labels); }
20 sub main'external_label { push(@labels,@_); }
21
22 if ($main'cpp)
23         {
24         $align="ALIGN";
25         $under="";
26         $com_start='/*';
27         $com_end='*/';
28         }
29
30 %lb=(   'eax',  '%al',
31         'ebx',  '%bl',
32         'ecx',  '%cl',
33         'edx',  '%dl',
34         'ax',   '%al',
35         'bx',   '%bl',
36         'cx',   '%cl',
37         'dx',   '%dl',
38         );
39
40 %hb=(   'eax',  '%ah',
41         'ebx',  '%bh',
42         'ecx',  '%ch',
43         'edx',  '%dh',
44         'ax',   '%ah',
45         'bx',   '%bh',
46         'cx',   '%ch',
47         'dx',   '%dh',
48         );
49
50 %regs=( 'eax',  '%eax',
51         'ebx',  '%ebx',
52         'ecx',  '%ecx',
53         'edx',  '%edx',
54         'esi',  '%esi',
55         'edi',  '%edi',
56         'ebp',  '%ebp',
57         'esp',  '%esp',
58         );
59
60 %reg_val=(
61         'eax',  0x00,
62         'ebx',  0x03,
63         'ecx',  0x01,
64         'edx',  0x02,
65         'esi',  0x06,
66         'edi',  0x07,
67         'ebp',  0x05,
68         'esp',  0x04,
69         );
70
71 sub main'LB
72         {
73         (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
74         return($lb{$_[0]});
75         }
76
77 sub main'HB
78         {
79         (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
80         return($hb{$_[0]});
81         }
82
83 sub main'DWP
84         {
85         local($addr,$reg1,$reg2,$idx)=@_;
86
87         $ret="";
88         $addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/;
89         $reg1="$regs{$reg1}" if defined($regs{$reg1});
90         $reg2="$regs{$reg2}" if defined($regs{$reg2});
91         $ret.=$addr if ($addr ne "") && ($addr ne 0);
92         if ($reg2 ne "")
93                 {
94                 if($idx ne "")
95                     { $ret.="($reg1,$reg2,$idx)"; }
96                 else
97                     { $ret.="($reg1,$reg2)"; }
98                 }
99         else
100                 { $ret.="($reg1)" }
101         return($ret);
102         }
103
104 sub main'BP
105         {
106         return(&main'DWP(@_));
107         }
108
109 #sub main'BP
110 #       {
111 #       local($addr,$reg1,$reg2,$idx)=@_;
112 #
113 #       $ret="";
114 #
115 #       $addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/;
116 #       $reg1="$regs{$reg1}" if defined($regs{$reg1});
117 #       $reg2="$regs{$reg2}" if defined($regs{$reg2});
118 #       $ret.=$addr if ($addr ne "") && ($addr ne 0);
119 #       if ($reg2 ne "")
120 #               { $ret.="($reg1,$reg2,$idx)"; }
121 #       else
122 #               { $ret.="($reg1)" }
123 #       return($ret);
124 #       }
125
126 sub main'mov    { &out2("movl",@_); }
127 sub main'movb   { &out2("movb",@_); }
128 sub main'and    { &out2("andl",@_); }
129 sub main'or     { &out2("orl",@_); }
130 sub main'shl    { &out2("sall",@_); }
131 sub main'shr    { &out2("shrl",@_); }
132 sub main'xor    { &out2("xorl",@_); }
133 sub main'xorb   { &out2("xorb",@_); }
134 sub main'add    { &out2("addl",@_); }
135 sub main'adc    { &out2("adcl",@_); }
136 sub main'sub    { &out2("subl",@_); }
137 sub main'rotl   { &out2("roll",@_); }
138 sub main'rotr   { &out2("rorl",@_); }
139 sub main'exch   { &out2("xchg",@_); }
140 sub main'cmp    { &out2("cmpl",@_); }
141 sub main'lea    { &out2("leal",@_); }
142 sub main'mul    { &out1("mull",@_); }
143 sub main'div    { &out1("divl",@_); }
144 sub main'jmp    { &out1("jmp",@_); }
145 sub main'jmp_ptr { &out1p("jmp",@_); }
146 sub main'je     { &out1("je",@_); }
147 sub main'jle    { &out1("jle",@_); }
148 sub main'jne    { &out1("jne",@_); }
149 sub main'jnz    { &out1("jnz",@_); }
150 sub main'jz     { &out1("jz",@_); }
151 sub main'jge    { &out1("jge",@_); }
152 sub main'jl     { &out1("jl",@_); }
153 sub main'jb     { &out1("jb",@_); }
154 sub main'jc     { &out1("jc",@_); }
155 sub main'jnc    { &out1("jnc",@_); }
156 sub main'jno    { &out1("jno",@_); }
157 sub main'dec    { &out1("decl",@_); }
158 sub main'inc    { &out1("incl",@_); }
159 sub main'push   { &out1("pushl",@_); $stack+=4; }
160 sub main'pop    { &out1("popl",@_); $stack-=4; }
161 sub main'bswap  { &out1("bswapl",@_); }
162 sub main'not    { &out1("notl",@_); }
163 sub main'call   { &out1("call",$under.$_[0]); }
164 sub main'ret    { &out0("ret"); }
165 sub main'nop    { &out0("nop"); }
166
167 sub out2
168         {
169         local($name,$p1,$p2)=@_;
170         local($l,$ll,$t);
171         local(%special)=(       "roll",0xD1C0,"rorl",0xD1C8,
172                                 "rcll",0xD1D0,"rcrl",0xD1D8,
173                                 "shll",0xD1E0,"shrl",0xD1E8,
174                                 "sarl",0xD1F8);
175         
176         if ((defined($special{$name})) && defined($regs{$p1}) && ($p2 == 1))
177                 {
178                 $op=$special{$name}|$reg_val{$p1};
179                 $tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
180                 $tmp2=sprintf(".byte %d\t",$op     &0xff);
181                 push(@out,$tmp1);
182                 push(@out,$tmp2);
183
184                 $p2=&conv($p2);
185                 $p1=&conv($p1);
186                 &main'comment("$name $p2 $p1");
187                 return;
188                 }
189
190         push(@out,"\t$name\t");
191         $t=&conv($p2).",";
192         $l=length($t);
193         push(@out,$t);
194         $ll=4-($l+9)/8;
195         $tmp1=sprintf("\t" x $ll);
196         push(@out,$tmp1);
197         push(@out,&conv($p1)."\n");
198         }
199
200 sub out1
201         {
202         local($name,$p1)=@_;
203         local($l,$t);
204         local(%special)=("bswapl",0x0FC8);
205
206         if ((defined($special{$name})) && defined($regs{$p1}))
207                 {
208                 $op=$special{$name}|$reg_val{$p1};
209                 $tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
210                 $tmp2=sprintf(".byte %d\t",$op     &0xff);
211                 push(@out,$tmp1);
212                 push(@out,$tmp2);
213
214                 $p2=&conv($p2);
215                 $p1=&conv($p1);
216                 &main'comment("$name $p2 $p1");
217                 return;
218                 }
219
220         push(@out,"\t$name\t".&conv($p1)."\n");
221         }
222
223 sub out1p
224         {
225         local($name,$p1)=@_;
226         local($l,$t);
227
228         push(@out,"\t$name\t*".&conv($p1)."\n");
229         }
230
231 sub out0
232         {
233         push(@out,"\t$_[0]\n");
234         }
235
236 sub conv
237         {
238         local($p)=@_;
239
240 #       $p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
241
242         $p=$regs{$p} if (defined($regs{$p}));
243
244         $p =~ s/^(-{0,1}[0-9A-Fa-f]+)$/\$$1/;
245         $p =~ s/^(0x[0-9A-Fa-f]+)$/\$$1/;
246         return $p;
247         }
248
249 sub main'file
250         {
251         local($file)=@_;
252
253         local($tmp)=<<"EOF";
254         .file   "$file.s"
255         .version        "01.01"
256 gcc2_compiled.:
257 EOF
258         push(@out,$tmp);
259         }
260
261 sub main'function_begin
262         {
263         local($func)=@_;
264
265         &main'external_label($func);
266         $func=$under.$func;
267
268         local($tmp)=<<"EOF";
269 .text
270         .align $align
271 .globl $func
272 EOF
273         push(@out,$tmp);
274         if ($main'cpp)
275                 { $tmp=push(@out,"\tTYPE($func,\@function)\n"); }
276         else    { $tmp=push(@out,"\t.type\t$func,\@function\n"); }
277         push(@out,"$func:\n");
278         $tmp=<<"EOF";
279         pushl   %ebp
280         pushl   %ebx
281         pushl   %esi
282         pushl   %edi
283
284 EOF
285         push(@out,$tmp);
286         $stack=20;
287         }
288
289 sub main'function_begin_B
290         {
291         local($func,$extra)=@_;
292
293         &main'external_label($func);
294         $func=$under.$func;
295
296         local($tmp)=<<"EOF";
297 .text
298         .align $align
299 .globl $func
300 EOF
301         push(@out,$tmp);
302         if ($main'cpp)
303                 { push(@out,"\tTYPE($func,\@function)\n"); }
304         else    { push(@out,"\t.type    $func,\@function\n"); }
305         push(@out,"$func:\n");
306         $stack=4;
307         }
308
309 sub main'function_end
310         {
311         local($func)=@_;
312
313         $func=$under.$func;
314
315         local($tmp)=<<"EOF";
316         popl    %edi
317         popl    %esi
318         popl    %ebx
319         popl    %ebp
320         ret
321 .${func}_end:
322 EOF
323         push(@out,$tmp);
324         if ($main'cpp)
325                 { push(@out,"\tSIZE($func,.${func}_end-$func)\n"); }
326         else    { push(@out,"\t.size\t$func,.${func}_end-$func\n"); }
327         push(@out,".ident       \"$func\"\n");
328         $stack=0;
329         %label=();
330         }
331
332 sub main'function_end_A
333         {
334         local($func)=@_;
335
336         local($tmp)=<<"EOF";
337         popl    %edi
338         popl    %esi
339         popl    %ebx
340         popl    %ebp
341         ret
342 EOF
343         push(@out,$tmp);
344         }
345
346 sub main'function_end_B
347         {
348         local($func)=@_;
349
350         $func=$under.$func;
351
352         push(@out,".${func}_end:\n");
353         if ($main'cpp)
354                 { push(@out,"\tSIZE($func,.${func}_end-$func)\n"); }
355         else    { push(@out,"\t.size\t$func,.${func}_end-$func\n"); }
356         push(@out,".ident       \"desasm.pl\"\n");
357         $stack=0;
358         %label=();
359         }
360
361 sub main'wparam
362         {
363         local($num)=@_;
364
365         return(&main'DWP($stack+$num*4,"esp","",0));
366         }
367
368 sub main'stack_push
369         {
370         local($num)=@_;
371         $stack+=$num*4;
372         &main'sub("esp",$num*4);
373         }
374
375 sub main'stack_pop
376         {
377         local($num)=@_;
378         $stack-=$num*4;
379         &main'add("esp",$num*4);
380         }
381
382 sub main'swtmp
383         {
384         return(&main'DWP($_[0]*4,"esp","",0));
385         }
386
387 # Should use swtmp, which is above esp.  Linix can trash the stack above esp
388 #sub main'wtmp
389 #       {
390 #       local($num)=@_;
391 #
392 #       return(&main'DWP(-($num+1)*4,"esp","",0));
393 #       }
394
395 sub main'comment
396         {
397         foreach (@_)
398                 {
399                 if (/^\s*$/)
400                         { push(@out,"\n"); }
401                 else
402                         { push(@out,"\t$com_start $_ $com_end\n"); }
403                 }
404         }
405
406 sub main'label
407         {
408         if (!defined($label{$_[0]}))
409                 {
410                 $label{$_[0]}=".${label}${_[0]}";
411                 $label++;
412                 }
413         return($label{$_[0]});
414         }
415
416 sub main'set_label
417         {
418         if (!defined($label{$_[0]}))
419                 {
420                 $label{$_[0]}=".${label}${_[0]}";
421                 $label++;
422                 }
423         push(@out,".align $align\n") if ($_[1] != 0);
424         push(@out,"$label{$_[0]}:\n");
425         }
426
427 sub main'file_end
428         {
429         }
430
431 sub main'data_word
432         {
433         push(@out,"\t.long $_[0]\n");
434         }