diff --git a/SourceGen/AsmGen/AsmAcme.cs b/SourceGen/AsmGen/AsmAcme.cs
index 9a5e2b0..d6f0f3a 100644
--- a/SourceGen/AsmGen/AsmAcme.cs
+++ b/SourceGen/AsmGen/AsmAcme.cs
@@ -320,6 +320,12 @@ namespace SourceGen.AsmGen {
return string.Empty; // indicate original is fine
}
+ // IGenerator
+ public FormatDescriptor ModifyInstructionOperandFormat(int offset, FormatDescriptor dfd,
+ int operand) {
+ return dfd;
+ }
+
// IGenerator
public void UpdateCharacterEncoding(FormatDescriptor dfd) { }
diff --git a/SourceGen/AsmGen/AsmCc65.cs b/SourceGen/AsmGen/AsmCc65.cs
index e94a037..b6ebc06 100644
--- a/SourceGen/AsmGen/AsmCc65.cs
+++ b/SourceGen/AsmGen/AsmCc65.cs
@@ -217,6 +217,7 @@ namespace SourceGen.AsmGen {
mLocalizer = new LabelLocalizer(Project);
if (!Settings.GetBool(AppSettings.SRCGEN_DISABLE_LABEL_LOCALIZATION, false)) {
mLocalizer.LocalPrefix = "@";
+ mLocalizer.QuirkVariablesEndScope = true;
mLocalizer.Analyze();
}
@@ -346,6 +347,12 @@ namespace SourceGen.AsmGen {
}
}
+ // IGenerator
+ public FormatDescriptor ModifyInstructionOperandFormat(int offset, FormatDescriptor dfd,
+ int operand) {
+ return dfd;
+ }
+
// IGenerator
public void UpdateCharacterEncoding(FormatDescriptor dfd) { }
diff --git a/SourceGen/AsmGen/AsmMerlin32.cs b/SourceGen/AsmGen/AsmMerlin32.cs
index 54c8ce7..d344076 100644
--- a/SourceGen/AsmGen/AsmMerlin32.cs
+++ b/SourceGen/AsmGen/AsmMerlin32.cs
@@ -367,6 +367,19 @@ namespace SourceGen.AsmGen {
return string.Empty;
}
+ // IGenerator
+ public FormatDescriptor ModifyInstructionOperandFormat(int offset, FormatDescriptor dfd,
+ int operand) {
+ if (dfd.FormatType == FormatDescriptor.Type.NumericLE && dfd.IsStringOrCharacter &&
+ (operand & 0x7f) == (byte)',') {
+ // Merlin throws an error on comma operands, e.g. LDA #','
+ dfd = FormatDescriptor.Create(dfd.Length,
+ FormatDescriptor.Type.NumericLE, FormatDescriptor.SubType.None);
+ }
+
+ return dfd;
+ }
+
// IGenerator
public void UpdateCharacterEncoding(FormatDescriptor dfd) { }
diff --git a/SourceGen/AsmGen/AsmTass64.cs b/SourceGen/AsmGen/AsmTass64.cs
index fd7e8c9..186e50c 100644
--- a/SourceGen/AsmGen/AsmTass64.cs
+++ b/SourceGen/AsmGen/AsmTass64.cs
@@ -341,6 +341,12 @@ namespace SourceGen.AsmGen {
return string.Empty; // indicate original is fine
}
+ // IGenerator
+ public FormatDescriptor ModifyInstructionOperandFormat(int offset, FormatDescriptor dfd,
+ int operand) {
+ return dfd;
+ }
+
// IGenerator
public void UpdateCharacterEncoding(FormatDescriptor dfd) {
CharEncoding.Encoding newEnc = PseudoOp.SubTypeToEnc(dfd.FormatSubType);
diff --git a/SourceGen/AsmGen/GenCommon.cs b/SourceGen/AsmGen/GenCommon.cs
index 25f7f0f..4d60800 100644
--- a/SourceGen/AsmGen/GenCommon.cs
+++ b/SourceGen/AsmGen/GenCommon.cs
@@ -230,14 +230,17 @@ namespace SourceGen.AsmGen {
// Check Length to watch for bogus descriptors. (ApplyFormatDescriptors() should
// now be screening bad descriptors out, so we may not need the Length test.)
if (attr.DataDescriptor != null && attr.Length == attr.DataDescriptor.Length) {
+ FormatDescriptor dfd = gen.ModifyInstructionOperandFormat(offset,
+ attr.DataDescriptor, operand);
+
// Format operand as directed.
if (op.AddrMode == OpDef.AddressMode.BlockMove) {
// Special handling for the double-operand block move.
string opstr1 = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
- gen.Localizer.LabelMap, attr.DataDescriptor, operand >> 8, 1,
+ gen.Localizer.LabelMap, dfd, operand >> 8, 1,
PseudoOp.FormatNumericOpFlags.None);
string opstr2 = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
- gen.Localizer.LabelMap, attr.DataDescriptor, operand & 0xff, 1,
+ gen.Localizer.LabelMap, dfd, operand & 0xff, 1,
PseudoOp.FormatNumericOpFlags.None);
if (gen.Quirks.BlockMoveArgsReversed) {
string tmp = opstr1;
@@ -248,10 +251,10 @@ namespace SourceGen.AsmGen {
formattedOperand = hash + opstr1 + "," + hash + opstr2;
} else {
if (attr.DataDescriptor.IsStringOrCharacter) {
- gen.UpdateCharacterEncoding(attr.DataDescriptor);
+ gen.UpdateCharacterEncoding(dfd);
}
formattedOperand = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
- lvLookup, gen.Localizer.LabelMap, attr.DataDescriptor,
+ lvLookup, gen.Localizer.LabelMap, dfd,
offset, operandForSymbol, operandLen, opFlags);
}
} else {
diff --git a/SourceGen/AsmGen/IGenerator.cs b/SourceGen/AsmGen/IGenerator.cs
index 427adde..3bc3f44 100644
--- a/SourceGen/AsmGen/IGenerator.cs
+++ b/SourceGen/AsmGen/IGenerator.cs
@@ -95,6 +95,19 @@ namespace SourceGen.AsmGen {
/// null if the op is unsupported or broken and should be emitted as hex.
string ModifyOpcode(int offset, OpDef op);
+ ///
=
and
+ .set
) ends local label scope, so the label localizer
+ has to take variable assignment into account.LDA #','
)
+ cause an error.STX $00,X
vs.
STX $0000,X
). This isn't a problem with project/platform
diff --git a/SourceGen/SGTestData/2019-local-variables b/SourceGen/SGTestData/2019-local-variables
index 716a16a..2e00938 100644
Binary files a/SourceGen/SGTestData/2019-local-variables and b/SourceGen/SGTestData/2019-local-variables differ
diff --git a/SourceGen/SGTestData/2019-local-variables.dis65 b/SourceGen/SGTestData/2019-local-variables.dis65
index ba3f3cd..c6fe823 100644
--- a/SourceGen/SGTestData/2019-local-variables.dis65
+++ b/SourceGen/SGTestData/2019-local-variables.dis65
@@ -1,9 +1,13 @@
### 6502bench SourceGen dis65 v1.0 ###
{
-"_ContentVersion":2,"FileDataLength":137,"FileDataCrc32":708791740,"ProjectProps":{
+"_ContentVersion":2,"FileDataLength":151,"FileDataCrc32":-814797830,"ProjectProps":{
"CpuName":"65816","IncludeUndocumentedInstr":false,"EntryFlags":32702671,"AutoLabelStyle":"Simple","AnalysisParams":{
"AnalyzeUncategorizedData":true,"DefaultTextScanMode":"LowHighAscii","MinCharsForString":4,"SeekNearbyTargets":false,"SmartPlpHandling":false},
"PlatformSymbolFileIdentifiers":[],"ExtensionScriptFileIdentifiers":[],"ProjectSyms":{
+"__ENABLE_LABEL_LOCALIZATION":{
+"DataDescriptor":{
+"Length":1,"Format":"NumericLE","SubFormat":"Decimal","SymbolRef":null},
+"Comment":"","Label":"__ENABLE_LABEL_LOCALIZATION","Value":1,"Source":"Project","Type":"Constant"},
"CONST_ONE":{
"DataDescriptor":{
"Length":1,"Format":"NumericLE","SubFormat":"Hex","SymbolRef":null},
@@ -44,7 +48,11 @@
"87":{
"Label":"PTR_1","Value":4183,"Source":"User","Type":"LocalOrGlobalAddr"},
"126":{
-"Label":"DPCODE","Value":128,"Source":"User","Type":"LocalOrGlobalAddr"}},
+"Label":"DPCODE","Value":128,"Source":"User","Type":"LocalOrGlobalAddr"},
+"136":{
+"Label":"SPLIT1","Value":138,"Source":"User","Type":"LocalOrGlobalAddr"},
+"143":{
+"Label":"SPLIT2","Value":145,"Source":"User","Type":"LocalOrGlobalAddr"}},
"OperandFormats":{
"8":{
"Length":2,"Format":"NumericLE","SubFormat":"Symbol","SymbolRef":{
@@ -52,7 +60,11 @@
"24":{
"Length":2,"Format":"NumericLE","SubFormat":"Decimal","SymbolRef":null},
"26":{
-"Length":2,"Format":"NumericLE","SubFormat":"Decimal","SymbolRef":null}},
+"Length":2,"Format":"NumericLE","SubFormat":"Decimal","SymbolRef":null},
+"136":{
+"Length":2,"Format":"NumericLE","SubFormat":"Ascii","SymbolRef":null},
+"143":{
+"Length":2,"Format":"NumericLE","SubFormat":"Ascii","SymbolRef":null}},
"LvTables":{
"12":{
"Variables":[{
@@ -180,4 +192,16 @@
"Variables":[{
"DataDescriptor":{
"Length":1,"Format":"NumericLE","SubFormat":"Hex","SymbolRef":null},
-"Comment":"same as org","Label":"DPNOP","Value":128,"Source":"Variable","Type":"ExternalAddr"}],"ClearPrevious":false}}}
+"Comment":"same as org","Label":"DPNOP","Value":128,"Source":"Variable","Type":"ExternalAddr"}],"ClearPrevious":false},
+"138":{
+"Variables":[{
+"DataDescriptor":{
+"Length":1,"Format":"NumericLE","SubFormat":"Hex","SymbolRef":null},
+"Comment":"","Label":"SPLITTER","Value":128,"Source":"Variable","Type":"ExternalAddr"}],"ClearPrevious":false},
+"139":{
+"Variables":[{
+"DataDescriptor":{
+"Length":1,"Format":"NumericLE","SubFormat":"Hex","SymbolRef":null},
+"Comment":"","Label":"FOO","Value":128,"Source":"Variable","Type":"ExternalAddr"}],"ClearPrevious":false},
+"145":{
+"Variables":[],"ClearPrevious":false}}}
diff --git a/SourceGen/SGTestData/Expected/2019-local-variables_64tass.S b/SourceGen/SGTestData/Expected/2019-local-variables_64tass.S
index ae249e5..c1bdc50 100644
--- a/SourceGen/SGTestData/Expected/2019-local-variables_64tass.S
+++ b/SourceGen/SGTestData/Expected/2019-local-variables_64tass.S
@@ -1,5 +1,7 @@
;Edited to have duplicate labels (PROJ_ZERO, DPCODE).
.cpu "65816"
+ .enc sg_ascii
+ .cdef $20,$7e,$20
PROJ_ZERO = $00 ;project addr
PROJ_ONE = $01 ;project addr
CONST_ZERO = $f0 ;project const
@@ -66,7 +68,7 @@ PTR .var $22 ;#2
ldx PTR
PTR .var $24 ;#3
ldx PTR
-PTR_1 nop
+_PTR_1 nop
PTR_A .var $20
ldy PTR_A
PTR_B .var $1f
@@ -104,6 +106,13 @@ DPCODE nop
lda DPCODE
lda @wDPCODE
lda @lDPCODE
+_SPLIT1 lda #','
+SPLITTER .var $80
+ ldx $1234
+ beq _SPLIT1
+_SPLIT2 lda ','
+ ldx $5678
+ beq _SPLIT2
rts
.here
diff --git a/SourceGen/SGTestData/Expected/2019-local-variables_Merlin32.S b/SourceGen/SGTestData/Expected/2019-local-variables_Merlin32.S
index 9a21569..30a0802 100644
--- a/SourceGen/SGTestData/Expected/2019-local-variables_Merlin32.S
+++ b/SourceGen/SGTestData/Expected/2019-local-variables_Merlin32.S
@@ -63,7 +63,7 @@ L103C lda #$fe
ldx ]PTR
]PTR equ $24 ;#3
ldx ]PTR
-PTR_1 nop
+:PTR_1 nop
]PTR_A equ $20
ldy ]PTR_A
]PTR_B equ $1f
@@ -101,5 +101,12 @@ DPCODE nop
lda DPCODE
lda: DPCODE
ldal DPCODE
+:SPLIT1 lda #$2c
+]SPLITTER equ $80
+ ldx $1234
+ beq :SPLIT1
+:SPLIT2 lda $2c
+ ldx $5678
+ beq :SPLIT2
rts
diff --git a/SourceGen/SGTestData/Expected/2019-local-variables_acme.S b/SourceGen/SGTestData/Expected/2019-local-variables_acme.S
index 86746b4..4676037 100644
--- a/SourceGen/SGTestData/Expected/2019-local-variables_acme.S
+++ b/SourceGen/SGTestData/Expected/2019-local-variables_acme.S
@@ -99,7 +99,7 @@ L103C lda #$fe
.CONST0 = $10
.PTR = $24 ;#3
ldx .PTR
-PTR_1 nop
+@PTR_1 nop
!zone Z000058
.NH0 = $00 ;not hidden
.NH1 = $01 ;not hidden
@@ -191,6 +191,36 @@ DPCODE nop
lda+1 DPCODE
lda+2 DPCODE
lda+3 DPCODE
+@SPLIT1 lda #','
+ !zone Z00008a
+.NH0 = $00 ;not hidden
+.NH1 = $01 ;not hidden
+.PTR0 = $10
+.CONST0 = $10
+.PTR_C = $1d
+.PTR_D = $21
+.PTR = $24 ;#3
+.VAL0 = $30
+.VAL14 = $31
+.VAL5 = $35
+.SPLITTER = $80
+ ldx $1234
+ beq @SPLIT1
+@SPLIT2 lda ','
+ !zone Z000091
+.NH0 = $00 ;not hidden
+.NH1 = $01 ;not hidden
+.PTR0 = $10
+.CONST0 = $10
+.PTR_C = $1d
+.PTR_D = $21
+.PTR = $24 ;#3
+.VAL0 = $30
+.VAL14 = $31
+.VAL5 = $35
+.SPLITTER = $80
+ ldx $5678
+ beq @SPLIT2
rts
} ;!pseudopc
diff --git a/SourceGen/SGTestData/Expected/2019-local-variables_cc65.S b/SourceGen/SGTestData/Expected/2019-local-variables_cc65.S
index 92f34eb..5081c35 100644
--- a/SourceGen/SGTestData/Expected/2019-local-variables_cc65.S
+++ b/SourceGen/SGTestData/Expected/2019-local-variables_cc65.S
@@ -106,5 +106,12 @@ DPCODE: nop
lda DPCODE
lda a:DPCODE
lda f:DPCODE
+SPLIT1: lda #','
+SPLITTER .set $80
+ ldx $1234
+ beq SPLIT1
+@SPLIT2: lda ','
+ ldx $5678
+ beq @SPLIT2
rts
diff --git a/SourceGen/SGTestData/Expected/2019-local-variables_cc65.cfg b/SourceGen/SGTestData/Expected/2019-local-variables_cc65.cfg
index a1b5f7c..f691a70 100644
--- a/SourceGen/SGTestData/Expected/2019-local-variables_cc65.cfg
+++ b/SourceGen/SGTestData/Expected/2019-local-variables_cc65.cfg
@@ -2,7 +2,7 @@
MEMORY {
MAIN: file=%O, start=%S, size=65536;
# MEM000: file=%O, start=$1000, size=126;
-# MEM001: file=%O, start=$0080, size=11;
+# MEM001: file=%O, start=$0080, size=25;
}
SEGMENTS {
CODE: load=MAIN, type=rw;
diff --git a/SourceGen/SGTestData/Source/2019-local-variables.S b/SourceGen/SGTestData/Source/2019-local-variables.S
index 9872326..db1922b 100644
--- a/SourceGen/SGTestData/Source/2019-local-variables.S
+++ b/SourceGen/SGTestData/Source/2019-local-variables.S
@@ -3,6 +3,8 @@
;
; Assembler: Merlin 32
+; EDIT: add __ENABLE_LABEL_LOCALIZATION to project symbols
+
org $1000
; Define these as project symbols.
@@ -145,4 +147,13 @@ DPCODE nop
lda DPCODE ;should be DPNOP
lda |DPCODE ;should be DPCODE
lda >DPCODE ;should be DPCODE
+
+; Local label test. ca65 v2.18 erases cheap local label scope when it
+; encounters a constant or .set.
+LOCAL1 lda #$2c ;EDIT: format as ASCII
+ ldx $1234 ;put variable table here with one arbitrary entry
+ beq LOCAL1
+LOCAL2 lda $2c ;EDIT: format as ASCII
+ ldx $5678 ;put empty variable table here
+ beq LOCAL2
rts