URL
https://opencores.org/ocsvn/lxp32/lxp32/trunk
Subversion Repositories lxp32
Compare Revisions
- This comparison shows the changes necessary to convert path
/lxp32/trunk/tools/src/lxp32dump
- from Rev 6 to Rev 9
- ↔ Reverse comparison
Rev 6 → Rev 9
/CMakeLists.txt
1,7 → 1,7
cmake_minimum_required(VERSION 3.3.0) |
|
add_executable(lxp32dump disassembler.cpp main.cpp) |
|
# Install |
|
install(TARGETS lxp32dump DESTINATION .) |
cmake_minimum_required(VERSION 3.3.0) |
|
add_executable(lxp32dump disassembler.cpp main.cpp) |
|
# Install |
|
install(TARGETS lxp32dump DESTINATION .) |
/disassembler.cpp
1,481 → 1,456
/* |
* Copyright (c) 2016 by Alex I. Kuznetsov. |
* |
* Part of the LXP32 CPU IP core. |
* |
* This module implements members of the Disassembler class. |
*/ |
|
#include "disassembler.h" |
|
#include <sstream> |
#include <stdexcept> |
|
/* |
* Disassembler::Operand class members |
*/ |
|
Disassembler::Operand::Operand(Type t,int value): |
_type(t),_value(value) {} |
|
Disassembler::Operand::Type Disassembler::Operand::type() const { |
return _type; |
} |
|
int Disassembler::Operand::value() const { |
return _value; |
} |
|
/* |
* Disassembler class members |
*/ |
|
Disassembler::Disassembler(std::istream &is,std::ostream &os): |
_is(is),_os(os),_fmt(Bin),_preferAliases(true),_lineNumber(0),_pos(0) {} |
|
void Disassembler::setFormat(Format fmt) { |
_fmt=fmt; |
} |
|
void Disassembler::setBase(Word base) { |
_pos=base; |
} |
|
void Disassembler::setPreferAliases(bool b) { |
_preferAliases=b; |
} |
|
void Disassembler::dump() { |
Word word; |
|
for(;;) { |
auto offset=_pos; |
if(!getWord(word)) break; |
auto opcode=word>>26; |
|
std::string instruction; |
|
bool lcValid=false; |
Word lcOperand; |
|
switch(opcode) { |
case 0x10: |
instruction=decodeAdd(word); |
break; |
case 0x18: |
instruction=decodeAnd(word); |
break; |
case 0x21: |
instruction=decodeCall(word); |
break; |
case 0x15: |
instruction=decodeDivs(word); |
break; |
case 0x14: |
instruction=decodeDivu(word); |
break; |
case 0x02: |
instruction=decodeHlt(word); |
break; |
case 0x20: |
instruction=decodeJmp(word); |
break; |
case 0x01: |
instruction=decodeLc(word,lcValid,lcOperand); |
break; |
case 0x0B: |
instruction=decodeLsb(word); |
break; |
case 0x0A: |
instruction=decodeLub(word); |
break; |
case 0x08: |
instruction=decodeLw(word); |
break; |
case 0x17: |
instruction=decodeMods(word); |
break; |
case 0x16: |
instruction=decodeModu(word); |
break; |
case 0x12: |
instruction=decodeMul(word); |
break; |
case 0x00: |
instruction=decodeNop(word); |
break; |
case 0x19: |
instruction=decodeOr(word); |
break; |
case 0x0E: |
instruction=decodeSb(word); |
break; |
case 0x1C: |
instruction=decodeSl(word); |
break; |
case 0x1F: |
instruction=decodeSrs(word); |
break; |
case 0x1E: |
instruction=decodeSru(word); |
break; |
case 0x11: |
instruction=decodeSub(word); |
break; |
case 0x0C: |
instruction=decodeSw(word); |
break; |
case 0x1A: |
instruction=decodeXor(word); |
break; |
default: |
if((opcode>>4)==0x03) instruction=decodeCjmpxx(word); |
else if((opcode>>3)==0x05) instruction=decodeLcs(word); |
else instruction=decodeWord(word); |
} |
|
auto size=instruction.size(); |
std::size_t padding=0; |
if(size<32) padding=32-size; |
|
_os<<'\t'<<instruction<<std::string(padding,' ')<<"// "; |
_os<<hex(offset)<<": "<<hex(word); |
if(lcValid) _os<<' '<<hex(lcOperand); |
_os<<std::endl; |
} |
} |
|
bool Disassembler::getWord(Word &w) { |
if(_fmt==Bin) { |
char buf[sizeof(Word)] {}; // zero-initialize |
_is.read(buf,sizeof(Word)); |
|
auto n=static_cast<std::size_t>(_is.gcount()); |
if(n==0) return false; |
if(n<sizeof(Word)) std::cerr<<"Warning: last word is truncated"<<std::endl; |
|
w=(static_cast<unsigned char>(buf[3])<<24)|(static_cast<unsigned char>(buf[2])<<16)| |
(static_cast<unsigned char>(buf[1])<<8)|static_cast<unsigned char>(buf[0]); |
} |
else { |
try { |
std::string line; |
if(!std::getline(_is,line)) return false; |
_lineNumber++; |
|
if(_fmt==Textio) w=std::stoul(line,nullptr,2); |
else if(_fmt==Dec) w=std::stoul(line,nullptr,10); |
else if(_fmt==Hex) w=std::stoul(line,nullptr,16); |
else return false; |
} |
catch(std::exception &) { |
throw std::runtime_error("Bad literal at line "+std::to_string(_lineNumber)); |
} |
} |
_pos+=sizeof(Word); |
return true; |
} |
|
std::string Disassembler::str(const Operand &op) { |
if(op.type()==Operand::Register) { |
if(!_preferAliases) return "r"+std::to_string(op.value()); |
else if(op.value()>=240&&op.value()<=247) return "iv"+std::to_string(op.value()-240); |
else if(op.value()==252) return "cr"; |
else if(op.value()==253) return "irp"; |
else if(op.value()==254) return "rp"; |
else if(op.value()==255) return "sp"; |
else return "r"+std::to_string(op.value()); |
} |
else return std::to_string(op.value()); |
} |
|
Disassembler::Operand Disassembler::decodeRd1Operand(Word w) { |
int value=(w>>8)&0xFF; |
if(w&0x02000000) return Operand(Operand::Register,value); |
else { |
if(value>127) value-=256; |
return Operand(Operand::Direct,value); |
} |
} |
|
Disassembler::Operand Disassembler::decodeRd2Operand(Word w) { |
int value=w&0xFF; |
if(w&0x01000000) return Operand(Operand::Register,value); |
else { |
if(value>127) value-=256; |
return Operand(Operand::Direct,value); |
} |
} |
|
Disassembler::Operand Disassembler::decodeDstOperand(Word w) { |
int value=(w>>16)&0xFF; |
return Operand(Operand::Register,value); |
} |
|
std::string Disassembler::decodeSimpleInstruction(const std::string &op,Word w) { |
std::ostringstream oss; |
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
oss<<op<<' '<<str(dst)<<", "<<str(rd1)<<", "<<str(rd2); |
return oss.str(); |
} |
|
std::string Disassembler::decodeAdd(Word w) { |
std::ostringstream oss; |
|
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(rd2.type()==Operand::Direct&&rd2.value()==0&&_preferAliases) |
oss<<"mov "<<str(dst)<<", "<<str(rd1); |
else |
oss<<"add "<<str(dst)<<", "<<str(rd1)<<", "<<str(rd2); |
|
return oss.str(); |
} |
|
std::string Disassembler::decodeAnd(Word w) { |
return decodeSimpleInstruction("and",w); |
} |
|
std::string Disassembler::decodeCall(Word w) { |
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(dst.value()!=0xFE) return decodeWord(w); |
if(rd1.type()!=Operand::Register) return decodeWord(w); |
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); |
|
return "call "+str(rd1); |
} |
|
std::string Disassembler::decodeCjmpxx(Word w) { |
auto jumpType=(w>>26)&0x0F; |
std::string op; |
|
switch(jumpType) { |
case 0x8: |
op="cjmpe"; |
break; |
case 0x4: |
op="cjmpne"; |
break; |
case 0x2: |
op="cjmpug"; |
break; |
case 0xA: |
op="cjmpuge"; |
break; |
case 0x1: |
op="cjmpsg"; |
break; |
case 0x9: |
op="cjmpsge"; |
break; |
default: |
return decodeWord(w); |
} |
|
return decodeSimpleInstruction(op,w); |
} |
|
std::string Disassembler::decodeDivs(Word w) { |
auto rd2=decodeRd2Operand(w); |
if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w); |
return decodeSimpleInstruction("divs",w); |
} |
|
std::string Disassembler::decodeDivu(Word w) { |
auto rd2=decodeRd2Operand(w); |
if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w); |
return decodeSimpleInstruction("divu",w); |
} |
|
std::string Disassembler::decodeHlt(Word w) { |
if(w!=0x08000000) return decodeWord(w); |
return "hlt"; |
} |
|
std::string Disassembler::decodeJmp(Word w) { |
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(dst.value()!=0) return decodeWord(w); |
if(rd1.type()!=Operand::Register) return decodeWord(w); |
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); |
|
if(rd1.value()==253&&_preferAliases) return "iret"; |
if(rd1.value()==254&&_preferAliases) return "ret"; |
return "jmp "+str(rd1); |
} |
|
std::string Disassembler::decodeLc(Word w,bool &valid,Word &operand) { |
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
valid=false; |
|
if(rd1.type()!=Operand::Direct||rd1.value()!=0) return decodeWord(w); |
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); |
|
bool b=getWord(operand); |
if(!b) return decodeWord(w); |
|
valid=true; |
return "lc "+str(dst)+", 0x"+hex(operand); |
} |
|
std::string Disassembler::decodeLcs(Word w) { |
auto dst=decodeDstOperand(w); |
auto operand=w&0xFFFF; |
operand|=(w>>8)&0x001F0000; |
if(operand&0x00100000) operand|=0xFFE00000; |
return "lcs "+str(dst)+", 0x"+hex(operand); |
} |
|
std::string Disassembler::decodeLsb(Word w) { |
std::ostringstream oss; |
|
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(rd1.type()!=Operand::Register) return decodeWord(w); |
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); |
|
return "lsb "+str(dst)+", "+str(rd1); |
} |
|
std::string Disassembler::decodeLub(Word w) { |
std::ostringstream oss; |
|
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(rd1.type()!=Operand::Register) return decodeWord(w); |
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); |
|
return "lub "+str(dst)+", "+str(rd1); |
} |
|
std::string Disassembler::decodeLw(Word w) { |
std::ostringstream oss; |
|
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(rd1.type()!=Operand::Register) return decodeWord(w); |
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); |
|
return "lw "+str(dst)+", "+str(rd1); |
} |
|
std::string Disassembler::decodeMods(Word w) { |
auto rd2=decodeRd2Operand(w); |
if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w); |
return decodeSimpleInstruction("mods",w); |
} |
|
std::string Disassembler::decodeModu(Word w) { |
auto rd2=decodeRd2Operand(w); |
if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w); |
return decodeSimpleInstruction("modu",w); |
} |
|
std::string Disassembler::decodeMul(Word w) { |
return decodeSimpleInstruction("mul",w); |
} |
|
std::string Disassembler::decodeNop(Word w) { |
if(w!=0) return decodeWord(w); |
return "nop"; |
} |
|
std::string Disassembler::decodeOr(Word w) { |
return decodeSimpleInstruction("or",w); |
} |
|
std::string Disassembler::decodeSb(Word w) { |
std::ostringstream oss; |
|
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(dst.value()!=0) return decodeWord(w); |
if(rd1.type()!=Operand::Register) return decodeWord(w); |
|
return "sb "+str(rd1)+", "+str(rd2); |
} |
|
std::string Disassembler::decodeSl(Word w) { |
auto rd2=decodeRd2Operand(w); |
if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w); |
return decodeSimpleInstruction("sl",w); |
} |
|
std::string Disassembler::decodeSrs(Word w) { |
auto rd2=decodeRd2Operand(w); |
if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w); |
return decodeSimpleInstruction("srs",w); |
} |
|
std::string Disassembler::decodeSru(Word w) { |
auto rd2=decodeRd2Operand(w); |
if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w); |
return decodeSimpleInstruction("sru",w); |
} |
|
std::string Disassembler::decodeSub(Word w) { |
std::ostringstream oss; |
|
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(rd1.type()==Operand::Direct&&rd1.value()==0&&_preferAliases) |
oss<<"neg "<<str(dst)<<", "<<str(rd2); |
else |
oss<<"sub "<<str(dst)<<", "<<str(rd1)<<", "<<str(rd2); |
|
return oss.str(); |
} |
|
std::string Disassembler::decodeSw(Word w) { |
std::ostringstream oss; |
|
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(dst.value()!=0) return decodeWord(w); |
if(rd1.type()!=Operand::Register) return decodeWord(w); |
|
return "sw "+str(rd1)+", "+str(rd2); |
} |
|
std::string Disassembler::decodeXor(Word w) { |
std::ostringstream oss; |
|
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(rd2.type()==Operand::Direct&&rd2.value()==-1&&_preferAliases) |
oss<<"not "<<str(dst)<<", "<<str(rd1); |
else |
oss<<"xor "<<str(dst)<<", "<<str(rd1)<<", "<<str(rd2); |
|
return oss.str(); |
} |
|
std::string Disassembler::decodeWord(Word w) { |
return ".word 0x"+hex(w); |
} |
/* |
* Copyright (c) 2016 by Alex I. Kuznetsov. |
* |
* Part of the LXP32 CPU IP core. |
* |
* This module implements members of the Disassembler class. |
*/ |
|
#include "disassembler.h" |
|
#include <stdexcept> |
|
/* |
* Disassembler::Operand class members |
*/ |
|
Disassembler::Operand::Operand(Type t,int value): |
_type(t),_value(value) {} |
|
Disassembler::Operand::Type Disassembler::Operand::type() const { |
return _type; |
} |
|
int Disassembler::Operand::value() const { |
return _value; |
} |
|
/* |
* Disassembler class members |
*/ |
|
Disassembler::Disassembler(std::istream &is,std::ostream &os): |
_is(is),_os(os),_fmt(Bin),_preferAliases(true),_lineNumber(0),_pos(0) {} |
|
void Disassembler::setFormat(Format fmt) { |
_fmt=fmt; |
} |
|
void Disassembler::setBase(Word base) { |
_pos=base; |
} |
|
void Disassembler::setPreferAliases(bool b) { |
_preferAliases=b; |
} |
|
void Disassembler::dump() { |
Word word; |
|
for(;;) { |
auto offset=_pos; |
if(!getWord(word)) break; |
auto opcode=word>>26; |
|
std::string instruction; |
|
bool lcValid=false; |
Word lcOperand; |
|
switch(opcode) { |
case 0x10: |
instruction=decodeAdd(word); |
break; |
case 0x18: |
instruction=decodeAnd(word); |
break; |
case 0x21: |
instruction=decodeCall(word); |
break; |
case 0x15: |
instruction=decodeDivs(word); |
break; |
case 0x14: |
instruction=decodeDivu(word); |
break; |
case 0x02: |
instruction=decodeHlt(word); |
break; |
case 0x20: |
instruction=decodeJmp(word); |
break; |
case 0x01: |
instruction=decodeLc(word,lcValid,lcOperand); |
break; |
case 0x0B: |
instruction=decodeLsb(word); |
break; |
case 0x0A: |
instruction=decodeLub(word); |
break; |
case 0x08: |
instruction=decodeLw(word); |
break; |
case 0x17: |
instruction=decodeMods(word); |
break; |
case 0x16: |
instruction=decodeModu(word); |
break; |
case 0x12: |
instruction=decodeMul(word); |
break; |
case 0x00: |
instruction=decodeNop(word); |
break; |
case 0x19: |
instruction=decodeOr(word); |
break; |
case 0x0E: |
instruction=decodeSb(word); |
break; |
case 0x1C: |
instruction=decodeSl(word); |
break; |
case 0x1F: |
instruction=decodeSrs(word); |
break; |
case 0x1E: |
instruction=decodeSru(word); |
break; |
case 0x11: |
instruction=decodeSub(word); |
break; |
case 0x0C: |
instruction=decodeSw(word); |
break; |
case 0x1A: |
instruction=decodeXor(word); |
break; |
default: |
if((opcode>>4)==0x03) instruction=decodeCjmpxx(word); |
else if((opcode>>3)==0x05) instruction=decodeLcs(word); |
else instruction=decodeWord(word); |
} |
|
auto size=instruction.size(); |
std::size_t padding=0; |
if(size<32) padding=32-size; |
|
_os<<'\t'<<instruction<<std::string(padding,' ')<<"// "; |
_os<<hex(offset)<<": "<<hex(word); |
if(lcValid) _os<<' '<<hex(lcOperand); |
_os<<std::endl; |
} |
} |
|
bool Disassembler::getWord(Word &w) { |
if(_fmt==Bin) { |
char buf[sizeof(Word)] {}; // zero-initialize |
_is.read(buf,sizeof(Word)); |
|
auto n=static_cast<std::size_t>(_is.gcount()); |
if(n==0) return false; |
if(n<sizeof(Word)) std::cerr<<"Warning: last word is truncated"<<std::endl; |
|
w=(static_cast<unsigned char>(buf[3])<<24)|(static_cast<unsigned char>(buf[2])<<16)| |
(static_cast<unsigned char>(buf[1])<<8)|static_cast<unsigned char>(buf[0]); |
} |
else { |
try { |
std::string line; |
if(!std::getline(_is,line)) return false; |
_lineNumber++; |
|
if(_fmt==Textio) w=std::stoul(line,nullptr,2); |
else if(_fmt==Dec) w=std::stoul(line,nullptr,10); |
else if(_fmt==Hex) w=std::stoul(line,nullptr,16); |
else return false; |
} |
catch(std::exception &) { |
throw std::runtime_error("Bad literal at line "+std::to_string(_lineNumber)); |
} |
} |
_pos+=sizeof(Word); |
return true; |
} |
|
std::string Disassembler::str(const Operand &op) { |
if(op.type()==Operand::Register) { |
if(!_preferAliases) return "r"+std::to_string(op.value()); |
else if(op.value()>=240&&op.value()<=247) return "iv"+std::to_string(op.value()-240); |
else if(op.value()==252) return "cr"; |
else if(op.value()==253) return "irp"; |
else if(op.value()==254) return "rp"; |
else if(op.value()==255) return "sp"; |
else return "r"+std::to_string(op.value()); |
} |
else return std::to_string(op.value()); |
} |
|
Disassembler::Operand Disassembler::decodeRd1Operand(Word w) { |
int value=(w>>8)&0xFF; |
if(w&0x02000000) return Operand(Operand::Register,value); |
else { |
if(value>127) value-=256; |
return Operand(Operand::Direct,value); |
} |
} |
|
Disassembler::Operand Disassembler::decodeRd2Operand(Word w) { |
int value=w&0xFF; |
if(w&0x01000000) return Operand(Operand::Register,value); |
else { |
if(value>127) value-=256; |
return Operand(Operand::Direct,value); |
} |
} |
|
Disassembler::Operand Disassembler::decodeDstOperand(Word w) { |
int value=(w>>16)&0xFF; |
return Operand(Operand::Register,value); |
} |
|
std::string Disassembler::decodeSimpleInstruction(const std::string &op,Word w) { |
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
return op+' '+str(dst)+", "+str(rd1)+", "+str(rd2); |
} |
|
std::string Disassembler::decodeAdd(Word w) { |
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(rd2.type()==Operand::Direct&&rd2.value()==0&&_preferAliases) |
return "mov "+str(dst)+", "+str(rd1); |
else |
return "add "+str(dst)+", "+str(rd1)+", "+str(rd2); |
} |
|
std::string Disassembler::decodeAnd(Word w) { |
return decodeSimpleInstruction("and",w); |
} |
|
std::string Disassembler::decodeCall(Word w) { |
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(dst.value()!=0xFE) return decodeWord(w); |
if(rd1.type()!=Operand::Register) return decodeWord(w); |
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); |
|
return "call "+str(rd1); |
} |
|
std::string Disassembler::decodeCjmpxx(Word w) { |
auto jumpType=(w>>26)&0x0F; |
std::string op; |
|
switch(jumpType) { |
case 0x8: |
op="cjmpe"; |
break; |
case 0x4: |
op="cjmpne"; |
break; |
case 0x2: |
op="cjmpug"; |
break; |
case 0xA: |
op="cjmpuge"; |
break; |
case 0x1: |
op="cjmpsg"; |
break; |
case 0x9: |
op="cjmpsge"; |
break; |
default: |
return decodeWord(w); |
} |
|
return decodeSimpleInstruction(op,w); |
} |
|
std::string Disassembler::decodeDivs(Word w) { |
auto rd2=decodeRd2Operand(w); |
if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w); |
return decodeSimpleInstruction("divs",w); |
} |
|
std::string Disassembler::decodeDivu(Word w) { |
auto rd2=decodeRd2Operand(w); |
if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w); |
return decodeSimpleInstruction("divu",w); |
} |
|
std::string Disassembler::decodeHlt(Word w) { |
if(w!=0x08000000) return decodeWord(w); |
return "hlt"; |
} |
|
std::string Disassembler::decodeJmp(Word w) { |
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(dst.value()!=0) return decodeWord(w); |
if(rd1.type()!=Operand::Register) return decodeWord(w); |
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); |
|
if(rd1.value()==253&&_preferAliases) return "iret"; |
if(rd1.value()==254&&_preferAliases) return "ret"; |
return "jmp "+str(rd1); |
} |
|
std::string Disassembler::decodeLc(Word w,bool &valid,Word &operand) { |
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
valid=false; |
|
if(rd1.type()!=Operand::Direct||rd1.value()!=0) return decodeWord(w); |
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); |
|
bool b=getWord(operand); |
if(!b) return decodeWord(w); |
|
valid=true; |
return "lc "+str(dst)+", 0x"+hex(operand); |
} |
|
std::string Disassembler::decodeLcs(Word w) { |
auto dst=decodeDstOperand(w); |
auto operand=w&0xFFFF; |
operand|=(w>>8)&0x001F0000; |
if(operand&0x00100000) operand|=0xFFE00000; |
return "lcs "+str(dst)+", 0x"+hex(operand); |
} |
|
std::string Disassembler::decodeLsb(Word w) { |
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(rd1.type()!=Operand::Register) return decodeWord(w); |
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); |
|
return "lsb "+str(dst)+", "+str(rd1); |
} |
|
std::string Disassembler::decodeLub(Word w) { |
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(rd1.type()!=Operand::Register) return decodeWord(w); |
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); |
|
return "lub "+str(dst)+", "+str(rd1); |
} |
|
std::string Disassembler::decodeLw(Word w) { |
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(rd1.type()!=Operand::Register) return decodeWord(w); |
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w); |
|
return "lw "+str(dst)+", "+str(rd1); |
} |
|
std::string Disassembler::decodeMods(Word w) { |
auto rd2=decodeRd2Operand(w); |
if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w); |
return decodeSimpleInstruction("mods",w); |
} |
|
std::string Disassembler::decodeModu(Word w) { |
auto rd2=decodeRd2Operand(w); |
if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w); |
return decodeSimpleInstruction("modu",w); |
} |
|
std::string Disassembler::decodeMul(Word w) { |
return decodeSimpleInstruction("mul",w); |
} |
|
std::string Disassembler::decodeNop(Word w) { |
if(w!=0) return decodeWord(w); |
return "nop"; |
} |
|
std::string Disassembler::decodeOr(Word w) { |
return decodeSimpleInstruction("or",w); |
} |
|
std::string Disassembler::decodeSb(Word w) { |
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(dst.value()!=0) return decodeWord(w); |
if(rd1.type()!=Operand::Register) return decodeWord(w); |
|
return "sb "+str(rd1)+", "+str(rd2); |
} |
|
std::string Disassembler::decodeSl(Word w) { |
auto rd2=decodeRd2Operand(w); |
if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w); |
return decodeSimpleInstruction("sl",w); |
} |
|
std::string Disassembler::decodeSrs(Word w) { |
auto rd2=decodeRd2Operand(w); |
if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w); |
return decodeSimpleInstruction("srs",w); |
} |
|
std::string Disassembler::decodeSru(Word w) { |
auto rd2=decodeRd2Operand(w); |
if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w); |
return decodeSimpleInstruction("sru",w); |
} |
|
std::string Disassembler::decodeSub(Word w) { |
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(rd1.type()==Operand::Direct&&rd1.value()==0&&_preferAliases) |
return "neg "+str(dst)+", "+str(rd2); |
else |
return "sub "+str(dst)+", "+str(rd1)+", "+str(rd2); |
} |
|
std::string Disassembler::decodeSw(Word w) { |
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(dst.value()!=0) return decodeWord(w); |
if(rd1.type()!=Operand::Register) return decodeWord(w); |
|
return "sw "+str(rd1)+", "+str(rd2); |
} |
|
std::string Disassembler::decodeXor(Word w) { |
auto dst=decodeDstOperand(w); |
auto rd1=decodeRd1Operand(w); |
auto rd2=decodeRd2Operand(w); |
|
if(rd2.type()==Operand::Direct&&rd2.value()==-1&&_preferAliases) |
return "not "+str(dst)+", "+str(rd1); |
else |
return "xor "+str(dst)+", "+str(rd1)+", "+str(rd2); |
} |
|
std::string Disassembler::decodeWord(Word w) { |
return ".word 0x"+hex(w); |
} |
/disassembler.h
1,95 → 1,95
/* |
* Copyright (c) 2016 by Alex I. Kuznetsov. |
* |
* Part of the LXP32 CPU IP core. |
* |
* This module defines the Disassembler class which disassembles |
* LXP32 executable code. |
*/ |
|
#ifndef DISASSEMBLER_H_INCLUDED |
#define DISASSEMBLER_H_INCLUDED |
|
#include <iostream> |
#include <type_traits> |
#include <cstdint> |
|
class Disassembler { |
public: |
enum Format {Bin,Textio,Dec,Hex}; |
typedef std::uint32_t Word; |
private: |
class Operand { |
public: |
enum Type {Register,Direct}; |
private: |
Type _type; |
int _value; |
public: |
Operand(Type t,int value); |
Type type() const; |
int value() const; |
}; |
|
std::istream &_is; |
std::ostream &_os; |
Format _fmt; |
bool _preferAliases; |
int _lineNumber; |
Word _pos; |
public: |
Disassembler(std::istream &is,std::ostream &os); |
void setFormat(Format fmt); |
void setBase(Word base); |
void setPreferAliases(bool b); |
void dump(); |
|
template <typename T> static std::string hex(const T &w) { |
static_assert(std::is_integral<T>::value,"Argument must be of integral type"); |
const char *hexstr="0123456789ABCDEF"; |
std::string res; |
|
res.reserve(sizeof(T)*2); |
|
for(int i=sizeof(T)*8-4;i>=0;i-=4) { |
res.push_back(hexstr[(w>>i)&0x0F]); |
} |
return res; |
} |
private: |
bool getWord(Word &w); |
std::string str(const Operand &op); |
static Operand decodeRd1Operand(Word w); |
static Operand decodeRd2Operand(Word w); |
static Operand decodeDstOperand(Word w); |
|
std::string decodeSimpleInstruction(const std::string &op,Word w); |
std::string decodeAdd(Word w); |
std::string decodeAnd(Word w); |
std::string decodeCall(Word w); |
std::string decodeCjmpxx(Word w); |
std::string decodeDivs(Word w); |
std::string decodeDivu(Word w); |
std::string decodeHlt(Word w); |
std::string decodeJmp(Word w); |
std::string decodeLc(Word w,bool &valid,Word &operand); |
std::string decodeLcs(Word w); |
std::string decodeLsb(Word w); |
std::string decodeLub(Word w); |
std::string decodeLw(Word w); |
std::string decodeMods(Word w); |
std::string decodeModu(Word w); |
std::string decodeMul(Word w); |
std::string decodeNop(Word w); |
std::string decodeOr(Word w); |
std::string decodeSb(Word w); |
std::string decodeSl(Word w); |
std::string decodeSrs(Word w); |
std::string decodeSru(Word w); |
std::string decodeSub(Word w); |
std::string decodeSw(Word w); |
std::string decodeXor(Word w); |
std::string decodeWord(Word w); |
}; |
|
#endif |
/* |
* Copyright (c) 2016 by Alex I. Kuznetsov. |
* |
* Part of the LXP32 CPU IP core. |
* |
* This module defines the Disassembler class which disassembles |
* LXP32 executable code. |
*/ |
|
#ifndef DISASSEMBLER_H_INCLUDED |
#define DISASSEMBLER_H_INCLUDED |
|
#include <iostream> |
#include <type_traits> |
#include <cstdint> |
|
class Disassembler { |
public: |
enum Format {Bin,Textio,Dec,Hex}; |
typedef std::uint32_t Word; |
private: |
class Operand { |
public: |
enum Type {Register,Direct}; |
private: |
Type _type; |
int _value; |
public: |
Operand(Type t,int value); |
Type type() const; |
int value() const; |
}; |
|
std::istream &_is; |
std::ostream &_os; |
Format _fmt; |
bool _preferAliases; |
int _lineNumber; |
Word _pos; |
public: |
Disassembler(std::istream &is,std::ostream &os); |
void setFormat(Format fmt); |
void setBase(Word base); |
void setPreferAliases(bool b); |
void dump(); |
|
template <typename T> static std::string hex(const T &w) { |
static_assert(std::is_integral<T>::value,"Argument must be of integral type"); |
const char *hexstr="0123456789ABCDEF"; |
std::string res; |
|
res.reserve(sizeof(T)*2); |
|
for(int i=sizeof(T)*8-4;i>=0;i-=4) { |
res.push_back(hexstr[(w>>i)&0x0F]); |
} |
return res; |
} |
private: |
bool getWord(Word &w); |
std::string str(const Operand &op); |
static Operand decodeRd1Operand(Word w); |
static Operand decodeRd2Operand(Word w); |
static Operand decodeDstOperand(Word w); |
|
std::string decodeSimpleInstruction(const std::string &op,Word w); |
std::string decodeAdd(Word w); |
std::string decodeAnd(Word w); |
std::string decodeCall(Word w); |
std::string decodeCjmpxx(Word w); |
std::string decodeDivs(Word w); |
std::string decodeDivu(Word w); |
std::string decodeHlt(Word w); |
std::string decodeJmp(Word w); |
std::string decodeLc(Word w,bool &valid,Word &operand); |
std::string decodeLcs(Word w); |
std::string decodeLsb(Word w); |
std::string decodeLub(Word w); |
std::string decodeLw(Word w); |
std::string decodeMods(Word w); |
std::string decodeModu(Word w); |
std::string decodeMul(Word w); |
std::string decodeNop(Word w); |
std::string decodeOr(Word w); |
std::string decodeSb(Word w); |
std::string decodeSl(Word w); |
std::string decodeSrs(Word w); |
std::string decodeSru(Word w); |
std::string decodeSub(Word w); |
std::string decodeSw(Word w); |
std::string decodeXor(Word w); |
std::string decodeWord(Word w); |
}; |
|
#endif |
/main.cpp
1,199 → 1,199
/* |
* Copyright (c) 2016 by Alex I. Kuznetsov. |
* |
* Part of the LXP32 CPU IP core. |
* |
* Main translation unit for the LXP32 disassembler. |
*/ |
|
#ifdef _MSC_VER |
#define _CRT_SECURE_NO_WARNINGS |
#endif |
|
#include "disassembler.h" |
|
#include <iostream> |
#include <fstream> |
#include <string> |
#include <stdexcept> |
#include <cstring> |
#include <cstdlib> |
#include <cstdio> |
#include <ctime> |
|
static void displayUsage(std::ostream &os,const char *program) { |
os<<std::endl; |
os<<"Usage:"<<std::endl; |
os<<" "<<program<<" [ option(s) | input file ]"<<std::endl<<std::endl; |
|
os<<"Options:"<<std::endl; |
os<<" -b <addr> Base address (for comments only)"<<std::endl; |
os<<" -f <fmt> Input format (bin, textio, dec, hex), default: autodetect"<<std::endl; |
os<<" -h, --help Display a short help message"<<std::endl; |
os<<" -na Do not use instruction and register aliases"<<std::endl; |
os<<" -o <file> Output file name, default: standard output"<<std::endl; |
os<<" -- Do not interpret subsequent arguments as options"<<std::endl; |
} |
|
static Disassembler::Format detectInputFormat(std::istream &in) { |
static const std::size_t Size=256; |
static const char *textio="01\r\n \t"; |
static const char *dec="0123456789\r\n \t"; |
static const char *hex="0123456789ABCDEFabcdef\r\n \t"; |
|
char buf[Size]; |
in.read(buf,Size); |
auto s=static_cast<std::size_t>(in.gcount()); |
in.clear(); |
in.seekg(0); |
|
Disassembler::Format fmt=Disassembler::Textio; |
|
for(std::size_t i=0;i<s;i++) { |
if(fmt==Disassembler::Textio&&!strchr(textio,buf[i])) fmt=Disassembler::Dec; |
if(fmt==Disassembler::Dec&&!strchr(dec,buf[i])) fmt=Disassembler::Hex; |
if(fmt==Disassembler::Hex&&!strchr(hex,buf[i])) { |
fmt=Disassembler::Bin; |
break; |
} |
} |
|
return fmt; |
} |
|
int main(int argc,char *argv[]) try { |
std::string inputFileName,outputFileName; |
|
std::cerr<<"LXP32 Platform Disassembler"<<std::endl; |
std::cerr<<"Copyright (c) 2016-2019 by Alex I. Kuznetsov"<<std::endl; |
|
Disassembler::Format fmt=Disassembler::Bin; |
bool noMoreOptions=false; |
bool formatSpecified=false; |
Disassembler::Word base=0; |
bool noAliases=false; |
|
if(argc<=1) { |
displayUsage(std::cout,argv[0]); |
return 0; |
} |
|
for(int i=1;i<argc;i++) { |
if(argv[i][0]!='-'||noMoreOptions) { |
if(inputFileName.empty()) inputFileName=argv[i]; |
else throw std::runtime_error("Only one input file name can be specified"); |
} |
else if(!strcmp(argv[i],"--")) noMoreOptions=true; |
else if(!strcmp(argv[i],"-b")) { |
if(++i==argc) { |
displayUsage(std::cerr,argv[0]); |
return EXIT_FAILURE; |
} |
try { |
base=std::stoul(argv[i],nullptr,0); |
if(base%4!=0) throw std::exception(); |
} |
catch(std::exception &) { |
throw std::runtime_error("Invalid base address"); |
} |
} |
else if(!strcmp(argv[i],"-f")) { |
if(++i==argc) { |
displayUsage(std::cerr,argv[0]); |
return EXIT_FAILURE; |
} |
if(!strcmp(argv[i],"bin")) fmt=Disassembler::Bin; |
else if(!strcmp(argv[i],"textio")) fmt=Disassembler::Textio; |
else if(!strcmp(argv[i],"dec")) fmt=Disassembler::Dec; |
else if(!strcmp(argv[i],"hex")) fmt=Disassembler::Hex; |
else throw std::runtime_error("Unrecognized input format"); |
formatSpecified=true; |
} |
else if(!strcmp(argv[i],"-h")||!strcmp(argv[i],"--help")) { |
displayUsage(std::cout,argv[0]); |
return 0; |
} |
else if(!strcmp(argv[i],"-na")) { |
noAliases=true; |
} |
else if(!strcmp(argv[i],"-o")) { |
if(++i==argc) { |
displayUsage(std::cerr,argv[0]); |
return EXIT_FAILURE; |
} |
outputFileName=argv[i]; |
} |
else throw std::runtime_error(std::string("Unrecognized option: \"")+argv[i]+"\""); |
} |
|
if(!formatSpecified) { // auto-detect input file format |
std::ifstream in(inputFileName,std::ios_base::in|std::ios_base::binary); |
fmt=detectInputFormat(in); |
} |
|
std::ifstream in; |
|
if(fmt==Disassembler::Bin) in.open(inputFileName,std::ios_base::in|std::ios_base::binary); |
else in.open(inputFileName,std::ios_base::in); |
if(!in) throw std::runtime_error("Cannot open \""+inputFileName+"\""); |
|
std::ofstream out; |
std::ostream *os=&std::cout; |
if(!outputFileName.empty()) { |
out.open(outputFileName,std::ios_base::out); |
if(!out) throw std::runtime_error("Cannot open \""+outputFileName+"\""); |
os=&out; |
} |
|
auto t=std::time(NULL); |
char szTime[256]; |
auto r=std::strftime(szTime,256,"%c",std::localtime(&t)); |
if(r==0) szTime[0]='\0'; |
|
*os<<"/*"<<std::endl; |
*os<<" * Input file: "<<inputFileName<<std::endl; |
*os<<" * Input format: "; |
|
switch(fmt) { |
case Disassembler::Bin: |
*os<<"bin"; |
break; |
case Disassembler::Textio: |
*os<<"textio"; |
break; |
case Disassembler::Dec: |
*os<<"dec"; |
break; |
case Disassembler::Hex: |
*os<<"hex"; |
break; |
default: |
break; |
} |
|
if(!formatSpecified) *os<<" (autodetected)"; |
*os<<std::endl; |
*os<<" * Base address: 0x"<<Disassembler::hex(base)<<std::endl; |
*os<<" * Disassembled by lxp32dump at "<<szTime<<std::endl; |
*os<<" */"<<std::endl<<std::endl; |
|
Disassembler disasm(in,*os); |
disasm.setFormat(fmt); |
disasm.setBase(base); |
disasm.setPreferAliases(!noAliases); |
|
try { |
disasm.dump(); |
} |
catch(std::exception &) { |
if(!outputFileName.empty()) { |
out.close(); |
std::remove(outputFileName.c_str()); |
} |
throw; |
} |
} |
catch(std::exception &ex) { |
std::cerr<<"Error: "<<ex.what()<<std::endl; |
return EXIT_FAILURE; |
} |
/* |
* Copyright (c) 2016 by Alex I. Kuznetsov. |
* |
* Part of the LXP32 CPU IP core. |
* |
* Main translation unit for the LXP32 disassembler. |
*/ |
|
#ifdef _MSC_VER |
#define _CRT_SECURE_NO_WARNINGS |
#endif |
|
#include "disassembler.h" |
|
#include <iostream> |
#include <fstream> |
#include <string> |
#include <stdexcept> |
#include <cstring> |
#include <cstdlib> |
#include <cstdio> |
#include <ctime> |
|
static void displayUsage(std::ostream &os,const char *program) { |
os<<std::endl; |
os<<"Usage:"<<std::endl; |
os<<" "<<program<<" [ option(s) | input file ]"<<std::endl<<std::endl; |
|
os<<"Options:"<<std::endl; |
os<<" -b <addr> Base address (for comments only)"<<std::endl; |
os<<" -f <fmt> Input format (bin, textio, dec, hex), default: autodetect"<<std::endl; |
os<<" -h, --help Display a short help message"<<std::endl; |
os<<" -na Do not use instruction and register aliases"<<std::endl; |
os<<" -o <file> Output file name, default: standard output"<<std::endl; |
os<<" -- Do not interpret subsequent arguments as options"<<std::endl; |
} |
|
static Disassembler::Format detectInputFormat(std::istream &in) { |
static const std::size_t Size=256; |
static const char *textio="01\r\n \t"; |
static const char *dec="0123456789\r\n \t"; |
static const char *hex="0123456789ABCDEFabcdef\r\n \t"; |
|
char buf[Size]; |
in.read(buf,Size); |
auto s=static_cast<std::size_t>(in.gcount()); |
in.clear(); |
in.seekg(0); |
|
Disassembler::Format fmt=Disassembler::Textio; |
|
for(std::size_t i=0;i<s;i++) { |
if(fmt==Disassembler::Textio&&!strchr(textio,buf[i])) fmt=Disassembler::Dec; |
if(fmt==Disassembler::Dec&&!strchr(dec,buf[i])) fmt=Disassembler::Hex; |
if(fmt==Disassembler::Hex&&!strchr(hex,buf[i])) { |
fmt=Disassembler::Bin; |
break; |
} |
} |
|
return fmt; |
} |
|
int main(int argc,char *argv[]) try { |
std::string inputFileName,outputFileName; |
|
std::cerr<<"LXP32 Platform Disassembler"<<std::endl; |
std::cerr<<"Copyright (c) 2016-2019 by Alex I. Kuznetsov"<<std::endl; |
|
Disassembler::Format fmt=Disassembler::Bin; |
bool noMoreOptions=false; |
bool formatSpecified=false; |
Disassembler::Word base=0; |
bool noAliases=false; |
|
if(argc<=1) { |
displayUsage(std::cout,argv[0]); |
return 0; |
} |
|
for(int i=1;i<argc;i++) { |
if(argv[i][0]!='-'||noMoreOptions) { |
if(inputFileName.empty()) inputFileName=argv[i]; |
else throw std::runtime_error("Only one input file name can be specified"); |
} |
else if(!strcmp(argv[i],"--")) noMoreOptions=true; |
else if(!strcmp(argv[i],"-b")) { |
if(++i==argc) { |
displayUsage(std::cerr,argv[0]); |
return EXIT_FAILURE; |
} |
try { |
base=std::stoul(argv[i],nullptr,0); |
if(base%4!=0) throw std::exception(); |
} |
catch(std::exception &) { |
throw std::runtime_error("Invalid base address"); |
} |
} |
else if(!strcmp(argv[i],"-f")) { |
if(++i==argc) { |
displayUsage(std::cerr,argv[0]); |
return EXIT_FAILURE; |
} |
if(!strcmp(argv[i],"bin")) fmt=Disassembler::Bin; |
else if(!strcmp(argv[i],"textio")) fmt=Disassembler::Textio; |
else if(!strcmp(argv[i],"dec")) fmt=Disassembler::Dec; |
else if(!strcmp(argv[i],"hex")) fmt=Disassembler::Hex; |
else throw std::runtime_error("Unrecognized input format"); |
formatSpecified=true; |
} |
else if(!strcmp(argv[i],"-h")||!strcmp(argv[i],"--help")) { |
displayUsage(std::cout,argv[0]); |
return 0; |
} |
else if(!strcmp(argv[i],"-na")) { |
noAliases=true; |
} |
else if(!strcmp(argv[i],"-o")) { |
if(++i==argc) { |
displayUsage(std::cerr,argv[0]); |
return EXIT_FAILURE; |
} |
outputFileName=argv[i]; |
} |
else throw std::runtime_error(std::string("Unrecognized option: \"")+argv[i]+"\""); |
} |
|
if(!formatSpecified) { // auto-detect input file format |
std::ifstream in(inputFileName,std::ios_base::in|std::ios_base::binary); |
fmt=detectInputFormat(in); |
} |
|
std::ifstream in; |
|
if(fmt==Disassembler::Bin) in.open(inputFileName,std::ios_base::in|std::ios_base::binary); |
else in.open(inputFileName,std::ios_base::in); |
if(!in) throw std::runtime_error("Cannot open \""+inputFileName+"\""); |
|
std::ofstream out; |
std::ostream *os=&std::cout; |
if(!outputFileName.empty()) { |
out.open(outputFileName,std::ios_base::out); |
if(!out) throw std::runtime_error("Cannot open \""+outputFileName+"\""); |
os=&out; |
} |
|
auto t=std::time(NULL); |
char szTime[256]; |
auto r=std::strftime(szTime,256,"%c",std::localtime(&t)); |
if(r==0) szTime[0]='\0'; |
|
*os<<"/*"<<std::endl; |
*os<<" * Input file: "<<inputFileName<<std::endl; |
*os<<" * Input format: "; |
|
switch(fmt) { |
case Disassembler::Bin: |
*os<<"bin"; |
break; |
case Disassembler::Textio: |
*os<<"textio"; |
break; |
case Disassembler::Dec: |
*os<<"dec"; |
break; |
case Disassembler::Hex: |
*os<<"hex"; |
break; |
default: |
break; |
} |
|
if(!formatSpecified) *os<<" (autodetected)"; |
*os<<std::endl; |
*os<<" * Base address: 0x"<<Disassembler::hex(base)<<std::endl; |
*os<<" * Disassembled by lxp32dump at "<<szTime<<std::endl; |
*os<<" */"<<std::endl<<std::endl; |
|
Disassembler disasm(in,*os); |
disasm.setFormat(fmt); |
disasm.setBase(base); |
disasm.setPreferAliases(!noAliases); |
|
try { |
disasm.dump(); |
} |
catch(std::exception &) { |
if(!outputFileName.empty()) { |
out.close(); |
std::remove(outputFileName.c_str()); |
} |
throw; |
} |
} |
catch(std::exception &ex) { |
std::cerr<<"Error: "<<ex.what()<<std::endl; |
return EXIT_FAILURE; |
} |