mirror of
https://github.com/fadden/6502bench.git
synced 2024-12-31 21:30:59 +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:
parent
84eceee085
commit
47b1363738
256
Asm65/OpDef.cs
256
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)
|
||||
};
|
||||
}
|
||||
|
||||
/// <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,
|
||||
|
@ -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 = "??? ";
|
||||
|
@ -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 ||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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),
|
||||
|
@ -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 <arg> 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>
|
||||
|
@ -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 #<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>
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user