1
0
mirror of https://github.com/fadden/6502bench.git synced 2025-08-05 09:25:39 +00:00

Tweak instruction operand edit

The code that allowed easy editing of project symbol operands wasn't
handling overlapping multi-byte regions correctly.

This adds a new section to the 20200-ui-edge-cases test case that has
instructions with various kinds of address operands.
This commit is contained in:
Andy McFadden
2025-06-15 15:07:02 -07:00
parent bde4f2ed07
commit 898307eb73
9 changed files with 675 additions and 45 deletions

View File

@@ -43,7 +43,7 @@ RDPAGE2 @ $C01C ;R bit 7: using page 2?
RDHIRES @ $C01D ;R bit 7: using hi-res graphics?
ALTCHARSET @ $C01E ;R bit 7: using alt char set?
RD80VID @ $C01F ;R bit 7: using 80 columns?
TAPEOUT @ $C020 ;RW toggle caseette tape output
TAPEOUT @ $C020 ;RW toggle cassette tape output
MONOCOLOR @ $C021 ;W color/mono
TBCOLOR @ $C022 ;RW screen color (low is BG, high is FG)
VGCINT @ $C023 ;R VGC interrupts

View File

@@ -1,8 +1,8 @@
### 6502bench SourceGen dis65 v1.0 ###
{
"_ContentVersion":3,
"FileDataLength":50,
"FileDataCrc32":-1443914879,
"_ContentVersion":6,
"FileDataLength":183,
"FileDataCrc32":-593505978,
"ProjectProps":{
"CpuName":"6502",
"IncludeUndocumentedInstr":false,
@@ -13,27 +13,130 @@
"AnalyzeUncategorizedData":true,
"DefaultTextScanMode":"LowHighAscii",
"MinCharsForString":4,
"SeekNearbyTargets":true,
"SmartPlpHandling":true},
"SeekNearbyTargets":false,
"UseRelocData":false,
"SmartPlpHandling":false,
"SmartPlbHandling":true},
"PlatformSymbolFileIdentifiers":["RT:Apple/F8-ROM.sym65",
"RT:Apple/Cxxx-IO.sym65",
"RT:Apple/DOS33.sym65"],
"ExtensionScriptFileIdentifiers":["RT:Apple/VisHiRes.cs"],
"PlatformSymbolFileIdentifiers":["RT:TestData/TestSyms.sym65"],
"ExtensionScriptFileIdentifiers":[],
"ProjectSyms":{
}},
"FOO":{
"DataDescriptor":{
"Length":16,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null,
"Extra":null},
"Comment":"",
"HasWidth":true,
"Direction":"ReadWrite",
"MultiMask":null,
"Label":"FOO",
"Value":61440,
"Source":"Project",
"Type":"ExternalAddr",
"LabelAnno":"None"},
"FOO_5":{
"DataDescriptor":{
"Length":1,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null,
"Extra":null},
"Comment":"",
"HasWidth":false,
"Direction":"ReadWrite",
"MultiMask":null,
"Label":"FOO_5",
"Value":61445,
"Source":"Project",
"Type":"ExternalAddr",
"LabelAnno":"None"},
"FOOZP":{
"DataDescriptor":{
"Length":8,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null,
"Extra":null},
"Comment":"",
"HasWidth":true,
"Direction":"ReadWrite",
"MultiMask":null,
"Label":"FOOZP",
"Value":240,
"Source":"Project",
"Type":"ExternalAddr",
"LabelAnno":"None"},
"OVERL":{
"DataDescriptor":{
"Length":1,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null,
"Extra":null},
"Comment":"",
"HasWidth":false,
"Direction":"ReadWrite",
"MultiMask":null,
"Label":"OVERL",
"Value":12288,
"Source":"Project",
"Type":"ExternalAddr",
"LabelAnno":"None"}}},
"AddressMap":[{
"Offset":0,
"Addr":8192},
"Addr":8192,
"Length":16,
"PreLabel":"",
"DisallowInward":false,
"DisallowOutward":false,
"IsRelative":false},
{
"Offset":10,
"Addr":8202},
"Addr":8202,
"Length":6,
"PreLabel":"",
"DisallowInward":false,
"DisallowOutward":false,
"IsRelative":false},
{
"Offset":16,
"Addr":8448}],
"Addr":8448,
"Length":33,
"PreLabel":"",
"DisallowInward":false,
"DisallowOutward":false,
"IsRelative":false},
{
"Offset":49,
"Addr":244,
"Length":4,
"PreLabel":"",
"DisallowInward":false,
"DisallowOutward":false,
"IsRelative":false},
{
"Offset":53,
"Addr":8704,
"Length":130,
"PreLabel":"",
"DisallowInward":false,
"DisallowOutward":false,
"IsRelative":false}],
"TypeHints":[{
"Low":0,
"High":0,
@@ -52,20 +155,243 @@
},
"UserLabels":{
"53":{
"Label":"line1",
"Value":8704,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"67":{
"Label":"line2",
"Value":8718,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"44":{
"Label":"addr1",
"Value":8476,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"110":{
"Label":"next1",
"Value":8761,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"16":{
"Label":"skip",
"Value":8448,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"49":{
"Label":"zf4",
"Value":244,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"182":{
"Label":"done",
"Value":8833,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"157":{
"Label":"bitsy",
"Value":8808,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"}},
"OperandFormats":{
},
"18":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Symbol",
"SymbolRef":{
"Label":"addr1",
"Part":"Low"},
"Extra":null},
"24":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Symbol",
"SymbolRef":{
"Label":"addr1",
"Part":"Low"},
"Extra":null},
"53":{
"Length":14,
"Format":"StringNullTerm",
"SubFormat":"Ascii",
"SymbolRef":null,
"Extra":null},
"67":{
"Length":14,
"Format":"StringNullTerm",
"SubFormat":"Ascii",
"SymbolRef":null,
"Extra":null},
"81":{
"Length":14,
"Format":"StringNullTerm",
"SubFormat":"Ascii",
"SymbolRef":null,
"Extra":null},
"95":{
"Length":14,
"Format":"StringNullTerm",
"SubFormat":"Ascii",
"SymbolRef":null,
"Extra":null},
"137":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Symbol",
"SymbolRef":{
"Label":"line2",
"Part":"Low"},
"Extra":null},
"155":{
"Length":2,
"Format":"NumericLE",
"SubFormat":"Symbol",
"SymbolRef":{
"Label":"bitsy",
"Part":"Low"},
"Extra":null},
"163":{
"Length":2,
"Format":"NumericLE",
"SubFormat":"Address",
"SymbolRef":null,
"Extra":null},
"165":{
"Length":2,
"Format":"NumericLE",
"SubFormat":"Address",
"SymbolRef":null,
"Extra":null},
"167":{
"Length":2,
"Format":"NumericLE",
"SubFormat":"Address",
"SymbolRef":null,
"Extra":null},
"169":{
"Length":2,
"Format":"NumericLE",
"SubFormat":"Address",
"SymbolRef":null,
"Extra":null},
"171":{
"Length":2,
"Format":"NumericLE",
"SubFormat":"Address",
"SymbolRef":null,
"Extra":null},
"173":{
"Length":2,
"Format":"NumericLE",
"SubFormat":"Address",
"SymbolRef":null,
"Extra":null},
"175":{
"Length":2,
"Format":"NumericLE",
"SubFormat":"Address",
"SymbolRef":null,
"Extra":null},
"177":{
"Length":2,
"Format":"NumericLE",
"SubFormat":"Symbol",
"SymbolRef":{
"Label":"line2",
"Part":"Low"},
"Extra":null},
"179":{
"Length":2,
"Format":"NumericLE",
"SubFormat":"Address",
"SymbolRef":null,
"Extra":null}},
"LvTables":{
},
"110":{
"Variables":[{
"DataDescriptor":{
"Length":2,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null,
"Extra":null},
"Comment":"",
"HasWidth":true,
"Direction":"ReadWrite",
"MultiMask":null,
"Label":"foo_f0",
"Value":240,
"Source":"Variable",
"Type":"ExternalAddr",
"LabelAnno":"None"},
{
"DataDescriptor":{
"Length":2,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null,
"Extra":null},
"Comment":"",
"HasWidth":true,
"Direction":"ReadWrite",
"MultiMask":null,
"Label":"foo_f4",
"Value":244,
"Source":"Variable",
"Type":"ExternalAddr",
"LabelAnno":"None"}],
"ClearPrevious":false}},
"Visualizations":[],
"VisualizationAnimations":[],
"VisualizationSets":{
},
"RelocList":{
},
"DbrValues":{
}}

View File

@@ -1,8 +1,13 @@
.cpu "6502"
.enc "sg_ascii"
.cdef $20,$7e,$20
FOOZP = $f0
OVERL = $3000
FOO = $f000
FOO_5 = $f005
* = $2000
jmp L2100
jmp skip
.text "hello, " ;string should be split by no-op addr change
.logical $200a
@@ -11,15 +16,64 @@
.here
.logical $2100
L2100 lda #$00
skip lda #$00
sta addr1-1 ;edit this operand
sta addr1
sta addr1+1
jmp L2121
jmp next1
.text "testing stuff."
addr1 .text "!?---"
.here
.logical $00f4
zf4 .byte $00
.byte $00
L00F6 .byte $00
.byte $00
.here
.logical $2200
line1 .null "this is line1"
line2 .null "this is line2"
L221C .null "this is line3"
.null "this is line4"
.byte $80
L2121 rts
foo_f0 .var $f0
foo_f4 .var $f4
next1 lda addr1
sta FOO
sta FOO_5
sta FOO+8
ldx OVERL
ldx line1
ldx line2
ldx L221C
ldx L221C+1
ldx line2+35
ldy $00
ldy foo_f0
ldy foo_f0+1
ldy FOOZP+2
ldy zf4
ldy L00F6
lda #$00
nop
bcc bitsy+1
bitsy .byte $2c
lda #$ff
jmp done
.word FOO
.word FOO_5
.word FOO+9
.word OVERL
.word line1
.word line2
.word L221C
.word line2+33
.word zf4
.byte $80
done rts
.here

View File

@@ -1,6 +1,11 @@
!cpu 6502
FOOZP = $f0
OVERL = $3000
FOO = $f000
FOO_5 = $f005
* = $2000
jmp L2100
jmp skip
!text "hello, " ;string should be split by no-op addr change
!pseudopc $200a {
@@ -9,15 +14,65 @@
}
!pseudopc $2100 {
L2100 lda #$00
skip lda #$00
sta addr1-1 ;edit this operand
sta addr1
sta addr1+1
jmp L2121
jmp next1
!text "testing stuff."
addr1 !text "!?---"
}
!pseudopc $00f4 {
zf4 !byte $00
!byte $00
L00F6 !byte $00
!byte $00
}
!pseudopc $2200 {
line1 !text "this is line1",$00
line2 !text "this is line2",$00
L221C !text "this is line3",$00
!text "this is line4",$00
!byte $80
L2121 rts
!zone Z00006e
.foo_f0 = $f0
.foo_f4 = $f4
next1 lda addr1
sta FOO
sta FOO_5
sta FOO+8
ldx OVERL
ldx line1
ldx line2
ldx L221C
ldx L221C+1
ldx line2+35
ldy $00
ldy .foo_f0
ldy .foo_f0+1
ldy FOOZP+2
ldy+1 zf4
ldy+1 L00F6
lda #$00
nop
bcc bitsy+1
bitsy !byte $2c
lda #$ff
jmp done
!word FOO
!word FOO_5
!word FOO+9
!word OVERL
!word line1
!word line2
!word L221C
!word line2+33
!word zf4
!byte $80
done rts
}

View File

@@ -1,6 +1,11 @@
.setcpu "6502"
FOOZP = $f0
OVERL = $3000
FOO = $f000
FOO_5 = $f005
.org $2000
jmp L2100
jmp skip
.byte "hello, " ;string should be split by no-op addr change
.org $200a
@@ -8,14 +13,61 @@
.byte $80
.org $2100
L2100: lda #$00
skip: lda #$00
sta addr1-1 ;edit this operand
sta addr1
sta addr1+1
jmp L2121
jmp next1
.byte "testing stuff."
addr1: .byte "!?---"
.org $00f4
zf4: .byte $00
.byte $00
L00F6: .byte $00
.byte $00
.org $2200
line1: .asciiz "this is line1"
line2: .asciiz "this is line2"
L221C: .asciiz "this is line3"
.asciiz "this is line4"
.byte $80
L2121: rts
foo_f0 .set $f0
foo_f4 .set $f4
next1: lda addr1
sta FOO
sta FOO_5
sta FOO+8
ldx OVERL
ldx line1
ldx line2
ldx L221C
ldx L221C+1
ldx line2+35
ldy $00
ldy foo_f0
ldy foo_f0+1
ldy FOOZP+2
ldy zf4
ldy L00F6
lda #$00
nop
bcc bitsy+1
bitsy: .byte $2c
lda #$ff
jmp done
.word FOO
.word FOO_5
.word FOO+9
.word OVERL
.word line1
.word line2
.word L221C
.word line2+33
.word zf4
.byte $80
done: rts

View File

@@ -1,5 +1,10 @@
FOOZP equ $f0
OVERL equ $3000
FOO equ $f000
FOO_5 equ $f005
org $2000
jmp L2100
jmp skip
asc 'hello, ' ;string should be split by no-op addr change
org $200a
@@ -7,14 +12,61 @@
dfb $80
org $2100
L2100 lda #$00
skip lda #$00
sta addr1-1 ;edit this operand
sta addr1
sta addr1+1
jmp L2121
jmp next1
asc 'testing stuff.'
addr1 asc '!?---'
org $00f4
zf4 dfb $00
dfb $00
L00F6 dfb $00
dfb $00
org $2200
line1 asc 'this is line1',00
line2 asc 'this is line2',00
L221C asc 'this is line3',00
asc 'this is line4',00
dfb $80
L2121 rts
]foo_f0 equ $f0
]foo_f4 equ $f4
next1 lda addr1
sta FOO
sta FOO_5
sta FOO+8
ldx OVERL
ldx line1
ldx line2
ldx L221C
ldx L221C+1
ldx line2+35
ldy $00
ldy ]foo_f0
ldy ]foo_f0+1
ldy FOOZP+2
ldy zf4
ldy L00F6
lda #$00
nop
bcc bitsy+1
bitsy dfb $2c
lda #$ff
jmp done
dw FOO
dw FOO_5
dw FOO+9
dw OVERL
dw line1
dw line2
dw L221C
dw line2+33
dw zf4
dfb $80
done rts

View File

@@ -6,6 +6,8 @@
;
; Assembler: Merlin 32
; EDIT: disable "find nearby targets"
ORG $2000
jmp skip
@@ -18,16 +20,80 @@
org $2100 ;EDIT: add this
skip
lda #$00
sta addr0 ;TEST: edit this operand ("addr1-1")
sta addr0 ;EDIT: set label to "addr1"
sta addr1
sta addr2
jmp done
sta addr2 ;EDIT: set label to "addr1"
jmp next1
L1 asc 'testing stuff'
asc 'testing stuff'
addr0 asc '.'
addr1 asc '!' ;EDIT: place label here
addr1 asc '!' ;EDIT: set label "addr1"
addr2 asc '?'
asc '---'
; Exercise the various paths for "edit operand target label".
; EDIT: add a project symbol FOO, value $F000, width 16
; EDIT: add a project symbol FOO_5, value $F005 (overlaps w/FOO)
; EDIT: add a project symbol FOOZP, value $F0, width 8
; EDIT: add a project symbol OVERL, value $3000 (overlaps w/platform)
; and add TestData/TestSyms.sym65 from runtime
FOO equ $f000
FOO_5 equ $f005
FOOZP equ $f0
OVERL equ $3000
; Define a slice of zero page inside the program.
org $f4 ;EDIT: add this
zf4 ds 4 ;EDIT: add label "zf4"
org $2200 ;EDIT: add this
; EDIT: format block as zero-terminated strings
line1 asc 'this is line1',00 ;EDIT: label "line1"
line2 asc 'this is line2',00 ;EDIT: label "line2"
line3 asc 'this is line3',00 ;do not label (should get auto-label)
line4 asc 'this is line4',00 ;do not label (should not get autoed)
dfb $80
next1
lda addr1 ;internal addr
sta FOO ;external addr
sta FOO_5 ;external addr (overlaps w/FOO)
sta FOO+8 ;external addr (range)
ldx OVERL ;external addr, plat and proj
ldx line1 ;internal addr
ldx line2 ;internal addr
ldx line3 ;internal addr with offset, line start
ldx line3+1 ;internal addr with offset, inside line
ldx line4+7 ;EDIT: set operand symbol "line2"
; EDIT: add local variable entry "foo_f0", value $f0, width 2
; EDIT: add local variable entry "foo_f4", value $f4, width 2
ldy $00 ;no match
ldy FOOZP ;can be either LVT or project
ldy FOOZP+1 ;can be either LVT or project
ldy FOOZP+2 ;can only be project
ldy FOOZP+4 ;can be either LVT or internal
ldy FOOZP+6 ;can be project or internal
lda #$00
nop
bcc bitsy+1 ;EDIT: set symbol "bitsy"
bitsy bit $ffa9 ;EDIT: set label "bitsy" on BIT instruction
jmp done
; EDIT: format as 16-bit addresses
dw FOO
dw FOO_5
dw FOO+9
dw OVERL
dw line1
dw line2
dw line3
dw line4+5 ;EDIT: set operand symbol "line2"
dw zf4
dfb $80
done rts

View File

@@ -946,17 +946,41 @@ namespace SourceGen.WpfGui {
} else if (attr.OperandAddress >= 0) {
ShowNarExternalSymbol = true;
// There can be multiple symbols with the same value, so we walk through the
// There can be multiple symbols with the same address, so we walk through the
// list and identify the first matching platform and project symbols. We're
// only interested in address symbols, not constants.
// only interested in address symbols, not constants. Identifying both project
// and platform can be helpful for the user who might be wondering why the platform
// symbol isn't appearing.
Symbol firstPlatform = null;
Symbol firstProject = null;
// Start by doing a symbol table lookup, which will give us the correct answer
// when there are overlapping multi-byte values and masks.
Symbol lsym = mProject.SymbolTable.FindNonVariableByAddress(attr.OperandAddress,
OpDef.MemoryEffect.ReadModifyWrite); // just guess at the mem effect
if (lsym == null) {
// Nothing currently defined.
} else if (lsym.SymbolSource == Symbol.Source.Platform) {
firstPlatform = lsym;
} else if (lsym.SymbolSource == Symbol.Source.Project) {
firstProject = lsym;
} else {
Debug.Assert(false, "was expecting project or platform for external addr");
}
// Now walk the table to find whichever we didn't find earlier. Project symbols
// have priority on overlaps, so we should just be looking for platform syms here.
foreach (Symbol sym in mProject.SymbolTable) {
if (sym.Value == attr.OperandAddress && !sym.IsConstant) {
if (sym.IsConstant || !(sym is DefSymbol)) {
continue;
}
int width = ((DefSymbol)sym).DataDescriptor.Length;
if (attr.OperandAddress >= sym.Value &&
attr.OperandAddress < sym.Value + width) {
if (firstPlatform == null && sym.SymbolSource == Symbol.Source.Platform) {
firstPlatform = sym;
} else if (firstProject == null &&
sym.SymbolSource == Symbol.Source.Project) {
sym.SymbolSource == Symbol.Source.Project) {
firstProject = sym;
}
@@ -1147,14 +1171,15 @@ namespace SourceGen.WpfGui {
/// Configures the UI in the Local Variable box at load time.
/// </summary>
private void LocalVariables_Loaded() {
if (!mOpDef.IsDirectPageInstruction && !mOpDef.IsStackRelInstruction) {
if (mOpDef.IsDirectPageInstruction) {
LvMatchFoundText = LV_MATCH_FOUND_ADDRESS;
} else if (mOpDef.IsStackRelInstruction) {
LvMatchFoundText = LV_MATCH_FOUND_CONSTANT;
} else {
ShowLvNotApplicable = true;
return;
}
LvMatchFoundText = mOpDef.IsDirectPageInstruction ?
LV_MATCH_FOUND_ADDRESS : LV_MATCH_FOUND_CONSTANT;
LocalVariableLookup lvLookup =
new LocalVariableLookup(mProject.LvTables, mProject, null, false, false);