nkeynes@228: .section .text nkeynes@228: .include "sh4/inc.s" nkeynes@228: nkeynes@228: ! expect_interrupt( int intevt ) nkeynes@228: .global _expect_interrupt nkeynes@228: _expect_interrupt: nkeynes@228: stc sr, r3 ! Mask off interrupts nkeynes@228: mov.l bl_mask, r0 nkeynes@228: or r3, r0 nkeynes@228: ldc r0, sr nkeynes@228: mova expected_intevt, r0 nkeynes@228: mov.l r4, @r0 nkeynes@228: xor r1, r1 nkeynes@228: mova expected_expevt, r0 nkeynes@228: mov.l r1, @r0 nkeynes@228: mova _interrupt_count, r0 nkeynes@228: mov.l r1, @r0 nkeynes@228: mova _interrupt_pc, r0 nkeynes@228: mov.l r1, @r0 nkeynes@228: ldc r3, sr ! Restore old SR state nkeynes@228: rts nkeynes@228: nop nkeynes@228: nkeynes@228: .global _expect_exception nkeynes@228: _expect_exception: nkeynes@228: stc sr, r3 ! Mask off interrupts nkeynes@228: mov.l bl_mask, r0 nkeynes@228: or r3, r0 nkeynes@228: ldc r0, sr nkeynes@228: mova expected_expevt, r0 nkeynes@228: mov.l r4, @r0 nkeynes@228: xor r1, r1 nkeynes@228: mova expected_intevt, r0 nkeynes@228: mov.l r1, @r0 nkeynes@228: mova _interrupt_count, r0 nkeynes@228: mov.l r1, @r0 nkeynes@228: mova _interrupt_pc, r0 nkeynes@228: mov.l r1, @r0 nkeynes@228: ldc r3, sr ! Restore old SR state nkeynes@228: rts nkeynes@228: nop nkeynes@228: nkeynes@228: .align 4 nkeynes@228: .global _interrupt_count nkeynes@228: _interrupt_count: nkeynes@228: .long 0x00000000 nkeynes@228: .global _interrupt_pc nkeynes@228: _interrupt_pc: nkeynes@228: .long 0x00000000 nkeynes@228: bl_mask: nkeynes@228: .long 0x10000000 nkeynes@228: nkeynes@228: .global _install_interrupt_handler nkeynes@228: _install_interrupt_handler: nkeynes@228: stc vbr, r1 nkeynes@228: mova old_vbr, r0 nkeynes@228: mov.l r1, @r0 nkeynes@228: mova __interrupt_handler, r0 nkeynes@228: ldc r0, vbr nkeynes@228: rts nkeynes@228: nop nkeynes@228: nkeynes@228: .global _remove_interrupt_handler nkeynes@228: _remove_interrupt_handler: nkeynes@228: mov.l old_vbr, r1 nkeynes@228: ldc r1, vbr nkeynes@228: rts nkeynes@228: nop nkeynes@228: .align 4 nkeynes@228: old_vbr: nkeynes@228: .long 0x00000000 nkeynes@228: expected_intevt: nkeynes@228: .long 0x00000000 nkeynes@228: expected_expevt: nkeynes@228: .long 0x00000000 nkeynes@228: nkeynes@228: nkeynes@228: __interrupt_handler: nkeynes@228: .skip 0x100 nkeynes@228: general_exception: nkeynes@228: mov.l handler_stack_ptr_k, r15 nkeynes@228: mov.l @r15, r15 nkeynes@228: mov.l r0, @-r15 nkeynes@228: mov.l r1, @-r15 nkeynes@228: mov.l r2, @-r15 nkeynes@228: nkeynes@228: mov.l expevt_k, r0 nkeynes@228: mov.l @r0, r1 nkeynes@228: mov.l expected_expevt_k, r2 nkeynes@228: mov.l @r2, r2 nkeynes@228: cmp/eq r1, r2 nkeynes@228: bf general_not_expected nkeynes@228: bra ex_expected nkeynes@228: nop nkeynes@228: general_not_expected: nkeynes@228: bra ex_dontcare nkeynes@228: nop nkeynes@228: nop nkeynes@228: expevt_k: nkeynes@228: .long 0xFF000024 nkeynes@228: expected_expevt_k: nkeynes@228: .long expected_expevt nkeynes@228: handler_stack_ptr_k: nkeynes@228: .long handler_stack_ptr nkeynes@228: .skip 0x2D4 ! Pad up to 0x400 nkeynes@228: nkeynes@228: tlb_exception: nkeynes@228: mov.l handler_stack_ptr, r15 nkeynes@228: mov.l r0, @-r15 nkeynes@228: mov.l r1, @-r15 nkeynes@228: mov.l r2, @-r15 nkeynes@228: nkeynes@228: mov.l expevt1_k, r0 nkeynes@228: mov.l @r0, r1 nkeynes@228: mov.l expected_expevt1_k, r2 nkeynes@228: mov.l @r2, r2 nkeynes@228: cmp/eq r1, r2 nkeynes@228: bf tlb_not_expected nkeynes@228: bra ex_expected nkeynes@228: nop nkeynes@228: tlb_not_expected: nkeynes@228: bra ex_dontcare nkeynes@228: nop nkeynes@228: expevt1_k: nkeynes@228: .long 0xFF000024 nkeynes@228: expected_expevt1_k: nkeynes@228: .long expected_expevt nkeynes@228: nkeynes@228: .skip 0x1DC ! Pad up to 0x600 nkeynes@228: nkeynes@228: irq_raised: nkeynes@228: mov.l handler_stack_ptr, r15 nkeynes@228: mov.l r0, @-r15 nkeynes@228: mov.l r1, @-r15 nkeynes@228: mov.l r2, @-r15 nkeynes@228: nkeynes@228: mov.l intevt_k, r0 nkeynes@228: mov.l @r0, r1 nkeynes@228: mov.l expected_intevt_k, r2 nkeynes@228: mov.l @r2, r2 nkeynes@228: cmp/eq r1, r2 nkeynes@228: bf ex_dontcare nkeynes@228: nkeynes@228: ex_expected: nkeynes@228: mov.l interrupt_count_k, r0 nkeynes@228: mov.l @r0, r2 nkeynes@228: add #1, r2 nkeynes@228: mov.l r2, @r0 nkeynes@228: stc spc, r2 nkeynes@228: mov.l interrupt_pc_k, r0 nkeynes@228: mov.l r2, @r0 nkeynes@228: nkeynes@228: ! For most instructions, spc = raising instruction, so add 2 to get the next nkeynes@228: ! instruction. Exceptions are the slot illegals (need pc+4), and trapa/ nkeynes@228: ! user-break-after-instruction where the pc is already correct nkeynes@228: mov.l slot_illegal_k, r0 nkeynes@228: cmp/eq r0, r1 nkeynes@228: bt ex_slot_spc nkeynes@228: mov.l slot_fpu_disable_k, r0 nkeynes@228: cmp/eq r0, r1 nkeynes@228: bt ex_slot_spc nkeynes@228: mov.l trapa_exc_k, r0 nkeynes@228: cmp/eq r0, r1 nkeynes@228: bt ex_nochain nkeynes@228: mov.l break_after_k, r0 nkeynes@228: cmp/eq r0, r1 nkeynes@228: bt ex_nochain nkeynes@228: ! For everything else, spc += 2 nkeynes@228: add #2, r2 nkeynes@228: ldc r2, spc nkeynes@228: bra ex_nochain nkeynes@228: nop nkeynes@228: ex_slot_spc: nkeynes@228: add #4, r2 nkeynes@228: ldc r2, spc nkeynes@228: bra ex_nochain nkeynes@228: nop nkeynes@228: nkeynes@228: ex_dontcare: ! Not the event we were waiting for. nkeynes@233: ! Check if its a trapa #42 ("Switch to system mode") nkeynes@233: mov.l trapa_exc_k, r0 nkeynes@233: cmp/eq r0,r1 nkeynes@233: bf ex_chain nkeynes@233: mov.l trapa_k, r0 nkeynes@233: mov.l @r0, r0 nkeynes@233: shlr2 r0 nkeynes@233: cmp/eq #42, r0 nkeynes@233: bf ex_chain nkeynes@233: ! Yes, yes it is - update SSR and return without chaining nkeynes@233: stc ssr, r0 nkeynes@233: mov #0x40, r1 nkeynes@233: mov #24, r2 nkeynes@233: shld r2, r1 nkeynes@233: or r0, r1 nkeynes@233: ldc r1, ssr nkeynes@233: bra ex_nochain nkeynes@233: nop nkeynes@233: nkeynes@233: ex_chain: nkeynes@228: mov.l old_vbr_k, r2 nkeynes@228: mov.l @r2, r2 nkeynes@228: xor r0, r0 nkeynes@228: cmp/eq r0, r2 nkeynes@228: bt ex_nochain nkeynes@228: nkeynes@228: stc ssr, r0 nkeynes@228: mov.l r0, @-r15 nkeynes@228: stc spc, r0 nkeynes@228: mov.l r0, @-r15 nkeynes@228: stc sgr, r0 nkeynes@228: mov.l r0, @-r15 nkeynes@228: mov.l ex_chainreturn, r0 nkeynes@228: ldc r0, spc nkeynes@228: mova handler_stack_ptr, r0 nkeynes@228: mov.l r15, @r0 nkeynes@228: braf r2 ! Chain on nkeynes@228: nop nkeynes@228: nkeynes@228: ex_chainreturn: nkeynes@228: mov.l handler_stack_ptr, r15 nkeynes@228: mov.l @r15+, r0 nkeynes@228: ldc r0, sgr nkeynes@228: mov.l @r15+, r0 nkeynes@228: ldc r0, spc nkeynes@228: mov.l @r15+, r0 nkeynes@228: ldc r0, ssr nkeynes@228: nkeynes@228: ex_nochain: ! No previous vbr to chain to nkeynes@228: mova handler_stack_ptr, r0 nkeynes@228: mov r15, r1 nkeynes@228: add #12, r1 nkeynes@228: mov.l r1, @r0 nkeynes@228: mov.l @r15+, r2 nkeynes@228: mov.l @r15+, r1 nkeynes@228: mov.l @r15+, r0 nkeynes@233: stc sgr, r15 nkeynes@228: rte nkeynes@233: nop nkeynes@228: .align 4 nkeynes@228: expected_intevt_k: nkeynes@228: .long expected_intevt nkeynes@228: interrupt_count_k: nkeynes@228: .long _interrupt_count nkeynes@228: interrupt_pc_k: nkeynes@228: .long _interrupt_pc nkeynes@228: old_vbr_k: nkeynes@228: .long old_vbr nkeynes@228: trapa_k: nkeynes@228: .long 0xFF000020 nkeynes@228: intevt_k: nkeynes@228: .long 0xFF000028 nkeynes@228: nkeynes@228: slot_illegal_k: nkeynes@228: .long 0x000001A0 nkeynes@228: slot_fpu_disable_k: nkeynes@228: .long 0x00000820 nkeynes@228: trapa_exc_k: nkeynes@228: .long 0x00000160 nkeynes@228: break_after_k: nkeynes@228: .long 0x000001E0 nkeynes@228: nkeynes@228: handler_stack_ptr: nkeynes@228: .long handler_stack_end nkeynes@228: nkeynes@228: handler_stack: nkeynes@228: .skip 0x200 nkeynes@228: handler_stack_end: