mirror of
https://github.com/fadden/6502bench.git
synced 2025-02-08 05:30:35 +00:00
Data Bank Register management, part 4
Implemented "smart" PLB handling. If we see PHK/PLB, or 8-bit LDA imm/PHA/PLB, we create a data bank change item. The feature can be disabled with a project property.
This commit is contained in:
parent
ee58d9e803
commit
0929077fda
@ -1295,47 +1295,34 @@ namespace SourceGen {
|
||||
/// Determines the value of the Data Bank Register (DBR, register 'B') for relevant
|
||||
/// instructions, and updates the Anattrib OperandOffset value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is of questionable value when we have reliable relocation data. OTOH it's
|
||||
/// pretty quick even on very large files.
|
||||
/// </remarks>
|
||||
public void ApplyDataBankRegister(Dictionary<int, DbrValue> userValues,
|
||||
Dictionary<int, DbrValue> dbrChanges) {
|
||||
Debug.Assert(!mCpuDef.HasAddr16); // 65816 only
|
||||
|
||||
dbrChanges.Clear();
|
||||
|
||||
short[] bval = new short[mAnattribs.Length];
|
||||
|
||||
// Initialize all entries to "unknown".
|
||||
Misc.Memset(bval, DbrValue.UNKNOWN);
|
||||
|
||||
// Set B=K every time we cross an address boundary and the program bank changes.
|
||||
short prevBank = DbrValue.UNKNOWN;
|
||||
foreach (AddressMap.AddressMapEntry ent in mAddrMap) {
|
||||
short mapBank = (short)(ent.Addr >> 16);
|
||||
if (mapBank != prevBank) {
|
||||
bval[ent.Offset] = mapBank;
|
||||
prevBank = mapBank;
|
||||
dbrChanges.Add(ent.Offset, new DbrValue(false, (byte)mapBank,
|
||||
DbrValue.Source.Auto));
|
||||
}
|
||||
if (mAnalysisParameters.SmartPlbHandling) {
|
||||
GenerateSmartPlbChanges(dbrChanges);
|
||||
}
|
||||
|
||||
// Apply the user-specified values, overwriting existing values.
|
||||
// Apply the user-specified values, overwriting auto-generated values.
|
||||
foreach (KeyValuePair<int, DbrValue> kvp in userValues) {
|
||||
dbrChanges[kvp.Key] = kvp.Value;
|
||||
}
|
||||
|
||||
// Create an array for fast access.
|
||||
short[] bval = new short[mAnattribs.Length];
|
||||
Misc.Memset(bval, DbrValue.UNKNOWN);
|
||||
foreach (KeyValuePair<int, DbrValue> kvp in dbrChanges) {
|
||||
bval[kvp.Key] = kvp.Value.AsShort;
|
||||
}
|
||||
|
||||
// Run through the file, looking for PHK/PLB pairs. When we find one, set an
|
||||
// entry for the PLB instruction unless an entry already exists there.
|
||||
|
||||
// add to dbrChanges with "Auto" or "smart"
|
||||
|
||||
// ? look for LDA #imm8 / PHA / PLB?
|
||||
|
||||
// ...
|
||||
|
||||
|
||||
// Run through file, updating instructions as needed.
|
||||
short curVal = 0;
|
||||
short curVal = (byte)(mAddrMap.Get(0) >> 16); // start with B=K
|
||||
for (int offset = 0; offset < mAnattribs.Length; offset++) {
|
||||
if (bval[offset] != DbrValue.UNKNOWN) {
|
||||
curVal = bval[offset];
|
||||
@ -1358,15 +1345,65 @@ namespace SourceGen {
|
||||
int newOffset = mAddrMap.AddressToOffset(offset, newAddr);
|
||||
if (newAddr != mAnattribs[offset].OperandAddress ||
|
||||
newOffset != mAnattribs[offset].OperandOffset) {
|
||||
Debug.WriteLine("DBR rewrite at +" + offset.ToString("x6") + ": $" +
|
||||
mAnattribs[offset].OperandAddress.ToString("x6") + "/+" +
|
||||
mAnattribs[offset].OperandOffset.ToString("x6") + " --> $" +
|
||||
newAddr.ToString("x6") + "/+" + newOffset.ToString("x6"));
|
||||
//Debug.WriteLine("DBR rewrite at +" + offset.ToString("x6") + ": $" +
|
||||
// mAnattribs[offset].OperandAddress.ToString("x6") + "/+" +
|
||||
// mAnattribs[offset].OperandOffset.ToString("x6") + " --> $" +
|
||||
// newAddr.ToString("x6") + "/+" + newOffset.ToString("x6"));
|
||||
|
||||
mAnattribs[offset].OperandAddress = newAddr;
|
||||
mAnattribs[offset].OperandOffset = newOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateSmartPlbChanges(Dictionary<int, DbrValue> dbrChanges) {
|
||||
#if false
|
||||
// Set B=K every time we cross an address boundary and the program bank changes.
|
||||
short prevBank = DbrValue.UNKNOWN;
|
||||
foreach (AddressMap.AddressMapEntry ent in mAddrMap) {
|
||||
short mapBank = (short)(ent.Addr >> 16);
|
||||
if (mapBank != prevBank) {
|
||||
prevBank = mapBank;
|
||||
dbrChanges.Add(ent.Offset, new DbrValue(false, (byte)mapBank,
|
||||
DbrValue.Source.Auto));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Run through the file, looking for PLB. If the preceding code was something
|
||||
// we can reliably pull a value out of, create an entry for it.
|
||||
for (int offset = 0; offset < mAnattribs.Length; offset++) {
|
||||
if (!mAnattribs[offset].IsInstructionStart) {
|
||||
continue;
|
||||
}
|
||||
OpDef op = mCpuDef.GetOpDef(mFileData[offset]);
|
||||
if (op != OpDef.OpPLB_StackPull) {
|
||||
continue;
|
||||
}
|
||||
if (offset < 1) {
|
||||
continue;
|
||||
}
|
||||
if (!mAnattribs[offset - 1].IsInstructionStart) {
|
||||
continue;
|
||||
}
|
||||
op = mCpuDef.GetOpDef(mFileData[offset - 1]);
|
||||
if (op == OpDef.OpPHK_StackPush) {
|
||||
// output B=K
|
||||
dbrChanges.Add(offset, new DbrValue(true, 0, DbrValue.Source.Auto));
|
||||
} else if (op == OpDef.OpPHA_StackPush && offset >= 4) {
|
||||
// check for LDA imm
|
||||
if (!mAnattribs[offset - 3].IsInstructionStart) {
|
||||
continue;
|
||||
}
|
||||
op = mCpuDef.GetOpDef(mFileData[offset - 3]);
|
||||
if (!(op == OpDef.OpLDA_ImmLongA || op == OpDef.OpLDA_Imm)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
byte bank = mFileData[offset - 2];
|
||||
dbrChanges.Add(offset, new DbrValue(false, bank, DbrValue.Source.Auto));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1056,19 +1056,21 @@ namespace SourceGen {
|
||||
// behavior is unwise.)
|
||||
if (mProject.DbrChanges.TryGetValue(offset,
|
||||
out CodeAnalysis.DbrValue dbrValue)) {
|
||||
string operandStr;
|
||||
string bankStr;
|
||||
if (dbrValue.FollowPbr) {
|
||||
operandStr = Res.Strings.DATA_BANK_USER_K;
|
||||
bankStr = Res.Strings.DATA_BANK_K;
|
||||
} else {
|
||||
string fmt;
|
||||
if (dbrValue.ValueSource == CodeAnalysis.DbrValue.Source.Auto) {
|
||||
fmt = Res.Strings.DATA_BANK_AUTO_FMT;
|
||||
} else {
|
||||
fmt = Res.Strings.DATA_BANK_USER_FMT;
|
||||
}
|
||||
operandStr = string.Format(fmt,
|
||||
mFormatter.FormatHexValue(dbrValue.Bank, 2));
|
||||
bankStr = mFormatter.FormatHexValue(dbrValue.Bank, 2);
|
||||
}
|
||||
|
||||
string fmt;
|
||||
if (dbrValue.ValueSource == CodeAnalysis.DbrValue.Source.Auto) {
|
||||
fmt = Res.Strings.DATA_BANK_AUTO_FMT;
|
||||
} else {
|
||||
fmt = Res.Strings.DATA_BANK_USER_FMT;
|
||||
}
|
||||
string operandStr = string.Format(fmt, bankStr);
|
||||
|
||||
Line dbrLine = new Line(offset, 0, Line.Type.DataBankDirective);
|
||||
dbrLine.Parts = FormattedParts.CreateDirective(
|
||||
mFormatter.FormatPseudoOp(mPseudoOpNames.DataBankDirective),
|
||||
|
@ -225,6 +225,7 @@ namespace SourceGen {
|
||||
public bool SeekNearbyTargets { get; set; }
|
||||
public bool UseRelocData { get; set; }
|
||||
public bool SmartPlpHandling { get; set; }
|
||||
public bool SmartPlbHandling { get; set; }
|
||||
|
||||
public SerAnalysisParameters() { }
|
||||
public SerAnalysisParameters(ProjectProperties.AnalysisParameters src) {
|
||||
@ -234,6 +235,7 @@ namespace SourceGen {
|
||||
SeekNearbyTargets = src.SeekNearbyTargets;
|
||||
UseRelocData = src.UseRelocData;
|
||||
SmartPlpHandling = src.SmartPlpHandling;
|
||||
SmartPlbHandling = src.SmartPlbHandling;
|
||||
}
|
||||
}
|
||||
public class SerAddressMap {
|
||||
@ -632,12 +634,19 @@ namespace SourceGen {
|
||||
proj.ProjectProps.AnalysisParams.UseRelocData =
|
||||
spf.ProjectProps.AnalysisParams.UseRelocData;
|
||||
if (spf._ContentVersion < 2) {
|
||||
// This was made optional in v1.3. Default it to true for older projects.
|
||||
// This was made optional in v1.3 (#2). Default it to true for older projects.
|
||||
proj.ProjectProps.AnalysisParams.SmartPlpHandling = true;
|
||||
} else {
|
||||
proj.ProjectProps.AnalysisParams.SmartPlpHandling =
|
||||
spf.ProjectProps.AnalysisParams.SmartPlpHandling;
|
||||
}
|
||||
if (spf._ContentVersion < 4) {
|
||||
// Introduced in v1.7 (#4). Default it to true for older projects.
|
||||
proj.ProjectProps.AnalysisParams.SmartPlbHandling = true;
|
||||
} else {
|
||||
proj.ProjectProps.AnalysisParams.SmartPlbHandling =
|
||||
spf.ProjectProps.AnalysisParams.SmartPlbHandling;
|
||||
}
|
||||
|
||||
// Deserialize ProjectProperties: external file identifiers.
|
||||
Debug.Assert(proj.ProjectProps.PlatformSymbolFileIdentifiers.Count == 0);
|
||||
|
@ -54,6 +54,7 @@ namespace SourceGen {
|
||||
public bool SeekNearbyTargets { get; set; }
|
||||
public bool UseRelocData { get; set; }
|
||||
public bool SmartPlpHandling { get; set; }
|
||||
public bool SmartPlbHandling { get; set; }
|
||||
|
||||
public AnalysisParameters() {
|
||||
// Set default values.
|
||||
@ -63,6 +64,7 @@ namespace SourceGen {
|
||||
SeekNearbyTargets = true;
|
||||
UseRelocData = false;
|
||||
SmartPlpHandling = true;
|
||||
SmartPlbHandling = true;
|
||||
}
|
||||
public AnalysisParameters(AnalysisParameters src) {
|
||||
AnalyzeUncategorizedData = src.AnalyzeUncategorizedData;
|
||||
@ -71,6 +73,7 @@ namespace SourceGen {
|
||||
SeekNearbyTargets = src.SeekNearbyTargets;
|
||||
UseRelocData = src.UseRelocData;
|
||||
SmartPlpHandling = src.SmartPlpHandling;
|
||||
SmartPlbHandling = src.SmartPlbHandling;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ limitations under the License.
|
||||
<system:String x:Key="str_ClipformatDisassembly">Disassembly</system:String>
|
||||
<system:String x:Key="str_DataBankAutoFmt">{0} (auto)</system:String>
|
||||
<system:String x:Key="str_DataBankUserFmt">{0}</system:String>
|
||||
<system:String x:Key="str_DataBankUserK">K</system:String>
|
||||
<system:String x:Key="str_DataBankK">K</system:String>
|
||||
<system:String x:Key="str_DefaultHeaderCommentFmt">6502bench SourceGen v{0}</system:String>
|
||||
<system:String x:Key="str_DefaultAsciiDelimPat">‘#’</system:String>
|
||||
<system:String x:Key="str_DefaultHighAsciiDelimPat">“#”</system:String>
|
||||
|
@ -47,8 +47,8 @@ namespace SourceGen.Res {
|
||||
(string)Application.Current.FindResource("str_DataBankAutoFmt");
|
||||
public static string DATA_BANK_USER_FMT =
|
||||
(string)Application.Current.FindResource("str_DataBankUserFmt");
|
||||
public static string DATA_BANK_USER_K =
|
||||
(string)Application.Current.FindResource("str_DataBankUserK");
|
||||
public static string DATA_BANK_K =
|
||||
(string)Application.Current.FindResource("str_DataBankK");
|
||||
public static string DEFAULT_HEADER_COMMENT_FMT =
|
||||
(string)Application.Current.FindResource("str_DefaultHeaderCommentFmt");
|
||||
public static string DEFAULT_ASCII_DELIM_PAT =
|
||||
|
@ -262,6 +262,11 @@ improve automatic operand formatting.</p>
|
||||
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>If "smart PLB handling" is checked, the analyzer will watch for
|
||||
code patterns like <code>PLB</code> preceded by <code>PHK</code>,
|
||||
and generate appropriate Data Bank Register changes. If not enabled,
|
||||
the DBR is set to the bank of the address of the start of the file,
|
||||
and does not change unless explicitly set. Only useful for 65816 code.</p>
|
||||
|
||||
<p>The "default text encoding" setting has two effects. First, it
|
||||
specifies which character encoding to use when searching for strings in
|
||||
|
@ -107,6 +107,8 @@ limitations under the License.
|
||||
IsChecked="{Binding UseRelocData}" IsEnabled="{Binding IsRelocDataAvailable}"/>
|
||||
<CheckBox Margin="0,4,0,0" Content="Smart PLP handling"
|
||||
IsChecked="{Binding SmartPlpHandling}"/>
|
||||
<CheckBox Margin="0,4,0,0" Content="Smart PLB handling"
|
||||
IsChecked="{Binding SmartPlbHandling}"/>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Margin="0,4,0,0">
|
||||
<TextBlock Margin="0,3,0,0" Text="Default text encoding:"/>
|
||||
|
@ -364,6 +364,14 @@ namespace SourceGen.WpfGui {
|
||||
IsDirty = true;
|
||||
}
|
||||
}
|
||||
public bool SmartPlbHandling {
|
||||
get { return mWorkProps.AnalysisParams.SmartPlbHandling; }
|
||||
set {
|
||||
mWorkProps.AnalysisParams.SmartPlbHandling = 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