From 47b136373858a74121ce70ac9f9828a823ebbe76 Mon Sep 17 00:00:00 2001
From: Andy McFadden
Date: Thu, 11 Apr 2019 16:23:02 -0700
Subject: [PATCH] Add more detail to cross references
In the cross-reference table we now indicate whether the reference
source is doing a read, write, read-modify-write, branch, subroutine
call, is just referencing the address, or is part of the data.
---
Asm65/OpDef.cs | 256 ++++++++++++++++++------
SourceGen/AppForms/ProjectView.cs | 32 ++-
SourceGen/AsmGen/AsmMerlin32.cs | 7 +-
SourceGen/CodeAnalysis.cs | 2 +-
SourceGen/DataAnalysis.cs | 11 +-
SourceGen/DisasmProject.cs | 35 ++--
SourceGen/RuntimeData/Help/codegen.html | 10 +-
SourceGen/RuntimeData/Help/mainwin.html | 18 +-
SourceGen/SymbolTable.cs | 4 +-
SourceGen/XrefSet.cs | 23 ++-
10 files changed, 303 insertions(+), 95 deletions(-)
diff --git a/Asm65/OpDef.cs b/Asm65/OpDef.cs
index 4edd2cd..37a1f38 100644
--- a/Asm65/OpDef.cs
+++ b/Asm65/OpDef.cs
@@ -33,7 +33,18 @@ namespace Asm65 {
NoCont, // RTS, BRK, ... (jump to new address, not specified in operand)
CallSubroutine, // JSR, JSL (jump to new address, and also continue to next)
ConditionalBranch // BCC, BEQ, ... (jump to new address and/or continue to next)
- };
+ }
+
+ ///
+ /// Effect of executing an instruction on memory.
+ ///
+ public enum MemoryEffect {
+ Unknown = 0,
+ None, // e.g. TAX, PEA addr, LDA #imm
+ Read, // e.g. LDA addr
+ Write, // e.g. STA addr
+ ReadModifyWrite // e.g. LSR addr
+ }
///
/// Addressing mode. This uses the same distinctions as Eyes & Lichty, which for
@@ -160,6 +171,22 @@ namespace Asm65 {
///
public FlowEffect Effect { get; private set; }
+ ///
+ /// Effect this instruction has on memory.
+ ///
+ public MemoryEffect MemEffect {
+ get {
+ // If we do this a lot, we should probably just go through and set the
+ // mem effect to "none" in all the immediate-mode op definitions.
+ if (IsImmediate) {
+ return MemoryEffect.None;
+ } else {
+ return BaseMemEffect;
+ }
+ }
+ }
+ private MemoryEffect BaseMemEffect { get; set; }
+
///
/// Cycles required. The low 8 bits hold the base cycle count, the remaining bits
/// are defined by the CycleMod enum.
@@ -221,6 +248,7 @@ namespace Asm65 {
this.Mnemonic = src.Mnemonic;
this.FlagsAffected = src.FlagsAffected;
this.Effect = src.Effect;
+ this.BaseMemEffect = src.BaseMemEffect;
this.CycDef = src.CycDef;
this.IsOperandWidthUnambiguous = src.IsOperandWidthUnambiguous;
this.StatusFlagUpdater = src.StatusFlagUpdater;
@@ -247,10 +275,10 @@ namespace Asm65 {
///
- /// True if this operation is a branch instruction (conditional branch,
+ /// True if this operation is any type of branch instruction (conditional branch,
/// unconditional branch/jump, subroutine call).
///
- public bool IsBranch {
+ public bool IsBranchOrSubCall {
get {
return Effect == FlowEffect.Branch ||
Effect == FlowEffect.ConditionalBranch ||
@@ -258,6 +286,15 @@ namespace Asm65 {
}
}
+ ///
+ /// True if this operation is a subroutine call.
+ ///
+ public bool IsSubroutineCall {
+ get {
+ return Effect == FlowEffect.CallSubroutine;
+ }
+ }
+
///
/// True if the operand is an immediate value, which should be prefixed with '#'.
///
@@ -270,11 +307,11 @@ namespace Asm65 {
}
///
- /// True if the operand is an "extended immediate" value, which includes PEA
- /// as well as Imm.
+ /// True if the operand is an "extended immediate" value, which includes PEA in
+ /// addition to Imm/ImmLongA/ImmLongXY.
///
public bool IsExtendedImmediate {
- get { // should this include PER as well?
+ get {
return IsImmediate || AddrMode == AddressMode.StackAbs;
}
}
@@ -748,24 +785,28 @@ namespace Asm65 {
private static OpDef OpADC = new OpDef() {
Mnemonic = OpName.ADC,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Read,
FlagsAffected = FlagsAffected_NVZC,
StatusFlagUpdater = FlagUpdater_NVZC
};
private static OpDef OpAND = new OpDef() {
Mnemonic = OpName.AND,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Read,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ // special handling for imm
};
private static OpDef OpASL = new OpDef() {
Mnemonic = OpName.ASL,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.ReadModifyWrite,
FlagsAffected = FlagsAffected_NZC,
StatusFlagUpdater = FlagUpdater_NZC
};
private static OpDef OpBCC = new OpDef() {
Mnemonic = OpName.BCC,
Effect = FlowEffect.ConditionalBranch,
+ BaseMemEffect = MemoryEffect.None,
StatusFlagUpdater = delegate(StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) {
condBranchTakenFlags.C = 0;
@@ -776,6 +817,7 @@ namespace Asm65 {
private static OpDef OpBCS = new OpDef() {
Mnemonic = OpName.BCS,
Effect = FlowEffect.ConditionalBranch,
+ BaseMemEffect = MemoryEffect.None,
StatusFlagUpdater = delegate (StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) {
condBranchTakenFlags.C = 1;
@@ -786,6 +828,7 @@ namespace Asm65 {
private static OpDef OpBEQ = new OpDef() {
Mnemonic = OpName.BEQ,
Effect = FlowEffect.ConditionalBranch,
+ BaseMemEffect = MemoryEffect.None,
StatusFlagUpdater = delegate (StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) {
condBranchTakenFlags.Z = 1;
@@ -796,12 +839,14 @@ namespace Asm65 {
private static OpDef OpBIT = new OpDef() {
Mnemonic = OpName.BIT,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZC, // special handling for imm
StatusFlagUpdater = FlagUpdater_NZC // special handling for imm
};
private static OpDef OpBMI = new OpDef() {
Mnemonic = OpName.BMI,
Effect = FlowEffect.ConditionalBranch,
+ BaseMemEffect = MemoryEffect.None,
StatusFlagUpdater = delegate (StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) {
condBranchTakenFlags.N = 1;
@@ -812,6 +857,7 @@ namespace Asm65 {
private static OpDef OpBNE = new OpDef() {
Mnemonic = OpName.BNE,
Effect = FlowEffect.ConditionalBranch,
+ BaseMemEffect = MemoryEffect.None,
StatusFlagUpdater = delegate (StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) {
condBranchTakenFlags.Z = 0;
@@ -822,6 +868,7 @@ namespace Asm65 {
private static OpDef OpBPL = new OpDef() {
Mnemonic = OpName.BPL,
Effect = FlowEffect.ConditionalBranch,
+ BaseMemEffect = MemoryEffect.None,
StatusFlagUpdater = delegate (StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) {
condBranchTakenFlags.N = 0;
@@ -831,19 +878,23 @@ namespace Asm65 {
};
private static OpDef OpBRA = new OpDef() {
Mnemonic = OpName.BRA,
- Effect = FlowEffect.Branch
+ Effect = FlowEffect.Branch,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpBRK = new OpDef() {
Mnemonic = OpName.BRK,
- Effect = FlowEffect.NoCont
+ Effect = FlowEffect.NoCont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpBRL = new OpDef() {
Mnemonic = OpName.BRL,
- Effect = FlowEffect.Branch
+ Effect = FlowEffect.Branch,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpBVC = new OpDef() {
Mnemonic = OpName.BVC,
Effect = FlowEffect.ConditionalBranch,
+ BaseMemEffect = MemoryEffect.None,
StatusFlagUpdater = delegate (StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) {
condBranchTakenFlags.V = 0;
@@ -854,6 +905,7 @@ namespace Asm65 {
private static OpDef OpBVS = new OpDef() {
Mnemonic = OpName.BVS,
Effect = FlowEffect.ConditionalBranch,
+ BaseMemEffect = MemoryEffect.None,
StatusFlagUpdater = delegate (StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) {
condBranchTakenFlags.V = 1;
@@ -864,6 +916,7 @@ namespace Asm65 {
private static OpDef OpCLC = new OpDef() {
Mnemonic = OpName.CLC,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_C,
StatusFlagUpdater = delegate (StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) {
@@ -874,6 +927,7 @@ namespace Asm65 {
private static OpDef OpCLD = new OpDef() {
Mnemonic = OpName.CLD,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_D,
StatusFlagUpdater = delegate (StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) {
@@ -884,6 +938,7 @@ namespace Asm65 {
private static OpDef OpCLI = new OpDef() {
Mnemonic = OpName.CLI,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_I,
StatusFlagUpdater = delegate (StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) {
@@ -894,6 +949,7 @@ namespace Asm65 {
private static OpDef OpCLV = new OpDef() {
Mnemonic = OpName.CLV,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_V,
StatusFlagUpdater = delegate (StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) {
@@ -904,246 +960,293 @@ namespace Asm65 {
private static OpDef OpCMP = new OpDef() {
Mnemonic = OpName.CMP,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Read,
FlagsAffected = FlagsAffected_NZC,
StatusFlagUpdater = FlagUpdater_NZC
};
private static OpDef OpCOP = new OpDef() {
Mnemonic = OpName.COP,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpCPX = new OpDef() {
Mnemonic = OpName.CPX,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Read,
FlagsAffected = FlagsAffected_NZC,
StatusFlagUpdater = FlagUpdater_NZC
};
private static OpDef OpCPY = new OpDef() {
Mnemonic = OpName.CPY,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Read,
FlagsAffected = FlagsAffected_NZC,
StatusFlagUpdater = FlagUpdater_NZC
};
private static OpDef OpDEC = new OpDef() {
Mnemonic = OpName.DEC,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.ReadModifyWrite,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpDEX = new OpDef() {
Mnemonic = OpName.DEX,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpDEY = new OpDef() {
Mnemonic = OpName.DEY,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpEOR = new OpDef() {
Mnemonic = OpName.EOR,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Read,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpINC = new OpDef() {
Mnemonic = OpName.INC,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.ReadModifyWrite,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpINX = new OpDef() {
Mnemonic = OpName.INX,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpINY = new OpDef() {
Mnemonic = OpName.INY,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpJML = new OpDef() {
Mnemonic = OpName.JML, // technically JMP with long operand, but JML is convention
Effect = FlowEffect.Branch,
+ BaseMemEffect = MemoryEffect.None,
IsOperandWidthUnambiguous = true,
};
private static OpDef OpJMP = new OpDef() {
Mnemonic = OpName.JMP,
Effect = FlowEffect.Branch,
+ BaseMemEffect = MemoryEffect.None,
IsOperandWidthUnambiguous = true
};
private static OpDef OpJSL = new OpDef() {
Mnemonic = OpName.JSL, // technically JSR with long operand, but JSL is convention
Effect = FlowEffect.CallSubroutine,
+ BaseMemEffect = MemoryEffect.None,
IsOperandWidthUnambiguous = true,
StatusFlagUpdater = FlagUpdater_Subroutine
};
private static OpDef OpJSR = new OpDef() {
Mnemonic = OpName.JSR,
Effect = FlowEffect.CallSubroutine,
+ BaseMemEffect = MemoryEffect.None,
IsOperandWidthUnambiguous = true,
StatusFlagUpdater = FlagUpdater_Subroutine
};
private static OpDef OpLDA = new OpDef() {
Mnemonic = OpName.LDA,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Read,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ // special handling for imm
};
private static OpDef OpLDX = new OpDef() {
Mnemonic = OpName.LDX,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Read,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ // special handling for imm
};
private static OpDef OpLDY = new OpDef() {
Mnemonic = OpName.LDY,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Read,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ // special handling for imm
};
private static OpDef OpLSR = new OpDef() {
Mnemonic = OpName.LSR,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.ReadModifyWrite,
FlagsAffected = FlagsAffected_NZC,
StatusFlagUpdater = FlagUpdater_NZC
};
private static OpDef OpMVN = new OpDef() {
Mnemonic = OpName.MVN,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None // not quite right, but what is?
};
private static OpDef OpMVP = new OpDef() {
Mnemonic = OpName.MVP,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpNOP = new OpDef() {
Mnemonic = OpName.NOP,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpORA = new OpDef() {
Mnemonic = OpName.ORA,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Read,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ // special handling for imm
};
private static OpDef OpPEA = new OpDef() {
Mnemonic = OpName.PEA,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpPEI = new OpDef() {
Mnemonic = OpName.PEI,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Read
};
private static OpDef OpPER = new OpDef() {
Mnemonic = OpName.PER,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpPHA = new OpDef() {
Mnemonic = OpName.PHA,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpPHB = new OpDef() {
Mnemonic = OpName.PHB,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpPHD = new OpDef() {
Mnemonic = OpName.PHD,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpPHK = new OpDef() {
Mnemonic = OpName.PHK,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpPHP = new OpDef() {
Mnemonic = OpName.PHP,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpPHX = new OpDef() {
Mnemonic = OpName.PHX,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpPHY = new OpDef() {
Mnemonic = OpName.PHY,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpPLA = new OpDef() {
Mnemonic = OpName.PLA,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpPLB = new OpDef() {
Mnemonic = OpName.PLB,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpPLD = new OpDef() {
Mnemonic = OpName.PLD,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpPLP = new OpDef() {
Mnemonic = OpName.PLP,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_All,
StatusFlagUpdater = FlagUpdater_PLP
};
private static OpDef OpPLX = new OpDef() {
Mnemonic = OpName.PLX,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpPLY = new OpDef() {
Mnemonic = OpName.PLY,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpREP = new OpDef() {
Mnemonic = OpName.REP,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_All,
StatusFlagUpdater = FlagUpdater_REP
};
private static OpDef OpROL = new OpDef() {
Mnemonic = OpName.ROL,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.ReadModifyWrite,
FlagsAffected = FlagsAffected_NZC,
StatusFlagUpdater = FlagUpdater_ROL
};
private static OpDef OpROR = new OpDef() {
Mnemonic = OpName.ROR,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.ReadModifyWrite,
FlagsAffected = FlagsAffected_NZC,
StatusFlagUpdater = FlagUpdater_ROR
};
private static OpDef OpRTI = new OpDef() {
Mnemonic = OpName.RTI,
- Effect = FlowEffect.NoCont
+ Effect = FlowEffect.NoCont,
+ BaseMemEffect = MemoryEffect.None,
};
private static OpDef OpRTL = new OpDef() {
Mnemonic = OpName.RTL,
- Effect = FlowEffect.NoCont
+ Effect = FlowEffect.NoCont,
+ BaseMemEffect = MemoryEffect.None,
};
private static OpDef OpRTS = new OpDef() {
Mnemonic = OpName.RTS,
- Effect = FlowEffect.NoCont
+ Effect = FlowEffect.NoCont,
+ BaseMemEffect = MemoryEffect.None,
};
private static OpDef OpSBC = new OpDef() {
Mnemonic = OpName.SBC,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Read,
FlagsAffected = FlagsAffected_NVZC,
StatusFlagUpdater = FlagUpdater_NVZC
};
private static OpDef OpSEC = new OpDef() {
Mnemonic = OpName.SEC,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_C,
StatusFlagUpdater = delegate (StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) {
@@ -1154,6 +1257,7 @@ namespace Asm65 {
private static OpDef OpSED = new OpDef() {
Mnemonic = OpName.SED,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_D,
StatusFlagUpdater = delegate (StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) {
@@ -1164,6 +1268,7 @@ namespace Asm65 {
private static OpDef OpSEI = new OpDef() {
Mnemonic = OpName.SEI,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_I,
StatusFlagUpdater = delegate (StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) {
@@ -1174,126 +1279,150 @@ namespace Asm65 {
private static OpDef OpSEP = new OpDef() {
Mnemonic = OpName.SEP,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_All,
StatusFlagUpdater = FlagUpdater_SEP
};
private static OpDef OpSTA = new OpDef() {
Mnemonic = OpName.STA,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Write,
};
private static OpDef OpSTP = new OpDef() {
Mnemonic = OpName.STP,
- Effect = FlowEffect.NoCont
+ Effect = FlowEffect.NoCont,
+ BaseMemEffect = MemoryEffect.None,
};
private static OpDef OpSTX = new OpDef() {
Mnemonic = OpName.STX,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Write,
};
private static OpDef OpSTY = new OpDef() {
Mnemonic = OpName.STY,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Write,
};
private static OpDef OpSTZ = new OpDef() {
Mnemonic = OpName.STZ,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Write,
};
private static OpDef OpTAX = new OpDef() {
Mnemonic = OpName.TAX,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpTAY = new OpDef() {
Mnemonic = OpName.TAY,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpTCD = new OpDef() {
Mnemonic = OpName.TCD,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpTCS = new OpDef() {
Mnemonic = OpName.TCS,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpTDC = new OpDef() {
Mnemonic = OpName.TDC,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpTRB = new OpDef() {
Mnemonic = OpName.TRB,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.ReadModifyWrite,
FlagsAffected = FlagsAffected_Z,
StatusFlagUpdater = FlagUpdater_Z
};
private static OpDef OpTSB = new OpDef() {
Mnemonic = OpName.TSB,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.ReadModifyWrite,
FlagsAffected = FlagsAffected_Z,
StatusFlagUpdater = FlagUpdater_Z
};
private static OpDef OpTSC = new OpDef() {
Mnemonic = OpName.TSC,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpTSX = new OpDef() {
Mnemonic = OpName.TSX,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpTXA = new OpDef() {
Mnemonic = OpName.TXA,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpTXS = new OpDef() {
Mnemonic = OpName.TXS,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpTXY = new OpDef() {
Mnemonic = OpName.TXY,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpTYA = new OpDef() {
Mnemonic = OpName.TYA,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpTYX = new OpDef() {
Mnemonic = OpName.TYX,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpWAI = new OpDef() {
Mnemonic = OpName.WAI,
- Effect = FlowEffect.Cont // when I=1 (interrupts disabled), continues on interrupt
+ Effect = FlowEffect.Cont, // when I=1 (interrupts disabled), continues on interrupt
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpWDM = new OpDef() {
Mnemonic = OpName.WDM,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpXBA = new OpDef() {
Mnemonic = OpName.XBA,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
private static OpDef OpXCE = new OpDef() {
Mnemonic = OpName.XCE,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_C,
StatusFlagUpdater = FlagUpdater_XCE
};
@@ -2698,18 +2827,21 @@ namespace Asm65 {
IsUndocumented = true,
Mnemonic = OpName.ANC,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZC,
StatusFlagUpdater = FlagUpdater_NZC
};
private static OpDef OpANE = new OpDef() {
IsUndocumented = true,
Mnemonic = OpName.ANE,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpALR = new OpDef() {
IsUndocumented = true,
Mnemonic = OpName.ALR,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZC,
StatusFlagUpdater = FlagUpdater_NZC
};
@@ -2717,6 +2849,7 @@ namespace Asm65 {
IsUndocumented = true,
Mnemonic = OpName.ARR,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NVZC,
StatusFlagUpdater = FlagUpdater_NVZC
};
@@ -2724,23 +2857,27 @@ namespace Asm65 {
IsUndocumented = true,
Mnemonic = OpName.DCP,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.ReadModifyWrite,
FlagsAffected = FlagsAffected_C,
StatusFlagUpdater = FlagUpdater_C
};
- private static OpDef OpDOP = new OpDef() {
+ private static OpDef OpDOP = new OpDef() { // double-byte NOP
IsUndocumented = true,
Mnemonic = OpName.DOP,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpJAM = new OpDef() {
IsUndocumented = true,
Mnemonic = OpName.JAM,
- Effect = FlowEffect.NoCont
+ Effect = FlowEffect.NoCont,
+ BaseMemEffect = MemoryEffect.None
};
private static OpDef OpISC = new OpDef() {
IsUndocumented = true,
Mnemonic = OpName.ISC,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.ReadModifyWrite,
FlagsAffected = FlagsAffected_NVZC,
StatusFlagUpdater = FlagUpdater_NVZC
};
@@ -2748,6 +2885,7 @@ namespace Asm65 {
IsUndocumented = true,
Mnemonic = OpName.LAS,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Read,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
@@ -2755,20 +2893,15 @@ namespace Asm65 {
IsUndocumented = true,
Mnemonic = OpName.LAX,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Read,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
- //private static OpDef OpLXA = new OpDef() {
- // IsUndocumented = true,
- // Mnemonic = OpName.LXA,
- // Effect = FlowEffect.Cont,
- // FlagsAffected = FlagsAffected_NZ,
- // StatusFlagUpdater = FlagUpdater_NZ
- //};
private static OpDef OpRLA = new OpDef() {
IsUndocumented = true,
Mnemonic = OpName.RLA,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.ReadModifyWrite,
FlagsAffected = FlagsAffected_NZC,
StatusFlagUpdater = FlagUpdater_NZC
};
@@ -2776,6 +2909,7 @@ namespace Asm65 {
IsUndocumented = true,
Mnemonic = OpName.RRA,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.ReadModifyWrite,
FlagsAffected = FlagsAffected_NVZC,
StatusFlagUpdater = FlagUpdater_NVZC
};
@@ -2783,6 +2917,7 @@ namespace Asm65 {
IsUndocumented = true,
Mnemonic = OpName.SAX,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Write,
FlagsAffected = FlagsAffected_NZ,
StatusFlagUpdater = FlagUpdater_NZ
};
@@ -2790,33 +2925,33 @@ namespace Asm65 {
IsUndocumented = true,
Mnemonic = OpName.SBX,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None,
FlagsAffected = FlagsAffected_NZC,
StatusFlagUpdater = FlagUpdater_NZC
};
private static OpDef OpSHA = new OpDef() {
IsUndocumented = true,
Mnemonic = OpName.SHA,
- Effect = FlowEffect.Cont
- };
- private static OpDef OpTAS = new OpDef() {
- IsUndocumented = true,
- Mnemonic = OpName.TAS,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Write
};
private static OpDef OpSHX = new OpDef() {
IsUndocumented = true,
Mnemonic = OpName.SHX,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Write
};
private static OpDef OpSHY = new OpDef() {
IsUndocumented = true,
Mnemonic = OpName.SHY,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Write
};
private static OpDef OpSLO = new OpDef() {
IsUndocumented = true,
Mnemonic = OpName.SLO,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.ReadModifyWrite,
FlagsAffected = FlagsAffected_NZC,
StatusFlagUpdater = FlagUpdater_NZC
};
@@ -2824,14 +2959,23 @@ namespace Asm65 {
IsUndocumented = true,
Mnemonic = OpName.SRE,
Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.ReadModifyWrite,
FlagsAffected = FlagsAffected_NZC,
StatusFlagUpdater = FlagUpdater_NZC
};
- private static OpDef OpTOP = new OpDef() {
+ private static OpDef OpTAS = new OpDef() {
+ IsUndocumented = true,
+ Mnemonic = OpName.TAS,
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.Write
+ };
+ private static OpDef OpTOP = new OpDef() { // triple-byte NOP
IsUndocumented = true,
Mnemonic = OpName.TOP,
- Effect = FlowEffect.Cont
+ Effect = FlowEffect.Cont,
+ BaseMemEffect = MemoryEffect.None
};
+
public static readonly OpDef OpSLO_DPIndexXInd = new OpDef(OpSLO) {
Opcode = 0x03,
AddrMode = AddressMode.DPIndexXInd,
diff --git a/SourceGen/AppForms/ProjectView.cs b/SourceGen/AppForms/ProjectView.cs
index a1d22d8..3ddb606 100644
--- a/SourceGen/AppForms/ProjectView.cs
+++ b/SourceGen/AppForms/ProjectView.cs
@@ -4003,6 +4003,7 @@ namespace SourceGen.AppForms {
return;
}
+ // TODO(someday): localization
Asm65.Formatter formatter = mOutputFormatter;
bool showBank = !mProject.CpuDef.HasAddr16;
for (int i = 0; i < xrefs.Count; i++) {
@@ -4011,15 +4012,36 @@ namespace SourceGen.AppForms {
string typeStr;
switch (xr.Type) {
- case XrefSet.XrefType.BranchOperand:
+ case XrefSet.XrefType.SubCallOp:
+ typeStr = "call ";
+ break;
+ case XrefSet.XrefType.BranchOp:
typeStr = "branch ";
break;
- case XrefSet.XrefType.InstrOperand:
- typeStr = "instr ";
- break;
- case XrefSet.XrefType.DataOperand:
+ case XrefSet.XrefType.RefFromData:
typeStr = "data ";
break;
+ case XrefSet.XrefType.MemAccessOp:
+ switch (xr.AccType) {
+ case OpDef.MemoryEffect.Read:
+ typeStr = "read ";
+ break;
+ case OpDef.MemoryEffect.Write:
+ typeStr = "write ";
+ break;
+ case OpDef.MemoryEffect.ReadModifyWrite:
+ typeStr = "rmw ";
+ break;
+ case OpDef.MemoryEffect.None: // e.g. LDA #
+ /// Given a reference from srcOffset to targetOffset, check to see if there's a
+ /// nearby location that we'd prefer to refer to. For example, if targetOffset points
+ /// into the middle of an instruction, we'd rather have it refer to the first byte.
+ ///
+ /// Reference source.
+ /// Reference target.
+ /// New value for targetOffset, or original value if nothing better was
+ /// found.
private int FindAlternateTarget(int srcOffset, int targetOffset) {
int origTargetOffset = targetOffset;
@@ -393,7 +402,7 @@ namespace SourceGen {
// Source is an instruction, so we have an instruction referencing an instruction.
// Could be a branch, an address push, or self-modifying code.
OpDef op = mProject.CpuDef.GetOpDef(mProject.FileData[srcOffset]);
- if (op.IsBranch) {
+ if (op.IsBranchOrSubCall) {
// Don't mess with jumps and branches -- always go directly to the
// target address.
} else if (op == OpDef.OpPEA_StackAbs || op == OpDef.OpPER_StackPCRelLong) {
diff --git a/SourceGen/DisasmProject.cs b/SourceGen/DisasmProject.cs
index b30df98..338531f 100644
--- a/SourceGen/DisasmProject.cs
+++ b/SourceGen/DisasmProject.cs
@@ -478,7 +478,8 @@ namespace SourceGen {
reanalysisTimer.EndTask("GenerateXrefs");
reanalysisTimer.StartTask("GenerateActiveDefSymbolList");
- // Generate the list of project/platform symbols that are being used.
+ // Generate the list of project/platform symbols that are being used. This forms
+ // the list of EQUates at the top of the file.
GenerateActiveDefSymbolList();
reanalysisTimer.EndTask("GenerateActiveDefSymbolList");
@@ -792,15 +793,19 @@ namespace SourceGen {
Anattrib attr = mAnattribs[offset];
XrefSet.XrefType xrefType = XrefSet.XrefType.Unknown;
+ OpDef.MemoryEffect accType = OpDef.MemoryEffect.Unknown;
if (attr.IsInstruction) {
OpDef op = CpuDef.GetOpDef(FileData[offset]);
- if (op.IsBranch) {
- xrefType = XrefSet.XrefType.BranchOperand;
+ if (op.IsSubroutineCall) {
+ xrefType = XrefSet.XrefType.SubCallOp;
+ } else if (op.IsBranchOrSubCall) {
+ xrefType = XrefSet.XrefType.BranchOp;
} else {
- xrefType = XrefSet.XrefType.InstrOperand;
+ xrefType = XrefSet.XrefType.MemAccessOp;
+ accType = op.MemEffect;
}
} else if (attr.IsData || attr.IsInlineData) {
- xrefType = XrefSet.XrefType.DataOperand;
+ xrefType = XrefSet.XrefType.RefFromData;
}
bool hasZeroOffsetSym = false;
@@ -825,7 +830,8 @@ namespace SourceGen {
mAnattribs[operandOffset].Address;
}
- AddXref(symOffset, new XrefSet.Xref(offset, true, xrefType, adj));
+ AddXref(symOffset,
+ new XrefSet.Xref(offset, true, xrefType, accType, adj));
if (adj == 0) {
hasZeroOffsetSym = true;
}
@@ -838,7 +844,8 @@ namespace SourceGen {
if (operandOffset >= 0) {
adj = defSym.Value - operandOffset;
}
- defSym.Xrefs.Add(new XrefSet.Xref(offset, true, xrefType, adj));
+ defSym.Xrefs.Add(
+ new XrefSet.Xref(offset, true, xrefType, accType, adj));
} else {
Debug.WriteLine("NOTE: not xrefing '" + sym.Label + "'");
Debug.Assert(false); // not possible?
@@ -849,7 +856,8 @@ namespace SourceGen {
Debug.Assert(attr.IsData || attr.IsInlineData);
int operandOffset = RawData.GetWord(mFileData, offset,
dfd.Length, dfd.FormatType == FormatDescriptor.Type.NumericBE);
- AddXref(operandOffset, new XrefSet.Xref(offset, false, xrefType, 0));
+ AddXref(operandOffset,
+ new XrefSet.Xref(offset, false, xrefType, accType, 0));
}
// Look for instruction offset references. We skip this if we've already
@@ -857,7 +865,8 @@ namespace SourceGen {
// just leave a duplicate entry. (The symbolic ref wins because we need
// it for the label localizer and possibly the label refactorer.)
if (!hasZeroOffsetSym && attr.IsInstructionStart && attr.OperandOffset >= 0) {
- AddXref(attr.OperandOffset, new XrefSet.Xref(offset, false, xrefType, 0));
+ AddXref(attr.OperandOffset,
+ new XrefSet.Xref(offset, false, xrefType, accType, 0));
}
}
@@ -1492,13 +1501,15 @@ namespace SourceGen {
}
///
- /// Updates all symbolic references to the old label.
+ /// Updates all symbolic references to the old label. Call this after replacing
+ /// mAnattribs[labelOffset].Symbol.
///
/// Offset with the just-renamed label.
/// Previous value.
private void RefactorLabel(int labelOffset, string oldLabel) {
if (!mXrefs.TryGetValue(labelOffset, out XrefSet xrefs)) {
- // This can happen if you add a label in the middle of nowhere and rename it.
+ // This can happen if you add a label in a file section that nothing references,
+ // and then rename it.
Debug.WriteLine("RefactorLabel: no references to " + oldLabel);
return;
}
@@ -1548,7 +1559,7 @@ namespace SourceGen {
continue;
}
- Debug.WriteLine("Replacing symbol at +" + xr.Offset.ToString("x6") +
+ Debug.WriteLine("Replacing OpFor symbol at +" + xr.Offset.ToString("x6") +
" with " + newLabel);
OperandFormats[xr.Offset] = FormatDescriptor.Create(
dfd.Length, new WeakSymbolRef(newLabel, dfd.SymbolRef.ValuePart),
diff --git a/SourceGen/RuntimeData/Help/codegen.html b/SourceGen/RuntimeData/Help/codegen.html
index 68aacf3..56b11f0 100644
--- a/SourceGen/RuntimeData/Help/codegen.html
+++ b/SourceGen/RuntimeData/Help/codegen.html
@@ -127,7 +127,7 @@ code, but also needs to know how to handle the corner cases.
Bugs:
- - Undocumented opcodes:
SHA (ZP),Y
($93) is not supported;
+ - Undocumented opcode
SHA (ZP),Y
($93) is not supported;
the assembler appears to be expecting SHA ABS,X
instead.
- BRK, COP, and WDM are not allowed to have operands.
@@ -166,7 +166,6 @@ code, but also needs to know how to handle the corner cases.
PC relative branches don't wrap around at bank boundaries.
BRK <arg> is assembled to opcode $05 rather than $00.
WDM is not supported.
- Source file names may not have spaces in them on Windows.
Quirks:
@@ -178,8 +177,8 @@ code, but also needs to know how to handle the corner cases.
more common interpretation would be label >> (8 - 16)
.
(This is actually somewhat convenient, since none of the expressions
SourceGen currently generates require parenthesis.)
- Undocumented opcodes: SBX ($cb) uses the mnemonic AXS. All other
- opcodes match up with the "unintended opcodes" document.
+ Undocumented opcode SBX
($cb) uses the mnemonic AXS. All
+ other opcodes match up with the "unintended opcodes" document.
ca65 is implemented as a single-pass assembler, so label widths
can't always be known in time. For example, if you use some zero-page
labels, but they're defined via .ORG $0000 after the point where the
@@ -224,7 +223,8 @@ code, but also needs to know how to handle the corner cases.
Values loaded into registers are implicitly mod 256 or 65536. There
is no need to explicitly mask an expression.
The assembler tracks register widths when it sees SEP/REP instructions,
- but doesn't attempt to track the emulation flag. So if you issue a REP
+ but doesn't attempt to track the emulation flag. So if you issue a
+ REP #$20
while in emulation mode, the assembler will incorrectly assume long
registers. (Really I just want to be able to turn the width-tracking
off, but there's no way to do that.)
diff --git a/SourceGen/RuntimeData/Help/mainwin.html b/SourceGen/RuntimeData/Help/mainwin.html
index 9893541..c5dd301 100644
--- a/SourceGen/RuntimeData/Help/mainwin.html
+++ b/SourceGen/RuntimeData/Help/mainwin.html
@@ -216,10 +216,20 @@ For each reference, the file offset, address, and some details about the
type of reference will be shown.
The reference type indicates whether the origin is an instruction or
-data operand. Branch instructions are called out separately. In
-addition, it will be identified as a numeric or symbolic reference.
-Symbolic references may be offset from the actual operand value; if this
-is the case, the adjustment will be shown as well.
+data operand, and provides an indication of the nature of the reference:
+
+ - call - subroutine call (e.g. JSR addr, JSL addr)
+ - branch - conditional or unconditional branch (e.g. JMP addr, BCC addr)
+ - read - read from memory (e.g. LDA addr, BIT addr)
+ - write - write to memory (e.g. STA addr)
+ - rmw - read-modify-write (e.g. LSR addr, TSB addr)
+ - ref - address reference only (e.g. LDA #<addr, PEA addr)
+ - data - address referenced by data (e.g. .DD2 addr)
+
+In addition, the source will be identified as a symbolic ("Sym") or
+numeric ("Num") reference. Symbolic references may be offset from the
+actual operand value; if this is the case, the adjustment will be shown
+as well.
Double-clicking on a reference moves the code list selection to that
reference, and adds the previous selection to the navigation stack.
diff --git a/SourceGen/SymbolTable.cs b/SourceGen/SymbolTable.cs
index d847ed9..1d4926f 100644
--- a/SourceGen/SymbolTable.cs
+++ b/SourceGen/SymbolTable.cs
@@ -215,7 +215,7 @@ namespace SourceGen {
///
/// Generates a unique address symbol. Does not add the symbol to the list.
///
- /// Address label will be applied to
+ /// Address that label will be applied to.
/// Symbol table.
/// Prefix to use; must start with a letter.
/// Newly-created, unique symbol.
@@ -239,7 +239,7 @@ namespace SourceGen {
sb.Append(index);
label = sb.ToString();
} while (index <= MAX_RENAME && symbols.TryGetValue(label, out unused));
- if (index == MAX_RENAME) {
+ if (index > MAX_RENAME) {
// I give up
throw new Exception("Too many identical symbols");
}
diff --git a/SourceGen/XrefSet.cs b/SourceGen/XrefSet.cs
index dc399e9..3fa602e 100644
--- a/SourceGen/XrefSet.cs
+++ b/SourceGen/XrefSet.cs
@@ -28,12 +28,16 @@ namespace SourceGen {
public class XrefSet : IEnumerable {
///
/// Reference type. This is mostly useful for display to the user.
+ ///
+ /// The enum is in priority order, i.e. the lowest-valued
+ /// item "wins" in situations where only one value is used.
///
public enum XrefType {
Unknown = 0,
- InstrOperand, // generic instruction operand
- BranchOperand, // branch instruction
- DataOperand // e.g. ".dd2 "
+ SubCallOp, // subroutine call
+ BranchOp, // branch instruction
+ RefFromData, // reference in data area, e.g. ".dd2 "
+ MemAccessOp, // instruction that accesses memory, or refers to an address
}
///
@@ -41,7 +45,7 @@ namespace SourceGen {
///
public class Xref {
///
- /// Offset of start of instruction or data with the reference.
+ /// Offset of start of instruction or data that refers to the target offset.
///
public int Offset { get; private set; }
@@ -55,22 +59,29 @@ namespace SourceGen {
///
public XrefType Type { get; private set; }
+ ///
+ /// For Type==MemAccessOp, what type of memory access is performed.
+ ///
+ public Asm65.OpDef.MemoryEffect AccType { get; private set; }
+
///
/// Adjustment to symbol. For example, "LDA label+2" adds an xref entry to
/// "label", with an adjustment of +2.
///
public int Adjustment { get; private set; }
- public Xref(int offset, bool isSymbolic, XrefType type, int adjustment) {
+ public Xref(int offset, bool isSymbolic, XrefType type,
+ Asm65.OpDef.MemoryEffect accType, int adjustment) {
Offset = offset;
IsSymbolic = isSymbolic;
Type = type;
+ AccType = accType;
Adjustment = adjustment;
}
public override string ToString() {
return "Xref off=+" + Offset.ToString("x6") + " sym=" + IsSymbolic +
- " type=" + Type + " adj=" + Adjustment;
+ " type=" + Type + " accType= " + AccType + " adj=" + Adjustment;
}
}