Fix 65816 operand formatting issues

Some 16-bit operands are tracked internally as 24-bit, appending the
B (data bank) or K (program bank) register to form the full address.
For some assemblers the K-bank instructions must be output as 24-bit
values, even for 16-bit JMP/JSR, but for most we want to strip the
bank byte off before outputting the operand as hex or decimal.

This expands 20032-labels-and-symbols with a mix of 24-bit, 16-bit+B,
and 16-bit+K instructions formatted in various ways.  No existing
tests were affected by this change.

(issue #172)
This commit is contained in:
Andy McFadden committed 2025-07-19 13:39:12 -07:00
1 parent 4846a26c9a
commit c70d015b00
8 files changed
+481 -16

No files matched your search

+29 -13
View File
@@ -636,25 +636,21 @@ namespace SourceGen {
case FormatDescriptor.SubType.None:
case FormatDescriptor.SubType.Hex:
case FormatDescriptor.SubType.Address:
if ((formatter.ExpressionMode == Formatter.FormatConfig.ExpressionMode.Cc65 ||
formatter.ExpressionMode == Formatter.FormatConfig.ExpressionMode.Merlin) &&
(flags & FormatNumericOpFlags.IsAbsolutePBR) != 0) {
// cc65 really doesn't like 24-bit values for JMP/JSR. If it sees a
// 24-bit hex constant it emits JML/JSL. Merlin works either way, and
// I think it looks better as a 16-bit value.
operandValue &= 0xffff;
}
return formatter.FormatHexValue(operandValue, hexMinLen);
return formatter.FormatHexValue(
StripBank(operandValue, operandLen, flags), hexMinLen);
case FormatDescriptor.SubType.Decimal:
return formatter.FormatDecimalValue(operandValue);
return formatter.FormatDecimalValue(StripBank(operandValue, operandLen, flags));
case FormatDescriptor.SubType.SignedDecimal:
if ((flags & FormatNumericOpFlags.AllowSignedDecimal) != 0) {
return formatter.FormatSignedDecimalValue(operandValue, operandLen);
return formatter.FormatSignedDecimalValue(
StripBank(operandValue, operandLen, flags), operandLen);
} else {
return formatter.FormatDecimalValue(operandValue);
return formatter.FormatDecimalValue(
StripBank(operandValue, operandLen, flags));
}
case FormatDescriptor.SubType.Binary:
return formatter.FormatBinaryValue(operandValue, hexMinLen * 4);
return formatter.FormatBinaryValue(
StripBank(operandValue, operandLen, flags), hexMinLen * 4);
case FormatDescriptor.SubType.Ascii:
case FormatDescriptor.SubType.HighAscii:
case FormatDescriptor.SubType.C64Petscii:
@@ -711,6 +707,26 @@ namespace SourceGen {
}
}
/// <summary>
/// Trims the bank byte off of 16-bit instruction operands. The bank byte wasn't part of
/// the original instruction; it was added by combining with B or K. Before displaying the
/// operand as hex/decimal/binary we want to shed the bank byte... usually. While cc65
/// requires a 16-bit value (it turns JSR to JSL otherwise), 64tass requires a 24-bit value
/// to confirm that you're calling code in the correct bank.
/// </summary>
private static int StripBank(int operandValue, int operandLen, FormatNumericOpFlags flags) {
if (operandLen != 2) {
// Not a 16-bit operand, don't mess with it.
return operandValue;
}
if ((flags & FormatNumericOpFlags.IsAbsolutePBR) != 0 &&
(flags & FormatNumericOpFlags.Is64Tass) != 0) {
// Generating code for 64tass JMP/JSR. Leave it alone.
return operandValue;
}
return operandValue & 0xffff;
}
/// <summary>
/// Format the symbol and adjustment using common expression syntax (ACME, 64tass).
/// </summary>
Binary file not shown.
@@ -1,8 +1,8 @@
### 6502bench SourceGen dis65 v1.0 ###
{
"_ContentVersion":6,
"FileDataLength":761,
"FileDataCrc32":1509582706,
"FileDataLength":878,
"FileDataCrc32":429430896,
"ProjectProps":{
"CpuName":"65816",
"IncludeUndocumentedInstr":false,
@@ -155,6 +155,33 @@
"PreLabel":"",
"DisallowInward":false,
"DisallowOutward":false,
"IsRelative":false},
{
"Offset":763,
"Addr":131088,
"Length":-1024,
"PreLabel":"",
"DisallowInward":false,
"DisallowOutward":false,
"IsRelative":false},
{
"Offset":764,
"Addr":16,
"Length":-1024,
"PreLabel":"",
"DisallowInward":false,
"DisallowOutward":false,
"IsRelative":false},
{
"Offset":765,
"Addr":139264,
"Length":-1024,
"PreLabel":"",
"DisallowInward":false,
"DisallowOutward":false,
"IsRelative":false}],
"TypeHints":[{
"Low":0,
@@ -268,6 +295,20 @@
"Value":135169,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"763":{
"Label":"testlow",
"Value":131088,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"},
"764":{
"Label":"testzp",
"Value":16,
"Source":"User",
"Type":"GlobalAddr",
"LabelAnno":"None"}},
"OperandFormats":{
@@ -1581,6 +1622,198 @@
"Label":"biggie",
"Part":"Bank"},
"Extra":null},
"794":{
"Length":4,
"Format":"NumericLE",
"SubFormat":"Symbol",
"SymbolRef":{
"Label":"biggie",
"Part":"Low"},
"Extra":null},
"798":{
"Length":4,
"Format":"NumericLE",
"SubFormat":"Symbol",
"SymbolRef":{
"Label":"biggie",
"Part":"Low"},
"Extra":null},
"802":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Symbol",
"SymbolRef":{
"Label":"biggie",
"Part":"Low"},
"Extra":null},
"805":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Symbol",
"SymbolRef":{
"Label":"ptest",
"Part":"Low"},
"Extra":null},
"808":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Symbol",
"SymbolRef":{
"Label":"ptest",
"Part":"Low"},
"Extra":null},
"811":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Symbol",
"SymbolRef":{
"Label":"testlow",
"Part":"Low"},
"Extra":null},
"814":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Symbol",
"SymbolRef":{
"Label":"testlow",
"Part":"Low"},
"Extra":null},
"817":{
"Length":2,
"Format":"NumericLE",
"SubFormat":"Symbol",
"SymbolRef":{
"Label":"testzp",
"Part":"Low"},
"Extra":null},
"820":{
"Length":4,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null,
"Extra":null},
"824":{
"Length":4,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null,
"Extra":null},
"828":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null,
"Extra":null},
"831":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null,
"Extra":null},
"834":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null,
"Extra":null},
"837":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null,
"Extra":null},
"840":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null,
"Extra":null},
"843":{
"Length":2,
"Format":"NumericLE",
"SubFormat":"Hex",
"SymbolRef":null,
"Extra":null},
"852":{
"Length":4,
"Format":"NumericLE",
"SubFormat":"Decimal",
"SymbolRef":null,
"Extra":null},
"856":{
"Length":4,
"Format":"NumericLE",
"SubFormat":"Decimal",
"SymbolRef":null,
"Extra":null},
"860":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Decimal",
"SymbolRef":null,
"Extra":null},
"863":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Decimal",
"SymbolRef":null,
"Extra":null},
"866":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Decimal",
"SymbolRef":null,
"Extra":null},
"869":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Decimal",
"SymbolRef":null,
"Extra":null},
"872":{
"Length":3,
"Format":"NumericLE",
"SubFormat":"Decimal",
"SymbolRef":null,
"Extra":null},
"875":{
"Length":2,
"Format":"NumericLE",
"SubFormat":"Decimal",
"SymbolRef":null,
"Extra":null}},
"LvTables":{
@@ -231,6 +231,8 @@ after ldx <after+8,y
.here
.logical $021000
_L21000 nop
.as
.xs
ptest pea $1001
pea $1001
pea ptest & $ffff
@@ -240,6 +242,59 @@ ptest pea $1001
pea $0012
pea biggie & $ffff
pea biggie >> 16
jmp L22000
.here
.logical $020010
testlow .byte $02
.here
.logical $0010
testzp .byte $00
.here
.logical $022000
L22000 nop
phk
plb
lda $123456,x
jsl $123456
jsr $023456
lda ptest & $ffff,x
jsr ptest
lda @wtestlow & $ffff,x
jsr testlow
lda testzp,x
nop
lda biggie,x
jsl biggie
jsr biggie & $ffff,k
lda ptest & $ffff,x
jsr ptest
lda @wtestlow & $ffff,x
jsr testlow
lda testzp,x
nop
lda $123456,x
jsl $123456
jsr $023456
lda $1001,x
jsr $021001
lda @w$0010,x
jsr $020010
lda $10,x
nop
sep #$30
lda #$e0
pha
plb
lda 1193046,x
jsl 1193046
jsr 144470
lda 4097,x
jsr 135169
lda @w16,x
jsr 131088
lda 16,x
rts
.here
@@ -24,5 +24,9 @@
!hex 6b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920
!hex 646f67732ea97aa959a934c230a97b56a95a34a93412eaad9f11a59fa5a0b2a1
!hex b1a2b7a3a7a4b5a5a1a6b9a700a5c0b1c1b6c2b4c3d4c4ea5c001002eaf40110
!hex f40110f40110f45634f41200f45634f41200f45634f4120060
!hex f40110f40110f45634f41200f45634f41200f45634f412004c00200200ea4bab
!hex bf56341222563412205634bd0110200110bd1000201000b510eabf5634122256
!hex 3412205634bd0110200110bd1000201000b510eabf56341222563412205634bd
!hex 0110200110bd1000201000b510eae230a9e048abbf56341222563412205634bd
!hex 0110200110bd1000201000b51060
}
@@ -227,6 +227,8 @@ after: ldx <after+8,y
.org $021000
@L21000: nop
.a8
.i8
ptest: pea $1001
pea $1001
pea ptest & $ffff
@@ -236,5 +238,55 @@ ptest: pea $1001
pea $0012
pea biggie & $ffff
pea biggie >> 16
jmp L22000 & $ffff
.org $020010
testlow: .byte $02
.org $0010
testzp: .byte $00
.org $022000
L22000: nop
phk
plb
lda $123456,x
jsl $123456
jsr $3456
lda ptest & $ffff,x
jsr ptest & $ffff
lda a:testlow & $ffff,x
jsr testlow & $ffff
lda testzp,x
nop
lda biggie,x
jsl biggie
jsr biggie & $ffff
lda ptest & $ffff,x
jsr ptest & $ffff
lda a:testlow & $ffff,x
jsr testlow & $ffff
lda testzp,x
nop
lda $123456,x
jsl $123456
jsr $3456
lda $1001,x
jsr $1001
lda a:$0010,x
jsr $0010
lda $10,x
nop
sep #$30
lda #$e0
pha
plb
lda 1193046,x
jsl 1193046
jsr 13398
lda 4097,x
jsr 4097
lda a:16,x
jsr 16
lda 16,x
rts
@@ -218,6 +218,7 @@ after ldx <after+8&$ff,y
org $021000
:L21000 nop
mx %11
ptest pea $1001
pea $1001
pea ptest
@@ -227,5 +228,55 @@ ptest pea $1001
pea $0012
pea biggie
pea ^biggie
jmp L22000
org $020010
testlow dfb $02
org $0010
testzp dfb $00
org $022000
L22000 nop
phk
plb
ldal $123456,x
jsl $123456
jsr $3456
lda ptest,x
jsr ptest
lda: testlow,x
jsr testlow
lda testzp,x
nop
ldal biggie,x
jsl biggie
jsr biggie
lda ptest,x
jsr ptest
lda: testlow,x
jsr testlow
lda testzp,x
nop
ldal $123456,x
jsl $123456
jsr $3456
lda $1001,x
jsr $1001
lda: $0010,x
jsr $0010
lda $10,x
nop
sep #$30
lda #$e0
pha
plb
ldal 1193046,x
jsl 1193046
jsr 13398
lda 4097,x
jsr 4097
lda: 16,x
jsr 16
lda 16,x
rts
@@ -265,5 +265,59 @@ ptest pea ptest ;don't format
pea ^biggie
pea biggie ;format as symbol (low+bank)
pea ^biggie
jmp btest
; Check some in-bank and cross-bank internal/external operands.
org $020010
testlow dfb $02
org $0010
testzp dfb $00
org $022000
btest nop
phk
plb
ldal biggie,x ;don't format
jsl biggie
jsr biggie
lda ptest,x
jsr ptest
lda: testlow,x
jsr testlow
lda testzp,x
nop
ldal biggie,x ;format as symbol
jsl biggie
jsr biggie
lda ptest,x
jsr ptest
lda: testlow,x
jsr testlow
lda testzp,x
nop
ldal biggie,x ;explicitly format as hex
jsl biggie
jsr biggie
lda ptest,x
jsr ptest
lda: testlow,x
jsr testlow
lda testzp,x
nop
sep #$30
mx %11
lda #$e0
pha
plb
ldal biggie,x ;explicitly format as decimal
jsl biggie
jsr biggie
lda ptest,x
jsr ptest
lda: testlow,x
jsr testlow
lda testzp,x
rts