feat(arnitech): handlers for a 65816's native-mode interrupts on a Blade

A Blade reads the 65816's native-mode vectors from the RAM under the KERNAL
at $FFE4-$FFEF. native_vectors_init puts handlers' addresses there: IRQ and
NMI save A, X, and Y at full width, the direct page, and the data bank, push
the frame an emulation-mode interrupt makes, and run the KERNAL's handlers
through CINV and NMINV in 8-bit native mode, whose RTI comes back to restore
everything. BRK, COP, and ABORT go to the BRK handler, which on a Blade first
sets the direct page and data bank to 0 and returns to emulation mode.
This commit is contained in:
chris committed 2026-10-18 08:57:01 +02:00
1 parent 90b921ac5e
commit b7fef8abe6
3 files changed
+126 -1

No files matched your search

+7
View File
@@ -33,3 +33,10 @@
!addr RRNET_TX_CMD = $DE0C ; write-only
!addr RRNET_TX_LENGTH = $DE0E ; write-only
}
!ifdef CONFIG_ARNITECH_BLADE {
; The 65816's native-mode vectors, which a Blade reads from the RAM under the KERNAL (ADR 0029)
!addr NATIVE_VECTORS = $FFE4 ; COP, BRK, ABORT, NMI, reserved, IRQ
}
+106
View File
@@ -0,0 +1,106 @@
;; #LAYOUT# STD * #TAKE
;; #LAYOUT# * * #IGNORE
;
; The 65816's native-mode interrupts on a Blade (mc64blade only, arnitech's ADR 0029 and 0030)
;
; In native mode the 65816 fetches its vectors from $FFE4-$FFEF, where the KERNAL's jump table
; has its JMPs, so a Blade reads them from the RAM under the KERNAL, which CINT fills. A program
; that switches to native mode with interrupts on keeps running: the IRQ and NMI handlers save
; the registers, the direct page, and the data bank, run the KERNAL's handlers through CINV and
; NMINV in 8-bit native mode on direct page 0 and data bank 0, and return with RTI. BRK, COP, and
; ABORT go to the BRK handler, which returns to emulation mode and to READY. The code here runs
; only on a 65816, so its own opcodes are bytes.
;
!ifdef CONFIG_ARNITECH_BLADE {
native_vectors_init:
ldx #(__native_vector_table_end - native_vector_table - 1)
@1:
lda native_vector_table, x
sta NATIVE_VECTORS, x ; with the KERNAL banked in, the write reaches the RAM under it
dex
bpl @1
rts
native_vector_table:
!word default_brk_handler ; COP
!word default_brk_handler ; BRK
!word default_brk_handler ; ABORT
!word native_nmi ; NMI
!word default_brk_handler ; reserved
!word native_irq ; IRQ
__native_vector_table_end:
;
; IRQ and NMI in native mode, with any register widths: the registers go on the stack whole,
; then a frame as an IRQ or NMI makes it in emulation mode, whose RTI comes back to native_return.
;
native_irq:
!byte $C2, $30 ; REP #$30: 16-bit A, X, and Y
pha
!byte $A9 ; LDA #: the handler's address, less one, for RTS
!word native_irq_kernal - 1
!byte $80 ; BRA native_save
!byte native_save - (* + 1)
native_nmi:
!byte $C2, $30 ; REP #$30
pha
!byte $A9 ; LDA #
!word hw_entry_nmi - 1
; FALLTROUGH
native_save:
!byte $DA ; PHX
!byte $5A ; PHY
!byte $8B ; PHB
!byte $0B ; PHD
tax ; the handler's address, 16 bits
!byte $F4, $00, $00 ; PEA $0000
!byte $2B ; PLD: direct page 0
!byte $E2, $20 ; SEP #$20: 8-bit A
lda #$00
pha
!byte $AB ; PLB: data bank 0
; The frame the KERNAL's handler returns through: program bank, address, status (8-bit A,
; X, and Y, interrupts off)
pha
!byte $F4 ; PEA native_return
!word native_return
lda #$34
pha
!byte $DA ; PHX: the handler's address, for RTS
!byte $E2, $30 ; SEP #$30: 8-bit X and Y
rts
native_irq_kernal:
; The KERNAL's IRQ handlers end by pulling Y, X, and A, as hw_entry_irq pushes them
pha
pha
pha
jmp (CINV)
native_return:
!byte $C2, $30 ; REP #$30
!byte $2B ; PLD
!byte $AB ; PLB
!byte $7A ; PLY
!byte $FA ; PLX
pla
rti
}
@@ -9,7 +9,19 @@ default_brk_handler:
sei ; disable IRQs, to be sure they wont interfere
!ifdef CONFIG_PLATFORM_COMMODORE_64 {
!ifdef CONFIG_ARNITECH_BLADE {
; A Blade's 65816 comes here from BRK, COP, and ABORT in native mode too (arnitech_native.s):
; direct page 0, data bank 0, and back to emulation mode
!byte $F4, $00, $00 ; PEA $0000
!byte $2B ; PLD
!byte $4B ; PHK
!byte $AB ; PLB
sec
!byte $FB ; XCE
} else ifdef CONFIG_PLATFORM_COMMODORE_64 {
ldx #$00
sta VIC_SCROLX ; turn the display off - we want as little screen artifacts as possible