--- /dev/null
+#ifndef INTR_H_
+#define INTR_H_
+
+#include "psxregs.h"
+
+#define NUM_IRQS 11
+
+struct intr_frame {
+ uint32_t sr, cause, epc;
+ uint32_t r[29]; /* 29 regs, don't save zero, k0, and k1 */
+ uint32_t lo, hi;
+} __attribute__ ((packed));
+
+void intr_init(void);
+
+/* set CP0 SR (reg 12) IM bits (8-15) to enable all interrupts */
+#define enable() \
+ asm volatile ( \
+ "mfc0 $12, $8\n\t" \
+ "nop\n\t" \
+ "ori $8, $8, 0xff00\n\t" \
+ "nop\n\t" \
+ "mtc0 $12, $8\n\t" \
+ ::: "$8")
+
+/* clear CP0 SR (reg 12) IM bits (8-15) to disable all interrupts */
+#define disable() \
+ asm volatile ( \
+ "lui $9, 0xffff\n\t" \
+ "mfc0 $12, $8\n\t" \
+ "ori $9, $9, 0x00ff\n\t" \
+ "nop\n\t" \
+ "and $8, $8, $9\n\t" \
+ "nop\n\t" \
+ "mtc0 $12, $8\n\t" \
+ ::: "$8", "$9")
+
+#define mask_all() (REG_IMASK = 0x7ff)
+#define unmask_all() (REG_IMASK = 0)
+
+#define mask_irq(n) (REG_IMASK &= ~(1 << (n)))
+#define unmask_irq(n) (REG_IMASK |= 1 << (n))
+
+#define ack_irq(n) (REG_ISTAT = 1 << (n))
+#define irq_status(n) (REG_ISTAT & (1 << (n)))
+
+void set_irq_handler(int irq, void (*func)(struct intr_frame*));
+
+#endif /* INTR_H_ */
--- /dev/null
+#include <regdef.h>
+ .text
+ .set noreorder
+
+ .equ C0_SR, $12
+ .equ C0_CAUSE, $13
+ .equ C0_EPC, $14
+
+ .macro enable_intr
+ mfc0 C0_SR, t0
+ nop
+ ori t0, t0, 0xff00
+ nop
+ mtc0 C0_SR, t0
+ .endm
+
+ .macro disable_intr
+ lui t1, 0xffff
+ mfc0 C0_SR, t0
+ ori t1, t1, 0x00ff
+ nop
+ and t0, t0, t1
+ nop
+ mtc0 C0_SR, t0
+ .endm
+
+ .extern intr_dispatch
+
+ .globl intr_init
+intr_init:
+ disable_intr
+ la t0, intr_entry
+ nop
+ sw t0, 0x80(zero)
+ enable_intr
+ jr ra
+ nop
+
+
+ .equ IFRM_SR, 0
+ .equ IFRM_CAUSE, 4
+ .equ IFRM_EPC, 8
+ .equ IFRM_R1, 12
+ .equ IFRM_LO, 128
+ .equ IFRM_HI, 132
+ .equ IFRM_SIZE, 136
+
+ .set noat
+ .globl intr_entry
+intr_entry:
+ addi k1, sp, -IFRM_SIZE
+ # save registers
+ sw $1, IFRM_R1(k1) # at
+ sw $2, IFRM_R1+4(k1) # v0
+ sw $3, IFRM_R1+8(k1) # v1
+ sw $4, IFRM_R1+12(k1) # a0
+ sw $5, IFRM_R1+16(k1) # a1
+ sw $6, IFRM_R1+20(k1) # a2
+ sw $7, IFRM_R1+24(k1) # a3
+ sw $8, IFRM_R1+28(k1) # t0
+ sw $9, IFRM_R1+32(k1) # t1
+ sw $10, IFRM_R1+36(k1) # t2
+ sw $11, IFRM_R1+40(k1) # t3
+ sw $12, IFRM_R1+44(k1) # t4
+ sw $13, IFRM_R1+48(k1) # t5
+ sw $14, IFRM_R1+52(k1) # t6
+ sw $15, IFRM_R1+56(k1) # t7
+ sw $16, IFRM_R1+60(k1) # s0
+ sw $17, IFRM_R1+64(k1) # s1
+ sw $18, IFRM_R1+68(k1) # s2
+ sw $19, IFRM_R1+72(k1) # s3
+ sw $20, IFRM_R1+76(k1) # s4
+ sw $21, IFRM_R1+80(k1) # s5
+ sw $22, IFRM_R1+84(k1) # s6
+ sw $23, IFRM_R1+88(k1) # s7
+ sw $24, IFRM_R1+92(k1) # t8
+ sw $25, IFRM_R1+96(k1) # t9
+ sw $28, IFRM_R1+100(k1) # gp
+ sw $29, IFRM_R1+104(k1) # sp
+ sw $30, IFRM_R1+108(k1) # fp
+ sw $31, IFRM_R1+112(k1) # ra
+ move sp, k1
+ # save sr/cause/epc
+ mfc0 k0, C0_SR
+ mfc0 k1, C0_CAUSE
+ sw k0, IFRM_SR(sp)
+ mfc0 k0, C0_EPC
+ sw k1, IFRM_CAUSE(sp)
+ sw k0, IFRM_EPC(sp)
+ # save hi/lo
+ mfhi k1
+ mflo k0
+ sw k1, IFRM_HI(sp)
+ sw k0, IFRM_LO(sp)
+
+ # call C dispatch
+ la gp, _gp # make sure gp points where the compiler expects
+ move a0, sp
+ jal intr_dispatch
+ addi sp, -16
+ move k1, sp
+ addi sp, 16
+
+ # restore registers
+ lw $1, IFRM_R1(k1) # at
+ lw $2, IFRM_R1+4(k1) # v0
+ lw $3, IFRM_R1+8(k1) # v1
+ lw $4, IFRM_R1+12(k1) # a0
+ lw $5, IFRM_R1+16(k1) # a1
+ lw $6, IFRM_R1+20(k1) # a2
+ lw $7, IFRM_R1+24(k1) # a3
+ lw $8, IFRM_R1+28(k1) # t0
+ lw $9, IFRM_R1+32(k1) # t1
+ lw $10, IFRM_R1+36(k1) # t2
+ lw $11, IFRM_R1+40(k1) # t3
+ lw $12, IFRM_R1+44(k1) # t4
+ lw $13, IFRM_R1+48(k1) # t5
+ lw $14, IFRM_R1+52(k1) # t6
+ lw $15, IFRM_R1+56(k1) # t7
+ lw $16, IFRM_R1+60(k1) # s0
+ lw $17, IFRM_R1+64(k1) # s1
+ lw $18, IFRM_R1+68(k1) # s2
+ lw $19, IFRM_R1+72(k1) # s3
+ lw $20, IFRM_R1+76(k1) # s4
+ lw $21, IFRM_R1+80(k1) # s5
+ lw $22, IFRM_R1+84(k1) # s6
+ lw $23, IFRM_R1+88(k1) # s7
+ lw $24, IFRM_R1+92(k1) # t8
+ lw $25, IFRM_R1+96(k1) # t9
+ lw $28, IFRM_R1+100(k1) # gp
+ lw $29, IFRM_R1+104(k1) # sp
+ lw $30, IFRM_R1+108(k1) # fp
+ lw k0, IFRM_SR(k1)
+ lw $31, IFRM_R1+112(k1) # ra
+
+ # restore sr
+ mtc0 k0, C0_SR
+
+ lw k0, IFRM_EPC(k1)
+ nop
+ j k0
+ rfe # bd
+ .set at
+
+# vi:ts=8 sts=8 sw=8 ft=mips: