1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-05-31 22:41:37 +00:00
6502bench/Asm65/CpuDef.cs
Andy McFadden b60dc4fee4 Add W65C02S support, part 1
We were claiming W65C02S, but it turns out that CPU has the Rockwell
extensions and the STP/WAI instructions.  We need to change existing
references to be "WDC 65C02", and add a new CPU definition for the
actual W65C02S chip.

This adds the new CPU definition, the instruction definitions for
the Rockwell extensions, and updates the selectors in project properties
and the instruction chart tool.

This change shouldn't affect any existing projects.  Still more to do
before W65C02 works though, mostly because the Rockwell instructions
introduced a new two-argument address mode that has to be handled in
various places.
2020-10-10 15:46:34 -07:00

1502 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("CpuDefs okay");
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:
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);
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.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.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
}
};
}
}