From 213d72bb80fbc8c1661bba925c0ef013cf50385f Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Tue, 26 Mar 2024 22:08:08 +0200 Subject: [PATCH] started working on interrupts --- src/debug.c | 19 ++++++++ src/debug.h | 6 +++ src/intr.c | 18 +++++++ src/intr.h | 49 +++++++++++++++++++ src/intr_asm.S | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 3 ++ src/psxregs.h | 28 ++++++----- 7 files changed, 255 insertions(+), 13 deletions(-) create mode 100644 src/debug.c create mode 100644 src/debug.h create mode 100644 src/intr.c create mode 100644 src/intr.h create mode 100644 src/intr_asm.S diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 0000000..7169d16 --- /dev/null +++ b/src/debug.c @@ -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 index 0000000..df887cd --- /dev/null +++ b/src/debug.h @@ -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 index 0000000..7bef4cb --- /dev/null +++ b/src/intr.c @@ -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 index 0000000..d7bab79 --- /dev/null +++ b/src/intr.h @@ -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 index 0000000..6b23a2d --- /dev/null +++ b/src/intr_asm.S @@ -0,0 +1,145 @@ +#include + .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: diff --git a/src/main.c b/src/main.c index 3850c99..2d93924 100644 --- a/src/main.c +++ b/src/main.c @@ -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(); diff --git a/src/psxregs.h b/src/psxregs.h index d3042c3..44be478 100644 --- a/src/psxregs.h +++ b/src/psxregs.h @@ -1,9 +1,13 @@ #ifndef PSXREGS_H_ #define PSXREGS_H_ +#include + +#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 @@ -24,17 +28,15 @@ #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) -- 1.7.10.4