OpenCores
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;
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.