summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/perlasm/x86unix.pl
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/perlasm/x86unix.pl')
-rw-r--r--src/lib/libcrypto/perlasm/x86unix.pl544
1 files changed, 544 insertions, 0 deletions
diff --git a/src/lib/libcrypto/perlasm/x86unix.pl b/src/lib/libcrypto/perlasm/x86unix.pl
new file mode 100644
index 0000000000..9ceabf0705
--- /dev/null
+++ b/src/lib/libcrypto/perlasm/x86unix.pl
@@ -0,0 +1,544 @@
1#!/usr/local/bin/perl
2
3package x86unix;
4
5$label="L000";
6$const="";
7$constl=0;
8
9$align=($main'aout)?"4":"16";
10$under=($main'aout)?"_":"";
11$com_start=($main'sol)?"/":"#";
12
13sub main'asm_init_output { @out=(); }
14sub main'asm_get_output { return(@out); }
15sub main'get_labels { return(@labels); }
16sub main'external_label { push(@labels,@_); }
17
18if ($main'cpp)
19 {
20 $align="ALIGN";
21 $under="";
22 $com_start='/*';
23 $com_end='*/';
24 }
25
26%lb=( 'eax', '%al',
27 'ebx', '%bl',
28 'ecx', '%cl',
29 'edx', '%dl',
30 'ax', '%al',
31 'bx', '%bl',
32 'cx', '%cl',
33 'dx', '%dl',
34 );
35
36%hb=( 'eax', '%ah',
37 'ebx', '%bh',
38 'ecx', '%ch',
39 'edx', '%dh',
40 'ax', '%ah',
41 'bx', '%bh',
42 'cx', '%ch',
43 'dx', '%dh',
44 );
45
46%regs=( 'eax', '%eax',
47 'ebx', '%ebx',
48 'ecx', '%ecx',
49 'edx', '%edx',
50 'esi', '%esi',
51 'edi', '%edi',
52 'ebp', '%ebp',
53 'esp', '%esp',
54 );
55
56%reg_val=(
57 'eax', 0x00,
58 'ebx', 0x03,
59 'ecx', 0x01,
60 'edx', 0x02,
61 'esi', 0x06,
62 'edi', 0x07,
63 'ebp', 0x05,
64 'esp', 0x04,
65 );
66
67sub main'LB
68 {
69 (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
70 return($lb{$_[0]});
71 }
72
73sub main'HB
74 {
75 (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
76 return($hb{$_[0]});
77 }
78
79sub main'DWP
80 {
81 local($addr,$reg1,$reg2,$idx)=@_;
82
83 $ret="";
84 $addr =~ s/(^|[+ \t])([A-Za-z_]+[A-Za-z0-9_]+)($|[+ \t])/$1$under$2$3/;
85 $reg1="$regs{$reg1}" if defined($regs{$reg1});
86 $reg2="$regs{$reg2}" if defined($regs{$reg2});
87 $ret.=$addr if ($addr ne "") && ($addr ne 0);
88 if ($reg2 ne "")
89 {
90 if($idx ne "")
91 { $ret.="($reg1,$reg2,$idx)"; }
92 else
93 { $ret.="($reg1,$reg2)"; }
94 }
95 else
96 { $ret.="($reg1)" }
97 return($ret);
98 }
99
100sub main'BP
101 {
102 return(&main'DWP(@_));
103 }
104
105sub main'BC
106 {
107 return @_;
108 }
109
110sub main'DWC
111 {
112 return @_;
113 }
114
115#sub main'BP
116# {
117# local($addr,$reg1,$reg2,$idx)=@_;
118#
119# $ret="";
120#
121# $addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/;
122# $reg1="$regs{$reg1}" if defined($regs{$reg1});
123# $reg2="$regs{$reg2}" if defined($regs{$reg2});
124# $ret.=$addr if ($addr ne "") && ($addr ne 0);
125# if ($reg2 ne "")
126# { $ret.="($reg1,$reg2,$idx)"; }
127# else
128# { $ret.="($reg1)" }
129# return($ret);
130# }
131
132sub main'mov { &out2("movl",@_); }
133sub main'movb { &out2("movb",@_); }
134sub main'and { &out2("andl",@_); }
135sub main'or { &out2("orl",@_); }
136sub main'shl { &out2("sall",@_); }
137sub main'shr { &out2("shrl",@_); }
138sub main'xor { &out2("xorl",@_); }
139sub main'xorb { &out2("xorb",@_); }
140sub main'add { &out2("addl",@_); }
141sub main'adc { &out2("adcl",@_); }
142sub main'sub { &out2("subl",@_); }
143sub main'rotl { &out2("roll",@_); }
144sub main'rotr { &out2("rorl",@_); }
145sub main'exch { &out2("xchg",@_); }
146sub main'cmp { &out2("cmpl",@_); }
147sub main'lea { &out2("leal",@_); }
148sub main'mul { &out1("mull",@_); }
149sub main'div { &out1("divl",@_); }
150sub main'jmp { &out1("jmp",@_); }
151sub main'jmp_ptr { &out1p("jmp",@_); }
152sub main'je { &out1("je",@_); }
153sub main'jle { &out1("jle",@_); }
154sub main'jne { &out1("jne",@_); }
155sub main'jnz { &out1("jnz",@_); }
156sub main'jz { &out1("jz",@_); }
157sub main'jge { &out1("jge",@_); }
158sub main'jl { &out1("jl",@_); }
159sub main'jb { &out1("jb",@_); }
160sub main'jc { &out1("jc",@_); }
161sub main'jnc { &out1("jnc",@_); }
162sub main'jno { &out1("jno",@_); }
163sub main'dec { &out1("decl",@_); }
164sub main'inc { &out1("incl",@_); }
165sub main'push { &out1("pushl",@_); $stack+=4; }
166sub main'pop { &out1("popl",@_); $stack-=4; }
167sub main'pushf { &out0("pushf"); $stack+=4; }
168sub main'popf { &out0("popf"); $stack-=4; }
169sub main'not { &out1("notl",@_); }
170sub main'call { &out1("call",$under.$_[0]); }
171sub main'ret { &out0("ret"); }
172sub main'nop { &out0("nop"); }
173
174# The bswapl instruction is new for the 486. Emulate if i386.
175sub main'bswap
176 {
177 if ($main'i386)
178 {
179 &main'comment("bswapl @_");
180 &main'exch(main'HB(@_),main'LB(@_));
181 &main'rotr(@_,16);
182 &main'exch(main'HB(@_),main'LB(@_));
183 }
184 else
185 {
186 &out1("bswapl",@_);
187 }
188 }
189
190sub out2
191 {
192 local($name,$p1,$p2)=@_;
193 local($l,$ll,$t);
194 local(%special)=( "roll",0xD1C0,"rorl",0xD1C8,
195 "rcll",0xD1D0,"rcrl",0xD1D8,
196 "shll",0xD1E0,"shrl",0xD1E8,
197 "sarl",0xD1F8);
198
199 if ((defined($special{$name})) && defined($regs{$p1}) && ($p2 == 1))
200 {
201 $op=$special{$name}|$reg_val{$p1};
202 $tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
203 $tmp2=sprintf(".byte %d\t",$op &0xff);
204 push(@out,$tmp1);
205 push(@out,$tmp2);
206
207 $p2=&conv($p2);
208 $p1=&conv($p1);
209 &main'comment("$name $p2 $p1");
210 return;
211 }
212
213 push(@out,"\t$name\t");
214 $t=&conv($p2).",";
215 $l=length($t);
216 push(@out,$t);
217 $ll=4-($l+9)/8;
218 $tmp1=sprintf("\t" x $ll);
219 push(@out,$tmp1);
220 push(@out,&conv($p1)."\n");
221 }
222
223sub out1
224 {
225 local($name,$p1)=@_;
226 local($l,$t);
227 local(%special)=("bswapl",0x0FC8);
228
229 if ((defined($special{$name})) && defined($regs{$p1}))
230 {
231 $op=$special{$name}|$reg_val{$p1};
232 $tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
233 $tmp2=sprintf(".byte %d\t",$op &0xff);
234 push(@out,$tmp1);
235 push(@out,$tmp2);
236
237 $p2=&conv($p2);
238 $p1=&conv($p1);
239 &main'comment("$name $p2 $p1");
240 return;
241 }
242
243 push(@out,"\t$name\t".&conv($p1)."\n");
244 }
245
246sub out1p
247 {
248 local($name,$p1)=@_;
249 local($l,$t);
250
251 push(@out,"\t$name\t*".&conv($p1)."\n");
252 }
253
254sub out0
255 {
256 push(@out,"\t$_[0]\n");
257 }
258
259sub conv
260 {
261 local($p)=@_;
262
263# $p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
264
265 $p=$regs{$p} if (defined($regs{$p}));
266
267 $p =~ s/^(-{0,1}[0-9A-Fa-f]+)$/\$$1/;
268 $p =~ s/^(0x[0-9A-Fa-f]+)$/\$$1/;
269 return $p;
270 }
271
272sub main'file
273 {
274 local($file)=@_;
275
276 local($tmp)=<<"EOF";
277 .file "$file.s"
278 .version "01.01"
279gcc2_compiled.:
280EOF
281 push(@out,$tmp);
282 }
283
284sub main'function_begin
285 {
286 local($func)=@_;
287
288 &main'external_label($func);
289 $func=$under.$func;
290
291 local($tmp)=<<"EOF";
292.text
293 .align $align
294.globl $func
295EOF
296 push(@out,$tmp);
297 if ($main'cpp)
298 { $tmp=push(@out,"\tTYPE($func,\@function)\n"); }
299 elsif ($main'gaswin)
300 { $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
301 else { $tmp=push(@out,"\t.type\t$func,\@function\n"); }
302 push(@out,"$func:\n");
303 $tmp=<<"EOF";
304 pushl %ebp
305 pushl %ebx
306 pushl %esi
307 pushl %edi
308
309EOF
310 push(@out,$tmp);
311 $stack=20;
312 }
313
314sub main'function_begin_B
315 {
316 local($func,$extra)=@_;
317
318 &main'external_label($func);
319 $func=$under.$func;
320
321 local($tmp)=<<"EOF";
322.text
323 .align $align
324.globl $func
325EOF
326 push(@out,$tmp);
327 if ($main'cpp)
328 { push(@out,"\tTYPE($func,\@function)\n"); }
329 elsif ($main'gaswin)
330 { $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
331 else { push(@out,"\t.type $func,\@function\n"); }
332 push(@out,"$func:\n");
333 $stack=4;
334 }
335
336sub main'function_end
337 {
338 local($func)=@_;
339
340 $func=$under.$func;
341
342 local($tmp)=<<"EOF";
343 popl %edi
344 popl %esi
345 popl %ebx
346 popl %ebp
347 ret
348.${func}_end:
349EOF
350 push(@out,$tmp);
351
352 if ($main'cpp)
353 { push(@out,"\tSIZE($func,.${func}_end-$func)\n"); }
354 elsif ($main'gaswin)
355 { $tmp=push(@out,"\t.align 4\n"); }
356 else { push(@out,"\t.size\t$func,.${func}_end-$func\n"); }
357 push(@out,".ident \"$func\"\n");
358 $stack=0;
359 %label=();
360 }
361
362sub main'function_end_A
363 {
364 local($func)=@_;
365
366 local($tmp)=<<"EOF";
367 popl %edi
368 popl %esi
369 popl %ebx
370 popl %ebp
371 ret
372EOF
373 push(@out,$tmp);
374 }
375
376sub main'function_end_B
377 {
378 local($func)=@_;
379
380 $func=$under.$func;
381
382 push(@out,".L_${func}_end:\n");
383 if ($main'cpp)
384 { push(@out,"\tSIZE($func,.L_${func}_end-$func)\n"); }
385 elsif ($main'gaswin)
386 { push(@out,"\t.align 4\n"); }
387 else { push(@out,"\t.size\t$func,.L_${func}_end-$func\n"); }
388 push(@out,".ident \"desasm.pl\"\n");
389 $stack=0;
390 %label=();
391 }
392
393sub main'wparam
394 {
395 local($num)=@_;
396
397 return(&main'DWP($stack+$num*4,"esp","",0));
398 }
399
400sub main'stack_push
401 {
402 local($num)=@_;
403 $stack+=$num*4;
404 &main'sub("esp",$num*4);
405 }
406
407sub main'stack_pop
408 {
409 local($num)=@_;
410 $stack-=$num*4;
411 &main'add("esp",$num*4);
412 }
413
414sub main'swtmp
415 {
416 return(&main'DWP($_[0]*4,"esp","",0));
417 }
418
419# Should use swtmp, which is above esp. Linix can trash the stack above esp
420#sub main'wtmp
421# {
422# local($num)=@_;
423#
424# return(&main'DWP(-($num+1)*4,"esp","",0));
425# }
426
427sub main'comment
428 {
429 foreach (@_)
430 {
431 if (/^\s*$/)
432 { push(@out,"\n"); }
433 else
434 { push(@out,"\t$com_start $_ $com_end\n"); }
435 }
436 }
437
438sub main'label
439 {
440 if (!defined($label{$_[0]}))
441 {
442 $label{$_[0]}=".${label}${_[0]}";
443 $label++;
444 }
445 return($label{$_[0]});
446 }
447
448sub main'set_label
449 {
450 if (!defined($label{$_[0]}))
451 {
452 $label{$_[0]}=".${label}${_[0]}";
453 $label++;
454 }
455 push(@out,".align $align\n") if ($_[1] != 0);
456 push(@out,"$label{$_[0]}:\n");
457 }
458
459sub main'file_end
460 {
461 if ($const ne "")
462 {
463 push(@out,".section .rodata\n");
464 push(@out,$const);
465 $const="";
466 }
467 }
468
469sub main'data_word
470 {
471 push(@out,"\t.long $_[0]\n");
472 }
473
474# debug output functions: puts, putx, printf
475
476sub main'puts
477 {
478 &pushvars();
479 &main'push('$Lstring' . ++$constl);
480 &main'call('puts');
481 $stack-=4;
482 &main'add("esp",4);
483 &popvars();
484
485 $const .= "Lstring$constl:\n\t.string \"@_[0]\"\n";
486 }
487
488sub main'putx
489 {
490 &pushvars();
491 &main'push($_[0]);
492 &main'push('$Lstring' . ++$constl);
493 &main'call('printf');
494 &main'add("esp",8);
495 $stack-=8;
496 &popvars();
497
498 $const .= "Lstring$constl:\n\t.string \"\%X\"\n";
499 }
500
501sub main'printf
502 {
503 $ostack = $stack;
504 &pushvars();
505 for ($i = @_ - 1; $i >= 0; $i--)
506 {
507 if ($i == 0) # change this to support %s format strings
508 {
509 &main'push('$Lstring' . ++$constl);
510 $const .= "Lstring$constl:\n\t.string \"@_[$i]\"\n";
511 }
512 else
513 {
514 if ($_[$i] =~ /([0-9]*)\(%esp\)/)
515 {
516 &main'push(($1 + $stack - $ostack) . '(%esp)');
517 }
518 else
519 {
520 &main'push($_[$i]);
521 }
522 }
523 }
524 &main'call('printf');
525 $stack-=4*@_;
526 &main'add("esp",4*@_);
527 &popvars();
528 }
529
530sub pushvars
531 {
532 &main'pushf();
533 &main'push("edx");
534 &main'push("ecx");
535 &main'push("eax");
536 }
537
538sub popvars
539 {
540 &main'pop("eax");
541 &main'pop("ecx");
542 &main'pop("edx");
543 &main'popf();
544 }