mirror of
https://github.com/fadden/6502bench.git
synced 2024-10-31 19:04:44 +00:00
Fix display of instruction attributes
The "affected flags" constants were incorrect for BIT, BRK, COP, RTI, XCE, and the undocmented instructions ANE, DCP, and SAX. The constants are used for the changed-flag summary shown in the info window and the instruction chart. Of greater import: the status flag updater for BIT was incorrectly marking N/V/C as indeterminate instead of N/V/Z. The undocmented instructions ANE, DCP, and SAX were also incorrect. The cycle counts shown in line comments are computed correctly, but the counts shown in the info window and instruction chart were displaying the full set of modifiers, ignoring the CPU type. That's okay for the info window, which spells the modifiers out, though it'd be better if the bits were explicitly marked as being applicable to the current CPU or a different one.
This commit is contained in:
parent
7bbccaf71f
commit
1b0ee7de21
@ -242,6 +242,14 @@ namespace Asm65 {
|
|||||||
/// <returns>Instruction definition.</returns>
|
/// <returns>Instruction definition.</returns>
|
||||||
public OpDef GetOpDef(int op) { return mOpDefs[op]; }
|
public OpDef GetOpDef(int op) { return mOpDefs[op]; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the set of cycle mods for the given instruction that are in effect
|
||||||
|
/// for the current CPU.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="op">Instruction opcode number (0-255).</param>
|
||||||
|
/// <returns>Reduced cycle mod set.</returns>
|
||||||
|
public OpDef.CycleMod GetOpCycleMod(int op) { return mCycleMods[op]; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indexer. Returns the definition of opcode N.
|
/// Indexer. Returns the definition of opcode N.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -196,6 +196,10 @@ namespace Asm65 {
|
|||||||
/// Cycles required. The low 8 bits hold the base cycle count, the remaining bits
|
/// Cycles required. The low 8 bits hold the base cycle count, the remaining bits
|
||||||
/// are defined by the CycleMod enum.
|
/// are defined by the CycleMod enum.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remaks>
|
||||||
|
/// This always returns the full set of possible cycle mods. In most cases you want
|
||||||
|
/// the set that has irrelevant mods masked out. See CpuDef.GetOpCycleMod().
|
||||||
|
/// </remaks>
|
||||||
private int CycDef { get; set; }
|
private int CycDef { get; set; }
|
||||||
public int Cycles { get { return CycDef & 0xff; } }
|
public int Cycles { get { return CycDef & 0xff; } }
|
||||||
public CycleMod CycleMods { get { return (CycleMod)(CycDef & ~0xff); } }
|
public CycleMod CycleMods { get { return (CycleMod)(CycDef & ~0xff); } }
|
||||||
@ -301,8 +305,14 @@ namespace Asm65 {
|
|||||||
new StatusFlags() { Z = 1 };
|
new StatusFlags() { Z = 1 };
|
||||||
private static StatusFlags FlagsAffected_C =
|
private static StatusFlags FlagsAffected_C =
|
||||||
new StatusFlags() { C = 1 };
|
new StatusFlags() { C = 1 };
|
||||||
|
private static StatusFlags FlagsAffected_MXCE =
|
||||||
|
new StatusFlags() { M = 1, X = 1, C = 1, E = 1 };
|
||||||
|
private static StatusFlags FlagsAffected_DI =
|
||||||
|
new StatusFlags() { D = 1, I = 1 };
|
||||||
private static StatusFlags FlagsAffected_NZ =
|
private static StatusFlags FlagsAffected_NZ =
|
||||||
new StatusFlags() { N = 1, Z = 1 };
|
new StatusFlags() { N = 1, Z = 1 };
|
||||||
|
private static StatusFlags FlagsAffected_NVZ =
|
||||||
|
new StatusFlags() { N = 1, V = 1, Z = 1 };
|
||||||
private static StatusFlags FlagsAffected_NZC =
|
private static StatusFlags FlagsAffected_NZC =
|
||||||
new StatusFlags() { N = 1, Z = 1, C = 1 };
|
new StatusFlags() { N = 1, Z = 1, C = 1 };
|
||||||
private static StatusFlags FlagsAffected_NVZC =
|
private static StatusFlags FlagsAffected_NVZC =
|
||||||
@ -626,6 +636,11 @@ namespace Asm65 {
|
|||||||
flags.Z = flags.N = TriState16.INDETERMINATE;
|
flags.Z = flags.N = TriState16.INDETERMINATE;
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
private static StatusFlags FlagUpdater_NVZ(StatusFlags flags, int immVal,
|
||||||
|
ref StatusFlags condBranchTakenFlags) {
|
||||||
|
flags.Z = flags.V = flags.N = TriState16.INDETERMINATE;
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
private static StatusFlags FlagUpdater_NZC(StatusFlags flags, int immVal,
|
private static StatusFlags FlagUpdater_NZC(StatusFlags flags, int immVal,
|
||||||
ref StatusFlags condBranchTakenFlags) {
|
ref StatusFlags condBranchTakenFlags) {
|
||||||
flags.C = flags.Z = flags.N = TriState16.INDETERMINATE;
|
flags.C = flags.Z = flags.N = TriState16.INDETERMINATE;
|
||||||
@ -879,8 +894,8 @@ namespace Asm65 {
|
|||||||
Mnemonic = OpName.BIT,
|
Mnemonic = OpName.BIT,
|
||||||
Effect = FlowEffect.Cont,
|
Effect = FlowEffect.Cont,
|
||||||
BaseMemEffect = MemoryEffect.None,
|
BaseMemEffect = MemoryEffect.None,
|
||||||
FlagsAffected = FlagsAffected_NZC, // special handling for imm
|
FlagsAffected = FlagsAffected_NVZ, // special handling for imm
|
||||||
StatusFlagUpdater = FlagUpdater_NZC // special handling for imm
|
StatusFlagUpdater = FlagUpdater_NVZ // special handling for imm
|
||||||
};
|
};
|
||||||
private static OpDef OpBMI = new OpDef() {
|
private static OpDef OpBMI = new OpDef() {
|
||||||
Mnemonic = OpName.BMI,
|
Mnemonic = OpName.BMI,
|
||||||
@ -923,7 +938,14 @@ namespace Asm65 {
|
|||||||
private static OpDef OpBRK = new OpDef() {
|
private static OpDef OpBRK = new OpDef() {
|
||||||
Mnemonic = OpName.BRK,
|
Mnemonic = OpName.BRK,
|
||||||
Effect = FlowEffect.NoCont,
|
Effect = FlowEffect.NoCont,
|
||||||
BaseMemEffect = MemoryEffect.None
|
BaseMemEffect = MemoryEffect.None,
|
||||||
|
// On 6502/65C02 this also affects the 'B' flag, which overlaps with X. Nobody
|
||||||
|
// really cares though. On 6502 this doesn't clear the 'D' flag.
|
||||||
|
//
|
||||||
|
// We don't set a StatusFlagUpdater because the flags are only changed for the
|
||||||
|
// software break handler function. If we could actually track this into that,
|
||||||
|
// we'd need to configure the flags appropriately based on CPU type.
|
||||||
|
FlagsAffected = FlagsAffected_DI
|
||||||
};
|
};
|
||||||
private static OpDef OpBRL = new OpDef() {
|
private static OpDef OpBRL = new OpDef() {
|
||||||
Mnemonic = OpName.BRL,
|
Mnemonic = OpName.BRL,
|
||||||
@ -1006,7 +1028,8 @@ namespace Asm65 {
|
|||||||
private static OpDef OpCOP = new OpDef() {
|
private static OpDef OpCOP = new OpDef() {
|
||||||
Mnemonic = OpName.COP,
|
Mnemonic = OpName.COP,
|
||||||
Effect = FlowEffect.Cont,
|
Effect = FlowEffect.Cont,
|
||||||
BaseMemEffect = MemoryEffect.None
|
BaseMemEffect = MemoryEffect.None,
|
||||||
|
FlagsAffected = FlagsAffected_DI
|
||||||
};
|
};
|
||||||
private static OpDef OpCPX = new OpDef() {
|
private static OpDef OpCPX = new OpDef() {
|
||||||
Mnemonic = OpName.CPX,
|
Mnemonic = OpName.CPX,
|
||||||
@ -1264,6 +1287,7 @@ namespace Asm65 {
|
|||||||
Mnemonic = OpName.RTI,
|
Mnemonic = OpName.RTI,
|
||||||
Effect = FlowEffect.NoCont,
|
Effect = FlowEffect.NoCont,
|
||||||
BaseMemEffect = MemoryEffect.None,
|
BaseMemEffect = MemoryEffect.None,
|
||||||
|
FlagsAffected = FlagsAffected_All
|
||||||
};
|
};
|
||||||
private static OpDef OpRTL = new OpDef() {
|
private static OpDef OpRTL = new OpDef() {
|
||||||
Mnemonic = OpName.RTL,
|
Mnemonic = OpName.RTL,
|
||||||
@ -1462,7 +1486,7 @@ namespace Asm65 {
|
|||||||
Mnemonic = OpName.XCE,
|
Mnemonic = OpName.XCE,
|
||||||
Effect = FlowEffect.Cont,
|
Effect = FlowEffect.Cont,
|
||||||
BaseMemEffect = MemoryEffect.None,
|
BaseMemEffect = MemoryEffect.None,
|
||||||
FlagsAffected = FlagsAffected_C,
|
FlagsAffected = FlagsAffected_MXCE,
|
||||||
StatusFlagUpdater = FlagUpdater_XCE
|
StatusFlagUpdater = FlagUpdater_XCE
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2880,7 +2904,9 @@ namespace Asm65 {
|
|||||||
IsUndocumented = true,
|
IsUndocumented = true,
|
||||||
Mnemonic = OpName.ANE,
|
Mnemonic = OpName.ANE,
|
||||||
Effect = FlowEffect.Cont,
|
Effect = FlowEffect.Cont,
|
||||||
BaseMemEffect = MemoryEffect.None
|
BaseMemEffect = MemoryEffect.None,
|
||||||
|
FlagsAffected = FlagsAffected_NZ,
|
||||||
|
StatusFlagUpdater = FlagUpdater_NZ
|
||||||
};
|
};
|
||||||
private static OpDef OpALR = new OpDef() {
|
private static OpDef OpALR = new OpDef() {
|
||||||
IsUndocumented = true,
|
IsUndocumented = true,
|
||||||
@ -2903,8 +2929,8 @@ namespace Asm65 {
|
|||||||
Mnemonic = OpName.DCP,
|
Mnemonic = OpName.DCP,
|
||||||
Effect = FlowEffect.Cont,
|
Effect = FlowEffect.Cont,
|
||||||
BaseMemEffect = MemoryEffect.ReadModifyWrite,
|
BaseMemEffect = MemoryEffect.ReadModifyWrite,
|
||||||
FlagsAffected = FlagsAffected_C,
|
FlagsAffected = FlagsAffected_NZC,
|
||||||
StatusFlagUpdater = FlagUpdater_C
|
StatusFlagUpdater = FlagUpdater_NZC
|
||||||
};
|
};
|
||||||
private static OpDef OpDOP = new OpDef() { // double-byte NOP
|
private static OpDef OpDOP = new OpDef() { // double-byte NOP
|
||||||
IsUndocumented = true,
|
IsUndocumented = true,
|
||||||
@ -2962,9 +2988,7 @@ namespace Asm65 {
|
|||||||
IsUndocumented = true,
|
IsUndocumented = true,
|
||||||
Mnemonic = OpName.SAX,
|
Mnemonic = OpName.SAX,
|
||||||
Effect = FlowEffect.Cont,
|
Effect = FlowEffect.Cont,
|
||||||
BaseMemEffect = MemoryEffect.Write,
|
BaseMemEffect = MemoryEffect.Write
|
||||||
FlagsAffected = FlagsAffected_NZ,
|
|
||||||
StatusFlagUpdater = FlagUpdater_NZ
|
|
||||||
};
|
};
|
||||||
private static OpDef OpSBX = new OpDef() {
|
private static OpDef OpSBX = new OpDef() {
|
||||||
IsUndocumented = true,
|
IsUndocumented = true,
|
||||||
|
@ -3608,6 +3608,10 @@ namespace SourceGen {
|
|||||||
|
|
||||||
sb.Append("\u2022Cycles: ");
|
sb.Append("\u2022Cycles: ");
|
||||||
int cycles = op.Cycles;
|
int cycles = op.Cycles;
|
||||||
|
// TODO: diff GetOpCycleMod vs. op.CycleMods to show which bits apply to
|
||||||
|
// current CPU vs. other CPUs
|
||||||
|
//Asm65.OpDef.CycleMod cycMods =
|
||||||
|
// mProject.CpuDef.GetOpCycleMod(mProject.FileData[line.FileOffset]);
|
||||||
Asm65.OpDef.CycleMod cycMods = op.CycleMods;
|
Asm65.OpDef.CycleMod cycMods = op.CycleMods;
|
||||||
sb.Append(cycles.ToString());
|
sb.Append(cycles.ToString());
|
||||||
if (cycMods != 0) {
|
if (cycMods != 0) {
|
||||||
|
@ -61,6 +61,9 @@ ASCII.</p>
|
|||||||
<p>This opens a window with a summary of all 256 opcodes. The CPU can
|
<p>This opens a window with a summary of all 256 opcodes. The CPU can
|
||||||
be chosen from the pop-up list at the bottom. Undocumented opcodes are
|
be chosen from the pop-up list at the bottom. Undocumented opcodes are
|
||||||
shown in italics.</p>
|
shown in italics.</p>
|
||||||
|
<p>The status flags affected by each instruction are shown for the 65816
|
||||||
|
implementation. The only significant difference vs. 6502/65C02
|
||||||
|
is in the way the BRK instruction affects the D and B/X flags.</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -141,8 +141,8 @@ namespace SourceGen.Tools.WpfGui {
|
|||||||
// Populate the items source.
|
// Populate the items source.
|
||||||
InstructionItems.Clear();
|
InstructionItems.Clear();
|
||||||
CpuDef cpuDef = CpuDef.GetBestMatch(item.Type, true, false);
|
CpuDef cpuDef = CpuDef.GetBestMatch(item.Type, true, false);
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int opc = 0; opc < 256; opc++) {
|
||||||
OpDef op = cpuDef[i];
|
OpDef op = cpuDef[opc];
|
||||||
|
|
||||||
int opLen = op.GetLength(StatusFlags.AllIndeterminate);
|
int opLen = op.GetLength(StatusFlags.AllIndeterminate);
|
||||||
string sampleValue = "$12";
|
string sampleValue = "$12";
|
||||||
@ -169,11 +169,12 @@ namespace SourceGen.Tools.WpfGui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string cycles = op.Cycles.ToString();
|
string cycles = op.Cycles.ToString();
|
||||||
if (op.CycleMods != 0) {
|
OpDef.CycleMod mods = cpuDef.GetOpCycleMod(opc);
|
||||||
|
if (mods != 0) {
|
||||||
cycles += '+';
|
cycles += '+';
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionItems.Add(new InstructionItem(mFormatter.FormatHexValue(i, 2),
|
InstructionItems.Add(new InstructionItem(mFormatter.FormatHexValue(opc, 2),
|
||||||
instrSample, flags.ToString(), cycles,
|
instrSample, flags.ToString(), cycles,
|
||||||
mOpDesc.GetShortDescription(op.Mnemonic),
|
mOpDesc.GetShortDescription(op.Mnemonic),
|
||||||
mOpDesc.GetAddressModeDescription(op.AddrMode),
|
mOpDesc.GetAddressModeDescription(op.AddrMode),
|
||||||
|
Loading…
Reference in New Issue
Block a user