start work on interrupt handler; refactor
This commit is contained in:
parent
d05169fcbc
commit
ab2896cec6
4 changed files with 339 additions and 58 deletions
260
kernel.asm
Normal file
260
kernel.asm
Normal file
|
@ -0,0 +1,260 @@
|
|||
// not really a kernel,
|
||||
// just handling some low-level stuff like interrupts.
|
||||
|
||||
Start:
|
||||
lui k0, K_BASE
|
||||
|
||||
// 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
|
||||
ld t3, 0(t0)
|
||||
sd t4, 8(t0)
|
||||
addiu t0, t0, 0x10
|
||||
bne t1, t2,-
|
||||
cache 1, 0(t0) // not sure if this is necessary, but it doesn't hurt.
|
||||
|
||||
// enable SI and PI interrupts.
|
||||
lui a0, PIF_BASE
|
||||
lli t0, 8
|
||||
sw t0, PIF_RAM+0x3C(a0)
|
||||
|
||||
// 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.
|
||||
subiu sp, sp, 8
|
||||
|
||||
// TODO: just wipe a portion of RAM?
|
||||
sw r0, K_64DRIVE_MAGIC(k0)
|
||||
sw r0, K_REASON(k0)
|
||||
|
||||
Drive64Init:
|
||||
lui gp, CI_BASE
|
||||
lui t2, 0x5544 // "UD" of "UDEV"
|
||||
lw t1, CI_HW_MAGIC(gp)
|
||||
ori t2, t2, 0x4556 // "EV" of "UDEV"
|
||||
|
||||
beq t1, t2, Drive64Confirmed
|
||||
nop
|
||||
|
||||
Drive64TryExtended:
|
||||
lui gp, CI_BASE_EXTENDED
|
||||
lw t1, CI_HW_MAGIC(gp)
|
||||
bne t1, t2, Drive64Done
|
||||
nop
|
||||
|
||||
Drive64Confirmed:
|
||||
sw t2, K_64DRIVE_MAGIC(k0)
|
||||
sw gp, K_CI_BASE(k0)
|
||||
|
||||
// enable writing to cartROM (SDRAM) for USB writing later
|
||||
lli t1, 0xF0
|
||||
|
||||
CI_WAIT()
|
||||
sw t1, CI_COMMAND(gp) // send our command
|
||||
CI_WAIT()
|
||||
|
||||
Drive64Done:
|
||||
|
||||
// clear internal exception/interrupt value
|
||||
ori k1, r0, r0
|
||||
|
||||
// load up most registers with a dummy value for debugging
|
||||
lui at, 0xCAFE
|
||||
ori at, r0, 0xBABE
|
||||
dsllv at, 32
|
||||
// attempting to use this as an address should trigger an interrupt
|
||||
ori at, r0, 0xDEAD
|
||||
dsllv at, 16
|
||||
ori at, r0, 0xBEEF
|
||||
|
||||
// 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
|
||||
|
||||
align(0x10)
|
||||
_InterruptStart: // for copying purposes
|
||||
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
|
||||
_InterruptEnd: // for copying purposes
|
||||
|
||||
InterruptHandler:
|
||||
lui k0, K_BASE
|
||||
sw k1, K_REASON(k0)
|
||||
|
||||
sd at, K_DUMP+0x08(k0)
|
||||
|
||||
// disable interrupts, clear exception and error level bits:
|
||||
mfc0 at, CP0_Status
|
||||
sw at, K_STATUS(k0) // TODO: restored later
|
||||
addiu at, r0, 0xFFFC
|
||||
and k1, k1, at
|
||||
mtc0 k1, CP0_Status
|
||||
|
||||
mfc0 k1, CP0_Cause
|
||||
sw k1, K_CAUSE(k0)
|
||||
|
||||
// TODO: option to only store clobbered registers
|
||||
// TODO: option to dump COP1 registers too
|
||||
|
||||
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)
|
||||
|
||||
// free to modify any GPR here
|
||||
|
||||
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)
|
||||
andi k1, k1, 0x2000 // check if this was a trap exception
|
||||
mfc0 k0, CP0_EPC
|
||||
beqz k1, ReturnFromInterrupt
|
||||
sw k0, K_EPC(k0)
|
||||
|
||||
ReturnFromTrap:
|
||||
addiu k0, k0, 4
|
||||
|
||||
ReturnFromInterrupt:
|
||||
// restore interrupts
|
||||
mfc0 k1, CP0_Status
|
||||
ori k1, k1, 1
|
||||
mtc0 k1, CP0_Status
|
||||
|
||||
// wait, shouldn't this be ERET?
|
||||
rfe
|
||||
jr k0
|
||||
or k1, r0, r0
|
||||
|
||||
nops((K_BASE << 16) + 0x10000)
|
68
main.asm
68
main.asm
|
@ -18,68 +18,28 @@ insert "6102.bin"
|
|||
|
||||
include "main.inc"
|
||||
|
||||
Start:
|
||||
N64_INIT() // enable interrupts
|
||||
include "kernel.asm"
|
||||
|
||||
// SP defaults to RSP instruction memory: 0xA4001FF0
|
||||
// we can do better than that.
|
||||
lui sp, BLAH_BASE
|
||||
// SP should always be 8-byte aligned
|
||||
// so that SD and LD instructions don't fail on it.
|
||||
subiu sp, sp, 8
|
||||
nops(0x80010000)
|
||||
|
||||
Main:
|
||||
lui t0, K_BASE
|
||||
lw gp, K_CI_BASE(t0)
|
||||
|
||||
lui s0, BLAH_BASE
|
||||
|
||||
Drive64Init:
|
||||
lui gp, CI_BASE
|
||||
lui t2, 0x5544 // "UD" of "UDEV"
|
||||
lw t1, CI_HW_MAGIC(gp)
|
||||
ori t2, t2, 0x4556 // "EV" of "UDEV"
|
||||
|
||||
beq t1, t2, Drive64Confirmed
|
||||
nop // delay slot
|
||||
|
||||
Drive64TryExtended:
|
||||
lui gp, CI_BASE_EXTENDED
|
||||
lw t1, CI_HW_MAGIC(gp)
|
||||
bne t1, t2, Main
|
||||
nop // delay slot
|
||||
|
||||
Drive64Confirmed:
|
||||
sw t2, BLAH_CONFIRMED(s0)
|
||||
sw gp, BLAH_CI_BASE(s0)
|
||||
|
||||
// enable writing to cartROM (SDRAM) for USB writing later
|
||||
lli t1, 0xF0
|
||||
|
||||
CI_WAIT()
|
||||
sw t1, CI_COMMAND(gp) // send our command
|
||||
CI_WAIT()
|
||||
|
||||
Main:
|
||||
if 0 {
|
||||
mfc0 t0, 0x9 // move cycle Count register from COP 0
|
||||
mfc0 t0, CP0_Count
|
||||
mfc0 t1, CP0_Status+0
|
||||
sw t0, BLAH_COUNTS+0(s0)
|
||||
mfc0 t0, 0x9 // move cycle Count register from COP 0
|
||||
sw t0, BLAH_COUNTS+4(s0)
|
||||
// seems like 41 half-cycles between the two mfc0's, rarely 42?
|
||||
} else {
|
||||
mfc0 t0, 0x9
|
||||
mfc0 t1, 0x9
|
||||
sw t0, BLAH_COUNTS+0(s0)
|
||||
sw t1, BLAH_COUNTS+4(s0)
|
||||
// seems like 22 half-cycles between the two mfc0's
|
||||
}
|
||||
|
||||
// what is our stack pointer set to, anyway?
|
||||
sw sp, 0xC(s0)
|
||||
sw t1, 8(s0)
|
||||
|
||||
// decompress our picture
|
||||
include "lz.asm"
|
||||
|
||||
mfc0 t0, 0x9
|
||||
mfc0 t0, CP0_Count
|
||||
sw t0, BLAH_COUNTS+8(s0)
|
||||
lw t1, BLAH_CONFIRMED(s0)
|
||||
lui t0, K_BASE
|
||||
lw t1, K_64DRIVE_MAGIC(t0)
|
||||
beqz t1, InitVideo
|
||||
nop // delay slot
|
||||
|
||||
|
@ -112,7 +72,7 @@ InitVideo: // currently 80001190 (this comment is likely out of date)
|
|||
jal SetupScreen
|
||||
nop
|
||||
|
||||
mfc0 t0, 0x9 // move cycle Count register from COP 0
|
||||
mfc0 t0, CP0_Count
|
||||
sw t0, BLAH_COUNTS+0xC(s0)
|
||||
|
||||
MainLoop:
|
||||
|
@ -175,7 +135,7 @@ PushVideoTask:
|
|||
sw t5, 0x14(a0)
|
||||
sw t6, 0x18(a0)
|
||||
sw t7, 0x1C(a0)
|
||||
li t0, VIDEO_STACK & ADDR_MASK // ?
|
||||
li t0, VIDEO_STACK & ADDR_MASK // used for DList calls and returns?
|
||||
li t1, VIDEO_STACK_SIZE
|
||||
li t2, VIDEO_BUFFER & ADDR_MASK
|
||||
li t3, (VIDEO_BUFFER & ADDR_MASK) + VIDEO_BUFFER_SIZE // end pointer (not size!)
|
||||
|
|
29
main.inc
29
main.inc
|
@ -1,13 +1,32 @@
|
|||
constant UNCACHED(0xA0000000)
|
||||
constant ADDR_MASK(0x1FFFFFFF)
|
||||
|
||||
// "kernel" constants:
|
||||
constant K_BASE(0x8000) // k0 is set to this.
|
||||
constant K_DUMP(0x0400) // we save registers and state here
|
||||
// when handling interrupts
|
||||
constant K_REASON(0x0600)
|
||||
constant K_CAUSE(0x0604)
|
||||
constant K_STATUS(0x0608)
|
||||
constant K_EPC(0x060C)
|
||||
constant K_64DRIVE_MAGIC(0x0800)
|
||||
constant K_CI_BASE(0x0804)
|
||||
|
||||
constant K_STACK_INIT_BASE(0x803F) // note that this gets subtracted by 8
|
||||
// and that the stack grows *backwards.*
|
||||
|
||||
// internal interrupt enum: (0 means no known interrupt/exception)
|
||||
constant K_INT_TLB_REFILL(1)
|
||||
constant K_INT_XTLB_REFILL(2)
|
||||
constant K_INT_CACHE_ERROR(3)
|
||||
constant K_INT_OTHER(4)
|
||||
|
||||
constant BLAH_BASE(0x803F)
|
||||
constant BLAH_CONFIRMED(0x0000)
|
||||
constant BLAH_CI_BASE(0x0004)
|
||||
constant BLAH_COUNTS(0x0010)
|
||||
constant BLAH_SP_TASK(0x0040)
|
||||
constant BLAH_DLIST_JUMPER(0x0080)
|
||||
constant BLAH_XXD(0x0100)
|
||||
|
||||
constant VIDEO_BUFFER(0x80100000)
|
||||
constant VIDEO_BUFFER_SIZE(640 * 480 * 4)
|
||||
constant VIDEO_STACK(VIDEO_BUFFER + VIDEO_BUFFER_SIZE)
|
||||
|
@ -15,6 +34,12 @@ constant VIDEO_STACK_SIZE(0x400)
|
|||
constant VIDEO_YIELD(VIDEO_STACK + VIDEO_STACK_SIZE)
|
||||
constant VIDEO_YIELD_SIZE(0xC00)
|
||||
|
||||
macro nops(new_pc) {
|
||||
while (pc() < {new_pc}) {
|
||||
nop
|
||||
}
|
||||
}
|
||||
|
||||
macro PI_WAIT() {
|
||||
lui t5, PI_BASE
|
||||
-
|
||||
|
|
40
n64.inc
40
n64.inc
|
@ -1,4 +1,4 @@
|
|||
// via krom
|
||||
// by krom, edited by notwa
|
||||
|
||||
//=============
|
||||
// N64 Include
|
||||
|
@ -66,9 +66,11 @@ constant k0(26)
|
|||
constant k1(27)
|
||||
constant gp(28)
|
||||
constant sp(29)
|
||||
constant s8(30)
|
||||
constant fp(30)
|
||||
constant ra(31)
|
||||
|
||||
constant s8(30) // alias of fp
|
||||
|
||||
// N64 MIPS 4300 CP1 Floating Point Unit (FPU) Registers (COP1)
|
||||
constant f0(0)
|
||||
constant f1(1)
|
||||
|
@ -103,6 +105,40 @@ constant f29(29)
|
|||
constant f30(30)
|
||||
constant f31(31)
|
||||
|
||||
// Coprocessor 0 registers
|
||||
constant CP0_Index(0)
|
||||
constant CP0_Random(1)
|
||||
constant CP0_EntryLo0(2)
|
||||
constant CP0_EntryLo1(3)
|
||||
constant CP0_Context(4)
|
||||
constant CP0_PageMask(5)
|
||||
constant CP0_Wired(6)
|
||||
constant CP0_Reserved_1(7)
|
||||
constant CP0_BadVAddr(8)
|
||||
constant CP0_Count(9)
|
||||
constant CP0_EntryHi(10)
|
||||
constant CP0_Compare(11)
|
||||
constant CP0_Status(12)
|
||||
constant CP0_Cause(13)
|
||||
constant CP0_EPC(14)
|
||||
constant CP0_PRid(15)
|
||||
constant CP0_Config(16)
|
||||
constant CP0_LLAddr(17)
|
||||
constant CP0_WatchLo(18)
|
||||
constant CP0_WatchHi(19)
|
||||
constant CP0_XContext(20)
|
||||
constant CP0_Reserved_2(21)
|
||||
constant CP0_Reserved_3(22)
|
||||
constant CP0_Reserved_4(23)
|
||||
constant CP0_Reserved_5(24)
|
||||
constant CP0_Reserved_6(25)
|
||||
constant CP0_PErr(26) // unused
|
||||
constant CP0_CacheErr(27) // unused
|
||||
constant CP0_TagLo(28)
|
||||
constant CP0_TagHi(29) // reserved
|
||||
constant CP0_ErrorPC(30)
|
||||
constant CP0_Reserved_7(31)
|
||||
|
||||
// Memory Map
|
||||
constant RDRAM($A000) // $00000000..$003FFFFF RDRAM Memory 4MB ($00000000..$007FFFFF 8MB With Expansion Pak)
|
||||
|
||||
|
|
Loading…
Reference in a new issue