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.pl628
1 files changed, 628 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..b61425e951
--- /dev/null
+++ b/src/lib/libcrypto/perlasm/x86unix.pl
@@ -0,0 +1,628 @@
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($_[0]=~/%[a-d][lh]/?"addb":"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($_[0]=~/%[a-d][lh]/?"xchgb":"xchgl",@_); }
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($_[0]=~/%[a-d][hl]/?"incb":"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"); }
182sub main'test { &out2("testl",@_); }
183sub main'movz { &out2("movzbl",@_); }
184sub main'neg { &out1("negl",@_); }
185
186# The bswapl instruction is new for the 486. Emulate if i386.
187sub main'bswap
188 {
189 if ($main'i386)
190 {
191 &main'comment("bswapl @_");
192 &main'exch(main'HB(@_),main'LB(@_));
193 &main'rotr(@_,16);
194 &main'exch(main'HB(@_),main'LB(@_));
195 }
196 else
197 {
198 &out1("bswapl",@_);
199 }
200 }
201
202sub out2
203 {
204 local($name,$p1,$p2)=@_;
205 local($l,$ll,$t);
206 local(%special)=( "roll",0xD1C0,"rorl",0xD1C8,
207 "rcll",0xD1D0,"rcrl",0xD1D8,
208 "shll",0xD1E0,"shrl",0xD1E8,
209 "sarl",0xD1F8);
210
211 if ((defined($special{$name})) && defined($regs{$p1}) && ($p2 == 1))
212 {
213 $op=$special{$name}|$reg_val{$p1};
214 $tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
215 $tmp2=sprintf(".byte %d\t",$op &0xff);
216 push(@out,$tmp1);
217 push(@out,$tmp2);
218
219 $p2=&conv($p2);
220 $p1=&conv($p1);
221 &main'comment("$name $p2 $p1");
222 return;
223 }
224
225 push(@out,"\t$name\t");
226 $t=&conv($p2).",";
227 $l=length($t);
228 push(@out,$t);
229 $ll=4-($l+9)/8;
230 $tmp1=sprintf("\t" x $ll);
231 push(@out,$tmp1);
232 push(@out,&conv($p1)."\n");
233 }
234
235sub out1
236 {
237 local($name,$p1)=@_;
238 local($l,$t);
239 local(%special)=("bswapl",0x0FC8);
240
241 if ((defined($special{$name})) && defined($regs{$p1}))
242 {
243 $op=$special{$name}|$reg_val{$p1};
244 $tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
245 $tmp2=sprintf(".byte %d\t",$op &0xff);
246 push(@out,$tmp1);
247 push(@out,$tmp2);
248
249 $p2=&conv($p2);
250 $p1=&conv($p1);
251 &main'comment("$name $p2 $p1");
252 return;
253 }
254
255 push(@out,"\t$name\t".&conv($p1)."\n");
256 }
257
258sub out1p
259 {
260 local($name,$p1)=@_;
261 local($l,$t);
262
263 push(@out,"\t$name\t*".&conv($p1)."\n");
264 }
265
266sub out0
267 {
268 push(@out,"\t$_[0]\n");
269 }
270
271sub conv
272 {
273 local($p)=@_;
274
275# $p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
276
277 $p=$regs{$p} if (defined($regs{$p}));
278
279 $p =~ s/^(-{0,1}[0-9A-Fa-f]+)$/\$$1/;
280 $p =~ s/^(0x[0-9A-Fa-f]+)$/\$$1/;
281 return $p;
282 }
283
284sub main'file
285 {
286 local($file)=@_;
287
288 if ($main'openbsd)
289 { push(@out,"#include <machine/asm.h>\n"); return; }
290
291 local($tmp)=<<"EOF";
292 .file "$file.s"
293 .version "01.01"
294gcc2_compiled.:
295EOF
296 push(@out,$tmp);
297 }
298
299sub main'function_begin
300 {
301 local($func)=@_;
302
303 &main'external_label($func);
304 $func=$under.$func;
305
306 if ($main'openbsd)
307 { push (@out, "\nENTRY($func)\n"); goto skip; }
308
309 local($tmp)=<<"EOF";
310.text
311 .align $align
312.globl $func
313EOF
314 push(@out,$tmp);
315 if ($main'cpp)
316 { $tmp=push(@out,"\tTYPE($func,\@function)\n"); }
317 elsif ($main'gaswin)
318 { $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
319 else { $tmp=push(@out,"\t.type\t$func,\@function\n"); }
320 push(@out,"$func:\n");
321skip:
322 $tmp=<<"EOF";
323 pushl %ebp
324 pushl %ebx
325 pushl %esi
326 pushl %edi
327
328EOF
329 push(@out,$tmp);
330 $stack=20;
331 }
332
333sub main'function_begin_B
334 {
335 local($func,$extra)=@_;
336
337 &main'external_label($func);
338 $func=$under.$func;
339
340 if ($main'openbsd)
341 { push(@out, "\nENTRY($func)\n"); goto skip; }
342
343 local($tmp)=<<"EOF";
344.text
345 .align $align
346.globl $func
347EOF
348 push(@out,$tmp);
349 if ($main'cpp)
350 { push(@out,"\tTYPE($func,\@function)\n"); }
351 elsif ($main'gaswin)
352 { $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
353 else { push(@out,"\t.type $func,\@function\n"); }
354 push(@out,"$func:\n");
355skip:
356 $stack=4;
357 }
358
359sub main'function_end
360 {
361 local($func)=@_;
362
363 $func=$under.$func;
364
365 local($tmp)=<<"EOF";
366 popl %edi
367 popl %esi
368 popl %ebx
369 popl %ebp
370 ret
371.L_${func}_end:
372EOF
373 push(@out,$tmp);
374
375 if ($main'cpp)
376 { push(@out,"\tSIZE($func,.L_${func}_end-$func)\n"); }
377 elsif ($main'gaswin)
378 { $tmp=push(@out,"\t.align 4\n"); }
379 else { push(@out,"\t.size\t$func,.L_${func}_end-$func\n"); }
380 push(@out,".ident \"$func\"\n");
381 $stack=0;
382 %label=();
383 }
384
385sub main'function_end_A
386 {
387 local($func)=@_;
388
389 local($tmp)=<<"EOF";
390 popl %edi
391 popl %esi
392 popl %ebx
393 popl %ebp
394 ret
395EOF
396 push(@out,$tmp);
397 }
398
399sub main'function_end_B
400 {
401 local($func)=@_;
402
403 $func=$under.$func;
404
405 push(@out,".L_${func}_end:\n");
406 if ($main'cpp)
407 { push(@out,"\tSIZE($func,.L_${func}_end-$func)\n"); }
408 elsif ($main'gaswin)
409 { push(@out,"\t.align 4\n"); }
410 else { push(@out,"\t.size\t$func,.L_${func}_end-$func\n"); }
411 push(@out,".ident \"desasm.pl\"\n");
412 $stack=0;
413 %label=();
414 }
415
416sub main'wparam
417 {
418 local($num)=@_;
419
420 return(&main'DWP($stack+$num*4,"esp","",0));
421 }
422
423sub main'stack_push
424 {
425 local($num)=@_;
426 $stack+=$num*4;
427 &main'sub("esp",$num*4);
428 }
429
430sub main'stack_pop
431 {
432 local($num)=@_;
433 $stack-=$num*4;
434 &main'add("esp",$num*4);
435 }
436
437sub main'swtmp
438 {
439 return(&main'DWP($_[0]*4,"esp","",0));
440 }
441
442# Should use swtmp, which is above esp. Linix can trash the stack above esp
443#sub main'wtmp
444# {
445# local($num)=@_;
446#
447# return(&main'DWP(-($num+1)*4,"esp","",0));
448# }
449
450sub main'comment
451 {
452 if (!$main'openbsd && $main'elf)
453 # GNU and SVR4 as'es use different comment delimiters,
454 { # so we just skip comments...
455 push(@out,"\n");
456 return;
457 }
458 foreach (@_)
459 {
460 if (/^\s*$/)
461 { push(@out,"\n"); }
462 else
463 { push(@out,"\t$com_start $_ $com_end\n"); }
464 }
465 }
466
467sub main'public_label
468 {
469 $label{$_[0]}="${under}${_[0]}" if (!defined($label{$_[0]}));
470 push(@out,".globl\t$label{$_[0]}\n");
471 }
472
473sub main'label
474 {
475 if (!defined($label{$_[0]}))
476 {
477 $label{$_[0]}=".${label}${_[0]}";
478 $label++;
479 }
480 return($label{$_[0]});
481 }
482
483sub main'set_label
484 {
485 if (!defined($label{$_[0]}))
486 {
487 $label{$_[0]}=".${label}${_[0]}";
488 $label++;
489 }
490 if ($main'openbsd)
491 { push(@out,"_ALIGN_TEXT\n") if ($_[1] != 0); }
492 else
493 { push(@out,".align $align\n") if ($_[1] != 0); }
494 push(@out,"$label{$_[0]}:\n");
495 }
496
497sub main'file_end
498 {
499 if ($const ne "")
500 {
501 push(@out,".section .rodata\n");
502 push(@out,$const);
503 $const="";
504 }
505 }
506
507sub main'data_word
508 {
509 push(@out,"\t.long\t".join(',',@_)."\n");
510 }
511
512# debug output functions: puts, putx, printf
513
514sub main'puts
515 {
516 &pushvars();
517 &main'push('$Lstring' . ++$constl);
518 &main'call('puts');
519 $stack-=4;
520 &main'add("esp",4);
521 &popvars();
522
523 $const .= "Lstring$constl:\n\t.string \"@_[0]\"\n";
524 }
525
526sub main'putx
527 {
528 &pushvars();
529 &main'push($_[0]);
530 &main'push('$Lstring' . ++$constl);
531 &main'call('printf');
532 &main'add("esp",8);
533 $stack-=8;
534 &popvars();
535
536 $const .= "Lstring$constl:\n\t.string \"\%X\"\n";
537 }
538
539sub main'printf
540 {
541 $ostack = $stack;
542 &pushvars();
543 for ($i = @_ - 1; $i >= 0; $i--)
544 {
545 if ($i == 0) # change this to support %s format strings
546 {
547 &main'push('$Lstring' . ++$constl);
548 $const .= "Lstring$constl:\n\t.string \"@_[$i]\"\n";
549 }
550 else
551 {
552 if ($_[$i] =~ /([0-9]*)\(%esp\)/)
553 {
554 &main'push(($1 + $stack - $ostack) . '(%esp)');
555 }
556 else
557 {
558 &main'push($_[$i]);
559 }
560 }
561 }
562 &main'call('printf');
563 $stack-=4*@_;
564 &main'add("esp",4*@_);
565 &popvars();
566 }
567
568sub pushvars
569 {
570 &main'pushf();
571 &main'push("edx");
572 &main'push("ecx");
573 &main'push("eax");
574 }
575
576sub popvars
577 {
578 &main'pop("eax");
579 &main'pop("ecx");
580 &main'pop("edx");
581 &main'popf();
582 }
583
584sub main'picmeup
585 {
586 local($dst,$sym)=@_;
587 if ($main'cpp)
588 {
589 local($tmp)=<<___;
590#if (defined(ELF) || defined(SOL)) && defined(PIC)
591 .align 8
592 call 1f
5931: popl $regs{$dst}
594 addl \$_GLOBAL_OFFSET_TABLE_+[.-1b],$regs{$dst}
595 movl $sym\@GOT($regs{$dst}),$regs{$dst}
596#else
597 leal $sym,$regs{$dst}
598#endif
599___
600 push(@out,$tmp);
601 }
602 elsif ($main'openbsd)
603 {
604 push(@out, "#ifdef PIC\n");
605 push(@out, "\tPIC_PROLOGUE\n");
606 &main'mov($dst,"PIC_GOT($sym)");
607 push(@out, "\tPIC_EPILOGUE\n");
608 push(@out, "#else\n");
609 &main'lea($dst,&main'DWP($sym));
610 push(@out, "#endif\n");
611 }
612 elsif ($main'pic && ($main'elf || $main'aout))
613 {
614 push(@out,"\t.align\t8\n");
615 &main'call(&main'label("PIC_me_up"));
616 &main'set_label("PIC_me_up");
617 &main'blindpop($dst);
618 &main'add($dst,"\$$under"."_GLOBAL_OFFSET_TABLE_+[.-".
619 &main'label("PIC_me_up") . "]");
620 &main'mov($dst,&main'DWP($sym."\@GOT",$dst));
621 }
622 else
623 {
624 &main'lea($dst,&main'DWP($sym));
625 }
626 }
627
628sub main'blindpop { &out1("popl",@_); }