Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[KERNAL] 65C816 native NMI sets up for native return from emulated call #342

Merged
merged 3 commits into from
Jun 14, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 15 additions & 14 deletions kernal/x16/65c816/interrupt.s
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.include "banks.inc"

.import iclall, igetin
.import cbinv, cinv, nminv
.import __irq, __irq_65c816_saved, __irq_native_ret
Expand All @@ -17,7 +19,7 @@ rom_bank = 1
.pushcpu
.setcpu "65816"

.macro c816_interrupt_impl vector
.macro c816_interrupt_impl
rep #$30 ; 16-bit accumulator and index
.I16
.A16
Expand Down Expand Up @@ -49,12 +51,11 @@ rom_bank = 1
phx ; save X and Y
phy

jmp (vector)
.A8
.I8
.endmacro

.macro irq_brk_common_impl addr, emulated_kernal_vector, emulated_kernal_impl
.macro intr_common_impl addr, emulated_kernal_vector, emulated_kernal_impl
.A16
.I16
tsx
Expand Down Expand Up @@ -82,6 +83,10 @@ rom_bank = 1
clc

php
.endmacro

.macro irq_brk_common_impl addr, emulated_kernal_vector, emulated_kernal_impl
intr_common_impl addr, emulated_kernal_vector, emulated_kernal_impl

lda $0B, S
pha
Expand All @@ -107,15 +112,17 @@ c816_nmib:
jmp (innmi)

c816_irqb:
c816_interrupt_impl inirq
c816_interrupt_impl
jmp (inirq)

.segment "C816_BRK"
c816_brk:
jmp c816_brk_impl

.segment "MEMDRV"
c816_brk_impl:
c816_interrupt_impl inbrk
c816_interrupt_impl
jmp (inbrk)

.segment "C816_COP_NATIVE"
c816_cop_native:
Expand Down Expand Up @@ -173,15 +180,9 @@ __interrupt_65c816_native_kernal_impl_ret:
rti

nnnmi:
.A16
.I16
sec
xce
.A8
.I8
clc
stz rom_bank
jmp (nminv)
c816_interrupt_impl
intr_common_impl
jmp nmi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nnnmi needs to setup an emulation mode context and then jump to the nminv vector, not the KERNAL implementation; otherwise, NMIs in native mode won't ever execute a NMI handler written in emulation mode for the 65C02.

Copy link
Collaborator Author

@mooinglemur mooinglemur Jun 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is exactly what is done here. nmi is the target of the emulation mode NMI vector, and this function is what calls jmp (nminv) which by default leads to nnmi.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the code for the emulation mode nmi target is in __nmi in the source, as it is copied into low RAM at init. The preservation that nmi does is minimal, so a double pla from a custom emulation mode NMI handler to clear the stack that it does should be able to rti into our fake RTI frames, one to return to native mode, and the other to return to the interrupted code.


nncop:
nnabort:
Expand Down
Loading