1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-06-19 21:29:30 +00:00

Address region isolation, part 2

Added an address-to-offset test in the GeneratePlatformSymbolRefs()
method, which sets the operand symbols for anything that lands outside
the scope of the file.  Because the region isolation code prevented
symbols from being associated with the operands in the initial code
scan, those operands were being examined here.  Without the additional
test, the inappropriate label associations were getting a second chance.

Added "[!in]" and "[!out]" to the comment field of .addrs lines.  This
is only for the on-screen display and text exports, not asm gen.

Bumped the project file CONTENT_VERSION.

Added a regression test (20290-region-isolation).

The test turned up an existing problem: pre-labels are emitted by the
asm generators on their own line, but the code that puts excessively
long labels on a separate line wasn't taking that into account.  This
has been fixed.  No changes to existing regression tests, which didn't
happen to use long labels.
This commit is contained in:
Andy McFadden 2024-05-21 10:32:18 -07:00
parent ea4ddc1071
commit e137db2b5c
16 changed files with 1551 additions and 16 deletions

View File

@ -272,7 +272,9 @@ namespace CommonUtil {
return "[AddrRegion: +" + Offset.ToString("x6") +
" len=" + (Length == FLOATING_LEN ? "float" : "$" + Length.ToString("x4")) +
" addr=" + (Address == NON_ADDR ? "NA" : "$" + Address.ToString("x4")) +
" actualLen=$" + ActualLength.ToString("x4") + " isRel=" + IsRelative + "]";
" actualLen=$" + ActualLength.ToString("x4") +
" disIn=" + DisallowInward + " disOut=" + DisallowOutward + " isRel=" +
IsRelative + "]";
}
}

View File

@ -664,7 +664,7 @@ namespace SourceGen.AsmGen {
// IGenerator
public void OutputLine(string label, string opcode, string operand, string comment) {
// Break the line if the label is long and it's not a .EQ directive.
if (!string.IsNullOrEmpty(label) &&
if (!string.IsNullOrEmpty(label) && !string.IsNullOrEmpty(opcode) &&
!string.Equals(opcode, sDataOpNames.EquDirective,
StringComparison.InvariantCultureIgnoreCase)) {

View File

@ -660,9 +660,10 @@ namespace SourceGen.AsmGen {
StringComparison.InvariantCultureIgnoreCase)) {
label += ':';
if (mLabelNewLine == GenCommon.LabelPlacement.PreferSeparateLine ||
(mLabelNewLine == GenCommon.LabelPlacement.SplitIfTooLong &&
label.Length >= mColumnWidths[0])) {
if (!string.IsNullOrEmpty(opcode) &&
(mLabelNewLine == GenCommon.LabelPlacement.PreferSeparateLine ||
(mLabelNewLine == GenCommon.LabelPlacement.SplitIfTooLong &&
label.Length >= mColumnWidths[0]))) {
mOutStream.WriteLine(label);
label = string.Empty;
}

View File

@ -607,7 +607,8 @@ namespace SourceGen.AsmGen {
// IGenerator
public void OutputLine(string label, string opcode, string operand, string comment) {
// Split long label, but not on EQU directives (confuses the assembler).
if (!string.IsNullOrEmpty(label) && !string.Equals(opcode, sDataOpNames.EquDirective,
if (!string.IsNullOrEmpty(label) && !string.IsNullOrEmpty(opcode) &&
!string.Equals(opcode, sDataOpNames.EquDirective,
StringComparison.InvariantCultureIgnoreCase)) {
if (mLabelNewLine == GenCommon.LabelPlacement.PreferSeparateLine ||
(mLabelNewLine == GenCommon.LabelPlacement.SplitIfTooLong &&

View File

@ -772,7 +772,7 @@ namespace SourceGen.AsmGen {
// IGenerator
public void OutputLine(string label, string opcode, string operand, string comment) {
// Break the line if the label is long and it's not a .EQ/.VAR directive.
if (!string.IsNullOrEmpty(label) &&
if (!string.IsNullOrEmpty(label) && !string.IsNullOrEmpty(opcode) &&
!string.Equals(opcode, sDataOpNames.EquDirective,
StringComparison.InvariantCultureIgnoreCase) &&
!string.Equals(opcode, sDataOpNames.VarDirective,

View File

@ -1438,8 +1438,10 @@ namespace SourceGen {
attr.OperandAddress >= 0 && attr.OperandOffset < 0) {
// This is an instruction that hasn't been explicitly formatted. It
// has an operand address, but not an offset, meaning it's a reference
// to an address outside the scope of the file. See if it has a
// platform symbol definition.
// to an address outside the scope of the file -or- a reference to an address
// region that we're not supposed to interact with (DisallowInbound on it
// or DisallowOutbound on us). See if it has a platform symbol definition,
// or perhaps an address region pre-label.
//
// It might seem unwise to examine the full symbol table, because it has
// non-project non-platform symbols in it. However, any matching user
@ -1493,10 +1495,20 @@ namespace SourceGen {
if (sym == null && checkNearby && (address & 0xffff) < 0xffff &&
address > 0x0000ff) {
sym = SymbolTable.FindNonVariableByAddress(address + 1, accType);
if (sym != null && sym.SymbolSource != Symbol.Source.Project &&
sym.SymbolSource != Symbol.Source.Platform) {
Debug.WriteLine("Applying non-platform in GeneratePlatform: " + sym);
// should be okay to do this
}
if (sym != null && sym.SymbolSource != Symbol.Source.Project &&
sym.SymbolSource != Symbol.Source.Platform &&
sym.SymbolSource != Symbol.Source.AddrPreLabel) {
// If we matched to something other than a project/platform symbol or
// pre-label (which are expected to be outside the file area), make sure
// we're not doing an invalid cross-region reference.
if (AddrMap.AddressToOffset(offset, sym.Value) >= 0) {
Debug.WriteLine("GeneratePlatform applying non-platform at +" +
offset.ToString("x6") + ": " + sym);
} else {
Debug.WriteLine("GeneratePlatform not applying at +" +
offset.ToString("x6") + ": " + sym);
sym = null;
}
}

View File

@ -1122,9 +1122,19 @@ namespace SourceGen {
comment += " (auto-generated)";
}
#else
string comment = string.Empty;
string cstr = string.Empty;
if (change.IsSynthetic) {
comment = mFormatter.FormatEolComment("(auto-generated)");
cstr += " (auto-generated)";
}
if (region.DisallowInward) {
cstr += " [!in]";
}
if (region.DisallowOutward) {
cstr += " [!out]";
}
string comment = string.Empty;
if (cstr.Length > 0) {
comment = mFormatter.FormatEolComment(cstr.Substring(1));
}
#endif
newLine.Parts = FormattedParts.CreateFullDirective(string.Empty,

View File

@ -52,7 +52,7 @@ namespace SourceGen {
// ignore stuff that's in one side but not the other. However, if we're opening a
// newer file in an older program, it's worth letting the user know that some stuff
// may get lost as soon as they save the file.
public const int CONTENT_VERSION = 5;
public const int CONTENT_VERSION = 6;
// Max JSON file length.
internal const int MAX_JSON_LENGTH = 64 * 1024 * 1024;

Binary file not shown.

View File

@ -0,0 +1,323 @@
### 6502bench SourceGen dis65 v1.0 ###
{
"_ContentVersion":6,
"FileDataLength":1537,
"FileDataCrc32":950074699,
"ProjectProps":{
"CpuName":"6502",
"IncludeUndocumentedInstr":false,
"TwoByteBrk":false,
"EntryFlags":32702671,
"AutoLabelStyle":"Simple",
"AnalysisParams":{
"AnalyzeUncategorizedData":true,
"DefaultTextScanMode":"LowHighAscii",
"MinCharsForString":4,
"SeekNearbyTargets":true,
"UseRelocData":false,
"SmartPlpHandling":false,
"SmartPlbHandling":true},
"PlatformSymbolFileIdentifiers":[],
"ExtensionScriptFileIdentifiers":[],
"ProjectSyms":{
}},
"AddressMap":[{
"Offset":0,
"Addr":2048,
"Length":256,
"PreLabel":"",
"DisallowInward":false,
"DisallowOutward":false,
"IsRelative":false},
{
"Offset":45,
"Addr":2093,
"Length":12,
"PreLabel":"",
"DisallowInward":false,
"DisallowOutward":true,
"IsRelative":true},
{
"Offset":256,
"Addr":4096,
"Length":256,
"PreLabel":"",
"DisallowInward":true,
"DisallowOutward":true,
"IsRelative":false},
{
"Offset":512,
"Addr":4096,
"Length":256,
"PreLabel":"",
"DisallowInward":false,
"DisallowOutward":false,
"IsRelative":false},
{
"Offset":537,
"Addr":36864,
"Length":18,
"PreLabel":"inner1_pre",
"DisallowInward":false,
"DisallowOutward":false,
"IsRelative":false},
{
"Offset":768,
"Addr":8192,
"Length":256,
"PreLabel":"",
"DisallowInward":false,
"DisallowOutward":true,
"IsRelative":false},
{
"Offset":793,
"Addr":40960,
"Length":18,
"PreLabel":"inner2_pre",
"DisallowInward":false,
"DisallowOutward":false,
"IsRelative":false},
{
"Offset":1024,
"Addr":12288,
"Length":256,
"PreLabel":"",
"DisallowInward":true,
"DisallowOutward":false,
"IsRelative":false},
{
"Offset":1049,
"Addr":45056,
"Length":18,
"PreLabel":"inner3_pre",
"DisallowInward":false,
"DisallowOutward":false,
"IsRelative":false},
{
"Offset":1280,
"Addr":16384,
"Length":256,
"PreLabel":"",
"DisallowInward":true,
"DisallowOutward":true,
"IsRelative":false},
{
"Offset":1305,
"Addr":49152,
"Length":18,
"PreLabel":"inner4_pre",
"DisallowInward":false,
"DisallowOutward":false,
"IsRelative":false}],
"TypeHints":[{
"Low":0,
"High":0,
"Hint":"Code"},
{
"Low":256,
"High":256,
"Hint":"Code"},
{
"Low":512,
"High":512,
"Hint":"Code"},
{
"Low":1024,
"High":1024,
"Hint":"Code"},
{
"Low":1280,
"High":1280,
"Hint":"Code"}],
"StatusFlagOverrides":{
},
"Comments":{
},
"LongComments":{
},
"Notes":{
},
"UserLabels":{
"256":{
"Label":"region1x",
"Value":4096,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"36":{
"Label":"altbnk1",
"Value":2084,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"45":{
"Label":"altbnk2",
"Value":2093,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"57":{
"Label":"done",
"Value":2105,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"512":{
"Label":"region1",
"Value":4096,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"537":{
"Label":"inner1",
"Value":36864,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"555":{
"Label":"finish1",
"Value":4139,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"768":{
"Label":"region2",
"Value":8192,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"793":{
"Label":"inner2",
"Value":40960,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"811":{
"Label":"finish2",
"Value":8235,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"1024":{
"Label":"region3",
"Value":12288,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"1049":{
"Label":"inner3",
"Value":45056,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"1067":{
"Label":"finish3",
"Value":12331,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"1280":{
"Label":"region4",
"Value":16384,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"1305":{
"Label":"inner4",
"Value":49152,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"1323":{
"Label":"finish4",
"Value":16427,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"1287":{
"Label":"copy",
"Value":16391,
"Source":"User",
"Type":"NonUniqueLocalAddr",
"LabelAnno":"None"},
"1031":{
"Label":"copy",
"Value":12295,
"Source":"User",
"Type":"NonUniqueLocalAddr",
"LabelAnno":"None"},
"775":{
"Label":"copy",
"Value":8199,
"Source":"User",
"Type":"NonUniqueLocalAddr",
"LabelAnno":"None"},
"519":{
"Label":"copy",
"Value":4103,
"Source":"User",
"Type":"NonUniqueLocalAddr",
"LabelAnno":"None"},
"24":{
"Label":"self",
"Value":2072,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"}},
"OperandFormats":{
},
"LvTables":{
},
"Visualizations":[],
"VisualizationAnimations":[],
"VisualizationSets":{
},
"RelocList":{
},
"DbrValues":{
}}

View File

@ -0,0 +1,237 @@
.cpu "6502"
* = $0800
jsr region1
jsr region2
jsr $3000
jsr $4000
lda inner1
lda inner2
lda $b000
lda $c000
self .byte $ad,$ea
L081A nop
jsr altbnk1
jsr altbnk2
jmp done
altbnk1 bit $c080
lda self+1
bne L081A
rts
.logical *+$0000
altbnk2 bit $c080
lda $0819
bne $081a
ldx $081b
rts
.here
done nop
rts
.fill 197,$00
.logical $1000
region1x lda region1x
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
rts
.fill 202,$00
.here
.logical $1000
region1 lda region1
pha
ldy #$11
nop
_copy lda inner1_pre,y
sta inner1,y
dey
bpl _copy
bit $101d
jsr inner1
jmp finish1
inner1_pre
.logical $9000
inner1 ldx inner1
ldy #$aa
ldy finish1
ldy finish2
ldy $302b
ldy $402b
rts
.here
finish1 ldy finish1
ldx region1
ldx region2
ldx $3000
ldx $4000
lda inner1
lda inner2
lda $b000
lda $c000
pla
rts
.fill 184,$00
.here
.logical $2000
region2 lda region2
pha
ldy #$11
nop
_copy lda inner2_pre,y
sta inner2,y
dey
bpl _copy
bit $201d
jsr inner2
jmp finish2
inner2_pre
.logical $a000
inner2 ldx inner2
ldy #$aa
ldy $102b
ldy finish2
ldy $302b
ldy $402b
rts
.here
finish2 ldy finish2
ldx $1000
ldx region2
ldx $3000
ldx $4000
pla
rts
.fill 196,$00
.here
.logical $3000
region3 lda region3
pha
ldy #$11
nop
_copy lda inner3_pre,y
sta inner3,y
dey
bpl _copy
bit $301d
jsr inner3
jmp finish3
inner3_pre
.logical $b000
inner3 ldx inner3
ldy #$aa
ldy finish1
ldy finish2
ldy finish3
ldy $402b
rts
.here
finish3 ldy finish3
ldx region1
ldx region2
ldx region3
ldx $4000
pla
rts
.fill 196,$00
.here
.logical $4000
region4 lda region4
pha
ldy #$11
nop
_copy lda inner4_pre,y
sta inner4,y
dey
bpl _copy
bit $401d
jsr inner4
jmp finish4
inner4_pre
.logical $c000
inner4 ldx inner4
ldy #$aa
ldy $102b
ldy $202b
ldy $302b
ldy finish4
rts
.here
finish4 ldy finish4
ldx $1000
ldx $2000
ldx $3000
ldx region4
pla
rts
.fill 196,$00
.here
.logical $0000
.byte $ff
.here

View File

@ -0,0 +1,237 @@
!cpu 6502
* = $0800
jsr region1
jsr region2
jsr $3000
jsr $4000
lda inner1
lda inner2
lda $b000
lda $c000
self !byte $ad,$ea
L081A nop
jsr altbnk1
jsr altbnk2
jmp done
altbnk1 bit $c080
lda self+1
bne L081A
rts
!pseudopc *+$0000 {
altbnk2 bit $c080
lda $0819
bne $081a
ldx $081b
rts
}
done nop
rts
!fill 197,$00
!pseudopc $1000 {
region1x lda region1x
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
rts
!fill 202,$00
}
!pseudopc $1000 {
region1 lda region1
pha
ldy #$11
nop
@copy lda inner1_pre,y
sta inner1,y
dey
bpl @copy
bit $101d
jsr inner1
jmp finish1
inner1_pre
!pseudopc $9000 {
inner1 ldx inner1
ldy #$aa
ldy finish1
ldy finish2
ldy $302b
ldy $402b
rts
}
finish1 ldy finish1
ldx region1
ldx region2
ldx $3000
ldx $4000
lda inner1
lda inner2
lda $b000
lda $c000
pla
rts
!fill 184,$00
}
!pseudopc $2000 {
region2 lda region2
pha
ldy #$11
nop
@copy lda inner2_pre,y
sta inner2,y
dey
bpl @copy
bit $201d
jsr inner2
jmp finish2
inner2_pre
!pseudopc $a000 {
inner2 ldx inner2
ldy #$aa
ldy $102b
ldy finish2
ldy $302b
ldy $402b
rts
}
finish2 ldy finish2
ldx $1000
ldx region2
ldx $3000
ldx $4000
pla
rts
!fill 196,$00
}
!pseudopc $3000 {
region3 lda region3
pha
ldy #$11
nop
@copy lda inner3_pre,y
sta inner3,y
dey
bpl @copy
bit $301d
jsr inner3
jmp finish3
inner3_pre
!pseudopc $b000 {
inner3 ldx inner3
ldy #$aa
ldy finish1
ldy finish2
ldy finish3
ldy $402b
rts
}
finish3 ldy finish3
ldx region1
ldx region2
ldx region3
ldx $4000
pla
rts
!fill 196,$00
}
!pseudopc $4000 {
region4 lda region4
pha
ldy #$11
nop
@copy lda inner4_pre,y
sta inner4,y
dey
bpl @copy
bit $401d
jsr inner4
jmp finish4
inner4_pre
!pseudopc $c000 {
inner4 ldx inner4
ldy #$aa
ldy $102b
ldy $202b
ldy $302b
ldy finish4
rts
}
finish4 ldy finish4
ldx $1000
ldx $2000
ldx $3000
ldx region4
pla
rts
!fill 196,$00
}
!pseudopc $0000 {
!byte $ff
}

View File

@ -0,0 +1,231 @@
.setcpu "6502"
.org $0800
jsr region1
jsr region2
jsr $3000
jsr $4000
lda inner1
lda inner2
lda $b000
lda $c000
self: .byte $ad,$ea
L081A: nop
jsr altbnk1
jsr altbnk2
jmp done
altbnk1: bit $c080
lda self+1
bne L081A
rts
.org *+$0000
altbnk2: bit $c080
lda $0819
bne $081a
ldx $081b
rts
.org $0839
done: nop
rts
.res 197,$00
.org $1000
region1x: lda region1x
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
rts
.res 202,$00
.org $1000
region1: lda region1
pha
ldy #$11
nop
@copy: lda inner1_pre,y
sta inner1,y
dey
bpl @copy
bit $101d
jsr inner1
jmp finish1
inner1_pre:
.org $9000
inner1: ldx inner1
ldy #$aa
ldy finish1
ldy finish2
ldy $302b
ldy $402b
rts
.org $102b
finish1: ldy finish1
ldx region1
ldx region2
ldx $3000
ldx $4000
lda inner1
lda inner2
lda $b000
lda $c000
pla
rts
.res 184,$00
.org $2000
region2: lda region2
pha
ldy #$11
nop
@copy: lda inner2_pre,y
sta inner2,y
dey
bpl @copy
bit $201d
jsr inner2
jmp finish2
inner2_pre:
.org $a000
inner2: ldx inner2
ldy #$aa
ldy $102b
ldy finish2
ldy $302b
ldy $402b
rts
.org $202b
finish2: ldy finish2
ldx $1000
ldx region2
ldx $3000
ldx $4000
pla
rts
.res 196,$00
.org $3000
region3: lda region3
pha
ldy #$11
nop
@copy: lda inner3_pre,y
sta inner3,y
dey
bpl @copy
bit $301d
jsr inner3
jmp finish3
inner3_pre:
.org $b000
inner3: ldx inner3
ldy #$aa
ldy finish1
ldy finish2
ldy finish3
ldy $402b
rts
.org $302b
finish3: ldy finish3
ldx region1
ldx region2
ldx region3
ldx $4000
pla
rts
.res 196,$00
.org $4000
region4: lda region4
pha
ldy #$11
nop
@copy: lda inner4_pre,y
sta inner4,y
dey
bpl @copy
bit $401d
jsr inner4
jmp finish4
inner4_pre:
.org $c000
inner4: ldx inner4
ldy #$aa
ldy $102b
ldy $202b
ldy $302b
ldy finish4
rts
.org $402b
finish4: ldy finish4
ldx $1000
ldx $2000
ldx $3000
ldx region4
pla
rts
.res 196,$00
.org $0000
.byte $ff

View File

@ -0,0 +1,9 @@
# 6502bench SourceGen generated linker script for 20290-region-isolation
MEMORY {
MAIN: file=%O, start=%S, size=65536;
}
SEGMENTS {
CODE: load=MAIN, type=rw;
}
FEATURES {}
SYMBOLS {}

View File

@ -0,0 +1,230 @@
org $0800
jsr region1
jsr region2
jsr $3000
jsr $4000
lda inner1
lda inner2
lda $b000
lda $c000
self dfb $ad,$ea
L081A nop
jsr altbnk1
jsr altbnk2
jmp done
altbnk1 bit $c080
lda self+1
bne L081A
rts
org *+$0000
altbnk2 bit $c080
lda $0819
bne $081a
ldx $081b
rts
org $0839
done nop
rts
ds 197
org $1000
region1x lda region1x
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
rts
ds 202
org $1000
region1 lda region1
pha
ldy #$11
nop
:copy lda inner1_pre,y
sta inner1,y
dey
bpl :copy
bit $101d
jsr inner1
jmp finish1
inner1_pre
org $9000
inner1 ldx inner1
ldy #$aa
ldy finish1
ldy finish2
ldy $302b
ldy $402b
rts
org $102b
finish1 ldy finish1
ldx region1
ldx region2
ldx $3000
ldx $4000
lda inner1
lda inner2
lda $b000
lda $c000
pla
rts
ds 184
org $2000
region2 lda region2
pha
ldy #$11
nop
:copy lda inner2_pre,y
sta inner2,y
dey
bpl :copy
bit $201d
jsr inner2
jmp finish2
inner2_pre
org $a000
inner2 ldx inner2
ldy #$aa
ldy $102b
ldy finish2
ldy $302b
ldy $402b
rts
org $202b
finish2 ldy finish2
ldx $1000
ldx region2
ldx $3000
ldx $4000
pla
rts
ds 196
org $3000
region3 lda region3
pha
ldy #$11
nop
:copy lda inner3_pre,y
sta inner3,y
dey
bpl :copy
bit $301d
jsr inner3
jmp finish3
inner3_pre
org $b000
inner3 ldx inner3
ldy #$aa
ldy finish1
ldy finish2
ldy finish3
ldy $402b
rts
org $302b
finish3 ldy finish3
ldx region1
ldx region2
ldx region3
ldx $4000
pla
rts
ds 196
org $4000
region4 lda region4
pha
ldy #$11
nop
:copy lda inner4_pre,y
sta inner4,y
dey
bpl :copy
bit $401d
jsr inner4
jmp finish4
inner4_pre
org $c000
inner4 ldx inner4
ldy #$aa
ldy $102b
ldy $202b
ldy $302b
ldy finish4
rts
org $402b
finish4 ldy finish4
ldx $1000
ldx $2000
ldx $3000
ldx region4
pla
rts
ds 196
org $0000
dfb $ff

View File

@ -0,0 +1,242 @@
; Copyright 2024 faddenSoft. All Rights Reserved.
; See the LICENSE.txt file for distribution terms (Apache 2.0).
;
; Assembler: 64tass
; % tass64 --ascii --case-sensitive --nostart 20290-region-isolation.S
;
; This is pretending to be a multi-bank ROM, with 256 bytes per bank.
.cpu "6502"
;
; Initial region. This should end before region1, rather than span
; all sub-regions, so that we're exercising top-level regions for
; regions 1-4.
;
* = $0800
BANK = $c080
jsr region1
jsr region2
jsr region3
jsr region4
lda inner1
lda inner2
lda inner3
lda inner4
; Local reference, can use "do not follow" to avoid mid-instruction branch.
self lda $eaea
call jsr altbnk1
jsr altbnk2
jmp done
; These pretend to be code that switches the ROM bank, so the code
; after the BIT instruction is actually in a different ROM, and the
; BNE goes to something else.
; EDIT: mark individual BNE as "do not follow"
altbnk1 bit BANK ;e.g. trigger a ROM bank switch
lda self+1
bne self+2
rts
; EDIT: put this in a separate region, mark "disallow outbound"
altbnk2 bit BANK
lda self+1
bne self+2
ldx call ;EDIT: set symbol explicitly, should work
rts
done nop
rts
.align 256
;
; region 1x: fully closed
;
; This overlaps with region 1. By closing it we should prevent any
; of the external references from resolving here.
;
.logical $1000
region1x lda region1x
.fill 50,$ea
rts
.align 256
.endlogical
;
; region 1: fully open
;
.logical $1000 ;*
region1 lda region1 ;*
pha
ldy #inner1_end-inner1-1 ;*
nop
_copy lda inner1_pre,y ;*
sta inner1,y ;*
dey
bpl _copy
bit inner1_pre+4 ;* should be an unresolved hole
jsr inner1 ;*
jmp finish1 ;*
; relocated inner chunk
inner1_pre ;*
.logical region1+$8000 ;*
inner1 ldx inner1 ;*
ldy #$aa
ldy finish1
ldy finish2
ldy finish3
ldy finish4
rts
inner1_end ;*
.endlogical
finish1 ldy finish1 ;*
ldx region1
ldx region2
ldx region3
ldx region4
lda inner1
lda inner2
lda inner3
lda inner4
pla
rts
.align 256 ;pad chunk to 256 bytes
.endlogical
;
; region 2: disallow outbound
;
.logical $2000
region2 lda region2
pha
ldy #inner2_end-inner2-1 ;*
nop
_copy lda inner2_pre,y ;*
sta inner2,y ;*
dey
bpl _copy
bit inner2_pre+4 ;* should be an unresolved hole
jsr inner2 ;*
jmp finish2 ;*
; relocated inner chunk
inner2_pre ;*
.logical region2+$8000 ;*
inner2 ldx inner2 ;*
ldy #$aa
ldy finish1
ldy finish2
ldy finish3
ldy finish4
rts
inner2_end ;*
.endlogical
finish2 ldy finish2 ;*
ldx region1
ldx region2
ldx region3
ldx region4
pla
rts
.align 256 ;pad chunk to 256 bytes
.endlogical
;
; region 3: disallow inbound
;
.logical $3000
region3 lda region3
pha
ldy #inner3_end-inner3-1 ;*
nop
_copy lda inner3_pre,y ;*
sta inner3,y ;*
dey
bpl _copy
bit inner3_pre+4 ;* should be an unresolved hole
jsr inner3 ;*
jmp finish3 ;*
; relocated inner chunk
inner3_pre ;*
.logical region3+$8000 ;*
inner3 ldx inner3 ;*
ldy #$aa
ldy finish1
ldy finish2
ldy finish3
ldy finish4
rts
inner3_end ;*
.endlogical
finish3 ldy finish3 ;*
ldx region1
ldx region2
ldx region3
ldx region4
pla
rts
.align 256 ;pad chunk to 256 bytes
.endlogical
;
; region 4: disallow both
;
.logical $4000
region4 lda region4
pha
ldy #inner4_end-inner4-1 ;*
nop
_copy lda inner4_pre,y ;*
sta inner4,y ;*
dey
bpl _copy
bit inner4_pre+4 ;* should be an unresolved hole
jsr inner4 ;*
jmp finish4 ;*
; relocated inner chunk
inner4_pre ;*
.logical region4+$8000 ;*
inner4 ldx inner4 ;*
ldy #$aa
ldy finish1
ldy finish2
ldy finish3
ldy finish4
rts
inner4_end ;*
.endlogical
finish4 ldy finish4 ;*
ldx region1
ldx region2
ldx region3
ldx region4
pla
rts
.align 256 ;pad chunk to 256 bytes
.endlogical
; Not sure how to force asm to output alignment padding at end of file.
; Leave this marked as non-addressable.
.byte $ff