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.
107 lines
3.1 KiB
ArmAsm
107 lines
3.1 KiB
ArmAsm
;; #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
|
|
}
|