X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fperlasm%2Fx86unix.pl;h=7d87eb1701bf53edf35ab407b3b438b38dad7577;hp=bb9c6925d8d8ec62d01e1ce58452f3412303817a;hb=07d488daf66ed88a7b2758325eed7e45fac0aafb;hpb=0c34556cbd509afc84d5a6796d463122408a028b diff --git a/crypto/perlasm/x86unix.pl b/crypto/perlasm/x86unix.pl index bb9c6925d8..7d87eb1701 100644 --- a/crypto/perlasm/x86unix.pl +++ b/crypto/perlasm/x86unix.pl @@ -1,14 +1,15 @@ #!/usr/local/bin/perl -package x86unix; +package x86unix; # GAS actually... $label="L000"; $const=""; $constl=0; $align=($main'aout)?"4":"16"; -$under=($main'aout)?"_":""; -$com_start=($main'sol)?"/":"#"; +$under=($main'aout or $main'coff)?"_":""; +$dot=($main'aout)?"":"."; +$com_start="#" if ($main'aout or $main'coff); sub main'asm_init_output { @out=(); } sub main'asm_get_output { return(@out); } @@ -51,6 +52,24 @@ if ($main'cpp) 'edi', '%edi', 'ebp', '%ebp', 'esp', '%esp', + + 'mm0', '%mm0', + 'mm1', '%mm1', + 'mm2', '%mm2', + 'mm3', '%mm3', + 'mm4', '%mm4', + 'mm5', '%mm5', + 'mm6', '%mm6', + 'mm7', '%mm7', + + 'xmm0', '%xmm0', + 'xmm1', '%xmm1', + 'xmm2', '%xmm2', + 'xmm3', '%xmm3', + 'xmm4', '%xmm4', + 'xmm5', '%xmm5', + 'xmm6', '%xmm6', + 'xmm7', '%xmm7', ); %reg_val=( @@ -81,22 +100,27 @@ sub main'DWP local($addr,$reg1,$reg2,$idx)=@_; $ret=""; - $addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/; + $addr =~ s/(^|[+ \t])([A-Za-z_]+[A-Za-z0-9_]+)($|[+ \t])/$1$under$2$3/; $reg1="$regs{$reg1}" if defined($regs{$reg1}); $reg2="$regs{$reg2}" if defined($regs{$reg2}); $ret.=$addr if ($addr ne "") && ($addr ne 0); if ($reg2 ne "") { - if($idx ne "") + if($idx ne "" && $idx != 0) { $ret.="($reg1,$reg2,$idx)"; } else { $ret.="($reg1,$reg2)"; } } - else + elsif ($reg1 ne "") { $ret.="($reg1)" } return($ret); } +sub main'QWP + { + return(&main'DWP(@_)); + } + sub main'BP { return(&main'DWP(@_)); @@ -140,6 +164,7 @@ sub main'xorb { &out2("xorb",@_); } sub main'add { &out2("addl",@_); } sub main'adc { &out2("adcl",@_); } sub main'sub { &out2("subl",@_); } +sub main'sbb { &out2("sbbl",@_); } sub main'rotl { &out2("roll",@_); } sub main'rotr { &out2("rorl",@_); } sub main'exch { &out2("xchg",@_); } @@ -156,7 +181,10 @@ sub main'jnz { &out1("jnz",@_); } sub main'jz { &out1("jz",@_); } sub main'jge { &out1("jge",@_); } sub main'jl { &out1("jl",@_); } +sub main'ja { &out1("ja",@_); } +sub main'jae { &out1("jae",@_); } sub main'jb { &out1("jb",@_); } +sub main'jbe { &out1("jbe",@_); } sub main'jc { &out1("jc",@_); } sub main'jnc { &out1("jnc",@_); } sub main'jno { &out1("jno",@_); } @@ -164,10 +192,38 @@ sub main'dec { &out1("decl",@_); } sub main'inc { &out1("incl",@_); } sub main'push { &out1("pushl",@_); $stack+=4; } sub main'pop { &out1("popl",@_); $stack-=4; } +sub main'pushf { &out0("pushfl"); $stack+=4; } +sub main'popf { &out0("popfl"); $stack-=4; } sub main'not { &out1("notl",@_); } -sub main'call { &out1("call",$under.$_[0]); } +sub main'call { my $pre=$under; + foreach $i (%label) + { if ($label{$i} eq $_[0]) { $pre=''; last; } } + &out1("call",$pre.$_[0]); + } sub main'ret { &out0("ret"); } sub main'nop { &out0("nop"); } +sub main'test { &out2("testl",@_); } +sub main'bt { &out2("btl",@_); } +sub main'leave { &out0("leave"); } +sub main'cpuid { &out0(".byte 0x0f; .byte 0xa2"); } +sub main'rdtsc { &out0(".byte 0x0f; .byte 0x31"); } +sub main'halt { &out0("hlt"); } + +# SSE2 +sub main'emms { &out0("emms"); } +sub main'movd { &out2("movd",@_); } +sub main'movq { &out2("movq",@_); } +sub main'movdqu { &out2("movdqu",@_); } +sub main'movdqa { &out2("movdqa",@_); } +sub main'movdq2q{ &out2("movdq2q",@_); } +sub main'movq2dq{ &out2("movq2dq",@_); } +sub main'paddq { &out2("paddq",@_); } +sub main'pmuludq{ &out2("pmuludq",@_); } +sub main'psrlq { &out2("psrlq",@_); } +sub main'psllq { &out2("psllq",@_); } +sub main'pxor { &out2("pxor",@_); } +sub main'por { &out2("por",@_); } +sub main'pand { &out2("pand",@_); } # The bswapl instruction is new for the 486. Emulate if i386. sub main'bswap @@ -273,8 +329,6 @@ sub main'file local($tmp)=<<"EOF"; .file "$file.s" - .version "01.01" -gcc2_compiled.: EOF push(@out,$tmp); } @@ -288,15 +342,17 @@ sub main'function_begin local($tmp)=<<"EOF"; .text - .align $align -.globl $func +.globl $func EOF push(@out,$tmp); if ($main'cpp) - { $tmp=push(@out,"\tTYPE($func,\@function)\n"); } - elsif ($main'gaswin) - { $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); } - else { $tmp=push(@out,"\t.type\t$func,\@function\n"); } + { $tmp=push(@out,"TYPE($func,\@function)\n"); } + elsif ($main'coff) + { $tmp=push(@out,".def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); } + elsif ($main'aout and !$main'pic) + { } + else { $tmp=push(@out,".type\t$func,\@function\n"); } + push(@out,".align\t$align\n"); push(@out,"$func:\n"); $tmp=<<"EOF"; pushl %ebp @@ -318,15 +374,17 @@ sub main'function_begin_B local($tmp)=<<"EOF"; .text - .align $align -.globl $func +.globl $func EOF push(@out,$tmp); if ($main'cpp) - { push(@out,"\tTYPE($func,\@function)\n"); } - elsif ($main'gaswin) - { $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); } - else { push(@out,"\t.type $func,\@function\n"); } + { push(@out,"TYPE($func,\@function)\n"); } + elsif ($main'coff) + { $tmp=push(@out,".def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); } + elsif ($main'aout and !$main'pic) + { } + else { push(@out,".type $func,\@function\n"); } + push(@out,".align\t$align\n"); push(@out,"$func:\n"); $stack=4; } @@ -343,17 +401,15 @@ sub main'function_end popl %ebx popl %ebp ret -$const -.${func}_end: +${dot}L_${func}_end: EOF push(@out,$tmp); - $const=""; if ($main'cpp) - { push(@out,"\tSIZE($func,.${func}_end-$func)\n"); } - elsif ($main'gaswin) - { $tmp=push(@out,"\t.align 4\n"); } - else { push(@out,"\t.size\t$func,.${func}_end-$func\n"); } + { push(@out,"SIZE($func,${dot}L_${func}_end-$func)\n"); } + elsif ($main'coff or $main'aout) + { } + else { push(@out,".size\t$func,${dot}L_${func}_end-$func\n"); } push(@out,".ident \"$func\"\n"); $stack=0; %label=(); @@ -379,13 +435,13 @@ sub main'function_end_B $func=$under.$func; - push(@out,".L_${func}_end:\n"); + push(@out,"${dot}L_${func}_end:\n"); if ($main'cpp) - { push(@out,"\tSIZE($func,.L_${func}_end-$func)\n"); } - elsif ($main'gaswin) - { push(@out,"\t.align 4\n"); } - else { push(@out,"\t.size\t$func,.L_${func}_end-$func\n"); } - push(@out,".ident \"desasm.pl\"\n"); + { push(@out,"SIZE($func,${dot}L_${func}_end-$func)\n"); } + elsif ($main'coff or $main'aout) + { } + else { push(@out,".size\t$func,${dot}L_${func}_end-$func\n"); } + push(@out,".ident \"$func\"\n"); $stack=0; %label=(); } @@ -426,6 +482,12 @@ sub main'swtmp sub main'comment { + if (!defined($com_start) or $main'elf) + { # Regarding $main'elf above... + # GNU and SVR4 as'es use different comment delimiters, + push(@out,"\n"); # so we just skip ELF comments... + return; + } foreach (@_) { if (/^\s*$/) @@ -439,7 +501,7 @@ sub main'label { if (!defined($label{$_[0]})) { - $label{$_[0]}=".${label}${_[0]}"; + $label{$_[0]}="${dot}${label}${_[0]}"; $label++; } return($label{$_[0]}); @@ -449,20 +511,86 @@ sub main'set_label { if (!defined($label{$_[0]})) { - $label{$_[0]}=".${label}${_[0]}"; + $label{$_[0]}="${dot}${label}${_[0]}"; $label++; } - push(@out,".align $align\n") if ($_[1] != 0); + if ($_[1]!=0) + { + if ($_[1]>1) { main'align($_[1]); } + else { push(@out,".align $align\n"); } + } push(@out,"$label{$_[0]}:\n"); } sub main'file_end { + # try to detect if SSE2 or MMX extensions were used on ELF platform... + if ($main'elf && grep {/%[x]*mm[0-7]/i} @out) { + local($tmp); + + push (@out,"\n.comm\t${under}OPENSSL_ia32cap_P,4,4\n"); + + push (@out,".section\t.init\n"); + # One can argue that it's wasteful to craft every + # SSE/MMX module with this snippet... Well, it's 72 + # bytes long and for the moment we have two modules. + # Let's argue when we have 7 modules or so... + # + # $1<<10 sets a reserved bit to signal that variable + # was initialized already... + &main'picmeup("edx","OPENSSL_ia32cap_P"); + $tmp=<<___; + cmpl \$0,(%edx) + jne 1f + movl \$1<<10,(%edx) + pushf + popl %eax + movl %eax,%ecx + xorl \$1<<21,%eax + pushl %eax + popf + pushf + popl %eax + xorl %ecx,%eax + btl \$21,%eax + jnc 1f + pushl %edi + pushl %ebx + movl %edx,%edi + movl \$1,%eax + .byte 0x0f; .byte 0xa2 + orl \$1<<10,%edx + movl %edx,0(%edi) + popl %ebx + popl %edi + .align $align + 1: +___ + push (@out,$tmp); + } + + if ($const ne "") + { + push(@out,".section .rodata\n"); + push(@out,$const); + $const=""; + } } sub main'data_word { - push(@out,"\t.long $_[0]\n"); + push(@out,"\t.long\t".join(',',@_)."\n"); + } + +sub main'align + { + my $val=$_[0],$p2,$i; + if ($main'aout) { + for ($p2=0;$val!=0;$val>>=1) { $p2++; } + $val=$p2-1; + $val.=",0x90"; + } + push(@out,".align\t$val\n"); } # debug output functions: puts, putx, printf @@ -523,6 +651,7 @@ sub main'printf sub pushvars { + &main'pushf(); &main'push("edx"); &main'push("ecx"); &main'push("eax"); @@ -533,4 +662,75 @@ sub popvars &main'pop("eax"); &main'pop("ecx"); &main'pop("edx"); + &main'popf(); + } + +sub main'picmeup + { + local($dst,$sym)=@_; + if ($main'cpp) + { + local($tmp)=<<___; +#if (defined(ELF) || defined(SOL)) && defined(PIC) + call 1f +1: popl $regs{$dst} + addl \$_GLOBAL_OFFSET_TABLE_+[.-1b],$regs{$dst} + movl $sym\@GOT($regs{$dst}),$regs{$dst} +#else + leal $sym,$regs{$dst} +#endif +___ + push(@out,$tmp); + } + elsif ($main'pic && ($main'elf || $main'aout)) + { + &main'call(&main'label("PIC_me_up")); + &main'set_label("PIC_me_up"); + &main'blindpop($dst); + &main'add($dst,"\$${under}_GLOBAL_OFFSET_TABLE_+[.-". + &main'label("PIC_me_up") . "]"); + &main'mov($dst,&main'DWP($under.$sym."\@GOT",$dst)); + } + else + { + &main'lea($dst,&main'DWP($sym)); + } + } + +sub main'blindpop { &out1("popl",@_); } + +sub main'initseg + { + local($f)=@_; + local($tmp); + if ($main'elf) + { + $tmp=<<___; +.section .init + call $under$f + .align $align +___ + } + elsif ($main'coff) + { + $tmp=<<___; # applies to both Cygwin and Mingw +.section .ctors +.long $under$f +___ + } + elsif ($main'aout) + { + local($ctor)="${under}_GLOBAL_\$I\$$f"; + $tmp=".text\n"; + $tmp.=".type $ctor,\@function\n" if ($main'pic); + $tmp.=<<___; # OpenBSD way... +.globl $ctor +.align 2 +$ctor: + jmp $under$f +___ + } + push(@out,$tmp) if ($tmp); } + +1;