From 98914e9f8028d5c344e704d271459fdb8a4cb61f Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Fri, 2 Aug 2019 17:21:50 -0700 Subject: [PATCH] Treat BRK as a 1-byte instruction The 65816 definition makes it a two-byte instruction, like COP. On the 6502 it acted like a two-byte instruction, but in practice very few assemblers treat it that way. Very few humans, for that matter. So it's now treated as a single byte instruction, with the following byte encoded as a data value. --- Asm65/CpuDef.cs | 6 +++--- Asm65/Formatter.cs | 2 +- Asm65/OpDef.cs | 8 ++++++-- SourceGen/AsmGen/AsmCc65.cs | 2 +- SourceGen/AsmGen/AsmTass64.cs | 3 +-- SourceGen/CodeAnalysis.cs | 16 ++++++++++------ .../Expected/1000-allops-value-65816_64tass.S | 4 +++- .../Expected/1000-allops-value-65816_Merlin32.S | 4 +++- .../Expected/1000-allops-value-65816_cc65.S | 4 +++- .../Expected/1001-allops-zero-65816_64tass.S | 4 +++- .../Expected/1001-allops-zero-65816_Merlin32.S | 4 +++- .../Expected/1001-allops-zero-65816_cc65.S | 4 +++- .../Expected/1002-embedded-instructions_64tass.S | 2 +- .../1002-embedded-instructions_Merlin32.S | 2 +- .../Expected/1002-embedded-instructions_cc65.S | 2 +- .../Expected/2000-allops-value-6502_64tass.S | 4 +++- .../Expected/2000-allops-value-6502_Merlin32.S | 4 +++- .../Expected/2000-allops-value-6502_cc65.S | 4 +++- .../Expected/2001-allops-zero-6502_64tass.S | 4 +++- .../Expected/2001-allops-zero-6502_Merlin32.S | 4 +++- .../Expected/2001-allops-zero-6502_cc65.S | 4 +++- .../Expected/2002-allops-value-65C02_64tass.S | 4 +++- .../Expected/2002-allops-value-65C02_Merlin32.S | 4 +++- .../Expected/2002-allops-value-65C02_cc65.S | 4 +++- .../Expected/2003-allops-zero-65C02_64tass.S | 4 +++- .../Expected/2003-allops-zero-65C02_Merlin32.S | 4 +++- .../Expected/2003-allops-zero-65C02_cc65.S | 4 +++- .../SGTestData/Expected/2014-label-dp_64tass.S | 4 +++- .../SGTestData/Expected/2014-label-dp_Merlin32.S | 4 +++- .../SGTestData/Expected/2014-label-dp_cc65.S | 4 +++- 30 files changed, 88 insertions(+), 39 deletions(-) diff --git a/Asm65/CpuDef.cs b/Asm65/CpuDef.cs index 772e18c..64937af 100644 --- a/Asm65/CpuDef.cs +++ b/Asm65/CpuDef.cs @@ -409,7 +409,7 @@ namespace Asm65 { private static CpuDef Cpu6502 { get; } = new CpuDef("MOS 6502", (1 << 16) - 1, false) { Type = CpuType.Cpu6502, mOpDefs = new OpDef[] { - OpDef.OpBRK_StackInt, // 0x00 + OpDef.OpBRK_Implied, // 0x00 OpDef.OpORA_DPIndexXInd, OpDef.GenerateUndoc(0x02, OpDef.OpJAM_Implied), OpDef.OpSLO_DPIndexXInd, @@ -673,7 +673,7 @@ namespace Asm65 { private static CpuDef Cpu65C02 { get; } = new CpuDef("WDC W65C02S", (1 << 16) - 1, false) { Type = CpuType.Cpu65C02, mOpDefs = new OpDef[] { - OpDef.OpBRK_StackInt, // 0x00 + OpDef.OpBRK_Implied, // 0x00 OpDef.OpORA_DPIndexXInd, OpDef.GenerateUndoc(0x02, OpDef.OpLDD_Imm), OpDef.GenerateUndoc(0x03, OpDef.OpNOP_65C02), @@ -937,7 +937,7 @@ namespace Asm65 { private static CpuDef Cpu65816 { get; } = new CpuDef("WDC W65C816S", (1 << 24) - 1, true) { Type = CpuType.Cpu65816, mOpDefs = new OpDef[] { - OpDef.OpBRK_StackInt, // 0x00 + OpDef.OpBRK_Implied, // 0x00 OpDef.OpORA_DPIndexXInd, OpDef.OpCOP_StackInt, OpDef.OpORA_StackRel, diff --git a/Asm65/Formatter.cs b/Asm65/Formatter.cs index c7a5b17..ea33c4a 100644 --- a/Asm65/Formatter.cs +++ b/Asm65/Formatter.cs @@ -543,7 +543,7 @@ namespace Asm65 { case AddressMode.DP: case AddressMode.PCRel: case AddressMode.PCRelLong: // BRL - case AddressMode.StackInt: // BRK/COP + case AddressMode.StackInt: // COP case AddressMode.StackPCRelLong: // PER case AddressMode.WDM: fmt = wdisStr + "{0}"; diff --git a/Asm65/OpDef.cs b/Asm65/OpDef.cs index 37a1f38..fc70400 100644 --- a/Asm65/OpDef.cs +++ b/Asm65/OpDef.cs @@ -1444,9 +1444,13 @@ namespace Asm65 { AddrMode = AddressMode.Unknown }; - public static readonly OpDef OpBRK_StackInt = new OpDef(OpBRK) { + public static readonly OpDef OpBRK_Implied = new OpDef(OpBRK) { Opcode = 0x00, - AddrMode = AddressMode.StackInt, + // There should arguably be OpBRK_Implied for 6502/65C02 and OpBRK_StackInt for + // 65816, but in practice hardly any assemblers prefer (or even allow) it to be + // a two-byte instruction. The BRK does *act* like a two-byte instruction, but + // code rarely reflects this usage. + AddrMode = AddressMode.Implied, CycDef = 7 | (int)(CycleMod.OneIfE0) }; public static readonly OpDef OpORA_DPIndexXInd = new OpDef(OpORA) { diff --git a/SourceGen/AsmGen/AsmCc65.cs b/SourceGen/AsmGen/AsmCc65.cs index 4ae2007..a86e1d0 100644 --- a/SourceGen/AsmGen/AsmCc65.cs +++ b/SourceGen/AsmGen/AsmCc65.cs @@ -321,7 +321,7 @@ namespace SourceGen.AsmGen { // IGenerator public string ModifyOpcode(int offset, OpDef op) { - if ((op == OpDef.OpWDM_WDM || op == OpDef.OpBRK_StackInt) && mAsmVersion <= V2_17) { + if ((op == OpDef.OpWDM_WDM) && mAsmVersion <= V2_17) { // cc65 v2.17 doesn't support WDM, and assembles BRK to opcode $05. // https://github.com/cc65/cc65/issues/715 // https://github.com/cc65/cc65/issues/716 diff --git a/SourceGen/AsmGen/AsmTass64.cs b/SourceGen/AsmGen/AsmTass64.cs index 7c3cc38..149a00c 100644 --- a/SourceGen/AsmGen/AsmTass64.cs +++ b/SourceGen/AsmGen/AsmTass64.cs @@ -276,8 +276,7 @@ namespace SourceGen.AsmGen { return null; } } - if (op == OpDef.OpBRK_StackInt || op == OpDef.OpCOP_StackInt || - op == OpDef.OpWDM_WDM) { + if (op == OpDef.OpCOP_StackInt || op == OpDef.OpWDM_WDM) { // 64tass doesn't like these to have an operand. Output as hex. return null; } diff --git a/SourceGen/CodeAnalysis.cs b/SourceGen/CodeAnalysis.cs index a7435c9..f83cd61 100644 --- a/SourceGen/CodeAnalysis.cs +++ b/SourceGen/CodeAnalysis.cs @@ -646,8 +646,12 @@ namespace SourceGen { // On first visit, check for BRK inline call. if (firstVisit) { - if (op == OpDef.OpBRK_StackInt) { - CheckForInlineCall(op, offset, out bool unused); + if (op == OpDef.OpBRK_Implied) { + bool noContinue = CheckForInlineCall(op, offset, !doContinue); + if (!noContinue) { + // We're expected to continue execution past the BRK. + doContinue = true; + } } } @@ -675,7 +679,7 @@ namespace SourceGen { if (firstVisit) { // Currently ignoring OpDef.OpJSR_AbsIndexXInd if (op == OpDef.OpJSR_Abs || op == OpDef.OpJSR_AbsLong) { - CheckForInlineCall(op, offset, out bool noContinue); + bool noContinue = CheckForInlineCall(op, offset, false); if (noContinue) { LogD(offset, "Script declared inline call no-continue"); mAnattribs[offset].DoesNotContinue = true; @@ -902,8 +906,7 @@ namespace SourceGen { /// Instruction being examined. /// File offset of start of instruction. /// Set if any plugin declares the call to be no-continue. - private void CheckForInlineCall(OpDef op, int offset, out bool noContinue) { - noContinue = false; + private bool CheckForInlineCall(OpDef op, int offset, bool noContinue) { for (int i = 0; i < mScriptArray.Length; i++) { IPlugin script = mScriptArray[i]; if (op == OpDef.OpJSR_Abs && script is IPlugin_InlineJsr) { @@ -912,11 +915,12 @@ namespace SourceGen { } else if (op == OpDef.OpJSR_AbsLong && script is IPlugin_InlineJsl) { ((IPlugin_InlineJsl)script).CheckJsl(offset, out bool noCont); noContinue |= noCont; - } else if (op == OpDef.OpBRK_StackInt && script is IPlugin_InlineBrk) { + } else if (op == OpDef.OpBRK_Implied && script is IPlugin_InlineBrk) { ((IPlugin_InlineBrk)script).CheckBrk(offset, out bool noCont); noContinue &= noCont; } } + return noContinue; } private bool SetOperandFormat(int offset, DataSubType subType, string label) { diff --git a/SourceGen/SGTestData/Expected/1000-allops-value-65816_64tass.S b/SourceGen/SGTestData/Expected/1000-allops-value-65816_64tass.S index 2b51577..c46fc05 100644 --- a/SourceGen/SGTestData/Expected/1000-allops-value-65816_64tass.S +++ b/SourceGen/SGTestData/Expected/1000-allops-value-65816_64tass.S @@ -15,7 +15,9 @@ nop nop nop - .byte $00,$ff + brk + + .byte $ff L101F ora ($ff,x) .byte $02,$ff diff --git a/SourceGen/SGTestData/Expected/1000-allops-value-65816_Merlin32.S b/SourceGen/SGTestData/Expected/1000-allops-value-65816_Merlin32.S index 3a0a3c2..2506283 100644 --- a/SourceGen/SGTestData/Expected/1000-allops-value-65816_Merlin32.S +++ b/SourceGen/SGTestData/Expected/1000-allops-value-65816_Merlin32.S @@ -12,7 +12,9 @@ nop nop nop - brk $ff + brk + + dfb $ff L101F ora ($ff,x) cop $ff diff --git a/SourceGen/SGTestData/Expected/1000-allops-value-65816_cc65.S b/SourceGen/SGTestData/Expected/1000-allops-value-65816_cc65.S index 25dc27a..bc57f59 100644 --- a/SourceGen/SGTestData/Expected/1000-allops-value-65816_cc65.S +++ b/SourceGen/SGTestData/Expected/1000-allops-value-65816_cc65.S @@ -16,7 +16,9 @@ nop nop nop - .byte $00,$ff + brk + + .byte $ff L101F: ora ($ff,x) cop $ff diff --git a/SourceGen/SGTestData/Expected/1001-allops-zero-65816_64tass.S b/SourceGen/SGTestData/Expected/1001-allops-zero-65816_64tass.S index f6a4ba9..305e6b2 100644 --- a/SourceGen/SGTestData/Expected/1001-allops-zero-65816_64tass.S +++ b/SourceGen/SGTestData/Expected/1001-allops-zero-65816_64tass.S @@ -15,7 +15,9 @@ nop nop nop - .byte $00,$00 + brk + + .byte $00 L101F ora ($00,x) .byte $02,$00 diff --git a/SourceGen/SGTestData/Expected/1001-allops-zero-65816_Merlin32.S b/SourceGen/SGTestData/Expected/1001-allops-zero-65816_Merlin32.S index eb0df97..32d7e3c 100644 --- a/SourceGen/SGTestData/Expected/1001-allops-zero-65816_Merlin32.S +++ b/SourceGen/SGTestData/Expected/1001-allops-zero-65816_Merlin32.S @@ -12,7 +12,9 @@ nop nop nop - brk $00 + brk + + dfb $00 L101F ora ($00,x) cop $00 diff --git a/SourceGen/SGTestData/Expected/1001-allops-zero-65816_cc65.S b/SourceGen/SGTestData/Expected/1001-allops-zero-65816_cc65.S index 0855b66..4e2b707 100644 --- a/SourceGen/SGTestData/Expected/1001-allops-zero-65816_cc65.S +++ b/SourceGen/SGTestData/Expected/1001-allops-zero-65816_cc65.S @@ -16,7 +16,9 @@ nop nop nop - .byte $00,$00 + brk + + .byte $00 L101F: ora ($00,x) cop $00 diff --git a/SourceGen/SGTestData/Expected/1002-embedded-instructions_64tass.S b/SourceGen/SGTestData/Expected/1002-embedded-instructions_64tass.S index 257e07a..89af921 100644 --- a/SourceGen/SGTestData/Expected/1002-embedded-instructions_64tass.S +++ b/SourceGen/SGTestData/Expected/1002-embedded-instructions_64tass.S @@ -22,7 +22,7 @@ L101C sep #$30 lda $00 beq L1025 lda #$00 - .byte $00 + brk L1025 sta $012345 rts diff --git a/SourceGen/SGTestData/Expected/1002-embedded-instructions_Merlin32.S b/SourceGen/SGTestData/Expected/1002-embedded-instructions_Merlin32.S index fe854bf..80c2d07 100644 --- a/SourceGen/SGTestData/Expected/1002-embedded-instructions_Merlin32.S +++ b/SourceGen/SGTestData/Expected/1002-embedded-instructions_Merlin32.S @@ -19,7 +19,7 @@ L101C sep #$30 lda $00 beq L1025 lda #$00 - dfb $00 + brk L1025 stal $012345 rts diff --git a/SourceGen/SGTestData/Expected/1002-embedded-instructions_cc65.S b/SourceGen/SGTestData/Expected/1002-embedded-instructions_cc65.S index 970397f..6cd97f0 100644 --- a/SourceGen/SGTestData/Expected/1002-embedded-instructions_cc65.S +++ b/SourceGen/SGTestData/Expected/1002-embedded-instructions_cc65.S @@ -23,7 +23,7 @@ L101C: sep #$30 lda $00 beq L1025 lda #$00 - .byte $00 + brk L1025: sta $012345 rts diff --git a/SourceGen/SGTestData/Expected/2000-allops-value-6502_64tass.S b/SourceGen/SGTestData/Expected/2000-allops-value-6502_64tass.S index 0b297b2..fb631c9 100644 --- a/SourceGen/SGTestData/Expected/2000-allops-value-6502_64tass.S +++ b/SourceGen/SGTestData/Expected/2000-allops-value-6502_64tass.S @@ -19,7 +19,9 @@ nop nop nop - .byte $00,$ff + brk + + .byte $ff L1035 ora ($ff,x) jam diff --git a/SourceGen/SGTestData/Expected/2000-allops-value-6502_Merlin32.S b/SourceGen/SGTestData/Expected/2000-allops-value-6502_Merlin32.S index 3a44f4b..f50d8c0 100644 --- a/SourceGen/SGTestData/Expected/2000-allops-value-6502_Merlin32.S +++ b/SourceGen/SGTestData/Expected/2000-allops-value-6502_Merlin32.S @@ -18,7 +18,9 @@ nop nop nop - brk $ff + brk + + dfb $ff L1035 ora ($ff,x) dfb $02 diff --git a/SourceGen/SGTestData/Expected/2000-allops-value-6502_cc65.S b/SourceGen/SGTestData/Expected/2000-allops-value-6502_cc65.S index ac8b3f7..3728660 100644 --- a/SourceGen/SGTestData/Expected/2000-allops-value-6502_cc65.S +++ b/SourceGen/SGTestData/Expected/2000-allops-value-6502_cc65.S @@ -20,7 +20,9 @@ nop nop nop - .byte $00,$ff + brk + + .byte $ff L1035: ora ($ff,x) jam diff --git a/SourceGen/SGTestData/Expected/2001-allops-zero-6502_64tass.S b/SourceGen/SGTestData/Expected/2001-allops-zero-6502_64tass.S index 46894e2..20b9367 100644 --- a/SourceGen/SGTestData/Expected/2001-allops-zero-6502_64tass.S +++ b/SourceGen/SGTestData/Expected/2001-allops-zero-6502_64tass.S @@ -19,7 +19,9 @@ nop nop nop - .byte $00,$00 + brk + + .byte $00 L1035 ora ($00,x) jam diff --git a/SourceGen/SGTestData/Expected/2001-allops-zero-6502_Merlin32.S b/SourceGen/SGTestData/Expected/2001-allops-zero-6502_Merlin32.S index 29ab50e..137ee0b 100644 --- a/SourceGen/SGTestData/Expected/2001-allops-zero-6502_Merlin32.S +++ b/SourceGen/SGTestData/Expected/2001-allops-zero-6502_Merlin32.S @@ -18,7 +18,9 @@ nop nop nop - brk $00 + brk + + dfb $00 L1035 ora ($00,x) dfb $02 diff --git a/SourceGen/SGTestData/Expected/2001-allops-zero-6502_cc65.S b/SourceGen/SGTestData/Expected/2001-allops-zero-6502_cc65.S index a5b0d61..5f6d006 100644 --- a/SourceGen/SGTestData/Expected/2001-allops-zero-6502_cc65.S +++ b/SourceGen/SGTestData/Expected/2001-allops-zero-6502_cc65.S @@ -20,7 +20,9 @@ nop nop nop - .byte $00,$00 + brk + + .byte $00 L1035: ora ($00,x) jam diff --git a/SourceGen/SGTestData/Expected/2002-allops-value-65C02_64tass.S b/SourceGen/SGTestData/Expected/2002-allops-value-65C02_64tass.S index 2ca6ddf..e15b12a 100644 --- a/SourceGen/SGTestData/Expected/2002-allops-value-65C02_64tass.S +++ b/SourceGen/SGTestData/Expected/2002-allops-value-65C02_64tass.S @@ -8,7 +8,9 @@ nop nop nop - .byte $00,$ff + brk + + .byte $ff L1014 ora ($ff,x) .byte $02,$ff diff --git a/SourceGen/SGTestData/Expected/2002-allops-value-65C02_Merlin32.S b/SourceGen/SGTestData/Expected/2002-allops-value-65C02_Merlin32.S index a398b3c..1b406c6 100644 --- a/SourceGen/SGTestData/Expected/2002-allops-value-65C02_Merlin32.S +++ b/SourceGen/SGTestData/Expected/2002-allops-value-65C02_Merlin32.S @@ -7,7 +7,9 @@ nop nop nop - brk $ff + brk + + dfb $ff L1014 ora ($ff,x) dfb $02,$ff diff --git a/SourceGen/SGTestData/Expected/2002-allops-value-65C02_cc65.S b/SourceGen/SGTestData/Expected/2002-allops-value-65C02_cc65.S index cd73545..3ca3e18 100644 --- a/SourceGen/SGTestData/Expected/2002-allops-value-65C02_cc65.S +++ b/SourceGen/SGTestData/Expected/2002-allops-value-65C02_cc65.S @@ -9,7 +9,9 @@ nop nop nop - .byte $00,$ff + brk + + .byte $ff L1014: ora ($ff,x) .byte $02,$ff diff --git a/SourceGen/SGTestData/Expected/2003-allops-zero-65C02_64tass.S b/SourceGen/SGTestData/Expected/2003-allops-zero-65C02_64tass.S index 2da7fd9..c3c9c95 100644 --- a/SourceGen/SGTestData/Expected/2003-allops-zero-65C02_64tass.S +++ b/SourceGen/SGTestData/Expected/2003-allops-zero-65C02_64tass.S @@ -8,7 +8,9 @@ nop nop nop - .byte $00,$00 + brk + + .byte $00 L1014 ora ($00,x) .byte $02,$00 diff --git a/SourceGen/SGTestData/Expected/2003-allops-zero-65C02_Merlin32.S b/SourceGen/SGTestData/Expected/2003-allops-zero-65C02_Merlin32.S index 4c9f8a5..29ba3b7 100644 --- a/SourceGen/SGTestData/Expected/2003-allops-zero-65C02_Merlin32.S +++ b/SourceGen/SGTestData/Expected/2003-allops-zero-65C02_Merlin32.S @@ -7,7 +7,9 @@ nop nop nop - brk $00 + brk + + dfb $00 L1014 ora ($00,x) dfb $02,$00 diff --git a/SourceGen/SGTestData/Expected/2003-allops-zero-65C02_cc65.S b/SourceGen/SGTestData/Expected/2003-allops-zero-65C02_cc65.S index 931c484..b7c76aa 100644 --- a/SourceGen/SGTestData/Expected/2003-allops-zero-65C02_cc65.S +++ b/SourceGen/SGTestData/Expected/2003-allops-zero-65C02_cc65.S @@ -9,7 +9,9 @@ nop nop nop - .byte $00,$00 + brk + + .byte $00 L1014: ora ($00,x) .byte $02,$00 diff --git a/SourceGen/SGTestData/Expected/2014-label-dp_64tass.S b/SourceGen/SGTestData/Expected/2014-label-dp_64tass.S index 9792000..f30a278 100644 --- a/SourceGen/SGTestData/Expected/2014-label-dp_64tass.S +++ b/SourceGen/SGTestData/Expected/2014-label-dp_64tass.S @@ -16,7 +16,9 @@ nop nop nop - .byte $00,$80 + brk + + .byte $80 L101F ora (L0080,x) .byte $02,$80 diff --git a/SourceGen/SGTestData/Expected/2014-label-dp_Merlin32.S b/SourceGen/SGTestData/Expected/2014-label-dp_Merlin32.S index 8f44ad3..0dadda8 100644 --- a/SourceGen/SGTestData/Expected/2014-label-dp_Merlin32.S +++ b/SourceGen/SGTestData/Expected/2014-label-dp_Merlin32.S @@ -13,7 +13,9 @@ nop nop nop - brk $80 + brk + + dfb $80 L101F dfb $01,$80 cop $80 diff --git a/SourceGen/SGTestData/Expected/2014-label-dp_cc65.S b/SourceGen/SGTestData/Expected/2014-label-dp_cc65.S index 0ace41e..2882c84 100644 --- a/SourceGen/SGTestData/Expected/2014-label-dp_cc65.S +++ b/SourceGen/SGTestData/Expected/2014-label-dp_cc65.S @@ -17,7 +17,9 @@ nop nop nop - .byte $00,$80 + brk + + .byte $80 L101F: ora (L0080,x) cop $80