mirror of
https://github.com/fadden/6502bench.git
synced 2024-12-03 05:49:48 +00:00
Fix 64tass code gen corner case
On the 65816, if you say "JSR foo" from bank $12, but "foo" is an address in bank 0, most assemblers will conclude that you're forming a 16-bit argument with a 16-bit address and assemble happily. 64tass halts with an error. Up until v1.55 or so, you could fake it out by supplying a large offset. This no longer works. The preferred way to say "no really I mean to do this" is to append ",k" to the operand. We now do that as needed. I didn't want to define a new ExpressionMode for 64tass just to support an operand modifier that should probably never actually get generated (you can't call across banks with JSR!), so this is implemented with a quirk and an op flag. 64tass v1.56.2625 is now the default. (issue #104)
This commit is contained in:
parent
19ba34760b
commit
478afa542e
@ -127,6 +127,7 @@ namespace SourceGen.AsmGen {
|
||||
|
||||
// Version we're coded against.
|
||||
private static CommonUtil.Version V1_53 = new CommonUtil.Version(1, 53, 1515);
|
||||
private static CommonUtil.Version V1_56 = new CommonUtil.Version(1, 56, 2625);
|
||||
|
||||
// Pseudo-op string constants.
|
||||
private static PseudoOp.PseudoOpNames sDataOpNames =
|
||||
@ -178,13 +179,14 @@ namespace SourceGen.AsmGen {
|
||||
if (asmVersion != null) {
|
||||
mAsmVersion = asmVersion.Version; // Use the actual version.
|
||||
} else {
|
||||
mAsmVersion = V1_53; // No assembler installed, use default.
|
||||
mAsmVersion = V1_56; // No assembler installed, use default.
|
||||
}
|
||||
|
||||
Quirks.StackIntOperandIsImmediate = true;
|
||||
Quirks.LeadingUnderscoreSpecial = true;
|
||||
Quirks.Need24BitsForAbsPBR = true;
|
||||
Quirks.BitNumberIsArg = true;
|
||||
Quirks.BankZeroAbsPBRRestrict = true;
|
||||
|
||||
mWorkDirectory = workDirectory;
|
||||
mFileNameBase = fileNameBase;
|
||||
|
@ -215,7 +215,8 @@ namespace SourceGen.AsmGen {
|
||||
|
||||
string formattedOperand = null;
|
||||
int operandLen = instrLen - 1;
|
||||
PseudoOp.FormatNumericOpFlags opFlags = PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix;
|
||||
PseudoOp.FormatNumericOpFlags opFlags =
|
||||
PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix;
|
||||
bool isPcRelBankWrap = false;
|
||||
|
||||
// Tweak branch instructions. We want to show the absolute address rather
|
||||
@ -243,6 +244,11 @@ namespace SourceGen.AsmGen {
|
||||
if (op.IsAbsolutePBR) {
|
||||
opFlags |= PseudoOp.FormatNumericOpFlags.IsAbsolutePBR;
|
||||
}
|
||||
if (gen.Quirks.BankZeroAbsPBRRestrict) {
|
||||
// Hack to avoid having to define a new FormatConfig.ExpressionMode for 64tass.
|
||||
// Get rid of this 64tass gets its own exp mode.
|
||||
opFlags |= PseudoOp.FormatNumericOpFlags.Is64Tass;
|
||||
}
|
||||
|
||||
// 16-bit operands outside bank 0 need to include the bank when computing
|
||||
// symbol adjustment.
|
||||
|
@ -207,6 +207,13 @@ namespace SourceGen.AsmGen {
|
||||
/// Enumeration of quirky or buggy behavior that GenCommon needs to handle.
|
||||
/// </summary>
|
||||
public class AssemblerQuirks {
|
||||
/// <summary>
|
||||
/// Does the assembler require a qualifier to be added to the operand when an instruction
|
||||
/// formed with the Program Bank Register (JMP/JSR) attempts to access a bank zero
|
||||
/// address from outside bank zero?
|
||||
/// </summary>
|
||||
public bool BankZeroAbsPBRRestrict { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Does the assembler expect the bit index for BBR/BBS/RMB/SMB to be expressed as
|
||||
/// a separate argument?
|
||||
|
@ -562,6 +562,7 @@ namespace SourceGen {
|
||||
IsAbsolutePBR = 1 << 1, // operand implicitly uses 'K' on 65816 (JMP/JSR)
|
||||
HasHashPrefix = 1 << 2, // operand has a leading '#', reducing ambiguity
|
||||
OmitLabelPrefixSuffix = 1 << 3, // don't show annotation char or non-unique prefix
|
||||
Is64Tass = 1 << 4, // hack to allow 64tass to keep using "common" exp
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -798,6 +799,7 @@ namespace SourceGen {
|
||||
symbolValue &= 0xffff;
|
||||
}
|
||||
|
||||
bool needCommaK = false;
|
||||
if ((flags & FormatNumericOpFlags.IsAbsolutePBR) != 0) {
|
||||
if ((operandValue & 0x00ff0000) == (symbolValue & 0x00ff0000)) {
|
||||
// JMP or JSR to something within the same bank. We don't need to
|
||||
@ -805,10 +807,16 @@ namespace SourceGen {
|
||||
symbolValue &= 0xffff;
|
||||
} else {
|
||||
// This is an absolute JMP/JSR to an out-of-bank location, which is
|
||||
// bogus and should probably be prevented at a higher level. We handle
|
||||
// it by altering the mask so an adjustment that covers the difference
|
||||
// in bank values is generated.
|
||||
mask = 0x00ffffff;
|
||||
// bogus and should probably be prevented at a higher level. Most
|
||||
// assemblers are perfectly happy with this because we're passing a
|
||||
// 16-bit argument to a 16-bit operation, but 64tass doesn't like it
|
||||
// when you do this. We used to just alter the mask to generate a
|
||||
// (potentially very large) offset, but 64tass stopped accepting that.
|
||||
// The correct approach is to add ",k" to the operand.
|
||||
//mask = 0x00ffffff;
|
||||
if ((flags & FormatNumericOpFlags.Is64Tass) != 0) {
|
||||
needCommaK = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -863,6 +871,10 @@ namespace SourceGen {
|
||||
if (sb[0] == '(' && (flags & FormatNumericOpFlags.HasHashPrefix) == 0) {
|
||||
sb.Insert(0, "0+");
|
||||
}
|
||||
|
||||
if (needCommaK) {
|
||||
sb.Append(",k");
|
||||
}
|
||||
} else {
|
||||
Debug.Assert(false, "bad numeric len");
|
||||
sb.Append("?????");
|
||||
|
@ -166,7 +166,7 @@ code, but also needs to know how to handle the corner cases.</p>
|
||||
|
||||
<h3><a name="64tass">64tass</a></h3>
|
||||
|
||||
<p>Tested versions: v1.53.1515, v1.54.1900
|
||||
<p>Tested versions: v1.53.1515, v1.54.1900, v1.56.2625
|
||||
<a href="https://sourceforge.net/projects/tass64/">[web site]</a></p>
|
||||
|
||||
<p>Bugs:</p>
|
||||
@ -202,7 +202,9 @@ code, but also needs to know how to handle the corner cases.</p>
|
||||
65816 Program Bank Register (16-bit JMP/JSR) must be specified
|
||||
as 24-bit values for code that lives outside bank 0. This is
|
||||
true for both symbols and raw hex (e.g. <code>JSR $1234</code>
|
||||
is invalid outside bank 0).</li>
|
||||
is invalid outside bank 0). Attempting to JSR to a label in bank
|
||||
0 from outside bank 0 causes an error, even though it is technically
|
||||
a 16-bit operand.</li>
|
||||
<li>The arguments to COP and BRK require immediate-mode syntax
|
||||
(<code>COP #$03</code> rather than <code>COP $03</code>).
|
||||
<li>For historical reasons, the default behavior of the assembler is to
|
||||
|
Binary file not shown.
@ -1,8 +1,8 @@
|
||||
### 6502bench SourceGen dis65 v1.0 ###
|
||||
{
|
||||
"_ContentVersion":4,
|
||||
"FileDataLength":238,
|
||||
"FileDataCrc32":2077431201,
|
||||
"FileDataLength":266,
|
||||
"FileDataCrc32":-1640516088,
|
||||
"ProjectProps":{
|
||||
"CpuName":"65816",
|
||||
"IncludeUndocumentedInstr":false,
|
||||
@ -264,6 +264,54 @@
|
||||
"SubFormat":"Symbol",
|
||||
"SymbolRef":{
|
||||
"Label":"skip",
|
||||
"Part":"Low"}},
|
||||
|
||||
"233":{
|
||||
"Length":3,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Symbol",
|
||||
"SymbolRef":{
|
||||
"Label":"skip",
|
||||
"Part":"Low"}},
|
||||
|
||||
"236":{
|
||||
"Length":3,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Symbol",
|
||||
"SymbolRef":{
|
||||
"Label":"skip",
|
||||
"Part":"Low"}},
|
||||
|
||||
"239":{
|
||||
"Length":3,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Symbol",
|
||||
"SymbolRef":{
|
||||
"Label":"skip",
|
||||
"Part":"Low"}},
|
||||
|
||||
"242":{
|
||||
"Length":3,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Symbol",
|
||||
"SymbolRef":{
|
||||
"Label":"skip",
|
||||
"Part":"Low"}},
|
||||
|
||||
"245":{
|
||||
"Length":3,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Symbol",
|
||||
"SymbolRef":{
|
||||
"Label":"skip",
|
||||
"Part":"Low"}},
|
||||
|
||||
"250":{
|
||||
"Length":3,
|
||||
"Format":"NumericLE",
|
||||
"SubFormat":"Symbol",
|
||||
"SymbolRef":{
|
||||
"Label":"skip",
|
||||
"Part":"Low"}}},
|
||||
|
||||
"LvTables":{
|
||||
|
@ -107,7 +107,7 @@ fwdchk nop
|
||||
nop
|
||||
rts
|
||||
|
||||
L543280 jsr skip+$540000
|
||||
L543280 jsr skip,k
|
||||
nop
|
||||
rep #$30
|
||||
.al
|
||||
@ -132,8 +132,20 @@ L543280 jsr skip+$540000
|
||||
lda #$eaea
|
||||
rep #$30
|
||||
nop
|
||||
jsr $54edcb
|
||||
nop
|
||||
lda skip
|
||||
lda skip+20
|
||||
jsr skip,k
|
||||
jsr skip+20,k
|
||||
jsr (skip,k,x)
|
||||
bne _L5432B7
|
||||
jmp (skip,k,x)
|
||||
|
||||
_L5432B7 jsr $54edcb
|
||||
lda $edcb
|
||||
bne _L5432C2
|
||||
jmp ($54edcb,x)
|
||||
|
||||
_L5432C2 nop
|
||||
rtl
|
||||
|
||||
.here
|
||||
|
@ -8,5 +8,6 @@
|
||||
!hex 1632201732201832207d32207e32207f32eaa200fc1932fc7a32206e32207132
|
||||
!hex 206832206b3220743220773280187c19327c7a326c08106c0810dc0810dc0810
|
||||
!hex 7d3254eaea60200e20eac23008a90000e230a90028a9eaeae23008a900c230a9
|
||||
!hex 000028a9eaeac230ea20cbedea6b
|
||||
!hex 000028a9eaeac230eaad0e20ad2220200e20202220fc0e20d0037c0e2020cbed
|
||||
!hex adcbedd0037ccbedea6b
|
||||
} ;!pseudopc
|
||||
|
@ -134,7 +134,19 @@ L543280: jsr skip
|
||||
lda #$eaea
|
||||
rep #$30
|
||||
nop
|
||||
jsr $edcb
|
||||
nop
|
||||
lda skip
|
||||
lda skip+20
|
||||
jsr skip
|
||||
jsr skip+20
|
||||
jsr (skip,x)
|
||||
bne @L5432B7
|
||||
jmp (skip,x)
|
||||
|
||||
@L5432B7: jsr $edcb
|
||||
lda $edcb
|
||||
bne @L5432C2
|
||||
jmp ($edcb,x)
|
||||
|
||||
@L5432C2: nop
|
||||
rtl
|
||||
|
||||
|
@ -5,7 +5,7 @@ MEMORY {
|
||||
# MEM001: file=%O, start=$440000, size=28;
|
||||
# MEM002: file=%O, start=$44ffc0, size=15;
|
||||
# MEM003: file=%O, start=$2000, size=32;
|
||||
# MEM004: file=%O, start=$543210, size=152;
|
||||
# MEM004: file=%O, start=$543210, size=180;
|
||||
}
|
||||
SEGMENTS {
|
||||
CODE: load=MAIN, type=rw;
|
||||
|
@ -123,7 +123,19 @@ L543280 jsr skip
|
||||
lda #$eaea
|
||||
rep #$30
|
||||
nop
|
||||
jsr $edcb
|
||||
nop
|
||||
lda skip
|
||||
lda skip+20
|
||||
jsr skip
|
||||
jsr skip+20
|
||||
jsr (skip,x)
|
||||
bne :L5432B7
|
||||
jmp (skip,x)
|
||||
|
||||
:L5432B7 jsr $edcb
|
||||
lda $edcb
|
||||
bne :L5432C2
|
||||
jmp ($edcb,x)
|
||||
|
||||
:L5432C2 nop
|
||||
rtl
|
||||
|
||||
|
@ -6,7 +6,7 @@ NOTE: some tests may fail if you use a version of the assembler that is
|
||||
different from the one used to generate the expected output. The current
|
||||
set was generated for:
|
||||
|
||||
* 64tass v1.53.1515
|
||||
* 64tass v1.56.2625
|
||||
* ACME v0.97
|
||||
* cc65 v2.18
|
||||
* Merlin 32 v1.0
|
||||
|
@ -2,7 +2,7 @@
|
||||
; See the LICENSE.txt file for distribution terms (Apache 2.0).
|
||||
;
|
||||
; Assembler: cc65
|
||||
; (cl65 --target none -C <cfg>.cfg <src>.S)
|
||||
; cl65 --target none -C 20052-branches-and-banks.cfg 20052-branches-and-banks.S
|
||||
;
|
||||
; For the 65816 we want to exercise some additional things.
|
||||
|
||||
@ -169,8 +169,22 @@ nxt54b:
|
||||
.i16
|
||||
nop
|
||||
|
||||
; try a 16-bit JSR with no symbol
|
||||
; try some 16-bit stuff with and without symbols
|
||||
lda skip ;EDIT: set these to "skip" label
|
||||
lda skip+20
|
||||
jsr skip
|
||||
jsr skip+20
|
||||
jsr (skip,X)
|
||||
bne past1
|
||||
jmp (skip,X)
|
||||
past1:
|
||||
|
||||
; try a few without symbols
|
||||
jsr $edcb
|
||||
lda $edcb
|
||||
bne past2
|
||||
jmp ($edcb,X)
|
||||
past2:
|
||||
nop
|
||||
|
||||
rtl
|
||||
|
Loading…
Reference in New Issue
Block a user