mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-11-17 23:22:49 +02:00
231 lines
4.0 KiB
ArmAsm
231 lines
4.0 KiB
ArmAsm
// The kernel stack.
|
|
.lcomm kernel_stack, KERNEL_STACK_SIZE
|
|
|
|
.globl __start
|
|
.globl run_idle
|
|
.set noat
|
|
.set noreorder
|
|
|
|
#define EntryLo0 2
|
|
#define EntryLo1 3
|
|
#define EntryHi 10
|
|
#define Random 1
|
|
#define Index 0
|
|
#define PageMask 5
|
|
#define Wired 6
|
|
#define Config 16
|
|
#define Status 12
|
|
#define Cause 13
|
|
#define Compare 11
|
|
|
|
#define save_regs \
|
|
sw $k0, -0x180($zero) ;\
|
|
lw $k0, -0x184($zero) ;\
|
|
sw $at, 12($k0) ;\
|
|
sw $k1, 108($k0) ;\
|
|
lw $k1, -0x180($zero) ;\
|
|
sw $k1, 104($k0) ;\
|
|
sw $v0, 16($k0) ;\
|
|
sw $v1, 20($k0) ;\
|
|
sw $t0, 40($k0) ;\
|
|
sw $sp, 84($k0) ;\
|
|
sw $fp, 88($k0) ;\
|
|
sw $ra, 92($k0) ;\
|
|
lw $gp, -12($zero) ;\
|
|
la $sp, kernel_stack + KERNEL_STACK_SIZE ;\
|
|
move $a0, $k0 ;\
|
|
la $ra, kernel_exit ;\
|
|
bal save_args
|
|
|
|
#define restore_regs \
|
|
lw $v0, 96($k0) ;\
|
|
lw $v1, 100($k0) ;\
|
|
mthi $v0 ;\
|
|
mtlo $v1 ;\
|
|
lw $v0, 16($k0) ;\
|
|
lw $v1, 20($k0) ;\
|
|
lw $a0, 24($k0) ;\
|
|
lw $a1, 28($k0) ;\
|
|
lw $a2, 32($k0) ;\
|
|
lw $a3, 36($k0) ;\
|
|
lw $t0, 40($k0) ;\
|
|
lw $t1, 44($k0) ;\
|
|
lw $t2, 48($k0) ;\
|
|
lw $t3, 52($k0) ;\
|
|
lw $t4, 56($k0) ;\
|
|
lw $t5, 60($k0) ;\
|
|
lw $t6, 64($k0) ;\
|
|
lw $t7, 68($k0) ;\
|
|
lw $t8, 72($k0) ;\
|
|
lw $t9, 76($k0) ;\
|
|
lw $gp, 80($k0) ;\
|
|
lw $sp, 84($k0) ;\
|
|
lw $fp, 88($k0) ;\
|
|
lw $ra, 92($k0) ;\
|
|
lw $at, 12($k0) ;\
|
|
lw $k1, 104($k0) ;\
|
|
sw $k1, -0x180($zero) ;\
|
|
lw $k1, 108($k0) ;\
|
|
sw $k0, -0x184($zero) ;\
|
|
lw $k0, -0x180($zero)
|
|
|
|
addr_000:
|
|
// TLB refill
|
|
// TODO: this should probably be assembly-only for speed reasons
|
|
|
|
li $a0, 0xffff0000
|
|
la $t9, panic
|
|
jr $t9
|
|
|
|
save_regs
|
|
mfc0 $a1, $EntryHi
|
|
la $t9, tlb_refill
|
|
jr $t9
|
|
nop
|
|
.fill 0x100 - (. - addr_000)
|
|
addr_100:
|
|
// Cache error
|
|
// TODO
|
|
|
|
li $a0, 0xaaaa0000
|
|
la $t9, panic
|
|
jr $t9
|
|
|
|
save_regs
|
|
la $t9, cache_error
|
|
jr $t9
|
|
nop
|
|
.fill 0x180 - (. - addr_000)
|
|
addr_180:
|
|
// General exception
|
|
// TODO
|
|
|
|
li $a0, 0xaaff0000
|
|
la $t9, panic
|
|
jr $t9
|
|
|
|
save_regs
|
|
la $t9, exception
|
|
jr $t9
|
|
nop
|
|
.fill 0x200 - (. - addr_000)
|
|
addr_200:
|
|
// Interrupt
|
|
// TODO
|
|
|
|
li $a0, 0x0a0f0000
|
|
la $t9, panic
|
|
jr $t9
|
|
|
|
save_regs
|
|
la $t9, interrupt
|
|
jr $t9
|
|
nop
|
|
.fill 0x280 - (. - addr_000)
|
|
|
|
// space for save_regs.
|
|
.word 0
|
|
.word 0
|
|
|
|
start_idle:
|
|
b .
|
|
nop
|
|
.word idle_page
|
|
.word 0x80000000 // A pointer to the current page.
|
|
|
|
__start:
|
|
bal 1f
|
|
nop
|
|
.word _gp
|
|
// For some reason the disassembler considers everything
|
|
// after __start non-code until the next label. So I add a label.
|
|
start_hack:
|
|
1: lw $gp, 0($ra)
|
|
|
|
la $sp, kernel_stack + KERNEL_STACK_SIZE
|
|
|
|
// Disable interrupts during bootstrap.
|
|
mtc0 $zero, $Status
|
|
|
|
// TODO: flush cache
|
|
|
|
// Set kseg0 cachable.
|
|
li $k0, 0x3
|
|
mtc0 $k0, $Config, 0
|
|
|
|
// Clear .bss
|
|
la $a0, _edata
|
|
la $a1, _end
|
|
1: sw $zero, 0($a0)
|
|
bne $a1, $a0, 1b
|
|
addu $a0, 4
|
|
|
|
// Set timer to a defined value
|
|
mtc0 $zero, $Compare, 0
|
|
|
|
// Use the interrupt vector for interrupts
|
|
li $k0, 1 << 23
|
|
mtc0 $k0, $Cause
|
|
|
|
li $a0, 0xff0a0000
|
|
la $t9, panic
|
|
jr $t9
|
|
|
|
// clear the tlb, hardwire page 0 to 0xffffffff
|
|
// and soft-wire it to (0x294 << 20) + (0x290 << 10)
|
|
// (for the idle task).
|
|
|
|
// this address doesn't reach the tlb, so it can't trigger exceptions.
|
|
mtc0 $zero, $PageMask
|
|
mtc0 $zero, $EntryLo0
|
|
mtc0 $zero, $EntryLo1
|
|
li $t0, 0x80000000
|
|
// There are 32 tlb entries.
|
|
addi $a0, $zero, 31
|
|
1: mtc0 $t0, $EntryHi
|
|
mtc0 $a0, $Index
|
|
tlbwi
|
|
addiu $t0, $t0, 1 << 13
|
|
bgtz $a0, 1b
|
|
addiu $a0, $a0, -1
|
|
|
|
la $t9, init
|
|
jalr $t9
|
|
nop
|
|
sw $gp, -12($zero)
|
|
|
|
save_args:
|
|
sw $a0, 24($k0)
|
|
sw $a1, 28($k0)
|
|
sw $a2, 32($k0)
|
|
sw $a3, 36($k0)
|
|
sw $t1, 44($k0)
|
|
sw $t2, 48($k0)
|
|
sw $t3, 52($k0)
|
|
sw $t4, 56($k0)
|
|
sw $t5, 60($k0)
|
|
sw $t6, 64($k0)
|
|
sw $t7, 68($k0)
|
|
sw $t8, 72($k0)
|
|
sw $t9, 76($k0)
|
|
sw $gp, 80($k0)
|
|
j $ra
|
|
|
|
run_idle:
|
|
move $k0, $a0
|
|
move $k1, $gp
|
|
// Prepare enabling interrupts and switching to user mode.
|
|
// The command is executed in the delay slot of the jump.
|
|
li $t0, 0xff11
|
|
// Now it's acceptable to receive an exception. Jump to kuseg,
|
|
// thereby generating a tlb_refill exception (which is handled).
|
|
// The address is the virtual address where the idle task is.
|
|
la $t9, ((0x294 << 20) + (0x290 << 10) + 0x288)
|
|
jr $t9
|
|
mtc0 $t0, $Status
|
|
|
|
kernel_exit:
|
|
move $k0, $v0
|
|
restore_regs
|
|
eret
|