1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-07-06 16:29:03 +00:00

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.
This commit is contained in:
Andy McFadden 2019-04-11 16:23:02 -07:00
parent 84eceee085
commit 47b1363738
10 changed files with 303 additions and 95 deletions

View File

@ -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)
};
}
/// <summary>
/// Effect of executing an instruction on memory.
/// </summary>
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
}
/// <summary>
/// Addressing mode. This uses the same distinctions as Eyes & Lichty, which for
@ -160,6 +171,22 @@ namespace Asm65 {
/// </summary>
public FlowEffect Effect { get; private set; }
/// <summary>
/// Effect this instruction has on memory.
/// </summary>
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; }
/// <summary>
/// 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 {
/// <summary>
/// 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).
/// </summary>
public bool IsBranch {
public bool IsBranchOrSubCall {
get {
return Effect == FlowEffect.Branch ||
Effect == FlowEffect.ConditionalBranch ||
@ -258,6 +286,15 @@ namespace Asm65 {
}
}
/// <summary>
/// True if this operation is a subroutine call.
/// </summary>
public bool IsSubroutineCall {
get {
return Effect == FlowEffect.CallSubroutine;
}
}
/// <summary>
/// True if the operand is an immediate value, which should be prefixed with '#'.
/// </summary>
@ -270,11 +307,11 @@ namespace Asm65 {
}
/// <summary>
/// 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.
/// </summary>
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,

View File

@ -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 #<symbol, PEA addr
typeStr = "ref ";
break;
case OpDef.MemoryEffect.Unknown:
default:
Debug.Assert(false);
typeStr = "??! ";
break;
}
break;
default:
Debug.Assert(false);
typeStr = "??? ";

View File

@ -336,9 +336,10 @@ namespace SourceGen.AsmGen {
// The assembler works correctly if the symbol is defined as a two-digit hex
// value (e.g. "foo equ $80") but fails if it's four (e.g. "foo equ $0080"). We
// output symbols with minimal digits, but we have no control over labels when
// the code has a zero-page EQU. So if the operand is a reference to a user
// label, we need to output the instruction as hex.
// output symbols with minimal digits, but this doesn't help if the code itself
// lives on zero page. If the operand is a reference to a zero-page user label,
// we need to output the instruction as hex.
// More info: https://github.com/apple2accumulator/merlin32/issues/8
if (op == OpDef.OpPEI_StackDPInd ||
op == OpDef.OpSTY_DPIndexX ||
op == OpDef.OpSTX_DPIndexY ||

View File

@ -537,7 +537,7 @@ namespace SourceGen {
bool doBranch, doContinue;
// Check for branching.
if (op.IsBranch) {
if (op.IsBranchOrSubCall) {
if (mAnattribs[offset].IsOperandOffsetDirect) {
branchOffset = mAnattribs[offset].OperandOffset;
}

View File

@ -347,6 +347,15 @@ namespace SourceGen {
isBigEndian);
}
/// <summary>
/// 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.
/// </summary>
/// <param name="srcOffset">Reference source.</param>
/// <param name="targetOffset">Reference target.</param>
/// <returns>New value for targetOffset, or original value if nothing better was
/// found.</returns>
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) {

View File

@ -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 {
}
/// <summary>
/// Updates all symbolic references to the old label.
/// Updates all symbolic references to the old label. Call this after replacing
/// mAnattribs[labelOffset].Symbol.
/// </summary>
/// <param name="labelOffset">Offset with the just-renamed label.</param>
/// <param name="oldLabel">Previous value.</param>
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),

View File

@ -127,7 +127,7 @@ code, but also needs to know how to handle the corner cases.</p>
<p>Bugs:</p>
<ul>
<li>Undocumented opcodes: <code>SHA (ZP),Y</code> ($93) is not supported;
<li>Undocumented opcode <code>SHA (ZP),Y</code> ($93) is not supported;
the assembler appears to be expecting <code>SHA ABS,X</code> instead.</li>
<li>BRK, COP, and WDM are not allowed to have operands.</li>
</ul>
@ -166,7 +166,6 @@ code, but also needs to know how to handle the corner cases.</p>
<li>PC relative branches don't wrap around at bank boundaries.</li>
<li>BRK &lt;arg&gt; is assembled to opcode $05 rather than $00.</li>
<li>WDM is not supported.</li>
<li>Source file names may not have spaces in them on Windows.</li>
</ul>
<p>Quirks:</p>
@ -178,8 +177,8 @@ code, but also needs to know how to handle the corner cases.</p>
more common interpretation would be <code>label >> (8 - 16)</code>.
(This is actually somewhat convenient, since none of the expressions
SourceGen currently generates require parenthesis.)</li>
<li>Undocumented opcodes: SBX ($cb) uses the mnemonic AXS. All other
opcodes match up with the "unintended opcodes" document.</li>
<li>Undocumented opcode <code>SBX</code> ($cb) uses the mnemonic AXS. All
other opcodes match up with the "unintended opcodes" document.</li>
<li>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.</p>
<li>Values loaded into registers are implicitly mod 256 or 65536. There
is no need to explicitly mask an expression.</li>
<li>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
<code>REP #$20</code>
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.)</li>

View File

@ -216,10 +216,20 @@ For each reference, the file offset, address, and some details about the
type of reference will be shown.</p>
<p>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.</p>
data operand, and provides an indication of the nature of the reference:</p>
<ul>
<li>call - subroutine call (e.g. JSR addr, JSL addr)</li>
<li>branch - conditional or unconditional branch (e.g. JMP addr, BCC addr)</li>
<li>read - read from memory (e.g. LDA addr, BIT addr)</li>
<li>write - write to memory (e.g. STA addr)</li>
<li>rmw - read-modify-write (e.g. LSR addr, TSB addr)</li>
<li>ref - address reference only (e.g. LDA #&lt;addr, PEA addr)</li>
<li>data - address referenced by data (e.g. .DD2 addr)</li>
</ul>
<p>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.</p>
<p>Double-clicking on a reference moves the code list selection to that
reference, and adds the previous selection to the navigation stack.</p>

View File

@ -215,7 +215,7 @@ namespace SourceGen {
/// <summary>
/// Generates a unique address symbol. Does not add the symbol to the list.
/// </summary>
/// <param name="addr">Address label will be applied to</param>
/// <param name="addr">Address that label will be applied to.</param>
/// <param name="symbols">Symbol table.</param>
/// <param name="prefix">Prefix to use; must start with a letter.</param>
/// <returns>Newly-created, unique symbol.</returns>
@ -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");
}

View File

@ -28,12 +28,16 @@ namespace SourceGen {
public class XrefSet : IEnumerable<XrefSet.Xref> {
/// <summary>
/// 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.
/// </summary>
public enum XrefType {
Unknown = 0,
InstrOperand, // generic instruction operand
BranchOperand, // branch instruction
DataOperand // e.g. ".dd2 <address>"
SubCallOp, // subroutine call
BranchOp, // branch instruction
RefFromData, // reference in data area, e.g. ".dd2 <address>"
MemAccessOp, // instruction that accesses memory, or refers to an address
}
/// <summary>
@ -41,7 +45,7 @@ namespace SourceGen {
/// </summary>
public class Xref {
/// <summary>
/// Offset of start of instruction or data with the reference.
/// Offset of start of instruction or data that refers to the target offset.
/// </summary>
public int Offset { get; private set; }
@ -55,22 +59,29 @@ namespace SourceGen {
/// </summary>
public XrefType Type { get; private set; }
/// <summary>
/// For Type==MemAccessOp, what type of memory access is performed.
/// </summary>
public Asm65.OpDef.MemoryEffect AccType { get; private set; }
/// <summary>
/// Adjustment to symbol. For example, "LDA label+2" adds an xref entry to
/// "label", with an adjustment of +2.
/// </summary>
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;
}
}