summaryrefslogtreecommitdiff
path: root/interrupts.asm
diff options
context:
space:
mode:
Diffstat (limited to 'interrupts.asm')
-rw-r--r--interrupts.asm87
1 files changed, 40 insertions, 47 deletions
diff --git a/interrupts.asm b/interrupts.asm
index 9592d0b..cf2b195 100644
--- a/interrupts.asm
+++ b/interrupts.asm
@@ -4,23 +4,10 @@
;; this, it can be any of 0, 1, 2.
int_mode: dc.b 0
- ;; 0 if interrupts are turned on.
- ;; 1 if they are being held.
-int_held: dc.b 0
+ ;; 0 if the emulated device doesn't want interrupts.
+ ;; 1 if interrupts are turned on.
+int_enabled: dc.b 1
- ;; 0 if no interrupt is pending.
- ;; 1 if an interrupt occurred while interrupts were being
- ;; held.
- ;; 3 (==1|2) if an NMI is pending.
-int_waiting: dc.b 0
-
- ;; The value of epc as a result of a held interrupt. This is
- ;; stored as a derefenced value (pointer into host memory).
-
- ;; I store it as a native pointer because Z80 interrupts can
- ;; be very strange. Interrupt mode 0 in particular requires
- ;; a shim.
-int_jump: dc.l 0
;; In interrupt mode 0, an interrupt will force a byte onto
;; the data bus for the processor to execute. To handle
@@ -42,37 +29,41 @@ int_opcode: dc.b 0
int_return: dc.w 0 ; the destination address
- ;; This is a macro to hold interrupts.
-
- ;; When interrupts are "disabled" (held), host interrupts will
- ;; still fire. The ISR will see that they are held and update
- ;; the above fields with the interrupt type and location.
- ;; Then the EI macro to enable them will cause it to fire.
-HOLD_INTS MACRO
- move.b #1,int_held
- ENDM
-
- ;; This is a macro to release a held interrupt.
-CONTINUE_INTS MACRO
- bsr ints_continue ; 18 cycles
- ENDM
-
-ints_continue:
- tst.b int_waiting ; 4 cycles
- bne.b ints_continue_pending ; 8 cycles not taken
- ;; Common case: no interrupt pending
- move.b #0,int_held ; 4 cycles
- rts ; 16 cycles
- ;; typical case: 4+18+4+8+4+16 = 54 cycles
-
- ;; I can go faster (24 cycles typical case) by using 68k
- ;; hardware interrupt disable/reenable.
-ints_continue_pending:
- subq.b #3,int_waiting
- beq int_do_nmi
- move.b int_mode,
+ ;; This is the interrupt routine. It can come at any point
+ ;; during an instruction, though routines that use a5 (e.g. by
+ ;; calling C subroutines) will have to turn off interrupts.
+ ;; Routines that call into TIOS will have to remove this
+ ;; interrupt handler.
+int_handler:
+ sub.l #4,a5
+ rte
+int_nevermind:
+ rts
+do_interrupt:
+ ;; todo: make this file m4'd
+ add.l #INT_OFFSET,a5 ; clear the interrupt flag
+
+ tst.b int_enabled ; 4 cycles
+ beq.b int_nevermind ; 8 cycles not taken
+ ;; Common case: interrupts enabled, fall through
+
+ ;; Since this is an instruction all its own, we have D0, D1,
+ ;; and D2 available.
+
+ pop.l a0
+
+ ;; Interrupts are most often in mode 1, then mode 2, and
+ ;; almost never in mode 0.
+ move.b int_mode,d0
+ cmpi.b #1,d0
+ beq int_do_mode2
+ cmpi.b #2,d0
+ beq int_do_mode1
+ cmpi.b #1,d0
+ beq int_do_mode0
+ jmp (a0)
;; This routine emulates a mode 0 interrupt.
@@ -85,9 +76,11 @@ int_do_mode0:
;; This routine emulates a mode 1 interrupt.
- ;; IM 1: RST 38 is executed on every interrupt.
+ ;; IM 1: RST 38 is executed on every interrupt. This is what
+ ;; the TI-83+ uses almost all the time.
int_do_mode1:
- rts
+ jmp emu_op_ff
+
;; This routine emulates a mode 2 interrupt.