diff options
| author | Duncan Smith | 2010-11-13 00:26:25 -0800 |
|---|---|---|
| committer | Duncan Smith | 2010-11-13 00:26:25 -0800 |
| commit | cc79084db8e2d0d0c3f8009855628c28668c837a (patch) | |
| tree | ed3ab63db1dc8fb4563dadf61080093dea52d262 | |
| parent | 677c903c27858a0d5ef7b09c4273550770673b4a (diff) | |
First bit of the new interrupts code added
| -rw-r--r-- | interrupts.asm | 87 | ||||
| -rw-r--r-- | opcodes.asm.m4 | 154 | ||||
| -rw-r--r-- | opcodes.inc.m4 | 2 |
3 files changed, 43 insertions, 200 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. diff --git a/opcodes.asm.m4 b/opcodes.asm.m4 index 6d6be9e..50c26f8 100644 --- a/opcodes.asm.m4 +++ b/opcodes.asm.m4 @@ -101,6 +101,7 @@ _align SET 0 START MACRO ORG emu_plain_op+_align _align SET _align+$40 + jmp do_interrupt ; for interrupt routines ENDM ;; LOHI/HILO are hideously slow for instructions used often. @@ -203,9 +204,7 @@ OPCODE(00,«»,4) ;; Read a word and put it in BC ;; No flags OPCODE(01,« - HOLD_INTS FETCHWI ebc - CONTINUE_INTS »,36,,12) ;; LD (BC),A @@ -244,10 +243,8 @@ OPCODE(05,« ;; B <- immed.b ;; No flags OPCODE(06,« - HOLD_INTS LOHI ebc FETCHBI ebc - CONTINUE_INTS HILO ebc »,26,,10) ;nok @@ -311,9 +308,7 @@ OPCODE(0d,« ;; LD C,immed.b ;; No flags OPCODE(0e,« - HOLD_INTS FETCHBI ebc - CONTINUE_INTS »,18,,6) ;nok @@ -332,7 +327,6 @@ OPCODE(0f,« ;; if B not zero ;; No flags OPCODE(10,« - HOLD_INTS LOHI ebc subq.b #1,ebc beq.s local(end) ; slooooow @@ -344,16 +338,13 @@ OPCODE(10,« move.l a0,epc local(end): HILO ebc - CONTINUE_INTS »,,,32) ;nok ;; LD DE,immed.w ;; No flags OPCODE(11,« - HOLD_INTS FETCHWI ede - CONTINUE_INTS ») ;nok @@ -394,10 +385,8 @@ OPCODE(15,« ;; LD D,immed.b ;; No flags OPCODE(16,« - HOLD_INTS LOHI ede FETCHBI ede - CONTINUE_INTS HILO ede ») ;nok @@ -415,7 +404,6 @@ OPCODE(17,« ;; Branch relative by a signed immediate byte ;; No flags OPCODE(18,« - HOLD_INTS clr.w d1 FETCHBI d1 move.l epc,a0 @@ -423,7 +411,6 @@ OPCODE(18,« add.w d0,d1 ; ??? Can I avoid underef/deref cycle? bsr deref move.l a0,epc - CONTINUE_INTS ») ;nok @@ -467,9 +454,7 @@ OPCODE(1d,« ;; LD E,immed.b ;; No flags OPCODE(1e,« - HOLD_INTS FETCHBI ede - CONTINUE_INTS ») ;nok @@ -486,20 +471,16 @@ OPCODE(1f,« ;; PC <- PC+immed.b ;; No flags OPCODE(20,« - HOLD_INTS bsr f_norm_z ;; if the emulated Z flag is set, this will be clear beq emu_op_18 ; branch taken: Z reset -> eq (zero set) add.l #1,epc ; skip over the immediate byte - CONTINUE_INTS ») ;; LD HL,immed.w ;; No flags OPCODE(21,« - HOLD_INTS FETCHWI ehl - CONTINUE_INTS ») ;nok @@ -507,9 +488,7 @@ OPCODE(21,« ;; (address) <- HL ;; No flags OPCODE(22,« - HOLD_INTS FETCHWI d1 - CONTINUE_INTS PUTW ehl,d1 ») ;nok @@ -542,10 +521,8 @@ OPCODE(25,« ;; LD H,immed.b ;; No flags OPCODE(26,« - HOLD_INTS LOHI ehl FETCHBI ehl - CONTINUE_INTS HILO ehl ») ;nok @@ -566,11 +543,9 @@ OPCODE(27,« ;; SPEED can be made faster ;; No flags OPCODE(28,« - HOLD_INTS bsr f_norm_z bne emu_op_18 add.l #1,epc - CONTINUE_INTS ») ;nok @@ -584,9 +559,7 @@ OPCODE(29,« ;; LD HL,(immed.w) ;; address is absolute OPCODE(2a,« - HOLD_INTS FETCHWI d1 - CONTINUE_INTS FETCHW d1,ehl ») ;nok @@ -612,9 +585,7 @@ OPCODE(2d,« ;; LD L,immed.b OPCODE(2e,« - HOLD_INTS FETCHBI ehl - CONTINUE_INTS ») ;nok @@ -637,20 +608,16 @@ OPCODE(30,« ;; LD SP,immed.w OPCODE(31,« - HOLD_INTS FETCHWI d1 bsr deref movea.l a0,esp - CONTINUE_INTS ») ;nok ;; LD (immed.w),A ;; store indirect OPCODE(32,« - HOLD_INTS FETCHWI d1 - CONTINUE_INTS rol.w #8,d1 PUTB eaf,d1 ») @@ -662,9 +629,7 @@ OPCODE(32,« ;; FYI: Do not have to deref because this will never cross a ;; page boundary. So sayeth BrandonW. OPCODE(33,« - HOLD_INTS addq.w #1,esp - CONTINUE_INTS ») ;nok @@ -690,9 +655,7 @@ OPCODE(35,« ;; LD (HL),immed.b OPCODE(36,« - HOLD_INTS FETCHBI d1 - CONTINUE_INTS PUTB ehl,d1 ») ;nok @@ -713,31 +676,25 @@ OPCODE(37,« ;; If carry set ;; PC <- PC+immed.b OPCODE(38,« - HOLD_INTS bsr f_norm_c bne emu_op_18 add.l #1,epc - CONTINUE_INTS ») ;; ADD HL,SP ;; HL <- HL+SP OPCODE(39,« - HOLD_INTS move.l esp,a0 bsr underef F_ADD_W ehl,d0 ; ??? Can I avoid underef/deref cycle? bsr deref move.l a0,esp - CONTINUE_INTS ») ;nok ;; LD A,(immed.w) OPCODE(3a,« - HOLD_INTS FETCHWI d1 - CONTINUE_INTS FETCHB d1,eaf ») ;nok @@ -762,9 +719,7 @@ OPCODE(3d,« ;; LD A,immed.b OPCODE(3e,« - HOLD_INTS FETCHBI eaf - CONTINUE_INTS ») ;; CCF @@ -1824,20 +1779,16 @@ OPCODE(bf,« ;; PCh <- (SP+1) ;; SP <- (SP+2) OPCODE(c0,« - HOLD_INTS bsr f_norm_z ;; SPEED inline RET beq emu_op_c9 ; RET - CONTINUE_INTS ») ;nok ;; POP BC ;; Pops a word into BC OPCODE(c1,« ; S10 T - HOLD_INTS POPW ebc - CONTINUE_INTS ») ;nok @@ -1845,52 +1796,42 @@ OPCODE(c1,« ; S10 T ;; if ~Z ;; PC <- immed.w OPCODE(c2,« - HOLD_INTS bsr f_norm_z bne.s emu_op_c3 add.l #2,epc - CONTINUE_INTS ») ;nok ;; JP immed.w ;; PC <- immed.w OPCODE(c3,« - HOLD_INTS FETCHWI d1 bsr deref movea.l a0,epc - CONTINUE_INTS »,36,,12) ;nok ;; CALL NZ,immed.w ;; If ~Z, CALL immed.w OPCODE(c4,« - HOLD_INTS bsr f_norm_z ;; CALL (emu_op_cd) will run HOLD_INTS again. This doesn't ;; matter with the current implementation because HOLD_INTS ;; simply sets a bit. bne emu_op_cd add.l #2,epc - CONTINUE_INTS ») ;nok ;; PUSH BC OPCODE(c5,« - HOLD_INTS PUSHW ebc - CONTINUE_INTS ») ;nok ;; ADD A,immed.b OPCODE(c6,« - HOLD_INTS FETCHBI d1 - CONTINUE_INTS F_ADD_B d1,eaf ») ;nok @@ -1899,23 +1840,19 @@ OPCODE(c6,« ;; == CALL 0 ;; XXX check OPCODE(c7,« - HOLD_INTS move.l epc,a0 bsr underef PUSHW d0 move.w #$00,d0 bsr deref move.l a0,epc - CONTINUE_INTS ») ;nok ;; RET Z OPCODE(c8,« - HOLD_INTS bsr f_norm_z beq.s emu_op_c9 - CONTINUE_INTS ») ;nok @@ -1924,22 +1861,18 @@ OPCODE(c8,« ;; PCh <- (SP+1) POPW ;; SP <- (SP+2) OPCODE(c9,« - HOLD_INTS POPW d1 bsr deref movea.l a0,epc - CONTINUE_INTS ») ;nok ;; JP Z,immed.w ;; If Z, jump OPCODE(ca,« - HOLD_INTS bsr f_norm_z beq emu_op_c3 add.l #2,epc - CONTINUE_INTS ») ;nok ;; prefix @@ -1950,11 +1883,9 @@ OPCODE(cb,« ;; CALL Z,immed.w OPCODE(cc,« - HOLD_INTS bsr f_norm_z beq.s emu_op_cd add.l #2,epc - CONTINUE_INTS ») ;nok @@ -1965,7 +1896,6 @@ OPCODE(cc,« ;; SP <- SP - 2 ;; PC <- address OPCODE(cd,« - HOLD_INTS ; released in JP routine move.l epc,a0 bsr underef ; d0 has PC add.w #2,d0 @@ -1975,9 +1905,7 @@ OPCODE(cd,« ;; ADC A,immed.b OPCODE(ce,« - HOLD_INTS FETCHWI d1 - CONTINUE_INTS F_ADC_B d1,eaf ») ;nok @@ -1985,76 +1913,60 @@ OPCODE(ce,« ;; RST &08 ;; == CALL 8 OPCODE(cf,« - HOLD_INTS move.l epc,a0 bsr underef ; d0 has PC PUSHW d0 move.w #$08,d0 bsr deref move.l a0,epc - CONTINUE_INTS ») ;nok ;; RET NC OPCODE(d0,« - HOLD_INTS bsr f_norm_c beq emu_op_c9 - CONTINUE_INTS ») ;nok ;; POP DE OPCODE(d1,« - HOLD_INTS POPW ede - CONTINUE_INTS ») ;nok ;; JP NC,immed.w OPCODE(d2,« - HOLD_INTS bsr f_norm_c beq emu_op_c3 add.l #2,epc - CONTINUE_INTS ») ;; OUT immed.b,A OPCODE(d3,« - HOLD_INTS move.b eaf,d1 FETCHBI d0 bsr port_out - CONTINUE_INTS ») ;nok ;; CALL NC,immed.w OPCODE(d4,« - HOLD_INTS bsr f_norm_c beq emu_op_cd add.l #2,epc - CONTINUE_INTS ») ;nok ;; PUSH DE OPCODE(d5,« - HOLD_INTS PUSHW ede - CONTINUE_INTS ») ;nok ;; SUB A,immed.b OPCODE(d6,« - HOLD_INTS FETCHBI d1 - CONTINUE_INTS F_SUB_B eaf,d1 ») ;nok @@ -2062,23 +1974,19 @@ OPCODE(d6,« ;; RST &10 ;; == CALL 10 OPCODE(d7,« - HOLD_INTS move.l epc,a0 bsr underef PUSHW d0 move.w #$10,d0 bsr deref move.l a0,epc - CONTINUE_INTS ») ;nok ;; RET C OPCODE(d8,« - HOLD_INTS bsr f_norm_c bne emu_op_c9 - CONTINUE_INTS ») ;nok @@ -2092,30 +2000,24 @@ OPCODE(d9,« ;; JP C,immed.w OPCODE(da,« - HOLD_INTS bsr f_norm_c bne emu_op_c3 - CONTINUE_INTS ») ;nok OPCODE(db,« ;; IN A,immed.b - HOLD_INTS move.b eaf,d1 FETCHBI d0 - CONTINUE_INTS bsr port_in ») ;nok ;; CALL C,immed.w OPCODE(dc,« - HOLD_INTS bsr f_norm_c bne emu_op_cd add.l #2,epc - CONTINUE_INTS ») ;nok @@ -2125,9 +2027,7 @@ OPCODE(dd,« ; prefix ;; SBC A,immed.b OPCODE(de,« - HOLD_INTS FETCHWI d1 - CONTINUE_INTS F_SBC_B d1,eaf ») ;nok @@ -2135,24 +2035,20 @@ OPCODE(de,« ;; RST &18 ;; == CALL 18 OPCODE(df,« - HOLD_INTS move.l epc,a0 bsr underef PUSHW d0 move.w #$18,d0 bsr deref move.l a0,epc - CONTINUE_INTS ») ;nok ;; RET PO ;; If parity odd (P zero), return OPCODE(e0,« - HOLD_INTS bsr f_norm_pv beq emu_op_c9 - CONTINUE_INTS ») ;nok @@ -2164,21 +2060,17 @@ OPCODE(e1,« ;; JP PO,immed.w OPCODE(e2,« - HOLD_INTS bsr f_norm_pv beq emu_op_c3 add.l #2,epc - CONTINUE_INTS ») ;nok ;; EX (SP),HL ;; Exchange OPCODE(e3,« - HOLD_INTS POPW d1 PUSHW ehl - CONTINUE_INTS move.w d1,ehl ») ;nok @@ -2186,27 +2078,21 @@ OPCODE(e3,« ;; CALL PO,immed.w ;; if parity odd (P=0), call OPCODE(e4,« - HOLD_INTS bsr f_norm_pv beq emu_op_cd add.l #2,epc - CONTINUE_INTS ») ;nok ;; PUSH HL OPCODE(e5,« - HOLD_INTS PUSHW ehl - CONTINUE_INTS ») ;nok ;; AND immed.b OPCODE(e6,« - HOLD_INTS FETCHBI d1 - CONTINUE_INTS F_AND_B d1,eaf ») ;nok @@ -2214,44 +2100,36 @@ OPCODE(e6,« ;; RST &20 ;; == CALL 20 OPCODE(e7,« - HOLD_INTS move.l epc,a0 bsr underef PUSHW d0 move.w #$20,d0 bsr deref move.l a0,epc - CONTINUE_INTS ») ;nok ;; RET PE ;; If parity odd (P zero), return OPCODE(e8,« - HOLD_INTS bsr f_norm_pv bne emu_op_c9 - CONTINUE_INTS ») ;nok ;; JP (HL) OPCODE(e9,« - HOLD_INTS FETCHB ehl,d1 bsr deref movea.l a0,epc - CONTINUE_INTS ») ;nok ;; JP PE,immed.w OPCODE(ea,« - HOLD_INTS bsr f_norm_pv bne emu_op_c3 add.l #2,epc - CONTINUE_INTS ») ;nok @@ -2264,11 +2142,9 @@ OPCODE(eb,« ;; CALL PE,immed.w ;; If parity even (P=1), call OPCODE(ec,« - HOLD_INTS bsr f_norm_c bne emu_op_cd add.l #2,epc - CONTINUE_INTS ») ;nok @@ -2280,9 +2156,7 @@ OPCODE(ed,« ; prefix ;; XOR immed.b OPCODE(ee,« - HOLD_INTS FETCHBI d1 - CONTINUE_INTS F_XOR_B d1,eaf ») ;nok @@ -2290,24 +2164,20 @@ OPCODE(ee,« ;; RST &28 ;; == CALL 28 OPCODE(ef,« - HOLD_INTS move.l epc,a0 bsr underef PUSHW d0 move.w #$28,d0 bsr deref move.l a0,epc - CONTINUE_INTS ») ;nok ;; RET P ;; Return if Positive OPCODE(f0,« - HOLD_INTS bsr f_norm_sign beq emu_op_c9 ; RET - CONTINUE_INTS ») ;nok @@ -2323,11 +2193,9 @@ OPCODE(f1,« ;; JP P,immed.w OPCODE(f2,« - HOLD_INTS bsr f_norm_sign beq emu_op_c3 ; JP add.l #2,epc - CONTINUE_INTS ») ;nok @@ -2339,21 +2207,17 @@ OPCODE(f3,« ;; CALL P,&0000 ;; Call if positive (S=0) OPCODE(f4,« - HOLD_INTS bsr f_norm_sign beq emu_op_cd - CONTINUE_INTS ») ;nok ;; PUSH AF OPCODE(f5,« - HOLD_INTS bsr flags_normalize LOHI eaf move.b flag_byte(pc),eaf ;; XXX wrong, af is not normalized by flags_normalize? - CONTINUE_INTS HILO eaf PUSHW eaf ») @@ -2361,9 +2225,7 @@ OPCODE(f5,« OPCODE(f6,« ;; OR immed.b - HOLD_INTS FETCHBI d1 - CONTINUE_INTS F_OR_B d1,eaf ») ;nok @@ -2371,45 +2233,37 @@ OPCODE(f6,« ;; RST &30 ;; == CALL 30 OPCODE(f7,« - HOLD_INTS move.l epc,a0 bsr underef PUSHW d0 move.w #$08,d0 bsr deref move.l a0,epc - CONTINUE_INTS ») ;nok ;; RET M ;; Return if Sign == 1, minus OPCODE(f8,« - HOLD_INTS bsr f_norm_sign bne emu_op_c9 ; RET - CONTINUE_INTS ») ;nok ;; LD SP,HL ;; SP <- HL OPCODE(f9,« - HOLD_INTS move.w ehl,d1 bsr deref movea.l a0,esp - CONTINUE_INTS ») ;nok ;; JP M,immed.w OPCODE(fa,« - HOLD_INTS bsr f_norm_sign bne emu_op_c3 ; JP add.l #2,epc - CONTINUE_INTS ») ;nok @@ -2422,11 +2276,9 @@ OPCODE(fb,« ;; CALL M,immed.w ;; Call if minus (S=1) OPCODE(fc,« - HOLD_INTS bsr f_norm_sign bne emu_op_cd add.l #2,epc - CONTINUE_INTS ») ;nok @@ -2437,9 +2289,7 @@ OPCODE(fd,« ; prefix ;; CP immed.b OPCODE(fe,« - HOLD_INTS FETCHBI d1 - CONTINUE_INTS F_CP_B d1,eaf ») ;nok @@ -2447,13 +2297,11 @@ OPCODE(fe,« ;; RST &38 ;; == CALL 38 OPCODE(ff,« - HOLD_INTS move.l epc,a0 bsr underef PUSHW d0 move.w #$08,d0 bsr deref move.l a0,epc - CONTINUE_INTS ») ;nok diff --git a/opcodes.inc.m4 b/opcodes.inc.m4 index 4d9a81c..fd225d4 100644 --- a/opcodes.inc.m4 +++ b/opcodes.inc.m4 @@ -13,3 +13,5 @@ $2 TIME $3 ifelse(«,$4», «,», «», «,$4») undefine(«label»)dnl DONE»)dnl +dnl +define(«INT_OFFSET», 6)dnl |
