summaryrefslogtreecommitdiff
path: root/lib/ultralib/src/os/exceptasm.s
diff options
context:
space:
mode:
authorAnghelo Carvajal <angheloalf95@gmail.com>2023-03-28 23:42:56 -0300
committerGitHub <noreply@github.com>2023-03-29 03:42:56 +0100
commitd66a21685f45d130f980e8a5ec7b08cfe189e40b (patch)
treef11b3b09dc5772e419fe08d3d0ead4e778def57f /lib/ultralib/src/os/exceptasm.s
parent6a5e64cc4c26398cc607bb02cdc12a056ddf42d1 (diff)
Initial repo setup (#1)
* git subrepo clone git@github.com:ethteck/splat.git tools/splat subrepo: subdir: "tools/splat" merged: "4fec014" upstream: origin: "git@github.com:ethteck/splat.git" branch: "master" commit: "4fec014" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * gitignore * decompress_baserom.py * Initial yaml * run flib * more yaml stuff * Builds an uncompressed ROM * setup ido download * git subrepo clone git@github.com:simonlindholm/asm-differ.git tools/asm-differ subrepo: subdir: "tools/asm-differ" merged: "ae40866" upstream: origin: "git@github.com:simonlindholm/asm-differ.git" branch: "main" commit: "ae40866" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * git subrepo clone git@github.com:simonlindholm/asm-processor.git tools/asm-processor subrepo: subdir: "tools/asm-processor" merged: "bbd86ea" upstream: origin: "git@github.com:simonlindholm/asm-processor.git" branch: "main" commit: "bbd86ea" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * git subrepo clone (merge) git@github.com:EllipticEllipsis/fado.git tools/fado subrepo: subdir: "tools/fado" merged: "8d896ee" upstream: origin: "git@github.com:EllipticEllipsis/fado.git" branch: "master" commit: "8d896ee" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * setup ido in makefile * data and rodata * add automatic file splits * bootstrap most symbol_addrs * git subrepo clone --branch=irix git@github.com:hensldm/ultralib.git lib/ultralib subrepo: subdir: "lib/ultralib" merged: "0d1e095" upstream: origin: "git@github.com:hensldm/ultralib.git" branch: "irix" commit: "0d1e095" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * setup ido building * various tooling * git subrepo pull tools/asm-differ subrepo: subdir: "tools/asm-differ" merged: "857b398" upstream: origin: "git@github.com:simonlindholm/asm-differ.git" branch: "main" commit: "857b398" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * Change defines to match IDO * review * newlin * update gitignore * Windows error * D_01000000 * yeet settings.json * yeet * git subrepo clone git@github.com:decompals/ultralib.git lib/ultralib subrepo: subdir: "lib/ultralib" merged: "d03b2a3" upstream: origin: "git@github.com:decompals/ultralib.git" branch: "main" commit: "d03b2a3" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * clangformat and clangtidy * Setup a bunch of headers * bootstrap boot and code functions and variables headers * global.h * update format.py includes * -D_MIPS_SZLONG=32 * format.py: --verbose * Update tools/decompress_baserom.py Co-authored-by: Derek Hensley <hensley.derek58@gmail.com> * Add libc to global.h * review * yeet saved_regs * yeet headers * yeet _MSC_VER * more header cleanup * add readme licensing note --------- Co-authored-by: Derek Hensley <hensley.derek58@gmail.com>
Diffstat (limited to 'lib/ultralib/src/os/exceptasm.s')
-rw-r--r--lib/ultralib/src/os/exceptasm.s1019
1 files changed, 1019 insertions, 0 deletions
diff --git a/lib/ultralib/src/os/exceptasm.s b/lib/ultralib/src/os/exceptasm.s
new file mode 100644
index 0000000..5a0bdcf
--- /dev/null
+++ b/lib/ultralib/src/os/exceptasm.s
@@ -0,0 +1,1019 @@
+#include "PR/R4300.h"
+#include "sys/asm.h"
+#include "sys/regdef.h"
+#include "PR/os.h"
+#include "PR/rcp.h"
+#include "PR/rdb.h"
+#include "exceptasm.h"
+#include "threadasm.h"
+
+#define KMC_CODE_ENTRY 0xBFF00014
+#define KMC_WPORT 0xBFF08000
+#define KMC_STAT 0xBFF08004
+
+.rdata
+
+#define REDISPATCH 0x00
+#define SW1 0x04
+#define SW2 0x08
+#define RCP 0x0c
+#define CART 0x10
+#define PRENMI 0x14
+#define IP6_HDLR 0x18
+#define IP7_HDLR 0x1c
+#define COUNTER 0x20
+
+__osIntOffTable:
+ .byte REDISPATCH
+ .byte PRENMI
+ .byte IP6_HDLR
+ .byte IP6_HDLR
+ .byte IP7_HDLR
+ .byte IP7_HDLR
+ .byte IP7_HDLR
+ .byte IP7_HDLR
+ .byte COUNTER
+ .byte COUNTER
+ .byte COUNTER
+ .byte COUNTER
+ .byte COUNTER
+ .byte COUNTER
+ .byte COUNTER
+ .byte COUNTER
+ .byte REDISPATCH
+ .byte SW1
+ .byte SW2
+ .byte SW2
+ .byte RCP
+ .byte RCP
+ .byte RCP
+ .byte RCP
+ .byte CART
+ .byte CART
+ .byte CART
+ .byte CART
+ .byte CART
+ .byte CART
+ .byte CART
+ .byte CART
+
+__osIntTable:
+ .word redispatch, sw1, sw2, rcp, cart, prenmi, IP6_Hdlr, IP7_Hdlr, counter
+
+#ifndef _FINALROM
+EXPORT(__osCauseTable_pt)
+ .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0
+ .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
+ .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+#endif
+
+.data
+
+EXPORT(__osHwIntTable)
+ .word 0, 0
+ .word 0, 0
+ .word 0, 0
+ .word 0, 0
+ .word 0, 0
+
+EXPORT(__osPiIntTable)
+ .word 0, 0
+
+#ifndef _FINALROM
+__osRdb_DbgRead_Ct:
+ .word 0
+
+__osRdb_Mesg:
+ .word 0
+
+__os_Kdebug_Pkt:
+ .word 0
+
+__osPreviousThread:
+ .word 0
+#endif
+
+.text
+
+LEAF(__osExceptionPreamble)
+ la k0, __osException
+ jr k0
+END(__osExceptionPreamble)
+
+#ifndef _FINALROM
+LEAF(__ptExceptionPreamble)
+.set noreorder
+ sw k0, -0x10(sp)
+ b pt_next
+ lui k0, %hi(__ptException)
+ nop
+ nop
+pt_next:
+ addiu k0, %lo(__ptException)
+ jr k0
+ nop
+.set reorder
+END(__ptExceptionPreamble)
+
+LEAF(__ptException)
+.set noreorder
+ mfc0 k0, C0_CAUSE
+ andi k0, k0, 0x7c
+ bnez k0, pt_not_Int
+ srl k0, k0, 2
+ mfc0 k0, C0_CAUSE
+ nop
+ andi k0, k0, CAUSE_IP7
+ beqz k0, __osException
+ nop
+ j pt_break
+ nop
+pt_not_Int:
+ sw k1, -8(sp)
+ /* determine if the pt exception handler should deal with this cause */
+ la k1, __osCauseTable_pt
+ add k1, k1, k0
+ lbu k0, (k1)
+ beqz k0, __osException
+ nop
+pt_break:
+pi_ok_loop:
+ lw k0, PHYS_TO_K1(PI_STATUS_REG)
+ nop
+ andi k0, k0, (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)
+ bnez k0, pi_ok_loop
+ nop
+ lw k0, KMC_STAT
+ nop
+ andi k0, k0, 8
+ bnez k0, pt_prof
+ li k0, KMC_CODE_ENTRY
+ lw k1, -8(sp)
+ jr k0
+ addiu sp, sp, -0x60
+pt_prof:
+ mfc0 k0, C0_EPC
+ /* the following two ways is a (necessarily) messy way to write "sw k0, KMC_WPORT" without using at */
+ lui k1, (KMC_WPORT >> 16 + 1)
+ sw k0, -(KMC_WPORT & 0xFFFF)(k1)
+ lw k1, -8(sp)
+ lw k0, -0x10(sp)
+ eret
+ nop
+.set reorder
+END(__ptException)
+#endif
+
+LEAF(__osException)
+ la k0, __osThreadSave
+ /* save AT */
+.set noat
+ sd $1, THREAD_GP1(k0);
+.set at
+ /* save sr */
+STAY2(mfc0 k1, C0_SR)
+ sw k1, THREAD_SR(k0)
+ /* clear interrupts */
+ and k1, k1, -4
+STAY2(mtc0 k1, C0_SR)
+ /* save other regs */
+ sd $8, THREAD_GP8(k0)
+ sd $9, THREAD_GP9(k0)
+ sd $10, THREAD_GP10(k0)
+ /* say fp has not been used */
+ sw zero, THREAD_FP(k0)
+ /* this instruction is useless, leftover because of bad placement of an ifdef for the debug version */
+STAY2(mfc0 t0, C0_CAUSE)
+#ifndef _FINALROM
+ lw t2, __kmc_pt_mode
+ bnez t2, skip_kmc_mode
+ andi t1, t0, 0x7c
+ li t2, 0
+ bne t1, t2, savecontext
+ and t1, k1, t0
+ andi t2, t1, CAUSE_IP7
+ beqz t2, notIP7
+ /* clear rdb write interrupt */
+ li t1, RDB_WRITE_INTR_REG
+ sw zero, (t1)
+IP7check:
+STAY2(mfc0 t0, C0_CAUSE)
+ andi t0, t0, CAUSE_IP7
+ bne zero, t0, IP7check
+ lui t2, (RDB_BASE_REG >> 16)
+ lw t0, (RDB_BASE_REG & 0xFFFF)(t2)
+ srl t1, t0, 0x1a
+ andi t1, t1, 0x3f
+ li t2, RDB_TYPE_HtoG_DATA
+ beq t1, t2, HandData
+ li t2, RDB_TYPE_HtoG_DEBUG
+ beq t1, t2, HandDbg
+ li t2, RDB_TYPE_HtoG_KDEBUG
+ beq t1, t2, HandKDebug
+ li t2, RDB_TYPE_HtoG_DEBUG_CT
+ beq t1, t2, DbgCnt
+ li t2, RDB_TYPE_HtoG_DATA_DONE
+ beq t1, t2, DataRead
+ li t2, RDB_TYPE_HtoG_LOG_DONE
+ beq t1, t2, LogRead
+ li t2, RDB_TYPE_HtoG_REQ_RAMROM
+ beq t1, t2, ReqRamrom
+ li t2, RDB_TYPE_HtoG_FREE_RAMROM
+ beq t1, t2, FreeRamrom
+ li t2, RDB_TYPE_HtoG_PROF_SIGNAL
+ beq t1, t2, SignalProf
+ b rdbout
+SignalProf:
+ li t2, 1
+ srl t1, t0, 0x10
+ andi t1, t1, 0xff
+ beq t1, t2, AckProf
+ li t2, 0xa8
+ sw t2, __osRdb_Mesg
+ b savecontext
+AckProf:
+ li t2, 0xb0
+ sw t2, __osRdb_Mesg
+ b savecontext
+HandKDebug:
+ sw t0, __os_Kdebug_Pkt
+ b savecontext
+DbgCnt:
+ li t2, 0xffffff
+ and t1, t0, t2
+ sw t1, __osRdb_DbgRead_Ct
+ b rdbout
+DataRead:
+ li t2, 0x88
+ sw t2, __osRdb_Mesg
+ b savecontext
+LogRead:
+ li t2, 0x80
+ sw t2, __osRdb_Mesg
+ b savecontext
+ReqRamrom:
+ li t2, 0x90
+ sw t2, __osRdb_Mesg
+ b savecontext
+FreeRamrom:
+ li t2, 0x98
+ sw t2, __osRdb_Mesg
+ b savecontext
+HandData:
+ srl t1, t0, 0x18
+ andi t1, t1, 3
+ beq zero, t1, rdbout
+ lw t2, __osRdb_Read_Data_Ct
+ subu t2, t2, t1
+ sw t2, __osRdb_Read_Data_Ct
+ sd t3, THREAD_GP11(k0)
+ lw t3, __osRdb_Read_Data_Buf
+ srl t2, t0, 0x10
+ andi t2, t2, 0xff
+ sb t2, (t3)
+ addi t3, t3, 1
+ addi t1, t1, -1
+ beq zero, t1, doneData
+ srl t2, t0, 8
+ andi t2, t2, 0xff
+ sb t2, (t3)
+ addi t3, t3, 1
+ addi t1, t1, -1
+ beq zero, t1, doneData
+ andi t0, t0, 0xff
+ sb t0, (t3)
+ addi t3, t3, 1
+doneData:
+ sw t3, __osRdb_Read_Data_Buf
+ ld t3, THREAD_GP11(k0)
+ lw t2, __osRdb_Read_Data_Ct
+ bne zero, t2, rdbout
+ li t2, 0x78
+ sw t2, __osRdb_Mesg
+ b savecontext
+HandDbg:
+ srl t1, t0, 0x18
+ andi t1, t1, 3
+ beq zero, t1, rdbout
+ lw t2, __osRdb_DbgRead_Ct
+ subu t2, t2, t1
+ sw t2, __osRdb_DbgRead_Ct
+ sd t3, THREAD_GP11(k0)
+ lw t3, __osRdb_DbgRead_Buf
+ bne zero, t3, 1f
+ ld t3, THREAD_GP11(k0)
+ b rdbout
+1:
+ srl t2, t0, 0x10
+ andi t2, t2, 0xff
+ sb t2, (t3)
+ addi t3, t3, 1
+ addi t1, t1, -1
+ beq zero, t1, doneDbg
+ srl t2, t0, 8
+ andi t2, t2, 0xff
+ sb t2, (t3)
+ addi t3, t3, 1
+ addi t1, t1, -1
+ beq zero, t1, doneDbg
+ andi t0, t0, 0xff
+ sb t0, (t3)
+ addi t3, t3, 1
+doneDbg:
+ sw t3, __osRdb_DbgRead_Buf
+ ld t3, THREAD_GP11(k0)
+ lw t2, __osRdb_DbgRead_Ct
+ bne zero, t2, rdbout
+ li t2, 0xa0
+ sw t2, __osRdb_Mesg
+ b savecontext
+notIP7:
+ andi t2, t1, CAUSE_IP6
+ beqz t2, savecontext
+ /* clear rdb read interrupt */
+ li t1, RDB_READ_INTR_REG
+ sw zero, (t1)
+ lw t2, __osRdb_IP6_Ct
+ bnez t2, 1f
+ li t2, 1
+ sw t2, __osRdb_IP6_Empty
+ b rdbout
+1:
+ addi t2, t2, -1
+ sw t2, __osRdb_IP6_Ct
+ lw t0, __osRdb_IP6_Data
+ lw t1, __osRdb_IP6_CurSend
+ sll t2, t1, 2
+ add t0, t2, t0
+ lw t2, (t0)
+ addi t1, t1, 1
+ lw t0, __osRdb_IP6_Size
+ sub t0, t0, t1
+ bgtz t0, 5f
+ li t1, 0
+5:
+ sw t1, __osRdb_IP6_CurSend
+checkIP6:
+STAY2(mfc0 t0, C0_CAUSE)
+ andi t0, t0, CAUSE_IP6
+ bne zero, t0, checkIP6
+ lui t0, (RDB_BASE_REG >> 16)
+ sw t2, (RDB_BASE_REG & 0xFFFF)(t0)
+rdbout:
+ ld t0, THREAD_GP8(k0)
+ ld t1, THREAD_GP9(k0)
+ ld t2, THREAD_GP10(k0)
+.set noat
+ ld $1, THREAD_GP1(k0)
+.set at
+ lw k1, THREAD_SR(k0)
+STAY2(mtc0 k1, C0_SR)
+ nop
+ nop
+ nop
+ nop
+ eret
+
+skip_kmc_mode:
+#endif
+
+savecontext:
+ move t0, k0
+ lw k0, __osRunningThread
+#ifndef _FINALROM
+ sw k0, __osPreviousThread
+#endif
+ ld t1, THREAD_GP1(t0)
+ sd t1, THREAD_GP1(k0)
+ ld t1, THREAD_SR(t0)
+ sd t1, THREAD_SR(k0)
+ ld t1, THREAD_GP8(t0)
+ sd t1, THREAD_GP8(k0)
+ ld t1, THREAD_GP9(t0)
+ sd t1, THREAD_GP9(k0)
+ ld t1, THREAD_GP10(t0)
+ sd t1, THREAD_GP10(k0)
+ sd $2, THREAD_GP2(k0)
+ sd $3, THREAD_GP3(k0)
+ sd $4, THREAD_GP4(k0)
+ sd $5, THREAD_GP5(k0)
+ sd $6, THREAD_GP6(k0)
+ sd $7, THREAD_GP7(k0)
+ sd $11, THREAD_GP11(k0)
+ sd $12, THREAD_GP12(k0)
+ sd $13, THREAD_GP13(k0)
+ sd $14, THREAD_GP14(k0)
+ sd $15, THREAD_GP15(k0)
+ sd $16, THREAD_GP16(k0)
+ sd $17, THREAD_GP17(k0)
+ sd $18, THREAD_GP18(k0)
+ sd $19, THREAD_GP19(k0)
+ sd $20, THREAD_GP20(k0)
+ sd $21, THREAD_GP21(k0)
+ sd $22, THREAD_GP22(k0)
+ sd $23, THREAD_GP23(k0)
+ sd $24, THREAD_GP24(k0)
+ sd $25, THREAD_GP25(k0)
+ sd $28, THREAD_GP28(k0)
+ sd $29, THREAD_GP29(k0)
+ sd $30, THREAD_GP30(k0)
+ sd $31, THREAD_GP31(k0)
+
+ mflo t0
+ sd t0, THREAD_LO(k0)
+ mfhi t0
+ sd t0, THREAD_HI(k0)
+
+ lw k1, THREAD_SR(k0)
+ andi t1, k1, SR_IMASK
+ beqz t1, savercp
+
+/*if any interrupts are enabled*/
+ la t0, __OSGlobalIntMask
+ lw t0, 0(t0)
+ xor t2, t0, ~0 /* not except not using not */
+ andi t2, t2, SR_IMASK
+ or ta0, t1, t2
+ and t3, k1, ~SR_IMASK
+ or t3, t3, ta0
+ sw t3, THREAD_SR(k0)
+ andi t0, t0, SR_IMASK
+ and t1, t1, t0
+ and k1, k1, ~SR_IMASK
+ or k1, k1, t1
+savercp:
+
+ lw t1, PHYS_TO_K1(MI_INTR_MASK_REG)
+ beqz t1, endrcp
+
+ la t0, __OSGlobalIntMask
+ lw t0, 0(t0)
+
+ srl t0, t0, 0x10
+ xor t0, t0, ~0
+ andi t0, t0, 0x3f
+ lw ta0, THREAD_RCP(k0)
+ and t0, t0, ta0
+ or t1, t1, t0
+endrcp:
+ sw t1, THREAD_RCP(k0)
+STAY2(mfc0 t0, C0_EPC)
+ sw t0, THREAD_PC(k0)
+ lw t0, THREAD_FP(k0)
+ beqz t0, 1f
+ cfc1 t0, fcr31
+ nop
+ sw t0, THREAD_FPCSR(k0)
+ sdc1 $f0, THREAD_FP0(k0)
+ sdc1 $f2, THREAD_FP2(k0)
+ sdc1 $f4, THREAD_FP4(k0)
+ sdc1 $f6, THREAD_FP6(k0)
+ sdc1 $f8, THREAD_FP8(k0)
+ sdc1 $f10, THREAD_FP10(k0)
+ sdc1 $f12, THREAD_FP12(k0)
+ sdc1 $f14, THREAD_FP14(k0)
+ sdc1 $f16, THREAD_FP16(k0)
+ sdc1 $f18, THREAD_FP18(k0)
+ sdc1 $f20, THREAD_FP20(k0)
+ sdc1 $f22, THREAD_FP22(k0)
+ sdc1 $f24, THREAD_FP24(k0)
+ sdc1 $f26, THREAD_FP26(k0)
+ sdc1 $f28, THREAD_FP28(k0)
+ sdc1 $f30, THREAD_FP30(k0)
+1:
+STAY2(mfc0 t0, C0_CAUSE)
+ sw t0, THREAD_CAUSE(k0)
+
+ li t1, OS_STATE_RUNNABLE
+ sh t1, THREAD_STATE(k0)
+
+#ifndef _FINALROM
+ lw a0, __os_Kdebug_Pkt
+ beqz a0, no_kdebug
+ sw zero, __os_Kdebug_Pkt
+ jal kdebugserver
+ b __osDispatchThreadSave
+no_kdebug:
+ lw a0, __osRdb_Mesg
+ beqz a0, no_rdb_mesg
+ sw zero, __osRdb_Mesg
+ jal send_mesg
+ lw t0, 0x120(k0)
+no_rdb_mesg:
+#endif
+
+ andi t1, t0, CAUSE_EXCMASK
+ li t2, EXC_BREAK
+ beq t1, t2, handle_break
+
+ li t2, EXC_CPU
+ beq t1, t2, handle_CpU
+
+ li t2, EXC_INT
+ bne t1, t2, panic
+handle_interrupt:
+ and s0, k1, t0
+next_interrupt:
+ andi t1, s0, SR_IMASK
+ srl t2, t1, 0xc
+ bnez t2, 1f
+
+ srl t2, t1, SR_IMASKSHIFT
+ addi t2, t2, 16
+1:
+
+ lbu t2, __osIntOffTable(t2)
+
+ lw t2, __osIntTable(t2)
+ jr t2
+
+IP6_Hdlr:
+ and s0, s0, ~CAUSE_IP6
+ b next_interrupt
+
+IP7_Hdlr:
+ and s0, s0, ~CAUSE_IP7
+ b next_interrupt
+
+counter:
+STAY2(mfc0 t1, C0_COMPARE)
+STAY2(mtc0 t1, C0_COMPARE)
+ li a0, MESG(OS_EVENT_COUNTER)
+ jal send_mesg
+ and s0, s0, ~CAUSE_IP8
+ b next_interrupt
+
+cart:
+ and s0, s0, ~CAUSE_IP4
+ la t1, __osHwIntTable
+ add t1, HWINTR_SIZE
+ lw t2, HWINTR_CALLBACK(t1)
+
+ beqz t2, 1f
+
+ lw sp, HWINTR_SP(t1)
+ jalr t2
+
+ beqz v0, 1f
+ b redispatch
+
+1:
+ li a0, MESG(OS_EVENT_CART)
+ jal send_mesg
+ b next_interrupt
+
+rcp:
+ lw s1, PHYS_TO_K1(MI_INTR_REG)
+ la t0, __OSGlobalIntMask
+ lw t0, (t0)
+
+ srl t0, t0, 0x10
+ and s1, s1, t0
+ andi t1, s1, MI_INTR_SP
+ beqz t1, vi
+
+ andi s1, s1, 0x3e
+ lw ta0, PHYS_TO_K1(SP_STATUS_REG)
+ li t1, (SP_CLR_INTR | SP_CLR_SIG3)
+
+ sw t1, PHYS_TO_K1(SP_STATUS_REG)
+ andi ta0, ta0, 0x300
+ beqz ta0, sp_other_break
+
+ li a0, MESG(OS_EVENT_SP)
+ jal send_mesg
+
+ beqz s1, NoMoreRcpInts
+
+ b vi
+
+sp_other_break:
+ li a0, MESG(OS_EVENT_SP_BREAK)
+ jal send_mesg
+
+ beqz s1, NoMoreRcpInts
+
+vi:
+ andi t1, s1, 0x8
+ beqz t1, ai
+
+ andi s1, s1, 0x37
+
+ sw zero, PHYS_TO_K1(VI_CURRENT_REG)
+ li a0, MESG(OS_EVENT_VI)
+ jal send_mesg
+ beqz s1, NoMoreRcpInts
+
+ai:
+ andi t1, s1, 0x4
+ beqz t1, si
+
+ andi s1, s1, 0x3b
+
+ li t1, 1
+ sw t1, PHYS_TO_K1(AI_STATUS_REG)
+
+ li a0, MESG(OS_EVENT_AI)
+ jal send_mesg
+ beqz s1, NoMoreRcpInts
+
+si:
+ andi t1, s1, 0x2
+ beqz t1, pi
+
+ andi s1, s1, 0x3d
+ /* any write clears interrupts */
+ sw zero, PHYS_TO_K1(SI_STATUS_REG)
+ li a0, MESG(OS_EVENT_SI)
+ jal send_mesg
+ beqz s1, NoMoreRcpInts
+
+pi:
+ andi t1, s1, 0x10
+ beqz t1, dp
+
+ andi s1, s1, 0x2f
+
+ li t1, PI_STATUS_CLR_INTR
+ sw t1, PHYS_TO_K1(PI_STATUS_REG)
+
+ la t1, __osPiIntTable
+ lw t2, (t1)
+ beqz t2, 1f
+
+ lw sp, 4(t1)
+ move a0, v0
+ jalr t2
+
+ bnez v0, 2f
+1:
+ li a0, MESG(OS_EVENT_PI)
+ jal send_mesg
+2:
+ beqz s1, NoMoreRcpInts
+
+dp:
+ andi t1, s1, 0x20
+ beqz t1, NoMoreRcpInts
+
+ andi s1, s1, 0x1f
+
+ li t1, MI_CLR_DP_INTR
+ sw t1, PHYS_TO_K1(MI_INIT_MODE_REG)
+
+ li a0, MESG(OS_EVENT_DP)
+ jal send_mesg
+
+NoMoreRcpInts:
+ and s0, s0, ~CAUSE_IP3
+ b next_interrupt
+
+prenmi:
+ lw k1, THREAD_SR(k0)
+
+ and k1, k1, ~CAUSE_IP5
+ sw k1, THREAD_SR(k0)
+ la t1, __osShutdown
+ lw t2, 0(t1)
+ beqz t2, firstnmi
+
+ and s0, s0, ~CAUSE_IP5
+ b redispatch
+
+firstnmi:
+ li t2, 1
+ sw t2, 0(t1) /* __osShutdown */
+ li a0, MESG(OS_EVENT_PRENMI)
+ jal send_mesg
+
+ and s0, s0, ~CAUSE_IP5
+ lw t2, __osRunQueue
+ lw k1, THREAD_SR(t2)
+ and k1, k1, ~CAUSE_IP5
+ sw k1, THREAD_SR(t2)
+ b redispatch
+
+sw2:
+ and t0, t0, ~CAUSE_SW2
+STAY2(mtc0 t0, C0_CAUSE)
+
+ li a0, MESG(OS_EVENT_SW2)
+ jal send_mesg
+
+ and s0, s0, ~CAUSE_SW2
+ b next_interrupt
+
+sw1:
+ and t0, t0, ~CAUSE_SW1
+STAY2(mtc0 t0, C0_CAUSE)
+
+ li a0, MESG(OS_EVENT_SW1)
+ jal send_mesg
+
+ and s0, s0, ~CAUSE_SW1
+ b next_interrupt
+
+handle_break:
+ li t1, OS_FLAG_CPU_BREAK
+ sh t1, THREAD_FLAGS(k0)
+ li a0, MESG(OS_EVENT_CPU_BREAK)
+ jal send_mesg
+ b redispatch
+
+redispatch:
+ lw t1, THREAD_PRI(k0)
+ lw t2, __osRunQueue
+ lw t3, THREAD_PRI(t2)
+
+ bge t1, t3, enqueueRunning
+
+ move a1, k0
+ la a0, __osRunQueue
+
+ jal __osEnqueueThread
+
+ j __osDispatchThread
+
+enqueueRunning:
+ la t1, __osRunQueue
+ lw t2, MQ_MTQUEUE(t1)
+ sw t2, THREAD_NEXT(k0)
+ sw k0, MQ_MTQUEUE(t1)
+ j __osDispatchThread
+panic:
+ sw k0, __osFaultedThread
+ li t1, OS_STATE_STOPPED
+ sh t1, THREAD_STATE(k0)
+ li t1, OS_FLAG_FAULT
+ sh t1, THREAD_FLAGS(k0)
+
+STAY2(mfc0 t2, C0_BADVADDR)
+
+ sw t2, THREAD_BADVADDR(k0)
+
+ li a0, MESG(OS_EVENT_FAULT)
+ jal send_mesg
+ j __osDispatchThread
+END(__osException)
+
+LEAF(send_mesg)
+ move s2, ra
+ la t2, __osEventStateTab
+ addu t2, t2, a0
+ lw t1, OS_EVENTSTATE_MESSAGE_QUEUE(t2)
+ beqz t1, send_done
+
+ lw t3, MQ_VALIDCOUNT(t1)
+ lw ta0, MQ_MSGCOUNT(t1)
+
+ bge t3, ta0, send_done
+
+ lw ta1, MQ_FIRST(t1)
+ addu ta1, ta1, t3
+
+ rem ta1, ta1, ta0
+ lw ta0, MQ_MSG(t1)
+ mul ta1, ta1, 4
+ addu ta0, ta0, ta1
+ lw ta1, OS_EVENTSTATE_MESSAGE(t2)
+ sw ta1, 0(ta0) /* msg[ta1] = */
+ addiu t2, t3, 1
+ sw t2, MQ_VALIDCOUNT(t1)
+ lw t2, MQ_MTQUEUE(t1)
+ lw t3, THREAD_NEXT(t2)
+ beqz t3, send_done
+
+ move a0, t1
+ jal __osPopThread
+
+ move t2, v0
+
+ move a1, t2
+ la a0, __osRunQueue
+ jal __osEnqueueThread
+send_done:
+ jr s2
+END(send_mesg)
+
+LEAF(handle_CpU) /* coprocessor error */
+ and t1, t0, CAUSE_CEMASK
+ srl t1, t1, CAUSE_CESHIFT
+ li t2, 1 /* cp1 error */
+ bne t1, t2, panic
+
+ /* enable cp1 (fpu) for this thread */
+ li t1, 1
+ sw t1, THREAD_FP(k0)
+ lw k1, THREAD_SR(k0)
+ or k1, k1, SR_CU1
+ sw k1, THREAD_SR(k0)
+ b enqueueRunning
+END(handle_CpU)
+
+LEAF(__osEnqueueAndYield)
+ lw a1, __osRunningThread
+#ifndef _FINALROM
+ sw a1, __osPreviousThread
+#endif
+STAY2(mfc0 t0, C0_SR)
+ ori t0, t0, SR_EXL
+ sw t0, THREAD_SR(a1)
+ sd s0, THREAD_GP16(a1)
+ sd s1, THREAD_GP17(a1)
+ sd s2, THREAD_GP18(a1)
+ sd s3, THREAD_GP19(a1)
+ sd s4, THREAD_GP20(a1)
+ sd s5, THREAD_GP21(a1)
+ sd s6, THREAD_GP22(a1)
+ sd s7, THREAD_GP23(a1)
+ sd gp, THREAD_GP28(a1)
+ sd sp, THREAD_GP29(a1)
+ sd s8, THREAD_GP30(a1)
+ sd ra, THREAD_GP31(a1)
+ sw ra, THREAD_PC(a1)
+ lw k1, THREAD_FP(a1)
+ beqz k1, 1f
+ cfc1 k1, fcr31
+ sw k1, THREAD_FPCSR(a1)
+ sdc1 $f20, THREAD_FP20(a1)
+ sdc1 $f22, THREAD_FP22(a1)
+ sdc1 $f24, THREAD_FP24(a1)
+ sdc1 $f26, THREAD_FP26(a1)
+ sdc1 $f28, THREAD_FP28(a1)
+ sdc1 $f30, THREAD_FP30(a1)
+1:
+ lw k1, THREAD_SR(a1)
+ andi t1, k1, SR_IMASK
+ beqz t1, 2f
+
+ la t0, __OSGlobalIntMask
+ lw t0, 0(t0)
+ xor t0, t0, ~0
+ andi t0, t0, SR_IMASK
+ or t1, t1, t0
+ and k1, k1, ~SR_IMASK
+ or k1, k1, t1
+ sw k1, THREAD_SR(a1)
+2:
+ lw k1, PHYS_TO_K1(MI_INTR_MASK_REG)
+ beqz k1, 3f
+
+ la k0, __OSGlobalIntMask
+ lw k0, 0(k0)
+
+ srl k0, k0, 0x10
+ xor k0, k0, ~0
+ andi k0, k0, 0x3f
+ lw t0, THREAD_RCP(a1)
+ and k0, k0, t0
+ or k1, k1, k0
+3:
+ sw k1, THREAD_RCP(a1)
+ beqz a0, noEnqueue
+ jal __osEnqueueThread
+noEnqueue:
+ j __osDispatchThread
+END(__osEnqueueAndYield)
+
+/*__osEnqueueThread(OSThread **, OSThread *)*/
+LEAF(__osEnqueueThread)
+ move t9, a0
+ lw t8, 0(a0)
+ lw ta3, THREAD_PRI(a1)
+ lw ta2, THREAD_PRI(t8)
+ blt ta2, ta3, 1f
+2:
+ move t9, t8
+ lw t8, THREAD_NEXT(t8)
+ lw ta2, THREAD_PRI(t8)
+ bge ta2, ta3, 2b
+1:
+ lw t8, THREAD_NEXT(t9)
+ sw t8, THREAD_NEXT(a1)
+ sw a1, THREAD_NEXT(t9)
+ sw a0, THREAD_QUEUE(a1)
+ jr ra
+END(__osEnqueueThread)
+
+LEAF(__osPopThread)
+ lw v0, 0(a0) /* a0 is OSThread** */
+ lw t9, THREAD_NEXT(v0)
+ sw t9, 0(a0)
+ jr ra
+END(__osPopThread)
+
+LEAF(__osNop)
+ jr ra
+END(__osNop)
+
+LEAF(__osDispatchThread)
+ la a0, __osRunQueue
+ jal __osPopThread
+ sw v0, __osRunningThread
+ li t0, OS_STATE_RUNNING
+ sh t0, THREAD_STATE(v0)
+ move k0, v0
+
+#ifndef _FINALROM
+ la t0, __osThprofFunc
+ lw t0, (t0)
+ beqz t0, __osDispatchThreadSave
+ lw a0, __osPreviousThread
+ lw sp, __osThprofStack
+ jalr t0
+#endif
+
+__osDispatchThreadSave:
+ lw k1, THREAD_SR(k0)
+ la t0, __OSGlobalIntMask
+ lw t0, 0(t0)
+ andi t0, t0, SR_IMASK
+ andi t1, k1, SR_IMASK
+ and t1, t1, t0
+ and k1, k1, ~SR_IMASK
+ or k1, k1, t1
+STAY2(mtc0 k1, C0_SR)
+.set noat
+ ld $1, THREAD_GP1(k0)
+.set at
+ ld $2, THREAD_GP2(k0)
+ ld $3, THREAD_GP3(k0)
+ ld $4, THREAD_GP4(k0)
+ ld $5, THREAD_GP5(k0)
+ ld $6, THREAD_GP6(k0)
+ ld $7, THREAD_GP7(k0)
+ ld $8, THREAD_GP8(k0)
+ ld $9, THREAD_GP9(k0)
+ ld $10, THREAD_GP10(k0)
+ ld $11, THREAD_GP11(k0)
+ ld $12, THREAD_GP12(k0)
+ ld $13, THREAD_GP13(k0)
+ ld $14, THREAD_GP14(k0)
+ ld $15, THREAD_GP15(k0)
+ ld $16, THREAD_GP16(k0)
+ ld $17, THREAD_GP17(k0)
+ ld $18, THREAD_GP18(k0)
+ ld $19, THREAD_GP19(k0)
+ ld $20, THREAD_GP20(k0)
+ ld $21, THREAD_GP21(k0)
+ ld $22, THREAD_GP22(k0)
+ ld $23, THREAD_GP23(k0)
+ ld $24, THREAD_GP24(k0)
+ ld $25, THREAD_GP25(k0)
+ ld $28, THREAD_GP28(k0)
+ ld $29, THREAD_GP29(k0)
+ ld $30, THREAD_GP30(k0)
+ ld $31, THREAD_GP31(k0)
+ ld k1, THREAD_LO(k0)
+ mtlo k1
+ ld k1, THREAD_HI(k0)
+ mthi k1
+ lw k1, THREAD_PC(k0)
+STAY2(mtc0 k1, C0_EPC)
+ lw k1, THREAD_FP(k0)
+ beqz k1, 1f
+
+ lw k1, THREAD_FPCSR(k0)
+STAY2(ctc1 k1, fcr31)
+ ldc1 $f0, THREAD_FP0(k0)
+ ldc1 $f2, THREAD_FP2(k0)
+ ldc1 $f4, THREAD_FP4(k0)
+ ldc1 $f6, THREAD_FP6(k0)
+ ldc1 $f8, THREAD_FP8(k0)
+ ldc1 $f10, THREAD_FP10(k0)
+ ldc1 $f12, THREAD_FP12(k0)
+ ldc1 $f14, THREAD_FP14(k0)
+ ldc1 $f16, THREAD_FP16(k0)
+ ldc1 $f18, THREAD_FP18(k0)
+ ldc1 $f20, THREAD_FP20(k0)
+ ldc1 $f22, THREAD_FP22(k0)
+ ldc1 $f24, THREAD_FP24(k0)
+ ldc1 $f26, THREAD_FP26(k0)
+ ldc1 $f28, THREAD_FP28(k0)
+ ldc1 $f30, THREAD_FP30(k0)
+
+1:
+ lw k1, THREAD_RCP(k0)
+ la k0, __OSGlobalIntMask
+ lw k0, 0(k0)
+ srl k0, k0, 0x10
+ and k1, k1, k0
+ sll k1, k1, 0x1
+ la k0, __osRcpImTable
+ addu k1, k1, k0
+ lhu k1, 0(k1)
+ la k0, PHYS_TO_K1(MI_INTR_MASK_REG)
+ sw k1, 0(k0)
+
+ nop
+ nop
+ nop
+ nop
+ eret
+END(__osDispatchThread)
+
+LEAF(__osCleanupThread)
+ move a0, zero
+ nop
+ jal osDestroyThread
+END(__osCleanupThread)