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
// make a similar statement about the E flag.
if ((mods & OpDef.CycleMod.OneIfM0) != 0) {
if (!flags.ShortM) {
if (!flags.IsShortM) {
cycles++;
}
mods &= ~OpDef.CycleMod.OneIfM0;
}
if ((mods & OpDef.CycleMod.TwoIfM0) != 0) {
if (!flags.ShortM) {
if (!flags.IsShortM) {
cycles += 2;
}
mods &= ~OpDef.CycleMod.TwoIfM0;
}
if ((mods & OpDef.CycleMod.OneIfX0) != 0) {
if (!flags.ShortX) {
if (!flags.IsShortX) {
cycles++;
}
mods &= ~OpDef.CycleMod.OneIfX0;
}
if ((mods & OpDef.CycleMod.OneIfE0) != 0) {
if (flags.E == 0) {
if (!flags.IsEmulationMode) {
cycles++;
}
mods &= ~OpDef.CycleMod.OneIfE0;
@ -323,7 +323,7 @@ namespace Asm65 {
}
}
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
}
mods &= ~OpDef.CycleMod.OneIfBranchPage;

View File

@ -518,10 +518,10 @@ namespace Asm65 {
return 4;
case AddressMode.ImmLongA:
bool shortM = flags.ShortM;
bool shortM = flags.IsShortM;
return shortM ? 2 : 3;
case AddressMode.ImmLongXY:
bool shortX = flags.ShortX;
bool shortX = flags.IsShortX;
return shortX ? 2 : 3;
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 {
get {
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 {
get {
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 {
get {
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
/// (8-bit) accumulator.
/// </summary>
public bool ShortM {
/// <remarks>
/// This is where we decide how to treat ambiguous status flags.
/// </remarks>
public bool IsShortM {
get {
// E==1 --> true (we're in emulation mode)
// E==0 || E==? : native / assumed native
@ -239,13 +251,25 @@ namespace Asm65 {
/// Returns true if the current processor status flags are configured for short
/// (8-bit) X/Y registers.
/// </summary>
public bool ShortX {
public bool IsShortX {
get {
// (same logic as ShortM)
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>
/// Access the value as a single integer. Used for serialization.
/// </summary>

View File

@ -87,8 +87,8 @@ namespace SourceGen.AsmGen {
// that in the ORG output handler.
if (proj.CpuDef.HasEmuFlag) {
StatusFlags curFlags = attr.StatusFlags;
curFlags.M = attr.StatusFlags.ShortM ? 1 : 0;
curFlags.X = attr.StatusFlags.ShortX ? 1 : 0;
curFlags.M = attr.StatusFlags.IsShortM ? 1 : 0;
curFlags.X = attr.StatusFlags.IsShortX ? 1 : 0;
if (curFlags.M != prevFlags.M || curFlags.X != prevFlags.X) {
// changed, output directive
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
// 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 ((operand & 0x30) != 0 && attr.StatusFlags.E == 1) {
if ((operand & 0x30) != 0 && attr.StatusFlags.IsEmulationMode) {
gen.OutputRegWidthDirective(offset, 0, 0, 1, 1);
}
}

View File

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