1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-12-01 22:50:35 +00:00
6502bench/SourceGen/SGTestData/Source/20052-branches-and-banks.S
Andy McFadden 478afa542e 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)
2021-08-09 14:11:15 -07:00

191 lines
5.4 KiB
ArmAsm

; Copyright 2018 faddenSoft. All Rights Reserved.
; See the LICENSE.txt file for distribution terms (Apache 2.0).
;
; Assembler: cc65
; cl65 --target none -C 20052-branches-and-banks.cfg 20052-branches-and-banks.S
;
; For the 65816 we want to exercise some additional things.
.setcpu "65816"
symlong = $123456
.org $1000
clc
xce
sep #$30
jml bank44
lodat: .byte $00,$01,$02 ;EDIT: set label
.org $440000
bank44: cmp f:bank44
low44: lda bank44
lda a:bank44 & $ffff
lda z:bank44 & $ffff ;DP ref, should resolve to "zero"
bmi low44
per low44-$40
bne low44-$40 ;branch to high44
brl bank44-$40 ;branch to late44
dat44: ;EDIT: set label
.addr dat44 ;EDIT: format as 16-bit Address
.faraddr dat44 ;EDIT: format as 24-bit Address
.org $44ffc0
late44: cmp f:late44
high44: beq cont44 ;EDIT: set label
bmi late44+$44 ;branch to low44
brl late44+$44 ;branch to low44
cont44: jml twok
.org $2000
twok: bit twok
pea dat44 & $ffff ;EDIT: set symbol=dat44
pea dat44 >> 16 ;EDIT: set symbol=dat44
bne skip
jmp [lodat]
skip: nop
j1: jsr j2 ;EDIT: set symbol=j2 for all, confirm auto-labels vanish
j2: jsr j3 ;EDIT: set label
j3: jsr j1
jsl symlong
jml bank54
.org $543210
bank54: cmp f:bank54
bra nxt54a
backchk:
nop ;EDIT: set label
nop
rts
backval:
.word backchk & $ffff
.byte bank54 >> 16
nxt54a:
; Test forward/backward refs. In cc65 this makes a difference because it's
; a one-pass assembler.
lda f:backchk ;EDIT: use symbol
lda f:fwdchk ;EDIT: use symbol
lda f:backchk ;EDIT: use hex
lda f:fwdchk ;EDIT: use hex
lda a:backchk & $ffff + 1 ;EDIT: use symbol
lda a:backchk & $ffff - 1 ;EDIT: use symbol
lda a:fwdchk & $ffff + 1 ;EDIT: use symbol
lda a:fwdchk & $ffff - 1 ;EDIT: use symbol
; Test non-bank-0 JSRs. The behavior varies significantly by assembler. The
; trick is that the high byte comes from the 'K' register. cc65 wants you
; to remove it for a 16-bit JSR (or fails because the operand is too big),
; 64tass wants you to keep it in place (or fails because you're trying to
; jump to the wrong bank), and Merlin32 doesn't care.
nop
jsr backchk & $ffff
jsr backchk & $ffff + 1 ;EDIT: set to "backchk"
jsr backchk & $ffff + 2 ;leave in hex
jsr fwdchk & $ffff
jsr fwdchk & $ffff + 1 ;EDIT: set to "fwdchk"
jsr fwdchk & $ffff + 2 ;leave in hex
nop
ldx #$00
jsr (backval & $ffff,X)
jsr (fwdval & $ffff,X)
jsr jmp1b & $ffff
jsr jmp1f & $ffff
jsr jmp2b & $ffff
jsr jmp2f & $ffff
jsr jmp3b & $ffff
jsr jmp3f & $ffff
bra nxt54b
; Fun fact: "JMP (addr)" and "JML [addr]" always load the indirect value
; from zero page. They do *not* use B or K. The (addr,X) mode uses the
; program bank (K). According to Eyes & Lichty, this is because the
; non-indexed form assumes you're jumping through a variable, while the
; indexed form assumes you've got an address table in your code. (Think
; how they would be used in ROM.)
jmp2b: jmp (backval & $ffff,X)
jmp2f: jmp (fwdval & $ffff,X)
jmp1b: jmp (lodat)
jmp1f: jmp (lodat)
jmp3b: jmp [lodat]
jmp3f: jmp [lodat]
fwdval:
.word fwdchk & $ffff
.byte bank54 >> 16
fwdchk:
nop ;EDIT: set label
nop
rts
nxt54b:
; Do odd thing: JSR to address in bank $00 from bank $54.
; Most assemblers just accept this because it's a JSR to
; a 16-bit address.
jsr skip ;EDIT: set to "skip" label
nop
; Test the non-"smart" PLP affects on the M/X flags.
; EDIT: disable "smart PLP" for this project
rep #$30
.a16
.i16
php
lda #$0000
sep #$30
.a8
.i8
lda #$00
plp ;smart->long, unsmart->short
lda #$ea
nop
sep #$30
.a8
.i8
php
lda #$00
rep #$30
.a16
.i16
lda #$0000
plp ;smart->short, unsmart->long
lda #$eaea
rep #$30
.a16
.i16
nop
; 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