1
0
mirror of https://github.com/fadden/6502bench.git synced 2025-02-07 14:31:00 +00:00

Address region isolation, part 3 (of 3)

If an address resolves to a user label in an isolated region, we
don't want to use it.  However, we still want to try to match it
to a project/platform symbol.

For example, suppose the isolated code wants to reference address
$1C00, which is a memory-mapped I/O location in one area, but a
regular bunch of code in the other.  We don't want it to map to
the regular code, but we do want it to resolve to our table of
platform I/O addresses.

We now handle this correctly.  The regression test has been updated
to check this.  The current implementation does a linear scan through
the symbol table, but I'm hoping this is not a common situation.

The reference manual has been updated to describe the new feature.
This commit is contained in:
Andy McFadden 2024-05-21 14:14:32 -07:00
parent e137db2b5c
commit 7a7ff44d3a
13 changed files with 376 additions and 101 deletions

View File

@ -1445,12 +1445,12 @@ namespace SourceGen {
// //
// It might seem unwise to examine the full symbol table, because it has // It might seem unwise to examine the full symbol table, because it has
// non-project non-platform symbols in it. However, any matching user // non-project non-platform symbols in it. However, any matching user
// labels would have been applied already. Also, we want to ensure that // labels would have been applied already (unless blocked by address region
// conflicting user labels take precedence, e.g. creating a user label "COUT" // isolation). Also, we want to ensure that conflicting user labels take
// will prevent a platform symbol with the same name from being visible. // precedence, e.g. creating a user label "COUT" will prevent a platform
// Using the full symbol table is potentially a tad less efficient than // symbol with the same name from being visible. Using the full symbol
// looking for a match exclusively in project/platform symbols, but it's // table is potentially a tad less efficient than looking for a match
// the correct thing to do. // exclusively in project/platform symbols, but it's the correct thing to do.
OpDef op = CpuDef.GetOpDef(FileData[offset]); OpDef op = CpuDef.GetOpDef(FileData[offset]);
accType = op.MemEffect; accType = op.MemEffect;
address = attr.OperandAddress; address = attr.OperandAddress;
@ -1508,7 +1508,11 @@ namespace SourceGen {
} else { } else {
Debug.WriteLine("GeneratePlatform not applying at +" + Debug.WriteLine("GeneratePlatform not applying at +" +
offset.ToString("x6") + ": " + sym); offset.ToString("x6") + ": " + sym);
sym = null; // Do a secondary scan, looking only at project/platform/pre-labels.
sym = SymbolTable.FindProjPlatPreByAddress(address, accType);
if (sym != null) {
Debug.WriteLine(" ...found matching proj/plat: " + sym);
}
} }
} }

View File

@ -2,7 +2,7 @@
{ {
"_ContentVersion":6, "_ContentVersion":6,
"FileDataLength":1537, "FileDataLength":1537,
"FileDataCrc32":950074699, "FileDataCrc32":-1543685807,
"ProjectProps":{ "ProjectProps":{
"CpuName":"6502", "CpuName":"6502",
"IncludeUndocumentedInstr":false, "IncludeUndocumentedInstr":false,
@ -21,7 +21,90 @@
"PlatformSymbolFileIdentifiers":[], "PlatformSymbolFileIdentifiers":[],
"ExtensionScriptFileIdentifiers":[], "ExtensionScriptFileIdentifiers":[],
"ProjectSyms":{ "ProjectSyms":{
}}, "IN_1":{
"DataDescriptor":{
"Length":256,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null},
"Comment":"",
"HasWidth":true,
"Direction":"ReadWrite",
"MultiMask":null,
"Label":"IN_1",
"Value":36864,
"Source":"Project",
"Type":"ExternalAddr",
"LabelAnno":"None"},
"IN_2":{
"DataDescriptor":{
"Length":256,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null},
"Comment":"",
"HasWidth":true,
"Direction":"ReadWrite",
"MultiMask":null,
"Label":"IN_2",
"Value":40960,
"Source":"Project",
"Type":"ExternalAddr",
"LabelAnno":"None"},
"IN_3":{
"DataDescriptor":{
"Length":256,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null},
"Comment":"",
"HasWidth":true,
"Direction":"ReadWrite",
"MultiMask":null,
"Label":"IN_3",
"Value":45056,
"Source":"Project",
"Type":"ExternalAddr",
"LabelAnno":"None"},
"IN_4":{
"DataDescriptor":{
"Length":256,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null},
"Comment":"",
"HasWidth":true,
"Direction":"ReadWrite",
"MultiMask":null,
"Label":"IN_4",
"Value":49152,
"Source":"Project",
"Type":"ExternalAddr",
"LabelAnno":"None"},
"THREE_K":{
"DataDescriptor":{
"Length":1,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null},
"Comment":"project symbol test",
"HasWidth":false,
"Direction":"ReadWrite",
"MultiMask":null,
"Label":"THREE_K",
"Value":12288,
"Source":"Project",
"Type":"ExternalAddr",
"LabelAnno":"None"}}},
"AddressMap":[{ "AddressMap":[{
"Offset":0, "Offset":0,
@ -303,6 +386,13 @@
"Value":2072, "Value":2072,
"Source":"User", "Source":"User",
"Type":"GlobalAddr", "Type":"GlobalAddr",
"LabelAnno":"None"},
"1319":{
"Label":"_checkit",
"Value":49166,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"}}, "LabelAnno":"None"}},
"OperandFormats":{ "OperandFormats":{

View File

@ -1,26 +1,32 @@
.cpu "6502" .cpu "6502"
THREE_K = $3000 ;project symbol test
IN_1 = $9000
IN_2 = $a000
IN_3 = $b000
IN_4 = $c000
* = $0800 * = $0800
jsr region1 jsr region1
jsr region2 jsr region2
jsr $3000 jsr THREE_K
jsr $4000 jsr $4000
lda inner1 lda L9005
lda inner2 lda LA008
lda $b000 lda IN_3+11
lda $c000 lda IN_4+14
self .byte $ad,$ea self .byte $ad,$ea
L081A nop L081A nop
jsr altbnk1 jsr altbnk1
jsr altbnk2 jsr altbnk2
jmp done jmp done
altbnk1 bit $c080 altbnk1 bit $ffc0
lda self+1 lda self+1
bne L081A bne L081A
rts rts
.logical *+$0000 .logical *+$0000
altbnk2 bit $c080 altbnk2 bit $ffc0
lda $0819 lda $0819
bne $081a bne $081a
ldx $081b ldx $081b
@ -106,7 +112,7 @@ inner1_pre
.logical $9000 .logical $9000
inner1 ldx inner1 inner1 ldx inner1
ldy #$aa ldy #$aa
ldy finish1 L9005 ldy finish1
ldy finish2 ldy finish2
ldy $302b ldy $302b
ldy $402b ldy $402b
@ -116,12 +122,12 @@ inner1 ldx inner1
finish1 ldy finish1 finish1 ldy finish1
ldx region1 ldx region1
ldx region2 ldx region2
ldx $3000 ldx THREE_K
ldx $4000 ldx $4000
lda inner1 lda inner1
lda inner2 lda inner2
lda $b000 lda IN_3
lda $c000 lda IN_4
pla pla
rts rts
@ -146,7 +152,7 @@ inner2_pre
inner2 ldx inner2 inner2 ldx inner2
ldy #$aa ldy #$aa
ldy $102b ldy $102b
ldy finish2 LA008 ldy finish2
ldy $302b ldy $302b
ldy $402b ldy $402b
rts rts
@ -155,12 +161,16 @@ inner2 ldx inner2
finish2 ldy finish2 finish2 ldy finish2
ldx $1000 ldx $1000
ldx region2 ldx region2
ldx $3000 ldx THREE_K
ldx $4000 ldx $4000
lda IN_1
lda inner2
lda IN_3
lda IN_4
pla pla
rts rts
.fill 196,$00 .fill 184,$00
.here .here
.logical $3000 .logical $3000
@ -192,10 +202,14 @@ finish3 ldy finish3
ldx region2 ldx region2
ldx region3 ldx region3
ldx $4000 ldx $4000
lda inner1
lda inner2
lda inner3
lda IN_4
pla pla
rts rts
.fill 196,$00 .fill 184,$00
.here .here
.logical $4000 .logical $4000
@ -218,19 +232,23 @@ inner4 ldx inner4
ldy $102b ldy $102b
ldy $202b ldy $202b
ldy $302b ldy $302b
ldy finish4 X_checkit ldy finish4
rts rts
.here .here
finish4 ldy finish4 finish4 ldy finish4
ldx $1000 ldx $1000
ldx $2000 ldx $2000
ldx $3000 ldx THREE_K
ldx region4 ldx region4
lda IN_1
lda IN_2
lda IN_3
lda inner4
pla pla
rts rts
.fill 196,$00 .fill 184,$00
.here .here
.logical $0000 .logical $0000
.byte $ff .byte $ff

View File

@ -1,26 +1,32 @@
!cpu 6502 !cpu 6502
THREE_K = $3000 ;project symbol test
IN_1 = $9000
IN_2 = $a000
IN_3 = $b000
IN_4 = $c000
* = $0800 * = $0800
jsr region1 jsr region1
jsr region2 jsr region2
jsr $3000 jsr THREE_K
jsr $4000 jsr $4000
lda inner1 lda L9005
lda inner2 lda LA008
lda $b000 lda IN_3+11
lda $c000 lda IN_4+14
self !byte $ad,$ea self !byte $ad,$ea
L081A nop L081A nop
jsr altbnk1 jsr altbnk1
jsr altbnk2 jsr altbnk2
jmp done jmp done
altbnk1 bit $c080 altbnk1 bit $ffc0
lda self+1 lda self+1
bne L081A bne L081A
rts rts
!pseudopc *+$0000 { !pseudopc *+$0000 {
altbnk2 bit $c080 altbnk2 bit $ffc0
lda $0819 lda $0819
bne $081a bne $081a
ldx $081b ldx $081b
@ -106,7 +112,7 @@ inner1_pre
!pseudopc $9000 { !pseudopc $9000 {
inner1 ldx inner1 inner1 ldx inner1
ldy #$aa ldy #$aa
ldy finish1 L9005 ldy finish1
ldy finish2 ldy finish2
ldy $302b ldy $302b
ldy $402b ldy $402b
@ -116,12 +122,12 @@ inner1 ldx inner1
finish1 ldy finish1 finish1 ldy finish1
ldx region1 ldx region1
ldx region2 ldx region2
ldx $3000 ldx THREE_K
ldx $4000 ldx $4000
lda inner1 lda inner1
lda inner2 lda inner2
lda $b000 lda IN_3
lda $c000 lda IN_4
pla pla
rts rts
@ -146,7 +152,7 @@ inner2_pre
inner2 ldx inner2 inner2 ldx inner2
ldy #$aa ldy #$aa
ldy $102b ldy $102b
ldy finish2 LA008 ldy finish2
ldy $302b ldy $302b
ldy $402b ldy $402b
rts rts
@ -155,12 +161,16 @@ inner2 ldx inner2
finish2 ldy finish2 finish2 ldy finish2
ldx $1000 ldx $1000
ldx region2 ldx region2
ldx $3000 ldx THREE_K
ldx $4000 ldx $4000
lda IN_1
lda inner2
lda IN_3
lda IN_4
pla pla
rts rts
!fill 196,$00 !fill 184,$00
} }
!pseudopc $3000 { !pseudopc $3000 {
@ -192,10 +202,14 @@ finish3 ldy finish3
ldx region2 ldx region2
ldx region3 ldx region3
ldx $4000 ldx $4000
lda inner1
lda inner2
lda inner3
lda IN_4
pla pla
rts rts
!fill 196,$00 !fill 184,$00
} }
!pseudopc $4000 { !pseudopc $4000 {
@ -218,19 +232,23 @@ inner4 ldx inner4
ldy $102b ldy $102b
ldy $202b ldy $202b
ldy $302b ldy $302b
ldy finish4 _checkit ldy finish4
rts rts
} }
finish4 ldy finish4 finish4 ldy finish4
ldx $1000 ldx $1000
ldx $2000 ldx $2000
ldx $3000 ldx THREE_K
ldx region4 ldx region4
lda IN_1
lda IN_2
lda IN_3
lda inner4
pla pla
rts rts
!fill 196,$00 !fill 184,$00
} }
!pseudopc $0000 { !pseudopc $0000 {
!byte $ff !byte $ff

View File

@ -1,26 +1,32 @@
.setcpu "6502" .setcpu "6502"
THREE_K = $3000 ;project symbol test
IN_1 = $9000
IN_2 = $a000
IN_3 = $b000
IN_4 = $c000
.org $0800 .org $0800
jsr region1 jsr region1
jsr region2 jsr region2
jsr $3000 jsr THREE_K
jsr $4000 jsr $4000
lda inner1 lda L9005
lda inner2 lda LA008
lda $b000 lda IN_3+11
lda $c000 lda IN_4+14
self: .byte $ad,$ea self: .byte $ad,$ea
L081A: nop L081A: nop
jsr altbnk1 jsr altbnk1
jsr altbnk2 jsr altbnk2
jmp done jmp done
altbnk1: bit $c080 altbnk1: bit $ffc0
lda self+1 lda self+1
bne L081A bne L081A
rts rts
.org *+$0000 .org *+$0000
altbnk2: bit $c080 altbnk2: bit $ffc0
lda $0819 lda $0819
bne $081a bne $081a
ldx $081b ldx $081b
@ -105,7 +111,7 @@ inner1_pre:
.org $9000 .org $9000
inner1: ldx inner1 inner1: ldx inner1
ldy #$aa ldy #$aa
ldy finish1 L9005: ldy finish1
ldy finish2 ldy finish2
ldy $302b ldy $302b
ldy $402b ldy $402b
@ -115,12 +121,12 @@ inner1: ldx inner1
finish1: ldy finish1 finish1: ldy finish1
ldx region1 ldx region1
ldx region2 ldx region2
ldx $3000 ldx THREE_K
ldx $4000 ldx $4000
lda inner1 lda inner1
lda inner2 lda inner2
lda $b000 lda IN_3
lda $c000 lda IN_4
pla pla
rts rts
@ -144,7 +150,7 @@ inner2_pre:
inner2: ldx inner2 inner2: ldx inner2
ldy #$aa ldy #$aa
ldy $102b ldy $102b
ldy finish2 LA008: ldy finish2
ldy $302b ldy $302b
ldy $402b ldy $402b
rts rts
@ -153,12 +159,16 @@ inner2: ldx inner2
finish2: ldy finish2 finish2: ldy finish2
ldx $1000 ldx $1000
ldx region2 ldx region2
ldx $3000 ldx THREE_K
ldx $4000 ldx $4000
lda IN_1
lda inner2
lda IN_3
lda IN_4
pla pla
rts rts
.res 196,$00 .res 184,$00
.org $3000 .org $3000
region3: lda region3 region3: lda region3
@ -189,10 +199,14 @@ finish3: ldy finish3
ldx region2 ldx region2
ldx region3 ldx region3
ldx $4000 ldx $4000
lda inner1
lda inner2
lda inner3
lda IN_4
pla pla
rts rts
.res 196,$00 .res 184,$00
.org $4000 .org $4000
region4: lda region4 region4: lda region4
@ -214,18 +228,22 @@ inner4: ldx inner4
ldy $102b ldy $102b
ldy $202b ldy $202b
ldy $302b ldy $302b
ldy finish4 _checkit: ldy finish4
rts rts
.org $402b .org $402b
finish4: ldy finish4 finish4: ldy finish4
ldx $1000 ldx $1000
ldx $2000 ldx $2000
ldx $3000 ldx THREE_K
ldx region4 ldx region4
lda IN_1
lda IN_2
lda IN_3
lda inner4
pla pla
rts rts
.res 196,$00 .res 184,$00
.org $0000 .org $0000
.byte $ff .byte $ff

View File

@ -1,25 +1,31 @@
THREE_K equ $3000 ;project symbol test
IN_1 equ $9000
IN_2 equ $a000
IN_3 equ $b000
IN_4 equ $c000
org $0800 org $0800
jsr region1 jsr region1
jsr region2 jsr region2
jsr $3000 jsr THREE_K
jsr $4000 jsr $4000
lda inner1 lda L9005
lda inner2 lda LA008
lda $b000 lda IN_3+11
lda $c000 lda IN_4+14
self dfb $ad,$ea self dfb $ad,$ea
L081A nop L081A nop
jsr altbnk1 jsr altbnk1
jsr altbnk2 jsr altbnk2
jmp done jmp done
altbnk1 bit $c080 altbnk1 bit $ffc0
lda self+1 lda self+1
bne L081A bne L081A
rts rts
org *+$0000 org *+$0000
altbnk2 bit $c080 altbnk2 bit $ffc0
lda $0819 lda $0819
bne $081a bne $081a
ldx $081b ldx $081b
@ -104,7 +110,7 @@ inner1_pre
org $9000 org $9000
inner1 ldx inner1 inner1 ldx inner1
ldy #$aa ldy #$aa
ldy finish1 L9005 ldy finish1
ldy finish2 ldy finish2
ldy $302b ldy $302b
ldy $402b ldy $402b
@ -114,12 +120,12 @@ inner1 ldx inner1
finish1 ldy finish1 finish1 ldy finish1
ldx region1 ldx region1
ldx region2 ldx region2
ldx $3000 ldx THREE_K
ldx $4000 ldx $4000
lda inner1 lda inner1
lda inner2 lda inner2
lda $b000 lda IN_3
lda $c000 lda IN_4
pla pla
rts rts
@ -143,7 +149,7 @@ inner2_pre
inner2 ldx inner2 inner2 ldx inner2
ldy #$aa ldy #$aa
ldy $102b ldy $102b
ldy finish2 LA008 ldy finish2
ldy $302b ldy $302b
ldy $402b ldy $402b
rts rts
@ -152,12 +158,16 @@ inner2 ldx inner2
finish2 ldy finish2 finish2 ldy finish2
ldx $1000 ldx $1000
ldx region2 ldx region2
ldx $3000 ldx THREE_K
ldx $4000 ldx $4000
lda IN_1
lda inner2
lda IN_3
lda IN_4
pla pla
rts rts
ds 196 ds 184
org $3000 org $3000
region3 lda region3 region3 lda region3
@ -188,10 +198,14 @@ finish3 ldy finish3
ldx region2 ldx region2
ldx region3 ldx region3
ldx $4000 ldx $4000
lda inner1
lda inner2
lda inner3
lda IN_4
pla pla
rts rts
ds 196 ds 184
org $4000 org $4000
region4 lda region4 region4 lda region4
@ -213,18 +227,22 @@ inner4 ldx inner4
ldy $102b ldy $102b
ldy $202b ldy $202b
ldy $302b ldy $302b
ldy finish4 _checkit ldy finish4
rts rts
org $402b org $402b
finish4 ldy finish4 finish4 ldy finish4
ldx $1000 ldx $1000
ldx $2000 ldx $2000
ldx $3000 ldx THREE_K
ldx region4 ldx region4
lda IN_1
lda IN_2
lda IN_3
lda inner4
pla pla
rts rts
ds 196 ds 184
org $0000 org $0000
dfb $ff dfb $ff

View File

@ -43,10 +43,10 @@ a way to tell the test harness to override the default. We do this by
creating project symbols: creating project symbols:
| Name | Value | Description | Name | Value | Description
| -------------------------- | ----- | -------------------------------------------| | -------------------------- | ----- | -----------------------------------------|
| __ENABLE_LABEL_NEWLINE | any | Puts long labels on their own line | | __ENABLE_LABEL_NEWLINE | any | Puts long labels on their own line |
| __ENABLE_ALL_LABEL_NEWLINE | any | Puts all labels on their own line | | __ENABLE_ALL_LABEL_NEWLINE | any | Puts all labels on their own line |
| __ENABLE_CYCLE_COUNTS | any | Adds cycle count to end-of-line comments | | __ENABLE_CYCLE_COUNTS | any | Adds cycle count to end-of-line comments |
### Execution ### ### Execution ###
@ -90,6 +90,7 @@ If you want to add or update a test, follow these steps:
into the Expected directory, replacing any existing copies. into the Expected directory, replacing any existing copies.
4. Run the test harness. This should now report success, and will 4. Run the test harness. This should now report success, and will
remove the tmpNNNNN directory. remove the tmpNNNNN directory.
5. Run "git diff" to verify that the changes match your expectations.
Be sure to have the version of the cross-assembler identified at the top Be sure to have the version of the cross-assembler identified at the top
of this document configured. of this document configured.

View File

@ -14,16 +14,21 @@
; regions 1-4. ; regions 1-4.
; ;
* = $0800 * = $0800
BANK = $c080 BANK = $ffc0
; EDIT: create project symbol THREE_K for $3000
jsr region1 jsr region1
jsr region2 jsr region2
jsr region3 jsr region3
jsr region4 jsr region4
lda inner1 ; EDIT: create project symbols for $8000/9000/a000/b000, len=256
lda inner2 ; These should resolve to the user labels (for 1/2) or the project
lda inner3 ; symbols (for 3/4). We use an offset from the base address to ensure
lda inner4 ; that the range is being taken into account.
lda inner1a
lda inner2a
lda inner3a
lda inner4a
; Local reference, can use "do not follow" to avoid mid-instruction branch. ; Local reference, can use "do not follow" to avoid mid-instruction branch.
self lda $eaea self lda $eaea
@ -91,7 +96,7 @@ inner1_pre ;*
.logical region1+$8000 ;* .logical region1+$8000 ;*
inner1 ldx inner1 ;* inner1 ldx inner1 ;*
ldy #$aa ldy #$aa
ldy finish1 inner1a ldy finish1
ldy finish2 ldy finish2
ldy finish3 ldy finish3
ldy finish4 ldy finish4
@ -137,7 +142,7 @@ inner2_pre ;*
inner2 ldx inner2 ;* inner2 ldx inner2 ;*
ldy #$aa ldy #$aa
ldy finish1 ldy finish1
ldy finish2 inner2a ldy finish2
ldy finish3 ldy finish3
ldy finish4 ldy finish4
rts rts
@ -149,6 +154,10 @@ finish2 ldy finish2 ;*
ldx region2 ldx region2
ldx region3 ldx region3
ldx region4 ldx region4
lda inner1
lda inner2
lda inner3
lda inner4
pla pla
rts rts
@ -179,7 +188,7 @@ inner3 ldx inner3 ;*
ldy #$aa ldy #$aa
ldy finish1 ldy finish1
ldy finish2 ldy finish2
ldy finish3 inner3a ldy finish3
ldy finish4 ldy finish4
rts rts
inner3_end ;* inner3_end ;*
@ -190,6 +199,10 @@ finish3 ldy finish3 ;*
ldx region2 ldx region2
ldx region3 ldx region3
ldx region4 ldx region4
lda inner1
lda inner2
lda inner3
lda inner4
pla pla
rts rts
@ -221,7 +234,7 @@ inner4 ldx inner4 ;*
ldy finish1 ldy finish1
ldy finish2 ldy finish2
ldy finish3 ldy finish3
ldy finish4 inner4a ldy finish4
rts rts
inner4_end ;* inner4_end ;*
.endlogical .endlogical
@ -231,6 +244,10 @@ finish4 ldy finish4 ;*
ldx region2 ldx region2
ldx region3 ldx region3
ldx region4 ldx region4
lda inner1
lda inner2
lda inner3
lda inner4
pla pla
rts rts

View File

@ -523,6 +523,7 @@ namespace SourceGen {
/// variables. /// variables.
/// </summary> /// </summary>
/// <param name="addr">Address to find.</param> /// <param name="addr">Address to find.</param>
/// <param name="effect">Memory effect type to match against.</param>
/// <returns>First matching symbol found, or null if nothing matched.</returns> /// <returns>First matching symbol found, or null if nothing matched.</returns>
public Symbol FindNonVariableByAddress(int addr, OpDef.MemoryEffect effect) { public Symbol FindNonVariableByAddress(int addr, OpDef.MemoryEffect effect) {
bool tryRead, tryWrite; bool tryRead, tryWrite;
@ -540,6 +541,7 @@ namespace SourceGen {
return null; return null;
} }
// The mSymbolsBy{Read,Write}Address tables don't include local vars or constants.
Symbol sym = null; Symbol sym = null;
if (tryRead) { if (tryRead) {
mSymbolsByReadAddress.TryGetValue(addr, out sym); mSymbolsByReadAddress.TryGetValue(addr, out sym);
@ -549,11 +551,10 @@ namespace SourceGen {
} }
if (sym == null) { if (sym == null) {
// Nothing matched, check the match groups. // Nothing matched, check the mask groups.
foreach (KeyValuePair<DefSymbol.MultiAddressMask, MaskGroup> kvp in mMaskGroups) { foreach (KeyValuePair<DefSymbol.MultiAddressMask, MaskGroup> kvp in mMaskGroups) {
DefSymbol.MultiAddressMask multiMask = kvp.Key; DefSymbol.MultiAddressMask multiMask = kvp.Key;
if ((addr & multiMask.CompareMask) == multiMask.CompareValue) { if ((addr & multiMask.CompareMask) == multiMask.CompareValue) {
MaskGroup group = kvp.Value;
DefSymbol defSym = kvp.Value.Find(addr, tryRead, tryWrite); DefSymbol defSym = kvp.Value.Find(addr, tryRead, tryWrite);
if (defSym != null) { if (defSym != null) {
sym = defSym; sym = defSym;
@ -565,6 +566,53 @@ namespace SourceGen {
return sym; return sym;
} }
/// <summary>
/// Searches the table for project/platform symbols with matching address values. Ignores
/// constants and variables.
/// </summary>
/// <param name="addr">Address to find.</param>
/// <param name="effect">Memory effect type to match against.</param>
/// <returns>First matching symbol found, or null if nothing matched.</returns>
public Symbol FindProjPlatPreByAddress(int addr, OpDef.MemoryEffect effect) {
bool tryRead, tryWrite;
if (effect == OpDef.MemoryEffect.Read) {
tryRead = true;
tryWrite = false;
} else if (effect == OpDef.MemoryEffect.Write) {
tryRead = false;
tryWrite = true;
} else if (effect == OpDef.MemoryEffect.ReadModifyWrite ||
effect == OpDef.MemoryEffect.None) {
tryRead = tryWrite = true;
} else {
Debug.Assert(false);
return null;
}
// We don't have a pair of tables for this, so just do a linear walk through
// the symbol table. This is inefficient, but the current use case is very rare.
foreach (KeyValuePair<string,Symbol> kvp in mSymbols) {
if (!(kvp.Value is DefSymbol)) {
continue;
}
DefSymbol defSym = (DefSymbol)kvp.Value;
if (defSym.SymbolSource != Symbol.Source.Project &&
defSym.SymbolSource != Symbol.Source.Platform &&
defSym.SymbolSource != Symbol.Source.AddrPreLabel) {
continue;
}
if (addr >= defSym.Value && addr < defSym.Value + defSym.DataDescriptor.Length) {
if ((tryRead && (defSym.Direction & DefSymbol.DirectionFlags.Read) != 0) ||
(tryWrite && (defSym.Direction & DefSymbol.DirectionFlags.Write) != 0))
{
return defSym;
}
}
}
// Do we need to check the mask groups?
return null;
}
public override string ToString() { public override string ToString() {
return "SymbolTable: " + mSymbols.Count + " by label, " + return "SymbolTable: " + mSymbols.Count + " by label, " +
mSymbolsByReadAddress.Count + " by addr(r), " + mSymbolsByReadAddress.Count + " by addr(r), " +

View File

@ -322,7 +322,9 @@ once, so there's no reason to treat them as separate projects. Currently,
the best way to deal with this is to concatenate the files into a single the best way to deal with this is to concatenate the files into a single
file, and operate on that.</p> file, and operate on that.</p>
<h2 id="overlap">Overlapping Address Spaces</h2> <h2 id="overlap">Overlapping Address Spaces</h2>
<p>Some programs use memory overlays, where multiple parts of the <p>Some programs use memory overlays, where multiple parts of the
code run in the same address in RAM. Others use bank switching to access code run in the same address in RAM. Others use bank switching to access
parts of the program that reside in separate physical RAM or ROM, parts of the program that reside in separate physical RAM or ROM,
@ -383,6 +385,16 @@ it is referring to.</p>
If we hit the top of the tree without finding a match, we conclude If we hit the top of the tree without finding a match, we conclude
that the reference is to an external address.</p> that the reference is to an external address.</p>
<p>The tree search can be pruned with the
"disallow inbound address resolution" and
"disallow outbound address resolution" flags, which can be set in
the address region edit dialog
(<a href="intro-details.html#region-isolation">more info here</a>).
When inbound resolution is disabled,
parents and siblings will not search into a region. When outbound
resolution is disabled, the search will not ascend to the region's parent.
Note that neither option prevents descent into a region's children.</p>
<h2 id="reloc-data">OMF Relocation Dictionaries</h2> <h2 id="reloc-data">OMF Relocation Dictionaries</h2>

View File

@ -30,9 +30,12 @@ would resolve to address $123456.
If you want to set the region to be non-addressable, enter If you want to set the region to be non-addressable, enter
"<code>NA</code>".</p> "<code>NA</code>".</p>
<p>You can also enter a <a href="intro-details.html#pre-labels">pre-label</a> <p>You can also enter a <a href="intro-details.html#pre-labels">pre-label</a>,
or specify that the operand should be formatted as a specify that the operand should be formatted as a
<a href="intro-details.html#relative-addr">relative address</a>. <a href="intro-details.html#relative-addr">relative address</a>,
or
<a href="intro-details.html#region-isolation">disallow address resolution</a>
across region boundaries.</p>
<p>To delete a region, click the "Delete Region" button.</p> <p>To delete a region, click the "Delete Region" button.</p>

View File

@ -653,8 +653,36 @@ within the file. The process is straightforward if the address only
appears once, but when overlays cause multiple parts of the file to have appears once, but when overlays cause multiple parts of the file to have
the same address, the operand target may be in different places depending the same address, the operand target may be in different places depending
on where the call is being made from. on where the call is being made from.
The algorithm for resolving addresses is described The algorithm for resolving addresses is described in the
in the <a href="advanced.html#overlap">advanced topics</a> section.</p> <a href="advanced.html#overlap">advanced topics</a> section.</p>
<h3 id="region-isolation">Isolation</h3>
<p>Code in regions that have been relocated will usually be able to
access code and data in other regions. However, sometimes code is
destined to be executed in an independent address space, such as a
disk drive controller, or is part of a bank-switched ROM that puts
multiple regions at the same address. In such cases, you wouldn't
want the address operand of, say, a <code>JSR</code> to resolve to
a symbol in a different region.</p>
<p>The address resolution behavior for a given region can be modified
with the "disallow inbound address resolution" and
"disallow outbound address resolution" checkboxes. The former
prevents other regions from searching for matches in the current
region, and the latter prevents the current region from searching
other regions. (The algorithm is described in the
<a href="advanced.html#overlap">advanced topics</a> section.)</p>
<p>In some rare cases it may be useful to allow resolution to work
in one direction. For example, suppose ROM bank #1 has a table of
<code>JMP</code> instructions for bank #2 that it will copy out to
RAM. The table should be placed into its own address region, with
outbound resolution disabled, because we don't want it to try to
jump to locations in our bank #1 code. It's useful to leave inbound
resolution enabled so that we can reference the table from the code
that copies it to RAM.</p>
<h3 id="non-addr">Non-Addressable Areas</h3> <h3 id="non-addr">Non-Addressable Areas</h3>