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