mirror of
https://github.com/fadden/6502bench.git
synced 2025-02-07 14:31:00 +00:00
Make "smart" PLP handling optional
We try to be clever with PHP/PLP, but sometimes we get it wrong. If we get it wrong a lot, we want to turn it off. Now we can.
This commit is contained in:
parent
54e7f68490
commit
431ad94d95
@ -146,6 +146,11 @@ namespace SourceGen {
|
||||
/// </summary>
|
||||
private StatusFlags mEntryFlags;
|
||||
|
||||
/// <summary>
|
||||
/// User-configurable analysis parameters.
|
||||
/// </summary>
|
||||
private ProjectProperties.AnalysisParameters mAnalysisParameters;
|
||||
|
||||
/// <summary>
|
||||
/// Debug trace log.
|
||||
/// </summary>
|
||||
@ -168,7 +173,8 @@ namespace SourceGen {
|
||||
/// <param name="debugLog">Object that receives debug log messages.</param>
|
||||
public CodeAnalysis(byte[] data, CpuDef cpuDef, Anattrib[] anattribs,
|
||||
AddressMap addrMap, TypeHint[] hints, StatusFlags[] statusFlagOverrides,
|
||||
StatusFlags entryFlags, ScriptManager scriptMan, DebugLog debugLog) {
|
||||
StatusFlags entryFlags, ProjectProperties.AnalysisParameters parms,
|
||||
ScriptManager scriptMan, DebugLog debugLog) {
|
||||
mFileData = data;
|
||||
mCpuDef = cpuDef;
|
||||
mAnattribs = anattribs;
|
||||
@ -177,6 +183,7 @@ namespace SourceGen {
|
||||
mStatusFlagOverrides = statusFlagOverrides;
|
||||
mEntryFlags = entryFlags;
|
||||
mScriptManager = scriptMan;
|
||||
mAnalysisParameters = parms;
|
||||
mDebugLog = debugLog;
|
||||
|
||||
mScriptSupport = new ScriptSupport(this);
|
||||
@ -789,16 +796,18 @@ namespace SourceGen {
|
||||
backOffsetLimit = 0;
|
||||
}
|
||||
StatusFlags flags = StatusFlags.AllIndeterminate;
|
||||
for (int offset = plpOffset - 1; offset >= backOffsetLimit; offset--) {
|
||||
Anattrib attr = mAnattribs[offset];
|
||||
if (!attr.IsInstructionStart || !attr.IsVisited) {
|
||||
continue;
|
||||
}
|
||||
OpDef op = mCpuDef.GetOpDef(mFileData[offset]);
|
||||
if (op == OpDef.OpPHP_StackPush) {
|
||||
LogI(plpOffset, "Found visited PHP at +" + offset.ToString("x6"));
|
||||
flags = mAnattribs[offset].StatusFlags;
|
||||
break;
|
||||
if (mAnalysisParameters.SmartPlpHandling) {
|
||||
for (int offset = plpOffset - 1; offset >= backOffsetLimit; offset--) {
|
||||
Anattrib attr = mAnattribs[offset];
|
||||
if (!attr.IsInstructionStart || !attr.IsVisited) {
|
||||
continue;
|
||||
}
|
||||
OpDef op = mCpuDef.GetOpDef(mFileData[offset]);
|
||||
if (op == OpDef.OpPHP_StackPush) {
|
||||
LogI(plpOffset, "Found visited PHP at +" + offset.ToString("x6"));
|
||||
flags = mAnattribs[offset].StatusFlags;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -618,8 +618,8 @@ namespace SourceGen {
|
||||
reanalysisTimer.StartTask("CodeAnalysis.Analyze");
|
||||
|
||||
CodeAnalysis ca = new CodeAnalysis(mFileData, CpuDef, mAnattribs, AddrMap,
|
||||
TypeHints, StatusFlagOverrides, ProjectProps.EntryFlags, mScriptManager,
|
||||
debugLog);
|
||||
TypeHints, StatusFlagOverrides, ProjectProps.EntryFlags,
|
||||
ProjectProps.AnalysisParams, mScriptManager, debugLog);
|
||||
|
||||
ca.Analyze();
|
||||
reanalysisTimer.EndTask("CodeAnalysis.Analyze");
|
||||
|
@ -219,6 +219,7 @@ namespace SourceGen {
|
||||
public string DefaultTextScanMode { get; set; }
|
||||
public int MinCharsForString { get; set; }
|
||||
public bool SeekNearbyTargets { get; set; }
|
||||
public bool SmartPlpHandling { get; set; }
|
||||
|
||||
public SerAnalysisParameters() { }
|
||||
public SerAnalysisParameters(ProjectProperties.AnalysisParameters src) {
|
||||
@ -226,6 +227,7 @@ namespace SourceGen {
|
||||
DefaultTextScanMode = src.DefaultTextScanMode.ToString();
|
||||
MinCharsForString = src.MinCharsForString;
|
||||
SeekNearbyTargets = src.SeekNearbyTargets;
|
||||
SmartPlpHandling = src.SmartPlpHandling;
|
||||
}
|
||||
}
|
||||
public class SerAddressMap {
|
||||
@ -511,6 +513,13 @@ namespace SourceGen {
|
||||
spf.ProjectProps.AnalysisParams.MinCharsForString;
|
||||
proj.ProjectProps.AnalysisParams.SeekNearbyTargets =
|
||||
spf.ProjectProps.AnalysisParams.SeekNearbyTargets;
|
||||
if (spf._ContentVersion < 2) {
|
||||
// This was made optional in v1.3. Default it to true for older projects.
|
||||
proj.ProjectProps.AnalysisParams.SmartPlpHandling = true;
|
||||
} else {
|
||||
proj.ProjectProps.AnalysisParams.SmartPlpHandling =
|
||||
spf.ProjectProps.AnalysisParams.SmartPlpHandling;
|
||||
}
|
||||
|
||||
// Deserialize ProjectProperties: external file identifiers.
|
||||
Debug.Assert(proj.ProjectProps.PlatformSymbolFileIdentifiers.Count == 0);
|
||||
|
@ -51,18 +51,22 @@ namespace SourceGen {
|
||||
public TextScanMode DefaultTextScanMode { get; set; }
|
||||
public int MinCharsForString { get; set; }
|
||||
public bool SeekNearbyTargets { get; set; }
|
||||
public bool SmartPlpHandling { get; set; }
|
||||
|
||||
public AnalysisParameters() {
|
||||
// Set default values.
|
||||
AnalyzeUncategorizedData = true;
|
||||
DefaultTextScanMode = TextScanMode.LowHighAscii;
|
||||
MinCharsForString = DataAnalysis.DEFAULT_MIN_STRING_LENGTH;
|
||||
SeekNearbyTargets = true;
|
||||
SmartPlpHandling = true;
|
||||
}
|
||||
public AnalysisParameters(AnalysisParameters src) {
|
||||
AnalyzeUncategorizedData = src.AnalyzeUncategorizedData;
|
||||
DefaultTextScanMode = src.DefaultTextScanMode;
|
||||
MinCharsForString = src.MinCharsForString;
|
||||
SeekNearbyTargets = src.SeekNearbyTargets;
|
||||
SmartPlpHandling = src.SmartPlpHandling;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,15 +244,18 @@ status flag override to get correct disassembly.</p>
|
||||
<p>The instruction that is most likely to cause problems is <code>PLP</code>,
|
||||
which pulls the processor status flags off of the stack. SourceGen
|
||||
doesn't try to track stack contents, so it can't know what values may
|
||||
be pulled. In many cases the PLP appears not long after a PHP, so
|
||||
SourceGen will scan backward through the file to find the nearest PHP,
|
||||
and use the status flags from that. If no PHP can be found, then all
|
||||
be pulled. In many cases the <code>PLP</code> appears not long after a
|
||||
<code>PHP</code>, so SourceGen will scan backward through the file to
|
||||
find the nearest <code>PHP</code>, and use the status flags from that. If
|
||||
no <code>PHP</code> can be found, then all
|
||||
flags are set to "indeterminate". (The boot loader in the Apple II 5.25"
|
||||
floppy disk controller is an example where SourceGen gets it wrong. The
|
||||
code does <code>CLC</code>/<code>PHP</code>, followed a bit later by the
|
||||
<code>PLP</code>, but it's actually using the stack to pass the carry
|
||||
flag around. Flagging the carry bit as indeterminate with a status flag
|
||||
override on the instruction following the PLP fixes things.)</p>
|
||||
override on the instruction following the PLP fixes things.) The
|
||||
"smart" behavior can be disabled in the project properties if it's coming
|
||||
out wrong more often than right.</p>
|
||||
|
||||
<p>Some other things that the code analyzer can't recognize automatically:</p>
|
||||
<ul>
|
||||
|
@ -227,11 +227,17 @@ entry point hint) will use this value. This is chiefly of value for
|
||||
|
||||
<p>If "analyze uncategorized data" is checked, SourceGen will attempt to
|
||||
identify character strings and regions that are filled with a repeated
|
||||
value. If it's
|
||||
not checked, anything that isn't detected as code or explicitly formatted
|
||||
will simply be shown as a byte value.</p>
|
||||
value. If it's not checked, anything that isn't detected as code or
|
||||
explicitly formatted as data will be shown as individual byte values.</p>
|
||||
<p>If "seek nearby targets" is checked, the analyzer will try to use
|
||||
nearby labels for data loads and stores.</p>
|
||||
nearby labels for data loads and stores, adjusting them to fit
|
||||
(e.g. <code>LDA LABEL+1</code>). If not enabled, labels are only used
|
||||
when they match exactly.</p>
|
||||
<p>If "smart PLP handling" is checked, the analyzer will try to use
|
||||
the processor status flags from a nearby <code>PHP</code> when a
|
||||
<code>PLP</code> is encountered. If not enabled, all flags are set to
|
||||
"indeterminate" following a <code>PLP</code>.</p>
|
||||
|
||||
<p>The "default text encoding" setting has two effects. First, it
|
||||
specifies which character encoding to use when searching for strings in
|
||||
uncategorized data. Second, if an assembler has a notion of preferred
|
||||
|
@ -94,10 +94,12 @@ limitations under the License.
|
||||
<GroupBox Header="Analysis Parameters" Grid.Column="1" Grid.Row="0" Grid.RowSpan="2"
|
||||
Margin="4,0,0,0" Padding="2,4">
|
||||
<StackPanel>
|
||||
<CheckBox Name="analyzeUncategorizedCheckBox" Content="Analyze uncategorized data"
|
||||
<CheckBox Content="Analyze uncategorized data"
|
||||
IsChecked="{Binding AnalyzeUncategorizedData}"/>
|
||||
<CheckBox Name="seekAltTargetCheckBox" Margin="0,4,0,0" Content="Seek nearby targets"
|
||||
<CheckBox Margin="0,4,0,0" Content="Seek nearby targets"
|
||||
IsChecked="{Binding SeekNearbyTargets}"/>
|
||||
<CheckBox Margin="0,4,0,0" Content="Smart PLP handling"
|
||||
IsChecked="{Binding SmartPlpHandling}"/>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Margin="0,4,0,0">
|
||||
<TextBlock Margin="0,3,0,0" Text="Default text encoding:"/>
|
||||
|
@ -275,6 +275,14 @@ namespace SourceGen.WpfGui {
|
||||
IsDirty = true;
|
||||
}
|
||||
}
|
||||
public bool SmartPlpHandling {
|
||||
get { return mWorkProps.AnalysisParams.SmartPlpHandling; }
|
||||
set {
|
||||
mWorkProps.AnalysisParams.SmartPlpHandling = value;
|
||||
OnPropertyChanged();
|
||||
IsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void Loaded_General() {
|
||||
for (int i = 0; i < CpuItems.Length; i++) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user