164 lines
4.5 KiB
C++
164 lines
4.5 KiB
C++
#ifndef DISASSEMBLER_H
|
|
#define DISASSEMBLER_H
|
|
|
|
#include "MemoryUsageMap.h"
|
|
#include "util.h"
|
|
#include "JumpLineManager.h"
|
|
#include "opcodes.h"
|
|
#include "attributedmemory.h"
|
|
|
|
#include <QByteArray>
|
|
#include <QStringList>
|
|
#include <QHash>
|
|
#include <QDebug>
|
|
#include <QStack>
|
|
|
|
|
|
class AddressStack
|
|
{
|
|
public:
|
|
AddressStack() { }
|
|
|
|
bool push(quint16 address, bool force = false) {
|
|
if (force || (!m_stack.contains(address)))
|
|
{
|
|
// qDebug() << " PUSH: " << uint16ToHex(address);
|
|
m_stack.push(address);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool isEmpty() { return m_stack.isEmpty(); }
|
|
quint16 pop() { return m_stack.pop(); }
|
|
|
|
private:
|
|
QStack<quint16> m_stack;
|
|
};
|
|
|
|
|
|
class DisassembledItem {
|
|
public:
|
|
DisassembledItem() { init(); }
|
|
|
|
DisassembledItem(quint8 opcode);
|
|
|
|
bool operator<(const DisassembledItem &other) const { return (address() < other.address()); }
|
|
|
|
void setOpcode(quint8 opcode) { m_opcode = opcode; }
|
|
void setAddress(quint16 add) { m_address = add; }
|
|
void setDisassembledString(QString ds) { m_disassembly_text = ds; }
|
|
void setHexValues(QByteArray hv) { m_hexvalues = hv; }
|
|
void setHexString(QString hs) { m_hexstring = hs; }
|
|
void setTargetAddress(quint16 ta) { m_unknown_ta = false; m_target_address = ta; }
|
|
void setRawArgument(quint16 arg) { m_has_arg = true; m_raw_arg = arg; }
|
|
void setCanNotFollow(bool canNotFollow) { m_canNotFollow = canNotFollow; }
|
|
void setIsInvalidOp(bool isInvalid) { m_isInvalidOp = isInvalid; }
|
|
|
|
quint8 opcode() const { return m_opcode; }
|
|
quint16 address() const { return m_address; }
|
|
QString disassembledString();
|
|
QString rawDisassembledString() const { return m_disassembly_text; }
|
|
QString hexAddress() const { return uint16ToHex(m_address); }
|
|
QByteArray hexValues() const { return m_hexvalues; }
|
|
QString hexString() const { return m_hexstring; }
|
|
|
|
bool isBranch() const { return OpCodes::isBranch(m_opcode); }
|
|
bool isJump() const { return OpCodes::isJump(m_opcode); }
|
|
bool isJsr() const { return OpCodes::isJsr(m_opcode); }
|
|
bool isReturn() { return OpCodes::isReturn(m_opcode); }
|
|
bool isBreak() { return OpCodes::isBreak(m_opcode); }
|
|
bool isInvalidOp() { return m_isInvalidOp; }
|
|
|
|
bool canNotFollow() { return m_canNotFollow; }
|
|
|
|
bool stopsProcessing()
|
|
{
|
|
return isBreak() || isInvalidOp() || isReturn() || canNotFollow();
|
|
}
|
|
|
|
quint16 nextContiguousAddress() { return m_nextContiguousAddress; }
|
|
quint16 nextFlowAddress() { return m_nextFlowAddress; }
|
|
|
|
void setNextContiguousAddress(quint16 addr) { m_nextContiguousAddress = addr; }
|
|
void setNextFlowAddress(quint16 addr) { m_nextFlowAddress = addr; }
|
|
|
|
quint16 targetAddress() const { return m_target_address; }
|
|
bool hasArg() const { return m_has_arg; }
|
|
|
|
quint8 arg8() { return m_raw_arg % 256; }
|
|
QString arg8Str() { return uint8ToHex(arg8()); }
|
|
|
|
quint16 arg16() { return m_raw_arg; }
|
|
QString arg16Str() { return uint16ToHex(arg16()); }
|
|
|
|
private:
|
|
void init();
|
|
|
|
quint8 m_opcode;
|
|
|
|
quint16 m_address;
|
|
quint16 m_nextContiguousAddress;
|
|
quint16 m_nextFlowAddress;
|
|
quint16 m_target_address;
|
|
|
|
QByteArray m_hexvalues;
|
|
QString m_disassembly_text;
|
|
QString m_hexstring;
|
|
|
|
bool m_unknown_ta;
|
|
quint16 m_raw_arg;
|
|
bool m_has_arg;
|
|
bool m_isInvalidOp;
|
|
bool m_canNotFollow;
|
|
};
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
class Disassembler
|
|
{
|
|
public:
|
|
Disassembler(AttributedMemory &mem);
|
|
|
|
enum ProcessorType {
|
|
MOS6502,
|
|
MOS65C02
|
|
};
|
|
|
|
|
|
QList<DisassembledItem> disassemble(quint16 from,
|
|
quint16 to,
|
|
QList<quint16> entryPoints,
|
|
bool processRecursively = true);
|
|
|
|
MemoryUsageMap *memoryUsageMap() { return &m_memusagemap; }
|
|
|
|
void setUnknownToData(quint16 from, quint16 to);
|
|
|
|
|
|
JumpLines getJumpLines() const { return m_jumplines; }
|
|
|
|
private:
|
|
|
|
bool disassembleOp(quint16 address,
|
|
DisassembledItem &retval,
|
|
MemoryUsageMap *memuse = Q_NULLPTR);
|
|
|
|
quint16 m_from;
|
|
quint16 m_to;
|
|
|
|
AttributedMemory *m_mem;
|
|
|
|
AddressStack m_stack;
|
|
|
|
MemoryUsageMap m_memusagemap;
|
|
|
|
JumpLineManager m_jlm;
|
|
|
|
JumpLines m_jumplines;
|
|
|
|
};
|
|
|
|
#endif // DISASSEMBLER_H
|