mirror of
https://github.com/markdavidlong/AppleSAWS.git
synced 2024-12-11 17:50:38 +00:00
Added memory role detection in disassembler for opcodes and operands
This commit is contained in:
parent
9ab500ede5
commit
7f4ca94e9a
@ -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 \
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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; }
|
||||
|
@ -5,10 +5,7 @@ MemRole::MemRole()
|
||||
m_parent = nullptr;
|
||||
}
|
||||
|
||||
MemRole::~MemRole()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MemRole::setParent(MemoryCell *parent)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
|
6
src/memory/roles/role_asm_operand.cpp
Normal file
6
src/memory/roles/role_asm_operand.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "role_asm_operand.h"
|
||||
|
||||
RoleAsmOperand::RoleAsmOperand()
|
||||
{
|
||||
|
||||
}
|
33
src/memory/roles/role_asm_operand.h
Normal file
33
src/memory/roles/role_asm_operand.h
Normal 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
|
@ -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;
|
||||
|
@ -61,7 +61,6 @@ private:
|
||||
|
||||
BinaryFileMetadata *m_bfm;
|
||||
|
||||
//Memory m_mem;
|
||||
AttributedMemory m_mem;
|
||||
|
||||
bool m_isRelo;
|
||||
|
@ -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));
|
||||
|