mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
387 lines
No EOL
16 KiB
C++
387 lines
No EOL
16 KiB
C++
#include "pch.h"
|
|
#include "SNES/Debugger/SnesDisUtils.h"
|
|
#include "SNES/SnesCpuTypes.h"
|
|
#include "SNES/SnesCpu.h"
|
|
#include "SNES/SnesConsole.h"
|
|
#include "Shared/EmuSettings.h"
|
|
#include "Debugger/DisassemblyInfo.h"
|
|
#include "Debugger/LabelManager.h"
|
|
#include "SNES/Debugger/DummySnesCpu.h"
|
|
#include "Utilities/HexUtilities.h"
|
|
#include "Utilities/FastString.h"
|
|
|
|
void SnesDisUtils::GetDisassembly(DisassemblyInfo &info, string &out, uint32_t memoryAddr, LabelManager* labelManager, EmuSettings* settings)
|
|
{
|
|
FastString str(settings->GetDebugConfig().UseLowerCaseDisassembly);
|
|
|
|
uint8_t opCode = info.GetOpCode();
|
|
SnesAddrMode addrMode = SnesDisUtils::OpMode[opCode];
|
|
str.Write(SnesDisUtils::OpName[opCode]);
|
|
str.Write(' ');
|
|
|
|
uint32_t opAddr = SnesDisUtils::GetOperandAddress(info, memoryAddr);
|
|
uint32_t opSize = info.GetOpSize();
|
|
|
|
FastString operand(settings->GetDebugConfig().UseLowerCaseDisassembly);
|
|
if(opSize > 1) {
|
|
if(addrMode == SnesAddrMode::Rel || addrMode == SnesAddrMode::RelLng || opSize == 4) {
|
|
AddressInfo address { (int32_t)opAddr, MemoryType::SnesMemory };
|
|
string label = labelManager ? labelManager->GetLabel(address) : "";
|
|
if(label.size()) {
|
|
operand.Write(label, true);
|
|
} else {
|
|
operand.WriteAll('$', HexUtilities::ToHex24(opAddr));
|
|
}
|
|
} else if(opSize == 2) {
|
|
operand.WriteAll('$', HexUtilities::ToHex((uint8_t)opAddr));
|
|
} else if(opSize == 3) {
|
|
operand.WriteAll('$', HexUtilities::ToHex((uint16_t)opAddr));
|
|
}
|
|
}
|
|
|
|
switch(addrMode) {
|
|
case SnesAddrMode::Abs: str.Write(operand); break;
|
|
case SnesAddrMode::AbsJmp: str.Write(operand); break;
|
|
case SnesAddrMode::AbsIdxXInd: str.WriteAll('(', operand, ",X)"); break;
|
|
case SnesAddrMode::AbsIdxX: str.WriteAll(operand, ",X"); break;
|
|
case SnesAddrMode::AbsIdxY: str.WriteAll(operand, ",Y"); break;
|
|
case SnesAddrMode::AbsInd: str.WriteAll('(', operand, ')'); break;
|
|
case SnesAddrMode::AbsIndLng: str.WriteAll('[', operand, ']'); break;
|
|
case SnesAddrMode::AbsLngIdxX: str.WriteAll(operand, ",X"); break;
|
|
case SnesAddrMode::AbsLng: str.Write(operand); break;
|
|
case SnesAddrMode::AbsLngJmp: str.Write(operand); break;
|
|
case SnesAddrMode::Acc: break;
|
|
case SnesAddrMode::BlkMov: str.WriteAll('$', operand[1], operand[2], ','); str.WriteAll('$', operand[3], operand[4]); break;
|
|
case SnesAddrMode::DirIdxIndX: str.WriteAll('(', operand, ",X)"); break;
|
|
case SnesAddrMode::DirIdxX: str.WriteAll(operand, ",X"); break;
|
|
case SnesAddrMode::DirIdxY: str.WriteAll(operand, ",Y"); break;
|
|
case SnesAddrMode::DirIndIdxY: str.WriteAll("(", operand, "),Y"); break;
|
|
case SnesAddrMode::DirIndLngIdxY: str.WriteAll("[", operand, "],Y"); break;
|
|
case SnesAddrMode::DirIndLng: str.WriteAll("[", operand, "]"); break;
|
|
case SnesAddrMode::DirInd: str.WriteAll("(", operand, ")"); break;
|
|
case SnesAddrMode::Dir: str.Write(operand); break;
|
|
|
|
case SnesAddrMode::Imm8: case SnesAddrMode::Imm16: case SnesAddrMode::ImmX: case SnesAddrMode::ImmM:
|
|
str.WriteAll('#', operand);
|
|
break;
|
|
|
|
case SnesAddrMode::Imp: break;
|
|
case SnesAddrMode::RelLng: str.Write(operand); break;
|
|
case SnesAddrMode::Rel: str.Write(operand); break;
|
|
case SnesAddrMode::Stk: break;
|
|
case SnesAddrMode::StkRel: str.WriteAll(operand, ",S"); break;
|
|
case SnesAddrMode::StkRelIndIdxY: str.WriteAll('(', operand, ",S),Y"); break;
|
|
|
|
default: throw std::runtime_error("invalid address mode");
|
|
}
|
|
|
|
out += str.ToString();
|
|
}
|
|
|
|
uint32_t SnesDisUtils::GetOperandAddress(DisassemblyInfo &info, uint32_t memoryAddr)
|
|
{
|
|
uint32_t opSize = info.GetOpSize();
|
|
uint32_t opAddr = 0;
|
|
uint8_t* byteCode = info.GetByteCode();
|
|
if(opSize == 2) {
|
|
opAddr = byteCode[1];
|
|
} else if(opSize == 3) {
|
|
opAddr = byteCode[1] | (byteCode[2] << 8);
|
|
} else if(opSize == 4) {
|
|
opAddr = byteCode[1] | (byteCode[2] << 8) | (byteCode[3] << 16);
|
|
}
|
|
|
|
SnesAddrMode addrMode = SnesDisUtils::OpMode[byteCode[0]];
|
|
if(addrMode == SnesAddrMode::Rel || addrMode == SnesAddrMode::RelLng) {
|
|
if(opSize == 2) {
|
|
opAddr = (memoryAddr & 0xFF0000) | (((int8_t)opAddr + memoryAddr + 2) & 0xFFFF);
|
|
} else {
|
|
opAddr = (memoryAddr & 0xFF0000) | (((int16_t)opAddr + memoryAddr + 3) & 0xFFFF);
|
|
}
|
|
}
|
|
|
|
return opAddr;
|
|
}
|
|
|
|
EffectiveAddressInfo SnesDisUtils::GetEffectiveAddress(DisassemblyInfo &info, SnesConsole *console, SnesCpuState &state, CpuType type)
|
|
{
|
|
SnesAddrMode opMode = SnesDisUtils::OpMode[info.GetOpCode()];
|
|
if(opMode == SnesAddrMode::Stk) {
|
|
//Show nothing for stack operations (push/pull)
|
|
return {};
|
|
}
|
|
|
|
bool showEffectiveAddress = HasEffectiveAddress(opMode);
|
|
|
|
DummySnesCpu dummyCpu(console, type);
|
|
state.PS &= ~(ProcFlags::IndexMode8 | ProcFlags::MemoryMode8);
|
|
state.PS |= info.GetFlags();
|
|
dummyCpu.SetDummyState(state);
|
|
dummyCpu.Exec();
|
|
|
|
bool isJump = SnesDisUtils::IsUnconditionalJump(info.GetOpCode()) || SnesDisUtils::IsConditionalJump(info.GetOpCode());
|
|
if(isJump) {
|
|
if(info.GetOpSize() == 3) {
|
|
//For 3-byte jumps, return the target address, and show no value
|
|
if(SnesDisUtils::IsUnconditionalJump(info.GetOpCode())) {
|
|
//Display the dummy cpu's current address - this allows indirect jumps to display the correct address based on K
|
|
return { (dummyCpu.GetState().K << 16) | dummyCpu.GetState().PC, 0, true };
|
|
} else {
|
|
return { dummyCpu.GetLastOperand(), 0, true };
|
|
}
|
|
} else {
|
|
//Relative or long jumps already show the final address in the disassembly, show nothing
|
|
return {};
|
|
}
|
|
}
|
|
|
|
//For everything else, return the last read/write address
|
|
uint32_t count = dummyCpu.GetOperationCount();
|
|
for(int i = count - 1; i > 0; i--) {
|
|
MemoryOperationInfo opInfo = dummyCpu.GetOperationInfo(i);
|
|
|
|
if(opInfo.Type != MemoryOperationType::ExecOperand) {
|
|
MemoryOperationInfo prevOpInfo = dummyCpu.GetOperationInfo(i - 1);
|
|
EffectiveAddressInfo result;
|
|
if(prevOpInfo.Type == opInfo.Type && prevOpInfo.Address == opInfo.Address - 1) {
|
|
//For 16-bit read/writes, return the first address
|
|
result.Address = prevOpInfo.Address;
|
|
result.Type = prevOpInfo.MemType;
|
|
result.ValueSize = 2;
|
|
} else if(opInfo.Type == MemoryOperationType::Write && prevOpInfo.Type == opInfo.Type && prevOpInfo.Address == opInfo.Address + 1) {
|
|
//For 16-bit RMW instructions, the 2nd byte is written first
|
|
result.Address = opInfo.Address;
|
|
result.Type = opInfo.MemType;
|
|
result.ValueSize = 2;
|
|
} else {
|
|
result.Address = opInfo.Address;
|
|
result.Type = opInfo.MemType;
|
|
result.ValueSize = 1;
|
|
}
|
|
result.ShowAddress = showEffectiveAddress;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
bool SnesDisUtils::CanDisassembleNextOp(uint8_t opCode)
|
|
{
|
|
//Stop disassembling on PLP (because it can alter X/M flags)
|
|
return opCode != 0x28;
|
|
}
|
|
|
|
void SnesDisUtils::UpdateCpuFlags(uint8_t opCode, uint8_t* byteCode, uint8_t& cpuFlags)
|
|
{
|
|
if(opCode == 0xC2) {
|
|
//REP, update the flags and keep disassembling
|
|
uint8_t flags = byteCode[1];
|
|
cpuFlags &= ~flags;
|
|
} else if(opCode == 0xE2) {
|
|
//SEP, update the flags and keep disassembling
|
|
uint8_t flags = byteCode[1];
|
|
cpuFlags |= flags;
|
|
}
|
|
}
|
|
|
|
bool SnesDisUtils::HasEffectiveAddress(SnesAddrMode addrMode)
|
|
{
|
|
switch(addrMode) {
|
|
case SnesAddrMode::Acc:
|
|
case SnesAddrMode::Imp:
|
|
case SnesAddrMode::Stk:
|
|
case SnesAddrMode::Sig8:
|
|
case SnesAddrMode::Imm8:
|
|
case SnesAddrMode::Rel:
|
|
case SnesAddrMode::RelLng:
|
|
case SnesAddrMode::Imm16:
|
|
case SnesAddrMode::BlkMov:
|
|
case SnesAddrMode::AbsLngJmp:
|
|
case SnesAddrMode::AbsLng:
|
|
case SnesAddrMode::ImmX:
|
|
case SnesAddrMode::ImmM:
|
|
case SnesAddrMode::AbsJmp:
|
|
return false;
|
|
|
|
case SnesAddrMode::DirIdxIndX:
|
|
case SnesAddrMode::DirIdxX:
|
|
case SnesAddrMode::DirIdxY:
|
|
case SnesAddrMode::DirIndIdxY:
|
|
case SnesAddrMode::DirIndLngIdxY:
|
|
case SnesAddrMode::DirIndLng:
|
|
case SnesAddrMode::DirInd:
|
|
case SnesAddrMode::Dir:
|
|
case SnesAddrMode::StkRel:
|
|
case SnesAddrMode::StkRelIndIdxY:
|
|
case SnesAddrMode::Abs:
|
|
case SnesAddrMode::AbsIdxXInd:
|
|
case SnesAddrMode::AbsIdxX:
|
|
case SnesAddrMode::AbsIdxY:
|
|
case SnesAddrMode::AbsLngIdxX:
|
|
case SnesAddrMode::AbsInd:
|
|
case SnesAddrMode::AbsIndLng:
|
|
return true;
|
|
}
|
|
|
|
throw std::runtime_error("Invalid mode");
|
|
}
|
|
|
|
uint8_t SnesDisUtils::GetOpSize(SnesAddrMode addrMode, uint8_t flags)
|
|
{
|
|
if(addrMode == SnesAddrMode::ImmX) {
|
|
return (flags & ProcFlags::IndexMode8) ? 2 : 3;
|
|
} else if(addrMode == SnesAddrMode::ImmM) {
|
|
return (flags & ProcFlags::MemoryMode8) ? 2 : 3;
|
|
}
|
|
|
|
return SnesDisUtils::OpSize[(int)addrMode];
|
|
}
|
|
|
|
uint8_t SnesDisUtils::GetOpSize(uint8_t opCode, uint8_t flags)
|
|
{
|
|
return GetOpSize(SnesDisUtils::OpMode[opCode], flags);
|
|
}
|
|
|
|
bool SnesDisUtils::IsUnconditionalJump(uint8_t opCode)
|
|
{
|
|
switch(opCode) {
|
|
case 0x00: //BRK
|
|
case 0x02: //COP
|
|
case 0x20: //JSR
|
|
case 0x22: //JSR
|
|
case 0x40: //RTI
|
|
case 0x4C: //JMP
|
|
case 0x5C: //JMP
|
|
case 0x60: //RTS
|
|
case 0x6B: //RTL
|
|
case 0x6C: //JMP
|
|
case 0x7C: //JMP
|
|
case 0x80: //BRA
|
|
case 0x82: //BRL
|
|
case 0xDC: //JMP
|
|
case 0xFC: //JSR
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool SnesDisUtils::IsConditionalJump(uint8_t opCode)
|
|
{
|
|
switch(opCode) {
|
|
case 0x10: //BPL
|
|
case 0x30: //BMI
|
|
case 0x50: //BVC
|
|
case 0x70: //BVS
|
|
case 0x90: //BCC
|
|
case 0xB0: //BCS
|
|
case 0xD0: //BNE
|
|
case 0xF0: //BEQ
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
CdlFlags::CdlFlags SnesDisUtils::GetOpFlags(uint8_t opCode, uint32_t pc, uint32_t prevPc)
|
|
{
|
|
switch(opCode) {
|
|
case 0x00: //BRK
|
|
case 0x02: //COP
|
|
case 0x20: //JSR
|
|
case 0x22: //JSR
|
|
case 0xFC: //JSR
|
|
return CdlFlags::SubEntryPoint;
|
|
|
|
case 0x10: //BPL
|
|
case 0x30: //BMI
|
|
case 0x50: //BVC
|
|
case 0x70: //BVS
|
|
case 0x90: //BCC
|
|
case 0xB0: //BCS
|
|
case 0xD0: //BNE
|
|
case 0xF0: //BEQ
|
|
case 0x4C: //JMP
|
|
case 0x5C: //JMP
|
|
case 0x6C: //JMP
|
|
case 0x7C: //JMP
|
|
case 0x80: //BRA
|
|
case 0x82: //BRL
|
|
case 0xDC: //JMP
|
|
return pc != prevPc + SnesDisUtils::GetOpSize(opCode, 0) ? CdlFlags::JumpTarget : CdlFlags::None;
|
|
|
|
default:
|
|
return CdlFlags::None;
|
|
}
|
|
}
|
|
|
|
bool SnesDisUtils::IsJumpToSub(uint8_t opCode)
|
|
{
|
|
switch(opCode) {
|
|
case 0x00: //BRK
|
|
case 0x02: //COP
|
|
case 0x20: //JSR
|
|
case 0x22: //JSL
|
|
case 0xFC: //JSR
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool SnesDisUtils::IsReturnInstruction(uint8_t opCode)
|
|
{
|
|
return opCode == 0x60 || opCode == 0x6B || opCode == 0x40;
|
|
}
|
|
|
|
uint8_t SnesDisUtils::OpSize[0x1F] = {
|
|
2, 2, 3, 0, 0, 3, 3, 3, 3, 3,
|
|
3, 4, 4, 3, 4, 1, 3, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 1, 3, 2, 1, 2,
|
|
2
|
|
};
|
|
|
|
string SnesDisUtils::OpName[256] = {
|
|
//0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
"BRK", "ORA", "COP", "ORA", "TSB", "ORA", "ASL", "ORA", "PHP", "ORA", "ASL", "PHD", "TSB", "ORA", "ASL", "ORA", // 0
|
|
"BPL", "ORA", "ORA", "ORA", "TRB", "ORA", "ASL", "ORA", "CLC", "ORA", "INC", "TCS", "TRB", "ORA", "ASL", "ORA", // 1
|
|
"JSR", "AND", "JSL", "AND", "BIT", "AND", "ROL", "AND", "PLP", "AND", "ROL", "PLD", "BIT", "AND", "ROL", "AND", // 2
|
|
"BMI", "AND", "AND", "AND", "BIT", "AND", "ROL", "AND", "SEC", "AND", "DEC", "TSC", "BIT", "AND", "ROL", "AND", // 3
|
|
"RTI", "EOR", "WDM", "EOR", "MVP", "EOR", "LSR", "EOR", "PHA", "EOR", "LSR", "PHK", "JMP", "EOR", "LSR", "EOR", // 4
|
|
"BVC", "EOR", "EOR", "EOR", "MVN", "EOR", "LSR", "EOR", "CLI", "EOR", "PHY", "TCD", "JML", "EOR", "LSR", "EOR", // 5
|
|
"RTS", "ADC", "PER", "ADC", "STZ", "ADC", "ROR", "ADC", "PLA", "ADC", "ROR", "RTL", "JMP", "ADC", "ROR", "ADC", // 6
|
|
"BVS", "ADC", "ADC", "ADC", "STZ", "ADC", "ROR", "ADC", "SEI", "ADC", "PLY", "TDC", "JMP", "ADC", "ROR", "ADC", // 7
|
|
"BRA", "STA", "BRL", "STA", "STY", "STA", "STX", "STA", "DEY", "BIT", "TXA", "PHB", "STY", "STA", "STX", "STA", // 8
|
|
"BCC", "STA", "STA", "STA", "STY", "STA", "STX", "STA", "TYA", "STA", "TXS", "TXY", "STZ", "STA", "STZ", "STA", // 9
|
|
"LDY", "LDA", "LDX", "LDA", "LDY", "LDA", "LDX", "LDA", "TAY", "LDA", "TAX", "PLB", "LDY", "LDA", "LDX", "LDA", // A
|
|
"BCS", "LDA", "LDA", "LDA", "LDY", "LDA", "LDX", "LDA", "CLV", "LDA", "TSX", "TYX", "LDY", "LDA", "LDX", "LDA", // B
|
|
"CPY", "CMP", "REP", "CMP", "CPY", "CMP", "DEC", "CMP", "INY", "CMP", "DEX", "WAI", "CPY", "CMP", "DEC", "CMP", // C
|
|
"BNE", "CMP", "CMP", "CMP", "PEI", "CMP", "DEC", "CMP", "CLD", "CMP", "PHX", "STP", "JML", "CMP", "DEC", "CMP", // D
|
|
"CPX", "SBC", "SEP", "SBC", "CPX", "SBC", "INC", "SBC", "INX", "SBC", "NOP", "XBA", "CPX", "SBC", "INC", "SBC", // E
|
|
"BEQ", "SBC", "SBC", "SBC", "PEA", "SBC", "INC", "SBC", "SED", "SBC", "PLX", "XCE", "JSR", "SBC", "INC", "SBC" // F
|
|
};
|
|
|
|
typedef SnesAddrMode M;
|
|
SnesAddrMode SnesDisUtils::OpMode[256] = {
|
|
//0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
M::Imm8, M::DirIdxIndX, M::Imm8, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Stk, M::ImmM, M::Acc, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // 0
|
|
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::Dir, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Acc, M::Imp, M::Abs, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 1
|
|
M::Abs, M::DirIdxIndX, M::AbsLng, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Stk, M::ImmM, M::Acc, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // 2
|
|
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::DirIdxX, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Acc, M::Imp, M::AbsIdxX, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 3
|
|
M::Stk, M::DirIdxIndX, M::Imm8, M::StkRel, M::BlkMov, M::Dir, M::Dir, M::DirIndLng, M::Stk, M::ImmM, M::Acc, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // 4
|
|
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::BlkMov, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Stk, M::Imp, M::AbsLng, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 5
|
|
M::Stk, M::DirIdxIndX, M::RelLng, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Stk, M::ImmM, M::Acc, M::Stk, M::AbsInd, M::Abs, M::Abs, M::AbsLng, // 6
|
|
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::DirIdxX, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Stk, M::Imp, M::AbsIdxXInd, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 7
|
|
M::Rel, M::DirIdxIndX, M::RelLng, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Imp, M::ImmM, M::Imp, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // 8
|
|
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::DirIdxX, M::DirIdxX, M::DirIdxY, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Imp, M::Imp, M::Abs, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 9
|
|
M::ImmX, M::DirIdxIndX, M::ImmX, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Imp, M::ImmM, M::Imp, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // A
|
|
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::DirIdxX, M::DirIdxX, M::DirIdxY, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Imp, M::Imp, M::AbsIdxX, M::AbsIdxX, M::AbsIdxY, M::AbsLngIdxX, // B
|
|
M::ImmX, M::DirIdxIndX, M::Imm8, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Imp, M::ImmM, M::Imp, M::Imp, M::Abs, M::Abs, M::Abs, M::AbsLng, // C
|
|
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::Dir, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Stk, M::Imp, M::AbsIndLng, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // D
|
|
M::ImmX, M::DirIdxIndX, M::Imm8, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Imp, M::ImmM, M::Imp, M::Imp, M::Abs, M::Abs, M::Abs, M::AbsLng, // E
|
|
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::Imm16, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Stk, M::Imp, M::AbsIdxXInd, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX // F
|
|
}; |