From 03a0fc13fd3ac3d8fb6925bd32e955c7491586ef Mon Sep 17 00:00:00 2001
From: Andy McFadden
Date: Tue, 20 Jul 2021 13:08:19 -0700
Subject: [PATCH] Expand max local variable width to 257
Code generated by one of the C compilers sets up the stack frame and
then maps the direct page on top of it. If the value at the top of
the stack is 16 bits, it will be referenced via address $ff. The
local variable editor was regarding this as illegal, because lvars are
currently only defined for direct page data, and the value doesn't
entirely fit there (unless you're doing an indirect JMP on an NMOS
6502, in which case it wraps around to $00... but let's ignore that).
The actual max width of a local variable is 257 because of the
possibility of a 16-bit access at $ff.
Older versions of SourceGen don't seem to have an issue when they
encounter this situation, as worrying about (start+width) is really
just an editor affectation. The access itself is still a direct-page
operation. You won't be able to edit the entry without reducing the
length, but otherwise everything works. I don't think there's a need
to bump the file version.
---
SourceGen/RuntimeData/Help/editors.html | 4 ++--
.../SGTestData/20152-local-variables.dis65 | 2 +-
SourceGen/WpfGui/EditDefSymbol.xaml | 2 +-
SourceGen/WpfGui/EditDefSymbol.xaml.cs | 18 ++++++++++++------
4 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/SourceGen/RuntimeData/Help/editors.html b/SourceGen/RuntimeData/Help/editors.html
index c9ae7fc..9c86ed3 100644
--- a/SourceGen/RuntimeData/Help/editors.html
+++ b/SourceGen/RuntimeData/Help/editors.html
@@ -397,8 +397,8 @@ delete the table, click the "Delete Table" button.
variable has a name, a value, a width, and an optional comment. The
standard naming rules for symbols apply. Variables are only used for
zero-page and stack-relative operands, so all values must fall in the
-range 0-255, with their width factored in. So the maximum address for
-a two-byte pointer is $fe.
+range 0-255. The width may extend one byte past the end (to address $0100)
+to allow 16-bit accesses to $ff (particularly useful on 65816).
You can move a table to any offset that is the start of an instruction
and doesn't already have a local variable table present. Click the
"Move Table" button and enter the new offset in hex. You can also click
diff --git a/SourceGen/SGTestData/20152-local-variables.dis65 b/SourceGen/SGTestData/20152-local-variables.dis65
index 5a2a349..40c812b 100644
--- a/SourceGen/SGTestData/20152-local-variables.dis65
+++ b/SourceGen/SGTestData/20152-local-variables.dis65
@@ -817,7 +817,7 @@
{
"DataDescriptor":{
-"Length":3,
+"Length":4,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null},
diff --git a/SourceGen/WpfGui/EditDefSymbol.xaml b/SourceGen/WpfGui/EditDefSymbol.xaml
index 1d2cdc0..b3ccfdc 100644
--- a/SourceGen/WpfGui/EditDefSymbol.xaml
+++ b/SourceGen/WpfGui/EditDefSymbol.xaml
@@ -75,7 +75,7 @@ limitations under the License.
-
diff --git a/SourceGen/WpfGui/EditDefSymbol.xaml.cs b/SourceGen/WpfGui/EditDefSymbol.xaml.cs
index 9ab5e37..9bc21fb 100644
--- a/SourceGen/WpfGui/EditDefSymbol.xaml.cs
+++ b/SourceGen/WpfGui/EditDefSymbol.xaml.cs
@@ -29,6 +29,9 @@ namespace SourceGen.WpfGui {
/// Symbol edit dialog.
///
public partial class EditDefSymbol : Window, INotifyPropertyChanged {
+ // 256-byte zero page, +1 for 16-bit access at $ff.
+ private const int MAX_VAR_WIDTH = 257;
+
///
/// Result; will be set non-null on OK.
///
@@ -200,7 +203,7 @@ namespace SourceGen.WpfGui {
int maxWidth;
if (isVariable) {
ConstantLabel = (string)FindResource("str_VariableConstant");
- maxWidth = 256;
+ maxWidth = MAX_VAR_WIDTH;
} else {
ConstantLabel = (string)FindResource("str_ProjectConstant");
maxWidth = 65536;
@@ -309,17 +312,20 @@ namespace SourceGen.WpfGui {
widthValid = mIsWidthOptional;
} else if (!Asm65.Number.TryParseInt(VarWidth, out thisWidth, out int unusedBase) ||
thisWidth < DefSymbol.MIN_WIDTH || thisWidth > DefSymbol.MAX_WIDTH ||
- (IsVariable && thisWidth > 256)) {
+ (IsVariable && thisWidth > MAX_VAR_WIDTH)) {
// All widths must be between 1 and 65536. For a variable, the full thing must
- // fit on zero page without wrapping. We test for 256 here so that we highlight
- // the "bad width" label, rather than the "it doesn't fit on the page" label.
+ // fit on zero page, except on 65816 where a 16-bit access at $ff can extend
+ // off the end of the direct page.
+ //
+ // We test the variable width here so that we highlight the "width limit" label,
+ // rather than the "value range" label.
widthValid = false;
}
bool valueRangeValid = true;
if (IsVariable && valueValid && widthValid) {
- // $ff with width 1 is okay, $ff with width 2 is not
- if (thisValue < 0 || thisValue + thisWidth > 256) {
+ // $ff with width 1 is okay, $ff with width 2 is okay on 65816, width=3 is bad
+ if (thisValue < 0 || thisValue + thisWidth > MAX_VAR_WIDTH) {
valueRangeValid = false;
}
} else if (IsAddress && valueValid) {