1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-07-08 14:28:55 +00:00

External symbol I/O direction and address mask, part 3 (of 3)

Added regression tests.  Improved error messages.  Updated
documentation.
This commit is contained in:
Andy McFadden 2019-10-16 17:32:30 -07:00
parent 4d8ee3fd07
commit bd11aea4a4
16 changed files with 473 additions and 46 deletions

View File

@ -144,9 +144,9 @@ namespace SourceGen {
if (line.StartsWith(TAG_CMD)) {
tag = ParseTag(line);
} else if (line.StartsWith(MULTI_MASK_CMD)) {
if (!ParseMask(line, out multiMask)) {
if (!ParseMask(line, out multiMask, out string badMaskMsg)) {
report.Add(lineNum, FileLoadItem.NO_COLUMN, FileLoadItem.Type.Warning,
Res.Strings.ERR_INVALID_MASK);
badMaskMsg);
}
//Debug.WriteLine("Mask is now " + mask.ToString("x6"));
} else {
@ -268,12 +268,15 @@ namespace SourceGen {
/// <param name="line">Line to parse.</param>
/// <param name="multiMask">Parsed mask value, or null if the line was empty.</param>
/// <returns>True if the mask was parsed successfully.</returns>
private bool ParseMask(string line, out DefSymbol.MultiAddressMask multiMask) {
private bool ParseMask(string line, out DefSymbol.MultiAddressMask multiMask,
out string badMaskMsg) {
Debug.Assert(line.StartsWith(MULTI_MASK_CMD));
const int MIN = 0;
const int MAX = 0x00ffff;
badMaskMsg = Res.Strings.ERR_INVALID_MULTI_MASK;
multiMask = null;
string maskStr = line.Substring(MULTI_MASK_CMD.Length).Trim();
if (string.IsNullOrEmpty(maskStr)) {
// empty line, disable mask
@ -293,16 +296,34 @@ namespace SourceGen {
if (!Asm65.Number.TryParseInt(cmpMaskStr, out cmpMask, out ignoredBase) ||
cmpMask < MIN || cmpMask > MAX) {
Debug.WriteLine("Bad cmpMask: " + cmpMaskStr);
badMaskMsg = Res.Strings.ERR_INVALID_COMPARE_MASK;
return false;
}
if (!Asm65.Number.TryParseInt(cmpValueStr, out cmpValue, out ignoredBase) ||
cmpValue < MIN || cmpValue > MAX) {
Debug.WriteLine("Bad cmpValue: " + cmpValueStr);
badMaskMsg = Res.Strings.ERR_INVALID_COMPARE_VALUE;
return false;
}
if (!Asm65.Number.TryParseInt(addrMaskStr, out addrMask, out ignoredBase) ||
addrMask < MIN || addrMask > MAX) {
Debug.WriteLine("Bad addrMask: " + addrMaskStr);
badMaskMsg = Res.Strings.ERR_INVALID_ADDRESS_MASK;
return false;
}
// The two masks should not overlap: one represents bits that must be in a
// specific state for a match to exist, the other indicates which bits are used
// to select a specific register. This should be a warning.
if ((cmpMask & ~addrMask) != cmpMask) {
Debug.WriteLine("Warning: cmpMask/addrMask overlap");
badMaskMsg = Res.Strings.ERR_INVALID_CMP_ADDR_OVERLAP;
return false;
}
// If cmpValue has bits set that aren't in cmpMask, we will never find a match.
if ((cmpValue & ~cmpMask) != 0) {
Debug.WriteLine("cmpValue has unexpected bits set");
badMaskMsg = Res.Strings.ERR_INVALID_CMP_EXTRA_BITS;
return false;
}

View File

@ -61,9 +61,14 @@ limitations under the License.
<system:String x:Key="str_ErrFileNotFoundFmt">File not found: {0}</system:String>
<system:String x:Key="str_ErrFileReadFailedFmt">Failed reading {0}: {1}.</system:String>
<system:String x:Key="str_ErrFileReadOnlyFmt">Cannot write to read-only file {0}.</system:String>
<system:String x:Key="str_ErrInvalidAddressMask">Invalid MULTI_MASK AddressMask</system:String>
<system:String x:Key="str_ErrInvalidCmpAddrOverlap">MULTI_MASK CompareMask and AddressMask overlap</system:String>
<system:String x:Key="str_ErrInvalidCmpExtraBits">MULTI_MASK CompareValue has bits not in CompareMask</system:String>
<system:String x:Key="str_ErrInvalidCompareMask">Invalid MULTI_MASK CompareMask</system:String>
<system:String x:Key="str_ErrInvalidCompareValue">Invalid MULTI_MASK CompareValue</system:String>
<system:String x:Key="str_ErrInvalidIntValue">Could not convert value to integer</system:String>
<system:String x:Key="str_ErrInvalidKeyValue">Key value is out of range</system:String>
<system:String x:Key="str_ErrInvalidMask">Invalid mask value</system:String>
<system:String x:Key="str_ErrInvalidMultiMask">Invalid MULTI_MASK line</system:String>
<system:String x:Key="str_ErrInvalidWidth">Invalid width value</system:String>
<system:String x:Key="str_ErrInvalidSysdef" xml:space="preserve"> - INVALID DEFINITION</system:String>
<system:String x:Key="str_ErrLoadConfigFile">Unable to load config file</system:String>
@ -72,7 +77,7 @@ limitations under the License.
<system:String x:Key="str_ErrProjectLoadFail">Unable to load project file</system:String>
<system:String x:Key="str_ErrProjectSaveFail">Unable to save project file</system:String>
<system:String x:Key="str_ErrTooLargeForPreview">[File was too large for preview window]</system:String>
<system:String x:Key="str_ErrValueIncompatibleWithMask">Symbol value is incompatible with multi-mask</system:String>
<system:String x:Key="str_ErrValueIncompatibleWithMask">Symbol value is incompatible with current multi-mask</system:String>
<system:String x:Key="str_ExternalFileBadDirFmt" xml:space="preserve">Symbol files and extension scripts must live in the application runtime directory ({0}) or project directory ({1}).&#x0d;&#x0d;File {2} lives elsewhere.</system:String>
<system:String x:Key="str_ExternalFileBadDirCaption">File Not In Runtime Directory</system:String>
<system:String x:Key="str_FileFilterAll">All files (*.*)|*.*</system:String>

View File

@ -103,12 +103,22 @@ namespace SourceGen.Res {
(string)Application.Current.FindResource("str_ErrFileReadFailedFmt");
public static string ERR_FILE_READ_ONLY_FMT =
(string)Application.Current.FindResource("str_ErrFileReadOnlyFmt");
public static string ERR_INVALID_ADDRESS_MASK =
(string)Application.Current.FindResource("str_ErrInvalidAddressMask");
public static string ERR_INVALID_CMP_ADDR_OVERLAP =
(string)Application.Current.FindResource("str_ErrInvalidCmpAddrOverlap");
public static string ERR_INVALID_CMP_EXTRA_BITS =
(string)Application.Current.FindResource("str_ErrInvalidCmpExtraBits");
public static string ERR_INVALID_COMPARE_MASK =
(string)Application.Current.FindResource("str_ErrInvalidCompareMask");
public static string ERR_INVALID_COMPARE_VALUE =
(string)Application.Current.FindResource("str_ErrInvalidCompareValue");
public static string ERR_INVALID_INT_VALUE =
(string)Application.Current.FindResource("str_ErrInvalidIntValue");
public static string ERR_INVALID_KEY_VALUE =
(string)Application.Current.FindResource("str_ErrInvalidKeyValue");
public static string ERR_INVALID_MASK =
(string)Application.Current.FindResource("str_ErrInvalidMask");
public static string ERR_INVALID_MULTI_MASK =
(string)Application.Current.FindResource("str_ErrInvalidMultiMask");
public static string ERR_INVALID_WIDTH =
(string)Application.Current.FindResource("str_ErrInvalidWidth");
public static string ERR_INVALID_SYSDEF =

View File

@ -27,12 +27,14 @@ matters.</p>
<p>Platform symbol files consist of comments, commands, and symbols.
Blank lines, and lines that begin with a semicolon (';'), are ignored. Lines
that begin with an asterisk ('*') are commands. Two are currently
that begin with an asterisk ('*') are commands. Three are currently
defined:</p>
<ul>
<li><code>*SYNOPSIS</code> - a short summary of the file contents.</li>
<li><code>*TAG</code> - a tag string to apply to all symbols that follow
in this file.</li>
<li><code>*MULTI_MASK</code> - specify a mask for symbols that appear
at multiple addresses.</li>
</ul>
<p>Tags can be used by extension scripts to identify a subset of symbols.
@ -44,30 +46,70 @@ are treated as untagged.</p>
<p>All other lines are symbols, which have the form:</p>
<pre>
label {=|@} value [width] [;comment]
LABEL {=|@|&lt;|&gt;} VALUE [WIDTH] [;COMMENT]
</pre>
<p>Labels must be at least two characters long, begin with a letter or
<p>The LABEL must be at least two characters long, begin with a letter or
underscore, and consist entirely of alphanumeric ASCII characters
(A-Z, a-z, 0-9) and the underscore ('_'). (This is the same format
required for line labels in SourceGen.)</p>
<p>Use '@' for address values, and '=' for constants. The only important
difference between them is that address values will be applied automatically
to operands that reference addresses outside the scope of the file.
Constants are never applied automatically.</p>
<p>The next token can be one of:</p>
<ul>
<li>@: general addresses</li>
<li>&lt;: read-only addresses</li>
<li>&gt;: write-only addresses</li>
<li>=: constants</li>
</ul>
<p>If an instruction references an address, and that address is outside
the bounds of the file, the list of address symbols (i.e. everything
that's not a constant) will be scanned for a match.
If found, the symbol is applied automatically. You normally want to
use '@', but can use '&lt;' and '&gt;' for memory-mapped I/O locations
that have different behavior depending on whether they are read or
written.</p>
<p>The value is a number in decimal, hexadecimal (with a leading '$'), or
<p>The VALUE is a number in decimal, hexadecimal (with a leading '$'), or
binary (with a leading '%'). The numeric base will be recorded and used when
formatting the symbol in generated output, so use whichever form is most
appropriate. Values are unsigned 24-bit numbers.</p>
<p>The width is optional, and ignored for constants. It must be a
<p>The WIDTH is optional, and ignored for constants. It must be a
decimal or hexadecimal value between 1 and 65536, inclusive. If omitted,
the default width is 1.</p>
<p>The comment is optional. If present, it will be saved and used as the
<p>The COMMENT is optional. If present, it will be saved and used as the
end-of-line comment on the .EQ directive if the symbol is used.</p>
<h4>Using MULTI_MASK</h4>
<p>The multi-address mask is used for systems like the Atari 2600, where
RAM, ROM, and I/O registers appear at multiple addresses. The hardware
looks for certain address lines to be set or clear, and if the pattern
matches, another set of bits is examined to determine which register or
RAM address is being accessed.</p>
<p>For example, suppose the access pattern for a set of registers is
<code>???0 ??1? 1??x xxxx</code> (where '?' can be any value, 0/1 must
be that value, and 'x' means the bit is used to determine the register).
So any value between $0280-029f matches, as does $23c0-23df, but
$0480 and $1280 don't. The register number is found in the low five bits.</p>
<p>The corresponding MULTI_MASK line, with values specifed in binary,
would be:</p>
<pre>*MULTI_MASK %0001001010000000 %0000001010000000 %0000000000011111</pre>
<p>The values are CompareMask, CompareValue, and AddressMask. To
determine if an address is in the register set, we check to see if
<code>(address &amp; CompareMask) == CompareValue</code>. If so, we can
extract the register number with <code>(address &amp; AddressMask)</code>.</p>
<p>We don't want to have a huge collection of equates at the top of the
file, so whatever value is used in the symbol declaration is considered
the "canonical" value. All other matching values are expressed as an
offset.</p>
<p>All values must fall between 0 and $00FFFFFF. The set bits in
CompareMask and AddressMask must not overlap, and CompareValue must not
have any bits set that aren't also set in CompareMask.</p>
<h3>Creating a Project-Specific Symbol File</h3>
<p>To create a platform symbol file for your project, just create a new

View File

@ -295,6 +295,11 @@ to the note in the code list and in the "Notes" window.</p>
<h2><a name="project-symbol">Edit Project Symbol</a></h2>
<p>This is used to edit the properties of a project symbol.</p>
<p>Symbols marked as "address" will be applied automatically when an
operand references an address outside the scope of the data file. They
will not be applied to addresses inside the data file. Symbols
marked as "constant" are not applied automatically, and must be
explicitly specified as an operand.</p>
<p>The label must meet the criteria for symbols (see
<a href="intro.html#about-symbols">All About Symbols</a>), and must
not have the same name as another project symbol. It can overlap
@ -302,19 +307,17 @@ with platform symbols and user labels.</p>
<p>The value may be entered in decimal, hexadecimal, or binary. The numeric
base you choose will be remembered, so that the value will be displayed
the same way when used in a .EQ directive.</p>
<p>You can optionally provide a width. For example, if the address is
of a two-byte pointer or a 64-byte buffer, you would set the width field
to cause all references to any location in that range to be set to the
symbol. Widths may be entered in hex or decimal. If the field
is left blank, a width of 1 is assumed. Overlapping symbols are allowed.
The width is ignored for constants.</p>
<p>You can optionally provide a width for address symbols. For example,
if the address is of a two-byte pointer or a 64-byte buffer, you would
set the width field to cause all references to any location in that range
to be set to the symbol. Widths may be entered in hex or decimal. If
the field is left blank, a width of 1 is assumed. Overlapping symbols
are allowed. The width is ignored for constants.</p>
<p>If you enter a comment, it will be placed at the end of the line of
the .EQ directive.</p>
<p>Symbols marked as "address" will be applied automatically when an
operand references an address outside the scope of the data file. They
will not be applied to addresses inside the data file. Symbols
marked as "constant" are not applied automatically, and must be
explicitly specified as an operand.</p>
<p>For address symbols that represent a memory-mapped I/O location, it
can be useful to have different symbols for reads and writes. Use
the Read/Write checkboxes to specify the desired behavior.</p>
<h2><a name="lvtable">Create/Edit Local Variable Table</a></h2>

View File

@ -144,6 +144,15 @@ instructions. If you don't know what state the flags are in, you can't
know whether <code>LDA #value</code> is two bytes or three, and the
disassembly of the instruction stream will come out wrong.</p>
<p>Some addresses correspond to memory-mapped I/O, rather than RAM or ROM.
Accessing the address can have side effects, like changing between text
and graphics modes. Sometimes reading and writing have different effects.
For example, on later models of the Apple II, reading from
$C000 returns the most recently hit key, while writing to $C000 disables
80 columns.</p>
<p>On a few systems, such as the Atari 2600, RAM, ROM, and registers can
appear at multiple locations, "mirrored" across the address space.</p>
<h3><a name="charenc">Character Encoding</a></h3>
<p>The American Standard Code for Information Interchange (ASCII) was
@ -459,6 +468,12 @@ a 4-byte symbol in the middle of a 256-byte symbol, the 4-byte symbol will
be visible because the start point is closer to the addresses it covers
than the start of the 256-byte range.</p>
<p>Platform symbols can be designated for reading, writing, or both.
Normally you'd want both, but if an address is a memory-mapped I/O
location that has different behavior for reads and writes, you'd want
to define two different symbols, and have the correct one applied
based on the access type.</p>
<p><b>Project symbols</b> behave like platform symbols, but they are
defined in the project file itself. The editor will prevent you from
creating two symbols with the same name. If two symbols have the same

View File

@ -53,3 +53,53 @@ BankWrap @ $fff0 $20
; Width specifiers on constants should be ignored.
FatConst = $4000 8
; I/O direction test
ReadOnly < $5000 2 ;R
WriteOnly > $5001 2 ;W
;
; MULTI_MASK tests.
;
; The behavior of overlapping masks is not currently defined, so we don't test
; that scenario.
;
; overlaps with multi range in second symbol file
AlsoMoreMultiZero @ $c110 ;winner
*MULTI_MASK $ff00 $c000 $000f ;$c000-c00f, repeats $c010-c01f, etc. to $c0ff
MultiZero @ $c000
AlsoMultiZero @ $c010 ;wins (alphabetically)
MultiOne @ $c021
; Test: C000, C010, C020, C0F0
; Test: C001, C011, C021
; Test: C002, C012, C022
MultiRead < $c004 3 ;$c004/5/6, read-only
MultiWrite > $c005 3 ;$c005/6/7, write-only
; Test: read C003 C004 C005 C006 C007
; Test: write C004 C005 C006 C007 C008
;
; Invalid values. These cause a warning at load time, and the symbol will
; be ignored.
;
; Not in range.
MultiInvalid @ $1234
; Not all covered addresses are inside the masked range.
TooLong @ $c0f8 $a
;
; Badly-formed MULTI_MASK entries. These cause a warning at load time, and
; the directive will be ignored.
;
*MULTI_MASK $fffff $ffff $ffff ;range
*MULTI_MASK $ffff $fffff $ffff ;range
*MULTI_MASK $ffff $ffff $fffff ;range
*MULTI_MASK

View File

@ -11,3 +11,31 @@ SameValB_A @ $2110
SameValC_B @ $2120
SepOver1 @ $3100 4 ;$3100-3103, inclusive
; I/O direction test -- replace part of the write-only range
WriteOnly2 > $5002
;
; MULTI_MASK tests.
;
; This overlaps with an earlier declaration, but *only* for address $c010,
; not for all occurrences.
NonMultiOver @ $c010 ;winner
*MULTI_MASK $ff00 $c100 $000f ;$c100-c10f, repeats $c110-c11f, etc. to $c1ff
; Symbol in previous file overlaps with this.
; Test: C100, C110, C120
MoreMultiZero @ $c100
;
; More erroneous masks. These are in a separate file mostly to test how
; errors in multiple files are reported.
;
*MULTI_MASK $fff0 $000f $000f ;CompareValue has bits not in CompareMask
*MULTI_MASK $fff0 $fff0 $00ff ;AddressMask and CompareMask overlap
*MULTI_MASK

View File

@ -1,6 +1,6 @@
### 6502bench SourceGen dis65 v1.0 ###
{
"_ContentVersion":2,"FileDataLength":222,"FileDataCrc32":-233099313,"ProjectProps":{
"_ContentVersion":2,"FileDataLength":329,"FileDataCrc32":-573118187,"ProjectProps":{
"CpuName":"6502","IncludeUndocumentedInstr":false,"EntryFlags":32702671,"AutoLabelStyle":"Simple","AnalysisParams":{
"AnalyzeUncategorizedData":true,"DefaultTextScanMode":"LowHighAscii","MinCharsForString":4,"SeekNearbyTargets":true,"SmartPlpHandling":true},
"PlatformSymbolFileIdentifiers":["PROJ:2021-external-symbols-1.sym65","PROJ:2021-external-symbols-2.sym65","PROJ:2021-external-symbols-3.sym65"],"ExtensionScriptFileIdentifiers":[],"ProjectSyms":{

View File

@ -18,15 +18,25 @@ Over2a = $3006 ;$3006
Over3 = $3006 ;$3006-300c
SepOver1 = $3100 ;$3100-3103, inclusive
SepOver2 = $3102 ;$3102-3105, inclusive
ReadOnly = $5000 ;R
WriteOnly = $5001 ;W
WriteOnly2 = $5002
MultiRead = $c004 ;$c004/5/6, read-only
MultiWrite = $c005 ;$c005/6/7, write-only
AlsoMultiZero = $c010 ;wins (alphabetically)
NonMultiOver = $c010 ;winner
MultiOne = $c021
MoreMultiZero = $c100
AlsoMoreMultiZero = $c110 ;winner
BankWrap = $fff0
* = $1000
L1000 lda CodeWrap+255
ldx L1000
ldy L1000+1
lda L10DD
lda CodeWrap+478
lda CodeWrap+485
lda L1148
lda CodeWrap+585
lda CodeWrap+592
nop
lda $1ffe
lda SameName1-1
@ -103,5 +113,46 @@ LocalVar .var $41
lda $4001
lda BankWrap+8
lda <BankWrap-232
L10DD rts
nop
lda ReadOnly
lda ReadOnly+1
ldx $5002
ldy $5003
sta WriteOnly-1
sta WriteOnly
stx WriteOnly2
sty $5003
nop
bit AlsoMultiZero-16
bit NonMultiOver
bit AlsoMultiZero+16
bit AlsoMultiZero+224
nop
bit MultiOne-32
bit MultiOne-16
bit MultiOne
nop
bit $c002
bit $c012
bit $c022
nop
lda MultiRead-1
lda MultiRead
lda MultiRead+1
lda MultiRead+2
lda $c007
sta MultiWrite-1
sta MultiWrite
sta MultiWrite+1
sta MultiWrite+2
sta $c008
nop
jsr MultiRead+1
nop
bit MoreMultiZero
bit AlsoMoreMultiZero
bit MoreMultiZero+32
bit MoreMultiZero+240
nop
L1148 rts

View File

@ -17,15 +17,25 @@ Over2a equ $3006 ;$3006
Over3 equ $3006 ;$3006-300c
SepOver1 equ $3100 ;$3100-3103, inclusive
SepOver2 equ $3102 ;$3102-3105, inclusive
ReadOnly equ $5000 ;R
WriteOnly equ $5001 ;W
WriteOnly2 equ $5002
MultiRead equ $c004 ;$c004/5/6, read-only
MultiWrite equ $c005 ;$c005/6/7, write-only
AlsoMultiZero equ $c010 ;wins (alphabetically)
NonMultiOver equ $c010 ;winner
MultiOne equ $c021
MoreMultiZero equ $c100
AlsoMoreMultiZero equ $c110 ;winner
BankWrap equ $fff0
org $1000
L1000 lda CodeWrap+255
ldx L1000
ldy L1000+1
lda L10DD
lda CodeWrap+478
lda CodeWrap+485
lda L1148
lda CodeWrap+585
lda CodeWrap+592
nop
lda $1ffe
lda SameName1-1
@ -102,5 +112,46 @@ L1000 lda CodeWrap+255
lda $4001
lda BankWrap+8
lda <BankWrap-65512
L10DD rts
nop
lda ReadOnly
lda ReadOnly+1
ldx $5002
ldy $5003
sta WriteOnly-1
sta WriteOnly
stx WriteOnly2
sty $5003
nop
bit AlsoMultiZero-16
bit NonMultiOver
bit AlsoMultiZero+16
bit AlsoMultiZero+224
nop
bit MultiOne-32
bit MultiOne-16
bit MultiOne
nop
bit $c002
bit $c012
bit $c022
nop
lda MultiRead-1
lda MultiRead
lda MultiRead+1
lda MultiRead+2
lda $c007
sta MultiWrite-1
sta MultiWrite
sta MultiWrite+1
sta MultiWrite+2
sta $c008
nop
jsr MultiRead+1
nop
bit MoreMultiZero
bit AlsoMoreMultiZero
bit MoreMultiZero+32
bit MoreMultiZero+240
nop
L1148 rts

View File

@ -18,15 +18,25 @@ Over2a = $3006 ;$3006
Over3 = $3006 ;$3006-300c
SepOver1 = $3100 ;$3100-3103, inclusive
SepOver2 = $3102 ;$3102-3105, inclusive
ReadOnly = $5000 ;R
WriteOnly = $5001 ;W
WriteOnly2 = $5002
MultiRead = $c004 ;$c004/5/6, read-only
MultiWrite = $c005 ;$c005/6/7, write-only
AlsoMultiZero = $c010 ;wins (alphabetically)
NonMultiOver = $c010 ;winner
MultiOne = $c021
MoreMultiZero = $c100
AlsoMoreMultiZero = $c110 ;winner
BankWrap = $fff0
* = $1000
L1000 lda CodeWrap+255
ldx L1000
ldy L1000+1
lda L10DD
lda CodeWrap+478
lda CodeWrap+485
lda L1148
lda CodeWrap+585
lda CodeWrap+592
nop
lda $1ffe
lda SameName1-1
@ -104,5 +114,46 @@ L1000 lda CodeWrap+255
lda $4001
lda BankWrap+8
lda <BankWrap-232
L10DD rts
nop
lda ReadOnly
lda ReadOnly+1
ldx $5002
ldy $5003
sta WriteOnly-1
sta WriteOnly
stx WriteOnly2
sty $5003
nop
bit AlsoMultiZero-16
bit NonMultiOver
bit AlsoMultiZero+16
bit AlsoMultiZero+224
nop
bit MultiOne-32
bit MultiOne-16
bit MultiOne
nop
bit $c002
bit $c012
bit $c022
nop
lda MultiRead-1
lda MultiRead
lda MultiRead+1
lda MultiRead+2
lda $c007
sta MultiWrite-1
sta MultiWrite
sta MultiWrite+1
sta MultiWrite+2
sta $c008
nop
jsr MultiRead+1
nop
bit MoreMultiZero
bit AlsoMoreMultiZero
bit MoreMultiZero+32
bit MoreMultiZero+240
nop
L1148 rts

View File

@ -18,6 +18,16 @@ Over2a = $3006 ;$3006
Over3 = $3006 ;$3006-300c
SepOver1 = $3100 ;$3100-3103, inclusive
SepOver2 = $3102 ;$3102-3105, inclusive
ReadOnly = $5000 ;R
WriteOnly = $5001 ;W
WriteOnly2 = $5002
MultiRead = $c004 ;$c004/5/6, read-only
MultiWrite = $c005 ;$c005/6/7, write-only
AlsoMultiZero = $c010 ;wins (alphabetically)
NonMultiOver = $c010 ;winner
MultiOne = $c021
MoreMultiZero = $c100
AlsoMoreMultiZero = $c110 ;winner
BankWrap = $fff0
; .segment "SEG000"
@ -25,9 +35,9 @@ BankWrap = $fff0
L1000: lda CodeWrap+255
ldx L1000
ldy L1000+1
lda L10DD
lda CodeWrap+478
lda CodeWrap+485
lda L1148
lda CodeWrap+585
lda CodeWrap+592
nop
lda $1ffe
lda SameName1-1
@ -104,5 +114,46 @@ LocalVar .set $41
lda $4001
lda BankWrap+8
lda <BankWrap-232
L10DD: rts
nop
lda ReadOnly
lda ReadOnly+1
ldx $5002
ldy $5003
sta WriteOnly-1
sta WriteOnly
stx WriteOnly2
sty $5003
nop
bit AlsoMultiZero-16
bit NonMultiOver
bit AlsoMultiZero+16
bit AlsoMultiZero+224
nop
bit MultiOne-32
bit MultiOne-16
bit MultiOne
nop
bit $c002
bit $c012
bit $c022
nop
lda MultiRead-1
lda MultiRead
lda MultiRead+1
lda MultiRead+2
lda $c007
sta MultiWrite-1
sta MultiWrite
sta MultiWrite+1
sta MultiWrite+2
sta $c008
nop
jsr MultiRead+1
nop
bit MoreMultiZero
bit AlsoMoreMultiZero
bit MoreMultiZero+32
bit MoreMultiZero+240
nop
L1148: rts

View File

@ -1,7 +1,7 @@
# 6502bench SourceGen generated linker script for 2021-external-symbols
MEMORY {
MAIN: file=%O, start=%S, size=65536;
# MEM000: file=%O, start=$1000, size=222;
# MEM000: file=%O, start=$1000, size=329;
}
SEGMENTS {
CODE: load=MAIN, type=rw;

View File

@ -117,4 +117,53 @@ Start lda Start-1 ;CodeWrap+255
lda $fff8 ;should be BankWrap+8
lda $08 ;should be BankWrap+24 or <BankWrap-232
nop
; test I/O direction
Dir equ $5000
lda Dir
lda Dir+1
ldx Dir+2
ldy Dir+3
sta Dir
sta Dir+1
stx Dir+2
sty Dir+3
nop
; test MULTI_MASK stuff
bit $c000 ;should all be AlsoMultiZero
bit $c010 ;<-- except this NonMultiOver
bit $c020
bit $c0f0
nop
bit $c001 ;should all be MultiOne
bit $c011
bit $c021
nop
bit $c002 ;should all be hex
bit $c012
bit $c022
nop
lda $c003
lda $c004 ;MultiRead
lda $c005 ;MultiRead+1
lda $c006 ;MultiRead+2
lda $c007
sta $c004
sta $c005 ;MultiWrite
sta $c006 ;MultiWrite+1
sta $c007 ;MultiWrite+2
sta $c008
nop
jsr $c005 ;MultiRead+1
nop
bit $c100 ;should all be MoreMultiZero
bit $c110 ;<-- except this AlsoMoreMultiZero
bit $c120
bit $c1f0
nop
END rts