#!/usr/local/bin/perl
-# Because the bswapl instruction is not supported for old assembers
-# (it was a new instruction for the 486), I've added .byte xxxx code
-# to put it in.
-# eric 24-Apr-1998
-#
-
package x86unix;
$label="L000";
+$const="";
+$constl=0;
$align=($main'aout)?"4":"16";
$under=($main'aout)?"_":"";
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 "")
- { $ret.="($reg1,$reg2,$idx)"; }
- else
+ {
+ if($idx ne "" && $idx != 0)
+ { $ret.="($reg1,$reg2,$idx)"; }
+ else
+ { $ret.="($reg1,$reg2)"; }
+ }
+ elsif ($reg1 ne "")
{ $ret.="($reg1)" }
return($ret);
}
return(&main'DWP(@_));
}
+sub main'BC
+ {
+ return @_;
+ }
+
+sub main'DWC
+ {
+ return @_;
+ }
+
#sub main'BP
# {
# local($addr,$reg1,$reg2,$idx)=@_;
sub main'inc { &out1("incl",@_); }
sub main'push { &out1("pushl",@_); $stack+=4; }
sub main'pop { &out1("popl",@_); $stack-=4; }
-sub main'bswap { &out1("bswapl",@_); }
+sub main'pushf { &out0("pushf"); $stack+=4; }
+sub main'popf { &out0("popf"); $stack-=4; }
sub main'not { &out1("notl",@_); }
-sub main'call { &out1("call",$under.$_[0]); }
+sub main'call { &out1("call",($_[0]=~/^\.L/?'':$under).$_[0]); }
sub main'ret { &out0("ret"); }
sub main'nop { &out0("nop"); }
+# The bswapl instruction is new for the 486. Emulate if i386.
+sub main'bswap
+ {
+ if ($main'i386)
+ {
+ &main'comment("bswapl @_");
+ &main'exch(main'HB(@_),main'LB(@_));
+ &main'rotr(@_,16);
+ &main'exch(main'HB(@_),main'LB(@_));
+ }
+ else
+ {
+ &out1("bswapl",@_);
+ }
+ }
+
sub out2
{
local($name,$p1,$p2)=@_;
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"); }
push(@out,"$func:\n");
$tmp=<<"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,"$func:\n");
$stack=4;
.${func}_end:
EOF
push(@out,$tmp);
+
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,".ident \"$func\"\n");
$stack=0;
$func=$under.$func;
- push(@out,".${func}_end:\n");
+ push(@out,".L_${func}_end:\n");
if ($main'cpp)
- { push(@out,"\tSIZE($func,.${func}_end-$func)\n"); }
- else { push(@out,"\t.size\t$func,.${func}_end-$func\n"); }
+ { 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");
$stack=0;
%label=();
sub main'comment
{
+ if ($main'elf) # GNU and SVR4 as'es use different comment delimiters,
+ { # so we just skip comments...
+ push(@out,"\n");
+ return;
+ }
foreach (@_)
{
if (/^\s*$/)
sub main'file_end
{
+ if ($const ne "")
+ {
+ push(@out,".section .rodata\n");
+ push(@out,$const);
+ $const="";
+ }
}
sub main'data_word
{
push(@out,"\t.long $_[0]\n");
}
+
+# debug output functions: puts, putx, printf
+
+sub main'puts
+ {
+ &pushvars();
+ &main'push('$Lstring' . ++$constl);
+ &main'call('puts');
+ $stack-=4;
+ &main'add("esp",4);
+ &popvars();
+
+ $const .= "Lstring$constl:\n\t.string \"@_[0]\"\n";
+ }
+
+sub main'putx
+ {
+ &pushvars();
+ &main'push($_[0]);
+ &main'push('$Lstring' . ++$constl);
+ &main'call('printf');
+ &main'add("esp",8);
+ $stack-=8;
+ &popvars();
+
+ $const .= "Lstring$constl:\n\t.string \"\%X\"\n";
+ }
+
+sub main'printf
+ {
+ $ostack = $stack;
+ &pushvars();
+ for ($i = @_ - 1; $i >= 0; $i--)
+ {
+ if ($i == 0) # change this to support %s format strings
+ {
+ &main'push('$Lstring' . ++$constl);
+ $const .= "Lstring$constl:\n\t.string \"@_[$i]\"\n";
+ }
+ else
+ {
+ if ($_[$i] =~ /([0-9]*)\(%esp\)/)
+ {
+ &main'push(($1 + $stack - $ostack) . '(%esp)');
+ }
+ else
+ {
+ &main'push($_[$i]);
+ }
+ }
+ }
+ &main'call('printf');
+ $stack-=4*@_;
+ &main'add("esp",4*@_);
+ &popvars();
+ }
+
+sub pushvars
+ {
+ &main'pushf();
+ &main'push("edx");
+ &main'push("ecx");
+ &main'push("eax");
+ }
+
+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)
+ .align 8
+ 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))
+ {
+ push(@out,"\t.align\t8\n");
+ &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($sym."\@GOT",$dst));
+ }
+ else
+ {
+ &main'lea($dst,&main'DWP($sym));
+ }
+ }
+
+sub main'blindpop { &out1("popl",@_); }