2018-08-16 23:02:25 -07:00
|
|
|
// not really a kernel,
|
|
|
|
// just handling some low-level stuff like interrupts.
|
|
|
|
|
|
|
|
Start:
|
2018-08-18 07:39:57 -07:00
|
|
|
mtc0 r0, CP0_Cause // clear cause
|
2018-08-18 10:41:30 -07:00
|
|
|
lui gp, K_BASE
|
2018-08-16 23:02:25 -07:00
|
|
|
|
|
|
|
// copy our interrupt handlers into place.
|
|
|
|
lui t0, 0x8000
|
|
|
|
la t1, _InterruptStart
|
|
|
|
la t2, _InterruptEnd
|
|
|
|
-
|
|
|
|
ld t3, 0(t1)
|
|
|
|
ld t4, 8(t1)
|
|
|
|
addiu t1, t1, 0x10
|
2018-08-18 07:39:57 -07:00
|
|
|
sd t3, 0(t0)
|
2018-08-16 23:02:25 -07:00
|
|
|
sd t4, 8(t0)
|
2018-08-18 07:39:57 -07:00
|
|
|
cache 0x19, 0(t0) // tell data cache to write itself out
|
|
|
|
cache 0x10, 0(t0) // tell instruction cache it needs to reload
|
2018-08-20 19:37:48 -07:00
|
|
|
// an instruction cache line is 2 rows, and a data cache line is 1 row,
|
|
|
|
// so poking at the start of each row is enough to flush them both.
|
2018-08-16 23:02:25 -07:00
|
|
|
bne t1, t2,-
|
2018-08-18 07:39:57 -07:00
|
|
|
addiu t0, t0, 0x10
|
2018-08-16 23:02:25 -07:00
|
|
|
|
|
|
|
// enable SI and PI interrupts.
|
|
|
|
lui a0, PIF_BASE
|
|
|
|
lli t0, 8
|
|
|
|
sw t0, PIF_RAM+0x3C(a0)
|
|
|
|
|
2018-08-18 07:39:57 -07:00
|
|
|
// enable CPU interrupts.
|
|
|
|
mfc0 t1, CP0_Status
|
|
|
|
ori t1, t1, CP0_STATUS_IM_ALL
|
|
|
|
mtc0 t1, CP0_Status
|
|
|
|
|
|
|
|
// enable even more interrupts.
|
|
|
|
lui t2, MI_BASE
|
|
|
|
ori t2, t2, MI_INTR_MASK
|
2018-08-20 19:37:48 -07:00
|
|
|
lli t0, MI_INTR_MASK_ALL
|
2018-08-18 07:39:57 -07:00
|
|
|
sw t0, 0(t2)
|
|
|
|
|
2018-08-19 17:13:11 -07:00
|
|
|
// set BSD DOM1 stuff, whatever that is.
|
|
|
|
lui v1, CART_DOM1_ADDR2
|
|
|
|
lw v0, 0(v1)
|
|
|
|
srl t8, v0, 16
|
|
|
|
srl t4, v0, 20
|
|
|
|
andi t9, t8, 0xF // t9=$07
|
|
|
|
andi t5, t4, 0xF // t5=$03
|
|
|
|
srl t7, v0, 8
|
|
|
|
//
|
|
|
|
andi t7, 0xFF // t7=$12
|
|
|
|
andi v0, 0xFF // v0=$40
|
|
|
|
// wait for PI
|
|
|
|
lui t2, PI_BASE
|
|
|
|
-
|
|
|
|
lw t0, PI_STATUS(t2)
|
|
|
|
andi t0, t0, 3
|
|
|
|
bnez t0,-
|
|
|
|
nop
|
|
|
|
//
|
|
|
|
sw v0, PI_BSD_DOM1_LAT(t2) // $40
|
|
|
|
sw t9, PI_BSD_DOM1_PGS(t2) // $07
|
|
|
|
sw t5, PI_BSD_DOM1_RLS(t2) // $03
|
|
|
|
sw t7, PI_BSD_DOM1_PWD(t2) // $12
|
2018-08-18 07:39:57 -07:00
|
|
|
|
2018-08-16 23:02:25 -07:00
|
|
|
// SP defaults to RSP instruction memory: 0xA4001FF0
|
|
|
|
// we can do better than that.
|
|
|
|
lui sp, K_STACK_INIT_BASE
|
|
|
|
// SP should always be 8-byte aligned
|
|
|
|
// so that SD and LD instructions don't fail on it.
|
2018-08-18 07:39:57 -07:00
|
|
|
// we also need 4 empty words for storing
|
2018-08-19 04:46:11 -07:00
|
|
|
// the 32-bit values of the callee's argument registers.
|
2018-08-16 23:53:37 -07:00
|
|
|
subiu sp, sp, 0x10
|
2018-08-19 04:46:11 -07:00
|
|
|
sd r0, 0(sp)
|
|
|
|
sd r0, 8(sp)
|
2018-08-16 23:02:25 -07:00
|
|
|
|
|
|
|
// TODO: just wipe a portion of RAM?
|
2018-08-18 07:39:57 -07:00
|
|
|
// or just DMA in the IH and our defaults from ROM...
|
2018-08-18 10:41:30 -07:00
|
|
|
sw r0, K_64DRIVE_MAGIC(gp)
|
|
|
|
sw r0, K_REASON(gp)
|
|
|
|
sw r0, K_IN_MAIN(gp)
|
|
|
|
sw r0, K_CONSOLE_AVAILABLE(gp)
|
2018-08-16 23:02:25 -07:00
|
|
|
|
|
|
|
Drive64Init:
|
2018-08-16 23:53:37 -07:00
|
|
|
lui t9, CI_BASE
|
2018-08-16 23:02:25 -07:00
|
|
|
lui t2, 0x5544 // "UD" of "UDEV"
|
2018-08-16 23:53:37 -07:00
|
|
|
lw t1, CI_HW_MAGIC(t9)
|
2018-08-16 23:02:25 -07:00
|
|
|
ori t2, t2, 0x4556 // "EV" of "UDEV"
|
|
|
|
|
|
|
|
beq t1, t2, Drive64Confirmed
|
|
|
|
nop
|
|
|
|
|
|
|
|
Drive64TryExtended:
|
2018-08-16 23:53:37 -07:00
|
|
|
lui t9, CI_BASE_EXTENDED
|
|
|
|
lw t1, CI_HW_MAGIC(t9)
|
2018-08-16 23:02:25 -07:00
|
|
|
bne t1, t2, Drive64Done
|
|
|
|
nop
|
|
|
|
|
|
|
|
Drive64Confirmed:
|
2018-08-18 10:41:30 -07:00
|
|
|
sw t2, K_64DRIVE_MAGIC(gp)
|
|
|
|
sw t9, K_CI_BASE(gp)
|
2018-08-16 23:02:25 -07:00
|
|
|
|
|
|
|
// enable writing to cartROM (SDRAM) for USB writing later
|
|
|
|
lli t1, 0xF0
|
2018-08-16 23:53:37 -07:00
|
|
|
CI_WAIT() // clobbers t0, requires t9
|
|
|
|
sw t1, CI_COMMAND(t9)
|
|
|
|
CI_WAIT() // clobbers t0, requires t9
|
2018-08-16 23:02:25 -07:00
|
|
|
|
2018-08-18 10:02:54 -07:00
|
|
|
Drive64CheckConsole:
|
|
|
|
// NOTE: we only check at boot, so disconnecting the console
|
|
|
|
// while running will cause a ton of lag (timeouts) until reset.
|
2018-08-19 04:46:11 -07:00
|
|
|
KDumpString(KSConsoleConfirmed)
|
2018-08-18 10:02:54 -07:00
|
|
|
lli t0, 1
|
|
|
|
beqzl v0, Drive64Done
|
2018-08-18 10:41:30 -07:00
|
|
|
sw t0, K_CONSOLE_AVAILABLE(gp)
|
2018-08-18 10:02:54 -07:00
|
|
|
|
2018-08-16 23:02:25 -07:00
|
|
|
Drive64Done:
|
|
|
|
|
2018-08-19 17:13:11 -07:00
|
|
|
// zero out RDRAM from 1 MiB to 4 MiB
|
|
|
|
// NOTE: this might overwrite the last 4 KiB of ROM that's loaded by 6102?
|
|
|
|
li t0, 0x80100000
|
|
|
|
li t1, 0x80400000
|
|
|
|
-
|
|
|
|
define x(0)
|
|
|
|
while {x} < 0x100 {
|
|
|
|
sd r0, {x}(t0)
|
|
|
|
evaluate x({x} + 8)
|
|
|
|
}
|
|
|
|
addiu t0, 0x100
|
|
|
|
bne t0, t1,-
|
|
|
|
nop
|
|
|
|
|
2018-08-18 10:35:11 -07:00
|
|
|
// delay to empty pipeline
|
2018-08-18 07:39:57 -07:00
|
|
|
nop
|
|
|
|
nop
|
|
|
|
nop
|
|
|
|
nop
|
|
|
|
nop
|
|
|
|
|
2018-08-19 04:46:11 -07:00
|
|
|
// try out an interrupt:
|
|
|
|
// sw r0, 0(r0)
|
|
|
|
// nop
|
2018-08-18 15:22:24 -07:00
|
|
|
// mfc0 t1, CP0_Status
|
|
|
|
// ori t1, 2
|
|
|
|
// mtc0 t1, CP0_Status
|
|
|
|
// la t0, WipeRegisters
|
|
|
|
// mtc0 t0, CP0_EPC
|
|
|
|
// j InterruptHandler
|
|
|
|
// nop
|
2018-08-16 23:02:25 -07:00
|
|
|
|
2018-08-18 07:39:57 -07:00
|
|
|
WipeRegisters:
|
2018-08-16 23:02:25 -07:00
|
|
|
// load up most registers with a dummy value for debugging
|
|
|
|
lui at, 0xCAFE
|
2018-08-18 15:19:18 -07:00
|
|
|
ori at, at, 0xBABE
|
|
|
|
dsll at, 16
|
2018-08-16 23:02:25 -07:00
|
|
|
// attempting to use this as an address should trigger an interrupt
|
2018-08-18 15:19:18 -07:00
|
|
|
ori at, at, 0xDEAD
|
|
|
|
dsll at, 16
|
|
|
|
ori at, at, 0xBEEF
|
2018-08-16 23:02:25 -07:00
|
|
|
|
|
|
|
// k0, k1, sp intentionally absent
|
|
|
|
daddu v0, at, r0
|
|
|
|
daddu v1, at, r0
|
|
|
|
daddu a0, at, r0
|
|
|
|
daddu a1, at, r0
|
|
|
|
daddu a2, at, r0
|
|
|
|
daddu a3, at, r0
|
|
|
|
daddu t0, at, r0
|
|
|
|
daddu t1, at, r0
|
|
|
|
daddu t2, at, r0
|
|
|
|
daddu t3, at, r0
|
|
|
|
daddu t4, at, r0
|
|
|
|
daddu t5, at, r0
|
|
|
|
daddu t6, at, r0
|
|
|
|
daddu t7, at, r0
|
|
|
|
daddu s0, at, r0
|
|
|
|
daddu s1, at, r0
|
|
|
|
daddu s2, at, r0
|
|
|
|
daddu s3, at, r0
|
|
|
|
daddu s4, at, r0
|
|
|
|
daddu s5, at, r0
|
|
|
|
daddu s6, at, r0
|
|
|
|
daddu s7, at, r0
|
|
|
|
daddu t8, at, r0
|
|
|
|
daddu t9, at, r0
|
|
|
|
daddu gp, at, r0
|
|
|
|
daddu fp, at, r0
|
|
|
|
daddu ra, at, r0
|
|
|
|
|
|
|
|
j Main
|
|
|
|
nop
|
|
|
|
|
2018-08-18 07:39:57 -07:00
|
|
|
align(0x10) // align to row for cache-poking purposes
|
|
|
|
_InterruptStart: // label for copying purposes
|
2018-08-16 23:02:25 -07:00
|
|
|
pushvar base
|
|
|
|
|
|
|
|
// note that we jump to the handler by jr instead of j
|
|
|
|
// because we want to change the PC to cached memory,
|
|
|
|
// which depends on the higher bits that j cannot change.
|
|
|
|
|
|
|
|
base 0x80000000
|
|
|
|
InterruptTBLRefill:
|
|
|
|
la k0, InterruptHandler
|
|
|
|
jr k0
|
|
|
|
lli k1, K_INT_TLB_REFILL
|
|
|
|
|
|
|
|
nops(0x80000080)
|
|
|
|
InterruptXTLBRefill:
|
|
|
|
la k0, InterruptHandler
|
|
|
|
jr k0
|
|
|
|
lli k1, K_INT_XTLB_REFILL
|
|
|
|
|
|
|
|
nops(0x80000100)
|
|
|
|
InterruptCacheError: // A0000100?
|
|
|
|
la k0, InterruptHandler
|
|
|
|
jr k0
|
|
|
|
lli k1, K_INT_CACHE_ERROR
|
|
|
|
|
|
|
|
nops(0x80000180)
|
|
|
|
InterruptOther:
|
|
|
|
la k0, InterruptHandler
|
|
|
|
jr k0
|
|
|
|
lli k1, K_INT_OTHER
|
|
|
|
|
|
|
|
nops(0x80000200)
|
|
|
|
pullvar base
|
2018-08-18 07:39:57 -07:00
|
|
|
_InterruptEnd: // label for copying purposes
|
2018-08-16 23:02:25 -07:00
|
|
|
|
|
|
|
InterruptHandler:
|
|
|
|
lui k0, K_BASE
|
|
|
|
sw k1, K_REASON(k0)
|
|
|
|
|
|
|
|
sd at, K_DUMP+0x08(k0)
|
|
|
|
|
2018-08-19 04:46:11 -07:00
|
|
|
// disable interrupts
|
2018-08-18 07:39:57 -07:00
|
|
|
mfc0 k1, CP0_Status
|
|
|
|
addiu at, r0, ~CP0_STATUS_IE
|
|
|
|
sw k1, K_STATUS(k0)
|
2018-08-16 23:02:25 -07:00
|
|
|
and k1, k1, at
|
|
|
|
mtc0 k1, CP0_Status
|
|
|
|
|
|
|
|
mfc0 k1, CP0_Cause
|
|
|
|
sw k1, K_CAUSE(k0)
|
|
|
|
|
|
|
|
// TODO: option to only store clobbered registers
|
2018-08-18 07:39:57 -07:00
|
|
|
// TODO: option to dump COP1 registers too (remember to check Status[FR])
|
2018-08-16 23:02:25 -07:00
|
|
|
|
|
|
|
sd r0, K_DUMP+0x00(k0) // intentional (it'd be weird if
|
|
|
|
// r0 showed as nonzero in memory dumps)
|
|
|
|
sd v0, K_DUMP+0x10(k0)
|
|
|
|
sd v1, K_DUMP+0x18(k0)
|
|
|
|
sd a0, K_DUMP+0x20(k0)
|
|
|
|
sd a1, K_DUMP+0x28(k0)
|
|
|
|
sd a2, K_DUMP+0x30(k0)
|
|
|
|
sd a3, K_DUMP+0x38(k0)
|
|
|
|
sd t0, K_DUMP+0x40(k0)
|
|
|
|
sd t1, K_DUMP+0x48(k0)
|
|
|
|
sd t2, K_DUMP+0x50(k0)
|
|
|
|
sd t3, K_DUMP+0x58(k0)
|
|
|
|
sd t4, K_DUMP+0x60(k0)
|
|
|
|
sd t5, K_DUMP+0x68(k0)
|
|
|
|
sd t6, K_DUMP+0x70(k0)
|
|
|
|
sd t7, K_DUMP+0x78(k0)
|
|
|
|
sd s0, K_DUMP+0x80(k0)
|
|
|
|
sd s1, K_DUMP+0x88(k0)
|
|
|
|
sd s2, K_DUMP+0x90(k0)
|
|
|
|
sd s3, K_DUMP+0x98(k0)
|
|
|
|
sd s4, K_DUMP+0xA0(k0)
|
|
|
|
sd s5, K_DUMP+0xA8(k0)
|
|
|
|
sd s6, K_DUMP+0xB0(k0)
|
|
|
|
sd s7, K_DUMP+0xB8(k0)
|
|
|
|
sd t8, K_DUMP+0xC0(k0)
|
|
|
|
sd t9, K_DUMP+0xC8(k0)
|
|
|
|
sd k0, K_DUMP+0xD0(k0)
|
|
|
|
sd k1, K_DUMP+0xD8(k0)
|
|
|
|
sd gp, K_DUMP+0xE0(k0)
|
|
|
|
sd sp, K_DUMP+0xE8(k0)
|
|
|
|
sd fp, K_DUMP+0xF0(k0)
|
|
|
|
sd ra, K_DUMP+0xF8(k0)
|
|
|
|
|
|
|
|
mfhi t0
|
|
|
|
mflo t1
|
|
|
|
sd t0, K_DUMP+0x100(k0)
|
|
|
|
sd t1, K_DUMP+0x108(k0)
|
|
|
|
|
2018-08-18 07:39:57 -07:00
|
|
|
mfc0 k1, CP0_EPC // TODO: check that this is valid?
|
|
|
|
sw k1, K_EPC(k0)
|
|
|
|
|
|
|
|
mfc0 k1, CP0_ErrorPC // TODO: check that this is valid?
|
|
|
|
sw k1, K_ERRORPC(k0)
|
|
|
|
|
|
|
|
mfc0 k1, CP0_BadVAddr
|
|
|
|
sw k1, K_BADVADDR(k0)
|
|
|
|
|
|
|
|
// prevent recursive interrupts if IHMain somehow causes an interrupt
|
2018-08-19 17:13:11 -07:00
|
|
|
// lw t1, K_IN_MAIN(k0)
|
|
|
|
// bnez t1, IHExit // TODO: reimplement properly
|
2018-08-18 07:39:57 -07:00
|
|
|
lli t0, 1
|
|
|
|
sw t0, K_IN_MAIN(k0)
|
|
|
|
|
2018-08-16 23:53:37 -07:00
|
|
|
// be wary, this is a tiny temporary stack!
|
|
|
|
ori sp, k0, K_STACK
|
|
|
|
|
|
|
|
IHMain: // free to modify any GPR from here to IHExit
|
2018-08-19 17:13:11 -07:00
|
|
|
|
|
|
|
if K_DEBUG {
|
2018-08-19 04:46:11 -07:00
|
|
|
KMaybeDumpString(KSNewline)
|
|
|
|
KMaybeDumpString(KSHandling)
|
2018-08-18 07:39:57 -07:00
|
|
|
|
|
|
|
ori a0, k0, K_DUMP + 0x80 * 0
|
|
|
|
lli a1, 0x80
|
|
|
|
ori a2, k0, K_XXD
|
|
|
|
jal DumpAndWrite
|
|
|
|
lli a3, 0x80 * 4
|
|
|
|
|
2018-08-19 04:46:11 -07:00
|
|
|
KMaybeDumpString(KSNewline)
|
2018-08-18 07:39:57 -07:00
|
|
|
|
|
|
|
ori a0, k0, K_DUMP + 0x80 * 1
|
|
|
|
lli a1, 0x80
|
|
|
|
ori a2, k0, K_XXD
|
|
|
|
jal DumpAndWrite
|
|
|
|
lli a3, 0x80 * 4
|
|
|
|
|
2018-08-19 04:46:11 -07:00
|
|
|
KMaybeDumpString(KSNewline)
|
2018-08-16 23:53:37 -07:00
|
|
|
|
2018-08-18 07:39:57 -07:00
|
|
|
// currently just 0x10 in size: LO and HI registers.
|
|
|
|
ori a0, k0, K_DUMP + 0x80 * 2
|
|
|
|
lli a1, 0x10
|
2018-08-16 23:53:37 -07:00
|
|
|
ori a2, k0, K_XXD
|
|
|
|
jal DumpAndWrite
|
2018-08-18 07:39:57 -07:00
|
|
|
lli a3, 0x10 * 4
|
2018-08-16 23:53:37 -07:00
|
|
|
|
2018-08-19 04:46:11 -07:00
|
|
|
KMaybeDumpString(KSNewline)
|
|
|
|
KMaybeDumpString(KSStates)
|
2018-08-18 07:39:57 -07:00
|
|
|
|
2018-08-20 19:37:48 -07:00
|
|
|
ori a0, k0, K_REASON
|
2018-08-18 07:39:57 -07:00
|
|
|
lli a1, 0x80
|
2018-08-16 23:53:37 -07:00
|
|
|
ori a2, k0, K_XXD
|
|
|
|
jal DumpAndWrite
|
2018-08-18 07:39:57 -07:00
|
|
|
lli a3, 0x80 * 4
|
2018-08-16 23:53:37 -07:00
|
|
|
|
2018-08-19 04:46:11 -07:00
|
|
|
KMaybeDumpString(KSNewline)
|
|
|
|
KMaybeDumpString(KSCode)
|
2018-08-19 17:13:11 -07:00
|
|
|
}
|
2018-08-19 04:46:11 -07:00
|
|
|
|
|
|
|
// switch-case on the cause code:
|
|
|
|
// conveniently, the ExcCode in Cause is already shifted left by 2.
|
|
|
|
lw t4, K_CAUSE(k0)
|
|
|
|
la t3, KCodes
|
|
|
|
andi t4, CP0_CAUSE_CODE
|
|
|
|
addu t3, t4
|
|
|
|
lw t4, 0(t3)
|
|
|
|
jr t4
|
|
|
|
nop
|
|
|
|
KCodeDone:
|
2018-08-19 17:13:11 -07:00
|
|
|
KMaybeDumpString(KSNewline)
|
2018-08-18 10:41:30 -07:00
|
|
|
|
2018-08-16 23:53:37 -07:00
|
|
|
IHExit:
|
2018-08-18 07:39:57 -07:00
|
|
|
sw r0, K_IN_MAIN(k0)
|
2018-08-16 23:53:37 -07:00
|
|
|
|
2018-08-16 23:02:25 -07:00
|
|
|
lui k0, K_BASE
|
|
|
|
ld t0, K_DUMP+0x100(k0)
|
|
|
|
ld t1, K_DUMP+0x108(k0)
|
|
|
|
mthi t0
|
|
|
|
mtlo t1
|
|
|
|
|
|
|
|
ld at, K_DUMP+0x08(k0)
|
|
|
|
ld v0, K_DUMP+0x10(k0)
|
|
|
|
ld v1, K_DUMP+0x18(k0)
|
|
|
|
ld a0, K_DUMP+0x20(k0)
|
|
|
|
ld a1, K_DUMP+0x28(k0)
|
|
|
|
ld a2, K_DUMP+0x30(k0)
|
|
|
|
ld a3, K_DUMP+0x38(k0)
|
|
|
|
ld t0, K_DUMP+0x40(k0)
|
|
|
|
ld t1, K_DUMP+0x48(k0)
|
|
|
|
ld t2, K_DUMP+0x50(k0)
|
|
|
|
ld t3, K_DUMP+0x58(k0)
|
|
|
|
ld t4, K_DUMP+0x60(k0)
|
|
|
|
ld t5, K_DUMP+0x68(k0)
|
|
|
|
ld t6, K_DUMP+0x70(k0)
|
|
|
|
ld t7, K_DUMP+0x78(k0)
|
|
|
|
ld s0, K_DUMP+0x80(k0)
|
|
|
|
ld s1, K_DUMP+0x88(k0)
|
|
|
|
ld s2, K_DUMP+0x90(k0)
|
|
|
|
ld s3, K_DUMP+0x98(k0)
|
|
|
|
ld s4, K_DUMP+0xA0(k0)
|
|
|
|
ld s5, K_DUMP+0xA8(k0)
|
|
|
|
ld s6, K_DUMP+0xB0(k0)
|
|
|
|
ld s7, K_DUMP+0xB8(k0)
|
|
|
|
ld t8, K_DUMP+0xC0(k0)
|
|
|
|
ld t9, K_DUMP+0xC8(k0)
|
|
|
|
ld gp, K_DUMP+0xE0(k0)
|
|
|
|
ld sp, K_DUMP+0xE8(k0)
|
|
|
|
ld fp, K_DUMP+0xF0(k0)
|
|
|
|
ld ra, K_DUMP+0xF8(k0)
|
|
|
|
|
|
|
|
lw k1, K_CAUSE(k0)
|
2018-08-19 17:13:11 -07:00
|
|
|
andi k1, k1, CP0_CAUSE_CODE
|
|
|
|
xori k1, k1, CP0_CODE_TR << 2 // check if this was a trap exception
|
2018-08-18 07:39:57 -07:00
|
|
|
bnez k1, ReturnFromInterrupt
|
2018-08-16 23:02:25 -07:00
|
|
|
mfc0 k0, CP0_EPC
|
|
|
|
|
|
|
|
ReturnFromTrap:
|
2018-08-18 07:39:57 -07:00
|
|
|
addiu k0, k0, 4 // TODO: this probably fails with branch delays?
|
|
|
|
mtc0 k0, CP0_EPC
|
2018-08-16 23:02:25 -07:00
|
|
|
|
|
|
|
ReturnFromInterrupt:
|
|
|
|
// restore interrupts
|
|
|
|
mfc0 k1, CP0_Status
|
|
|
|
ori k1, k1, 1
|
|
|
|
mtc0 k1, CP0_Status
|
|
|
|
|
2018-08-18 07:39:57 -07:00
|
|
|
// eret pseudo-code:
|
|
|
|
//if status & 4 then
|
|
|
|
// jump to ErrorPC
|
|
|
|
// clear status & 4
|
|
|
|
//elseif status & 2 then
|
|
|
|
// jump to EPC
|
|
|
|
// clear status & 2
|
|
|
|
//else
|
|
|
|
// raise new exception???
|
|
|
|
//end
|
|
|
|
eret
|
|
|
|
// no branch delay for eret
|
2018-08-16 23:02:25 -07:00
|
|
|
|
2018-08-19 17:13:11 -07:00
|
|
|
KCode0:
|
|
|
|
KMaybeDumpString(KSCode0)
|
|
|
|
|
2018-08-20 19:37:48 -07:00
|
|
|
KMILoop:
|
2018-08-19 17:13:11 -07:00
|
|
|
lui a0, MI_BASE
|
2018-08-20 19:37:48 -07:00
|
|
|
lw s0, MI_INTR(a0)
|
2018-08-19 17:13:11 -07:00
|
|
|
|
|
|
|
beqz s0,+
|
|
|
|
|
|
|
|
andi t3, s0, MI_INTR_SP // delay slot
|
|
|
|
bnez t3, KMISP
|
|
|
|
|
|
|
|
andi t4, s0, MI_INTR_SI // delay slot
|
|
|
|
bnez t4, KMISI
|
|
|
|
|
|
|
|
andi t3, s0, MI_INTR_AI // delay slot
|
|
|
|
bnez t3, KMIAI
|
|
|
|
|
|
|
|
andi t4, s0, MI_INTR_VI // delay slot
|
|
|
|
bnez t4, KMIVI
|
|
|
|
|
|
|
|
andi t3, s0, MI_INTR_PI // delay slot
|
|
|
|
bnez t3, KMIPI
|
|
|
|
|
|
|
|
andi t4, s0, MI_INTR_DP // delay slot
|
|
|
|
bnez t4, KMIDP
|
|
|
|
nop
|
|
|
|
+
|
|
|
|
|
|
|
|
j KCodeDone
|
|
|
|
nop
|
|
|
|
|
|
|
|
// FIXME: camelcase sucks
|
|
|
|
KMISP:
|
|
|
|
KMaybeDumpString(KSMISP)
|
|
|
|
|
2018-08-20 19:37:48 -07:00
|
|
|
lli t0, CLR_SG3 | CLR_INT // delay slot
|
2018-08-19 17:13:11 -07:00
|
|
|
lui a1, SP_BASE
|
|
|
|
sw t0, SP_STATUS(a1)
|
2018-08-20 19:37:48 -07:00
|
|
|
|
|
|
|
// then check andi t1, SG1 | SG2 ?
|
2018-08-19 17:13:11 -07:00
|
|
|
|
|
|
|
j KMILoop
|
|
|
|
andi s0, ~MI_INTR_SP
|
|
|
|
|
|
|
|
KMISI:
|
|
|
|
KMaybeDumpString(KSMISI)
|
2018-08-20 19:37:48 -07:00
|
|
|
|
|
|
|
lui a1, SI_BASE
|
|
|
|
sw r0, SI_STATUS(a1)
|
|
|
|
|
2018-08-19 17:13:11 -07:00
|
|
|
j KMILoop
|
|
|
|
andi s0, ~MI_INTR_SI
|
|
|
|
|
|
|
|
KMIAI:
|
|
|
|
KMaybeDumpString(KSMIAI)
|
2018-08-20 19:37:48 -07:00
|
|
|
|
|
|
|
lli t0, 0x01
|
|
|
|
lui a1, AI_BASE
|
|
|
|
sw t0, AI_STATUS(a1)
|
|
|
|
|
2018-08-19 17:13:11 -07:00
|
|
|
j KMILoop
|
|
|
|
andi s0, ~MI_INTR_AI
|
|
|
|
|
|
|
|
KMIVI:
|
|
|
|
KMaybeDumpString(KSMIVI)
|
2018-08-20 19:37:48 -07:00
|
|
|
|
|
|
|
lui a1, VI_BASE
|
|
|
|
sw r0, VI_V_CURRENT_LINE(a1)
|
|
|
|
|
2018-08-19 17:13:11 -07:00
|
|
|
j KMILoop
|
|
|
|
andi s0, ~MI_INTR_VI
|
|
|
|
|
|
|
|
KMIPI:
|
|
|
|
KMaybeDumpString(KSMIPI)
|
2018-08-20 19:37:48 -07:00
|
|
|
|
|
|
|
lli t0, 0x02
|
|
|
|
lui a1, PI_BASE
|
|
|
|
sw t0, PI_STATUS(a1)
|
|
|
|
|
2018-08-19 17:13:11 -07:00
|
|
|
j KMILoop
|
|
|
|
andi s0, ~MI_INTR_PI
|
|
|
|
|
|
|
|
KMIDP:
|
|
|
|
KMaybeDumpString(KSMIDP)
|
2018-08-20 19:37:48 -07:00
|
|
|
|
|
|
|
lli t0, 0x800
|
|
|
|
lui a1, MI_BASE
|
|
|
|
sw t0, MI_INIT_MODE(a1)
|
|
|
|
|
2018-08-19 17:13:11 -07:00
|
|
|
j KMILoop
|
|
|
|
andi s0, ~MI_INTR_DP
|
|
|
|
|
2018-08-19 04:46:11 -07:00
|
|
|
KCode1:; KMaybeDumpString(KSCode1); j KCodeDone; nop
|
|
|
|
KCode2:; KMaybeDumpString(KSCode2); j KCodeDone; nop
|
|
|
|
KCode3:; KMaybeDumpString(KSCode3); j KCodeDone; nop
|
|
|
|
KCode4:; KMaybeDumpString(KSCode4); j KCodeDone; nop
|
|
|
|
KCode5:; KMaybeDumpString(KSCode5); j KCodeDone; nop
|
|
|
|
KCode6:; KMaybeDumpString(KSCode6); j KCodeDone; nop
|
|
|
|
KCode7:; KMaybeDumpString(KSCode7); j KCodeDone; nop
|
|
|
|
KCode8:; KMaybeDumpString(KSCode8); j KCodeDone; nop
|
|
|
|
KCode9:; KMaybeDumpString(KSCode9); j KCodeDone; nop
|
|
|
|
KCode10:; KMaybeDumpString(KSCode10); j KCodeDone; nop
|
|
|
|
KCode11:; KMaybeDumpString(KSCode11); j KCodeDone; nop
|
|
|
|
KCode12:; KMaybeDumpString(KSCode12); j KCodeDone; nop
|
|
|
|
KCode13:; KMaybeDumpString(KSCode13); j KCodeDone; nop
|
|
|
|
KCode14:; KMaybeDumpString(KSCode14); j KCodeDone; nop
|
|
|
|
KCode15:; KMaybeDumpString(KSCode15); j KCodeDone; nop
|
|
|
|
KCode16:; KMaybeDumpString(KSCode16); j KCodeDone; nop
|
|
|
|
KCode17:; KMaybeDumpString(KSCode17); j KCodeDone; nop
|
|
|
|
KCode18:; KMaybeDumpString(KSCode18); j KCodeDone; nop
|
|
|
|
KCode19:; KMaybeDumpString(KSCode19); j KCodeDone; nop
|
|
|
|
KCode20:; KMaybeDumpString(KSCode20); j KCodeDone; nop
|
|
|
|
KCode21:; KMaybeDumpString(KSCode21); j KCodeDone; nop
|
|
|
|
KCode22:; KMaybeDumpString(KSCode22); j KCodeDone; nop
|
|
|
|
KCode23:; KMaybeDumpString(KSCode23); j KCodeDone; nop
|
|
|
|
KCode24:; KMaybeDumpString(KSCode24); j KCodeDone; nop
|
|
|
|
KCode25:; KMaybeDumpString(KSCode25); j KCodeDone; nop
|
|
|
|
KCode26:; KMaybeDumpString(KSCode26); j KCodeDone; nop
|
|
|
|
KCode27:; KMaybeDumpString(KSCode27); j KCodeDone; nop
|
|
|
|
KCode28:; KMaybeDumpString(KSCode28); j KCodeDone; nop
|
|
|
|
KCode29:; KMaybeDumpString(KSCode29); j KCodeDone; nop
|
|
|
|
KCode30:; KMaybeDumpString(KSCode30); j KCodeDone; nop
|
|
|
|
KCode31:; KMaybeDumpString(KSCode31); j KCodeDone; nop
|
|
|
|
|
|
|
|
KCodes:
|
|
|
|
dw KCode0, KCode1, KCode2, KCode3
|
|
|
|
dw KCode4, KCode5, KCode6, KCode7
|
|
|
|
dw KCode8, KCode9, KCode10, KCode11
|
|
|
|
dw KCode12, KCode13, KCode14, KCode15
|
|
|
|
dw KCode16, KCode17, KCode18, KCode19
|
|
|
|
dw KCode20, KCode21, KCode22, KCode23
|
|
|
|
dw KCode24, KCode25, KCode26, KCode27
|
|
|
|
dw KCode28, KCode29, KCode30, KCode31
|
|
|
|
|
2018-08-20 19:37:48 -07:00
|
|
|
include "debug.asm"
|
|
|
|
|
2018-08-19 17:13:11 -07:00
|
|
|
if K_DEBUG {
|
2018-08-19 04:46:11 -07:00
|
|
|
KS(KSNewline, 10)
|
|
|
|
KSL(KSConsoleConfirmed, "USB debug console detected")
|
|
|
|
KSL(KSHandling, " ~~ Handling Interrupt ~~")
|
|
|
|
KSL(KSStates, " Interrupt States:")
|
|
|
|
|
|
|
|
KS(KSCode, " Interrupt Type: ")
|
|
|
|
KSL(KSCode0, "Regular Interrupt")
|
|
|
|
KSL(KSCode1, "TLB Modification Exception")
|
|
|
|
KSL(KSCode2, "TLB Exception (Load/Fetch)")
|
|
|
|
KSL(KSCode3, "TLB Exception (Store)")
|
|
|
|
KSL(KSCode4, "Address Error Exception (Load/Fetch)")
|
|
|
|
KSL(KSCode5, "Address Error Exception (Store)")
|
|
|
|
KSL(KSCode6, "Bus Error Exception (Fetch)")
|
|
|
|
KSL(KSCode7, "Bus Error Exception (Load/Store)")
|
|
|
|
KSL(KSCode8, "SysCall Exception")
|
|
|
|
KSL(KSCode9, "Breakpoint Exception")
|
|
|
|
KSL(KSCode10, "Reserved Instruction Exception")
|
|
|
|
KSL(KSCode11, "Coprocessor Unusable Exception")
|
|
|
|
KSL(KSCode12, "Arithmetic Overflow Exception")
|
|
|
|
KSL(KSCode13, "Trap Exception")
|
|
|
|
KSL(KSCode14, "RESERVED 14")
|
|
|
|
KSL(KSCode15, "Floating Point Exception")
|
|
|
|
KSL(KSCode16, "RESERVED 16")
|
|
|
|
KSL(KSCode17, "RESERVED 17")
|
|
|
|
KSL(KSCode18, "RESERVED 18")
|
|
|
|
KSL(KSCode19, "RESERVED 19")
|
|
|
|
KSL(KSCode20, "RESERVED 20")
|
|
|
|
KSL(KSCode21, "RESERVED 21")
|
|
|
|
KSL(KSCode22, "RESERVED 22")
|
|
|
|
KSL(KSCode23, "Watch")
|
|
|
|
KSL(KSCode24, "RESERVED 24")
|
|
|
|
KSL(KSCode25, "RESERVED 25")
|
|
|
|
KSL(KSCode26, "RESERVED 26")
|
|
|
|
KSL(KSCode27, "RESERVED 27")
|
|
|
|
KSL(KSCode28, "RESERVED 28")
|
|
|
|
KSL(KSCode29, "RESERVED 29")
|
|
|
|
KSL(KSCode30, "RESERVED 30")
|
|
|
|
KSL(KSCode31, "RESERVED 31")
|
2018-08-18 10:02:54 -07:00
|
|
|
|
2018-08-19 17:13:11 -07:00
|
|
|
KSL(KSMISP, " Signal Processor Interrupt")
|
|
|
|
KSL(KSMISI, " Serial Interface Interrupt")
|
|
|
|
KSL(KSMIAI, " Audio Interface Interrupt")
|
|
|
|
KSL(KSMIVI, " Video Interface Interrupt")
|
|
|
|
KSL(KSMIPI, " Peripheral Interface Interrupt")
|
|
|
|
KSL(KSMIDP, " Display Processor Interrupt")
|
|
|
|
}
|
|
|
|
|
2018-08-16 23:53:37 -07:00
|
|
|
align(4)
|
2018-08-16 23:02:25 -07:00
|
|
|
nops((K_BASE << 16) + 0x10000)
|