mirror of
https://github.com/fadden/6502bench.git
synced 2024-11-17 09:04:43 +00:00
478afa542e
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)
191 lines
5.4 KiB
ArmAsm
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
|