Blame | Last modification | View Log | RSS feed
#!/usr/bin/perl -w$DEBUG = 0;$us = ""; # underscore char. gcc linux does not add `_' to names !?!%directives = (title => AddPrefixDot,if => AddPrefixDot,ifdef => AddPrefixDot,ifndef => AddPrefixDot,ifnotdef => AddPrefixDot,else => AddPrefixDot,endif => AddPrefixDot,include => HandleInclude,".586" => IgnoreLine,".mmx" => IgnoreLine,".xmm" => IgnoreLine,".model" => IgnoreLine,".code" => SetTextSect,".const" => SetTextSect,public => HandlePublic,extrn => HandleExtern,extern => HandleExtern,externdef => HandleExtern,option => HandleOption,end => IgnoreLine,);%UsedRegTypes = ("eax", "l", "ebx", "l", "ecx", "l", "edx", "l","esi", "l", "edi", "l", "esp", "l", "ebp", "l","ax", "w", "bx", "w", "cx", "w", "dx", "w","si", "w", "di", "w", "sp", "w", "bp", "w",);%RegisterList = ( %UsedRegTypes,("ah", "b", "al", "b", "bh", "b", "bl", "b","ch", "b", "cl", "b", "dh", "b", "dl", "b","st", "f","st(0)", "f", "st(1)", "f", "st(2)", "f", "st(3)", "f","st(4)", "f", "st(5)", "f", "st(6)", "f", "st(7)", "f","mm0", "q", "mm1", "q", "mm2", "q", "mm3", "q","mm4", "q", "mm5", "q", "mm6", "q", "mm7", "q",));%MemoryTypes = ("byte", "b", "char", "b", "bp", "b","word", "w", "sword", "w", "wp", "w","dword", "l", "sdword", "l", "dwp", "l","qword", "q", "sqword", "q", "qwp", "q","real10", "t", "tbyte", "t",);%IntToFloatType = ( "b", "???", # Not supposed to happen!"w", "???", # Not supposed to happen!"l", "s","q", "l","t", "t",);%MemTypeToDef = ("b", "byte", "w", "short", "l", "long", "q", "long",);%SegAlignTypes = ("byte", "0","word", "1","dword", "2","para", "4","page", "8",);%SegCombineTypes = ("private", "","public", ".globl","stack", "","common", "","memory", "","at", "",);%SegUseTypes = ("use16", "","use32", "","flat", "",);%DAllocTypes = ("byte", ".byte", "db", ".byte","sword", ".short", "word", ".word", "dw", ".word","sdword", ".long", "dword", ".long", "dd", ".long","ptr", ".long","fword", "", "df", "","sqword", ".quad", "qword", ".quad", "dq", ".quad","tbyte", "", "dt", "","real4", ".single","real8", ".double","real10", ".tfloat",);%DAllocAlignTypes = (".byte", "0",".word", "1",".short", "1",".long", "2",".quad", "3",".single", "2",".double", "3",".tfloat", "4",);%LabelTypeToInst = (".byte", "b",".short", "w", ".word", "w",".long", "l",".quad", "q",".single", "s",".double", "l",".tfloat", "t",);sub PrintHash {my ( %h ) = @_;while(($key, $value) = each %h) {print "#$key: $value\n";}print "\n";}PrintHash( %directives ) if $DEBUG;PrintHash( %UsedRegTypes ) if $DEBUG;PrintHash( %RegisterList ) if $DEBUG;PrintHash( %MemoryTypes ) if $DEBUG;PrintHash( %MemTypeToDef ) if $DEBUG;print "\nProgram Results:\n\n" if $DEBUG;$warn_fixed = 0;$first = $second = $body = $rest = $indent = "";$old_prologue = $old_epilogue = $prologue = $epilogue = 1;$FuncName = $FuncType = "";@FuncArgs = ();@FuncArgsRef = ();@UsedRegs = ();@LabelTypes = ();@EquList = ();unless ( $#ARGV == 1 ) {printf STDERR "Usages: $0 <in-asm-file> <out-s-file>\n";exit -1;}$asmFile = $ARGV[0];open STDIN, $asmFileor die "Cannot open input file `$asmFile': $!\n";#($asmOutFile) = (lc($asmFile) =~ /^(.*)\.asm$/);$asmOutFile = $ARGV[1];open STDOUT, ">$asmOutFile"or die "Cannot open output file `$asmOutFile.s': $!\n";$warn_fixed = 1 if ( defined($ARGV[1]) && ($ARGV[1] eq "-wfixed") );$asmFile =~ /[^\/]+$/;print ".file \"$&\"\n";print "# Auto-converted from Intel's assembly format to AT&T's format\n\n";# Find all labels & equs in advance:while( <> ) {my ( $ename, $etype, $ltype );CanonizeAndComment( $_ );next unless defined $first;# Handle COMMENTS:if ( uc($first) eq "COMMENT" ) {while ( ($_ = <>) !~ /\^/ ) {;}next;}if ( $first =~ /:$/ ) {$LabelTypes{ $` } = "";next;}if ( lc $first eq ".data" ) {my ( $dtype );while ( ($_ = <>) !~ /^\./ ) {CanonizeAndComment();$etype = $directives{ lc $first };if ( defined($etype) &&(($etype eq "HandleExtern") || ($etype eq "HandlePublic")) ) {GetExternOrPublic();}elsif ( defined($second) && defined($DAllocTypes{ lc $second }) ) {$dtype = $LabelTypeToInst{ $DAllocTypes{lc $second} };$LabelTypes{ "$us$first" } = $dtype . "C";}}next;}next unless defined $second;if ( lc $second eq "label" ) {$ltype = GetLabelType( @arr_line );if ( $body =~ /\s+C($|[\s,]+)/ ) {$first = "$us$first";$ltype = $ltype . "C";}$LabelTypes{ $first } = $ltype;next;}if ( defined($DAllocTypes{lc($second)}) ) {$LabelTypes{ $first } = $LabelTypeToInst{ $DAllocTypes{lc($second)} };next;}$etype = $directives{ lc $first };if ( defined($etype) &&( ($etype eq "HandleExtern") || ($etype eq "HandlePublic") ) ) {GetExternOrPublic();next;}if ( lc $second eq "equ" ) {$EquList{ $first } = Enumerate($arr_line[2]);next;}if ( lc $second eq "proc" ) {my ( $fname, $ftype ) = ( "", "" );if ( $body =~ /\s+C($|[\s,]+)/ ) {$fname = "$us" ;$ftype = "C";}$fname = "$fname$first";$LabelTypes{ $fname } = "$ftype";}}sub GetExternOrPublic {my ( $etype, $ename );$body =~ /\S+\s*(C?)\s+([^:\s]*)\s*(:?)\s*(\S+)/;if ( $3 eq ":" ) {$etype = $DAllocTypes{lc($4)} if defined($4);$etype = $LabelTypeToInst{ $etype } if defined($etype);$ename = $2;}else {$body =~ /(\S+)$/;$ename = $1;$etype = "l";}if ( $body =~ /\s+C($|[\s,])/ ) {$ename = "$us$ename";$etype = $etype . "C";}$LabelTypes{ $ename } = $etype;}PrintHash( %LabelTypes ) if $DEBUG;PrintHash( %EquList ) if $DEBUG;seek STDIN, 0, 0;while( <> ) {# Any handling that reads more input needs to go back here (COMMENTS & PROC).restart:CanonizeAndComment( $_ );# Handle COMMENTS:if ( uc($first) eq "COMMENT" ) {($rest) = $rest =~ /\s*\^(.*)/o;print "# $rest\n";while ( ($_ = <>) !~ /\^/ ) {print "# $_";}$_ =~ /\^/;print "$`#";$_ = $';goto restart;}goto print_end unless defined $first;# Handle known directivesmy $var = $directives{ lc $first };if ( (defined $var) && (defined &$var) ) {$line = &$var( lc $first, $rest );print $line;goto print_end;}# Handle labels:if ( $first =~ /:/ ) {print "$first";print " $rest" if defined $rest;$indent = " ";goto print_end;}# Handle ret (pop regs, restore frame):if ( lc $first eq "ret" ) {if ( ($FuncName eq "") && ($epilogue) ) {print STDERR "Warning: ret on line $.,"." outside a function context!\n";}else {HandleRet() if $epilogue;}print $indent, "$first";print " $rest" if defined $rest;goto print_end;}# Handle .directives, and any stuff which isn't an instruction:if ( $first eq ".data" ) {HandleDataSect( @arr_line );goto restart;}if ( $first eq ".bss" ) {HandleBssSect( @arr_line );goto restart;}if ( $first =~ /^\./ ) {print "$first";print " $rest" if defined $rest;goto print_end;}if ( defined $second ) {# Handle segmentsif ( lc $second eq "segment" ) {HandleSegment( @arr_line );goto print_end;}# Handle EQUif ( lc $second eq "equ" ) {$EquList{ $first } = Enumerate($arr_line[2]);print ".equ $first, ", Enumerate($arr_line[2]), "\t";goto print_end;}# Handle PROCif ( lc $second eq "proc" ) {$indent = " ";HandleProc( @arr_line );goto restart;}# Handle ENDP (for indentation, clearing status, etc.):if ( lc $second eq "endp" ) {HandleENDP( $first );$indent = "";goto print_end;}# Handle LABELif ( lc $second eq "label" ) {$first = "$us$first" if ( $body =~ /\s+C($|[\s,]+)/ );print "$first:";$indent = " ";goto print_end;}}# Handle asm instructions:HandleAsmInst( $body );print_end:print "$white" if defined $white;print "#$comment" if defined $comment;print "\n";}PrintHash( %FuncArgsRef ) if $DEBUG;sub CanonizeAndComment {my ( $fw );# Do canonization:$_ =~ s/^(\s*)//o;($fw) = ( $1 );$_ =~ s/[\s]*$//o;$_ =~ /(\s*);(.*)$/o;($body, $white, $comment) = ($`, $1, $2);$white = $fw if ( (defined $body) && ($body eq "") &&(defined $comment) && ($comment ne "") );@arr_line = split( /\s+/, $body);($first, $second) = ($arr_line[0], $arr_line[1]);($rest) = ($body =~ /\S+\s+(.*)/o); # rest is all body except for $first}sub GetLabelType {my ( $arg, $atype, $ltype );while( @_ ) {$arg = shift @_;$atype = $DAllocTypes{ lc($arg) };$ltype = $LabelTypeToInst{ $atype } if defined($atype);return $ltype if defined($ltype);}return "l";}sub AddPrefixDot {my ( $x, $y, $ret ) = @_;$ret = "." . $x;if ( (defined $y) && ($y ne "") ) {$ret = $ret . " " . $y;}return $ret;}sub HandleInclude {my ( $x, $y ) = @_;PrintHash( %_ );($y) =~ /^\S+/;return ".include " . qq( "$&" ) . $';}sub IgnoreLine {return "";}sub SetTextSect {return ".text\n.p2align 2";}sub HandleDataSect {my ( $ret, $dalign ) = ( ".data", "" );while ( ($_ = <>) !~ /^\./ ) {$ret = "$ret$white" if defined $white;$ret = "$ret#$comment" if defined $comment;$ret = "$ret\n";CanonizeAndComment();if ( defined($second) && defined($DAllocTypes{ lc $second }) ) {$dtype = $DAllocTypes{ lc $second };$dalign = $DAllocAlignTypes{ $dtype };$ret = "$ret\n.globl $us$first\n.p2align $dalign\n";$ret = "$ret\n$us$first:\n\t$dtype";$body =~ s/\s*\S+\s+\S+\s*//;$body =~ s/\s//og;while ( $body ne "" ) {$body =~ s/^([^,]+),?//;$ret = "$ret " . Enumerate($1) . ",";}$ret =~ s/,$//;}elsif ( defined($first) ) {if ( (lc($first) eq "extrn") ||(lc($first) eq "extern") || (lc($first) eq "externdef") ) {$ret = $ret . HandleExtern( lc($first), $rest );}}}$ret = "$ret$white" if defined $white;$ret = "$ret#$comment" if defined $comment;$ret = "$ret\n";print "$ret"."\n";}sub HandleSegment {my ( $ret, $FuncComment, $segarg, $align, $def ) = ( "", "" );$sname = shift @_; # get section name$ret = ".section $sname, \"a\"";shift @_; # discard word `section'$segarg = shift @_;if ( defined($segarg) ) {print "segarg3: $segarg\n" if $DEBUG;$align = $SegAlignTypes{ lc $segarg };if ( defined($align) ) {$segarg = shift @_;goto sect_arg_end unless defined($segarg);}else {$align = "2" unless defined($align);}print "segarg4: $segarg\n" if $DEBUG;if ( lc($segarg) eq "readonly" ) {$ret = "$ret, \"r\"";$segarg = shift @_;goto sect_arg_end unless defined($segarg);}print "segarg5: $segarg\n" if $DEBUG;$def = $SegCombineTypes{ lc($segarg) };if ( defined($def) ) {$segarg = shift @_;goto sect_arg_end unless defined($segarg);}print "segarg6: $segarg\n" if $DEBUG;if ( defined( $SegUseTypes{ lc($segarg) } ) ) {$segarg = shift @_;goto sect_arg_end unless defined($segarg);}print "segarg7: $segarg\n" if $DEBUG;if ( lc($segarg) =~ /\'(code|data)\'/ ) {if ( $1 eq "code" ) {$ret = ".text\n$ret";}else {$ret = ".data\n$ret";}}}sect_arg_end:print "ret=$ret\nalign=$align\ndef=$def\n" if $DEBUG;$ret = "$ret\n";while ( lc($_ = <>) !~ /ends/ ) {$ret = "$ret$white" if defined $white;$ret = "$ret#$comment" if defined $comment;$ret = "$ret\n";CanonizeAndComment();refind_label:if ( (defined($first) && ($first =~ /:$/)) ||(defined($second) &&( (lc($second) eq "label") ||defined($DAllocTypes{lc($second)}) )) ) {$lname = "";$addnl = 0;if ( defined($first) && ($first =~ /:$/) ) {$lname = $`;$body = $first = "";$ltype = "l";}elsif ( lc($second) eq "label" ) {$ltype = GetLabelType( @arr_line );if ( $body =~ /\s+C($|[\s,])/ ) {$lname = "$us";$ltype = $ltype . "C";}$lname = "$lname$first";$body = $first = "";}else {$lname = "$first";$ltype = $LabelTypeToInst{ $DAllocTypes{lc($second)} };$body =~ s/\s*\S+\s+(\S+)/$1/;$first = $1;$addnl = 1;}$LabelTypes{ $lname } = $ltype;$ret = "$ret$def $lname\n" if ( defined($def) && ($def ne "") );$ret = "$ret.p2align $align\n$lname:";$ret = "$ret\n" if $addnl;undef $dtype;$dtype = $DAllocTypes{ lc $first } if ( defined($first) );do {if ( defined($dtype) ) {$ret = "$ret$dtype ";$body =~ s/\S+\s+//;$body =~ s/\s//og;while ( ($body =~ s/^([^,]+),?//) ne "" ) {$ret = $ret . Enumerate($1) . ", ";}$ret =~ s/\s*,\s*$//;}$ret = "$ret$white" if defined $white;$ret = "$ret#$comment" if defined $comment;$ret = "$ret\n";$_ = <>;CanonizeAndComment() if defined($_);undef $dtype;$dtype = $DAllocTypes{ lc $first } if ( defined($first) );}while ( defined($_) && (($body eq "") || defined($dtype)) );last if ( $body =~ /ends/ );goto refind_label;}if ( $body ne "" ) {$ret = "$ret$body";print STDERR "Warning: not data decl inside section, line $.\n";}}if ( $first ne $sname ) {print STDERR "Warning: on line $., sement $sname ends, not $first!\n";}print "$ret"."\n";}sub HandleBssSect {}sub HandleExtern {my ( $x, $y, $name ) = @_;($y) =~ /\s*([^:\s]*):(\S+)/;# $ltype = $DAllocTypes{lc($2)} if defined($2);# $ltype = $LabelTypeToInst{ $ltype } if defined($ltype);$name = $1;if ( $body =~ /\s+C($|[\s,])/ ) {$name = "$us$name";# $ltype = $ltype . "C" if defined($ltype);}# $LabelTypes{ $name } = $ltype if defined($ltype);return ".extern $name";}sub HandlePublic {my ( $name );$body =~ /\S+\s+(C?)\s+(\S+)/;$name = $2;if ( $1 eq "C" ) {$name = "$us$name";}return ".globl $name";}sub HandleOption {my ( $x, $y ) = @_;if ( $y eq "PROLOGUE:NONE" ) {$prologue = 0;print STDERR "Not creating function prologue from input line $.\n"if $DEBUG;}elsif ( $y eq "EPILOGUE:NONE" ) {$epilogue = 0;print STDERR "Not creating function epilogue from input line $.\n"if $DEBUG;}return "";}sub Enumerate {my ( $num ) = @_;if ( $num =~ /^([+\-]?)([0-9a-fA-F]+)h$/ ) {return "$1"."0x$2";}# if ( $num =~ /^([0-9]+)$/ ) {return $num;# }}sub HandleProc {my ( @line ) = @_;my ( $found, $FuncComment );$FuncComment = "";if ( $body =~ /\s+C($|[\s,]+)/ ) {print STDERR "C funcion!\n" if $DEBUG;$FuncName = "$us" ;$FuncType = "C";}$FuncName = "$FuncName$line[0]";$LabelTypes{ $FuncName } = "l$FuncType";for ( $i = 0; $i <= $#line; $i++ ) {if ( lc $line[$i] eq "uses" ) {for ( $i++; $i <= $#line; $i++ ) {$found = $line[$i] =~ /e?([abcd]x|[sd]i|[sb]p)/io;if ( $found ) {push( @UsedRegs, lc $& );}else {print STDERR "Warning: unknown or invalid register ";print STDERR "`$line[$i]\' on line $.\n";}}}}while ( ($_ = <>) =~ /:/ ) {if ( (defined $comment) && ($comment ne "") ) {$FuncComment = $FuncComment . "\n#$comment";}CanonizeAndComment();push @FuncArgs, ($body =~ /(\S+)\s*:\s*([^,\n]*)/og);}if ( (defined $comment) && ($comment ne "") ) {$FuncComment = $FuncComment . "\n#$comment";}if ( $FuncType ne "C" ) {$old_prologue = $prologue;$old_epilogue = $epilogue;$prologue = $epilogue = 0;while ( $#FuncArgs >= 0 ) { pop @FuncArgs };while ( $#UsedRegs >= 0 ) { pop @UsedRegs };}if ( (! $prologue) && ($#FuncArgs >= 0) ) {print STDERR "Warning: Function `$FuncName\' has arguments,\n"." but `OPTION PROLOGUE:NONE\' is set! args ignored.\n";while ( $#FuncArgs >= 0 ) { pop @FuncArgs };}if ( ($#UsedRegs >= 0) && (! ($prologue || $epilogue) ) ) {print STDERR "Warning: Function `$FuncName\' declares used "."registers,\n but no EPILOGUE and no PROLOGUE ","requeted.\n Regs will not be saved or restored!\n";while ( $#UsedRegs >= 0 ) { pop @UsedRegs };}print $FuncComment, "\n" unless ($FuncComment eq "");if ( $prologue ) {ProcessPrintFuncArgs() if ($#FuncArgs > -1);print ".globl $FuncName\n\n$FuncName:\n";PrintFuncFrame( "enter" );ProcessUsedRegs( "enter" ) if ($#UsedRegs > -1);}else {print ".globl $FuncName\n\n$FuncName:\n";}}sub ProcessPrintFuncArgs {my ( $offset, $i, $type, $offs_name, $arg_type, $maxlen );$offset = 8;print "\n";$maxlen = 0;for ( $i = 0; $i <= $#FuncArgs-1; $i += 2 ) {$maxlen = length($FuncArgs[$i]) if ( length($FuncArgs[$i]) > $maxlen );}for ( $i = 0; $i <= $#FuncArgs-1; $i += 2 ) {$offs_name = "PRM_" . uc $FuncArgs[$i];$arg_type = $FuncArgs[$i+1];if ( lc($arg_type) =~ /^ptr\s*/ ) {($type) = ($' =~ /\s*(\S*)\s*/);# print STDERR "Warning: Function `$FuncName\'s argument ".# "`$FuncArgs[$i]\'s size is not 4!\n";}else {$type = $arg_type;}print ".equ $offs_name, $offset";printf "%*s", $maxlen - length($offs_name) + 8 - length($offset), "";print "# ", uc $type, "\t$FuncArgs[$i]";if ( lc($arg_type) =~ /^ptr\s*/ ) {printf "%*spointer", $maxlen - length($offs_name) + 5;}print "\n";$offset += 4;$FuncArgsRef{ $FuncArgs[$i] } = "$offs_name(%ebp)";}print "\n";# PrintHash( %FuncArgsRef ) if $DEBUG;}sub PrintFuncFrame {print "\n";if ( $_[0] eq "enter" ) {print $indent, "pushl %ebp\n";print $indent, "movl %esp, %ebp\n";}else {print $indent, "movl %ebp, %esp\n";print $indent, "popl %ebp\n";}}sub ProcessUsedRegs {my ( $i, $type );print "\n";if ( $_[0] eq "enter" ) {for ( $i = 0; $i <= $#UsedRegs; $i++ ) {$type = $UsedRegTypes{ $UsedRegs[$i] };if ( $type eq "w" ) {print STDERR "Warning: function `$FuncName\' saves a 16-bit "."register ($UsedRegs[$i]).\n";}print "$indent", "push$type\t%$UsedRegs[$i]\n";}}else {for ( $i = $#UsedRegs; $i >= 0 ; $i-- ) {$type = $UsedRegTypes{ $UsedRegs[$i] };print "$indent", "pop$type\t%$UsedRegs[$i]\n";}}}sub HandleRet {ProcessUsedRegs( "leave" ) if ($#UsedRegs > -1);PrintFuncFrame( "leave" );print "\n";}sub HandleENDP {my ( $fname ) = @_;$fname = "$us$fname" if ( $FuncType eq "C" );unless ( $fname eq $FuncName ) {print STDERR "Warning: on line $. `$fname\' ends, inside $FuncName!\n";}if ( $FuncType ne "C" ) {$prologue = $old_prologue;$epilogue = $old_epilogue;}$FuncName = $FuncType = "";while ( $#FuncArgs >= 0 ) { pop @FuncArgs };while ( $#FuncArgsRef >= 0 ) { pop @FuncArgsRef };while ( $#UsedRegs >= 0 ) { pop @UsedRegs };print "\n# $fname ends here.\n\n";if ( $prologue ^ $epilogue ) {print STDERR "Warning: only one of PROLUGE and EPILOGUE is defined.\n"." Make sure prologue and epilogue are consistent!\n";}}sub ParseIndexRef {my ( $ireg, $idx ) = @_;if ( defined $RegisterList{ $ireg } ) {$ireg = "%".$ireg;}else {print STDERR "Error: in instruction on line $.: "."register `$ireg' unknown!\n";exit -1;}print ",$ireg,$idx)\n" if $DEBUG;return ( $ireg, $idx );}sub ParseMemRef {my ( $ref ) = @_;my ( $dsign, $disp, $base_reg, $index_reg, $index ) =( "", "", "", "", "1" );$ref =~ s/\s*//og;print "$ref\n" if $DEBUG;$found = $ref =~ /([+\-]?)([01248])\*([^+\-*]+)/;if ( $found && defined($RegisterList{$3}) ) {print "found 1: $3\n" if $DEBUG;if ( defined($1) && ($1 eq "-") ) {print STDERR "Error: negative register indexing on line $.!\n";exit -3;}($index_reg, $index) = ParseIndexRef( lc $3, $2 ) unless( $2 eq "0");$ref =~ s/([+\-]?)([01248])\*([^+\-*]+)//;}else {$found = $ref =~ s/([+\-]?)([^+\-*]+)\*([01248])//;if ( $found ) {if ( defined($RegisterList{$2}) ) {print "found 2: $2\n" if $DEBUG;if ( defined($1) && ($1 eq "-") ) {print STDERR "Error: negative register indexing"." on line $.!\n";exit -3;}($index_reg, $index) =ParseIndexRef(lc $2, $3) unless( $3 eq "0");}else {$disp = $1 if defined($1);$disp = $disp . Enumerate($2) . "*" . Enumerate($3);}}}$fn = 2;while ( $ref =~ s/([+\-]?)([^+\-*]+)\*([^+\-*]+)// ) {# print STDERR "Error: in instruction on line $.: too many `*'!\n";# exit -3;$fn++;print STDERR "found $fn"."*: $2*$3\n" if $DEBUG;$disp = "$disp$1" if defined($1);$disp = $disp . Enumerate($2) . "*" . Enumerate($3);print STDERR "$disp(\n" if $DEBUG;}while ( $ref =~ s/((^|[+\-])[0-9][0-9a-fA-F]*h?)// ) {$fn++;print STDERR "found $fn"."i: $1\n" if $DEBUG;$disp = $disp . Enumerate($1);print STDERR "$disp(\n" if $DEBUG;}while ( $ref =~ /[^+\-]/ ) {$fn++;$found = $ref =~ s/^([+\-]?)([^+\-]+)//;if ( $found ) {print STDERR "found $fn"."g: $1$2\n" if $DEBUG;if ( defined $RegisterList{ lc $2 } ) {if ( defined($1) && ($1 eq "-") ) {print STDERR "negative register reference on line $.!\n";exit -4;}if ( $base_reg ne "" ) {if ( $index_reg ne "" ) {print STDERR "Error: in instruction on line $.: "."base_reg & index_reg already defined!\n";exit -4;}($index_reg, $index) = ParseIndexRef( lc $2, "1" );}else {$base_reg = "%".lc($2);print STDERR "($base_reg,\n" if $DEBUG;}}else {$cdisp = $2;$cdisp = "$1$cdisp" if defined($1);my( $lbt );if ( defined($lbt = $LabelTypes{ "$us$cdisp" }) &&$lbt =~ /C$/ ) {$cdisp = "$us$cdisp";}$dsign = "+" if ( ($disp ne "") && ($disp !~ /^[+\-]/ ) );$disp = "$cdisp$dsign$disp";print STDERR "$disp(\n" if $DEBUG;}}}if ( $ref ne "" ) {print STDERR "Error: Not all memory reference parsed! (Rest=$ref)\n";exit -6;}$memref = "$disp($base_reg,$index_reg,$index)";print "$memref\n" if $DEBUG;$memref =~ s/\(([^,]+),,1\)/($1)/;print "$memref\n" if $DEBUG;$memref =~ s/,,/,/;print "$memref\n" if $DEBUG;$memref =~ s/\(,1\)//;print "$memref\n" if $DEBUG;$memref =~ s/^\+//;print "$memref\n" if $DEBUG;return $memref;}sub HandleSrcDstType {my ( $sd, $ref_type, $mem_ref, $sd_type, $lbt, $num, $tmp, $s, $m ) = @_;if ( defined $sd ) {$sd_type = $RegisterList{ $sd };unless ( defined $sd_type ) {($ref_type, $mem_ref) = ($sd =~ /([^\[]*)\[([^\]\n\r]+)\]$/);if ( !defined($mem_ref) ) { # maybe [] was missing:($ref_type, $mem_ref)= ($sd =~ /(\S*\s*[pP][tT][rR])\s*(.+)$/);}if ( defined $mem_ref ) {($sd_type) = (lc($ref_type) =~ /^(\S+)/);$sd_type = "dword" if ( ! defined($sd_type) );($sd_type) = $MemoryTypes{ $sd_type };print "mem ref: [$mem_ref] ($sd_type)\n" if $DEBUG;if ( defined $FuncArgsRef{ $mem_ref } ) {$sd = $FuncArgsRef{ $mem_ref };print "matched in arg-list: $sd\n" if $DEBUG;}else {$sd = ParseMemRef( $mem_ref );}}else {print "constant: $sd " if $DEBUG;if ( defined $FuncArgsRef{ $sd } ) {$sd = $FuncArgsRef{ $sd };print "matched in arg-list: $sd\n" if $DEBUG;}else {$tmp = $sd;$sd = "";while( $tmp ne "" ) {$tmp =~ s/^\s*([+\-]?[^\s+\-]+)\s*([+\-]?)/$2/;print "const=$tmp,match=$1" if $DEBUG;$1 =~ /[^+\-]+/;$s = $`;$m = $&;print ",net=$m\n" if $DEBUG;if ( ( defined($lbt = $LabelTypes{ "$us$m" }) &&$lbt =~ s/C$// ) ||defined($lbt = $LabelTypes{ $m }) ) {if ( defined( $sd_type ) ) {print STDERR "Warning: 2 labels on line $.!\n";}$m = "$us$m" if ( $& eq "C" );$sd = "$sd$s$m";$sd_type = $lbt;print"#label `($s)$m',type `$sd_type'\n" if $DEBUG;}elsif ( defined($EquList{ $m }) ) {$sd = "$sd$s$m";print "found equ `($s)$m'\n" if $DEBUG;}else {$sd = "$sd$s" . Enumerate( $m );print "found const `$s$m'\n" if $DEBUG;}}$sd =~ s/^\+//;$sd = "\$$sd" unless ( defined($sd_type ) );}print "($sd_type)" if ( $DEBUG && defined($sd_type) );print "\n" if $DEBUG;}}else {print "reg ref: $sd ($sd_type)\n" if $DEBUG;$sd = "%" . $sd;}}return ( $sd, $sd_type );}sub HandleAsmInst {my ( $inst ) = @_;my ( $opcode, $dst, $src, $extra, $src_type, $dst_type, $mem_ref );($opcode) = ($inst =~ /^(\S+)\s*/);$opcode = lc $opcode;($dst) = ($' =~ /^([^,\n\r]+)\s*,?\s*/);($src) = ($' =~ /^([^,\n\r]+)\s*,?\s*/) if defined $dst;($extra) = ($' =~ /^([^,\n\r]+)\s*,?\s*/) if defined $src;($src, $src_type) = HandleSrcDstType( $src ) if defined $src;($dst, $dst_type) = HandleSrcDstType( $dst ) if defined $dst;$print_adj = 0;if ( $opcode =~ /^f(.)/ ) { # Handle float commands:if ( $1 ne "i" ) { # Handle commands without integer:$src_type = $IntToFloatType{ $src_type } if defined($src_type);$dst_type = $IntToFloatType{ $dst_type } if defined($dst_type);}else { # Handle commands with integer: put `' instead of `w'.# $src_type = "" if ( defined($src_type) && ($src_type eq "w") );# $dst_type = "" if ( defined($dst_type) && ($dst_type eq "w") );}}else {# Adjust mmx-instructions:if ( #($opcode eq "movd") &&( (defined $src_type) && (defined $dst_type) ) &&( (($src_type eq "l") && ($dst_type eq "q")) ||(($src_type eq "q") && ($dst_type eq "l")) ) ) {$print_adj = 1 if $warn_fixed;$dst_type = $src_type = "q";}# if src or dst_type is `q' (for mmx), no need to put it$dst_type = "" if ( defined($dst_type) && ($dst_type eq "q") );$src_type = "" if ( defined($src_type) && ($src_type eq "q") );}if ( (defined $src_type) && (defined $dst_type) &&($src_type ne $dst_type) ) {print STDERR "Warning: instruction on line $. has different "."SRC ($src_type) and DST ($dst_type) types!\n";}$dst_type = $src_type if ( defined($src_type) && (!defined($dst_type)) );$cmd = $indent . "$opcode";$cmd = $cmd . $dst_type if defined($dst_type);$cmd = $cmd . " ";$cmd = $cmd . "\t" if defined $dst;$cmd = $cmd . $src . ", " if defined $src;$cmd = $cmd . "$dst" if defined $dst;$cmd = $cmd . ", $extra" if defined $extra;print $cmd;$cmd =~ s/^\s*//;print STDERR "Fixed types for `$cmd' (this is OK).\n" if $print_adj;}