6502bench/Asm65/CpuDef.cs

1503 lines
62 KiB
C#

/*
* Copyright 2018 faddenSoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Diagnostics;
namespace Asm65 {
/// <summary>
/// CPU definition. Includes a set of 256 opcodes.
/// </summary>
public class CpuDef {
/// <summary>
/// Human-readable name.
/// </summary>
public string Name { get; private set; }
/// <summary>
/// Maximum possible address.
/// </summary>
public int MaxAddressValue { get; private set; }
/// <summary>
/// Does this CPU have a 16-bit address space?
/// </summary>
public bool HasAddr16 { get { return MaxAddressValue <= 0xffff; } }
/// <summary>
/// Does this CPU support the emulation flag (65802/65816)?
/// </summary>
public bool HasEmuFlag { get; private set; }
/// <summary>
/// CPU type value.
/// </summary>
public CpuType Type { get; private set; }
/// <summary>
/// True if undocumented opcodes are included. (This does not mean that the CPU has
/// undocumented opcodes, only that they haven't been stripped out if they exist.)
/// </summary>
public bool HasUndocumented { get; private set; }
/// <summary>
/// Instruction set, 256 entries.
/// </summary>
private OpDef[] mOpDefs;
/// <summary>
/// Cycle counts, 256 entries.
/// </summary>
private int[] mCycleCounts;
/// <summary>
/// Cycle count modifiers, 256 entries.
/// </summary>
private OpDef.CycleMod[] mCycleMods;
/// <summary>
/// List of "interesting" CPUs. These will be presented in the system definition
/// file when starting a new project. The actual set of CPUs that are unique (from
/// our perspective) is much smaller, as most of these can be represented accurately
/// (for disassembly purposes) by a handful of archetypes.
/// </summary>
public enum CpuType {
CpuUnknown = 0,
Cpu6502, // Apple ][+
Cpu6502B, // Atari 800
Cpu6507, // Atari 2600
Cpu6502C, // Atari 5200
Cpu6510, // Commodore 64
Cpu8502, // Commodore 128
Cpu2A03, // NES
Cpu65C02, // Apple //e
Cpu65SC02, // Atari Lynx
CpuW65C02, // ?
Cpu65802, // ?
Cpu65816, // Apple IIgs
Cpu5A22 // SNES
}
/// <summary>
/// Converts a CPU type name string to a CpuType value. Used for deserialization.
/// </summary>
/// <param name="name">Case-sensitive CPU name</param>
/// <returns>CpuType value, or CpuUnknown if name wasn't recognized.</returns>
public static CpuType GetCpuTypeFromName(string name) {
switch (name) {
case "6502": return CpuType.Cpu6502;
case "6502B": return CpuType.Cpu6502B;
case "6502C": return CpuType.Cpu6502C;
case "6507": return CpuType.Cpu6507;
case "6510": return CpuType.Cpu6510;
case "8502": return CpuType.Cpu8502;
case "2A03": return CpuType.Cpu2A03;
case "65C02": return CpuType.Cpu65C02;
case "65SC02": return CpuType.Cpu65SC02;
case "W65C02": return CpuType.CpuW65C02;
case "65802": return CpuType.Cpu65802;
case "65816": return CpuType.Cpu65816;
case "5A22": return CpuType.Cpu5A22;
default:
return CpuType.CpuUnknown;
}
}
/// <summary>
/// Converts a CpuType value to a CPU type name string. Used for serialization.
/// </summary>
/// <param name="type">CPU type.</param>
/// <returns>CPU name string.</returns>
public static string GetCpuNameFromType(CpuType type) {
switch (type) {
case CpuType.Cpu6502: return "6502";
case CpuType.Cpu6502B: return "6502B";
case CpuType.Cpu6502C: return "6502C";
case CpuType.Cpu6507: return "6507";
case CpuType.Cpu6510: return "6510";
case CpuType.Cpu8502: return "8502";
case CpuType.Cpu2A03: return "2A03";
case CpuType.Cpu65C02: return "65C02";
case CpuType.Cpu65SC02: return "65SC02";
case CpuType.CpuW65C02: return "W65C02";
case CpuType.Cpu65802: return "65802";
case CpuType.Cpu65816: return "65816";
case CpuType.Cpu5A22: return "5A22";
default:
return "65??";
}
}
/// <summary>
/// Generates a CpuDef that best matches the parameters.
/// </summary>
/// <param name="type">Specific CPU we want.</param>
/// <param name="includeUndocumented">Set to true if "undocumented" opcodes should
/// be included in the definition.</param>
/// <returns>Best CpuDef.</returns>
public static CpuDef GetBestMatch(CpuType type, bool includeUndocumented,
bool twoByteBrk) {
// Many 65xx variants boil down to a 6502, 65C02, or 65816, at least as far as
// a disassembler needs to know. WDC's W65C02 has the Rockwell extensions plus
// a couple more, so it works for the extended 65C02 variants.
//
// These don't strictly fit, and would need full definitions:
//
// Hudson Soft HuC6280 (PC Engine / TurboGrafx)
// Commodore CSG 4510 / CSG 65CE02 (Amiga A2232 serial port; 4510 has one
// additional instruction, so use that as archetype)
// Jeri's 65DTV02 (used in C64DTV single-chip computer); same as 6502 with
// some differences in illegal opcodes
// Eloraam 65EL02 (defined in a Minecraft-based emulator)
CpuDef cpuDef;
switch (type) {
case CpuType.Cpu65802:
case CpuType.Cpu65816:
case CpuType.Cpu5A22:
cpuDef = Cpu65816;
break;
case CpuType.Cpu65C02:
case CpuType.Cpu65SC02:
cpuDef = Cpu65C02;
break;
case CpuType.CpuW65C02:
cpuDef = CpuW65C02;
break;
default:
// 6502, 6502B, 6502C, 6507, 6510, 8502, 2A03
cpuDef = Cpu6502;
break;
}
cpuDef.GenerateCycleCounts();
// If we don't want undocumented opcodes, strip them out of the definition.
// Entries are replaced with OpInvalid.
if (!includeUndocumented) {
CpuDef stripped = new CpuDef(cpuDef);
for (int i = 0; i < 256; i++) {
if (cpuDef.mOpDefs[i].IsUndocumented) {
stripped.mOpDefs[i] = OpDef.OpInvalid;
} else {
stripped.mOpDefs[i] = cpuDef.mOpDefs[i];
}
}
cpuDef = stripped;
}
// If we want two-byte BRKs, replace the entry with the StackInt form. Copy the rest.
if (twoByteBrk) {
CpuDef bigBrkDef = new CpuDef(cpuDef);
bigBrkDef.mOpDefs[0] = OpDef.OpBRK_StackInt;
for (int i = 1; i < 256; i++) {
bigBrkDef.mOpDefs[i] = cpuDef.mOpDefs[i];
}
cpuDef = bigBrkDef;
}
cpuDef.HasUndocumented = includeUndocumented;
return cpuDef;
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="name">Human-readable name.</param>
/// <param name="maxAddressValue">Address space bits (16 or 24).</param>
private CpuDef(string name, int maxAddressValue, bool hasEmuFlag) {
Name = name;
MaxAddressValue = maxAddressValue;
HasEmuFlag = hasEmuFlag;
HasUndocumented = true;
}
/// <summary>
/// Copy constructor. Does not copy the contents of mOpDefs. Only used internally.
/// </summary>
/// <param name="src">Object to copy from.</param>
private CpuDef(CpuDef src) {
Name = src.Name;
MaxAddressValue = src.MaxAddressValue;
HasEmuFlag = src.HasEmuFlag;
Type = src.Type;
mCycleCounts = src.mCycleCounts;
mCycleMods = src.mCycleMods;
mOpDefs = new OpDef[256];
}
/// <summary>
/// Returns an entry from the OpDef array for the specified opcode, 0-255.
/// </summary>
/// <param name="op">Instruction opcode number (0-255).</param>
/// <returns>Instruction definition.</returns>
public OpDef GetOpDef(int op) { return mOpDefs[op]; }
/// <summary>
/// Returns the set of cycle mods for the given instruction that are in effect
/// for the current CPU.
/// </summary>
/// <param name="op">Instruction opcode number (0-255).</param>
/// <returns>Reduced cycle mod set.</returns>
public OpDef.CycleMod GetOpCycleMod(int op) { return mCycleMods[op]; }
/// <summary>
/// Indexer. Returns the definition of opcode N.
/// </summary>
public OpDef this[int op] {
get { return mOpDefs[op]; }
}
/// <summary>
/// Returns the number of cycles required to execute the instruction. If the value
/// is negative, the negated value represents the minimum number of cycles for an
/// instruction with variable timing.
///
/// The value returned will factor in any CPU-specific aspects.
/// </summary>
/// <param name="opNum">Instruction opcode value.</param>
/// <returns>Cycle count.</returns>
public int GetCycles(int opNum, StatusFlags flags, OpDef.BranchTaken branchTaken,
bool branchCrossesPage) {
// The irrelevant modifiers have already been stripped out, e.g. OneIfD1 only
// affects the 65C02.
OpDef.CycleMod mods = mCycleMods[opNum];
int cycles = mCycleCounts[opNum];
// Walk through the various cycle mods. If we can evaluate them definitively,
// do so now and remove them from the set.
// The M/X flags are defined to be in one state or the other, even when the flag
// value is indeterminate, because we have to be able to size immediate operands
// appropriately. So there's no ambiguity here even when there's ambiguity. We
// make a similar statement about the E flag.
if ((mods & OpDef.CycleMod.OneIfM0) != 0) {
if (!flags.IsShortM) {
cycles++;
}
mods &= ~OpDef.CycleMod.OneIfM0;
}
if ((mods & OpDef.CycleMod.TwoIfM0) != 0) {
if (!flags.IsShortM) {
cycles += 2;
}
mods &= ~OpDef.CycleMod.TwoIfM0;
}
if ((mods & OpDef.CycleMod.OneIfX0) != 0) {
if (!flags.IsShortX) {
cycles++;
}
mods &= ~OpDef.CycleMod.OneIfX0;
}
if ((mods & OpDef.CycleMod.OneIfE0) != 0) {
if (!flags.IsEmulationMode) {
cycles++;
}
mods &= ~OpDef.CycleMod.OneIfE0;
}
// Some of these can be known, some can't.
if ((mods & OpDef.CycleMod.OneIfD1) != 0) {
if (flags.D == 1) {
cycles++;
}
if (flags.D == 0 || flags.D == 1) {
mods &= ~OpDef.CycleMod.OneIfD1;
}
}
if ((mods & OpDef.CycleMod.OneIfBranchTaken) != 0) {
if (branchTaken == OpDef.BranchTaken.Always) {
cycles++;
}
if (branchTaken != OpDef.BranchTaken.Indeterminate) {
mods &= ~OpDef.CycleMod.OneIfBranchTaken;
}
}
if ((mods & OpDef.CycleMod.OneIfBranchPage) != 0) {
if (branchCrossesPage && flags.IsEmulationMode) {
cycles++; // +1 unless we're in native mode on 65816
}
mods &= ~OpDef.CycleMod.OneIfBranchPage;
}
// We can't evaluate OneIfDpNonzero, OneIfIndexPage, or MinusOneIfNoPage.
// OneIf65C02 was handled earlier.
// TODO(maybe): in some cases we can know that the index doesn't cross a
// page boundary by checking the address, e.g. "LDA $2000,X" can't cross.
if (mods != 0) {
// Some unresolved mods remain.
cycles = -cycles;
}
return cycles;
}
/// <summary>
/// Consistency test.
/// </summary>
/// <returns>True on success.</returns>
public static bool DebugValidate() {
InternalValidate(Cpu6502);
InternalValidate(Cpu65C02);
InternalValidate(CpuW65C02);
InternalValidate(Cpu65816);
Debug.WriteLine("CpuDef: tests successful");
return true;
}
private static void InternalValidate(CpuDef cdef) {
for (int i = 0; i < 256; i++) {
OpDef op = cdef.mOpDefs[i];
if (op.Opcode != i && op.AddrMode != OpDef.AddressMode.Unknown) {
throw new Exception("CpuDef for " + cdef.Type + ": entry 0x" +
i.ToString("x") + " has value " + op.Opcode.ToString("x"));
}
if (op.AddrMode != OpDef.AddressMode.Unknown && op.Cycles == 0) {
throw new Exception("Instruction 0x" + i.ToString("x2") + ": " +
op + " missing cycles");
}
}
}
public override string ToString() {
return Name + " (has16=" + HasAddr16 + ", hasEmu=" + HasEmuFlag + ", hasUndoc=" +
HasUndocumented + ")";
}
/// <summary>
/// Generates the mCycleCounts and mCycleMods arrays.
/// </summary>
private void GenerateCycleCounts() {
if (mCycleCounts != null) {
return;
}
mCycleCounts = new int[256];
mCycleMods = new OpDef.CycleMod[256];
// Figure out which mods apply for this CPU.
OpDef.CycleMod ignoreMask = 0;
switch (Type) {
case CpuType.Cpu6502:
ignoreMask = OpDef.CycleMod.OneIfM0 |
OpDef.CycleMod.TwoIfM0 |
OpDef.CycleMod.OneIfX0 |
OpDef.CycleMod.OneIfDpNonzero |
OpDef.CycleMod.OneIfD1 |
OpDef.CycleMod.OneIfE0 |
OpDef.CycleMod.OneIf65C02 |
OpDef.CycleMod.MinusOneIfNoPage |
OpDef.CycleMod.BlockMove;
break;
case CpuType.Cpu65C02:
case CpuType.CpuW65C02:
ignoreMask = OpDef.CycleMod.OneIfM0 |
OpDef.CycleMod.TwoIfM0 |
OpDef.CycleMod.OneIfX0 |
OpDef.CycleMod.OneIfDpNonzero |
OpDef.CycleMod.OneIfE0 |
OpDef.CycleMod.BlockMove;
break;
case CpuType.Cpu65816:
ignoreMask = OpDef.CycleMod.OneIfD1 |
OpDef.CycleMod.OneIf65C02 |
OpDef.CycleMod.MinusOneIfNoPage;
break;
default:
Debug.Assert(false, "unsupported cpu type " + Type);
return;
}
// If an instruction has one or more applicable mods, declare it as variable.
for (int i = 0; i < 256; i++) {
OpDef op = mOpDefs[i];
int baseCycles = op.Cycles;
OpDef.CycleMod mods = op.CycleMods & ~ignoreMask;
if ((mods & OpDef.CycleMod.OneIf65C02) != 0) {
// This isn't variable -- the instruction always takes one cycle longer
// on the 65C02. (Applies to $6C, JMP (addr).)
Debug.Assert(Type == CpuType.Cpu65C02 || Type == CpuType.CpuW65C02);
baseCycles++;
mods &= ~OpDef.CycleMod.OneIf65C02;
}
mCycleCounts[i] = baseCycles;
mCycleMods[i] = mods;
}
}
// Classic MOS 6502, with full set of undocumented opcodes.
private static CpuDef Cpu6502 { get; } = new CpuDef("MOS 6502", (1 << 16) - 1, false) {
Type = CpuType.Cpu6502,
mOpDefs = new OpDef[] {
OpDef.OpBRK_Implied, // 0x00
OpDef.OpORA_DPIndexXInd,
OpDef.GenerateUndoc(0x02, OpDef.OpJAM_Implied),
OpDef.OpSLO_DPIndexXInd,
OpDef.GenerateUndoc(0x04, OpDef.OpDOP_DP),
OpDef.OpORA_DP,
OpDef.OpASL_DP,
OpDef.OpSLO_DP,
OpDef.OpPHP_StackPush, // 0x08
OpDef.OpORA_Imm,
OpDef.OpASL_Acc,
OpDef.GenerateUndoc(0x0b, OpDef.OpANC_Imm),
OpDef.OpTOP_Abs,
OpDef.OpORA_Abs,
OpDef.OpASL_Abs,
OpDef.OpSLO_Absolute,
OpDef.OpBPL_PCRel, // 0x10
OpDef.OpORA_DPIndIndexY,
OpDef.GenerateUndoc(0x12, OpDef.OpJAM_Implied),
OpDef.OpSLO_DPIndIndexY,
OpDef.GenerateUndoc(0x14, OpDef.OpDOP_DPIndexX),
OpDef.OpORA_DPIndexX,
OpDef.OpASL_DPIndexX,
OpDef.OpSLO_DPIndexX,
OpDef.OpCLC_Implied, // 0x18
OpDef.OpORA_AbsIndexY,
OpDef.GenerateUndoc(0x1a, OpDef.OpNOP_Implied),
OpDef.OpSLO_AbsIndexY,
OpDef.GenerateUndoc(0x1c, OpDef.OpTOP_AbsIndeX),
OpDef.OpORA_AbsIndexX,
OpDef.OpASL_AbsIndexX,
OpDef.OpSLO_AbsIndexX,
OpDef.OpJSR_Abs, // 0x20
OpDef.OpAND_DPIndexXInd,
OpDef.GenerateUndoc(0x22, OpDef.OpJAM_Implied),
OpDef.OpRLA_DPIndexXInd,
OpDef.OpBIT_DP,
OpDef.OpAND_DP,
OpDef.OpROL_DP,
OpDef.OpRLA_DP,
OpDef.OpPLP_StackPull, // 0x28
OpDef.OpAND_Imm,
OpDef.OpROL_Acc,
OpDef.GenerateUndoc(0x2b, OpDef.OpANC_Imm),
OpDef.OpBIT_Abs,
OpDef.OpAND_Abs,
OpDef.OpROL_Abs,
OpDef.OpRLA_Absolute,
OpDef.OpBMI_PCRel, // 0x30
OpDef.OpAND_DPIndIndexY,
OpDef.GenerateUndoc(0x32, OpDef.OpJAM_Implied),
OpDef.OpRLA_DPIndIndexY,
OpDef.GenerateUndoc(0x34, OpDef.OpDOP_DPIndexX),
OpDef.OpAND_DPIndexX,
OpDef.OpROL_DPIndexX,
OpDef.OpRLA_DPIndexX,
OpDef.OpSEC_Implied, // 0x38
OpDef.OpAND_AbsIndexY,
OpDef.GenerateUndoc(0x3a, OpDef.OpNOP_Implied),
OpDef.OpRLA_AbsIndexY,
OpDef.GenerateUndoc(0x3c, OpDef.OpTOP_AbsIndeX),
OpDef.OpAND_AbsIndexX,
OpDef.OpROL_AbsIndexX,
OpDef.OpRLA_AbsIndexX,
OpDef.OpRTI_StackRTI, // 0x40
OpDef.OpEOR_DPIndexXInd,
OpDef.GenerateUndoc(0x42, OpDef.OpJAM_Implied),
OpDef.OpSRE_DPIndexXInd,
OpDef.GenerateUndoc(0x44, OpDef.OpDOP_DP),
OpDef.OpEOR_DP,
OpDef.OpLSR_DP,
OpDef.OpSRE_DP,
OpDef.OpPHA_StackPush, // 0x48
OpDef.OpEOR_Imm,
OpDef.OpLSR_Acc,
OpDef.OpALR_Imm,
OpDef.OpJMP_Abs,
OpDef.OpEOR_Abs,
OpDef.OpLSR_Abs,
OpDef.OpSRE_Absolute,
OpDef.OpBVC_PCRel, // 0x50
OpDef.OpEOR_DPIndIndexY,
OpDef.GenerateUndoc(0x52, OpDef.OpJAM_Implied),
OpDef.OpSRE_DPIndIndexY,
OpDef.GenerateUndoc(0x54, OpDef.OpDOP_DPIndexX),
OpDef.OpEOR_DPIndexX,
OpDef.OpLSR_DPIndexX,
OpDef.OpSRE_DPIndexX,
OpDef.OpCLI_Implied, // 0x58
OpDef.OpEOR_AbsIndexY,
OpDef.GenerateUndoc(0x5a, OpDef.OpNOP_Implied),
OpDef.OpSRE_AbsIndexY,
OpDef.GenerateUndoc(0x5c, OpDef.OpTOP_AbsIndeX),
OpDef.OpEOR_AbsIndexX,
OpDef.OpLSR_AbsIndexX,
OpDef.OpSRE_AbsIndexX,
OpDef.OpRTS_StackRTS, // 0x60
OpDef.OpADC_DPIndexXInd,
OpDef.GenerateUndoc(0x62, OpDef.OpJAM_Implied),
OpDef.OpRRA_DPIndexXInd,
OpDef.GenerateUndoc(0x64, OpDef.OpDOP_DP),
OpDef.OpADC_DP,
OpDef.OpROR_DP,
OpDef.OpRRA_DP,
OpDef.OpPLA_StackPull, // 0x68
OpDef.OpADC_Imm,
OpDef.OpROR_Acc,
OpDef.OpARR_Imm,
OpDef.OpJMP_AbsInd,
OpDef.OpADC_Abs,
OpDef.OpROR_Abs,
OpDef.OpRRA_Absolute,
OpDef.OpBVS_PCRel, // 0x70
OpDef.OpADC_DPIndIndexY,
OpDef.GenerateUndoc(0x72, OpDef.OpJAM_Implied),
OpDef.OpRRA_DPIndIndexY,
OpDef.GenerateUndoc(0x74, OpDef.OpDOP_DPIndexX),
OpDef.OpADC_DPIndexX,
OpDef.OpROR_DPIndexX,
OpDef.OpRRA_DPIndexX,
OpDef.OpSEI_Implied, // 0x78
OpDef.OpADC_AbsIndexY,
OpDef.GenerateUndoc(0x7a, OpDef.OpNOP_Implied),
OpDef.OpRRA_AbsIndexY,
OpDef.GenerateUndoc(0x7c, OpDef.OpTOP_AbsIndeX),
OpDef.OpADC_AbsIndexX,
OpDef.OpROR_AbsIndexX,
OpDef.OpRRA_AbsIndexX,
OpDef.GenerateUndoc(0x80, OpDef.OpDOP_Imm), // 0x80
OpDef.OpSTA_DPIndexXInd,
OpDef.GenerateUndoc(0x82, OpDef.OpDOP_Imm),
OpDef.OpSAX_DPIndexXInd,
OpDef.OpSTY_DP,
OpDef.OpSTA_DP,
OpDef.OpSTX_DP,
OpDef.OpSAX_DP,
OpDef.OpDEY_Implied, // 0x88
OpDef.GenerateUndoc(0x89, OpDef.OpDOP_Imm),
OpDef.OpTXA_Implied,
OpDef.OpANE_Imm,
OpDef.OpSTY_Abs,
OpDef.OpSTA_Abs,
OpDef.OpSTX_Abs,
OpDef.OpSAX_Absolute,
OpDef.OpBCC_PCRel, // 0x90
OpDef.OpSTA_DPIndIndexY,
OpDef.GenerateUndoc(0x92, OpDef.OpJAM_Implied),
OpDef.OpSHA_DPIndIndexY,
OpDef.OpSTY_DPIndexX,
OpDef.OpSTA_DPIndexX,
OpDef.OpSTX_DPIndexY,
OpDef.OpSAX_DPIndexY,
OpDef.OpTYA_Implied, // 0x98
OpDef.OpSTA_AbsIndexY,
OpDef.OpTXS_Implied,
OpDef.OpTAS_AbsIndexY,
OpDef.OpSHY_AbsIndexX,
OpDef.OpSTA_AbsIndexX,
OpDef.OpSHX_AbsIndexY,
OpDef.OpSHA_AbsIndexY,
OpDef.OpLDY_Imm, // 0xa0
OpDef.OpLDA_DPIndexXInd,
OpDef.OpLDX_Imm,
OpDef.OpLAX_DPIndexXInd,
OpDef.OpLDY_DP,
OpDef.OpLDA_DP,
OpDef.OpLDX_DP,
OpDef.OpLAX_DP,
OpDef.OpTAY_Implied, // 0xa8
OpDef.OpLDA_Imm,
OpDef.OpTAX_Implied,
OpDef.OpLAX_Imm,
OpDef.OpLDY_Abs,
OpDef.OpLDA_Abs,
OpDef.OpLDX_Abs,
OpDef.OpLAX_Absolute,
OpDef.OpBCS_PCRel, // 0xb0
OpDef.OpLDA_DPIndIndexY,
OpDef.GenerateUndoc(0xb2, OpDef.OpJAM_Implied),
OpDef.OpLAX_DPIndIndexY,
OpDef.OpLDY_DPIndexX,
OpDef.OpLDA_DPIndexX,
OpDef.OpLDX_DPIndexY,
OpDef.OpLAX_DPIndexY,
OpDef.OpCLV_Implied, // 0xb8
OpDef.OpLDA_AbsIndexY,
OpDef.OpTSX_Implied,
OpDef.OpLAS_AbsIndexY,
OpDef.OpLDY_AbsIndexX,
OpDef.OpLDA_AbsIndexX,
OpDef.OpLDX_AbsIndexY,
OpDef.OpLAX_AbsIndexY,
OpDef.OpCPY_Imm, // 0xc0
OpDef.OpCMP_DPIndexXInd,
OpDef.GenerateUndoc(0xc2, OpDef.OpDOP_Imm),
OpDef.OpDCP_DPIndexXInd,
OpDef.OpCPY_DP,
OpDef.OpCMP_DP,
OpDef.OpDEC_DP,
OpDef.OpDCP_DP,
OpDef.OpINY_Implied, // 0xc8
OpDef.OpCMP_Imm,
OpDef.OpDEX_Implied,
OpDef.OpSBX_Imm,
OpDef.OpCPY_Abs,
OpDef.OpCMP_Abs,
OpDef.OpDEC_Abs,
OpDef.OpDCP_Abs,
OpDef.OpBNE_PCRel, // 0xd0
OpDef.OpCMP_DPIndIndexY,
OpDef.GenerateUndoc(0xd2, OpDef.OpJAM_Implied),
OpDef.OpDCP_DPIndIndexY,
OpDef.GenerateUndoc(0xd4, OpDef.OpDOP_DPIndexX),
OpDef.OpCMP_DPIndexX,
OpDef.OpDEC_DPIndexX,
OpDef.OpDCP_DPIndexX,
OpDef.OpCLD_Implied, // 0xd8
OpDef.OpCMP_AbsIndexY,
OpDef.GenerateUndoc(0xda, OpDef.OpNOP_Implied),
OpDef.OpDCP_AbsIndexY,
OpDef.GenerateUndoc(0xdc, OpDef.OpTOP_AbsIndeX),
OpDef.OpCMP_AbsIndexX,
OpDef.OpDEC_AbsIndexX,
OpDef.OpDCP_AbsIndexX,
OpDef.OpCPX_Imm, // 0xe0
OpDef.OpSBC_DPIndexXInd,
OpDef.GenerateUndoc(0xe2, OpDef.OpDOP_Imm),
OpDef.OpISC_DPIndexXInd,
OpDef.OpCPX_DP,
OpDef.OpSBC_DP,
OpDef.OpINC_DP,
OpDef.OpISC_DP,
OpDef.OpINX_Implied, // 0xe8
OpDef.OpSBC_Imm,
OpDef.OpNOP_Implied,
OpDef.GenerateUndoc(0xeb, OpDef.OpSBC_Imm),
OpDef.OpCPX_Abs,
OpDef.OpSBC_Abs,
OpDef.OpINC_Abs,
OpDef.OpISC_Abs,
OpDef.OpBEQ_PCRel, // 0xf0
OpDef.OpSBC_DPIndIndexY,
OpDef.GenerateUndoc(0xf2, OpDef.OpJAM_Implied),
OpDef.OpISC_DPIndIndexY,
OpDef.GenerateUndoc(0xf4, OpDef.OpDOP_DPIndexX),
OpDef.OpSBC_DPIndexX,
OpDef.OpINC_DPIndexX,
OpDef.OpISC_DPIndexX,
OpDef.OpSED_Implied, // 0xf8
OpDef.OpSBC_AbsIndexY,
OpDef.GenerateUndoc(0xfa, OpDef.OpNOP_Implied),
OpDef.OpISC_AbsIndexY,
OpDef.GenerateUndoc(0xfc, OpDef.OpTOP_AbsIndeX),
OpDef.OpSBC_AbsIndexX,
OpDef.OpINC_AbsIndexX,
OpDef.OpISC_AbsIndexX,
}
};
// Original 65C02, with new opcodes and a handful of slightly strange NOPs.
private static CpuDef Cpu65C02 { get; } = new CpuDef("WDC 65C02", (1 << 16) - 1, false) {
Type = CpuType.Cpu65C02,
mOpDefs = new OpDef[] {
OpDef.OpBRK_Implied, // 0x00
OpDef.OpORA_DPIndexXInd,
OpDef.GenerateUndoc(0x02, OpDef.OpLDD_Imm),
OpDef.GenerateUndoc(0x03, OpDef.OpNOP_65C02),
OpDef.OpTSB_DP,
OpDef.OpORA_DP,
OpDef.OpASL_DP,
OpDef.GenerateUndoc(0x07, OpDef.OpNOP_65C02),
OpDef.OpPHP_StackPush, // 0x08
OpDef.OpORA_Imm,
OpDef.OpASL_Acc,
OpDef.GenerateUndoc(0x0b, OpDef.OpNOP_65C02),
OpDef.OpTSB_Abs,
OpDef.OpORA_Abs,
OpDef.OpASL_Abs,
OpDef.GenerateUndoc(0x0f, OpDef.OpNOP_65C02),
OpDef.OpBPL_PCRel, // 0x10
OpDef.OpORA_DPIndIndexY,
OpDef.OpORA_DPInd,
OpDef.GenerateUndoc(0x13, OpDef.OpNOP_65C02),
OpDef.OpTRB_DP,
OpDef.OpORA_DPIndexX,
OpDef.OpASL_DPIndexX,
OpDef.GenerateUndoc(0x17, OpDef.OpNOP_65C02),
OpDef.OpCLC_Implied, // 0x18
OpDef.OpORA_AbsIndexY,
OpDef.OpINC_Acc,
OpDef.GenerateUndoc(0x1b, OpDef.OpNOP_65C02),
OpDef.OpTRB_Abs,
OpDef.OpORA_AbsIndexX,
OpDef.OpASL_AbsIndexX,
OpDef.GenerateUndoc(0x1f, OpDef.OpNOP_65C02),
OpDef.OpJSR_Abs, // 0x20
OpDef.OpAND_DPIndexXInd,
OpDef.GenerateUndoc(0x22, OpDef.OpLDD_Imm),
OpDef.GenerateUndoc(0x23, OpDef.OpNOP_65C02),
OpDef.OpBIT_DP,
OpDef.OpAND_DP,
OpDef.OpROL_DP,
OpDef.GenerateUndoc(0x27, OpDef.OpNOP_65C02),
OpDef.OpPLP_StackPull, // 0x28
OpDef.OpAND_Imm,
OpDef.OpROL_Acc,
OpDef.GenerateUndoc(0x2b, OpDef.OpNOP_65C02),
OpDef.OpBIT_Abs,
OpDef.OpAND_Abs,
OpDef.OpROL_Abs,
OpDef.GenerateUndoc(0x2f, OpDef.OpNOP_65C02),
OpDef.OpBMI_PCRel, // 0x30
OpDef.OpAND_DPIndIndexY,
OpDef.OpAND_DPInd,
OpDef.GenerateUndoc(0x33, OpDef.OpNOP_65C02),
OpDef.OpBIT_DPIndexX,
OpDef.OpAND_DPIndexX,
OpDef.OpROL_DPIndexX,
OpDef.GenerateUndoc(0x37, OpDef.OpNOP_65C02),
OpDef.OpSEC_Implied, // 0x38
OpDef.OpAND_AbsIndexY,
OpDef.OpDEC_Acc,
OpDef.GenerateUndoc(0x3b, OpDef.OpNOP_65C02),
OpDef.OpBIT_AbsIndexX,
OpDef.OpAND_AbsIndexX,
OpDef.OpROL_AbsIndexX,
OpDef.GenerateUndoc(0x3f, OpDef.OpNOP_65C02),
OpDef.OpRTI_StackRTI, // 0x40
OpDef.OpEOR_DPIndexXInd,
OpDef.GenerateUndoc(0x42, OpDef.OpLDD_Imm),
OpDef.GenerateUndoc(0x43, OpDef.OpNOP_65C02),
OpDef.GenerateUndoc(0x44, OpDef.OpLDD_DP),
OpDef.OpEOR_DP,
OpDef.OpLSR_DP,
OpDef.GenerateUndoc(0x47, OpDef.OpNOP_65C02),
OpDef.OpPHA_StackPush, // 0x48
OpDef.OpEOR_Imm,
OpDef.OpLSR_Acc,
OpDef.GenerateUndoc(0x4b, OpDef.OpNOP_65C02),
OpDef.OpJMP_Abs,
OpDef.OpEOR_Abs,
OpDef.OpLSR_Abs,
OpDef.GenerateUndoc(0x4f, OpDef.OpNOP_65C02),
OpDef.OpBVC_PCRel, // 0x50
OpDef.OpEOR_DPIndIndexY,
OpDef.OpEOR_DPInd,
OpDef.GenerateUndoc(0x53, OpDef.OpNOP_65C02),
OpDef.GenerateUndoc(0x54, OpDef.OpLDD_DPIndexX),
OpDef.OpEOR_DPIndexX,
OpDef.OpLSR_DPIndexX,
OpDef.GenerateUndoc(0x57, OpDef.OpNOP_65C02),
OpDef.OpCLI_Implied, // 0x58
OpDef.OpEOR_AbsIndexY,
OpDef.OpPHY_StackPush,
OpDef.GenerateUndoc(0x5b, OpDef.OpNOP_65C02),
OpDef.GenerateUndoc(0x5c, OpDef.OpLDD_Weird),
OpDef.OpEOR_AbsIndexX,
OpDef.OpLSR_AbsIndexX,
OpDef.GenerateUndoc(0x5f, OpDef.OpNOP_65C02),
OpDef.OpRTS_StackRTS, // 0x60
OpDef.OpADC_DPIndexXInd,
OpDef.GenerateUndoc(0x62, OpDef.OpLDD_Imm),
OpDef.GenerateUndoc(0x63, OpDef.OpNOP_65C02),
OpDef.OpSTZ_DP,
OpDef.OpADC_DP,
OpDef.OpROR_DP,
OpDef.GenerateUndoc(0x67, OpDef.OpNOP_65C02),
OpDef.OpPLA_StackPull, // 0x68
OpDef.OpADC_Imm,
OpDef.OpROR_Acc,
OpDef.GenerateUndoc(0x6b, OpDef.OpNOP_65C02),
OpDef.OpJMP_AbsInd,
OpDef.OpADC_Abs,
OpDef.OpROR_Abs,
OpDef.GenerateUndoc(0x6f, OpDef.OpNOP_65C02),
OpDef.OpBVS_PCRel, // 0x70
OpDef.OpADC_DPIndIndexY,
OpDef.OpADC_DPInd,
OpDef.GenerateUndoc(0x73, OpDef.OpNOP_65C02),
OpDef.OpSTZ_DPIndexX,
OpDef.OpADC_DPIndexX,
OpDef.OpROR_DPIndexX,
OpDef.GenerateUndoc(0x77, OpDef.OpNOP_65C02),
OpDef.OpSEI_Implied, // 0x78
OpDef.OpADC_AbsIndexY,
OpDef.OpPLY_StackPull,
OpDef.GenerateUndoc(0x7b, OpDef.OpNOP_65C02),
OpDef.OpJMP_AbsIndexXInd,
OpDef.OpADC_AbsIndexX,
OpDef.OpROR_AbsIndexX,
OpDef.GenerateUndoc(0x7f, OpDef.OpNOP_65C02),
OpDef.OpBRA_PCRel, // 0x80
OpDef.OpSTA_DPIndexXInd,
OpDef.GenerateUndoc(0x82, OpDef.OpLDD_Imm),
OpDef.GenerateUndoc(0x83, OpDef.OpNOP_65C02),
OpDef.OpSTY_DP,
OpDef.OpSTA_DP,
OpDef.OpSTX_DP,
OpDef.GenerateUndoc(0x87, OpDef.OpNOP_65C02),
OpDef.OpDEY_Implied, // 0x88
OpDef.OpBIT_Imm,
OpDef.OpTXA_Implied,
OpDef.GenerateUndoc(0x8b, OpDef.OpNOP_65C02),
OpDef.OpSTY_Abs,
OpDef.OpSTA_Abs,
OpDef.OpSTX_Abs,
OpDef.GenerateUndoc(0x8f, OpDef.OpNOP_65C02),
OpDef.OpBCC_PCRel, // 0x90
OpDef.OpSTA_DPIndIndexY,
OpDef.OpSTA_DPInd,
OpDef.GenerateUndoc(0x93, OpDef.OpNOP_65C02),
OpDef.OpSTY_DPIndexX,
OpDef.OpSTA_DPIndexX,
OpDef.OpSTX_DPIndexY,
OpDef.GenerateUndoc(0x97, OpDef.OpNOP_65C02),
OpDef.OpTYA_Implied, // 0x98
OpDef.OpSTA_AbsIndexY,
OpDef.OpTXS_Implied,
OpDef.GenerateUndoc(0x9b, OpDef.OpNOP_65C02),
OpDef.OpSTZ_Abs,
OpDef.OpSTA_AbsIndexX,
OpDef.OpSTZ_AbsIndexX,
OpDef.GenerateUndoc(0x9f, OpDef.OpNOP_65C02),
OpDef.OpLDY_Imm, // 0xa0
OpDef.OpLDA_DPIndexXInd,
OpDef.OpLDX_Imm,
OpDef.GenerateUndoc(0xa3, OpDef.OpNOP_65C02),
OpDef.OpLDY_DP,
OpDef.OpLDA_DP,
OpDef.OpLDX_DP,
OpDef.GenerateUndoc(0xa7, OpDef.OpNOP_65C02),
OpDef.OpTAY_Implied, // 0xa8
OpDef.OpLDA_Imm,
OpDef.OpTAX_Implied,
OpDef.GenerateUndoc(0xab, OpDef.OpNOP_65C02),
OpDef.OpLDY_Abs,
OpDef.OpLDA_Abs,
OpDef.OpLDX_Abs,
OpDef.GenerateUndoc(0xaf, OpDef.OpNOP_65C02),
OpDef.OpBCS_PCRel, // 0xb0
OpDef.OpLDA_DPIndIndexY,
OpDef.OpLDA_DPInd,
OpDef.GenerateUndoc(0xb3, OpDef.OpNOP_65C02),
OpDef.OpLDY_DPIndexX,
OpDef.OpLDA_DPIndexX,
OpDef.OpLDX_DPIndexY,
OpDef.GenerateUndoc(0xb7, OpDef.OpNOP_65C02),
OpDef.OpCLV_Implied, // 0xb8
OpDef.OpLDA_AbsIndexY,
OpDef.OpTSX_Implied,
OpDef.GenerateUndoc(0xbb, OpDef.OpNOP_65C02),
OpDef.OpLDY_AbsIndexX,
OpDef.OpLDA_AbsIndexX,
OpDef.OpLDX_AbsIndexY,
OpDef.GenerateUndoc(0xbf, OpDef.OpNOP_65C02),
OpDef.OpCPY_Imm, // 0xc0
OpDef.OpCMP_DPIndexXInd,
OpDef.GenerateUndoc(0xc2, OpDef.OpLDD_Imm),
OpDef.GenerateUndoc(0xc3, OpDef.OpNOP_65C02),
OpDef.OpCPY_DP,
OpDef.OpCMP_DP,
OpDef.OpDEC_DP,
OpDef.GenerateUndoc(0xc7, OpDef.OpNOP_65C02),
OpDef.OpINY_Implied, // 0xc8
OpDef.OpCMP_Imm,
OpDef.OpDEX_Implied,
OpDef.GenerateUndoc(0xcb, OpDef.OpNOP_65C02),
OpDef.OpCPY_Abs,
OpDef.OpCMP_Abs,
OpDef.OpDEC_Abs,
OpDef.GenerateUndoc(0xcf, OpDef.OpNOP_65C02),
OpDef.OpBNE_PCRel, // 0xd0
OpDef.OpCMP_DPIndIndexY,
OpDef.OpCMP_DPInd,
OpDef.GenerateUndoc(0xd3, OpDef.OpNOP_65C02),
OpDef.GenerateUndoc(0xd4, OpDef.OpLDD_DPIndexX),
OpDef.OpCMP_DPIndexX,
OpDef.OpDEC_DPIndexX,
OpDef.GenerateUndoc(0xd7, OpDef.OpNOP_65C02),
OpDef.OpCLD_Implied, // 0xd8
OpDef.OpCMP_AbsIndexY,
OpDef.OpPHX_StackPush,
OpDef.GenerateUndoc(0xdb, OpDef.OpNOP_65C02),
OpDef.GenerateUndoc(0xdc, OpDef.OpLDD_Absolute),
OpDef.OpCMP_AbsIndexX,
OpDef.OpDEC_AbsIndexX,
OpDef.GenerateUndoc(0xdf, OpDef.OpNOP_65C02),
OpDef.OpCPX_Imm, // 0xe0
OpDef.OpSBC_DPIndexXInd,
OpDef.GenerateUndoc(0xe2, OpDef.OpLDD_Imm),
OpDef.GenerateUndoc(0xe3, OpDef.OpNOP_65C02),
OpDef.OpCPX_DP,
OpDef.OpSBC_DP,
OpDef.OpINC_DP,
OpDef.GenerateUndoc(0xe7, OpDef.OpNOP_65C02),
OpDef.OpINX_Implied, // 0xe8
OpDef.OpSBC_Imm,
OpDef.OpNOP_Implied,
OpDef.GenerateUndoc(0xeb, OpDef.OpNOP_65C02),
OpDef.OpCPX_Abs,
OpDef.OpSBC_Abs,
OpDef.OpINC_Abs,
OpDef.GenerateUndoc(0xef, OpDef.OpNOP_65C02),
OpDef.OpBEQ_PCRel, // 0xf0
OpDef.OpSBC_DPIndIndexY,
OpDef.OpSBC_DPInd,
OpDef.GenerateUndoc(0xf3, OpDef.OpNOP_65C02),
OpDef.GenerateUndoc(0xf4, OpDef.OpLDD_DPIndexX),
OpDef.OpSBC_DPIndexX,
OpDef.OpINC_DPIndexX,
OpDef.GenerateUndoc(0xf7, OpDef.OpNOP_65C02),
OpDef.OpSED_Implied, // 0xf8
OpDef.OpSBC_AbsIndexY,
OpDef.OpPLX_StackPull,
OpDef.GenerateUndoc(0xfb, OpDef.OpNOP_65C02),
OpDef.GenerateUndoc(0xfc, OpDef.OpLDD_Absolute),
OpDef.OpSBC_AbsIndexX,
OpDef.OpINC_AbsIndexX,
OpDef.GenerateUndoc(0xff, OpDef.OpNOP_65C02),
}
};
// WDC's W65C02, with the Rockwell extensions and STP/WAI. I'm assuming that the
// behavior of the undocumented instructions remains unchanged, which is probably unwise
// but I have no information to the contrary.
private static CpuDef CpuW65C02 { get; } = new CpuDef("WDC W65C02S", (1 << 16) - 1, false) {
Type = CpuType.CpuW65C02,
mOpDefs = new OpDef[] {
OpDef.OpBRK_Implied, // 0x00
OpDef.OpORA_DPIndexXInd,
OpDef.GenerateUndoc(0x02, OpDef.OpLDD_Imm),
OpDef.GenerateUndoc(0x03, OpDef.OpNOP_65C02),
OpDef.OpTSB_DP,
OpDef.OpORA_DP,
OpDef.OpASL_DP,
OpDef.OpRMB0_DP,
OpDef.OpPHP_StackPush, // 0x08
OpDef.OpORA_Imm,
OpDef.OpASL_Acc,
OpDef.GenerateUndoc(0x0b, OpDef.OpNOP_65C02),
OpDef.OpTSB_Abs,
OpDef.OpORA_Abs,
OpDef.OpASL_Abs,
OpDef.OpBBR0_DPPCRel,
OpDef.OpBPL_PCRel, // 0x10
OpDef.OpORA_DPIndIndexY,
OpDef.OpORA_DPInd,
OpDef.GenerateUndoc(0x13, OpDef.OpNOP_65C02),
OpDef.OpTRB_DP,
OpDef.OpORA_DPIndexX,
OpDef.OpASL_DPIndexX,
OpDef.OpRMB1_DP,
OpDef.OpCLC_Implied, // 0x18
OpDef.OpORA_AbsIndexY,
OpDef.OpINC_Acc,
OpDef.GenerateUndoc(0x1b, OpDef.OpNOP_65C02),
OpDef.OpTRB_Abs,
OpDef.OpORA_AbsIndexX,
OpDef.OpASL_AbsIndexX,
OpDef.OpBBR1_DPPCRel,
OpDef.OpJSR_Abs, // 0x20
OpDef.OpAND_DPIndexXInd,
OpDef.GenerateUndoc(0x22, OpDef.OpLDD_Imm),
OpDef.GenerateUndoc(0x23, OpDef.OpNOP_65C02),
OpDef.OpBIT_DP,
OpDef.OpAND_DP,
OpDef.OpROL_DP,
OpDef.OpRMB2_DP,
OpDef.OpPLP_StackPull, // 0x28
OpDef.OpAND_Imm,
OpDef.OpROL_Acc,
OpDef.GenerateUndoc(0x2b, OpDef.OpNOP_65C02),
OpDef.OpBIT_Abs,
OpDef.OpAND_Abs,
OpDef.OpROL_Abs,
OpDef.OpBBR2_DPPCRel,
OpDef.OpBMI_PCRel, // 0x30
OpDef.OpAND_DPIndIndexY,
OpDef.OpAND_DPInd,
OpDef.GenerateUndoc(0x33, OpDef.OpNOP_65C02),
OpDef.OpBIT_DPIndexX,
OpDef.OpAND_DPIndexX,
OpDef.OpROL_DPIndexX,
OpDef.OpRMB3_DP,
OpDef.OpSEC_Implied, // 0x38
OpDef.OpAND_AbsIndexY,
OpDef.OpDEC_Acc,
OpDef.GenerateUndoc(0x3b, OpDef.OpNOP_65C02),
OpDef.OpBIT_AbsIndexX,
OpDef.OpAND_AbsIndexX,
OpDef.OpROL_AbsIndexX,
OpDef.OpBBR3_DPPCRel,
OpDef.OpRTI_StackRTI, // 0x40
OpDef.OpEOR_DPIndexXInd,
OpDef.GenerateUndoc(0x42, OpDef.OpLDD_Imm),
OpDef.GenerateUndoc(0x43, OpDef.OpNOP_65C02),
OpDef.GenerateUndoc(0x44, OpDef.OpLDD_DP),
OpDef.OpEOR_DP,
OpDef.OpLSR_DP,
OpDef.OpRMB4_DP,
OpDef.OpPHA_StackPush, // 0x48
OpDef.OpEOR_Imm,
OpDef.OpLSR_Acc,
OpDef.GenerateUndoc(0x4b, OpDef.OpNOP_65C02),
OpDef.OpJMP_Abs,
OpDef.OpEOR_Abs,
OpDef.OpLSR_Abs,
OpDef.OpBBR4_DPPCRel,
OpDef.OpBVC_PCRel, // 0x50
OpDef.OpEOR_DPIndIndexY,
OpDef.OpEOR_DPInd,
OpDef.GenerateUndoc(0x53, OpDef.OpNOP_65C02),
OpDef.GenerateUndoc(0x54, OpDef.OpLDD_DPIndexX),
OpDef.OpEOR_DPIndexX,
OpDef.OpLSR_DPIndexX,
OpDef.OpRMB5_DP,
OpDef.OpCLI_Implied, // 0x58
OpDef.OpEOR_AbsIndexY,
OpDef.OpPHY_StackPush,
OpDef.GenerateUndoc(0x5b, OpDef.OpNOP_65C02),
OpDef.GenerateUndoc(0x5c, OpDef.OpLDD_Weird),
OpDef.OpEOR_AbsIndexX,
OpDef.OpLSR_AbsIndexX,
OpDef.OpBBR5_DPPCRel,
OpDef.OpRTS_StackRTS, // 0x60
OpDef.OpADC_DPIndexXInd,
OpDef.GenerateUndoc(0x62, OpDef.OpLDD_Imm),
OpDef.GenerateUndoc(0x63, OpDef.OpNOP_65C02),
OpDef.OpSTZ_DP,
OpDef.OpADC_DP,
OpDef.OpROR_DP,
OpDef.OpRMB6_DP,
OpDef.OpPLA_StackPull, // 0x68
OpDef.OpADC_Imm,
OpDef.OpROR_Acc,
OpDef.GenerateUndoc(0x6b, OpDef.OpNOP_65C02),
OpDef.OpJMP_AbsInd,
OpDef.OpADC_Abs,
OpDef.OpROR_Abs,
OpDef.OpBBR6_DPPCRel,
OpDef.OpBVS_PCRel, // 0x70
OpDef.OpADC_DPIndIndexY,
OpDef.OpADC_DPInd,
OpDef.GenerateUndoc(0x73, OpDef.OpNOP_65C02),
OpDef.OpSTZ_DPIndexX,
OpDef.OpADC_DPIndexX,
OpDef.OpROR_DPIndexX,
OpDef.OpRMB7_DP,
OpDef.OpSEI_Implied, // 0x78
OpDef.OpADC_AbsIndexY,
OpDef.OpPLY_StackPull,
OpDef.GenerateUndoc(0x7b, OpDef.OpNOP_65C02),
OpDef.OpJMP_AbsIndexXInd,
OpDef.OpADC_AbsIndexX,
OpDef.OpROR_AbsIndexX,
OpDef.OpBBR7_DPPCRel,
OpDef.OpBRA_PCRel, // 0x80
OpDef.OpSTA_DPIndexXInd,
OpDef.GenerateUndoc(0x82, OpDef.OpLDD_Imm),
OpDef.GenerateUndoc(0x83, OpDef.OpNOP_65C02),
OpDef.OpSTY_DP,
OpDef.OpSTA_DP,
OpDef.OpSTX_DP,
OpDef.OpSMB0_DP,
OpDef.OpDEY_Implied, // 0x88
OpDef.OpBIT_Imm,
OpDef.OpTXA_Implied,
OpDef.GenerateUndoc(0x8b, OpDef.OpNOP_65C02),
OpDef.OpSTY_Abs,
OpDef.OpSTA_Abs,
OpDef.OpSTX_Abs,
OpDef.OpBBS0_DPPCRel,
OpDef.OpBCC_PCRel, // 0x90
OpDef.OpSTA_DPIndIndexY,
OpDef.OpSTA_DPInd,
OpDef.GenerateUndoc(0x93, OpDef.OpNOP_65C02),
OpDef.OpSTY_DPIndexX,
OpDef.OpSTA_DPIndexX,
OpDef.OpSTX_DPIndexY,
OpDef.OpSMB1_DP,
OpDef.OpTYA_Implied, // 0x98
OpDef.OpSTA_AbsIndexY,
OpDef.OpTXS_Implied,
OpDef.GenerateUndoc(0x9b, OpDef.OpNOP_65C02),
OpDef.OpSTZ_Abs,
OpDef.OpSTA_AbsIndexX,
OpDef.OpSTZ_AbsIndexX,
OpDef.OpBBS1_DPPCRel,
OpDef.OpLDY_Imm, // 0xa0
OpDef.OpLDA_DPIndexXInd,
OpDef.OpLDX_Imm,
OpDef.GenerateUndoc(0xa3, OpDef.OpNOP_65C02),
OpDef.OpLDY_DP,
OpDef.OpLDA_DP,
OpDef.OpLDX_DP,
OpDef.OpSMB2_DP,
OpDef.OpTAY_Implied, // 0xa8
OpDef.OpLDA_Imm,
OpDef.OpTAX_Implied,
OpDef.GenerateUndoc(0xab, OpDef.OpNOP_65C02),
OpDef.OpLDY_Abs,
OpDef.OpLDA_Abs,
OpDef.OpLDX_Abs,
OpDef.OpBBS2_DPPCRel,
OpDef.OpBCS_PCRel, // 0xb0
OpDef.OpLDA_DPIndIndexY,
OpDef.OpLDA_DPInd,
OpDef.GenerateUndoc(0xb3, OpDef.OpNOP_65C02),
OpDef.OpLDY_DPIndexX,
OpDef.OpLDA_DPIndexX,
OpDef.OpLDX_DPIndexY,
OpDef.OpSMB3_DP,
OpDef.OpCLV_Implied, // 0xb8
OpDef.OpLDA_AbsIndexY,
OpDef.OpTSX_Implied,
OpDef.GenerateUndoc(0xbb, OpDef.OpNOP_65C02),
OpDef.OpLDY_AbsIndexX,
OpDef.OpLDA_AbsIndexX,
OpDef.OpLDX_AbsIndexY,
OpDef.OpBBS3_DPPCRel,
OpDef.OpCPY_Imm, // 0xc0
OpDef.OpCMP_DPIndexXInd,
OpDef.GenerateUndoc(0xc2, OpDef.OpLDD_Imm),
OpDef.GenerateUndoc(0xc3, OpDef.OpNOP_65C02),
OpDef.OpCPY_DP,
OpDef.OpCMP_DP,
OpDef.OpDEC_DP,
OpDef.OpSMB4_DP,
OpDef.OpINY_Implied, // 0xc8
OpDef.OpCMP_Imm,
OpDef.OpDEX_Implied,
OpDef.OpWAI_Implied,
OpDef.OpCPY_Abs,
OpDef.OpCMP_Abs,
OpDef.OpDEC_Abs,
OpDef.OpBBS4_DPPCRel,
OpDef.OpBNE_PCRel, // 0xd0
OpDef.OpCMP_DPIndIndexY,
OpDef.OpCMP_DPInd,
OpDef.GenerateUndoc(0xd3, OpDef.OpNOP_65C02),
OpDef.GenerateUndoc(0xd4, OpDef.OpLDD_DPIndexX),
OpDef.OpCMP_DPIndexX,
OpDef.OpDEC_DPIndexX,
OpDef.OpSMB5_DP,
OpDef.OpCLD_Implied, // 0xd8
OpDef.OpCMP_AbsIndexY,
OpDef.OpPHX_StackPush,
OpDef.OpSTP_Implied,
OpDef.GenerateUndoc(0xdc, OpDef.OpLDD_Absolute),
OpDef.OpCMP_AbsIndexX,
OpDef.OpDEC_AbsIndexX,
OpDef.OpBBS5_DPPCRel,
OpDef.OpCPX_Imm, // 0xe0
OpDef.OpSBC_DPIndexXInd,
OpDef.GenerateUndoc(0xe2, OpDef.OpLDD_Imm),
OpDef.GenerateUndoc(0xe3, OpDef.OpNOP_65C02),
OpDef.OpCPX_DP,
OpDef.OpSBC_DP,
OpDef.OpINC_DP,
OpDef.OpSMB6_DP,
OpDef.OpINX_Implied, // 0xe8
OpDef.OpSBC_Imm,
OpDef.OpNOP_Implied,
OpDef.GenerateUndoc(0xeb, OpDef.OpNOP_65C02),
OpDef.OpCPX_Abs,
OpDef.OpSBC_Abs,
OpDef.OpINC_Abs,
OpDef.OpBBS6_DPPCRel,
OpDef.OpBEQ_PCRel, // 0xf0
OpDef.OpSBC_DPIndIndexY,
OpDef.OpSBC_DPInd,
OpDef.GenerateUndoc(0xf3, OpDef.OpNOP_65C02),
OpDef.GenerateUndoc(0xf4, OpDef.OpLDD_DPIndexX),
OpDef.OpSBC_DPIndexX,
OpDef.OpINC_DPIndexX,
OpDef.OpSMB7_DP,
OpDef.OpSED_Implied, // 0xf8
OpDef.OpSBC_AbsIndexY,
OpDef.OpPLX_StackPull,
OpDef.GenerateUndoc(0xfb, OpDef.OpNOP_65C02),
OpDef.GenerateUndoc(0xfc, OpDef.OpLDD_Absolute),
OpDef.OpSBC_AbsIndexX,
OpDef.OpINC_AbsIndexX,
OpDef.OpBBS7_DPPCRel,
}
};
// WDC 65802 and 65816. No undocumented opcodes -- all 256 are used.
private static CpuDef Cpu65816 { get; } = new CpuDef("WDC W65C816S", (1 << 24) - 1, true) {
Type = CpuType.Cpu65816,
mOpDefs = new OpDef[] {
OpDef.OpBRK_Implied, // 0x00
OpDef.OpORA_DPIndexXInd,
OpDef.OpCOP_StackInt,
OpDef.OpORA_StackRel,
OpDef.OpTSB_DP,
OpDef.OpORA_DP,
OpDef.OpASL_DP,
OpDef.OpORA_DPIndLong,
OpDef.OpPHP_StackPush, // 0x08
OpDef.OpORA_ImmLongA,
OpDef.OpASL_Acc,
OpDef.OpPHD_StackPush,
OpDef.OpTSB_Abs,
OpDef.OpORA_Abs,
OpDef.OpASL_Abs,
OpDef.OpORA_AbsLong,
OpDef.OpBPL_PCRel, // 0x10
OpDef.OpORA_DPIndIndexY,
OpDef.OpORA_DPInd,
OpDef.OpORA_StackRelIndIndexY,
OpDef.OpTRB_DP,
OpDef.OpORA_DPIndexX,
OpDef.OpASL_DPIndexX,
OpDef.OpORA_DPIndIndexYLong,
OpDef.OpCLC_Implied, // 0x18
OpDef.OpORA_AbsIndexY,
OpDef.OpINC_Acc,
OpDef.OpTCS_Implied,
OpDef.OpTRB_Abs,
OpDef.OpORA_AbsIndexX,
OpDef.OpASL_AbsIndexX,
OpDef.OpORA_AbsIndexXLong,
OpDef.OpJSR_Abs, // 0x20
OpDef.OpAND_DPIndexXInd,
OpDef.OpJSR_AbsLong,
OpDef.OpAND_StackRel,
OpDef.OpBIT_DP,
OpDef.OpAND_DP,
OpDef.OpROL_DP,
OpDef.OpAND_DPIndLong,
OpDef.OpPLP_StackPull, // 0x28
OpDef.OpAND_ImmLongA,
OpDef.OpROL_Acc,
OpDef.OpPLD_StackPull,
OpDef.OpBIT_Abs,
OpDef.OpAND_Abs,
OpDef.OpROL_Abs,
OpDef.OpAND_AbsLong,
OpDef.OpBMI_PCRel, // 0x30
OpDef.OpAND_DPIndIndexY,
OpDef.OpAND_DPInd,
OpDef.OpAND_StackRelIndIndexY,
OpDef.OpBIT_DPIndexX,
OpDef.OpAND_DPIndexX,
OpDef.OpROL_DPIndexX,
OpDef.OpAND_DPIndIndexYLong,
OpDef.OpSEC_Implied, // 0x38
OpDef.OpAND_AbsIndexY,
OpDef.OpDEC_Acc,
OpDef.OpTSC_Implied,
OpDef.OpBIT_AbsIndexX,
OpDef.OpAND_AbsIndexX,
OpDef.OpROL_AbsIndexX,
OpDef.OpAND_AbsIndexXLong,
OpDef.OpRTI_StackRTI, // 0x40
OpDef.OpEOR_DPIndexXInd,
OpDef.OpWDM_WDM,
OpDef.OpEOR_StackRel,
OpDef.OpMVP_BlockMove,
OpDef.OpEOR_DP,
OpDef.OpLSR_DP,
OpDef.OpEOR_DPIndLong,
OpDef.OpPHA_StackPush, // 0x48
OpDef.OpEOR_ImmLongA,
OpDef.OpLSR_Acc,
OpDef.OpPHK_StackPush,
OpDef.OpJMP_Abs,
OpDef.OpEOR_Abs,
OpDef.OpLSR_Abs,
OpDef.OpEOR_AbsLong,
OpDef.OpBVC_PCRel, // 0x50
OpDef.OpEOR_DPIndIndexY,
OpDef.OpEOR_DPInd,
OpDef.OpEOR_StackRelIndIndexY,
OpDef.OpMVN_BlockMove,
OpDef.OpEOR_DPIndexX,
OpDef.OpLSR_DPIndexX,
OpDef.OpEOR_DPIndIndexYLong,
OpDef.OpCLI_Implied, // 0x58
OpDef.OpEOR_AbsIndexY,
OpDef.OpPHY_StackPush,
OpDef.OpTCD_Implied,
OpDef.OpJMP_AbsLong,
OpDef.OpEOR_AbsIndexX,
OpDef.OpLSR_AbsIndexX,
OpDef.OpEOR_AbsIndexXLong,
OpDef.OpRTS_StackRTS, // 0x60
OpDef.OpADC_DPIndexXInd,
OpDef.OpPER_StackPCRelLong,
OpDef.OpADC_StackRel,
OpDef.OpSTZ_DP,
OpDef.OpADC_DP,
OpDef.OpROR_DP,
OpDef.OpADC_DPIndLong,
OpDef.OpPLA_StackPull, // 0x68
OpDef.OpADC_ImmLongA,
OpDef.OpROR_Acc,
OpDef.OpRTL_StackRTL,
OpDef.OpJMP_AbsInd,
OpDef.OpADC_Abs,
OpDef.OpROR_Abs,
OpDef.OpADC_AbsLong,
OpDef.OpBVS_PCRel, // 0x70
OpDef.OpADC_DPIndIndexY,
OpDef.OpADC_DPInd,
OpDef.OpADC_StackRelIndIndexY,
OpDef.OpSTZ_DPIndexX,
OpDef.OpADC_DPIndexX,
OpDef.OpROR_DPIndexX,
OpDef.OpADC_DPIndIndexYLong,
OpDef.OpSEI_Implied, // 0x78
OpDef.OpADC_AbsIndexY,
OpDef.OpPLY_StackPull,
OpDef.OpTDC_Implied,
OpDef.OpJMP_AbsIndexXInd,
OpDef.OpADC_AbsIndexX,
OpDef.OpROR_AbsIndexX,
OpDef.OpADC_AbsIndexXLong,
OpDef.OpBRA_PCRel, // 0x80
OpDef.OpSTA_DPIndexXInd,
OpDef.OpBRL_PCRelLong,
OpDef.OpSTA_StackRel,
OpDef.OpSTY_DP,
OpDef.OpSTA_DP,
OpDef.OpSTX_DP,
OpDef.OpSTA_DPIndLong,
OpDef.OpDEY_Implied, // 0x88
OpDef.OpBIT_ImmLongA,
OpDef.OpTXA_Implied,
OpDef.OpPHB_StackPush,
OpDef.OpSTY_Abs,
OpDef.OpSTA_Abs,
OpDef.OpSTX_Abs,
OpDef.OpSTA_AbsLong,
OpDef.OpBCC_PCRel, // 0x90
OpDef.OpSTA_DPIndIndexY,
OpDef.OpSTA_DPInd,
OpDef.OpSTA_StackRelIndIndexY,
OpDef.OpSTY_DPIndexX,
OpDef.OpSTA_DPIndexX,
OpDef.OpSTX_DPIndexY,
OpDef.OpSTA_DPIndIndexYLong,
OpDef.OpTYA_Implied, // 0x98
OpDef.OpSTA_AbsIndexY,
OpDef.OpTXS_Implied,
OpDef.OpTXY_Implied,
OpDef.OpSTZ_Abs,
OpDef.OpSTA_AbsIndexX,
OpDef.OpSTZ_AbsIndexX,
OpDef.OpSTA_AbsIndexXLong,
OpDef.OpLDY_ImmLongXY, // 0xa0
OpDef.OpLDA_DPIndexXInd,
OpDef.OpLDX_ImmLongXY,
OpDef.OpLDA_StackRel,
OpDef.OpLDY_DP,
OpDef.OpLDA_DP,
OpDef.OpLDX_DP,
OpDef.OpLDA_DPIndLong,
OpDef.OpTAY_Implied, // 0xa8
OpDef.OpLDA_ImmLongA,
OpDef.OpTAX_Implied,
OpDef.OpPLB_StackPull,
OpDef.OpLDY_Abs,
OpDef.OpLDA_Abs,
OpDef.OpLDX_Abs,
OpDef.OpLDA_AbsLong,
OpDef.OpBCS_PCRel, // 0xb0
OpDef.OpLDA_DPIndIndexY,
OpDef.OpLDA_DPInd,
OpDef.OpLDA_StackRelIndIndexY,
OpDef.OpLDY_DPIndexX,
OpDef.OpLDA_DPIndexX,
OpDef.OpLDX_DPIndexY,
OpDef.OpLDA_DPIndIndexYLong,
OpDef.OpCLV_Implied, // 0xb8
OpDef.OpLDA_AbsIndexY,
OpDef.OpTSX_Implied,
OpDef.OpTYX_Implied,
OpDef.OpLDY_AbsIndexX,
OpDef.OpLDA_AbsIndexX,
OpDef.OpLDX_AbsIndexY,
OpDef.OpLDA_AbsIndexXLong,
OpDef.OpCPY_ImmLongXY, // 0xc0
OpDef.OpCMP_DPIndexXInd,
OpDef.OpREP_Imm,
OpDef.OpCMP_StackRel,
OpDef.OpCPY_DP,
OpDef.OpCMP_DP,
OpDef.OpDEC_DP,
OpDef.OpCMP_DPIndLong,
OpDef.OpINY_Implied, // 0xc8
OpDef.OpCMP_ImmLongA,
OpDef.OpDEX_Implied,
OpDef.OpWAI_Implied,
OpDef.OpCPY_Abs,
OpDef.OpCMP_Abs,
OpDef.OpDEC_Abs,
OpDef.OpCMP_AbsLong,
OpDef.OpBNE_PCRel, // 0xd0
OpDef.OpCMP_DPIndIndexY,
OpDef.OpCMP_DPInd,
OpDef.OpCMP_StackRelIndIndexY,
OpDef.OpPEI_StackDPInd,
OpDef.OpCMP_DPIndexX,
OpDef.OpDEC_DPIndexX,
OpDef.OpCMP_DPIndIndexYLong,
OpDef.OpCLD_Implied, // 0xd8
OpDef.OpCMP_AbsIndexY,
OpDef.OpPHX_StackPush,
OpDef.OpSTP_Implied,
OpDef.OpJMP_AbsIndLong,
OpDef.OpCMP_AbsIndexX,
OpDef.OpDEC_AbsIndexX,
OpDef.OpCMP_AbsIndexXLong,
OpDef.OpCPX_ImmLongXY, // 0xe0
OpDef.OpSBC_DPIndexXInd,
OpDef.OpSEP_Imm,
OpDef.OpSBC_StackRel,
OpDef.OpCPX_DP,
OpDef.OpSBC_DP,
OpDef.OpINC_DP,
OpDef.OpSBC_DPIndLong,
OpDef.OpINX_Implied, // 0xe8
OpDef.OpSBC_ImmLongA,
OpDef.OpNOP_Implied,
OpDef.OpXBA_Implied,
OpDef.OpCPX_Abs,
OpDef.OpSBC_Abs,
OpDef.OpINC_Abs,
OpDef.OpSBC_AbsLong,
OpDef.OpBEQ_PCRel, // 0xf0
OpDef.OpSBC_DPIndIndexY,
OpDef.OpSBC_DPInd,
OpDef.OpSBC_StackRelIndIndexY,
OpDef.OpPEA_StackAbs,
OpDef.OpSBC_DPIndexX,
OpDef.OpINC_DPIndexX,
OpDef.OpSBC_DPIndIndexYLong,
OpDef.OpSED_Implied, // 0xf8
OpDef.OpSBC_AbsIndexY,
OpDef.OpPLX_StackPull,
OpDef.OpXCE_Implied,
OpDef.OpJSR_AbsIndexXInd,
OpDef.OpSBC_AbsIndexX,
OpDef.OpINC_AbsIndexX,
OpDef.OpSBC_AbsIndexXLong
}
};
}
}