Added memory role detection in disassembler for opcodes and operands

This commit is contained in:
mlong 2021-02-01 20:19:16 -06:00
parent 9ab500ede5
commit 7f4ca94e9a
17 changed files with 698 additions and 535 deletions

View File

@ -46,6 +46,7 @@ SOURCES += \
src/memory/memorycell.cpp \
src/memory/memrole.cpp \
src/memory/roles/role_asm_opcode.cpp \
src/memory/roles/role_asm_operand.cpp \
src/ui/startupdialog.cpp \
src/ui/viewers/intbasicfileviewer.cxx \
src/ui/widgets/notesdialog.cpp \
@ -100,6 +101,7 @@ HEADERS += \
src/memory/memorycell.h \
src/memory/memrole.h \
src/memory/roles/role_asm_opcode.h \
src/memory/roles/role_asm_operand.h \
src/ui/startupdialog.h \
src/ui/viewers/intbasicfileviewer.h \
src/ui/widgets/notesdialog.h \

View File

@ -1,28 +1,27 @@
#include "opcodes.h"
#include "disassembler.h"
#include "role_asm_opcode.h"
#include "role_asm_operand.h"
#include "util.h"
#include <QByteArray>
#include <QDebug>
#include <QList>
#include <math.h>
Disassembler::Disassembler(QByteArray memimage)
Disassembler::Disassembler(AttributedMemory &mem)
{
m_memimage = memimage;
m_mem = &mem;
m_memusagemap.clearData();
}
QList<DisassembledItem> Disassembler::disassemble(quint16 from, quint16 to,
QList<quint16> entryPoints,
bool processRecursively) {
m_from = from;
m_to = to;
QList<DisassembledItem> retval;
qDebug() << "\n\n*****************\n\nDisassemble: From"<<uint16ToHex(from)<<"to"<<uint16ToHex(to);
MemoryUsageMap memUse;
@ -36,8 +35,6 @@ QList<DisassembledItem> Disassembler::disassemble(quint16 from, quint16 to,
while (!stopping)
{
// quint8 opcode = m_memimage[next];
// qDebug() << "Opcode: " << uint8ToHex(opcode);
DisassembledItem item;
bool ok = false;
@ -107,13 +104,14 @@ QList<DisassembledItem> Disassembler::disassemble(quint16 from, quint16 to,
if (processRecursively)
{
m_jumplines = m_jlm.buildJumpLines();
qDebug() << "Num Channels: " << m_jlm.getNumJumpLineChannels();
m_jumplines = m_jlm.buildJumpLines();
qDebug() << "Num Channels: " << m_jlm.getNumJumpLineChannels();
}
return retval;
}
bool Disassembler::disassembleOp(quint16 address, DisassembledItem &retval, MemoryUsageMap *memuse)
{
@ -122,11 +120,25 @@ bool Disassembler::disassembleOp(quint16 address, DisassembledItem &retval, Memo
if ((*memuse)[address].testFlag(Operation)) return false;
}
quint8 opcode = m_memimage[address];
AssyInstruction op = OpCodes::getAssyInstruction(opcode);
retval.setInstruction(op);
quint8 opcode = m_mem->at(address);
if (opcode == 0x6C || opcode == 0x7c) // Indirect jumps
retval.setOpcode(opcode);
if (!m_mem->hasRoleAt(address,RoleAsmOpcode::RoleID))
{
auto opRole = new RoleAsmOpcode();
if (!m_mem->setRoleAt(address,opRole))
{
qWarning("Cannot set role %s at address %s for opcode %s",
qPrintable(opRole->name()),
qPrintable(uint16ToHex(address)),
qPrintable(uint8ToHex(opcode)));
delete opRole;
}
}
if (OpCodes::isIndirectJump(opcode)) // Indirect jumps
{
m_jlm.addJump(address,address,IsUnknownJump,m_from,m_to);
retval.setCanNotFollow(true);
@ -139,136 +151,164 @@ bool Disassembler::disassembleOp(quint16 address, DisassembledItem &retval, Memo
// Prepare Op Code arguments
for (int idx = 1; idx < op.numArgs()+1; idx++) {
quint8 val = m_memimage[address+idx];
auto numArgs = OpCodes::numArgs(opcode);
for (int idx = 1; idx < numArgs+1; idx++) {
qDebug() << "Opcode at " << uint16ToHex(idx + address);
auto oprndRole = new RoleAsmOperand();
if (numArgs == 1)
{
oprndRole->setOperandType(RoleAsmOperand::Type::Byte);
}
else {
if (idx == 1)
{
oprndRole->setOperandType(RoleAsmOperand::Type::WordLo);
}
else // idx == 2
{
oprndRole->setOperandType(RoleAsmOperand::Type::WordHi);
}
}
if (!m_mem->setRoleAt(address+idx,oprndRole))
{
qWarning(">> Cannot set role %s at address %s",
qPrintable(oprndRole->name()),
qPrintable(uint16ToHex(address)));
delete oprndRole;
}
quint8 val = m_mem->at(address+idx);
hexValues.append(val);
}
if (memuse)
{
(*memuse)[address].setFlag(Operation);
for (int idx = 1; idx < op.numArgs()+1; idx++)
for (int idx = 1; idx < OpCodes::numArgs(opcode)+1; idx++)
{
(*memuse)[address+idx].setFlag(OperationArg);
}
}
quint16 argval = 0;
if (op.numArgs() == 1)
if (numArgs == 1)
{
argval = (quint8) hexValues[1];
else if (op.numArgs() == 2)
}
else if (numArgs == 2)
{
argval = makeWord(hexValues[1],hexValues[2]);
}
for (int idx = 0; idx < hexValues.length(); idx++) {
hexValueString.append(QString("%1 ").arg((quint8) hexValues[idx],2,16,QChar('0')));
hexValueString.append(QString("%1 ").arg(uint8ToHex(hexValues[idx])));
}
retval.setNextContiguousAddress(address+1+op.numArgs());
retval.setNextFlowAddress(address+1+op.numArgs());
retval.setNextContiguousAddress(address+1+numArgs);
retval.setNextFlowAddress(address+1+numArgs);
QString mnemonic = OpCodes::mnemonic(opcode);
// Disassemble instruction
switch (op.addressMode()) {
case AM_InvalidOp: {
disassemblyLine = op.mnemonic();
retval.setIsInvalidOp(true);
break;
}
case AM_Absolute:{
disassemblyLine = QString("%1 _ARG16_").arg(op.mnemonic());
retval.setRawArgument(argval);
break;
}
case AM_AbsoluteIndexedIndirect:{
disassemblyLine = QString("%1 (_ARG16_,x)").arg(op.mnemonic());
retval.setRawArgument(argval);
break;
}
case AM_AbsoluteIndexedWithX:{
disassemblyLine = QString("%1 _ARG16_,x").arg(op.mnemonic());
retval.setRawArgument(argval);
break;
}
case AM_AbsoluteIndexedWithY:{
disassemblyLine = QString("%1 _ARG16_,y").arg(op.mnemonic());
retval.setRawArgument(argval);
break;
}
case AM_AbsoluteIndirect:{
disassemblyLine = QString("%1 (_ARG16_)").arg(op.mnemonic());
retval.setRawArgument(argval);
break;
}
case AM_Immediate:{
disassemblyLine = QString("%1 #%2").arg(op.mnemonic()).arg((quint8) hexValues[1],2,16,QChar('0')).toUpper();
retval.setRawArgument(argval);
break;
}
case AM_Implied:{
disassemblyLine = op.mnemonic();
break;
}
case AM_Accumulator:{
disassemblyLine = op.mnemonic();
break;
}
case AM_ProgramCounterRelative:{
qint8 offset = (qint8) hexValues[1];
quint16 offsetAddress = address+2+offset;
switch (OpCodes::addressMode(opcode)) {
case AM_InvalidOp: {
disassemblyLine = OpCodes::mnemonic(opcode);
retval.setIsInvalidOp(true);
break;
}
case AM_Absolute:{
disassemblyLine = QString("%1 _ARG16_").arg(mnemonic);
retval.setRawArgument(argval);
break;
}
case AM_AbsoluteIndexedIndirect:{
disassemblyLine = QString("%1 (_ARG16_,x)").arg(mnemonic);
retval.setRawArgument(argval);
break;
}
case AM_AbsoluteIndexedWithX:{
disassemblyLine = QString("%1 _ARG16_,x").arg(mnemonic);
retval.setRawArgument(argval);
break;
}
case AM_AbsoluteIndexedWithY:{
disassemblyLine = QString("%1 _ARG16_,y").arg(mnemonic);
retval.setRawArgument(argval);
break;
}
case AM_AbsoluteIndirect:{
disassemblyLine = QString("%1 (_ARG16_)").arg(mnemonic);
retval.setRawArgument(argval);
break;
}
case AM_Immediate:{
disassemblyLine = QString("%1 #%2").arg(mnemonic).arg((quint8) hexValues[1],2,16,QChar('0')).toUpper();
retval.setRawArgument(argval);
break;
}
case AM_Implied:{
disassemblyLine = mnemonic;
break;
}
case AM_Accumulator:{
disassemblyLine = mnemonic;
break;
}
case AM_ProgramCounterRelative:{
qint8 offset = (qint8) hexValues[1];
quint16 offsetAddress = address+2+offset;
retval.setTargetAddress(offsetAddress);
if (opcode == 0x80) // BRA
m_jlm.addJump(address,offsetAddress,IsBRA,m_from,m_to);
else
m_jlm.addJump(address,offsetAddress,IsBranch,m_from,m_to);
retval.setTargetAddress(offsetAddress);
if (opcode == 0x80) // BRA
m_jlm.addJump(address,offsetAddress,IsBRA,m_from,m_to);
else
m_jlm.addJump(address,offsetAddress,IsBranch,m_from,m_to);
disassemblyLine = QString("%1 _ARG16_ {%2%3}").arg(op.mnemonic())
.arg((offset<0)?"-":"+")
.arg(abs(offset));
retval.setRawArgument(offsetAddress);
break;
}
case AM_ZeroPage:{
disassemblyLine = QString("%1 _ARG8_").arg(op.mnemonic());
retval.setRawArgument(argval);
break;
}
case AM_ZeroPageIndirectIndexedWithY:{
disassemblyLine = QString("%1 (_ARG8_),Y").arg(op.mnemonic());
retval.setRawArgument(argval);
break;
}
case AM_ZeroPageIndexedIndirect:{
disassemblyLine = QString("%1 (_ARG8_,x)").arg(op.mnemonic());
retval.setRawArgument(argval);
break;
}
case AM_ZeroPageIndexedWithX:{
disassemblyLine = QString("%1 _ARG8_,x").arg(op.mnemonic());
retval.setRawArgument(argval);
break;
}
case AM_ZeroPageIndexedWithY:{
disassemblyLine = QString("%1 _ARG8_,y").arg(op.mnemonic());
retval.setRawArgument(argval);
break;
}
case AM_ZeroPageIndirect:{
disassemblyLine = QString("%1 (_ARG8_)").arg(op.mnemonic());
retval.setRawArgument(argval);
break;
}
default:{
disassemblyLine = op.mnemonic();
retval.setIsInvalidOp(true);
qDebug() << "Unhandled Address Mode: " << op.addressMode();
break;
}
disassemblyLine = QString("%1 _ARG16_ {%2%3}").arg(mnemonic)
.arg((offset<0)?"-":"+")
.arg(abs(offset));
retval.setRawArgument(offsetAddress);
break;
}
case AM_ZeroPage:{
disassemblyLine = QString("%1 _ARG8_").arg(mnemonic);
retval.setRawArgument(argval);
break;
}
case AM_ZeroPageIndirectIndexedWithY:{
disassemblyLine = QString("%1 (_ARG8_),Y").arg(mnemonic);
retval.setRawArgument(argval);
break;
}
case AM_ZeroPageIndexedIndirect:{
disassemblyLine = QString("%1 (_ARG8_,x)").arg(mnemonic);
retval.setRawArgument(argval);
break;
}
case AM_ZeroPageIndexedWithX:{
disassemblyLine = QString("%1 _ARG8_,x").arg(mnemonic);
retval.setRawArgument(argval);
break;
}
case AM_ZeroPageIndexedWithY:{
disassemblyLine = QString("%1 _ARG8_,y").arg(mnemonic);
retval.setRawArgument(argval);
break;
}
case AM_ZeroPageIndirect:{
disassemblyLine = QString("%1 (_ARG8_)").arg(mnemonic);
retval.setRawArgument(argval);
break;
}
default:{
disassemblyLine = mnemonic;
retval.setIsInvalidOp(true);
qDebug() << "Unhandled Address Mode: " << mnemonic;
break;
}
}
if (opcode == 0x20 || opcode == 0x4c) {
if (opcode == 0x20 || opcode == 0x4c) // JSR / JMP
{
retval.setTargetAddress(makeWord(hexValues[1],hexValues[2]));
if (opcode == 0x4c) // JMP
@ -294,6 +334,7 @@ bool Disassembler::disassembleOp(quint16 address, DisassembledItem &retval, Memo
}
void Disassembler::setUnknownToData(quint16 from, quint16 to)
{
for (int idx = from; idx <= to; idx++)
@ -305,28 +346,14 @@ void Disassembler::setUnknownToData(quint16 from, quint16 to)
}
}
DisassembledItem::DisassembledItem(AssyInstruction instr) {
m_canNotFollow = false;
setInstruction(instr);
}
//DisassembledItem::DisassembledItem(AssyInstruction instr) {
// m_canNotFollow = false;
// setInstruction(instr);
//}
void DisassembledItem::setInstruction(AssyInstruction instr) {
m_instruction = instr;
// qDebug() << "Set instruction: " << uint8ToHex(instr.opcode());
// qDebug() << " Copied instr:" << m_instruction.debugStr();
if (instr.opcode() == 0x20) { m_is_jsr = true; }
if (instr.opcode() == 0x10) { m_is_branch = true; } // BPL
if (instr.opcode() == 0x30) { m_is_branch = true; } // BMI
if (instr.opcode() == 0x50) { m_is_branch = true; } // BVC
if (instr.opcode() == 0x70) { m_is_branch = true; } // BVS
if (instr.opcode() == 0x90) { m_is_branch = true; } // BCC
if (instr.opcode() == 0xB0) { m_is_branch = true; } // BCS
if (instr.opcode() == 0xD0) { m_is_branch = true; } // BNE
if (instr.opcode() == 0xF0) { m_is_branch = true; } // BEQ
if (instr.opcode() == 0x80) { m_is_jump = true; } // BRA
if (instr.opcode() == 0x4C) { m_is_jump = true; } // JMP a
if (instr.opcode() == 0x6C) { m_is_jump = true; } // JMP (a)
if (instr.opcode() == 0x7C) { m_is_jump = true; } // JMP (a,x)
DisassembledItem::DisassembledItem(quint8 opcode) {
m_canNotFollow = false;
m_opcode = opcode;
}
QString DisassembledItem::disassembledString() {
@ -345,11 +372,9 @@ void DisassembledItem::init() {
m_address = m_target_address = 0;
m_nextContiguousAddress = 0;
m_nextFlowAddress = 0;
m_is_jump = m_is_branch = m_is_jsr = false;
m_unknown_ta = true;
m_raw_arg = 0;
m_has_arg = false;
m_canNotFollow = false;
m_isInvalidOp = false;
}

View File

@ -5,6 +5,7 @@
#include "util.h"
#include "JumpLineManager.h"
#include "opcodes.h"
#include "attributedmemory.h"
#include <QByteArray>
#include <QStringList>
@ -13,26 +14,6 @@
#include <QStack>
//enum AddressMode {
// AM_InvalidOp,
// AM_Absolute, // a
// AM_AbsoluteIndexedIndirect, // (a,x)
// AM_AbsoluteIndexedWithX, // a,x
// AM_AbsoluteIndexedWithY, // a,y
// AM_AbsoluteIndirect, // (a)
// AM_Immediate, // #
// AM_Implied, // i
// AM_Accumulator, // A
// AM_ProgramCounterRelative, // r
// AM_ZeroPage, // zp
// AM_ZeroPageIndexedIndirect, // (zp,x)
// AM_ZeroPageIndexedWithX, // zp,x
// AM_ZeroPageIndexedWithY, // zp,y
// AM_ZeroPageIndirect, // (zp)
// AM_ZeroPageIndirectIndexedWithY // (zp),y
//};
//////////////////////////////////////////////////////////////////////////////
class AddressStack
{
public:
@ -41,7 +22,7 @@ class AddressStack
bool push(quint16 address, bool force = false) {
if (force || (!m_stack.contains(address)))
{
qDebug() << " PUSH: " << uint16ToHex(address);
// qDebug() << " PUSH: " << uint16ToHex(address);
m_stack.push(address);
return true;
}
@ -55,75 +36,46 @@ class AddressStack
QStack<quint16> m_stack;
};
//////////////////////////////////////////////////////////////////////////////
//struct AssyInstruction {
//public:
// AssyInstruction(quint8 opcode = 0x00, QString mnemonic = "???", AddressMode am = AM_InvalidOp);
// AddressMode addressMode() { return m_addressMode; }
// QString mnemonic() { return m_mnemonic; }
// quint8 opcode() { return m_opcode; }
// quint8 numArgs();
// QString debugStr() { return QString("%1 %2 %3").arg(uint8ToHex(m_opcode)).arg(m_mnemonic).arg(m_addressMode); }
//private:
// QString m_mnemonic;
// quint8 m_opcode;
// AddressMode m_addressMode;
//};
//////////////////////////////////////////////////////////////////////////////
class DisassembledItem {
public:
DisassembledItem() { init(); }
DisassembledItem(AssyInstruction instr);
DisassembledItem(quint8 opcode);
bool operator<(const DisassembledItem &other) const { return (address() < other.address()); }
void setInstruction(AssyInstruction instr);
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 setBranch(bool branch) { m_is_branch = branch; }
void setJump(bool jump) { m_is_jump = jump; }
void setJsr(bool jsr) { m_is_jsr = jsr; }
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; }
AssyInstruction assyInstruction() const { return m_instruction; }
QString rawDisassembledString() const { return m_disassembly_text; }
QString disassembledString();
quint8 opcode() const { return m_opcode; }
quint16 address() const { return m_address; }
QString hexAddress() const { return QString("%1").arg(m_address,4,16,QChar('0')).toUpper(); }
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 m_is_branch; }
bool isJump() const { return m_is_jump; }
bool isJsr() const { return m_is_jsr; }
bool isReturn() { return (m_instruction.opcode() == 0x60) || m_instruction.opcode() == 0x40; }
bool isBreak() { return (m_instruction.opcode() == 0x00); }
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() {
if (isReturn()) qDebug() << "Is Return";
if (isInvalidOp()) qDebug() << "Is Invalid Op" << uint8ToHex(m_instruction.opcode());
if (canNotFollow()) qDebug() << "Not following jump";
if (isBreak()) qDebug() << "Is Break";
return isBreak() || isInvalidOp() || isReturn() || canNotFollow(); }
bool stopsProcessing()
{
return isBreak() || isInvalidOp() || isReturn() || canNotFollow();
}
quint16 nextContiguousAddress() { return m_nextContiguousAddress; }
quint16 nextFlowAddress() { return m_nextFlowAddress; }
@ -133,14 +85,18 @@ public:
quint16 targetAddress() const { return m_target_address; }
bool hasArg() const { return m_has_arg; }
quint16 arg16() { return m_raw_arg; }
quint8 arg8() { return m_raw_arg % 256; }
QString arg16Str() { return QString("%1").arg(arg16(),4,16,QChar('0')).toUpper(); }
QString arg8Str() { return QString("%1").arg(arg8(),2,16,QChar('0')).toUpper(); }
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;
@ -149,10 +105,7 @@ private:
QByteArray m_hexvalues;
QString m_disassembly_text;
QString m_hexstring;
bool m_is_branch;
bool m_is_jump;
bool m_is_jsr;
AssyInstruction m_instruction;
bool m_unknown_ta;
quint16 m_raw_arg;
bool m_has_arg;
@ -166,16 +119,14 @@ private:
class Disassembler
{
public:
Disassembler(QByteArray memimage);
Disassembler(AttributedMemory &mem);
enum ProcessorType {
P6502,
P65C02
MOS6502,
MOS65C02
};
QList<DisassembledItem> disassemble(quint16 from,
quint16 to,
QList<quint16> entryPoints,
@ -189,13 +140,15 @@ public:
JumpLines getJumpLines() const { return m_jumplines; }
private:
bool disassembleOp(quint16 address, DisassembledItem &retval, MemoryUsageMap *memuse = Q_NULLPTR);
bool disassembleOp(quint16 address,
DisassembledItem &retval,
MemoryUsageMap *memuse = Q_NULLPTR);
quint16 m_from;
quint16 m_to;
QByteArray m_memimage;
AttributedMemory *m_mem;
AddressStack m_stack;

View File

@ -43,6 +43,15 @@ bool AttributedMemory::setRoleAt(quint16 address,
return false;
}
bool AttributedMemory::replaceRoleAt(quint16 address,
MemRole *withRole)
{
if (!withRole) return false;
removeRoleAt(address,withRole->id());
return setRoleAt(address,withRole);
}
bool AttributedMemory::hasRoleAt(quint16 address, int withId)
{
return m_cells[address].hasRole(withId);
@ -58,6 +67,11 @@ QList<MemRole *> AttributedMemory::getAllRolesAt(quint16 address)
return m_cells[address].getAllRoles();
}
bool AttributedMemory::removeRoleAt(quint16 address, int withId)
{
return m_cells[address].removeRole(withId);
}
QByteArray AttributedMemory::getAllValues() const
{
return getAllValuesInRange(0x0000,0x0ffff);

View File

@ -22,6 +22,8 @@ public:
bool hasRoleAt(quint16 address, int withId);
MemRole *getRoleAt(quint16 address, int withId);
QList<MemRole *> getAllRolesAt(quint16 address);
bool removeRoleAt(quint16 address, int withId);
bool replaceRoleAt(quint16 address, MemRole *withRole);
QByteArray getAllValues() const;
QByteArray getAllValuesInExpectedRange() const;
@ -31,7 +33,6 @@ public:
bool addFile(QByteArray data, quint16 start); // From Memory.h. Should be replaced?
protected:
quint16 m_expected_bottom;

View File

@ -17,10 +17,14 @@ MemoryCell::~MemoryCell()
bool MemoryCell::setRole(MemRole *role)
{
if (!role) return false;
if (!role) {
qWarning("No role given!");
return false;
}
if (hasRole(role->id()))
{
qWarning("Address already has this role.");
return false;
}
@ -43,6 +47,16 @@ bool MemoryCell::hasRole(int id) const
return m_roles.contains(id);
}
bool MemoryCell::removeRole(int id)
{
if (hasRole(id))
{
m_roles.remove(id);
return true;
}
return false;
}
QList<MemRole *> MemoryCell::getAllRoles()
{
return m_roles.values();

View File

@ -18,6 +18,7 @@ public:
bool setRole(MemRole *role);
MemRole *getRole(int id);
bool hasRole(int id) const;
bool removeRole(int id);
void setValue(quint8 val) { m_value = val; }
quint8 value() const { return m_value; }

View File

@ -5,10 +5,7 @@ MemRole::MemRole()
m_parent = nullptr;
}
MemRole::~MemRole()
{
}
void MemRole::setParent(MemoryCell *parent)
{

View File

@ -1,18 +1,25 @@
#ifndef MEMROLE_H
#define MEMROLE_H
#include <QString>
// IDs:
// 1: RoleAsmOpcode
// 2: RoleAsmOperand
class MemoryCell;
class MemRole
{
public:
MemRole();
virtual ~MemRole();
virtual ~MemRole() { }
virtual int id() const = 0;
virtual QString name() const = 0;
void setParent(MemoryCell *parent);
MemoryCell *parent( ) const { return m_parent; }
virtual void setParent(MemoryCell *parent);
virtual MemoryCell *parent( ) const { return m_parent; }
protected:
MemoryCell *m_parent;

View File

@ -2,17 +2,13 @@
#include "opcodes.h"
#include "memorycell.h"
RoleAsmOpcode::RoleAsmOpcode()
{
}
RoleAsmOpcode::~RoleAsmOpcode()
{
}
QString RoleAsmOpcode::getMnemonic()
QString RoleAsmOpcode::mnemonic() const
{
return OpCodes::getMnemonic(m_parent->value());
}
AddressMode RoleAsmOpcode::addressMode() const
{
return OpCodes::addressMode(m_parent->value());
}

View File

@ -2,18 +2,27 @@
#define ROLE_ASM_OPCODE_H
#include "memrole.h"
#include "opcodes.h"
#include <QString>
class RoleAsmOpcode : public MemRole
{
public:
RoleAsmOpcode();
virtual ~RoleAsmOpcode();
static const int RoleID = 1;
RoleAsmOpcode() { m_am = AddressMode::AM_InvalidOp; }
virtual ~RoleAsmOpcode() { }
virtual int id() const { return 1; }
virtual int id() const override { return RoleID; }
virtual QString name() const override { return "RoleAsmOpcode"; }
QString mnemonic() const;
AddressMode addressMode() const;
protected:
AddressMode m_am;
QString getMnemonic();
};
#endif // ROLE_ASM_OPCODE_H

View File

@ -0,0 +1,6 @@
#include "role_asm_operand.h"
RoleAsmOperand::RoleAsmOperand()
{
}

View File

@ -0,0 +1,33 @@
#ifndef ROLEASMOPERAND_H
#define ROLEASMOPERAND_H
#include <QString>
#include "memrole.h"
class RoleAsmOperand : public MemRole
{
public:
static const int RoleID = 2;
typedef enum
{
Byte,
WordLo,
WordHi,
} Type;
RoleAsmOperand();
virtual int id() const override { return RoleID; }
virtual QString name() const override { return "RoleAsmOperand"; }
void setOperandType(Type type) { m_optype = type; }
Type operandType() const { return m_optype; }
protected:
Type m_optype;
};
#endif // ROLEASMOPERAND_H

View File

@ -154,8 +154,7 @@ QStringList DisassemblerViewer::getDisassemblyStrings() {
void DisassemblerViewer::disassemble(QList<quint16> entryPoints) {
//Disassembler dis(m_mem.values());
Disassembler dis(m_mem.getAllValues());
Disassembler dis(m_mem);
int length = m_file->length();
qDebug() << "DV: from: << " << m_file->address() << " to " << length;
int end = m_file->address()+length;

View File

@ -61,7 +61,6 @@ private:
BinaryFileMetadata *m_bfm;
//Memory m_mem;
AttributedMemory m_mem;
bool m_isRelo;

View File

@ -4,15 +4,92 @@ OpCodes::OpCodes()
{
}
AddressMode OpCodes::addressMode(quint8 opcode)
{
return getAssyInstruction(opcode).addressMode();
}
QString OpCodes::mnemonic(quint8 opcode)
{
return getAssyInstruction(opcode).mnemonic();
}
quint8 OpCodes::numArgs(quint8 opcode)
{
return getAssyInstruction(opcode).numArgs();
}
bool OpCodes::isJump(quint8 id)
{
if (id == 0x80) return true; // BRA
if (id == 0x4C) return true; // JMP a
if (id == 0x6C) return true; // JMP (a)
if (id == 0x7C) return true; // JMP (a,x);
return false;
}
bool OpCodes::isIndirectJump(quint8 id)
{
if (id == 0x6C) return true; // JMP (a)
if (id == 0x7C) return true; // JMP (a,x);
return false;
}
bool OpCodes::isBranch(quint8 id)
{
if (id == 0x10) return true; // BPL
if (id == 0x30) return true; // BMI
if (id == 0x50) return true; // BVC
if (id == 0x70) return true; // BVS
if (id == 0x90) return true; // BCC
if (id == 0xB0) return true; // BCS
if (id == 0xD0) return true; // BNE
if (id == 0xF0) return true; // BEQ
return false;
}
bool OpCodes::isJsr(quint8 id)
{
return (id == 0x20); // JSR
}
bool OpCodes::isReturn(quint8 id)
{
if (id == 0x40) return true; // RTI
if (id == 0x60) return true; // RTS
return false;
}
bool OpCodes::isBreak(quint8 id)
{
return (id = 0x00); // BRK
}
bool OpCodes::readsMemoryLoc(quint8 opcode)
{
return getAssyInstruction(opcode).readsMem();
}
bool OpCodes::writesMemoryLoc(quint8 opcode)
{
return getAssyInstruction(opcode).writesMem();
}
bool OpCodes::modifiesStack(quint8 opcode)
{
return getAssyInstruction(opcode).modifiesStack();
}
void OpCodes::makeOpcodeTable(QHash<quint8,AssyInstruction>* opcode_table)
{
opcode_table->insert(0x00,AssyInstruction(0x00, "BRK", AM_Implied));
opcode_table->insert(0x10,AssyInstruction(0x10, "BPL", AM_ProgramCounterRelative));
opcode_table->insert(0x20,AssyInstruction(0x20, "JSR", AM_Absolute));
opcode_table->insert(0x20,AssyInstruction(0x20, "JSR", AM_Absolute, false, false, true));
opcode_table->insert(0x30,AssyInstruction(0x30, "BMI", AM_ProgramCounterRelative));
opcode_table->insert(0x40,AssyInstruction(0x40, "RTI", AM_Implied));
opcode_table->insert(0x40,AssyInstruction(0x40, "RTI", AM_Implied, false, false, true));
opcode_table->insert(0x50,AssyInstruction(0x50, "BVC", AM_ProgramCounterRelative));
opcode_table->insert(0x60,AssyInstruction(0x60, "RTS", AM_Implied));
opcode_table->insert(0x60,AssyInstruction(0x60, "RTS", AM_Implied, false, false, true));
opcode_table->insert(0x70,AssyInstruction(0x70, "BVS", AM_ProgramCounterRelative));
opcode_table->insert(0x80,AssyInstruction(0x80, "BRA", AM_ProgramCounterRelative)); //65C02
opcode_table->insert(0x90,AssyInstruction(0x90, "BCC", AM_ProgramCounterRelative));
@ -23,39 +100,39 @@ void OpCodes::makeOpcodeTable(QHash<quint8,AssyInstruction>* opcode_table)
opcode_table->insert(0xe0,AssyInstruction(0xe0, "CPX", AM_Immediate));
opcode_table->insert(0xf0,AssyInstruction(0xf0, "BEQ", AM_ProgramCounterRelative));
opcode_table->insert(0x01,AssyInstruction(0x01, "ORA", AM_ZeroPageIndexedIndirect));
opcode_table->insert(0x11,AssyInstruction(0x11, "ORA", AM_ZeroPageIndirectIndexedWithY));
opcode_table->insert(0x21,AssyInstruction(0x21, "AND", AM_ZeroPageIndexedIndirect));
opcode_table->insert(0x31,AssyInstruction(0x31, "AND", AM_ZeroPageIndirectIndexedWithY));
opcode_table->insert(0x41,AssyInstruction(0x41, "EOR", AM_ZeroPageIndexedIndirect));
opcode_table->insert(0x51,AssyInstruction(0x51, "EOR", AM_ZeroPageIndirectIndexedWithY));
opcode_table->insert(0x61,AssyInstruction(0x61, "ADC", AM_ZeroPageIndexedIndirect));
opcode_table->insert(0x71,AssyInstruction(0x71, "ADC", AM_ZeroPageIndirectIndexedWithY));
opcode_table->insert(0x81,AssyInstruction(0x81, "STA", AM_ZeroPageIndexedIndirect));
opcode_table->insert(0x91,AssyInstruction(0x91, "STA", AM_ZeroPageIndirectIndexedWithY));
opcode_table->insert(0xa1,AssyInstruction(0xa1, "LDA", AM_ZeroPageIndexedIndirect));
opcode_table->insert(0xb1,AssyInstruction(0xb1, "LDA", AM_ZeroPageIndirectIndexedWithY));
opcode_table->insert(0xc1,AssyInstruction(0xc1, "CMP", AM_ZeroPageIndexedIndirect));
opcode_table->insert(0xd1,AssyInstruction(0xd1, "CMP", AM_ZeroPageIndirectIndexedWithY));
opcode_table->insert(0xe1,AssyInstruction(0xe1, "SBC", AM_ZeroPageIndexedIndirect));
opcode_table->insert(0xf1,AssyInstruction(0xff, "SBC", AM_ZeroPageIndirectIndexedWithY));
opcode_table->insert(0x01,AssyInstruction(0x01, "ORA", AM_ZeroPageIndexedIndirect, true, false, false));
opcode_table->insert(0x11,AssyInstruction(0x11, "ORA", AM_ZeroPageIndirectIndexedWithY, true, false, false));
opcode_table->insert(0x21,AssyInstruction(0x21, "AND", AM_ZeroPageIndexedIndirect, true, false, false));
opcode_table->insert(0x31,AssyInstruction(0x31, "AND", AM_ZeroPageIndirectIndexedWithY, true, false, false));
opcode_table->insert(0x41,AssyInstruction(0x41, "EOR", AM_ZeroPageIndexedIndirect, true, false, false));
opcode_table->insert(0x51,AssyInstruction(0x51, "EOR", AM_ZeroPageIndirectIndexedWithY, true, false, false));
opcode_table->insert(0x61,AssyInstruction(0x61, "ADC", AM_ZeroPageIndexedIndirect, true, false, false));
opcode_table->insert(0x71,AssyInstruction(0x71, "ADC", AM_ZeroPageIndirectIndexedWithY, true, false, false));
opcode_table->insert(0x81,AssyInstruction(0x81, "STA", AM_ZeroPageIndexedIndirect, false, true, false));
opcode_table->insert(0x91,AssyInstruction(0x91, "STA", AM_ZeroPageIndirectIndexedWithY, false, true, false));
opcode_table->insert(0xa1,AssyInstruction(0xa1, "LDA", AM_ZeroPageIndexedIndirect, true, false, false));
opcode_table->insert(0xb1,AssyInstruction(0xb1, "LDA", AM_ZeroPageIndirectIndexedWithY, true, false, false));
opcode_table->insert(0xc1,AssyInstruction(0xc1, "CMP", AM_ZeroPageIndexedIndirect, true, false, false));
opcode_table->insert(0xd1,AssyInstruction(0xd1, "CMP", AM_ZeroPageIndirectIndexedWithY, true, false, false));
opcode_table->insert(0xe1,AssyInstruction(0xe1, "SBC", AM_ZeroPageIndexedIndirect, true, false, false));
opcode_table->insert(0xf1,AssyInstruction(0xff, "SBC", AM_ZeroPageIndirectIndexedWithY, true, false, false));
opcode_table->insert(0x02,AssyInstruction(0x02, "???", AM_InvalidOp));
opcode_table->insert(0x12,AssyInstruction(0x12, "ORA", AM_ZeroPageIndirect));
opcode_table->insert(0x12,AssyInstruction(0x12, "ORA", AM_ZeroPageIndirect, true, false, false));
opcode_table->insert(0x22,AssyInstruction(0x22, "???", AM_InvalidOp));
opcode_table->insert(0x32,AssyInstruction(0x32, "AND", AM_ZeroPageIndirect));
opcode_table->insert(0x32,AssyInstruction(0x32, "AND", AM_ZeroPageIndirect, true, false, false));
opcode_table->insert(0x42,AssyInstruction(0x42, "???", AM_InvalidOp));
opcode_table->insert(0x52,AssyInstruction(0x52, "EOR", AM_ZeroPageIndirect));
opcode_table->insert(0x52,AssyInstruction(0x52, "EOR", AM_ZeroPageIndirect, true, false, false));
opcode_table->insert(0x62,AssyInstruction(0x62, "???", AM_InvalidOp));
opcode_table->insert(0x72,AssyInstruction(0x72, "ADC", AM_ZeroPageIndirect));
opcode_table->insert(0x72,AssyInstruction(0x72, "ADC", AM_ZeroPageIndirect, true, false, false));
opcode_table->insert(0x82,AssyInstruction(0x82, "???", AM_InvalidOp));
opcode_table->insert(0x92,AssyInstruction(0x92, "STA", AM_ZeroPageIndirect)); //65C02
opcode_table->insert(0x92,AssyInstruction(0x92, "STA", AM_ZeroPageIndirect, false, true, false)); //65C02
opcode_table->insert(0xa2,AssyInstruction(0xa2, "LDX", AM_Immediate));
opcode_table->insert(0xb2,AssyInstruction(0xb2, "LDA", AM_ZeroPageIndirect)); //65C02
opcode_table->insert(0xb2,AssyInstruction(0xb2, "LDA", AM_ZeroPageIndirect, true, false, false)); //65C02
opcode_table->insert(0xc2,AssyInstruction(0xc2, "???", AM_InvalidOp));
opcode_table->insert(0xd2,AssyInstruction(0xd2, "CMP", AM_ZeroPageIndirect));
opcode_table->insert(0xd2,AssyInstruction(0xd2, "CMP", AM_ZeroPageIndirect, true, false, false));
opcode_table->insert(0xe2,AssyInstruction(0xe2, "???", AM_InvalidOp));
opcode_table->insert(0xf2,AssyInstruction(0xf2, "SBC", AM_ZeroPageIndirect));
opcode_table->insert(0xf2,AssyInstruction(0xf2, "SBC", AM_ZeroPageIndirect, true, false, false));
opcode_table->insert(0x03,AssyInstruction(0x03, "???", AM_InvalidOp));
opcode_table->insert(0x13,AssyInstruction(0x13, "???", AM_InvalidOp));
@ -74,56 +151,56 @@ void OpCodes::makeOpcodeTable(QHash<quint8,AssyInstruction>* opcode_table)
opcode_table->insert(0xe3,AssyInstruction(0xe3, "???", AM_InvalidOp));
opcode_table->insert(0xf3,AssyInstruction(0xf3, "???", AM_InvalidOp));
opcode_table->insert(0x04,AssyInstruction(0x04, "TSB", AM_ZeroPage)); //65C02
opcode_table->insert(0x14,AssyInstruction(0x14, "TRB", AM_ZeroPage)); //65C02
opcode_table->insert(0x24,AssyInstruction(0x24, "BIT", AM_ZeroPage));
opcode_table->insert(0x34,AssyInstruction(0x34, "BIT", AM_ZeroPageIndexedWithX)); //65C02
opcode_table->insert(0x04,AssyInstruction(0x04, "TSB", AM_ZeroPage, true, false, false)); //65C02
opcode_table->insert(0x14,AssyInstruction(0x14, "TRB", AM_ZeroPage, true, false, false)); //65C02
opcode_table->insert(0x24,AssyInstruction(0x24, "BIT", AM_ZeroPage, true, false, false));
opcode_table->insert(0x34,AssyInstruction(0x34, "BIT", AM_ZeroPageIndexedWithX, true, false, false)); //65C02
opcode_table->insert(0x44,AssyInstruction(0x44, "???", AM_InvalidOp));
opcode_table->insert(0x54,AssyInstruction(0x54, "???", AM_InvalidOp));
opcode_table->insert(0x64,AssyInstruction(0x64, "STZ", AM_ZeroPage)); //65C02
opcode_table->insert(0x74,AssyInstruction(0x74, "STZ", AM_ZeroPageIndexedWithX)); //65C02
opcode_table->insert(0x84,AssyInstruction(0x84, "STY", AM_ZeroPage));
opcode_table->insert(0x94,AssyInstruction(0x94, "STY", AM_ZeroPageIndexedWithX));
opcode_table->insert(0xa4,AssyInstruction(0xa4, "LDY", AM_ZeroPage));
opcode_table->insert(0xb4,AssyInstruction(0xb4, "LDY", AM_ZeroPageIndexedWithX));
opcode_table->insert(0xc4,AssyInstruction(0xc4, "CPY", AM_ZeroPage));
opcode_table->insert(0x64,AssyInstruction(0x64, "STZ", AM_ZeroPage, false, true, false)); //65C02
opcode_table->insert(0x74,AssyInstruction(0x74, "STZ", AM_ZeroPageIndexedWithX, false, true, false)); //65C02
opcode_table->insert(0x84,AssyInstruction(0x84, "STY", AM_ZeroPage, false, true, false));
opcode_table->insert(0x94,AssyInstruction(0x94, "STY", AM_ZeroPageIndexedWithX, false, true, false));
opcode_table->insert(0xa4,AssyInstruction(0xa4, "LDY", AM_ZeroPage, true, false, false));
opcode_table->insert(0xb4,AssyInstruction(0xb4, "LDY", AM_ZeroPageIndexedWithX, true, false, false));
opcode_table->insert(0xc4,AssyInstruction(0xc4, "CPY", AM_ZeroPage, true, false, false));
opcode_table->insert(0xd4,AssyInstruction(0xd4, "???", AM_InvalidOp));
opcode_table->insert(0xe4,AssyInstruction(0xe4, "CPX", AM_ZeroPage));
opcode_table->insert(0xe4,AssyInstruction(0xe4, "CPX", AM_ZeroPage, true, false, false));
opcode_table->insert(0xf4,AssyInstruction(0xf4, "???", AM_InvalidOp));
opcode_table->insert(0x05,AssyInstruction(0x05, "ORA", AM_ZeroPage));
opcode_table->insert(0x15,AssyInstruction(0x15, "ORA", AM_ZeroPageIndexedWithX));
opcode_table->insert(0x25,AssyInstruction(0x25, "AND", AM_ZeroPage));
opcode_table->insert(0x35,AssyInstruction(0x35, "AND", AM_ZeroPageIndexedWithX));
opcode_table->insert(0x45,AssyInstruction(0x45, "EOR", AM_ZeroPage));
opcode_table->insert(0x55,AssyInstruction(0x55, "EOR", AM_ZeroPageIndexedWithX));
opcode_table->insert(0x65,AssyInstruction(0x65, "ADC", AM_ZeroPage));
opcode_table->insert(0x75,AssyInstruction(0x75, "ADC", AM_ZeroPageIndexedWithX));
opcode_table->insert(0x85,AssyInstruction(0x85, "STA", AM_ZeroPage));
opcode_table->insert(0x95,AssyInstruction(0x95, "STA", AM_ZeroPageIndexedWithX));
opcode_table->insert(0xa5,AssyInstruction(0xa5, "LDA", AM_ZeroPage));
opcode_table->insert(0xb5,AssyInstruction(0xb5, "LDA", AM_ZeroPageIndexedWithX));
opcode_table->insert(0xc5,AssyInstruction(0xc5, "CMP", AM_ZeroPage));
opcode_table->insert(0xd5,AssyInstruction(0xd5, "CMP", AM_ZeroPageIndexedWithX));
opcode_table->insert(0xe5,AssyInstruction(0xe5, "SEC", AM_ZeroPage));
opcode_table->insert(0xf5,AssyInstruction(0xf5, "SEC", AM_ZeroPageIndexedWithX));
opcode_table->insert(0x05,AssyInstruction(0x05, "ORA", AM_ZeroPage, true, false, false));
opcode_table->insert(0x15,AssyInstruction(0x15, "ORA", AM_ZeroPageIndexedWithX, true, false, false));
opcode_table->insert(0x25,AssyInstruction(0x25, "AND", AM_ZeroPage, true, false, false));
opcode_table->insert(0x35,AssyInstruction(0x35, "AND", AM_ZeroPageIndexedWithX, true, false, false));
opcode_table->insert(0x45,AssyInstruction(0x45, "EOR", AM_ZeroPage, true, false, false));
opcode_table->insert(0x55,AssyInstruction(0x55, "EOR", AM_ZeroPageIndexedWithX, true, false, false));
opcode_table->insert(0x65,AssyInstruction(0x65, "ADC", AM_ZeroPage, true, false, false));
opcode_table->insert(0x75,AssyInstruction(0x75, "ADC", AM_ZeroPageIndexedWithX, true, false, false));
opcode_table->insert(0x85,AssyInstruction(0x85, "STA", AM_ZeroPage, false, true, false));
opcode_table->insert(0x95,AssyInstruction(0x95, "STA", AM_ZeroPageIndexedWithX, false, true, false));
opcode_table->insert(0xa5,AssyInstruction(0xa5, "LDA", AM_ZeroPage, true, false, false));
opcode_table->insert(0xb5,AssyInstruction(0xb5, "LDA", AM_ZeroPageIndexedWithX, true, false, false));
opcode_table->insert(0xc5,AssyInstruction(0xc5, "CMP", AM_ZeroPage, true, false, false));
opcode_table->insert(0xd5,AssyInstruction(0xd5, "CMP", AM_ZeroPageIndexedWithX, true, false, false));
opcode_table->insert(0xe5,AssyInstruction(0xe5, "SBC", AM_ZeroPage, true, false, false));
opcode_table->insert(0xf5,AssyInstruction(0xf5, "SBC", AM_ZeroPageIndexedWithX, true, false, false));
opcode_table->insert(0x06,AssyInstruction(0x06, "ASL", AM_ZeroPage));
opcode_table->insert(0x16,AssyInstruction(0x16, "ASL", AM_ZeroPageIndexedWithX));
opcode_table->insert(0x26,AssyInstruction(0x26, "ROL", AM_ZeroPage));
opcode_table->insert(0x36,AssyInstruction(0x36, "ROL", AM_ZeroPageIndexedWithX));
opcode_table->insert(0x46,AssyInstruction(0x46, "LSR", AM_ZeroPage));
opcode_table->insert(0x56,AssyInstruction(0x56, "LSR", AM_ZeroPageIndexedWithX));
opcode_table->insert(0x66,AssyInstruction(0x66, "ROR", AM_ZeroPage));
opcode_table->insert(0x76,AssyInstruction(0x76, "ROR", AM_ZeroPageIndexedWithX));
opcode_table->insert(0x86,AssyInstruction(0x86, "STX", AM_ZeroPage));
opcode_table->insert(0x96,AssyInstruction(0x96, "STX", AM_ZeroPageIndexedWithY));
opcode_table->insert(0xa6,AssyInstruction(0xa6, "LDX", AM_ZeroPage));
opcode_table->insert(0xb6,AssyInstruction(0xb6, "LDX", AM_ZeroPageIndexedWithY));
opcode_table->insert(0xc6,AssyInstruction(0xc6, "DEC", AM_ZeroPage));
opcode_table->insert(0xd6,AssyInstruction(0xd6, "DEC", AM_ZeroPageIndexedWithX));
opcode_table->insert(0xe6,AssyInstruction(0xe6, "INC", AM_ZeroPage));
opcode_table->insert(0xf6,AssyInstruction(0xf6, "INC", AM_ZeroPageIndexedWithX));
opcode_table->insert(0x06,AssyInstruction(0x06, "ASL", AM_ZeroPage, true, true, false));
opcode_table->insert(0x16,AssyInstruction(0x16, "ASL", AM_ZeroPageIndexedWithX, true, true, false));
opcode_table->insert(0x26,AssyInstruction(0x26, "ROL", AM_ZeroPage, true, true, false));
opcode_table->insert(0x36,AssyInstruction(0x36, "ROL", AM_ZeroPageIndexedWithX, true, true, false));
opcode_table->insert(0x46,AssyInstruction(0x46, "LSR", AM_ZeroPage, true, true, false));
opcode_table->insert(0x56,AssyInstruction(0x56, "LSR", AM_ZeroPageIndexedWithX, true, true, false));
opcode_table->insert(0x66,AssyInstruction(0x66, "ROR", AM_ZeroPage, true, true, false));
opcode_table->insert(0x76,AssyInstruction(0x76, "ROR", AM_ZeroPageIndexedWithX, true, true, false));
opcode_table->insert(0x86,AssyInstruction(0x86, "STX", AM_ZeroPage, false, true, false));
opcode_table->insert(0x96,AssyInstruction(0x96, "STX", AM_ZeroPageIndexedWithY, false, true, false));
opcode_table->insert(0xa6,AssyInstruction(0xa6, "LDX", AM_ZeroPage, true, false, false));
opcode_table->insert(0xb6,AssyInstruction(0xb6, "LDX", AM_ZeroPageIndexedWithY, true, false, false));
opcode_table->insert(0xc6,AssyInstruction(0xc6, "DEC", AM_ZeroPage, true, true, false));
opcode_table->insert(0xd6,AssyInstruction(0xd6, "DEC", AM_ZeroPageIndexedWithX, true, true, false));
opcode_table->insert(0xe6,AssyInstruction(0xe6, "INC", AM_ZeroPage, true, true, false));
opcode_table->insert(0xf6,AssyInstruction(0xf6, "INC", AM_ZeroPageIndexedWithX, true, true, false));
opcode_table->insert(0x07,AssyInstruction(0x07, "???", AM_InvalidOp));
opcode_table->insert(0x17,AssyInstruction(0x17, "???", AM_InvalidOp));
@ -160,21 +237,21 @@ void OpCodes::makeOpcodeTable(QHash<quint8,AssyInstruction>* opcode_table)
opcode_table->insert(0xf8,AssyInstruction(0xf8, "SED", AM_Implied));
opcode_table->insert(0x09,AssyInstruction(0x09, "ORA", AM_Immediate));
opcode_table->insert(0x19,AssyInstruction(0x19, "ORA", AM_AbsoluteIndexedWithY));
opcode_table->insert(0x19,AssyInstruction(0x19, "ORA", AM_AbsoluteIndexedWithY, true, false, false));
opcode_table->insert(0x29,AssyInstruction(0x29, "AND", AM_Immediate));
opcode_table->insert(0x39,AssyInstruction(0x39, "AND", AM_AbsoluteIndexedWithY));
opcode_table->insert(0x39,AssyInstruction(0x39, "AND", AM_AbsoluteIndexedWithY, true, false, false));
opcode_table->insert(0x49,AssyInstruction(0x49, "EOR", AM_Immediate));
opcode_table->insert(0x59,AssyInstruction(0x59, "EOR", AM_AbsoluteIndexedWithY));
opcode_table->insert(0x59,AssyInstruction(0x59, "EOR", AM_AbsoluteIndexedWithY, true, false, false));
opcode_table->insert(0x69,AssyInstruction(0x69, "ADC", AM_Immediate));
opcode_table->insert(0x79,AssyInstruction(0x79, "ADC", AM_AbsoluteIndexedWithY));
opcode_table->insert(0x79,AssyInstruction(0x79, "ADC", AM_AbsoluteIndexedWithY, true, false, false));
opcode_table->insert(0x89,AssyInstruction(0x89, "BIT", AM_Immediate)); //65C02
opcode_table->insert(0x99,AssyInstruction(0x99, "STA", AM_AbsoluteIndexedWithY));
opcode_table->insert(0x99,AssyInstruction(0x99, "STA", AM_AbsoluteIndexedWithY, false, true, false));
opcode_table->insert(0xa9,AssyInstruction(0xa9, "LDA", AM_Immediate));
opcode_table->insert(0xb9,AssyInstruction(0xb9, "LDA", AM_AbsoluteIndexedWithY));
opcode_table->insert(0xb9,AssyInstruction(0xb9, "LDA", AM_AbsoluteIndexedWithY, true, false, false));
opcode_table->insert(0xc9,AssyInstruction(0xc9, "CMP", AM_Immediate));
opcode_table->insert(0xd9,AssyInstruction(0xd9, "CMP", AM_AbsoluteIndexedWithY));
opcode_table->insert(0xd9,AssyInstruction(0xd9, "CMP", AM_AbsoluteIndexedWithY, true, false, false));
opcode_table->insert(0xe9,AssyInstruction(0xe9, "SBC", AM_Immediate));
opcode_table->insert(0xf9,AssyInstruction(0xf9, "SBC", AM_AbsoluteIndexedWithY));
opcode_table->insert(0xf9,AssyInstruction(0xf9, "SBC", AM_AbsoluteIndexedWithY, true, false, false));
opcode_table->insert(0x0a,AssyInstruction(0x0a, "ASL", AM_Accumulator));
opcode_table->insert(0x1a,AssyInstruction(0x1a, "INA", AM_Accumulator)); //65C02
@ -210,56 +287,56 @@ void OpCodes::makeOpcodeTable(QHash<quint8,AssyInstruction>* opcode_table)
opcode_table->insert(0xeb,AssyInstruction(0xeb, "???", AM_InvalidOp));
opcode_table->insert(0xfb,AssyInstruction(0xfb, "???", AM_InvalidOp));
opcode_table->insert(0x0c,AssyInstruction(0x0c, "TSB", AM_Absolute)); //65C02
opcode_table->insert(0x1c,AssyInstruction(0x1c, "TRB", AM_Absolute)); //65C02
opcode_table->insert(0x2c,AssyInstruction(0x2c, "BIT", AM_Absolute));
opcode_table->insert(0x3c,AssyInstruction(0x3c, "BIT", AM_AbsoluteIndexedWithX)); //65C02
opcode_table->insert(0x0c,AssyInstruction(0x0c, "TSB", AM_Absolute, true, true, false)); //65C02
opcode_table->insert(0x1c,AssyInstruction(0x1c, "TRB", AM_Absolute, true, true, false)); //65C02
opcode_table->insert(0x2c,AssyInstruction(0x2c, "BIT", AM_Absolute, true, false, false));
opcode_table->insert(0x3c,AssyInstruction(0x3c, "BIT", AM_AbsoluteIndexedWithX, true, false, false)); //65C02
opcode_table->insert(0x4c,AssyInstruction(0x4c, "JMP", AM_Absolute));
opcode_table->insert(0x5c,AssyInstruction(0x5c, "???", AM_InvalidOp));
opcode_table->insert(0x6c,AssyInstruction(0x6c, "JMP", AM_AbsoluteIndirect));
opcode_table->insert(0x7c,AssyInstruction(0x7c, "JMP", AM_AbsoluteIndexedIndirect)); //65C02
opcode_table->insert(0x8c,AssyInstruction(0x8c, "STY", AM_Absolute));
opcode_table->insert(0x9c,AssyInstruction(0x9c, "STZ", AM_Absolute));
opcode_table->insert(0xac,AssyInstruction(0xac, "LDY", AM_Absolute));
opcode_table-