From 70ee8793ae3a9b1f824792343a892673f8b48cd5 Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Sat, 10 Oct 2020 18:34:19 -0700 Subject: [PATCH] Add W65C02S support, part 2 Created the "all ops" tests for W65C02. Filled in enough of the necessary infrastructure to be able to create the project and disassemble the file, though we're not yet handling the instructions correctly. --- Asm65/CpuDef.cs | 7 +- Asm65/OpDef.cs | 4 + SourceGen/MainController.cs | 1 + SourceGen/RuntimeData/SystemDefs.json | 13 + ...value-6502.S => 10000-allops-value-6502.S} | 0 .../Source/10003-allops-value-W65C02.S | 9 + .../Source/10013-allops-zero-W65C02.S | 9 + .../SGTestData/Source/allops-common-W65C02.S | 296 ++++++++++++++++++ SourceGen/Tests/GenTest.cs | 5 +- 9 files changed, 339 insertions(+), 5 deletions(-) rename SourceGen/SGTestData/Source/{10001-allops-value-6502.S => 10000-allops-value-6502.S} (100%) create mode 100644 SourceGen/SGTestData/Source/10003-allops-value-W65C02.S create mode 100644 SourceGen/SGTestData/Source/10013-allops-zero-W65C02.S create mode 100644 SourceGen/SGTestData/Source/allops-common-W65C02.S diff --git a/Asm65/CpuDef.cs b/Asm65/CpuDef.cs index 3c0eb29..617b543 100644 --- a/Asm65/CpuDef.cs +++ b/Asm65/CpuDef.cs @@ -359,7 +359,7 @@ namespace Asm65 { InternalValidate(Cpu65C02); InternalValidate(CpuW65C02); InternalValidate(Cpu65816); - Debug.WriteLine("CpuDefs okay"); + Debug.WriteLine("CpuDef: tests successful"); return true; } private static void InternalValidate(CpuDef cdef) { @@ -406,6 +406,7 @@ namespace Asm65 { OpDef.CycleMod.BlockMove; break; case CpuType.Cpu65C02: + case CpuType.CpuW65C02: ignoreMask = OpDef.CycleMod.OneIfM0 | OpDef.CycleMod.TwoIfM0 | OpDef.CycleMod.OneIfX0 | @@ -431,7 +432,7 @@ namespace Asm65 { 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); + Debug.Assert(Type == CpuType.Cpu65C02 || Type == CpuType.CpuW65C02); baseCycles++; mods &= ~OpDef.CycleMod.OneIf65C02; } @@ -973,7 +974,7 @@ namespace Asm65 { // 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, + Type = CpuType.CpuW65C02, mOpDefs = new OpDef[] { OpDef.OpBRK_Implied, // 0x00 OpDef.OpORA_DPIndexXInd, diff --git a/Asm65/OpDef.cs b/Asm65/OpDef.cs index 7808406..72d3d9a 100644 --- a/Asm65/OpDef.cs +++ b/Asm65/OpDef.cs @@ -603,6 +603,10 @@ namespace Asm65 { case 0xf0: // BEQ return FlagToBT(flags.Z, 1); default: + if ((op.Opcode & 0x0f) == 0x0f) { + // assume W65C02 BBR/BBS + return BranchTaken.Indeterminate; + } // Not a conditional branch. throw new Exception("Not a conditional branch"); } diff --git a/SourceGen/MainController.cs b/SourceGen/MainController.cs index 3b1a2d1..17f0c44 100644 --- a/SourceGen/MainController.cs +++ b/SourceGen/MainController.cs @@ -262,6 +262,7 @@ namespace SourceGen { Debug.Assert(CommonUtil.RangeSet.Test()); Debug.Assert(CommonUtil.TypedRangeSet.Test()); Debug.Assert(CommonUtil.Version.Test()); + Debug.Assert(Asm65.CpuDef.DebugValidate()); if (RuntimeDataAccess.GetDirectory() == null) { MessageBox.Show(Res.Strings.RUNTIME_DIR_NOT_FOUND, diff --git a/SourceGen/RuntimeData/SystemDefs.json b/SourceGen/RuntimeData/SystemDefs.json index 522cfa1..f3ec912 100644 --- a/SourceGen/RuntimeData/SystemDefs.json +++ b/SourceGen/RuntimeData/SystemDefs.json @@ -307,6 +307,19 @@ "Parameters" : { } }, + { + "Name" : "Generic W65C02", + "GroupName" : "Generic", + "Cpu" : "W65C02", + "Speed" : "1", + "Description" : "Generic W65C02-based system (65C02 with Rockwell and WDC extensions).", + "SymbolFiles" : [ + ], + "ExtensionScripts" : [ + ], + "Parameters" : { + } + }, { "Name" : "Generic 65816", "GroupName" : "Generic", diff --git a/SourceGen/SGTestData/Source/10001-allops-value-6502.S b/SourceGen/SGTestData/Source/10000-allops-value-6502.S similarity index 100% rename from SourceGen/SGTestData/Source/10001-allops-value-6502.S rename to SourceGen/SGTestData/Source/10000-allops-value-6502.S diff --git a/SourceGen/SGTestData/Source/10003-allops-value-W65C02.S b/SourceGen/SGTestData/Source/10003-allops-value-W65C02.S new file mode 100644 index 0000000..1d721a3 --- /dev/null +++ b/SourceGen/SGTestData/Source/10003-allops-value-W65C02.S @@ -0,0 +1,9 @@ +; Copyright 2020 faddenSoft. All Rights Reserved. +; See the LICENSE.txt file for distribution terms (Apache 2.0). +; +; Assembler: Merlin 32 + +ZP EQU $FF +ABS EQU $FEFF + + PUT allops-common-W65C02.S diff --git a/SourceGen/SGTestData/Source/10013-allops-zero-W65C02.S b/SourceGen/SGTestData/Source/10013-allops-zero-W65C02.S new file mode 100644 index 0000000..272b03c --- /dev/null +++ b/SourceGen/SGTestData/Source/10013-allops-zero-W65C02.S @@ -0,0 +1,9 @@ +; Copyright 2020 faddenSoft. All Rights Reserved. +; See the LICENSE.txt file for distribution terms (Apache 2.0). +; +; Assembler: Merlin 32 + +ZP EQU $00 +ABS EQU $0000 + + PUT allops-common-W65C02.S diff --git a/SourceGen/SGTestData/Source/allops-common-W65C02.S b/SourceGen/SGTestData/Source/allops-common-W65C02.S new file mode 100644 index 0000000..8dc246c --- /dev/null +++ b/SourceGen/SGTestData/Source/allops-common-W65C02.S @@ -0,0 +1,296 @@ +; Copyright 2020 faddenSoft. All Rights Reserved. +; See the LICENSE.txt file for distribution terms (Apache 2.0). +; +; Assembler: Merlin 32 + +; Macros for Rockwell extensions. We use the 3-arg format to +; cut down on the code size. +BBR MAC ;BBR bit,zp,label + DFB ]1*16+$0f + DFB ]2 + DFB ]3-*-1 + <<< +BBS MAC ;BBS bit,zp,label + DFB ]1*16+$8f + DFB ]2 + DFB ]3-*-1 + <<< +RMB MAC ;RMB bit,zp + DFB ]1*16+$07 + DFB ]2 + <<< +SMB MAC ;SMB bit,zp + DFB ]1*16+$87 + DFB ]2 + <<< + + ORG $1000 + + JSR PostBRK + JSR PostRTI + JSR PostRTS + JSR PostJMPI + JSR PostJMPX + JSR PostSTP + NOP + NOP + NOP + + BRK ZP ;$00 +PostBRK ORA (ZP,X) + DFB $02,ZP + DFB $03 + TSB ZP + ORA ZP + ASL ZP + RMB 0;ZP + PHP + ORA #ZP + ASL + DFB $0B + TSB: ABS + ORA: ABS + ASL: ABS + BBR 0;ZP;PostBBR0 +PostBBR0 BPL PostBPL ;$10 +PostBPL ORA (ZP),Y + ORA (ZP) + DFB $13 + TRB ZP + ORA ZP,X + ASL ZP,X + RMB 1;ZP + CLC + ORA: ABS,Y + INC + DFB $1B + TRB: ABS + ORA: ABS,X + ASL: ABS,X + BBR 1;ZP;PostBBR1 +PostBBR1 JSR ABS ;$20 + AND (ZP,X) + DFB $22,ZP + DFB $23 + BIT ZP + AND ZP + ROL ZP + RMB 2;ZP + PLP + AND #ZP + ROL + DFB $2B + BIT: ABS + AND: ABS + ROL: ABS + BBR 2;ZP;PostBBR2 +PostBBR2 BMI PostBMI ;$30 +PostBMI AND (ZP),Y + AND (ZP) + DFB $33 + BIT ZP,X + AND ZP,X + ROL ZP,X + RMB 3;ZP + SEC + AND: ABS,Y + DEC + DFB $3B + BIT: ABS,X + AND: ABS,X + ROL: ABS,X + BBR 3;ZP;PostBBR3 +PostBBR3 RTI ;$40 +PostRTI EOR (ZP,X) + DFB $42,ZP + DFB $43 + DFB $44,ZP + EOR ZP + LSR ZP + RMB 4;ZP + PHA + EOR #ZP + LSR + DFB $4B + JMP PostJMP +PostJMP EOR: ABS + LSR: ABS + BBR 4;ZP;PostBBR4 +PostBBR4 BVC PostBVC ;$50 +PostBVC EOR (ZP),Y + EOR (ZP) + DFB $53 + DFB $54,ZP + EOR ZP,X + LSR ZP,X + RMB 5;ZP + CLI + EOR: ABS,Y + PHY + DFB $5B + DFB $5C,ABS + EOR: ABS,X + LSR: ABS,X + BBR 5;ZP;PostBBR5 +PostBBR5 RTS ;$60 +PostRTS ADC (ZP,X) + DFB $62,ZP + DFB $63 + STZ ZP + ADC ZP + ROR ZP + RMB 6;ZP + PLA + ADC #ZP + ROR + DFB $6B + JMP (ABS) +PostJMPI ADC: ABS + ROR: ABS + BBR 6;ZP;PostBBR6 +PostBBR6 BVS PostBVS ;$70 +PostBVS ADC (ZP),Y + ADC (ZP) + DFB $73 + STZ ZP,X + ADC ZP,X + ROR ZP,X + RMB 7;ZP + SEI + ADC: ABS,Y + PLY + DFB $7B + JMP (ABS,X) +PostJMPX ADC: ABS,X + ROR: ABS,X + BBR 7;ZP;PostBBR7 +PostBBR7 BRA PostBRA ;$80 +PostBRA STA (ZP,X) + DFB $82,ZP + DFB $83 + STY ZP + STA ZP + STX ZP + SMB 0;ZP + DEY + BIT #ZP + TXA + DFB $8B + STY: ABS + STA: ABS + STX: ABS + BBS 0;ZP;PostBBS0 +PostBBS0 BCC PostBCC ;$90 +PostBCC STA (ZP),Y + STA (ZP) + DFB $93 + STY ZP,X + STA ZP,X + STX ZP,Y + SMB 1;ZP + TYA + STA: ABS,Y + TXS + DFB $9B + STZ: ABS + STA: ABS,X + STZ: ABS,X + BBS 1;ZP;PostBBS1 +PostBBS1 LDY #ZP ;$A0 + LDA (ZP,X) + LDX #ZP + DFB $A3 + LDY ZP + LDA ZP + LDX ZP + SMB 2;ZP + TAY + LDA #ZP + TAX + DFB $AB + LDY: ABS + LDA: ABS + LDX: ABS + BBS 2;ZP;PostBBS2 +PostBBS2 BCS PostBCS ;$B0 +PostBCS LDA (ZP),Y + LDA (ZP) + DFB $B3 + LDY ZP,X + LDA ZP,X + LDX ZP,Y + SMB 3;ZP + CLV + LDA: ABS,Y + TSX + DFB $BB + LDY: ABS,X + LDA: ABS,X + LDX: ABS,Y + BBS 3;ZP;PostBBS3 +PostBBS3 CPY #ZP ;$C0 + CMP (ZP,X) + DFB $C2,ZP + DFB $C3 + CPY ZP + CMP ZP + DEC ZP + SMB 4;ZP + INY + CMP #ZP + DEX + WAI + CPY: ABS + CMP: ABS + DEC: ABS + BBS 4;ZP;PostBBS4 +PostBBS4 BNE PostBNE ;$D0 +PostBNE CMP (ZP),Y + CMP (ZP) + DFB $D3 + DFB $D4,ZP + CMP ZP,X + DEC ZP,X + SMB 5;ZP + CLD + CMP: ABS,Y + PHX + STP +PostSTP DFB $DC,ABS + CMP: ABS,X + DEC: ABS,X + BBS 5;ZP;PostBBS5 +PostBBS5 CPX #ZP ;$E0 + SBC (ZP,X) + DFB $E2,ZP + DFB $E3 + CPX ZP + SBC ZP + INC ZP + SMB 6;ZP + INX + SBC #ZP + NOP + DFB $EB + CPX: ABS + SBC: ABS + INC: ABS + BBS 6;ZP;PostBBS6 +PostBBS6 BEQ PostBEQ ;$F0 +PostBEQ SBC (ZP),Y + SBC (ZP) + DFB $F3 + DFB $F4,ZP + SBC ZP,X + INC ZP,X + SMB 7;ZP + SED + SBC: ABS,Y + PLX + DFB $FB + DFB $FC,ABS + SBC: ABS,X + INC: ABS,X + BBS 7;ZP;PostBBS7 + +PostBBS7 rts diff --git a/SourceGen/Tests/GenTest.cs b/SourceGen/Tests/GenTest.cs index 7d8106e..7dcd575 100644 --- a/SourceGen/Tests/GenTest.cs +++ b/SourceGen/Tests/GenTest.cs @@ -192,13 +192,14 @@ namespace SourceGen.Tests { /// /// Determines the desired CPU from the test case number. /// - /// - /// + /// Test number. + /// CPU type enumeration value. private CpuDef.CpuType GetCpuTypeFromNum(int testNum) { switch (testNum % 10) { case 0: return CpuDef.CpuType.Cpu6502; case 1: return CpuDef.CpuType.Cpu65C02; case 2: return CpuDef.CpuType.Cpu65816; + case 3: return CpuDef.CpuType.CpuW65C02; default: return CpuDef.CpuType.CpuUnknown; } }