1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-12-01 22:50:35 +00:00

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.
This commit is contained in:
Andy McFadden 2020-10-10 15:33:08 -07:00
parent 9ffc4a9383
commit b60dc4fee4
10 changed files with 647 additions and 14 deletions

View File

@ -85,6 +85,7 @@ namespace Asm65 {
Cpu65C02, // Apple //e
Cpu65SC02, // Atari Lynx
CpuW65C02, // ?
Cpu65802, // ?
Cpu65816, // Apple IIgs
@ -107,6 +108,7 @@ namespace Asm65 {
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;
@ -131,6 +133,7 @@ namespace Asm65 {
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";
@ -149,12 +152,14 @@ namespace Asm65 {
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. These do not, and would need full definitions:
// 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)
// Rockwell R65C02 (used in ???)
// 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)
@ -170,6 +175,9 @@ namespace Asm65 {
case CpuType.Cpu65SC02:
cpuDef = Cpu65C02;
break;
case CpuType.CpuW65C02:
cpuDef = CpuW65C02;
break;
default:
// 6502, 6502B, 6502C, 6507, 6510, 8502, 2A03
cpuDef = Cpu6502;
@ -349,6 +357,7 @@ namespace Asm65 {
public static bool DebugValidate() {
InternalValidate(Cpu6502);
InternalValidate(Cpu65C02);
InternalValidate(CpuW65C02);
InternalValidate(Cpu65816);
Debug.WriteLine("CpuDefs okay");
return true;
@ -696,8 +705,8 @@ namespace Asm65 {
};
// WDC's 65C02, with new opcodes and a handful of slightly strange NOPs.
private static CpuDef Cpu65C02 { get; } = new CpuDef("WDC W65C02S", (1 << 16) - 1, false) {
// 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
@ -960,6 +969,272 @@ namespace Asm65 {
};
// 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,

View File

@ -805,6 +805,7 @@ namespace Asm65 {
case AddressMode.BlockMove:
case AddressMode.StackAbs:
case AddressMode.DP:
case AddressMode.DPPCRel:
case AddressMode.PCRel:
case AddressMode.PCRelLong: // BRL
case AddressMode.StackInt: // COP and two-byte BRK

View File

@ -74,6 +74,7 @@ namespace Asm65 {
DPIndexX, // OP dp,X 2
DPIndexXInd, // OP (dp,X) 2
DPIndexY, // OP dp,Y 2
DPPCRel, // OP dp,label 3 (BBR/BBS)
Imm, // OP #const8 2
ImmLongA, // OP #const8/16 2 or 3, depending on 'm' flag
ImmLongXY, // OP #const8/16 2 or 3, depending on 'x' flag
@ -526,6 +527,7 @@ namespace Asm65 {
case AddressMode.AbsInd:
case AddressMode.AbsIndLong:
case AddressMode.BlockMove:
case AddressMode.DPPCRel:
case AddressMode.PCRelLong:
case AddressMode.StackAbs:
case AddressMode.StackPCRelLong:
@ -607,7 +609,7 @@ namespace Asm65 {
}
/// <summary>
/// Get the raw operand value.
/// Gets the raw operand value.
/// </summary>
/// <param name="data">65xx code.</param>
/// <param name="offset">Offset of opcode.</param>
@ -3543,6 +3545,231 @@ namespace Asm65 {
#endregion Undocumented
#region Rockwell extensions
// ======================================================================================
// Rockwell extensions to the 65C02.
//
// These are declared separately because they overlap with 65816 instructions. The
// 32 opcodes occupy the numbers $x7 and $xf.
//
private static OpDef OpBBR = new OpDef() {
Mnemonic = "???",
Effect = FlowEffect.ConditionalBranch,
BaseMemEffect = MemoryEffect.None
};
private static OpDef OpBBS = new OpDef() {
Mnemonic = "???",
Effect = FlowEffect.ConditionalBranch,
BaseMemEffect = MemoryEffect.None
};
private static OpDef OpRMB = new OpDef() {
Mnemonic = "???",
Effect = FlowEffect.Cont,
BaseMemEffect = MemoryEffect.ReadModifyWrite
};
private static OpDef OpSMB = new OpDef() {
Mnemonic = "???",
Effect = FlowEffect.Cont,
BaseMemEffect = MemoryEffect.ReadModifyWrite
};
public static readonly OpDef OpBBR0_DPPCRel = new OpDef(OpBBR) {
Mnemonic = OpName.BBR0,
Opcode = 0x0f,
AddrMode = AddressMode.DPPCRel,
CycDef = 5
};
public static readonly OpDef OpBBR1_DPPCRel = new OpDef(OpBBR) {
Mnemonic = OpName.BBR1,
Opcode = 0x1f,
AddrMode = AddressMode.DPPCRel,
CycDef = 5
};
public static readonly OpDef OpBBR2_DPPCRel = new OpDef(OpBBR) {
Mnemonic = OpName.BBR2,
Opcode = 0x2f,
AddrMode = AddressMode.DPPCRel,
CycDef = 5
};
public static readonly OpDef OpBBR3_DPPCRel = new OpDef(OpBBR) {
Mnemonic = OpName.BBR3,
Opcode = 0x3f,
AddrMode = AddressMode.DPPCRel,
CycDef = 5
};
public static readonly OpDef OpBBR4_DPPCRel = new OpDef(OpBBR) {
Mnemonic = OpName.BBR4,
Opcode = 0x4f,
AddrMode = AddressMode.DPPCRel,
CycDef = 5
};
public static readonly OpDef OpBBR5_DPPCRel = new OpDef(OpBBR) {
Mnemonic = OpName.BBR5,
Opcode = 0x5f,
AddrMode = AddressMode.DPPCRel,
CycDef = 5
};
public static readonly OpDef OpBBR6_DPPCRel = new OpDef(OpBBR) {
Mnemonic = OpName.BBR6,
Opcode = 0x6f,
AddrMode = AddressMode.DPPCRel,
CycDef = 5
};
public static readonly OpDef OpBBR7_DPPCRel = new OpDef(OpBBR) {
Mnemonic = OpName.BBR7,
Opcode = 0x7f,
AddrMode = AddressMode.DPPCRel,
CycDef = 5
};
public static readonly OpDef OpBBS0_DPPCRel = new OpDef(OpBBS) {
Mnemonic = OpName.BBS0,
Opcode = 0x8f,
AddrMode = AddressMode.DPPCRel,
CycDef = 5
};
public static readonly OpDef OpBBS1_DPPCRel = new OpDef(OpBBS) {
Mnemonic = OpName.BBS1,
Opcode = 0x9f,
AddrMode = AddressMode.DPPCRel,
CycDef = 5
};
public static readonly OpDef OpBBS2_DPPCRel = new OpDef(OpBBS) {
Mnemonic = OpName.BBS2,
Opcode = 0xaf,
AddrMode = AddressMode.DPPCRel,
CycDef = 5
};
public static readonly OpDef OpBBS3_DPPCRel = new OpDef(OpBBS) {
Mnemonic = OpName.BBS3,
Opcode = 0xbf,
AddrMode = AddressMode.DPPCRel,
CycDef = 5
};
public static readonly OpDef OpBBS4_DPPCRel = new OpDef(OpBBS) {
Mnemonic = OpName.BBS4,
Opcode = 0xcf,
AddrMode = AddressMode.DPPCRel,
CycDef = 5
};
public static readonly OpDef OpBBS5_DPPCRel = new OpDef(OpBBS) {
Mnemonic = OpName.BBS5,
Opcode = 0xdf,
AddrMode = AddressMode.DPPCRel,
CycDef = 5
};
public static readonly OpDef OpBBS6_DPPCRel = new OpDef(OpBBS) {
Mnemonic = OpName.BBS6,
Opcode = 0xef,
AddrMode = AddressMode.DPPCRel,
CycDef = 5
};
public static readonly OpDef OpBBS7_DPPCRel = new OpDef(OpBBS) {
Mnemonic = OpName.BBS7,
Opcode = 0xff,
AddrMode = AddressMode.DPPCRel,
CycDef = 5
};
public static readonly OpDef OpRMB0_DP = new OpDef(OpRMB) {
Mnemonic = OpName.RMB0,
Opcode = 0x07,
AddrMode = AddressMode.DP,
CycDef = 5
};
public static readonly OpDef OpRMB1_DP = new OpDef(OpRMB) {
Mnemonic = OpName.RMB1,
Opcode = 0x17,
AddrMode = AddressMode.DP,
CycDef = 5
};
public static readonly OpDef OpRMB2_DP = new OpDef(OpRMB) {
Mnemonic = OpName.RMB2,
Opcode = 0x27,
AddrMode = AddressMode.DP,
CycDef = 5
};
public static readonly OpDef OpRMB3_DP = new OpDef(OpRMB) {
Mnemonic = OpName.RMB3,
Opcode = 0x37,
AddrMode = AddressMode.DP,
CycDef = 5
};
public static readonly OpDef OpRMB4_DP = new OpDef(OpRMB) {
Mnemonic = OpName.RMB4,
Opcode = 0x47,
AddrMode = AddressMode.DP,
CycDef = 5
};
public static readonly OpDef OpRMB5_DP = new OpDef(OpRMB) {
Mnemonic = OpName.RMB5,
Opcode = 0x57,
AddrMode = AddressMode.DP,
CycDef = 5
};
public static readonly OpDef OpRMB6_DP = new OpDef(OpRMB) {
Mnemonic = OpName.RMB6,
Opcode = 0x67,
AddrMode = AddressMode.DP,
CycDef = 5
};
public static readonly OpDef OpRMB7_DP = new OpDef(OpRMB) {
Mnemonic = OpName.RMB7,
Opcode = 0x77,
AddrMode = AddressMode.DP,
CycDef = 5
};
public static readonly OpDef OpSMB0_DP = new OpDef(OpSMB) {
Mnemonic = OpName.SMB0,
Opcode = 0x87,
AddrMode = AddressMode.DP,
CycDef = 5
};
public static readonly OpDef OpSMB1_DP = new OpDef(OpSMB) {
Mnemonic = OpName.SMB1,
Opcode = 0x97,
AddrMode = AddressMode.DP,
CycDef = 5
};
public static readonly OpDef OpSMB2_DP = new OpDef(OpSMB) {
Mnemonic = OpName.SMB2,
Opcode = 0xa7,
AddrMode = AddressMode.DP,
CycDef = 5
};
public static readonly OpDef OpSMB3_DP = new OpDef(OpSMB) {
Mnemonic = OpName.SMB3,
Opcode = 0xb7,
AddrMode = AddressMode.DP,
CycDef = 5
};
public static readonly OpDef OpSMB4_DP = new OpDef(OpSMB) {
Mnemonic = OpName.SMB4,
Opcode = 0xc7,
AddrMode = AddressMode.DP,
CycDef = 5
};
public static readonly OpDef OpSMB5_DP = new OpDef(OpSMB) {
Mnemonic = OpName.SMB5,
Opcode = 0xd7,
AddrMode = AddressMode.DP,
CycDef = 5
};
public static readonly OpDef OpSMB6_DP = new OpDef(OpSMB) {
Mnemonic = OpName.SMB6,
Opcode = 0xe7,
AddrMode = AddressMode.DP,
CycDef = 5
};
public static readonly OpDef OpSMB7_DP = new OpDef(OpSMB) {
Mnemonic = OpName.SMB7,
Opcode = 0xf7,
AddrMode = AddressMode.DP,
CycDef = 5
};
#endregion Rockwell extensions
/// <summary>
/// Generates one of the multiply-defined opcodes from a prototype. This is

View File

@ -117,6 +117,7 @@ namespace Asm65 {
/// shorter than those in the CPU data sheet.
/// </summary>
private static Dictionary<string, string> sShort_enUS = new Dictionary<string, string>() {
// 65816 instructions.
{ OpName.ADC, "Add With Carry" },
{ OpName.AND, "AND Accumulator With Memory" },
{ OpName.ASL, "Shift Memory or Accumulator Left" },
@ -236,6 +237,40 @@ namespace Asm65 {
// WDC 65C02 undocumented
{ OpName.LDD, "Load and Discard" },
// Rockwell 65C02 extensions
{ OpName.BBR0, "Branch on Bit Reset" },
{ OpName.BBR1, "Branch on Bit Reset" },
{ OpName.BBR2, "Branch on Bit Reset" },
{ OpName.BBR3, "Branch on Bit Reset" },
{ OpName.BBR4, "Branch on Bit Reset" },
{ OpName.BBR5, "Branch on Bit Reset" },
{ OpName.BBR6, "Branch on Bit Reset" },
{ OpName.BBR7, "Branch on Bit Reset" },
{ OpName.BBS0, "Branch on Bit Set" },
{ OpName.BBS1, "Branch on Bit Set" },
{ OpName.BBS2, "Branch on Bit Set" },
{ OpName.BBS3, "Branch on Bit Set" },
{ OpName.BBS4, "Branch on Bit Set" },
{ OpName.BBS5, "Branch on Bit Set" },
{ OpName.BBS6, "Branch on Bit Set" },
{ OpName.BBS7, "Branch on Bit Set" },
{ OpName.RMB0, "Reset Memory Bit" },
{ OpName.RMB1, "Reset Memory Bit" },
{ OpName.RMB2, "Reset Memory Bit" },
{ OpName.RMB3, "Reset Memory Bit" },
{ OpName.RMB4, "Reset Memory Bit" },
{ OpName.RMB5, "Reset Memory Bit" },
{ OpName.RMB6, "Reset Memory Bit" },
{ OpName.RMB7, "Reset Memory Bit" },
{ OpName.SMB0, "Set Memory Bit" },
{ OpName.SMB1, "Set Memory Bit" },
{ OpName.SMB2, "Set Memory Bit" },
{ OpName.SMB3, "Set Memory Bit" },
{ OpName.SMB4, "Set Memory Bit" },
{ OpName.SMB5, "Set Memory Bit" },
{ OpName.SMB6, "Set Memory Bit" },
{ OpName.SMB7, "Set Memory Bit" },
};
/// <summary>
@ -677,8 +712,54 @@ namespace Asm65 {
"Load and Discard. Usually a no-op, but the activity on the address bus " +
"can affect memory-mapped I/O."
},
//
// Rockwell 65C02 extensions.
//
{ OpName.BBR0, BBR_DESC },
{ OpName.BBR1, BBR_DESC },
{ OpName.BBR2, BBR_DESC },
{ OpName.BBR3, BBR_DESC },
{ OpName.BBR4, BBR_DESC },
{ OpName.BBR5, BBR_DESC },
{ OpName.BBR6, BBR_DESC },
{ OpName.BBR7, BBR_DESC },
{ OpName.BBS0, BBS_DESC },
{ OpName.BBS1, BBS_DESC },
{ OpName.BBS2, BBS_DESC },
{ OpName.BBS3, BBS_DESC },
{ OpName.BBS4, BBS_DESC },
{ OpName.BBS5, BBS_DESC },
{ OpName.BBS6, BBS_DESC },
{ OpName.BBS7, BBS_DESC },
{ OpName.RMB0, RMB_DESC },
{ OpName.RMB1, RMB_DESC },
{ OpName.RMB2, RMB_DESC },
{ OpName.RMB3, RMB_DESC },
{ OpName.RMB4, RMB_DESC },
{ OpName.RMB5, RMB_DESC },
{ OpName.RMB6, RMB_DESC },
{ OpName.RMB7, RMB_DESC },
{ OpName.SMB0, SMB_DESC },
{ OpName.SMB1, SMB_DESC },
{ OpName.SMB2, SMB_DESC },
{ OpName.SMB3, SMB_DESC },
{ OpName.SMB4, SMB_DESC },
{ OpName.SMB5, SMB_DESC },
{ OpName.SMB6, SMB_DESC },
{ OpName.SMB7, SMB_DESC },
};
private static string BBR_DESC =
"Branches to a relative address if the specified bit in memory is zero.";
private static string BBS_DESC =
"Branches to a relative address if the specified bit in memory is one.";
private static string RMB_DESC =
"Clears a bit in memory.";
private static string SMB_DESC =
"Sets a bit in memory.";
/// <summary>
/// Address mode short descriptions, USA English.
/// </summary>
@ -702,6 +783,7 @@ namespace Asm65 {
{ OpDef.AddressMode.DPIndexX, "Direct Page Indexed X" },
{ OpDef.AddressMode.DPIndexXInd, "Direct Page Indexed X Indirect" },
{ OpDef.AddressMode.DPIndexY, "Direct Page Indexed Y" },
{ OpDef.AddressMode.DPPCRel, "Direct Page / PC Relative" },
{ OpDef.AddressMode.Imm, "Immediate" },
{ OpDef.AddressMode.ImmLongA, "Immediate" },
{ OpDef.AddressMode.ImmLongXY, "Immediate" },

View File

@ -21,9 +21,12 @@ namespace Asm65 {
/// must be lower-case.
/// </summary>
public static class OpName {
// NOTE: these all happen to be three characters, but I don't think we want to
// guarantee that. On the 65816 some mnemonics are extended (e.g. LDAL for LDA with
// NOTE: these are generally three characters, but the pattern breaks with the Rockwell
// extensions unless we want to show the bit index as a 3rd argument (which some
// assemblers do). On the 65816 some mnemonics are extended (e.g. LDAL for LDA with
// a 24-bit operand), but that's assembler-specific and handled elsewhere.
//
// Bottom line: don't assume these will be 3 characters.
public const string Unknown = "???";
public const string ADC = "adc";
public const string AND = "and";
@ -143,5 +146,39 @@ namespace Asm65 {
// Undocumented 65C02 instructions.
public const string LDD = "ldd";
// Rockwell extensions
public const string BBR0 = "bbr0";
public const string BBR1 = "bbr1";
public const string BBR2 = "bbr2";
public const string BBR3 = "bbr3";
public const string BBR4 = "bbr4";
public const string BBR5 = "bbr5";
public const string BBR6 = "bbr6";
public const string BBR7 = "bbr7";
public const string BBS0 = "bbs0";
public const string BBS1 = "bbs1";
public const string BBS2 = "bbs2";
public const string BBS3 = "bbs3";
public const string BBS4 = "bbs4";
public const string BBS5 = "bbs5";
public const string BBS6 = "bbs6";
public const string BBS7 = "bbs7";
public const string RMB0 = "rmb0";
public const string RMB1 = "rmb1";
public const string RMB2 = "rmb2";
public const string RMB3 = "rmb3";
public const string RMB4 = "rmb4";
public const string RMB5 = "rmb5";
public const string RMB6 = "rmb6";
public const string RMB7 = "rmb7";
public const string SMB0 = "smb0";
public const string SMB1 = "smb1";
public const string SMB2 = "smb2";
public const string SMB3 = "smb3";
public const string SMB4 = "smb4";
public const string SMB5 = "smb5";
public const string SMB6 = "smb6";
public const string SMB7 = "smb7";
}
}

View File

@ -235,17 +235,22 @@ you later hit Cancel, but the changes are not applied immediately.</p>
<p>The choice of CPU determines the set of available instructions, as
well as cycle costs and register widths. There are many variations
on the 6502, but from the perspective of a disassembler most can be
treated as one of these three:</p>
treated as one of these four:</p>
<ol>
<li>MOS 6502. The original 8-bit instruction set.</li>
<li>WDC W65C02S. Expanded the instruction set and smoothed
<li>WDC 65C02. Expanded the instruction set and smoothed
some rough edges.</li>
<li>WDC W65C02S. An enhanced version of the 65C02, with some
additional instructions introduced by Rockwell (R65C02), as well
as WDC's STP and WAI instructions. The Rockwell additions overlap
with 65816 instructions, so code that uses them will not work on
16-bit CPUs.</li>
<li>WDC W65C816S. Expanded instruction set, 24-bit address space,
and 16-bit registers.</li>
</ol>
<p>The Rockwell R65C02, Hudson Soft HuC6280, and Commodore CSG 4510 / 65CE02
have instruction sets that expand on the 6502/65C02, but aren't compatible
with the 65816. These are not yet supported by SourceGen.</p>
<p>The Hudson Soft HuC6280 and Commodore CSG 4510 / 65CE02 are very
similar, but they have additional instructions and some fundamental
architectural changes. These are not currently supported by SourceGen.</p>
<p>If "enable undocumented instructions" is checked, some additional
opcodes are recognized on the 6502 and 65C02. These instructions are

View File

@ -30,7 +30,8 @@ limitations under the License.
<Window.Resources>
<system:String x:Key="str_6502">MOS 6502</system:String>
<system:String x:Key="str_65C02">WDC W65C02S</system:String>
<system:String x:Key="str_65C02">WDC 65C02</system:String>
<system:String x:Key="str_W65C02">WDC W65C02S</system:String>
<system:String x:Key="str_65816">WDC W65C816S</system:String>
</Window.Resources>

View File

@ -105,6 +105,7 @@ namespace SourceGen.Tools.WpfGui {
CpuItems = new CpuItem[] {
new CpuItem((string)FindResource("str_6502"), CpuDef.CpuType.Cpu6502),
new CpuItem((string)FindResource("str_65C02"), CpuDef.CpuType.Cpu65C02),
new CpuItem((string)FindResource("str_W65C02"), CpuDef.CpuType.CpuW65C02),
new CpuItem((string)FindResource("str_65816"), CpuDef.CpuType.Cpu65816),
};
}
@ -162,6 +163,8 @@ namespace SourceGen.Tools.WpfGui {
string sampleValue = "$12";
if (op.AddrMode == OpDef.AddressMode.BlockMove) {
sampleValue = "#$12,#$34";
} else if (op.AddrMode == OpDef.AddressMode.DPPCRel) {
sampleValue = "$12,$1234";
} else if (opLen == 3) {
sampleValue = "$1234";
} else if (opLen == 4) {

View File

@ -38,7 +38,8 @@ limitations under the License.
<!-- strings for combo boxes -->
<system:String x:Key="str_6502">MOS 6502</system:String>
<system:String x:Key="str_65C02">WDC W65C02S</system:String>
<system:String x:Key="str_65C02">WDC 65C02</system:String>
<system:String x:Key="str_W65C02">WDC W65C02S</system:String>
<system:String x:Key="str_65816">WDC W65C816S</system:String>
<system:String x:Key="str_DisableStringScan">None (disabled)</system:String>

View File

@ -126,6 +126,7 @@ namespace SourceGen.WpfGui {
CpuItems = new CpuItem[] {
new CpuItem((string)FindResource("str_6502"), CpuDef.CpuType.Cpu6502),
new CpuItem((string)FindResource("str_65C02"), CpuDef.CpuType.Cpu65C02),
new CpuItem((string)FindResource("str_W65C02"), CpuDef.CpuType.CpuW65C02),
new CpuItem((string)FindResource("str_65816"), CpuDef.CpuType.Cpu65816),
};
DefaultTextScanModeItems = new DefaultTextScanMode[] {