summaryrefslogtreecommitdiff
path: root/lib/compiler/disassembler.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler/disassembler.tcl')
-rw-r--r--[-rwxr-xr-x]lib/compiler/disassembler.tcl149
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