From 0ac0686c7a1af424879f926b889507f39ef8214a Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Thu, 7 Oct 2021 12:39:08 -0700 Subject: [PATCH] ORG rework, part 9 Modified "jump to" code to understand address range start/end lines. If there are multiple starts or ends at the same offset, we jump to the first one in the set, which is suboptimal but simpler to do. Simplified the API, embedding GoToMode in the Location object (which is where it really needs to be, to make fwd/back work right). Updated HTML export to grey out addresses in NON_ADDR sections. Changed default pseudo-op strings for address regions to ".addrs" and ".adrend", after trying a bunch of things that were worse. Added definitions for region-end pseudo-ops to Merlin32 and cc65 for display on screen. Added regression test 20260 for address region pre-labels. Fixed handling of leading underscores in platform/project symbols. These need to be escaped in 64tass output. Updated regression test 20170-external-symbols to check it. --- CommonUtil/AddressMap.cs | 2 +- SourceGen/AsmGen/AsmCc65.cs | 8 +- SourceGen/AsmGen/AsmMerlin32.cs | 2 +- SourceGen/Exporter.cs | 10 +- SourceGen/LineListGen.cs | 37 +-- SourceGen/MainController.cs | 146 +++++++----- SourceGen/NavStack.cs | 32 ++- SourceGen/PseudoOp.cs | 4 +- SourceGen/RenderAddressMap.cs | 18 +- SourceGen/RuntimeData/SGStyle.css | 7 + .../SGTestData/20170-external-symbols-1.sym65 | 3 +- .../SGTestData/20170-external-symbols.dis65 | 2 +- SourceGen/SGTestData/20260-pre-labels | Bin 0 -> 95 bytes SourceGen/SGTestData/20260-pre-labels.dis65 | 219 ++++++++++++++++++ .../Expected/20170-external-symbols_64tass.S | 4 +- .../Expected/20170-external-symbols_acme.S | 4 +- .../Expected/20170-external-symbols_cc65.S | 4 +- .../20170-external-symbols_merlin32.S | 4 +- .../Expected/20260-pre-labels_64tass.S | 76 ++++++ .../Expected/20260-pre-labels_acme.S | 79 +++++++ .../Expected/20260-pre-labels_cc65.S | 73 ++++++ .../Expected/20260-pre-labels_cc65.cfg | 9 + .../Expected/20260-pre-labels_merlin32.S | 72 ++++++ .../SGTestData/Source/20260-pre-labels.S | 111 +++++++++ SourceGen/WpfGui/EditAddress.xaml.cs | 4 +- SourceGen/WpfGui/MainWindow.xaml.cs | 12 +- 26 files changed, 821 insertions(+), 121 deletions(-) create mode 100644 SourceGen/SGTestData/20260-pre-labels create mode 100644 SourceGen/SGTestData/20260-pre-labels.dis65 create mode 100644 SourceGen/SGTestData/Expected/20260-pre-labels_64tass.S create mode 100644 SourceGen/SGTestData/Expected/20260-pre-labels_acme.S create mode 100644 SourceGen/SGTestData/Expected/20260-pre-labels_cc65.S create mode 100644 SourceGen/SGTestData/Expected/20260-pre-labels_cc65.cfg create mode 100644 SourceGen/SGTestData/Expected/20260-pre-labels_merlin32.S create mode 100644 SourceGen/SGTestData/Source/20260-pre-labels.S diff --git a/CommonUtil/AddressMap.cs b/CommonUtil/AddressMap.cs index 8d6a640..bccf941 100644 --- a/CommonUtil/AddressMap.cs +++ b/CommonUtil/AddressMap.cs @@ -977,7 +977,7 @@ namespace CommonUtil { /// /// /// This is NOT intended to say whether the sequence of addresses has a hiccup. The goal - /// is to identify multi-byte elements that have a .arstart/.arend statement in the middle. + /// is to identify multi-byte elements that have an arstart/arend statement in the middle. /// /// We can do this in a couple of different ways: /// 1. Find the node that holds the offset, confirm that it spans offset+length, and diff --git a/SourceGen/AsmGen/AsmCc65.cs b/SourceGen/AsmGen/AsmCc65.cs index 954ada4..e2c4121 100644 --- a/SourceGen/AsmGen/AsmCc65.cs +++ b/SourceGen/AsmGen/AsmCc65.cs @@ -112,8 +112,8 @@ namespace SourceGen.AsmGen { { "EquDirective", "=" }, { "VarDirective", ".set" }, { "ArStartDirective", ".org" }, - //ArEndDirective - //RegWidthDirective // .a8, .a16, .i8, .i16 + { "ArEndDirective", ".adrend" }, // on-screen display only + //RegWidthDirective // .a8, .a16, .i8, .i16 //DataBankDirective { "DefineData1", ".byte" }, { "DefineData2", ".word" }, @@ -123,12 +123,12 @@ namespace SourceGen.AsmGen { //DefineBigData3 //DefineBigData4 { "Fill", ".res" }, - { "Dense", ".byte" }, // not really dense, just comma-separated bytes + { "Dense", ".byte" }, // really just just comma-separated bytes //Junk { "StrGeneric", ".byte" }, //StrReverse { "StrNullTerm", ".asciiz" }, - //StrLen8 // macro with .strlen? + //StrLen8 // TODO(maybe): macro with .strlen? //StrLen16 //StrDci }); diff --git a/SourceGen/AsmGen/AsmMerlin32.cs b/SourceGen/AsmGen/AsmMerlin32.cs index 05d6224..7662a29 100644 --- a/SourceGen/AsmGen/AsmMerlin32.cs +++ b/SourceGen/AsmGen/AsmMerlin32.cs @@ -106,7 +106,7 @@ namespace SourceGen.AsmGen { { "EquDirective", "equ" }, { "VarDirective", "equ" }, { "ArStartDirective", "org" }, - { "ArEndDirective", "org_end" }, // not actually used + { "ArEndDirective", "adrend" }, // on-screen display only //RegWidthDirective //DataBankDirective { "DefineData1", "dfb" }, diff --git a/SourceGen/Exporter.cs b/SourceGen/Exporter.cs index 2ab8ef8..8dddb9f 100644 --- a/SourceGen/Exporter.cs +++ b/SourceGen/Exporter.cs @@ -735,9 +735,15 @@ namespace SourceGen { } if ((mLeftFlags & ActiveColumnFlags.Address) != 0) { if (!string.IsNullOrEmpty(parts.Addr)) { - string str = parts.Addr + ":"; + string str; + if (parts.IsNonAddressable) { + str = "" + parts.Addr + ""; + } else { + str = parts.Addr; + } + str += ":"; colPos = AddSpacedString(sb, colPos, mColStart[(int)Col.Address], - str, str.Length); + str, parts.Addr.Length + 1); } } if ((mLeftFlags & ActiveColumnFlags.Bytes) != 0) { diff --git a/SourceGen/LineListGen.cs b/SourceGen/LineListGen.cs index 3ceb91c..eeef4b4 100644 --- a/SourceGen/LineListGen.cs +++ b/SourceGen/LineListGen.cs @@ -282,8 +282,8 @@ namespace SourceGen { int topOffset = dl[topIndex].FileOffset; int firstIndex = dl.FindLineIndexByOffset(topOffset); Debug.Assert(topIndex >= firstIndex); - savedSel.mTopPosition = - new NavStack.Location(topOffset, topIndex - firstIndex, false); + savedSel.mTopPosition = new NavStack.Location(topOffset, topIndex - firstIndex, + NavStack.GoToMode.JumpToAdjIndex); List lineList = dl.mLineList; Debug.Assert(lineList.Count == sel.Length); @@ -832,7 +832,7 @@ namespace SourceGen { // Blank lines and comments can appear before or after code/data. They // must have the offset of the associated line, and a span of zero. if (line.FileOffset != expectedOffset && line.FileOffset != lastOffset) { - // .arend directives are associated with the last byte of a region, so + // arend directives are associated with the last byte of a region, so // we need to make a special exemption for them. if (line.LineType == Line.Type.ArEndDirective && line.FileOffset == expectedOffset - 1) { @@ -1035,7 +1035,7 @@ namespace SourceGen { // Insert long comments and notes. These may span multiple display lines, // and require word-wrap, so it's easiest just to render them fully here. - // Set "spaceAdded" to true so .arstart doesn't try to add one after the comment. + // Set "spaceAdded" to true so arstart doesn't try to add one after the comment. // // TODO: integrate into FormattedOperandCache so we don't have to // regenerate them unless they change. Use the MLC as the dependency. @@ -1066,7 +1066,7 @@ namespace SourceGen { AddressMap.AddressRegion region = change.Region; if (region.Offset == 0 && hasPrgHeader) { - // Suppress the .arstart at offset zero. We know there's another one + // Suppress the arstart at offset zero. We know there's another one // at offset +000002, and that it matches the value at +0/1. addrIter.MoveNext(); continue; @@ -1079,7 +1079,7 @@ namespace SourceGen { lines.Add(GenerateBlankLine(offset)); } spaceAdded = false; // next one will need a blank line - multiStart = true; // unless it's another .arstart immediately + multiStart = true; // unless it's another arstart immediately if (region.HasValidPreLabel) { Line preLine = @@ -1109,16 +1109,19 @@ namespace SourceGen { } else { addrStr = mFormatter.FormatHexValue(region.Address, 4); } -#if DEBUG +#if DEBUG1 string comment = mFormatter.FormatEolComment("ends at " + mFormatter.FormatOffset24(region.Offset + region.ActualLength - 1) + (region.IsFloating ? " (floating)" : string.Empty)); -#else - string comment = string.Empty; -#endif if (change.IsSynthetic) { comment += " (auto-generated)"; } +#else + string comment = string.Empty; + if (change.IsSynthetic) { + comment = mFormatter.FormatEolComment("(auto-generated)"); + } +#endif newLine.Parts = FormattedParts.CreateFullDirective(string.Empty, mFormatter.FormatPseudoOp(mPseudoOpNames.ArStartDirective), addrStr, comment); @@ -1284,10 +1287,10 @@ namespace SourceGen { // Check for address region ends, which will be positioned one byte before the // updated offset (unless they somehow got embedded inside something else). // - // The .arend can only appear on the same offset as .arstart in a single-byte + // The arend can only appear on the same offset as arstart in a single-byte // region, and we can't have more than one of those at the same offset. // If this is not a single-byte region, we need to reset the sub-line count. - // (Alternatively: track the offset of the last .arstart, and reset subline + // (Alternatively: track the offset of the last arstart, and reset subline // if they differ.) if (addrIter.Current != null && addrIter.Current.Region.Length != 1) { arSubLine = 0; @@ -1302,7 +1305,7 @@ namespace SourceGen { } if (change.Region.Offset == 0 && hasPrgHeader) { - // Suppress the .arend at offset +000001. + // Suppress the arend at offset +000001. addrIter.MoveNext(); arSubLine++; // need to track address map continue; @@ -1330,7 +1333,7 @@ namespace SourceGen { // Put a blank line before the next thing. // TODO(maybe): this gets lost in a partial update, e.g. you add a - // long comment right after a .arend with no following .arstart and + // long comment right after a arend with no following arstart and // then hit "undo", because the blank is logically part of the // following offset. addBlank = true; @@ -1649,7 +1652,7 @@ namespace SourceGen { } public AddressMap.AddressRegion GetAddrRegionFromLine(Line line, out bool isSynth) { - // A given offset can have one or more .arstart lines and one or more .arend lines. + // A given offset can have one or more arstart lines and one or more arend lines. // You can't have an end followed by a start, because that would mean the regions // overlap. If there's both start and end present, we have a 1-byte region. int offset = line.FileOffset; @@ -1666,14 +1669,14 @@ namespace SourceGen { while (addrIter.Current != null && addrIter.Current.Offset == offset) { AddressMap.AddressChange change = addrIter.Current; if (count == 0) { - // Could be pre-label or .arstart that follows it. Both go to the same place. + // Could be pre-label or arstart that follows it. Both go to the same place. isSynth = change.IsSynthetic; return change.Region; } if (change.IsStart && change.Region.HasValidPreLabel) { count--; if (count == 0) { - // This is the .arstart following the pre-label. + // This is the arstart following the pre-label. isSynth = change.IsSynthetic; return change.Region; } diff --git a/SourceGen/MainController.cs b/SourceGen/MainController.cs index 4e9a8be..34f21d9 100644 --- a/SourceGen/MainController.cs +++ b/SourceGen/MainController.cs @@ -1664,7 +1664,8 @@ namespace SourceGen { } if (line.IsAddressRangeDirective) { - // TODO(someday): make this jump to the actual directive rather than nearby code + // TODO(someday): make this jump to the specific directive rather than the first + // (should be able to do it with LineDelta) AddressMap.AddressRegion region = CodeLineList.GetAddrRegionFromLine(line, out bool unused); if (region == null) { @@ -1674,13 +1675,12 @@ namespace SourceGen { if (!testOnly) { if (line.LineType == LineListGen.Line.Type.ArStartDirective) { // jump to end - GoToLocation( - new NavStack.Location(region.Offset + region.ActualLength - 1, 0, true), - GoToMode.JumpToCodeData, true); + GoToLocation(new NavStack.Location(region.Offset + region.ActualLength - 1, + 0, NavStack.GoToMode.JumpToArEnd), true); } else { // jump to start - GoToLocation(new NavStack.Location(region.Offset, 0, true), - GoToMode.JumpToCodeData, true); + GoToLocation(new NavStack.Location(region.Offset, + 0, NavStack.GoToMode.JumpToArStart), true); } } return true; @@ -1706,9 +1706,11 @@ namespace SourceGen { int labelOffset = mProject.FindLabelOffsetByName(dfd.SymbolRef.Label); if (labelOffset >= 0) { if (!testOnly) { - // TODO(org): jump to .arstart - GoToLocation(new NavStack.Location(labelOffset, 0, false), - GoToMode.JumpToCodeData, true); + NavStack.GoToMode mode = NavStack.GoToMode.JumpToCodeData; + if (sym.SymbolSource == Symbol.Source.AddrPreLabel) { + mode = NavStack.GoToMode.JumpToArStart; + } + GoToLocation(new NavStack.Location(labelOffset, 0, mode), true); } return true; } @@ -1719,8 +1721,8 @@ namespace SourceGen { if (mProject.ActiveDefSymbolList[i] == sym) { int offset = LineListGen.DefSymOffsetFromIndex(i); if (!testOnly) { - GoToLocation(new NavStack.Location(offset, 0, false), - GoToMode.JumpToCodeData, true); + GoToLocation(new NavStack.Location(offset, 0, + NavStack.GoToMode.JumpToCodeData), true); } return true; } @@ -1737,8 +1739,8 @@ namespace SourceGen { // Operand has an in-file target offset. We can resolve it as a numeric reference. // Find the line for that offset and jump to it. if (!testOnly) { - GoToLocation(new NavStack.Location(attr.OperandOffset, 0, false), - GoToMode.JumpToCodeData, true); + GoToLocation(new NavStack.Location(attr.OperandOffset, 0, + NavStack.GoToMode.JumpToCodeData), true); } return true; } else if (attr.IsDataStart || attr.IsInlineDataStart) { @@ -1748,8 +1750,8 @@ namespace SourceGen { int operandOffset = DataAnalysis.GetDataOperandOffset(mProject, line.FileOffset); if (operandOffset >= 0) { if (!testOnly) { - GoToLocation(new NavStack.Location(operandOffset, 0, false), - GoToMode.JumpToCodeData, true); + GoToLocation(new NavStack.Location(operandOffset, 0, + NavStack.GoToMode.JumpToCodeData), true); } return true; } @@ -1809,15 +1811,15 @@ namespace SourceGen { int lastIndex = mMainWin.CodeListView_GetLastSelectedIndex(); - // Can only start with .arend if it's single-selection. + // Can only start with arend if it's single-selection. if (selIndex != lastIndex && selLine.LineType == LineListGen.Line.Type.ArEndDirective) { return false; } - // If multiple lines with code/data are selected, there must not be a .arstart + // If multiple lines with code/data are selected, there must not be an arstart // between them unless we're resizing a region. Determining whether or not a resize - // is valid is left to the edit dialog. It's okay for a .arend to be in the middle - // so long as the corresponding .arstart is at the current offset. + // is valid is left to the edit dialog. It's okay for an arend to be in the middle + // so long as the corresponding arstart is at the current offset. if (selLine.LineType == LineListGen.Line.Type.ArStartDirective) { // Skip overlapping region check. return true; @@ -1856,7 +1858,7 @@ namespace SourceGen { int nextOffset = lastOffset + CodeLineList[lastIndex].OffsetSpan; AddressMap addrMap = mProject.AddrMap; - // The offset of a .arend directive is the last byte in the address region. It + // The offset of an arend directive is the last byte in the address region. It // has a span length of zero because it's a directive, so if it's selected as // the last offset then our nextOffset calculation will be off by one. (This would // be avoided by using an exclusive end offset, but that causes other problems.) @@ -1865,13 +1867,13 @@ namespace SourceGen { nextOffset++; } - // Compute length of selection. May be zero if it's entirely .arstart/.arend. + // Compute length of selection. May be zero if it's entirely arstart/arend. int selectedLen = nextOffset - firstOffset; AddressMap.AddressRegion curRegion; if (CodeLineList[selIndex].LineType == LineListGen.Line.Type.ArStartDirective || CodeLineList[selIndex].LineType == LineListGen.Line.Type.ArEndDirective) { - // First selected line was .arstart/.arend, find the address map entry. + // First selected line was arstart/arend, find the address map entry. curRegion = CodeLineList.GetAddrRegionFromLine(CodeLineList[selIndex], out bool isSynth); Debug.Assert(curRegion != null); @@ -1888,7 +1890,7 @@ namespace SourceGen { } else { if (selectedLen == 0) { // A length of zero is only possible if nothing but directives were selected, - // but since the first entry wasn't .arstart/.arend this can't happen. + // but since the first entry wasn't arstart/arend this can't happen. Debug.Assert(false); return; } @@ -2820,20 +2822,20 @@ namespace SourceGen { GotoBox dlg = new GotoBox(mMainWin, mProject, offset, mFormatter); if (dlg.ShowDialog() == true) { - GoToLocation(new NavStack.Location(dlg.TargetOffset, 0, false), - GoToMode.JumpToCodeData, true); + GoToLocation(new NavStack.Location(dlg.TargetOffset, 0, + NavStack.GoToMode.JumpToCodeData), true); //mMainWin.CodeListView_Focus(); } } - public enum GoToMode { Unknown = 0, JumpToCodeData, JumpToNote, JumpToAdjIndex }; /// /// Moves the view and selection to the specified offset. We want to select stuff /// differently if we're jumping to a note vs. jumping to an instruction. /// - /// Offset to jump to. + /// Location to jump to. + /// Interesting set of lines within that offset. /// If set, push new offset onto navigation stack. - public void GoToLocation(NavStack.Location loc, GoToMode mode, bool doPush) { + public void GoToLocation(NavStack.Location newLoc, bool doPush) { NavStack.Location prevLoc = GetCurrentlySelectedLocation(); //Debug.WriteLine("GoToLocation: " + loc + " mode=" + mode + " doPush=" + doPush + // " (curLoc=" + prevLoc + ")"); @@ -2844,8 +2846,7 @@ namespace SourceGen { // entry in the symbol table for the current offset, we want to move the selection, // so we don't want to bail out if the offset matches. Easiest thing to do is to // do the move but not push it. - bool jumpToNote = (mode == GoToMode.JumpToNote); - if (loc.Offset == prevLoc.Offset && jumpToNote == prevLoc.IsNote) { + if (newLoc.Offset == prevLoc.Offset && newLoc.Mode == prevLoc.Mode) { // we're jumping to ourselves? if (doPush) { Debug.WriteLine("Ignoring push for goto to current offset"); @@ -2853,27 +2854,30 @@ namespace SourceGen { } } - int topLineIndex = CodeLineList.FindLineIndexByOffset(loc.Offset); + int topLineIndex = CodeLineList.FindLineIndexByOffset(newLoc.Offset); if (topLineIndex < 0) { - Debug.Assert(false, "failed goto offset +" + loc.Offset.ToString("x6")); + Debug.Assert(false, "failed goto offset +" + newLoc.Offset.ToString("x6")); return; } int lastLineIndex; - if (mode == GoToMode.JumpToNote) { + if (newLoc.Mode == NavStack.GoToMode.JumpToNote) { // Select all note lines, disregard the rest. while (CodeLineList[topLineIndex].LineType != LineListGen.Line.Type.Note) { + if (CodeLineList[topLineIndex].FileOffset != newLoc.Offset) { + // This can happen if the note got deleted. + break; + } topLineIndex++; - Debug.Assert(CodeLineList[topLineIndex].FileOffset == loc.Offset); } lastLineIndex = topLineIndex + 1; while (lastLineIndex < CodeLineList.Count && CodeLineList[lastLineIndex].LineType == LineListGen.Line.Type.Note) { lastLineIndex++; } - } else if (loc.Offset < 0) { + } else if (newLoc.Offset < 0) { // This is the offset of the header comment or a .EQ directive. Don't mess with it. lastLineIndex = topLineIndex + 1; - } else if (mode == GoToMode.JumpToCodeData) { + } else if (newLoc.Mode == NavStack.GoToMode.JumpToCodeData) { // Advance to the code or data line. while (CodeLineList[topLineIndex].LineType != LineListGen.Line.Type.Code && CodeLineList[topLineIndex].LineType != LineListGen.Line.Type.Data) { @@ -2881,14 +2885,35 @@ namespace SourceGen { } lastLineIndex = topLineIndex + 1; - } else if (mode == GoToMode.JumpToAdjIndex) { + } else if (newLoc.Mode == NavStack.GoToMode.JumpToAdjIndex) { // Adjust the line position by the line delta. If the adjustment moves us to // a different element, ignore the adjustment. if (CodeLineList[topLineIndex].FileOffset == - CodeLineList[topLineIndex + loc.LineDelta].FileOffset) { - topLineIndex += loc.LineDelta; + CodeLineList[topLineIndex + newLoc.LineDelta].FileOffset) { + topLineIndex += newLoc.LineDelta; } lastLineIndex = topLineIndex + 1; + } else if (newLoc.Mode == NavStack.GoToMode.JumpToArStart || + newLoc.Mode == NavStack.GoToMode.JumpToArEnd) { + LineListGen.Line.Type matchType = LineListGen.Line.Type.ArStartDirective; + if (newLoc.Mode != NavStack.GoToMode.JumpToArStart) { + matchType = LineListGen.Line.Type.ArEndDirective; + } + // Find first instance of specified type. + LineListGen.Line tmpLine = CodeLineList[topLineIndex]; + while (CodeLineList[topLineIndex].LineType != matchType) { + if (CodeLineList[topLineIndex].FileOffset > newLoc.Offset) { + // This can happen if the region got deleted. + break; + } + topLineIndex++; + } + lastLineIndex = topLineIndex + 1; + // If there's multiple lines, make sure they're all on screen. + while (lastLineIndex < CodeLineList.Count && + CodeLineList[lastLineIndex].LineType == matchType) { + lastLineIndex++; + } } else { Debug.Assert(false); lastLineIndex = topLineIndex + 1; @@ -3029,7 +3054,8 @@ namespace SourceGen { int offset = CodeLineList[index].FileOffset; int lineDelta = index - CodeLineList.FindLineIndexByOffset(offset); bool isNote = (CodeLineList[index].LineType == LineListGen.Line.Type.Note); - return new NavStack.Location(offset, lineDelta, isNote); + return new NavStack.Location(offset, lineDelta, + isNote ? NavStack.GoToMode.JumpToNote : NavStack.GoToMode.JumpToAdjIndex); } public void GotoLastChange() { @@ -3076,11 +3102,11 @@ namespace SourceGen { } if (isNote) { - GoToLocation(new NavStack.Location(offset, 0, true), - GoToMode.JumpToNote, true); + GoToLocation(new NavStack.Location(offset, 0, NavStack.GoToMode.JumpToNote), + true); } else { - GoToLocation(new NavStack.Location(offset, 0, false), - GoToMode.JumpToCodeData, true); + GoToLocation(new NavStack.Location(offset, 0, NavStack.GoToMode.JumpToCodeData), + true); } } @@ -3090,8 +3116,7 @@ namespace SourceGen { public void NavigateBackward() { Debug.Assert(mNavStack.HasBackward); NavStack.Location backLoc = mNavStack.MoveBackward(GetCurrentlySelectedLocation()); - GoToLocation(backLoc, - backLoc.IsNote ? GoToMode.JumpToNote : GoToMode.JumpToAdjIndex, false); + GoToLocation(backLoc, false); } public bool CanNavigateForward() { @@ -3100,8 +3125,7 @@ namespace SourceGen { public void NavigateForward() { Debug.Assert(mNavStack.HasForward); NavStack.Location fwdLoc = mNavStack.MoveForward(GetCurrentlySelectedLocation()); - GoToLocation(fwdLoc, - fwdLoc.IsNote ? GoToMode.JumpToNote : GoToMode.JumpToAdjIndex, false); + GoToLocation(fwdLoc, false); } /// @@ -3111,8 +3135,9 @@ namespace SourceGen { public void GoToLabel(Symbol sym) { int offset = mProject.FindLabelOffsetByName(sym.Label); if (offset >= 0) { - GoToLocation(new NavStack.Location(offset, 0, false), - GoToMode.JumpToCodeData, true); + // TODO(someday): jump to correct line for address region pre-labels + GoToLocation(new NavStack.Location(offset, 0, NavStack.GoToMode.JumpToCodeData), + true); } else { Debug.WriteLine("DClick symbol: " + sym + ": label not found"); } @@ -4045,14 +4070,23 @@ namespace SourceGen { esb.Append(" (floating)"); } esb.Append(CRLF); + esb.Append("Pre-label: "); + if (!string.IsNullOrEmpty(region.PreLabel)) { + esb.Append("'"); + esb.Append(region.PreLabel); + if (region.PreLabelAddress == Address.NON_ADDR) { + esb.Append("' (non-addressable)"); + } else { + esb.Append("' addr=$"); + esb.Append(mFormatter.FormatAddress(region.PreLabelAddress, + !mProject.CpuDef.HasAddr16)); + } + } else { + esb.Append("none"); + } + esb.Append(CRLF); esb.Append("Synthetic: " + isSynth); esb.Append(CRLF); - if (!string.IsNullOrEmpty(region.PreLabel)) { - esb.Append("Pre-label: '" + region.PreLabel + "' addr=$"); - esb.Append(mFormatter.FormatAddress(region.PreLabelAddress, - !mProject.CpuDef.HasAddr16)); - esb.Append(CRLF); - } esb.Append("Relative: " + region.IsRelative); esb.Append(CRLF); mMainWin.InfoPanelDetail1 = esb.ToString(); diff --git a/SourceGen/NavStack.cs b/SourceGen/NavStack.cs index a973ef2..103be4b 100644 --- a/SourceGen/NavStack.cs +++ b/SourceGen/NavStack.cs @@ -38,6 +38,15 @@ namespace SourceGen { // TODO(someday): change the back button to a pop-up list of locations (like the way // VS 2017 does it). + public enum GoToMode { + Unknown = 0, + JumpToCodeData, // destination is first byte of code or data at target offset + JumpToNote, // destination is Note at target offset + JumpToAdjIndex, // destination is first line at target offset plus LineDelta + JumpToArStart, // destination is arstart at target offset. + JumpToArEnd, // destination is arend at target offset + }; + /// /// Holds enough information to get us back where we were, in style. /// @@ -49,7 +58,7 @@ namespace SourceGen { /// /// Number of lines between the first line at the specified offset, and the - /// line we actually want to land on. + /// line we actually want to land on. Used when Mode=JumpToAdjIndex. /// /// /// It's possible this line no longer exists. Easiest test is to compare the @@ -59,21 +68,22 @@ namespace SourceGen { public int LineDelta { get; set; } /// - /// True if the target is the note at the given offset, rather than the code/data. + /// Specifies interesting things to find at the target offset. /// - /// - /// This is an alternative to LineDelta. - /// - public bool IsNote { get; set; } + public GoToMode Mode { get; set; } - public Location(int offset, int lineDelta, bool isNote) { + public Location(int offset, int lineDelta, GoToMode mode) { Offset = offset; LineDelta = lineDelta; - IsNote = isNote; + Mode = mode; + + //if (lineDelta != 0 && mode != GoToMode.JumpToAdjIndex) { + // Debug.WriteLine("HEY: lineDelta=" + lineDelta + " mode=" + mode); + //} } public override string ToString() { - return string.Format("[+{0:x6},{1},{2}]", Offset, LineDelta, IsNote); + return string.Format("[+{0:x6},{1},{2}]", Offset, LineDelta, Mode); } public static bool operator ==(Location a, Location b) { @@ -83,7 +93,7 @@ namespace SourceGen { if (ReferenceEquals(a, null) || ReferenceEquals(b, null)) { return false; // one is null } - return a.Offset == b.Offset && a.LineDelta == b.LineDelta && a.IsNote == b.IsNote; + return a.Offset == b.Offset && a.LineDelta == b.LineDelta && a.Mode == b.Mode; } public static bool operator !=(Location a, Location b) { return !(a == b); @@ -92,7 +102,7 @@ namespace SourceGen { return obj is Location && this == (Location)obj; } public override int GetHashCode() { - return Offset + (LineDelta * 1000000) + (IsNote ? (1<<24) : 0); + return Offset + (LineDelta * 1000000) + ((int)Mode << 24); } } diff --git a/SourceGen/PseudoOp.cs b/SourceGen/PseudoOp.cs index 04a8c90..52d3631 100644 --- a/SourceGen/PseudoOp.cs +++ b/SourceGen/PseudoOp.cs @@ -228,8 +228,8 @@ namespace SourceGen { new PseudoOpNames(new Dictionary { { "EquDirective", ".eq" }, { "VarDirective", ".var" }, - { "ArStartDirective", ".arstart" }, - { "ArEndDirective", ".arend" }, + { "ArStartDirective", ".addrs" }, + { "ArEndDirective", ".adrend" }, { "RegWidthDirective", ".rwid" }, { "DataBankDirective", ".dbank" }, diff --git a/SourceGen/RenderAddressMap.cs b/SourceGen/RenderAddressMap.cs index 001b7db..88bbf73 100644 --- a/SourceGen/RenderAddressMap.cs +++ b/SourceGen/RenderAddressMap.cs @@ -45,7 +45,7 @@ namespace SourceGen { int prevAddr = 0; int lastEndOffset = -1; - sb.AppendLine("Address region map for " + project.DataFileName); + sb.AppendLine("Address region map for \"" + project.DataFileName + "\""); sb.Append(CRLF); IEnumerator iter = addrMap.AddressChangeIterator; @@ -67,12 +67,6 @@ namespace SourceGen { } // Start following end, or start following start after a gap. - if (!string.IsNullOrEmpty(change.Region.PreLabel)) { - PrintDepthLines(sb, depth, true); - sb.Append("| pre='" + change.Region.PreLabel + "' "); - PrintAddress(sb, formatter, change.Region.PreLabelAddress, showBank); - sb.Append(CRLF); - } sb.Append(formatter.FormatOffset24(change.Offset)); PrintDepthLines(sb, depth, false); sb.Append("+- " + "start"); @@ -83,10 +77,16 @@ namespace SourceGen { // If there's a label here, show it. Anattrib attr = project.GetAnattrib(change.Offset); if (attr.Symbol != null && !string.IsNullOrEmpty(attr.Symbol.Label)) { - sb.Append(" : "); - sb.Append(attr.Symbol.Label); + sb.Append(" '"); + sb.Append(attr.Symbol.GenerateDisplayLabel(formatter)); + sb.Append("'"); } } + if (change.Region.HasValidPreLabel) { + sb.Append(" pre='"); + sb.Append(change.Region.PreLabel); + sb.Append("'"); + } sb.Append(CRLF); diff --git a/SourceGen/RuntimeData/SGStyle.css b/SourceGen/RuntimeData/SGStyle.css index 3be2f60..10f492d 100644 --- a/SourceGen/RuntimeData/SGStyle.css +++ b/SourceGen/RuntimeData/SGStyle.css @@ -1,6 +1,10 @@ /* * 6502bench SourceGen disassembly output style. */ + +/* + * General formatting. + */ body { font-family: Arial, Helvetica, sans-serif; font-size: 14px; /* 16 recommended for mobile */ @@ -11,6 +15,9 @@ table, th, td { border: 1px solid black; border-collapse: collapse; } +.greytext { + color: grey; +} /* * Blue underlined text is distracting. Change internal links to be diff --git a/SourceGen/SGTestData/20170-external-symbols-1.sym65 b/SourceGen/SGTestData/20170-external-symbols-1.sym65 index fdec8cd..2ee61e4 100644 --- a/SourceGen/SGTestData/20170-external-symbols-1.sym65 +++ b/SourceGen/SGTestData/20170-external-symbols-1.sym65 @@ -52,7 +52,8 @@ OverVar @ $40 4 BankWrap @ $fff0 $20 ; Width specifiers on constants should be ignored. -FatConst = $4000 8 +; Uses a leading '_' to test special 64tass handling. +_FatConst = $4000 8 ; Overlapping multi-byte items with exact and inexact matches. OverA_0 @ $6000 8 ;should win, alphabetically diff --git a/SourceGen/SGTestData/20170-external-symbols.dis65 b/SourceGen/SGTestData/20170-external-symbols.dis65 index 049369a..78df66a 100644 --- a/SourceGen/SGTestData/20170-external-symbols.dis65 +++ b/SourceGen/SGTestData/20170-external-symbols.dis65 @@ -27,7 +27,7 @@ "OperandFormats":{ "207":{ "Length":3,"Format":"NumericLE","SubFormat":"Symbol","SymbolRef":{ -"Label":"FatConst","Part":"Low"}}}, +"Label":"_FatConst","Part":"Low"}}}, "LvTables":{ "192":{ "Variables":[{ diff --git a/SourceGen/SGTestData/20260-pre-labels b/SourceGen/SGTestData/20260-pre-labels new file mode 100644 index 0000000000000000000000000000000000000000..5f523b4f2acea546400de27685dc720156bd96ab GIT binary patch literal 95 zcmXZTyA6Oa3`Nm507WW8=>cBhp2h>X$Ou`5&pO$KIb1OUiG*~kBV81tWM)7K%`V#4 lkqzRe0Xt5@a-!JpsDXCfL?h~am&y@b#X)iICGh5h#0LxBAGiPj literal 0 HcmV?d00001 diff --git a/SourceGen/SGTestData/20260-pre-labels.dis65 b/SourceGen/SGTestData/20260-pre-labels.dis65 new file mode 100644 index 0000000..2d7fef3 --- /dev/null +++ b/SourceGen/SGTestData/20260-pre-labels.dis65 @@ -0,0 +1,219 @@ +### 6502bench SourceGen dis65 v1.0 ### +{ +"_ContentVersion":5, +"FileDataLength":95, +"FileDataCrc32":482033261, +"ProjectProps":{ +"CpuName":"6502", +"IncludeUndocumentedInstr":false, +"TwoByteBrk":false, +"EntryFlags":32702671, +"AutoLabelStyle":"Simple", +"AnalysisParams":{ +"AnalyzeUncategorizedData":true, +"DefaultTextScanMode":"LowHighAscii", +"MinCharsForString":4, +"SeekNearbyTargets":false, +"UseRelocData":false, +"SmartPlpHandling":false, +"SmartPlbHandling":true}, + +"PlatformSymbolFileIdentifiers":[], +"ExtensionScriptFileIdentifiers":[], +"ProjectSyms":{ +"part2":{ +"DataDescriptor":{ +"Length":1, +"Format":"NumericLE", +"SubFormat":"Hex", +"SymbolRef":null}, + +"Comment":"precedence test", +"HasWidth":false, +"Direction":"ReadWrite", +"MultiMask":null, +"Label":"part2", +"Value":4155, +"Source":"Project", +"Type":"ExternalAddr", +"LabelAnno":"None"}, + +"zzz":{ +"DataDescriptor":{ +"Length":1, +"Format":"NumericLE", +"SubFormat":"Hex", +"SymbolRef":null}, + +"Comment":"", +"HasWidth":false, +"Direction":"ReadWrite", +"MultiMask":null, +"Label":"zzz", +"Value":4155, +"Source":"Project", +"Type":"ExternalAddr", +"LabelAnno":"None"}}}, + +"AddressMap":[{ +"Offset":0, +"Addr":-1025, +"Length":2, +"PreLabel":"", +"IsRelative":false}, + +{ +"Offset":2, +"Addr":4096, +"Length":-1024, +"PreLabel":"b4_begin", +"IsRelative":false}, + +{ +"Offset":11, +"Addr":8192, +"Length":48, +"PreLabel":"b4_part2", +"IsRelative":false}, + +{ +"Offset":35, +"Addr":12288, +"Length":-1024, +"PreLabel":"b4_part3", +"IsRelative":false}, + +{ +"Offset":59, +"Addr":16384, +"Length":31, +"PreLabel":"b4_part4b", +"IsRelative":false}, + +{ +"Offset":59, +"Addr":20480, +"Length":21, +"PreLabel":"b4_part4a", +"IsRelative":false}, + +{ +"Offset":59, +"Addr":24576, +"Length":12, +"PreLabel":"_b4_part4", +"IsRelative":false}, + +{ +"Offset":90, +"Addr":61440, +"Length":3, +"PreLabel":"", +"IsRelative":false}], +"TypeHints":[{ +"Low":2, +"High":2, +"Hint":"Code"}], +"StatusFlagOverrides":{ +}, + +"Comments":{ +}, + +"LongComments":{ +}, + +"Notes":{ +}, + +"UserLabels":{ +"2":{ +"Label":"begin", +"Value":4096, +"Source":"User", +"Type":"GlobalAddr", +"LabelAnno":"None"}, + +"11":{ +"Label":"part2", +"Value":8192, +"Source":"User", +"Type":"GlobalAddr", +"LabelAnno":"None"}, + +"33":{ +"Label":"local1", +"Value":8214, +"Source":"User", +"Type":"NonUniqueLocalAddr", +"LabelAnno":"None"}, + +"34":{ +"Label":"local2", +"Value":8215, +"Source":"User", +"Type":"NonUniqueLocalAddr", +"LabelAnno":"None"}, + +"57":{ +"Label":"local3", +"Value":12310, +"Source":"User", +"Type":"NonUniqueLocalAddr", +"LabelAnno":"None"}, + +"58":{ +"Label":"local4", +"Value":12311, +"Source":"User", +"Type":"NonUniqueLocalAddr", +"LabelAnno":"None"}, + +"35":{ +"Label":"part3", +"Value":12288, +"Source":"User", +"Type":"NonUniqueLocalAddr", +"LabelAnno":"None"}, + +"81":{ +"Label":"part4b", +"Value":16406, +"Source":"User", +"Type":"GlobalAddr", +"LabelAnno":"None"}, + +"71":{ +"Label":"part4a", +"Value":20492, +"Source":"User", +"Type":"GlobalAddr", +"LabelAnno":"None"}, + +"59":{ +"Label":"part4", +"Value":24576, +"Source":"User", +"Type":"GlobalAddr", +"LabelAnno":"None"}}, + +"OperandFormats":{ +"0":{ +"Length":2, +"Format":"NumericLE", +"SubFormat":"None", +"SymbolRef":null}}, + +"LvTables":{ +}, + +"Visualizations":[], +"VisualizationAnimations":[], +"VisualizationSets":{ +}, + +"RelocList":{ +}, + +"DbrValues":{ +}} diff --git a/SourceGen/SGTestData/Expected/20170-external-symbols_64tass.S b/SourceGen/SGTestData/Expected/20170-external-symbols_64tass.S index b0633f1..d025d6b 100644 --- a/SourceGen/SGTestData/Expected/20170-external-symbols_64tass.S +++ b/SourceGen/SGTestData/Expected/20170-external-symbols_64tass.S @@ -1,5 +1,5 @@ .cpu "6502" -FatConst = $4000 +X_FatConst = $4000 OverVar = $40 CodeWrap = $0f00 ;encases program @@ -116,7 +116,7 @@ LocalVar .var $41 ldx OverVar+3 ldx $44 nop - lda FatConst-1 + lda X_FatConst-1 lda $4000 lda $4001 lda BankWrap+8 diff --git a/SourceGen/SGTestData/Expected/20170-external-symbols_acme.S b/SourceGen/SGTestData/Expected/20170-external-symbols_acme.S index 15fd1c6..f6329c7 100644 --- a/SourceGen/SGTestData/Expected/20170-external-symbols_acme.S +++ b/SourceGen/SGTestData/Expected/20170-external-symbols_acme.S @@ -1,5 +1,5 @@ !cpu 6502 -FatConst = $4000 +_FatConst = $4000 OverVar = $40 CodeWrap = $0f00 ;encases program @@ -117,7 +117,7 @@ L1000 lda CodeWrap+255 ldx OverVar+3 ldx $44 nop - lda FatConst-1 + lda _FatConst-1 lda $4000 lda $4001 lda BankWrap+8 diff --git a/SourceGen/SGTestData/Expected/20170-external-symbols_cc65.S b/SourceGen/SGTestData/Expected/20170-external-symbols_cc65.S index 1378fa4..7777382 100644 --- a/SourceGen/SGTestData/Expected/20170-external-symbols_cc65.S +++ b/SourceGen/SGTestData/Expected/20170-external-symbols_cc65.S @@ -1,5 +1,5 @@ .setcpu "6502" -FatConst = $4000 +_FatConst = $4000 OverVar = $40 CodeWrap = $0f00 ;encases program @@ -116,7 +116,7 @@ LocalVar .set $41 ldx OverVar+3 ldx $44 nop - lda FatConst-1 + lda _FatConst-1 lda $4000 lda $4001 lda BankWrap+8 diff --git a/SourceGen/SGTestData/Expected/20170-external-symbols_merlin32.S b/SourceGen/SGTestData/Expected/20170-external-symbols_merlin32.S index e5b578d..b3030fb 100644 --- a/SourceGen/SGTestData/Expected/20170-external-symbols_merlin32.S +++ b/SourceGen/SGTestData/Expected/20170-external-symbols_merlin32.S @@ -1,4 +1,4 @@ -FatConst equ $4000 +_FatConst equ $4000 OverVar equ $40 CodeWrap equ $0f00 ;encases program @@ -115,7 +115,7 @@ L1000 lda CodeWrap+255 ldx OverVar+3 ldx $44 nop - lda FatConst-1 + lda _FatConst-1 lda $4000 lda $4001 lda BankWrap+8 diff --git a/SourceGen/SGTestData/Expected/20260-pre-labels_64tass.S b/SourceGen/SGTestData/Expected/20260-pre-labels_64tass.S new file mode 100644 index 0000000..1cb8ed3 --- /dev/null +++ b/SourceGen/SGTestData/Expected/20260-pre-labels_64tass.S @@ -0,0 +1,76 @@ + .cpu "6502" +zzz = $103b + + +* = $1000 +begin bit begin + nop + nop + nop + jmp part2 + + .logical $2000 +part2 bit part2 + nop + lda _local1 + lda local2 + lda local4 + nop + nop + nop + bit b4_part3 + jmp part3 + +_local1 .byte $81 +local2 .byte $82 + +b4_part3 + .logical $3000 +part3 bit part3 + nop + lda local2 + lda _local3 + lda local4 + nop + nop + nop + bit X_b4_part4 + jmp part4 + +_local3 .byte $83 +local4 .byte $84 + .here + .here + + .logical $4000 +b4_part4a + .logical $5000 +X_b4_part4 + .logical $6000 +part4 bit part4 + bit X_b4_part4 + nop + nop + nop + jmp part4a + + .here +part4a bit part4a + bit b4_part4a + jsr part4b + .here + .byte $00 + +part4b bit part4b + bit zzz + jmp _LF000 + + .here + .logical $f000 +_LF000 nop + bne $f003 + .here + .logical $0000 + .byte $ea + .byte $00 + .here diff --git a/SourceGen/SGTestData/Expected/20260-pre-labels_acme.S b/SourceGen/SGTestData/Expected/20260-pre-labels_acme.S new file mode 100644 index 0000000..eae9d0b --- /dev/null +++ b/SourceGen/SGTestData/Expected/20260-pre-labels_acme.S @@ -0,0 +1,79 @@ + !cpu 6502 +zzz = $103b + +* = $0000 + !word $1000 + + !pseudopc $1000 { +begin bit begin + nop + nop + nop + jmp part2 + + } + !pseudopc $2000 { +part2 bit part2 + nop + lda @local1 + lda local2 + lda local4 + nop + nop + nop + bit b4_part3 + jmp part3 + +@local1 !byte $81 +local2 !byte $82 + +b4_part3 + !pseudopc $3000 { +part3 bit part3 + nop + lda local2 + lda @local3 + lda local4 + nop + nop + nop + bit _b4_part4 + jmp part4 + +@local3 !byte $83 +local4 !byte $84 + } + } + + !pseudopc $4000 { +b4_part4a + !pseudopc $5000 { +_b4_part4 + !pseudopc $6000 { +part4 bit part4 + bit _b4_part4 + nop + nop + nop + jmp part4a + + } +part4a bit part4a + bit b4_part4a + jsr part4b + } + !byte $00 + +part4b bit part4b + bit zzz + jmp @LF000 + + } + !pseudopc $f000 { +@LF000 nop + bne $f003 + } + !pseudopc $0000 { + !byte $ea + !byte $00 + } diff --git a/SourceGen/SGTestData/Expected/20260-pre-labels_cc65.S b/SourceGen/SGTestData/Expected/20260-pre-labels_cc65.S new file mode 100644 index 0000000..bfe1d84 --- /dev/null +++ b/SourceGen/SGTestData/Expected/20260-pre-labels_cc65.S @@ -0,0 +1,73 @@ + .setcpu "6502" +zzz = $103b + + .org $0000 + .word $1000 + + .org $1000 +begin: bit begin + nop + nop + nop + jmp part2 + + .org $2000 +part2: bit part2 + nop + lda @local1 + lda local2 + lda local4 + nop + nop + nop + bit b4_part3 + jmp part3 + +@local1: .byte $81 +local2: .byte $82 + +b4_part3: + .org $3000 +part3: bit part3 + nop + lda local2 + lda @local3 + lda local4 + nop + nop + nop + bit _b4_part4 + jmp part4 + +@local3: .byte $83 +local4: .byte $84 + + .org $4000 +b4_part4a: + .org $5000 +_b4_part4: + .org $6000 +part4: bit part4 + bit _b4_part4 + nop + nop + nop + jmp part4a + + .org $500c +part4a: bit part4a + bit b4_part4a + jsr part4b + .org $4015 + .byte $00 + +part4b: bit part4b + bit zzz + jmp @LF000 + + .org $f000 +@LF000: nop + bne $f003 + .org $0000 + .byte $ea + .byte $00 diff --git a/SourceGen/SGTestData/Expected/20260-pre-labels_cc65.cfg b/SourceGen/SGTestData/Expected/20260-pre-labels_cc65.cfg new file mode 100644 index 0000000..cd98926 --- /dev/null +++ b/SourceGen/SGTestData/Expected/20260-pre-labels_cc65.cfg @@ -0,0 +1,9 @@ +# 6502bench SourceGen generated linker script for 20260-pre-labels +MEMORY { + MAIN: file=%O, start=%S, size=65536; +} +SEGMENTS { + CODE: load=MAIN, type=rw; +} +FEATURES {} +SYMBOLS {} diff --git a/SourceGen/SGTestData/Expected/20260-pre-labels_merlin32.S b/SourceGen/SGTestData/Expected/20260-pre-labels_merlin32.S new file mode 100644 index 0000000..4b5455c --- /dev/null +++ b/SourceGen/SGTestData/Expected/20260-pre-labels_merlin32.S @@ -0,0 +1,72 @@ +zzz equ $103b + + org $0000 + dw $1000 + + org $1000 +begin bit begin + nop + nop + nop + jmp part2 + + org $2000 +part2 bit part2 + nop + lda :local1 + lda local2 + lda local4 + nop + nop + nop + bit b4_part3 + jmp part3 + +:local1 dfb $81 +local2 dfb $82 + +b4_part3 + org $3000 +part3 bit part3 + nop + lda local2 + lda :local3 + lda local4 + nop + nop + nop + bit _b4_part4 + jmp part4 + +:local3 dfb $83 +local4 dfb $84 + + org $4000 +b4_part4a + org $5000 +_b4_part4 + org $6000 +part4 bit part4 + bit _b4_part4 + nop + nop + nop + jmp part4a + + org $500c +part4a bit part4a + bit b4_part4a + jsr part4b + org $4015 + dfb $00 + +part4b bit part4b + bit zzz + jmp :LF000 + + org $f000 +:LF000 nop + bne $f003 + org $0000 + dfb $ea + dfb $00 diff --git a/SourceGen/SGTestData/Source/20260-pre-labels.S b/SourceGen/SGTestData/Source/20260-pre-labels.S new file mode 100644 index 0000000..4b00437 --- /dev/null +++ b/SourceGen/SGTestData/Source/20260-pre-labels.S @@ -0,0 +1,111 @@ +; Copyright 2021 faddenSoft. All Rights Reserved. +; See the LICENSE.txt file for distribution terms (Apache 2.0). +; +; Test address region pre-labels. +; +; Assembler: 64tass +; % tass64 --ascii --case-sensitive --nostart 20260-nested-regions.S + + .cpu "6502" +* = $1000 + +; EDIT: create project symbol with same name as pre-label (pre-label should win) +; FILE-EDIT: change pre-label to match user label + +; EDIT: create explicit 2-byte NON_ADDR region here. +START + .word $1000 + + + .logical $1000 +; EDIT: create floating address region with pre-label here ($1000) +; (label should not appear because parent is non-addr) +begin bit begin + nop + nop + nop + jmp part2 + .here + +; EDIT: create fixed address region with pre-label here ($2000) +; (label should not appear because parent is non-addr) + .logical $2000 +part2 bit part2 + nop + lda _local1 + lda _local2 + lda _local4 ;this should force global conv +; (don't do _local3 here, or it gets promoted to global and interferes +; with local access to both _local3 and _local 4 later on) + nop + nop + nop + bit _b4_part3 + jmp _part3 + +_local1 .byte $81 ;data item with local label +_local2 .byte $82 ;data item with local label + +; EDIT: create floating address region with pre-label here ($3000) +_b4_part3 + .logical $3000 +_part3 bit _part3 ;NOTE: label must be declared local + nop + lda _local2 ;this should force global conv + lda _local3 + lda _local4 + nop + nop + nop + bit b4_part4 + jmp part4 + +_local3 .byte $83 ;data item with local label +_local4 .byte $84 ;data item with local label + +; the $2000 range ends here; the $3000 floater also ends here + .here + .here + +; Stack up multiple pre-labels at same offset. + + +; EDIT: create fixed address region with pre-label here ($4000) +; (label should not appear) +b4_part4b ;(not accessible) + .logical $4000 +; EDIT: create fixed address region with pre-label here ($5000) +b4_part4a + .logical $5000 +; EDIT: create fixed address region with pre-label here ($6000) +b4_part4 + .logical $6000 +part4 bit part4 + bit b4_part4 + nop + nop + nop + jmp part4a + .here +part4a bit part4a + bit b4_part4a + jsr part4b ;JSR to test code analysis halt + .here + brk ;shouldn't reach here +part4b bit part4b + bit b4_part4b + jmp end + .here + + + +; EDIT: created fixed 3-byte address region + .logical $f000 +end + nop + bne past ;BNE operand should be shown as hex value + +; EDIT: put actual end here, before the nop +past nop + .here + brk diff --git a/SourceGen/WpfGui/EditAddress.xaml.cs b/SourceGen/WpfGui/EditAddress.xaml.cs index f43fba3..4ee4264 100644 --- a/SourceGen/WpfGui/EditAddress.xaml.cs +++ b/SourceGen/WpfGui/EditAddress.xaml.cs @@ -309,7 +309,7 @@ namespace SourceGen.WpfGui { mPreLabelAddress = curRegion.PreLabelAddress; if (isSingleLine) { - // Only thing selected was .arstart/.arend. First action is to edit + // Only thing selected was arstart/arend. First action is to edit // the region properties, second action is to convert floating end // to fixed. mResultEntry1 = new AddressMap.AddressMapEntry(curRegion.Offset, @@ -332,7 +332,7 @@ namespace SourceGen.WpfGui { } } else { - // Selection started with .arstart and included multiple lines. First + // Selection started with arstart and included multiple lines. First // action is to resize region. Second action is edit without resize. // If resize is illegal (e.g. new region exactly overlaps another), // first action is disabled. diff --git a/SourceGen/WpfGui/MainWindow.xaml.cs b/SourceGen/WpfGui/MainWindow.xaml.cs index 30e5e1c..afbb059 100644 --- a/SourceGen/WpfGui/MainWindow.xaml.cs +++ b/SourceGen/WpfGui/MainWindow.xaml.cs @@ -1672,8 +1672,8 @@ namespace SourceGen.WpfGui { ReferencesListItem rli = (ReferencesListItem)item; // Jump to the offset, then shift the focus back to the code list. - mMainCtrl.GoToLocation(new NavStack.Location(rli.OffsetValue, 0, false), - MainController.GoToMode.JumpToCodeData, true); + mMainCtrl.GoToLocation(new NavStack.Location(rli.OffsetValue, 0, + NavStack.GoToMode.JumpToCodeData), true); codeListView.Focus(); } @@ -1716,8 +1716,8 @@ namespace SourceGen.WpfGui { NotesListItem nli = (NotesListItem)item; // Jump to the offset, then shift the focus back to the code list. - mMainCtrl.GoToLocation(new NavStack.Location(nli.OffsetValue, 0, true), - MainController.GoToMode.JumpToNote, true); + mMainCtrl.GoToLocation(new NavStack.Location(nli.OffsetValue, 0, + NavStack.GoToMode.JumpToNote), true); codeListView.Focus(); } @@ -2098,8 +2098,8 @@ namespace SourceGen.WpfGui { MessageListItem mli = (MessageListItem)item; // Jump to the offset, then shift the focus back to the code list. - mMainCtrl.GoToLocation(new NavStack.Location(mli.OffsetValue, 0, false), - MainController.GoToMode.JumpToCodeData, true); + mMainCtrl.GoToLocation(new NavStack.Location(mli.OffsetValue, 0, + NavStack.GoToMode.JumpToCodeData), true); codeListView.Focus(); }