diff options
author | Andrej Shadura <andrewsh@debian.org> | 2018-05-08 15:59:31 +0200 |
---|---|---|
committer | Andrej Shadura <andrewsh@debian.org> | 2018-05-08 15:59:31 +0200 |
commit | 47aa8b00b2b11df13a100489e0f904a4947177ef (patch) | |
tree | b35c9acc778ea2f761f3c549f7bee2f4491b3144 /lib/compiler/disassembler.tcl | |
parent | 5b8466f7fae0e071c0f4eda13051c93313910028 (diff) |
Import Upstream version 1.4.7
Diffstat (limited to 'lib/compiler/disassembler.tcl')
-rw-r--r--[-rwxr-xr-x] | lib/compiler/disassembler.tcl | 149 |
1 files changed, 87 insertions, 62 deletions
diff --git a/lib/compiler/disassembler.tcl b/lib/compiler/disassembler.tcl index b74fedf..6319c1e 100755..100644 --- a/lib/compiler/disassembler.tcl +++ b/lib/compiler/disassembler.tcl @@ -2,7 +2,7 @@ # Part of MCU 8051 IDE ( http://mcu8051ide.sf.net ) ############################################################################ -# Copyright (C) 2007-2009 by Martin Ošmera # +# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 by Martin Ošmera # # martin.osmera@gmail.com # # # # This program is free software; you can redistribute it and#or modify # @@ -21,6 +21,11 @@ # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ############################################################################ +# >>> File inclusion guard +if { ! [ info exists _DISASSEMBLER_TCL ] } { +set _DISASSEMBLER_TCL _ +# <<< File inclusion guard + # -------------------------------------------------------------------------- # Disassembler 8051 # @@ -46,8 +51,8 @@ namespace eval disassembler { variable hex_data {} ;# Raw input data variable hex {} ;# Adjusted input data, list: {addr hex0 hex1 hex2 ...} variable lineNum {} ;# Number of line currently beeing parsed - variable error_count {} ;# Number of errors raised during decompilation - variable warning_count {} ;# Number of warnings occured + variable error_count {} ;# Number of errors raised during disassembly + variable warning_count {} ;# Number of warnings occurred variable label_idx {} ;# Label index variable final_lbls 0 ;# Number of final labels variable label ;# Array of tempotary labels, label(int) -> addr @@ -58,7 +63,7 @@ namespace eval disassembler { # GENERAL PURPOSE PROCEDURES # ---------------------------------------------------------------- - ## Initiate decompilation + ## Initiate disassembly # @parm string data - Input IHEX8 code # @return string - output asm code or {} proc compile {data} { @@ -66,8 +71,8 @@ namespace eval disassembler { variable hex_data ;# Raw input variable hex ;# Adjusted input data, list: {addr hex0 hex1 hex2 ...} variable lineNum ;# Number of line currently beeing parsed - variable error_count ;# Number of errors raised during decompilation - variable warning_count ;# Number of warnings occured + variable error_count ;# Number of errors raised during disassembly + variable warning_count ;# Number of warnings occurred variable asm ;# Resulting source code set error_count 0 ;# reset errors count @@ -79,7 +84,7 @@ namespace eval disassembler { regexp -all {\r\n?} hex_data "\n" hex_data set hex_data [split $hex_data "\n"] - ${Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {SN}][mc "Initializing disassembler ..."] + ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {SN}][mc "Initializing disassembler ..."] # Verify input code validity and set variable 'hex' adjust_code @@ -87,17 +92,17 @@ namespace eval disassembler { # Exit if the code does not seem to be valid if {$error_count != 0} { if {${::Compiler::Settings::NOCOLOR}} { - ${Compiler::Settings::TEXT_OUPUT_COMMAND} \ + ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \ [::Compiler::msgc {EN}][mc "Disassembly FAILED ..."] - } { - ${Compiler::Settings::TEXT_OUPUT_COMMAND} \ + } else { + ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \ [::Compiler::msgc {EN}][mc "\033\[31;1mDisassembly FAILED\033\[m ..."] } return {} } - if {${Compiler::Settings::ABORT_VARIABLE}} { - ${Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"] + if {${::Compiler::Settings::ABORT_VARIABLE}} { + ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"] free_resources return {} } @@ -105,8 +110,8 @@ namespace eval disassembler { # Convert processor code into asm code decompile_code - if {${Compiler::Settings::ABORT_VARIABLE}} { - ${Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}[mc "Aborted"] + if {${::Compiler::Settings::ABORT_VARIABLE}} { + ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"] free_resources return {} } @@ -114,8 +119,8 @@ namespace eval disassembler { # Create labels in resulting code parse_labels - if {${Compiler::Settings::ABORT_VARIABLE}} { - ${Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"] + if {${::Compiler::Settings::ABORT_VARIABLE}} { + ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"] free_resources return {} } @@ -123,26 +128,26 @@ namespace eval disassembler { # Final stage final_stage - if {${Compiler::Settings::ABORT_VARIABLE}} { - ${Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"] + if {${::Compiler::Settings::ABORT_VARIABLE}} { + ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"] free_resources return {} } - # Free memory used during decompilation + # Free memory used during disassembly free_resources - if {${Compiler::Settings::ABORT_VARIABLE}} { - ${Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"] + if {${::Compiler::Settings::ABORT_VARIABLE}} { + ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EN}][mc "Aborted"] free_resources return {} } if {${::Compiler::Settings::NOCOLOR}} { - ${Compiler::Settings::TEXT_OUPUT_COMMAND} \ + ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \ [::Compiler::msgc {SN}][mc "Disassembly complete"] - } { - ${Compiler::Settings::TEXT_OUPUT_COMMAND} \ + } else { + ${::Compiler::Settings::TEXT_OUPUT_COMMAND} \ [mc "\033\[32;1mDisassembly complete\033\[m"] } @@ -167,7 +172,9 @@ namespace eval disassembler { foreach line $hex_data { - if {[expr {$lineNum % 10}] == 0} ${Compiler::Settings::UPDATE_COMMAND} + if {[expr {$lineNum % 10}] == 0} { + ${::Compiler::Settings::UPDATE_COMMAND} + } incr lineNum ;# line number @@ -209,7 +216,7 @@ namespace eval disassembler { set len [expr "0x$len"] set data [string range $line 8 {end-2}] if {$len != ([string length $data] / 2)} { - Error $lineNum [mc "Length field do not corespond true data length"] + Error $lineNum [mc "Length field do not correspond true data length"] continue } @@ -217,11 +224,11 @@ namespace eval disassembler { set addr_hex [string range $line 2 5] set addr [expr "0x$addr_hex"] if {$addr <= $pointer} { - Error $lineNum [mc "Unexpected address -- code is not well formated"] + Error $lineNum [mc "Unexpected address -- code is not well formatted"] continue } elseif {$addr > ($pointer + 1)} { set pointer $addr - } { + } else { incr pointer $len } @@ -262,7 +269,9 @@ namespace eval disassembler { foreach line $hex { - if {[expr {$idx % 10}] == 0} ${Compiler::Settings::UPDATE_COMMAND} + if {[expr {$idx % 10}] == 0} { + ${::Compiler::Settings::UPDATE_COMMAND} + } incr idx @@ -276,7 +285,7 @@ namespace eval disassembler { if {$trailing_data_length} { # Write trailing data foreach opcode $trailing_data { - append asm "_$pointer {DB 0${opcode}h {}} " + lappend asm _$pointer [list {DB} "0${opcode}h" {}] incr pointer } # Reset trailing data @@ -286,7 +295,7 @@ namespace eval disassembler { # Adjust pointer set pointer $addr_dec - append asm "{} {} {} {ORG [HEX $addr]h {}} " + lappend asm {} {} {} [list {ORG} "[HEX $addr]h" {}] } # Number of data fields @@ -295,7 +304,7 @@ namespace eval disassembler { # Append trailing data from last parsing to the current line if {$trailing_data_length} { # append - incr len $trailing_data_length + incr len $trailing_data_length set line [concat $trailing_data $line] # reset set trailing_data_length 0 @@ -310,13 +319,13 @@ namespace eval disassembler { set opcode [lindex $line $idx] ;# current opcode # Search for he given opcode - if {[lsearch ${CompilerConsts::defined_OPCODE} $opcode] == -1} { + if {[lsearch ${::CompilerConsts::defined_OPCODE} $opcode] == -1} { # opcode not found -> write opcode directly to source code - append asm "_$pointer {DB 0${opcode}h {}} " + lappend asm "_$pointer" [list {DB} "0${opcode}h" {}] set length 1 } else { # opcode found -> resolve it's definition - set def $CompilerConsts::Opcode($opcode) + set def $::CompilerConsts::Opcode($opcode) set instruction [lindex $def 0] ;# Instruction name set opr_types [lindex $def 1] ;# Oprand types @@ -338,15 +347,15 @@ namespace eval disassembler { set opr {} foreach type $opr_types { - if {[lsearch ${CompilerConsts::FixedOperands} [string tolower $type]] != -1} { + if {[lsearch ${::CompilerConsts::FixedOperands} [string tolower $type]] != -1} { # Fixed operand -> only copy set opr $type - } { + } else { # Get operand value incr idx if {$idx > $len} { - append asm "_$pointer {DB 0${opcode}h {}} " + lappend asm "_$pointer" [{DB} "0${opcode}h" {}] set instruction_skipped 1 set length 1 incr idx -1 @@ -361,7 +370,7 @@ namespace eval disassembler { incr idx if {$idx > $len} { - append asm "_$pointer {DB 0${opcode}h {}} " + lappend asm "_$pointer" [list {DB} "0${opcode}h" {}] set instruction_skipped 1 set length 1 incr idx -2 @@ -373,7 +382,7 @@ namespace eval disassembler { set opr "[HEX [lindex $line $idx]]h" set tmp_opr [string range $opr 0 {end-1}] set tmp_opr [expr "0x$tmp_opr"] - foreach item ${CompilerConsts::MapOfSFRBitArea} { + foreach item ${::CompilerConsts::MapOfSFRBitArea} { if {[expr "0x[lindex $item 1]"] == $tmp_opr} { set opr [lindex $item 0] break @@ -384,7 +393,7 @@ namespace eval disassembler { set opr "/[HEX [lindex $line $idx]]h" set tmp_opr [string range $opr 1 {end-1}] set tmp_opr [expr "0x$tmp_opr"] - foreach item ${CompilerConsts::MapOfSFRBitArea} { + foreach item ${::CompilerConsts::MapOfSFRBitArea} { if {[expr "0x[lindex $item 1]"] == $tmp_opr} { set opr [lindex $item 0] break @@ -395,7 +404,7 @@ namespace eval disassembler { set opr "[HEX [lindex $line $idx]]h" set tmp_opr [string range $opr 0 {end-1}] set tmp_opr [expr "0x$tmp_opr"] - foreach item ${CompilerConsts::MapOfSFRArea} { + foreach item ${::CompilerConsts::MapOfSFRArea} { if {[expr "0x[lindex $item 1]"] == $tmp_opr} { set opr [lindex $item 0] break @@ -417,7 +426,7 @@ namespace eval disassembler { if {$label($label_idx) > 0x0FFFF || $label($label_idx) < 0} { set label($label_idx) [expr {$label($label_idx) & 0x0FFFF}] - Warning "Code address overflow, instruction: $instruction" + Warning [mc "Code address overflow, instruction: %s" $instruction] } elseif {$label($label_idx) == $pointer} { unset label($label_idx) incr label_idx -1 @@ -429,6 +438,7 @@ namespace eval disassembler { set opr "lbl${label_idx}-" set label($label_idx) "$mask_opr[lindex $line $idx]" set label($label_idx) [expr "0x$label($label_idx)"] + set label($label_idx) [expr {($label($label_idx) & 0x007ff) | ($pointer & 0x0f800)}] if {$label($label_idx) == $pointer} { unset label($label_idx) @@ -443,7 +453,7 @@ namespace eval disassembler { incr idx if {$idx > $len} { - append asm "_$pointer {DB 0${opcode}h {}} " + lappend asm "_$pointer" [list {DB} "0${opcode}h" {}] set length 1 incr idx -2 set instruction_skipped 1 @@ -471,8 +481,17 @@ namespace eval disassembler { continue } + # Swap operands in case if of instruction "MOV data, data" + if { + $instruction == {mov} && + [lindex $opr_types 0] == {data} && + [lindex $opr_types 1] == {data} + } then { + set operands [list [lindex $operands 1] [lindex $operands 0]] + } + # Append line to source code list - append asm "_$pointer {$instruction {$operands} {}} " + lappend asm "_$pointer" [list $instruction $operands {}] } # Increment program address pointer incr pointer $length @@ -501,7 +520,7 @@ namespace eval disassembler { if {$idx != -1} { # Reuse an existing label regsub -all "lbl${i}-" $asm "label$idx" asm - } { + } else { # Realy a new label lappend addrs $label($i) incr lbl_idx @@ -517,7 +536,7 @@ namespace eval disassembler { if {$idx == -1} { # Not found append equ_block "{} {CODE [HEX [format %X $addr]]h label$i} " - } { + } else { # Found incr idx lset asm [list $idx 2] "label$i" @@ -544,7 +563,9 @@ namespace eval disassembler { # Rewrite the source code for {set i 1} {$i <= $len} {incr i 2} { - if {[expr {$len % 5}] == 0} ${Compiler::Settings::UPDATE_COMMAND} + if {[expr {$len % 5}] == 0} { + ${::Compiler::Settings::UPDATE_COMMAND} + } set line [lindex $asm $i] ;# Get line @@ -554,7 +575,7 @@ namespace eval disassembler { continue # Not an empty line - } { + } else { set label [lindex $line 2] ;# label set instr [lindex $line 0] ;# instruction set oprs [lindex $line 1] ;# oprands @@ -589,7 +610,7 @@ namespace eval disassembler { variable hex_data ;# Raw input data variable hex ;# Adjusted input data, list: {addr hex0 hex1 hex2 ...} variable lineNum ;# Number of line currently beeing parsed - variable error_count ;# Number of errors raised during decompilation + variable error_count ;# Number of errors raised during disassembly variable label_idx ;# Label index variable label ;# Array of tempotary labels, label(int) -> addr variable asm ;# Resulting source code @@ -620,12 +641,12 @@ namespace eval disassembler { } ## Report warning message - # @parm Int LineNumber - Number of line where it occured + # @parm Int LineNumber - Number of line where it occurred # @parm String ErrorInfo - Text of the warning # @return void proc Warning {ErrorInfo} { variable idx ;# Current position in asm list - variable warning_count ;# Number of warnings occured + variable warning_count ;# Number of warnings occurred # Increment warning counter incr warning_count @@ -633,32 +654,36 @@ namespace eval disassembler { # Report the warning if {${::Compiler::Settings::WARNING_LEVEL} < 2} { if {${::Compiler::Settings::NOCOLOR}} { - ${Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {WN}][mc "Warning: %s" $ErrorInfo] - } { - ${Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\033\[33mWarning\033\[m: %s" $ErrorInfo] + ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {WN}][mc "Warning: %s" $ErrorInfo] + } else { + ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\033\[33mWarning\033\[m: %s" $ErrorInfo] } } } ## Error - # @parm Int lineNumber - number of line, where the error occured + # @parm Int lineNumber - number of line, where the error occurred # @parm String info - error string proc Error {lineNumber info} { variable error_count incr error_count if {$lineNumber != {}} { if {${::Compiler::Settings::NOCOLOR}} { - set lineNumber [mc " at line %s" $lineNumber] - } { - set lineNumber [mc " at line \033\[31;1;4m%s\033\[m" $lineNumber] + set lineNumber [mc " at %s" $lineNumber] + } else { + set lineNumber [mc " at \033\[31;1;4m%s\033\[m" $lineNumber] } } if {${::Compiler::Settings::WARNING_LEVEL} < 3} { if {${::Compiler::Settings::NOCOLOR}} { - ${Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EL}][mc "Error%s: %s" $lineNumber $info] - } { - ${Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\033\[31;1mError%s\033\[m: %s" $lineNumber $info] + ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [::Compiler::msgc {EL}][mc "Error%s: %s" $lineNumber $info] + } else { + ${::Compiler::Settings::TEXT_OUPUT_COMMAND} [mc "\033\[31;1mError%s\033\[m: %s" $lineNumber $info] } } } } + +# >>> File inclusion guard +} +# <<< File inclusion guard |