From 2828cc8ca798bb13965b9135d799a16bd781fd6c Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Sun, 15 Sep 2019 14:19:45 -0700 Subject: [PATCH] Apply project/platform symbols to Numeric/Address data operands A ".dd2
" item would get linked to an internal label, but references to external addresses weren't doing the appropriate search through the platform/project symbol list. This change altered the output of the 2019-local-variables test. The previous behavior was restored by disabling "nearby" symbol matching in the project properties. Updated the "lookup symbol by address" function to ignore local variables. Also, minor updates to Applesoft and F8-ROM symbol tables. --- SourceGen/DisasmProject.cs | 48 ++++++++++++++----- SourceGen/RuntimeData/Apple/Applesoft.sym65 | 2 + SourceGen/RuntimeData/Apple/F8-ROM.sym65 | 15 ++++-- .../SGTestData/2019-local-variables.dis65 | 4 +- .../Expected/2019-local-variables_64tass.S | 2 +- .../Expected/2019-local-variables_Merlin32.S | 2 +- .../Expected/2019-local-variables_acme.S | 2 +- .../Expected/2019-local-variables_cc65.S | 2 +- SourceGen/SymbolTable.cs | 10 ++-- 9 files changed, 60 insertions(+), 27 deletions(-) diff --git a/SourceGen/DisasmProject.cs b/SourceGen/DisasmProject.cs index 9e74dda..fe3069e 100644 --- a/SourceGen/DisasmProject.cs +++ b/SourceGen/DisasmProject.cs @@ -1069,6 +1069,8 @@ namespace SourceGen { for (int offset = 0; offset < mAnattribs.Length; ) { Anattrib attr = mAnattribs[offset]; + Symbol sym; + int address; if (attr.IsInstructionStart && attr.DataDescriptor == null && attr.OperandAddress >= 0 && attr.OperandOffset < 0) { // Has an operand address, but not an offset, meaning it's a reference @@ -1083,29 +1085,56 @@ namespace SourceGen { // Using the full symbol table is potentially a tad less efficient than // looking for a match exclusively in project/platform symbols, but it's // the correct thing to do. - Symbol sym = SymbolTable.FindAddressByValue(attr.OperandAddress); + address = attr.OperandAddress; + sym = SymbolTable.FindNonVariableByAddress(address); + } else if (attr.IsDataStart && attr.DataDescriptor != null && + attr.DataDescriptor.IsNumeric && + attr.DataDescriptor.FormatSubType == FormatDescriptor.SubType.Address) { + // Found a Numeric/Address item that matches. Data items don't have + // OperandAddress or OperandOffset set, so we need to check manually to + // see if the address falls within the project. In most situations this + // isn't really necessary, because the data analysis pass will have resolved + // interal references to auto-generated labels. + // + // This is only firing if the item is explicitly formatted as an + // Address, so we're essentially "upgrading" the user format. + address = RawData.GetWord(mFileData, offset, attr.DataDescriptor.Length, + attr.DataDescriptor.FormatType == FormatDescriptor.Type.NumericBE); + if (AddrMap.AddressToOffset(offset, address) < 0) { + sym = SymbolTable.FindNonVariableByAddress(address); + } else { + Debug.WriteLine("Found unhandled internal data addr ref at +" + + offset.ToString("x6")); + address = -1; // don't touch interior stuff + sym = null; + } + } else { + address = -1; + sym = null; + } + if (address >= 0) { // If we didn't find it, check addr-1. This is very helpful when working // with pointers, because it gets us references to "PTR+1" when "PTR" is // defined. (It's potentially helpful in labeling the "near side" of an // address map split as well, since the first byte past is an external // address, and a label at the end of the current region will be offset // from by this.) - if (sym == null && (attr.OperandAddress & 0xffff) > 0 && checkNearby) { - sym = SymbolTable.FindAddressByValue(attr.OperandAddress - 1); + if (sym == null && (address & 0xffff) > 0 && checkNearby) { + sym = SymbolTable.FindNonVariableByAddress(address - 1); } // If that didn't work, try addr-2. Good for 24-bit addresses and jump // vectors that start with a JMP instruction. - if (sym == null && (attr.OperandAddress & 0xffff) > 1 && checkNearby) { - sym = SymbolTable.FindAddressByValue(attr.OperandAddress - 2); + if (sym == null && (address & 0xffff) > 1 && checkNearby) { + sym = SymbolTable.FindNonVariableByAddress(address - 2); } // Still nothing, try addr+1. Sometimes indexed addressing will use // "STA addr-1,y". This will also catch "STA addr-1" when addr is the // very start of a segment, which means we're actually finding a label // reference rather than project/platform symbol; only works if the // location already has a label. - if (sym == null && (attr.OperandAddress & 0xffff) < 0xffff && checkNearby) { - sym = SymbolTable.FindAddressByValue(attr.OperandAddress + 1); + if (sym == null && (address & 0xffff) < 0xffff && checkNearby) { + sym = SymbolTable.FindNonVariableByAddress(address + 1); if (sym != null && sym.SymbolSource != Symbol.Source.Project && sym.SymbolSource != Symbol.Source.Platform) { Debug.WriteLine("Applying non-platform in GeneratePlatform: " + sym); @@ -1118,11 +1147,6 @@ namespace SourceGen { mAnattribs[offset].DataDescriptor = FormatDescriptor.Create(mAnattribs[offset].Length, new WeakSymbolRef(sym.Label, WeakSymbolRef.Part.Low), false); - - // Used to do this here; now do it in GenerateXrefs() so we can - // pick up user-edited operand formats that reference project symbols. - //(sym as DefSymbol).Xrefs.Add(new XrefSet.Xref(offset, - // XrefSet.XrefType.NameReference, 0)); } } diff --git a/SourceGen/RuntimeData/Apple/Applesoft.sym65 b/SourceGen/RuntimeData/Apple/Applesoft.sym65 index 35f7a41..b5cee6a 100644 --- a/SourceGen/RuntimeData/Apple/Applesoft.sym65 +++ b/SourceGen/RuntimeData/Apple/Applesoft.sym65 @@ -6,6 +6,7 @@ *SYNOPSIS Applesoft BASIC addresses and constants +USRVEC @ $0A ;USR() command vector HCOLOR1 @ $1C ;hi-res color mask COUNTH @ $1D ;hi-res high-order byte of step for line HBASL @ $26 ;base address for hi-res drawing @@ -23,6 +24,7 @@ CURLIN @ $75 ;Applesoft current line number (2b) FACMO @ $A0 ;middle-order byte of mantissa of FAC FACLO @ $A1 ;low-order byte of mantissa of FAC FACSIGN @ $A2 ;single byte sign of FAC +PRGEND @ $AF ;pointer to end of program (2b) CHRGET @ $B1 ;get next character or Applesoft token CHRGOT @ $B7 ;get next, but don't advance TXTPTR TXTPTR @ $B8 ;points at next char or token diff --git a/SourceGen/RuntimeData/Apple/F8-ROM.sym65 b/SourceGen/RuntimeData/Apple/F8-ROM.sym65 index 2c5f2f2..e2e992b 100644 --- a/SourceGen/RuntimeData/Apple/F8-ROM.sym65 +++ b/SourceGen/RuntimeData/Apple/F8-ROM.sym65 @@ -13,7 +13,10 @@ WNDTOP @ $22 ;top of scroll window WNDBTM @ $23 ;bottom of scsroll window CH @ $24 ;cursor horizontal displacement CV @ $25 ;cursor vertical displacement -GBASL @ $26 ;base address for lo-res drawing +GBASL @ $26 ;base address for lo-res drawing (lo) +GBASH @ $27 ;base address for lo-res drawing (hi) +H2 @ $2C ;right end of horizontal line drawn by HLINE +V2 @ $2D ;bottom of vertical line drawn by VLINE INVFLAG @ $32 ;text mask (255=normal, 127=flash, 63=inv) PROMPT @ $33 ;prompt character CSWL @ $36 ;character output hook (lo) @@ -24,12 +27,14 @@ PCL @ $3A ;program counter save PCH @ $3B ;program counter save A1L @ $3C ;general purpose A1H @ $3D ;general purpose +A2L @ $3E ;general purpose +A2H @ $3F ;general purpose -SPDBYT @ $E7 ;text output speed limiter +SPDBYT @ $F1 ;text output speed limiter -BRKV @ $03f0 ;address of BRK handler -SOFTEVEC @ $03f2 ;address of RESET handler -PWREDUP @ $03f4 ;power-up RESET checksum +BRKV @ $03F0 ;address of BRK handler +SOFTEVEC @ $03F2 ;address of RESET handler +PWREDUP @ $03F4 ;power-up RESET checksum USRADDR @ $03F8 ;jump to function that handles monitor Ctrl-Y NMIVEC @ $03FB ;jump to function that handles NMI IRQADDR @ $03FE ;address of IRQ handler diff --git a/SourceGen/SGTestData/2019-local-variables.dis65 b/SourceGen/SGTestData/2019-local-variables.dis65 index e7eb92c..ba3f3cd 100644 --- a/SourceGen/SGTestData/2019-local-variables.dis65 +++ b/SourceGen/SGTestData/2019-local-variables.dis65 @@ -2,7 +2,7 @@ { "_ContentVersion":2,"FileDataLength":137,"FileDataCrc32":708791740,"ProjectProps":{ "CpuName":"65816","IncludeUndocumentedInstr":false,"EntryFlags":32702671,"AutoLabelStyle":"Simple","AnalysisParams":{ -"AnalyzeUncategorizedData":true,"DefaultTextScanMode":"LowHighAscii","MinCharsForString":4,"SeekNearbyTargets":true,"SmartPlpHandling":false}, +"AnalyzeUncategorizedData":true,"DefaultTextScanMode":"LowHighAscii","MinCharsForString":4,"SeekNearbyTargets":false,"SmartPlpHandling":false}, "PlatformSymbolFileIdentifiers":[],"ExtensionScriptFileIdentifiers":[],"ProjectSyms":{ "CONST_ONE":{ "DataDescriptor":{ @@ -31,7 +31,7 @@ "Low":0,"High":0,"Hint":"Code"}],"StatusFlagOverrides":{ }, "Comments":{ -}, +"4":"could be PROJ_ONE+2, but \"nearby\" is off"}, "LongComments":{ "-2147483647":{ "Text":"Edited to have duplicate labels (PROJ_ZERO, DPCODE).","BoxMode":false,"MaxWidth":80,"BackgroundColor":0}, diff --git a/SourceGen/SGTestData/Expected/2019-local-variables_64tass.S b/SourceGen/SGTestData/Expected/2019-local-variables_64tass.S index 4b9e10e..ae249e5 100644 --- a/SourceGen/SGTestData/Expected/2019-local-variables_64tass.S +++ b/SourceGen/SGTestData/Expected/2019-local-variables_64tass.S @@ -9,7 +9,7 @@ CONST_ZERO = $f0 ;project const .xs ldy PROJ_ZERO lda (PROJ_ONE),y - sta $03 + sta $03 ;could be PROJ_ONE+2, but "nearby" is off ldx $04 lda CONST_ZERO,s sta $f1,s diff --git a/SourceGen/SGTestData/Expected/2019-local-variables_Merlin32.S b/SourceGen/SGTestData/Expected/2019-local-variables_Merlin32.S index 1c2e82e..9a21569 100644 --- a/SourceGen/SGTestData/Expected/2019-local-variables_Merlin32.S +++ b/SourceGen/SGTestData/Expected/2019-local-variables_Merlin32.S @@ -6,7 +6,7 @@ CONST_ZERO equ $f0 ;project const org $1000 ldy PROJ_ZERO lda (PROJ_ONE),y - sta $03 + sta $03 ;could be PROJ_ONE+2, but "nearby" is off ldx $04 lda CONST_ZERO,S sta $f1,S diff --git a/SourceGen/SGTestData/Expected/2019-local-variables_acme.S b/SourceGen/SGTestData/Expected/2019-local-variables_acme.S index f4d88ce..86746b4 100644 --- a/SourceGen/SGTestData/Expected/2019-local-variables_acme.S +++ b/SourceGen/SGTestData/Expected/2019-local-variables_acme.S @@ -9,7 +9,7 @@ CONST_ZERO = $f0 ;project const !rs ldy PROJ_ZERO lda (PROJ_ONE),y - sta $03 + sta $03 ;could be PROJ_ONE+2, but "nearby" is off ldx $04 lda CONST_ZERO,S sta $f1,S diff --git a/SourceGen/SGTestData/Expected/2019-local-variables_cc65.S b/SourceGen/SGTestData/Expected/2019-local-variables_cc65.S index 6dc2cb2..92f34eb 100644 --- a/SourceGen/SGTestData/Expected/2019-local-variables_cc65.S +++ b/SourceGen/SGTestData/Expected/2019-local-variables_cc65.S @@ -10,7 +10,7 @@ CONST_ZERO = $f0 ;project const .i8 ldy PROJ_ZERO lda (PROJ_ONE),y - sta $03 + sta $03 ;could be PROJ_ONE+2, but "nearby" is off ldx $04 lda CONST_ZERO,S sta $f1,S diff --git a/SourceGen/SymbolTable.cs b/SourceGen/SymbolTable.cs index 6ab4c45..a66f8e2 100644 --- a/SourceGen/SymbolTable.cs +++ b/SourceGen/SymbolTable.cs @@ -144,11 +144,12 @@ namespace SourceGen { } /// - /// Searches the table for symbols with matching address values. Ignores constants. + /// Searches the table for symbols with matching address values. Ignores constants and + /// variables. /// /// Value to find. /// First matching symbol found, or null if nothing matched. - public Symbol FindAddressByValue(int value) { + public Symbol FindNonVariableByAddress(int value) { // Get sorted list of values. This is documented as efficient. IList values = mSymbolsByValue.Values; @@ -169,8 +170,9 @@ namespace SourceGen { while (mid > 0 && values[mid - 1].Value == value) { mid--; } - // now skip past constants - while (mid < values.Count && values[mid].SymbolType == Symbol.Type.Constant) { + // now skip past constants and variables + while (mid < values.Count && (values[mid].SymbolType == Symbol.Type.Constant || + values[mid].SymbolSource == Symbol.Source.Variable)) { //Debug.WriteLine("disregarding " + values[mid]); mid++; }