From: ian Date: Tue, 20 Dec 2005 22:29:06 +0000 (+0000) Subject: nice disassembly can include SFRs X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=97de3a4d3078f8c59b944ccb2db720216a829918;p=trains.git nice disassembly can include SFRs --- diff --git a/iwjpictest/to-insn-aliases b/iwjpictest/to-insn-aliases index e50837a..e579c3d 100755 --- a/iwjpictest/to-insn-aliases +++ b/iwjpictest/to-insn-aliases @@ -1,4 +1,21 @@ #!/usr/bin/perl -w +# usage +# to-insn-aliases +# -A .../insn-aliases.inc +# [-M ] +# [-H ] +# [] +# +# to-insn-aliases -P .../insn-aliases.inc (for debugging, really) +# +# eg +# gpdasm -p18f458 program+entire0.hex \ +# | ../iwjpictest/to-insn-aliases -A ../iwjpictest/insn-aliases.inc \ +# -M program+program.map -H /usr/share/gputils/header/p18f458.inc \ +# | less +# or +# ../iwjpictest/to-insn-aliases -A ../iwjpictest/insn-aliases.inc \ +# nmra-stream.asm.new use strict qw(vars); use IO::File; @@ -10,15 +27,122 @@ our (%mapping); # $mapping{$opcode}[$i]{Macro} = macro `opcode' # $mapping{$opcode}[$i]{ActualArgs}[$j] = '0','1', or formal arg letter or W -sub readaliases () { - my ($f, $inmacro, @formalargs, $newmapping); +our (%syms,%addrs); +# $syms{$loc}{$addr}[$i]= $show +# $addrs{$loc}[$i]= $addr + +sub parseoptions () { + my ($f); + for (;;) { + return unless @ARGV; + return unless $ARGV[0] =~ m/^\-/; + $_= shift @ARGV; + return if m/^\-\-$/; + s/^\-([APHM])// or die; + if (!length) { @ARGV or die; $_= shift @ARGV; } + $f= new IO::File $_; + if ($1 eq 'P') { $doprint= 1; readaliases($f); } + elsif ($1 eq 'A') { readaliases($f); } + elsif ($1 eq 'M') { readmap($f); } + elsif ($1 eq 'H') { readheader($f); } + else { die; } + die $! if $f->error(); + close $f; + } +} + +sub readheader ($) { + my ($f) = @_; + my ($ss, $name,$addr); + $ss= $syms{' sfr'}= { }; + while (<$f>) { +#print "1>$_"; + next unless m/^\;\-+\s*register file/i ... /^\;.*\-/; +#print "2>$_"; + next if m/^\;/; + next unless m/\S/; + die unless m/^(\w+)\s+equ\s+h\'0?(f[0-9a-f]{2})\'\s*$/i; + ($name,$addr) = ($1,$2); + $addr = hex($addr); + next if exists $ss->{$addr}; + $ss->{$addr}= $name; + } +} + +sub readmap ($) { + my ($f) = @_; + my ($name,$addr,$loc,$stor,$file); + my ($scope,$show, $k); + while (<$f>) { + next unless m/^\s+Symbols\s+$/ .. !m/\S/; + next if m/^\s+Symbols\s+$/; + next if m/^\s+Name\s+Address\s+Location\s+Storage\s+File\s+$/; + next unless m/[^ \t\n-]/; + die unless + m/^\s*(\w+)\s+(0x\w+|0+)\s+(program|data)\s+(static|extern)\s+(\S+)\s*$/; + ($name,$addr,$loc,$stor,$file)=($1,$2,$3,$4,$5); + $scope= $stor eq 'extern' ? '' : "$file:"; + $scope =~ s/\.asm\:$/:/; + $show= $scope.$name; + $addr= hex($addr); + push @{ $syms{$loc}{$addr} }, $show; + push @{ $addrs{$loc} }, $addr; + } + foreach $k (keys %addrs) { + $addrs{$k}= [ sort { $a <=> $b } @{ $addrs{$k} } ]; + } +} + +sub builtin_opcodes () { + my ($o); + foreach $o (qw(bra goto call rcall)) { + push @{ $mapping{$o} }, { + FormalArgs => [qw(n)], Macro => $o, ActualArgs => [qw(n)] + }; + } + push @{ $mapping{'call'} }, { + FormalArgs => [qw(n)], Macro => 'call', ActualArgs => [qw(n 0)] + }; + foreach $o (qw(return retfie)) { + push @{ $mapping{$o} }, { + FormalArgs => [], Macro => $o, ActualArgs => [qw(0)] + }; + } +} + +sub addr2print ($$$) { + my ($loc, $av, $default) = @_; + my ($i,$j, $al, $h,$ha); + $av =~ s/^0x// or return $default; + $av= hex($av); + if ($loc eq 'data' && $av >= 0xf00) { + $al= $syms{' sfr'}; + return $default unless exists $al->{$av}; + return $al->{$av}; + } + $al= $addrs{$loc}; + return $default unless $al; + $i= 0; $j= @$al; + for (;;) { +#print ">$loc|$default|av=$av|i=$i|j=$j\n"; + last if $i >= $j; + $h= ($i+$j) >> 1; + $ha= $al->[$h]; +#print ">$loc|$default|av=$av|i=$i|j=$j|h=$h|ha=$ha\n"; + if ($av == $ha) { return $syms{$loc}{$ha}[0]; } + elsif ($av < $ha) { $j=$h; } + else { $i=$h+1; } + } + $i--; + if ($i < 0) { return $default; } + $ha= $al->[$i]; + return sprintf "%s+0x%x", $syms{$loc}{$ha}[0], $av - $ha; +} + +sub readaliases ($) { + my ($f) = @_; + my ($inmacro, @formalargs, $newmapping); my ($formarglets) = 'inkfgb'; - @ARGV or die; - $_= shift @ARGV; - s/^\-([AP])// or die; - $doprint= $1 eq 'P'; - if (!length) { @ARGV or die; $_= shift @ARGV; } - $f= new IO::File $_; while (<$f>) { s/0xfe8/W/; if (m/^\s*\;/) { @@ -43,8 +167,6 @@ sub readaliases () { die; } } - die $! if $f->error(); - close $f; } sub printaliases () { @@ -63,8 +185,10 @@ sub mapinsn { my (@r) = @_; my ($org_opcode, @org_args) = @_; my ($m,$i,$mismatch,$specified,$pattern,%arg,$fa,$aa); +#print "**$org_opcode\n"; MAPPING: foreach $m (@{ $mapping{$org_opcode} }) { next unless @org_args == @{ $m->{ActualArgs} }; +#print "**$m->{Macro}|\n"; for ($i=0, $mismatch=0; !$mismatch && $i<@org_args; $i++) { $specified= $org_args[$i]; $pattern= $m->{ActualArgs}[$i]; @@ -77,6 +201,7 @@ sub mapinsn { if ($pattern =~ m/^[a-z]$/) { $arg{$&}= $specified; } elsif ($specified !~ m/^\s*$pattern\s*$/) { +#print "**$m->{Macro}|$pattern|$specified<\n"; next MAPPING; } } @@ -85,6 +210,17 @@ sub mapinsn { foreach $fa (@{ $m->{FormalArgs} }) { next unless $fa =~ m/^[a-z]$/; $aa= $arg{$fa}; +#print ">@r|$fa|$aa<\n"; + if ($fa =~ m/f/) { + if ($m->{Macro} =~ m/_[wf]*a/ && + $aa =~ m/^0x([6-9a-f][0-9a-f])$/) { + $aa= addr2print('data', "0xf$1", $aa); + } else { + $aa= addr2print('data', $aa, $aa); + } + } elsif ($fa =~ m/n/) { + $aa= addr2print('program', $aa, $aa); + } push @r, $aa; } last if @r==1; @@ -92,24 +228,50 @@ sub mapinsn { return @r; } -sub processfile () { - my ($comment, $lhs,$opcode,$midspc,$args,$rhs, @args); +sub processfiles () { + my ($comment,$addrshow, $addr,$symshow,$symbols); + my ($lhs,$opcode,$midspc,$args,$rhs, @args, $lastopcode); + my ($insertnewline); + $lastopcode= $insertnewline= ''; while (<>) { chomp; $comment= s/\;.*// ? $& : ''; - if (m/^((?:[0-9a-f]{6}\:\s*)?\w*\s+)(\w+)(\s+)(.*?)(\s*)$/) { + $symbols= ''; + if (s/^(([0-9a-f]{6})\:)\s+//) { + $addrshow= $&; + $addr= hex($2); + foreach $symshow (@{ $syms{'program'}{$addr} }) { + $symbols .= "$1 $symshow\n"; + } + } else { + $addrshow= ''; + } + if (m/^(\w*\s+)(\w+)(\s+)(.*?)(\s*)$/) { ($lhs,$opcode,$midspc,$args,$rhs) = ($1,$2,$3,$4,$5); + $symbols= $insertnewline.$symbols; + $insertnewline= ''; @args= split /\,/, $args; ($opcode, @args) = mapinsn($opcode, @args); $args= sprintf "%-*s", length($args), join ',', @args; $midspc =~ s/\t$/ / if length($opcode) >= 8; $_= $lhs.$opcode.$midspc.$args.$rhs; +#print ">$opcode|$lastopcode$opcode|$lastopcode