started working on interrupts master
authorJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 26 Mar 2024 20:08:08 +0000 (22:08 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 26 Mar 2024 20:08:08 +0000 (22:08 +0200)
src/debug.c [new file with mode: 0644]
src/debug.h [new file with mode: 0644]
src/intr.c [new file with mode: 0644]
src/intr.h [new file with mode: 0644]
src/intr_asm.S [new file with mode: 0644]
src/main.c
src/psxregs.h

diff --git a/src/debug.c b/src/debug.c
new file mode 100644 (file)
index 0000000..7169d16
--- /dev/null
@@ -0,0 +1,19 @@
+#include "gpu.h"
+#include "psxregs.h"
+
+void panic(const char *fmt, ...)
+{
+       gpu_reset();
+       gpu_display(0);
+       gpu_setmode(320, 264, 15, 50);
+       gpu_dispstart(0, 0);
+       gpu_cliprect(0, 0, 320, 264);
+       gpu_origin(0, 0);
+
+       REG_GP0 = GPCMD(GP0_TEXPG) | TEXPG_DITHER | TEXPG_DRAWDISP;
+
+       gpu_fillrect(0, 0, 320, 264, 0xff);
+       gpu_display(1);
+
+       for(;;);
+}
diff --git a/src/debug.h b/src/debug.h
new file mode 100644 (file)
index 0000000..df887cd
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef DEBUG_H_
+#define DEBUG_H_
+
+void panic(const char *fmt, ...);
+
+#endif /* DEBUG_H_ */
diff --git a/src/intr.c b/src/intr.c
new file mode 100644 (file)
index 0000000..7bef4cb
--- /dev/null
@@ -0,0 +1,18 @@
+#include "intr.h"
+#include "debug.h"
+
+static void (*handler[NUM_IRQS])(struct intr_frame*);
+
+void set_irq_handler(int irq, void (*func)(struct intr_frame*))
+{
+       handler[irq] = func;
+}
+
+void intr_dispatch(struct intr_frame *frm)
+{
+       if(((frm->cause >> 2) & 0x1f) == 0) {
+               /* interrupt */
+       } else {
+               panic("unhandled exception");
+       }
+}
diff --git a/src/intr.h b/src/intr.h
new file mode 100644 (file)
index 0000000..d7bab79
--- /dev/null
@@ -0,0 +1,49 @@
+#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_ */
diff --git a/src/intr_asm.S b/src/intr_asm.S
new file mode 100644 (file)
index 0000000..6b23a2d
--- /dev/null
@@ -0,0 +1,145 @@
+#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:
index 3850c99..2d93924 100644 (file)
@@ -1,3 +1,4 @@
+#include "intr.h"
 #include "gpu.h"
 #include "gte.h"
 #include "psxregs.h"
@@ -20,6 +21,8 @@ int main(void)
        int resv[3];
        int yoffs = 0;
 
+       intr_init();
+
        gte_init();
 
        gpu_reset();
index d3042c3..44be478 100644 (file)
@@ -1,9 +1,13 @@
 #ifndef PSXREGS_H_
 #define PSXREGS_H_
 
+#include <stdint.h>
+
+#define INTR_VEC               (*(volatile uint32_t*)0x80000080)
+
 #define REG_BASE               0x1f800000
-#define REGPTR32(x)            (*(volatile unsigned long*)(REG_BASE | (x)))
-#define REGPTR16(x)            (*(volatile unsigned short*)(REG_BASE | (x)))
+#define REGPTR32(x)            (*(volatile uint32_t*)(REG_BASE | (x)))
+#define REGPTR16(x)            (*(volatile uint16_t*)(REG_BASE | (x)))
 
 /* --- GPU --- */
 #define REGN_GP0               0x1810
 #define REG_IMASK              REGPTR32(REGN_IMASK)
 
 enum {
-       IRQ_VBLANK      = 0x0001,
-       IRQ_GPU         = 0x0002,
-       IRQ_CDROM       = 0x0004,
-       IRQ_DMA         = 0x0008,
-       IRQ_TIMER0      = 0x0010,
-       IRQ_TIMER1      = 0x0020,
-       IRQ_TIMER2      = 0x0040,
-       IRQ_JOYMC       = 0x0080,
-       IRQ_SIO         = 0x0100,
-       IRQ_SPU         = 0x0200,
-       IRQ_LPEN        = 0x0400
+       IRQ_VBLANK,
+       IRQ_GPU,
+       IRQ_CDROM,
+       IRQ_DMA,
+       IRQ_TIMER0, IRQ_TIMER1, IRQ_TIMER2,
+       IRQ_JOYMC,
+       IRQ_SIO,
+       IRQ_SPU,
+       IRQ_LPEN
 };
 
 #define GPCMD(cmd)     ((cmd) << 24)