1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-12-01 07:50:37 +00:00

Tweak M/X/E flag handling

The decision of how to handle indeterminate M/X flag values is made in
StatusFlags.  This provides consistent behavior throughout the app.
This was being done for M/X but not for E.

This change also renames the M/X tests, prefixing them with "Is" to
emphasize that they are boolean rather than tri-state.

There should be no change in behavior from this.
This commit is contained in:
Andy McFadden 2020-07-06 08:27:42 -07:00
parent 4e70edc90c
commit bc15178a8e
5 changed files with 40 additions and 16 deletions

View File

@ -281,25 +281,25 @@ namespace Asm65 {
// appropriately. So there's no ambiguity here even when there's ambiguity. We // appropriately. So there's no ambiguity here even when there's ambiguity. We
// make a similar statement about the E flag. // make a similar statement about the E flag.
if ((mods & OpDef.CycleMod.OneIfM0) != 0) { if ((mods & OpDef.CycleMod.OneIfM0) != 0) {
if (!flags.ShortM) { if (!flags.IsShortM) {
cycles++; cycles++;
} }
mods &= ~OpDef.CycleMod.OneIfM0; mods &= ~OpDef.CycleMod.OneIfM0;
} }
if ((mods & OpDef.CycleMod.TwoIfM0) != 0) { if ((mods & OpDef.CycleMod.TwoIfM0) != 0) {
if (!flags.ShortM) { if (!flags.IsShortM) {
cycles += 2; cycles += 2;
} }
mods &= ~OpDef.CycleMod.TwoIfM0; mods &= ~OpDef.CycleMod.TwoIfM0;
} }
if ((mods & OpDef.CycleMod.OneIfX0) != 0) { if ((mods & OpDef.CycleMod.OneIfX0) != 0) {
if (!flags.ShortX) { if (!flags.IsShortX) {
cycles++; cycles++;
} }
mods &= ~OpDef.CycleMod.OneIfX0; mods &= ~OpDef.CycleMod.OneIfX0;
} }
if ((mods & OpDef.CycleMod.OneIfE0) != 0) { if ((mods & OpDef.CycleMod.OneIfE0) != 0) {
if (flags.E == 0) { if (!flags.IsEmulationMode) {
cycles++; cycles++;
} }
mods &= ~OpDef.CycleMod.OneIfE0; mods &= ~OpDef.CycleMod.OneIfE0;
@ -323,7 +323,7 @@ namespace Asm65 {
} }
} }
if ((mods & OpDef.CycleMod.OneIfBranchPage) != 0) { if ((mods & OpDef.CycleMod.OneIfBranchPage) != 0) {
if (branchCrossesPage && flags.E != 0) { if (branchCrossesPage && flags.IsEmulationMode) {
cycles++; // +1 unless we're in native mode on 65816 cycles++; // +1 unless we're in native mode on 65816
} }
mods &= ~OpDef.CycleMod.OneIfBranchPage; mods &= ~OpDef.CycleMod.OneIfBranchPage;

View File

@ -518,10 +518,10 @@ namespace Asm65 {
return 4; return 4;
case AddressMode.ImmLongA: case AddressMode.ImmLongA:
bool shortM = flags.ShortM; bool shortM = flags.IsShortM;
return shortM ? 2 : 3; return shortM ? 2 : 3;
case AddressMode.ImmLongXY: case AddressMode.ImmLongXY:
bool shortX = flags.ShortX; bool shortX = flags.IsShortX;
return shortX ? 2 : 3; return shortX ? 2 : 3;
default: default:

View File

@ -132,6 +132,9 @@ namespace Asm65 {
} }
} }
/// <summary>
/// X (index register width) flag. For an unambiguous value, use IsShortX.
/// </summary>
public int X { public int X {
get { get {
return mState.GetBit((int)FlagBits.X); return mState.GetBit((int)FlagBits.X);
@ -149,6 +152,9 @@ namespace Asm65 {
} }
} }
/// <summary>
/// M (accumulator width) flag. For an unambiguous value, use IsShortM.
/// </summary>
public int M { public int M {
get { get {
return mState.GetBit((int)FlagBits.M); return mState.GetBit((int)FlagBits.M);
@ -200,6 +206,9 @@ namespace Asm65 {
} }
} }
/// <summary>
/// E (emulation) flag. For an unambiguous value, use IsEmulationMode.
/// </summary>
public int E { public int E {
get { get {
return mState.GetBit((int)FlagBits.E); return mState.GetBit((int)FlagBits.E);
@ -225,7 +234,10 @@ namespace Asm65 {
/// Returns true if the current processor status flags are configured for a short /// Returns true if the current processor status flags are configured for a short
/// (8-bit) accumulator. /// (8-bit) accumulator.
/// </summary> /// </summary>
public bool ShortM { /// <remarks>
/// This is where we decide how to treat ambiguous status flags.
/// </remarks>
public bool IsShortM {
get { get {
// E==1 --> true (we're in emulation mode) // E==1 --> true (we're in emulation mode)
// E==0 || E==? : native / assumed native // E==0 || E==? : native / assumed native
@ -239,13 +251,25 @@ namespace Asm65 {
/// Returns true if the current processor status flags are configured for short /// Returns true if the current processor status flags are configured for short
/// (8-bit) X/Y registers. /// (8-bit) X/Y registers.
/// </summary> /// </summary>
public bool ShortX { public bool IsShortX {
get { get {
// (same logic as ShortM) // (same logic as ShortM)
return (E == 1) || (X != 0); return (E == 1) || (X != 0);
} }
} }
/// <summary>
/// Returns true if the current processor status flags are configured for execution
/// in native mode.
/// </summary>
public bool IsEmulationMode {
get {
// E==1 : emulation --> true
// E==0 || E==? : native / assumed native --> false
return E == 1;
}
}
/// <summary> /// <summary>
/// Access the value as a single integer. Used for serialization. /// Access the value as a single integer. Used for serialization.
/// </summary> /// </summary>

View File

@ -87,8 +87,8 @@ namespace SourceGen.AsmGen {
// that in the ORG output handler. // that in the ORG output handler.
if (proj.CpuDef.HasEmuFlag) { if (proj.CpuDef.HasEmuFlag) {
StatusFlags curFlags = attr.StatusFlags; StatusFlags curFlags = attr.StatusFlags;
curFlags.M = attr.StatusFlags.ShortM ? 1 : 0; curFlags.M = attr.StatusFlags.IsShortM ? 1 : 0;
curFlags.X = attr.StatusFlags.ShortX ? 1 : 0; curFlags.X = attr.StatusFlags.IsShortX ? 1 : 0;
if (curFlags.M != prevFlags.M || curFlags.X != prevFlags.X) { if (curFlags.M != prevFlags.M || curFlags.X != prevFlags.X) {
// changed, output directive // changed, output directive
gen.OutputRegWidthDirective(offset, prevFlags.M, prevFlags.X, gen.OutputRegWidthDirective(offset, prevFlags.M, prevFlags.X,
@ -355,7 +355,7 @@ namespace SourceGen.AsmGen {
// Assemblers like Merlin32 try to be helpful and track SEP/REP, but they do the // Assemblers like Merlin32 try to be helpful and track SEP/REP, but they do the
// wrong thing if we're in emulation mode. Force flags back to short. // wrong thing if we're in emulation mode. Force flags back to short.
if (proj.CpuDef.HasEmuFlag && gen.Quirks.TracksSepRepNotEmu && op == OpDef.OpREP_Imm) { if (proj.CpuDef.HasEmuFlag && gen.Quirks.TracksSepRepNotEmu && op == OpDef.OpREP_Imm) {
if ((operand & 0x30) != 0 && attr.StatusFlags.E == 1) { if ((operand & 0x30) != 0 && attr.StatusFlags.IsEmulationMode) {
gen.OutputRegWidthDirective(offset, 0, 0, 1, 1); gen.OutputRegWidthDirective(offset, 0, 0, 1, 1);
} }
} }

View File

@ -928,8 +928,8 @@ namespace SourceGen {
if (attr.IsInstructionStart) { if (attr.IsInstructionStart) {
prevFlags = attr.StatusFlags; prevFlags = attr.StatusFlags;
// Apply the same tweak here that we do to curFlags below. // Apply the same tweak here that we do to curFlags below.
prevFlags.M = attr.StatusFlags.ShortM ? 1 : 0; prevFlags.M = attr.StatusFlags.IsShortM ? 1 : 0;
prevFlags.X = attr.StatusFlags.ShortX ? 1 : 0; prevFlags.X = attr.StatusFlags.IsShortX ? 1 : 0;
Debug.WriteLine("GenerateLineList startOff=+" + Debug.WriteLine("GenerateLineList startOff=+" +
startOffset.ToString("x6") + " using initial flags from +" + startOffset.ToString("x6") + " using initial flags from +" +
scanoff.ToString("x6") + ": " + prevFlags); scanoff.ToString("x6") + ": " + prevFlags);
@ -1017,8 +1017,8 @@ namespace SourceGen {
// assembler something. So we tweak our local copy and propagate it. // assembler something. So we tweak our local copy and propagate it.
string operandStr = string.Empty; string operandStr = string.Empty;
StatusFlags curFlags = attr.StatusFlags; StatusFlags curFlags = attr.StatusFlags;
curFlags.M = attr.StatusFlags.ShortM ? 1 : 0; curFlags.M = attr.StatusFlags.IsShortM ? 1 : 0;
curFlags.X = attr.StatusFlags.ShortX ? 1 : 0; curFlags.X = attr.StatusFlags.IsShortX ? 1 : 0;
if (curFlags.M != prevFlags.M) { if (curFlags.M != prevFlags.M) {
operandStr = (curFlags.M == 0) ? "longm" : "shortm"; operandStr = (curFlags.M == 0) ? "longm" : "shortm";
} }