/*
|
/*
|
* Copyright (c) 2016 by Alex I. Kuznetsov.
|
* Copyright (c) 2016 by Alex I. Kuznetsov.
|
*
|
*
|
* Part of the LXP32 CPU IP core.
|
* Part of the LXP32 CPU IP core.
|
*
|
*
|
* This module implements members of the Disassembler class.
|
* This module implements members of the Disassembler class.
|
*/
|
*/
|
|
|
#include "disassembler.h"
|
#include "disassembler.h"
|
|
|
#include <sstream>
|
#include <sstream>
|
#include <stdexcept>
|
#include <stdexcept>
|
|
|
/*
|
/*
|
* Disassembler::Operand class members
|
* Disassembler::Operand class members
|
*/
|
*/
|
|
|
Disassembler::Operand::Operand(Type t,int value):
|
Disassembler::Operand::Operand(Type t,int value):
|
_type(t),_value(value) {}
|
_type(t),_value(value) {}
|
|
|
Disassembler::Operand::Type Disassembler::Operand::type() const {
|
Disassembler::Operand::Type Disassembler::Operand::type() const {
|
return _type;
|
return _type;
|
}
|
}
|
|
|
int Disassembler::Operand::value() const {
|
int Disassembler::Operand::value() const {
|
return _value;
|
return _value;
|
}
|
}
|
|
|
std::string Disassembler::Operand::str() const {
|
|
if(_type==Register) {
|
|
if(_value>=240&&_value<=247) return "iv"+std::to_string(_value-240);
|
|
else if(_value==252) return "cr";
|
|
else if(_value==253) return "irp";
|
|
else if(_value==254) return "rp";
|
|
else if(_value==255) return "sp";
|
|
else return "r"+std::to_string(_value);
|
|
}
|
|
else return std::to_string(_value);
|
|
}
|
|
|
|
/*
|
/*
|
* Disassembler class members
|
* Disassembler class members
|
*/
|
*/
|
|
|
Disassembler::Disassembler(std::istream &is,std::ostream &os):
|
Disassembler::Disassembler(std::istream &is,std::ostream &os):
|
_is(is),_os(os),_fmt(Bin),_lineNumber(0),_pos(0) {}
|
_is(is),_os(os),_fmt(Bin),_preferAliases(true),_lineNumber(0),_pos(0) {}
|
|
|
void Disassembler::setFormat(Format fmt) {
|
void Disassembler::setFormat(Format fmt) {
|
_fmt=fmt;
|
_fmt=fmt;
|
}
|
}
|
|
|
void Disassembler::setBase(Word base) {
|
void Disassembler::setBase(Word base) {
|
_pos=base;
|
_pos=base;
|
}
|
}
|
|
|
|
void Disassembler::setPreferAliases(bool b) {
|
|
_preferAliases=b;
|
|
}
|
|
|
void Disassembler::dump() {
|
void Disassembler::dump() {
|
Word word;
|
Word word;
|
|
|
for(;;) {
|
for(;;) {
|
auto offset=_pos;
|
auto offset=_pos;
|
if(!getWord(word)) break;
|
if(!getWord(word)) break;
|
auto opcode=word>>26;
|
auto opcode=word>>26;
|
|
|
std::string instruction;
|
std::string instruction;
|
|
|
bool lcValid=false;
|
bool lcValid=false;
|
Word lcOperand;
|
Word lcOperand;
|
|
|
switch(opcode) {
|
switch(opcode) {
|
case 0x10:
|
case 0x10:
|
instruction=decodeAdd(word);
|
instruction=decodeAdd(word);
|
break;
|
break;
|
case 0x18:
|
case 0x18:
|
instruction=decodeAnd(word);
|
instruction=decodeAnd(word);
|
break;
|
break;
|
case 0x21:
|
case 0x21:
|
instruction=decodeCall(word);
|
instruction=decodeCall(word);
|
break;
|
break;
|
case 0x15:
|
case 0x15:
|
instruction=decodeDivs(word);
|
instruction=decodeDivs(word);
|
break;
|
break;
|
case 0x14:
|
case 0x14:
|
instruction=decodeDivu(word);
|
instruction=decodeDivu(word);
|
break;
|
break;
|
case 0x02:
|
case 0x02:
|
instruction=decodeHlt(word);
|
instruction=decodeHlt(word);
|
break;
|
break;
|
case 0x20:
|
case 0x20:
|
instruction=decodeJmp(word);
|
instruction=decodeJmp(word);
|
break;
|
break;
|
case 0x01:
|
case 0x01:
|
instruction=decodeLc(word,lcValid,lcOperand);
|
instruction=decodeLc(word,lcValid,lcOperand);
|
break;
|
break;
|
case 0x0B:
|
case 0x0B:
|
instruction=decodeLsb(word);
|
instruction=decodeLsb(word);
|
break;
|
break;
|
case 0x0A:
|
case 0x0A:
|
instruction=decodeLub(word);
|
instruction=decodeLub(word);
|
break;
|
break;
|
case 0x08:
|
case 0x08:
|
instruction=decodeLw(word);
|
instruction=decodeLw(word);
|
break;
|
break;
|
case 0x17:
|
case 0x17:
|
instruction=decodeMods(word);
|
instruction=decodeMods(word);
|
break;
|
break;
|
case 0x16:
|
case 0x16:
|
instruction=decodeModu(word);
|
instruction=decodeModu(word);
|
break;
|
break;
|
case 0x12:
|
case 0x12:
|
instruction=decodeMul(word);
|
instruction=decodeMul(word);
|
break;
|
break;
|
case 0x00:
|
case 0x00:
|
instruction=decodeNop(word);
|
instruction=decodeNop(word);
|
break;
|
break;
|
case 0x19:
|
case 0x19:
|
instruction=decodeOr(word);
|
instruction=decodeOr(word);
|
break;
|
break;
|
case 0x0E:
|
case 0x0E:
|
instruction=decodeSb(word);
|
instruction=decodeSb(word);
|
break;
|
break;
|
case 0x1C:
|
case 0x1C:
|
instruction=decodeSl(word);
|
instruction=decodeSl(word);
|
break;
|
break;
|
case 0x1F:
|
case 0x1F:
|
instruction=decodeSrs(word);
|
instruction=decodeSrs(word);
|
break;
|
break;
|
case 0x1E:
|
case 0x1E:
|
instruction=decodeSru(word);
|
instruction=decodeSru(word);
|
break;
|
break;
|
case 0x11:
|
case 0x11:
|
instruction=decodeSub(word);
|
instruction=decodeSub(word);
|
break;
|
break;
|
case 0x0C:
|
case 0x0C:
|
instruction=decodeSw(word);
|
instruction=decodeSw(word);
|
break;
|
break;
|
case 0x1A:
|
case 0x1A:
|
instruction=decodeXor(word);
|
instruction=decodeXor(word);
|
break;
|
break;
|
default:
|
default:
|
if((opcode>>4)==0x03) instruction=decodeCjmpxx(word);
|
if((opcode>>4)==0x03) instruction=decodeCjmpxx(word);
|
|
else if((opcode>>3)==0x05) instruction=decodeLcs(word);
|
else instruction=decodeWord(word);
|
else instruction=decodeWord(word);
|
}
|
}
|
|
|
auto size=instruction.size();
|
auto size=instruction.size();
|
std::size_t padding=0;
|
std::size_t padding=0;
|
if(size<32) padding=32-size;
|
if(size<32) padding=32-size;
|
|
|
_os<<'\t'<<instruction<<std::string(padding,' ')<<"// ";
|
_os<<'\t'<<instruction<<std::string(padding,' ')<<"// ";
|
_os<<hex(offset)<<": "<<hex(word);
|
_os<<hex(offset)<<": "<<hex(word);
|
if(lcValid) _os<<' '<<hex(lcOperand);
|
if(lcValid) _os<<' '<<hex(lcOperand);
|
_os<<std::endl;
|
_os<<std::endl;
|
}
|
}
|
}
|
}
|
|
|
bool Disassembler::getWord(Word &w) {
|
bool Disassembler::getWord(Word &w) {
|
if(_fmt==Bin) {
|
if(_fmt==Bin) {
|
char buf[sizeof(Word)] {}; // zero-initialize
|
char buf[sizeof(Word)] {}; // zero-initialize
|
_is.read(buf,sizeof(Word));
|
_is.read(buf,sizeof(Word));
|
|
|
auto n=static_cast<std::size_t>(_is.gcount());
|
auto n=static_cast<std::size_t>(_is.gcount());
|
if(n==0) return false;
|
if(n==0) return false;
|
if(n<sizeof(Word)) std::cerr<<"Warning: last word is truncated"<<std::endl;
|
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)|
|
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]);
|
(static_cast<unsigned char>(buf[1])<<8)|static_cast<unsigned char>(buf[0]);
|
}
|
}
|
else {
|
else {
|
try {
|
try {
|
std::string line;
|
std::string line;
|
if(!std::getline(_is,line)) return false;
|
if(!std::getline(_is,line)) return false;
|
_lineNumber++;
|
_lineNumber++;
|
|
|
if(_fmt==Textio) w=std::stoul(line,nullptr,2);
|
if(_fmt==Textio) w=std::stoul(line,nullptr,2);
|
else if(_fmt==Dec) w=std::stoul(line,nullptr,10);
|
else if(_fmt==Dec) w=std::stoul(line,nullptr,10);
|
else if(_fmt==Hex) w=std::stoul(line,nullptr,16);
|
else if(_fmt==Hex) w=std::stoul(line,nullptr,16);
|
else return false;
|
else return false;
|
}
|
}
|
catch(std::exception &) {
|
catch(std::exception &) {
|
throw std::runtime_error("Bad literal at line "+std::to_string(_lineNumber));
|
throw std::runtime_error("Bad literal at line "+std::to_string(_lineNumber));
|
}
|
}
|
}
|
}
|
_pos+=sizeof(Word);
|
_pos+=sizeof(Word);
|
return true;
|
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) {
|
Disassembler::Operand Disassembler::decodeRd1Operand(Word w) {
|
int value=(w>>8)&0xFF;
|
int value=(w>>8)&0xFF;
|
if(w&0x02000000) return Operand(Operand::Register,value);
|
if(w&0x02000000) return Operand(Operand::Register,value);
|
else {
|
else {
|
if(value>127) value-=256;
|
if(value>127) value-=256;
|
return Operand(Operand::Direct,value);
|
return Operand(Operand::Direct,value);
|
}
|
}
|
}
|
}
|
|
|
Disassembler::Operand Disassembler::decodeRd2Operand(Word w) {
|
Disassembler::Operand Disassembler::decodeRd2Operand(Word w) {
|
int value=w&0xFF;
|
int value=w&0xFF;
|
if(w&0x01000000) return Operand(Operand::Register,value);
|
if(w&0x01000000) return Operand(Operand::Register,value);
|
else {
|
else {
|
if(value>127) value-=256;
|
if(value>127) value-=256;
|
return Operand(Operand::Direct,value);
|
return Operand(Operand::Direct,value);
|
}
|
}
|
}
|
}
|
|
|
Disassembler::Operand Disassembler::decodeDstOperand(Word w) {
|
Disassembler::Operand Disassembler::decodeDstOperand(Word w) {
|
int value=(w>>16)&0xFF;
|
int value=(w>>16)&0xFF;
|
return Operand(Operand::Register,value);
|
return Operand(Operand::Register,value);
|
}
|
}
|
|
|
std::string Disassembler::decodeSimpleInstruction(const std::string &op,Word w) {
|
std::string Disassembler::decodeSimpleInstruction(const std::string &op,Word w) {
|
std::ostringstream oss;
|
std::ostringstream oss;
|
auto dst=decodeDstOperand(w);
|
auto dst=decodeDstOperand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
oss<<op<<' '<<dst.str()<<", "<<rd1.str()<<", "<<rd2.str();
|
oss<<op<<' '<<str(dst)<<", "<<str(rd1)<<", "<<str(rd2);
|
return oss.str();
|
return oss.str();
|
}
|
}
|
|
|
std::string Disassembler::decodeAdd(Word w) {
|
std::string Disassembler::decodeAdd(Word w) {
|
std::ostringstream oss;
|
std::ostringstream oss;
|
|
|
auto dst=decodeDstOperand(w);
|
auto dst=decodeDstOperand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
|
|
if(rd2.type()==Operand::Direct&&rd2.value()==0)
|
if(rd2.type()==Operand::Direct&&rd2.value()==0&&_preferAliases)
|
oss<<"mov "<<dst.str()<<", "<<rd1.str();
|
oss<<"mov "<<str(dst)<<", "<<str(rd1);
|
else
|
else
|
oss<<"add "<<dst.str()<<", "<<rd1.str()<<", "<<rd2.str();
|
oss<<"add "<<str(dst)<<", "<<str(rd1)<<", "<<str(rd2);
|
|
|
return oss.str();
|
return oss.str();
|
}
|
}
|
|
|
std::string Disassembler::decodeAnd(Word w) {
|
std::string Disassembler::decodeAnd(Word w) {
|
return decodeSimpleInstruction("and",w);
|
return decodeSimpleInstruction("and",w);
|
}
|
}
|
|
|
std::string Disassembler::decodeCall(Word w) {
|
std::string Disassembler::decodeCall(Word w) {
|
auto dst=decodeDstOperand(w);
|
auto dst=decodeDstOperand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
|
|
if(dst.value()!=0xFE) return decodeWord(w);
|
if(dst.value()!=0xFE) return decodeWord(w);
|
if(rd1.type()!=Operand::Register) return decodeWord(w);
|
if(rd1.type()!=Operand::Register) return decodeWord(w);
|
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
|
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
|
|
|
return "call "+rd1.str();
|
return "call "+str(rd1);
|
}
|
}
|
|
|
std::string Disassembler::decodeCjmpxx(Word w) {
|
std::string Disassembler::decodeCjmpxx(Word w) {
|
auto jumpType=(w>>26)&0x0F;
|
auto jumpType=(w>>26)&0x0F;
|
std::string op;
|
std::string op;
|
|
|
switch(jumpType) {
|
switch(jumpType) {
|
case 0x8:
|
case 0x8:
|
op="cjmpe";
|
op="cjmpe";
|
break;
|
break;
|
case 0x4:
|
case 0x4:
|
op="cjmpne";
|
op="cjmpne";
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
op="cjmpug";
|
op="cjmpug";
|
break;
|
break;
|
case 0xA:
|
case 0xA:
|
op="cjmpuge";
|
op="cjmpuge";
|
break;
|
break;
|
case 0x1:
|
case 0x1:
|
op="cjmpsg";
|
op="cjmpsg";
|
break;
|
break;
|
case 0x9:
|
case 0x9:
|
op="cjmpsge";
|
op="cjmpsge";
|
break;
|
break;
|
default:
|
default:
|
return decodeWord(w);
|
return decodeWord(w);
|
}
|
}
|
|
|
return decodeSimpleInstruction(op,w);
|
return decodeSimpleInstruction(op,w);
|
}
|
}
|
|
|
std::string Disassembler::decodeDivs(Word w) {
|
std::string Disassembler::decodeDivs(Word w) {
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w);
|
if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w);
|
return decodeSimpleInstruction("divs",w);
|
return decodeSimpleInstruction("divs",w);
|
}
|
}
|
|
|
std::string Disassembler::decodeDivu(Word w) {
|
std::string Disassembler::decodeDivu(Word w) {
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w);
|
if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w);
|
return decodeSimpleInstruction("divu",w);
|
return decodeSimpleInstruction("divu",w);
|
}
|
}
|
|
|
std::string Disassembler::decodeHlt(Word w) {
|
std::string Disassembler::decodeHlt(Word w) {
|
if(w!=0x08000000) return decodeWord(w);
|
if(w!=0x08000000) return decodeWord(w);
|
return "hlt";
|
return "hlt";
|
}
|
}
|
|
|
std::string Disassembler::decodeJmp(Word w) {
|
std::string Disassembler::decodeJmp(Word w) {
|
auto dst=decodeDstOperand(w);
|
auto dst=decodeDstOperand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
|
|
if(dst.value()!=0) return decodeWord(w);
|
if(dst.value()!=0) return decodeWord(w);
|
if(rd1.type()!=Operand::Register) return decodeWord(w);
|
if(rd1.type()!=Operand::Register) return decodeWord(w);
|
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
|
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
|
|
|
if(rd1.value()==253) return "iret";
|
if(rd1.value()==253&&_preferAliases) return "iret";
|
if(rd1.value()==254) return "ret";
|
if(rd1.value()==254&&_preferAliases) return "ret";
|
return "jmp "+rd1.str();
|
return "jmp "+str(rd1);
|
}
|
}
|
|
|
std::string Disassembler::decodeLc(Word w,bool &valid,Word &operand) {
|
std::string Disassembler::decodeLc(Word w,bool &valid,Word &operand) {
|
auto dst=decodeDstOperand(w);
|
auto dst=decodeDstOperand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
|
|
valid=false;
|
valid=false;
|
|
|
if(rd1.type()!=Operand::Direct||rd1.value()!=0) return decodeWord(w);
|
if(rd1.type()!=Operand::Direct||rd1.value()!=0) return decodeWord(w);
|
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
|
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
|
|
|
bool b=getWord(operand);
|
bool b=getWord(operand);
|
if(!b) return decodeWord(w);
|
if(!b) return decodeWord(w);
|
|
|
valid=true;
|
valid=true;
|
return "lc "+dst.str()+", 0x"+hex(operand);
|
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::string Disassembler::decodeLsb(Word w) {
|
std::ostringstream oss;
|
std::ostringstream oss;
|
|
|
auto dst=decodeDstOperand(w);
|
auto dst=decodeDstOperand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
|
|
if(rd1.type()!=Operand::Register) return decodeWord(w);
|
if(rd1.type()!=Operand::Register) return decodeWord(w);
|
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
|
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
|
|
|
return "lsb "+dst.str()+", "+rd1.str();
|
return "lsb "+str(dst)+", "+str(rd1);
|
}
|
}
|
|
|
std::string Disassembler::decodeLub(Word w) {
|
std::string Disassembler::decodeLub(Word w) {
|
std::ostringstream oss;
|
std::ostringstream oss;
|
|
|
auto dst=decodeDstOperand(w);
|
auto dst=decodeDstOperand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
|
|
if(rd1.type()!=Operand::Register) return decodeWord(w);
|
if(rd1.type()!=Operand::Register) return decodeWord(w);
|
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
|
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
|
|
|
return "lub "+dst.str()+", "+rd1.str();
|
return "lub "+str(dst)+", "+str(rd1);
|
}
|
}
|
|
|
std::string Disassembler::decodeLw(Word w) {
|
std::string Disassembler::decodeLw(Word w) {
|
std::ostringstream oss;
|
std::ostringstream oss;
|
|
|
auto dst=decodeDstOperand(w);
|
auto dst=decodeDstOperand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
|
|
if(rd1.type()!=Operand::Register) return decodeWord(w);
|
if(rd1.type()!=Operand::Register) return decodeWord(w);
|
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
|
if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
|
|
|
return "lw "+dst.str()+", "+rd1.str();
|
return "lw "+str(dst)+", "+str(rd1);
|
}
|
}
|
|
|
std::string Disassembler::decodeMods(Word w) {
|
std::string Disassembler::decodeMods(Word w) {
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w);
|
if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w);
|
return decodeSimpleInstruction("mods",w);
|
return decodeSimpleInstruction("mods",w);
|
}
|
}
|
|
|
std::string Disassembler::decodeModu(Word w) {
|
std::string Disassembler::decodeModu(Word w) {
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w);
|
if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w);
|
return decodeSimpleInstruction("modu",w);
|
return decodeSimpleInstruction("modu",w);
|
}
|
}
|
|
|
std::string Disassembler::decodeMul(Word w) {
|
std::string Disassembler::decodeMul(Word w) {
|
return decodeSimpleInstruction("mul",w);
|
return decodeSimpleInstruction("mul",w);
|
}
|
}
|
|
|
std::string Disassembler::decodeNop(Word w) {
|
std::string Disassembler::decodeNop(Word w) {
|
if(w!=0) return decodeWord(w);
|
if(w!=0) return decodeWord(w);
|
return "nop";
|
return "nop";
|
}
|
}
|
|
|
std::string Disassembler::decodeOr(Word w) {
|
std::string Disassembler::decodeOr(Word w) {
|
return decodeSimpleInstruction("or",w);
|
return decodeSimpleInstruction("or",w);
|
}
|
}
|
|
|
std::string Disassembler::decodeSb(Word w) {
|
std::string Disassembler::decodeSb(Word w) {
|
std::ostringstream oss;
|
std::ostringstream oss;
|
|
|
auto dst=decodeDstOperand(w);
|
auto dst=decodeDstOperand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
|
|
if(dst.value()!=0) return decodeWord(w);
|
if(dst.value()!=0) return decodeWord(w);
|
if(rd1.type()!=Operand::Register) return decodeWord(w);
|
if(rd1.type()!=Operand::Register) return decodeWord(w);
|
|
|
return "sb "+rd1.str()+", "+rd2.str();
|
return "sb "+str(rd1)+", "+str(rd2);
|
}
|
}
|
|
|
std::string Disassembler::decodeSl(Word w) {
|
std::string Disassembler::decodeSl(Word w) {
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w);
|
if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w);
|
return decodeSimpleInstruction("sl",w);
|
return decodeSimpleInstruction("sl",w);
|
}
|
}
|
|
|
std::string Disassembler::decodeSrs(Word w) {
|
std::string Disassembler::decodeSrs(Word w) {
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w);
|
if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w);
|
return decodeSimpleInstruction("srs",w);
|
return decodeSimpleInstruction("srs",w);
|
}
|
}
|
|
|
std::string Disassembler::decodeSru(Word w) {
|
std::string Disassembler::decodeSru(Word w) {
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w);
|
if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w);
|
return decodeSimpleInstruction("sru",w);
|
return decodeSimpleInstruction("sru",w);
|
}
|
}
|
|
|
std::string Disassembler::decodeSub(Word w) {
|
std::string Disassembler::decodeSub(Word w) {
|
return decodeSimpleInstruction("sub",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::string Disassembler::decodeSw(Word w) {
|
std::ostringstream oss;
|
std::ostringstream oss;
|
|
|
auto dst=decodeDstOperand(w);
|
auto dst=decodeDstOperand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
|
|
if(dst.value()!=0) return decodeWord(w);
|
if(dst.value()!=0) return decodeWord(w);
|
if(rd1.type()!=Operand::Register) return decodeWord(w);
|
if(rd1.type()!=Operand::Register) return decodeWord(w);
|
|
|
return "sw "+rd1.str()+", "+rd2.str();
|
return "sw "+str(rd1)+", "+str(rd2);
|
}
|
}
|
|
|
std::string Disassembler::decodeXor(Word w) {
|
std::string Disassembler::decodeXor(Word w) {
|
std::ostringstream oss;
|
std::ostringstream oss;
|
|
|
auto dst=decodeDstOperand(w);
|
auto dst=decodeDstOperand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd1=decodeRd1Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
auto rd2=decodeRd2Operand(w);
|
|
|
if(rd2.type()==Operand::Direct&&rd2.value()==-1)
|
if(rd2.type()==Operand::Direct&&rd2.value()==-1&&_preferAliases)
|
oss<<"not "<<dst.str()<<", "<<rd1.str();
|
oss<<"not "<<str(dst)<<", "<<str(rd1);
|
else
|
else
|
oss<<"xor "<<dst.str()<<", "<<rd1.str()<<", "<<rd2.str();
|
oss<<"xor "<<str(dst)<<", "<<str(rd1)<<", "<<str(rd2);
|
|
|
return oss.str();
|
return oss.str();
|
}
|
}
|
|
|
std::string Disassembler::decodeWord(Word w) {
|
std::string Disassembler::decodeWord(Word w) {
|
return ".word 0x"+hex(w);
|
return ".word 0x"+hex(w);
|
}
|
}
|
|
|