1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-11-29 10:50:28 +00:00

Data Bank Register management, part 3

Added a "fake" assembler pseudo-op for DBR changes.  Display entries
in line list.

Added entry to double-click handler so that you can double-click on
a PLB instruction operand to open the data bank editor.
This commit is contained in:
Andy McFadden 2020-07-09 15:17:47 -07:00
parent 973d162edb
commit ee58d9e803
16 changed files with 131 additions and 22 deletions

View File

@ -109,6 +109,7 @@ namespace SourceGen.AsmGen {
//VarDirective
{ "OrgDirective", "!pseudopc" },
//RegWidthDirective // !al, !as, !rl, !rs
//DataBankDirective
{ "DefineData1", "!byte" },
{ "DefineData2", "!word" },
{ "DefineData3", "!24" },

View File

@ -106,6 +106,7 @@ namespace SourceGen.AsmGen {
{ "VarDirective", ".set" },
{ "OrgDirective", ".org" },
//RegWidthDirective // .a8, .a16, .i8, .i16
//DataBankDirective
{ "DefineData1", ".byte" },
{ "DefineData2", ".word" },
{ "DefineData3", ".faraddr" },

View File

@ -97,6 +97,7 @@ namespace SourceGen.AsmGen {
{ "VarDirective", "equ" },
{ "OrgDirective", "org" },
//RegWidthDirective
//DataBankDirective
{ "DefineData1", "dfb" },
{ "DefineData2", "dw" },
{ "DefineData3", "adr" },

View File

@ -123,6 +123,7 @@ namespace SourceGen.AsmGen {
{ "VarDirective", ".var" },
{ "OrgDirective", ".logical" },
//RegWidthDirective // .as, .al, .xs, .xl
//DataBankDirective
{ "DefineData1", ".byte" },
{ "DefineData2", ".word" },
{ "DefineData3", ".long" },

View File

@ -1238,7 +1238,7 @@ namespace SourceGen {
/// </summary>
public byte Bank { get; private set; }
public enum Source { Unknown = 0, User, Auto, Smart };
public enum Source { Unknown = 0, User, Auto };
/// <summary>
/// From whence this value originates.
/// </summary>
@ -1295,9 +1295,12 @@ namespace SourceGen {
/// Determines the value of the Data Bank Register (DBR, register 'B') for relevant
/// instructions, and updates the Anattrib OperandOffset value.
/// </summary>
public void ApplyDataBankRegister(Dictionary<int, DbrValue> userValues) {
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".
@ -1310,24 +1313,29 @@ namespace SourceGen {
if (mapBank != prevBank) {
bval[ent.Offset] = mapBank;
prevBank = mapBank;
dbrChanges.Add(ent.Offset, new DbrValue(false, (byte)mapBank,
DbrValue.Source.Auto));
}
}
// Apply the user-specified values.
// Apply the user-specified values, overwriting existing values.
foreach (KeyValuePair<int, DbrValue> kvp in userValues) {
dbrChanges[kvp.Key] = kvp.Value;
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 = DbrValue.UNKNOWN;
short curVal = 0;
for (int offset = 0; offset < mAnattribs.Length; offset++) {
if (bval[offset] != DbrValue.UNKNOWN) {
curVal = bval[offset];

View File

@ -77,7 +77,7 @@ namespace SourceGen {
/// <summary>
/// Data Bank Register overrides.
/// </summary>
public Dictionary<int, CodeAnalysis.DbrValue> DbrValues { get; private set; }
public Dictionary<int, CodeAnalysis.DbrValue> DbrOverrides { get; private set; }
/// <summary>
/// Full line, possibly multi-line comments.
@ -195,6 +195,12 @@ namespace SourceGen {
// before data analysis has begun.
private Anattrib[] mCodeOnlyAnattribs;
/// <summary>
/// Changes to the Data Bank Register, by offset. These can come from DbrOverrides
/// or be automatically generated.
/// </summary>
public Dictionary<int, CodeAnalysis.DbrValue> DbrChanges { get; private set; }
// Symbol lists loaded from platform symbol files. This is essentially a list
// of lists, of symbols.
private List<PlatformSymbols> PlatformSyms { get; set; }
@ -279,7 +285,8 @@ namespace SourceGen {
Comments[i] = string.Empty;
}
DbrValues = new Dictionary<int, CodeAnalysis.DbrValue>();
DbrOverrides = new Dictionary<int, CodeAnalysis.DbrValue>();
DbrChanges = new Dictionary<int, CodeAnalysis.DbrValue>();
LongComments = new Dictionary<int, MultiLineComment>();
Notes = new SortedList<int, MultiLineComment>();
@ -816,7 +823,7 @@ namespace SourceGen {
if (!CpuDef.HasAddr16) {
// 24-bit address space, so DBR matters
reanalysisTimer.StartTask("CodeAnalysis.ApplyDataBankRegister");
ca.ApplyDataBankRegister(DbrValues);
ca.ApplyDataBankRegister(DbrOverrides, DbrChanges);
reanalysisTimer.EndTask("CodeAnalysis.ApplyDataBankRegister");
}
@ -2120,16 +2127,16 @@ namespace SourceGen {
break;
case UndoableChange.ChangeType.SetDataBank: {
// If there's no entry, treat it as an entry with value = Unknown.
DbrValues.TryGetValue(offset, out CodeAnalysis.DbrValue current);
DbrOverrides.TryGetValue(offset, out CodeAnalysis.DbrValue current);
if (current != (CodeAnalysis.DbrValue)oldValue) {
Debug.WriteLine("GLITCH: old DBR value mismatch (" +
current + " vs " + oldValue + ")");
Debug.Assert(false);
}
if (newValue == null) {
DbrValues.Remove(offset);
DbrOverrides.Remove(offset);
} else {
DbrValues[offset] = (CodeAnalysis.DbrValue)newValue;
DbrOverrides[offset] = (CodeAnalysis.DbrValue)newValue;
}
// ignore affectedOffsets

View File

@ -350,6 +350,7 @@ namespace SourceGen {
case LineListGen.Line.Type.Data:
case LineListGen.Line.Type.EquDirective:
case LineListGen.Line.Type.RegWidthDirective:
case LineListGen.Line.Type.DataBankDirective:
case LineListGen.Line.Type.OrgDirective:
case LineListGen.Line.Type.LocalVariableTable:
if (parts.IsLongComment) {
@ -710,6 +711,7 @@ namespace SourceGen {
case LineListGen.Line.Type.Data:
case LineListGen.Line.Type.EquDirective:
case LineListGen.Line.Type.RegWidthDirective:
case LineListGen.Line.Type.DataBankDirective:
case LineListGen.Line.Type.OrgDirective:
case LineListGen.Line.Type.LocalVariableTable:
if (parts.IsLongComment) {

View File

@ -119,10 +119,11 @@ namespace SourceGen {
OrgDirective = 1 << 5,
EquDirective = 1 << 6,
RegWidthDirective = 1 << 7,
DataBankDirective = 1 << 8,
// Additional metadata.
LocalVariableTable = 1 << 8,
VisualizationSet = 1 << 9,
LocalVariableTable = 1 << 9,
VisualizationSet = 1 << 10,
}
/// <summary>
@ -516,6 +517,7 @@ namespace SourceGen {
break;
case Line.Type.OrgDirective:
case Line.Type.RegWidthDirective:
case Line.Type.DataBankDirective:
case Line.Type.LongComment:
case Line.Type.Note:
// should have been done already
@ -1006,7 +1008,9 @@ namespace SourceGen {
}
if (attr.IsInstructionStart) {
// Generate reg width directive, if necessary.
// Generate reg width directive, if necessary. These are generated after the
// SEP/REP/PLP instruction has taken effect, so we want it to appear *before*
// the current instruction.
if (mProject.CpuDef.HasEmuFlag) {
// Changing from "ambiguous but assumed short" to "definitively short"
// merits a directive, notably at the start of the file. The tricky
@ -1044,6 +1048,34 @@ namespace SourceGen {
prevFlags = curFlags;
}
// Add data bank register change. This is generally applied to a PLB
// instruction, so we'd like it to appear on the line following the
// instruction, but that looks funny for e.g. the auto-added B=K at the
// start of each bank, and would be wrong if placed on a "LDA abs" line.
// (We could handle PLB lines differently, but apparently inconsistent
// behavior is unwise.)
if (mProject.DbrChanges.TryGetValue(offset,
out CodeAnalysis.DbrValue dbrValue)) {
string operandStr;
if (dbrValue.FollowPbr) {
operandStr = Res.Strings.DATA_BANK_USER_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));
}
Line dbrLine = new Line(offset, 0, Line.Type.DataBankDirective);
dbrLine.Parts = FormattedParts.CreateDirective(
mFormatter.FormatPseudoOp(mPseudoOpNames.DataBankDirective),
mFormatter.FormatPseudoOp(operandStr));
lines.Add(dbrLine);
}
// Look for embedded instructions.
int len;
for (len = 1; len < attr.Length; len++) {

View File

@ -1508,6 +1508,11 @@ namespace SourceGen {
EditStatusFlags();
}
break;
case LineListGen.Line.Type.DataBankDirective:
if (CanEditDataBank()) {
EditDataBank();
}
break;
case LineListGen.Line.Type.LongComment:
if (CanEditLongComment()) {
EditLongComment();
@ -1559,7 +1564,14 @@ namespace SourceGen {
}
break;
case CodeListColumn.Opcode:
if (IsPlbInstruction(line) && CanEditDataBank()) {
// Special handling for PLB instruction, so you can update the bank
// value just be double-clicking on it. Only used for PLBs without
// user- or auto-assigned bank changes.
EditDataBank();
} else {
JumpToOperandTarget(line, false);
}
break;
case CodeListColumn.Operand:
if (CanEditOperand()) {
@ -1571,7 +1583,6 @@ namespace SourceGen {
EditComment();
}
break;
}
break;
@ -1581,6 +1592,26 @@ namespace SourceGen {
}
}
private bool IsPlbInstruction(LineListGen.Line line) {
if (line.LineType != LineListGen.Line.Type.Code) {
return false;
}
int offset = line.FileOffset;
Anattrib attr = mProject.GetAnattrib(offset);
// should always be an instruction start since this is a code line
if (!attr.IsInstructionStart) {
Debug.Assert(false);
return false;
}
OpDef op = mProject.CpuDef.GetOpDef(mProject.FileData[offset]);
if (op != OpDef.OpPLB_StackPull) {
return false;
}
return true;
}
/// <summary>
/// Jumps to the line referenced by the operand of the selected line.
/// </summary>
@ -1865,8 +1896,8 @@ namespace SourceGen {
if (SelectionAnalysis.mNumItemsSelected != 1) {
return false;
}
return (SelectionAnalysis.mLineType == LineListGen.Line.Type.Code /*||
is data bank */);
return (SelectionAnalysis.mLineType == LineListGen.Line.Type.Code ||
SelectionAnalysis.mLineType == LineListGen.Line.Type.DataBankDirective);
}
public void EditDataBank() {
@ -1874,7 +1905,7 @@ namespace SourceGen {
int offset = CodeLineList[selIndex].FileOffset;
// Get current user-specified value, or null.
mProject.DbrValues.TryGetValue(offset, out CodeAnalysis.DbrValue curValue);
mProject.DbrOverrides.TryGetValue(offset, out CodeAnalysis.DbrValue curValue);
EditDataBank dlg = new EditDataBank(mMainWin, mProject, mFormatter, curValue);
if (dlg.ShowDialog() != true) {
@ -3782,6 +3813,9 @@ namespace SourceGen {
case LineListGen.Line.Type.RegWidthDirective:
lineTypeStr = "register width directive";
break;
case LineListGen.Line.Type.DataBankDirective:
lineTypeStr = "data bank directive";
break;
case LineListGen.Line.Type.LocalVariableTable:
isSimple = false;

View File

@ -549,8 +549,8 @@ namespace SourceGen {
// We could output the value as a short, using DbrValue.AsShort, but it doesn't
// save much space and could make life harder down the road.
spf.DbrValues = new Dictionary<string, SerDbrValue>(proj.DbrValues.Count);
foreach (KeyValuePair<int, CodeAnalysis.DbrValue> kvp in proj.DbrValues) {
spf.DbrValues = new Dictionary<string, SerDbrValue>(proj.DbrOverrides.Count);
foreach (KeyValuePair<int, CodeAnalysis.DbrValue> kvp in proj.DbrOverrides) {
spf.DbrValues.Add(kvp.Key.ToString(), new SerDbrValue(kvp.Value));
}
@ -883,7 +883,7 @@ namespace SourceGen {
}
CodeAnalysis.DbrValue newDbr = new CodeAnalysis.DbrValue(kvp.Value.FollowPbr,
kvp.Value.Bank, CodeAnalysis.DbrValue.Source.User);
proj.DbrValues.Add(intKey, newDbr);
proj.DbrOverrides.Add(intKey, newDbr);
}
}

View File

@ -68,6 +68,7 @@ namespace SourceGen {
public string VarDirective { get; private set; }
public string OrgDirective { get; private set; }
public string RegWidthDirective { get; private set; }
public string DataBankDirective { get; private set; }
public string DefineData1 { get; private set; }
public string DefineData2 { get; private set; }
@ -118,6 +119,7 @@ namespace SourceGen {
a.VarDirective == b.VarDirective &&
a.OrgDirective == b.OrgDirective &&
a.RegWidthDirective == b.RegWidthDirective &&
a.DataBankDirective == b.DataBankDirective &&
a.DefineData1 == b.DefineData1 &&
a.DefineData2 == b.DefineData2 &&
a.DefineData3 == b.DefineData3 &&
@ -228,6 +230,7 @@ namespace SourceGen {
{ "VarDirective", ".var" },
{ "OrgDirective", ".org" },
{ "RegWidthDirective", ".rwid" },
{ "DataBankDirective", ".dbank" },
{ "DefineData1", ".dd1" },
{ "DefineData2", ".dd2" },

View File

@ -34,6 +34,9 @@ limitations under the License.
<system:String x:Key="str_ClipformatAllColumns">All Columns</system:String>
<system:String x:Key="str_ClipformatAssemblerSource">Assembler Source</system:String>
<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_DefaultHeaderCommentFmt">6502bench SourceGen v{0}</system:String>
<system:String x:Key="str_DefaultAsciiDelimPat">&#x2018;#&#x2019;</system:String>
<system:String x:Key="str_DefaultHighAsciiDelimPat">&#x201c;#&#x201d;</system:String>

View File

@ -43,6 +43,12 @@ namespace SourceGen.Res {
(string)Application.Current.FindResource("str_AsmMismatchLengthFmt");
public static string ASM_OUTPUT_NOT_FOUND =
(string)Application.Current.FindResource("str_AsmOutputNotFound");
public static string DATA_BANK_AUTO_FMT =
(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 DEFAULT_HEADER_COMMENT_FMT =
(string)Application.Current.FindResource("str_DefaultHeaderCommentFmt");
public static string DEFAULT_ASCII_DELIM_PAT =

View File

@ -758,6 +758,12 @@ limitations under the License.
VerticalAlignment="Center" Margin="{StaticResource TBS}"
Text=".placeho" MaxLength="12"
FontFamily="{StaticResource GeneralMonoFont}"/>
<TextBlock Grid.Column="6" Grid.Row="5" Text="Data bank:"
HorizontalAlignment="Right" VerticalAlignment="Center"/>
<TextBox Name="dataBankTextBox" Grid.Column="7" Grid.Row="5"
VerticalAlignment="Center" Margin="{StaticResource TBS}"
Text=".placeho" MaxLength="12"
FontFamily="{StaticResource GeneralMonoFont}"/>
</Grid>
<GroupBox DockPanel.Dock="Bottom" Header="Quick Set"

View File

@ -1138,6 +1138,7 @@ namespace SourceGen.WpfGui {
new TextBoxPropertyMap(varDirectiveTextBox, "VarDirective"),
new TextBoxPropertyMap(orgDirectiveTextBox, "OrgDirective"),
new TextBoxPropertyMap(regWidthDirectiveTextBox, "RegWidthDirective"),
new TextBoxPropertyMap(dataBankTextBox, "DataBankDirective"),
new TextBoxPropertyMap(defineData1TextBox, "DefineData1"),
new TextBoxPropertyMap(defineData2TextBox, "DefineData2"),
new TextBoxPropertyMap(defineData3TextBox, "DefineData3"),

View File

@ -176,7 +176,10 @@ namespace SourceGen.WpfGui {
/// <returns>DBR value, or null if invalid.</returns>
private static CodeAnalysis.DbrValue StringToDbrValue(string valueStr) {
valueStr = valueStr.Trim();
if (valueStr.Equals(PROG_BANK_STR, StringComparison.InvariantCultureIgnoreCase)) {
if (string.IsNullOrEmpty(valueStr)) {
return null;
} else if (valueStr.Equals(PROG_BANK_STR,
StringComparison.InvariantCultureIgnoreCase)) {
return new CodeAnalysis.DbrValue(true, 0, CodeAnalysis.DbrValue.Source.User);
} else {
if (!Number.TryParseIntHex(valueStr, out int val)) {