1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-07-03 01:13:18 +03:00
iris/mips/entry.S

243 lines
4.9 KiB
ArmAsm
Raw Normal View History

2009-06-01 15:26:42 +03:00
// Iris: micro-kernel for a capability-based operating system.
// mips/entry.S: Routines which are entered from user space.
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
2009-05-11 01:28:12 +03:00
// The kernel stack.
.lcomm kernel_stack, KERNEL_STACK_SIZE
.globl run_idle
.globl directory
2009-05-11 01:28:12 +03:00
.set noat
.set noreorder
2009-05-11 01:28:12 +03:00
2009-05-25 01:31:35 +03:00
#define ARCH
#define ASM
2009-06-22 18:48:05 +03:00
#define __KERNEL
2009-05-25 01:31:35 +03:00
#include "arch.hh"
2009-05-11 01:28:12 +03:00
addr_000:
2009-05-27 15:38:52 +03:00
#if 0
2009-05-11 01:28:12 +03:00
// TLB refill
bne $zero, $k1, slow_refill
nop
2009-06-01 02:12:54 +03:00
bne $zero, $k0, slow_refill
lw $k1, -0xd94($zero)
mfc0 $k0, $CP0_ENTRY_HI
srl $k0, $k0, 19
and $k0, $k0, 0x3fc
addu $k0, $k0, $k1
2009-06-01 02:12:54 +03:00
beq $zero, $k0, zero_refill
lw $k0, 0($k0)
mfc0 $k1, $CP0_ENTRY_HI
srl $k1, $k1, 10
and $k1, $k1, 0x1f8
add $k0, $k0, $k1
lw $k1, 0($k0)
mtc0 $k1, $CP0_ENTRY_LO0
lw $k1, 4($k0)
mtc0 $k1, $CP0_ENTRY_LO1
2009-06-01 02:12:54 +03:00
1: tlbwr
move $zero, $k0
move $zero, $k1
eret
2009-06-01 02:12:54 +03:00
zero_refill:
mtc0 $zero, $CP_ENTRY_LO0
b 1b
mtc0 $zero, $CP_ENTRY_LO1
slow_refill:
2009-06-01 02:12:54 +03:00
move $k1, $zero
2009-05-27 15:38:52 +03:00
#endif
2009-05-22 23:48:49 +03:00
sw $ra, -0xd88($zero)
2009-05-14 21:31:47 +03:00
bal save_regs
2009-05-27 15:38:52 +03:00
nop
2009-05-11 01:28:12 +03:00
la $t9, tlb_refill
jr $t9
nop
.fill 0x100 - (. - addr_000)
addr_100:
// Cache error
2009-05-22 23:48:49 +03:00
sw $ra, -0xd88($zero)
2009-05-14 21:31:47 +03:00
bal save_regs
2009-05-27 15:38:52 +03:00
nop
2009-05-11 01:28:12 +03:00
la $t9, cache_error
jr $t9
nop
.fill 0x180 - (. - addr_000)
addr_180:
// General exception
2009-05-22 23:48:49 +03:00
sw $ra, -0xd88($zero)
2009-05-14 21:31:47 +03:00
bal save_regs
2009-05-27 15:38:52 +03:00
nop
2009-05-11 01:28:12 +03:00
la $t9, exception
jr $t9
nop
2009-05-27 15:38:52 +03:00
.fill 0x200 - (. - addr_000) - 8
.word 0x0000001e // 1f8 EntryLo data for idle page.
.word 0x80000000 // 1fc A pointer to the current page.
2009-05-11 01:28:12 +03:00
addr_200:
// Interrupt
2009-05-22 23:48:49 +03:00
sw $ra, -0xd88($zero)
2009-05-14 21:31:47 +03:00
bal save_regs
2009-05-27 15:38:52 +03:00
nop
2009-05-11 01:28:12 +03:00
la $t9, interrupt
jr $t9
nop
2009-05-27 15:38:52 +03:00
.fill 0x280 - (. - addr_000) - 20
2009-05-11 01:28:12 +03:00
directory:
.word 0 // -d94 == directory
// space for save_regs
2009-05-22 23:48:49 +03:00
.word 0 // -d90 == k0
.word idle // -d8c == current
.word 0 // -d88 == ra
.word _gp // -d84 == gp
2009-05-11 01:28:12 +03:00
2009-05-27 15:38:52 +03:00
start_idle: // 280
2009-05-14 21:31:47 +03:00
// Wait for the next interrupt, then the first thread will be scheduled.
// It is impractical to try to call schedule, because for that the
// idle task would need to own capabilities.
2009-05-22 23:48:49 +03:00
move $v0, $zero
2009-05-14 21:31:47 +03:00
syscall
2009-05-23 21:55:31 +03:00
nop
2009-05-14 21:31:47 +03:00
1: wait
b 1b
nop
2009-05-11 01:28:12 +03:00
2009-05-19 00:18:23 +03:00
// TODO: save only fragile registers now, the rest on task switch.
2009-05-14 21:31:47 +03:00
kernel_exit:
2009-07-04 17:21:28 +03:00
#ifndef NDEBUG
// Allow interrupts to set EPC and friends.
mfc0 $k0, $CP0_STATUS
ori $k0, $k0, 0xff13
mtc0 $k0, $CP0_STATUS
#endif
2009-05-19 00:18:23 +03:00
lw $k0, SAVE_PC($v0)
2009-05-25 01:31:35 +03:00
mtc0 $k0, $CP0_EPC
2009-05-19 00:18:23 +03:00
lw $k0, SAVE_LO($v0)
lw $k1, SAVE_HI($v0)
mtlo $k0
mthi $k1
lw $v1, SAVE_V1($v0)
lw $a0, SAVE_A0($v0)
lw $a1, SAVE_A1($v0)
lw $a2, SAVE_A2($v0)
lw $a3, SAVE_A3($v0)
lw $t0, SAVE_T0($v0)
lw $t1, SAVE_T1($v0)
lw $t2, SAVE_T2($v0)
lw $t3, SAVE_T3($v0)
lw $t4, SAVE_T4($v0)
lw $t5, SAVE_T5($v0)
lw $t6, SAVE_T6($v0)
lw $t7, SAVE_T7($v0)
lw $t8, SAVE_T8($v0)
lw $t9, SAVE_T9($v0)
2009-05-22 23:48:49 +03:00
lw $s0, SAVE_S0($v0)
lw $s1, SAVE_S1($v0)
lw $s2, SAVE_S2($v0)
lw $s3, SAVE_S3($v0)
lw $s4, SAVE_S4($v0)
lw $s5, SAVE_S5($v0)
lw $s6, SAVE_S6($v0)
lw $s7, SAVE_S7($v0)
2009-05-19 00:18:23 +03:00
lw $fp, SAVE_FP($v0)
lw $ra, SAVE_RA($v0)
lw $at, SAVE_AT($v0)
lw $k0, SAVE_K0($v0)
lw $k1, SAVE_V0($v0)
2009-05-22 23:48:49 +03:00
sw $k1, -0xd90($zero)
2009-05-19 00:18:23 +03:00
lw $k1, SAVE_K1($v0)
2009-05-22 23:48:49 +03:00
sw $v0, -0xd8c($zero)
2009-05-23 21:55:31 +03:00
lw $sp, SAVE_SP($v0)
2009-05-22 23:48:49 +03:00
lw $gp, SAVE_GP($v0)
lw $v0, -0xd90($zero)
2009-05-14 21:31:47 +03:00
eret
2009-05-11 01:28:12 +03:00
2009-05-14 21:31:47 +03:00
save_regs:
2009-05-22 23:48:49 +03:00
sw $k0, -0xd90($zero)
lw $k0, -0xd8c($zero)
2009-05-19 00:18:23 +03:00
sw $at, SAVE_AT($k0)
sw $gp, SAVE_GP($k0)
sw $sp, SAVE_SP($k0)
sw $fp, SAVE_FP($k0)
2009-05-11 01:28:12 +03:00
2009-05-19 00:18:23 +03:00
sw $k1, SAVE_K1($k0)
2009-05-22 23:48:49 +03:00
lw $k1, -0xd90($zero)
2009-05-19 00:18:23 +03:00
sw $k1, SAVE_K0($k0)
2009-05-11 01:28:12 +03:00
2009-05-22 23:48:49 +03:00
lw $k1, -0xd88($zero)
2009-05-19 00:18:23 +03:00
sw $k1, SAVE_RA($k0)
sw $v0, SAVE_V0($k0)
sw $v1, SAVE_V1($k0)
sw $a0, SAVE_A0($k0)
sw $a1, SAVE_A1($k0)
sw $a2, SAVE_A2($k0)
sw $a3, SAVE_A3($k0)
sw $t0, SAVE_T0($k0)
sw $t1, SAVE_T1($k0)
sw $t2, SAVE_T2($k0)
sw $t3, SAVE_T3($k0)
sw $t4, SAVE_T4($k0)
sw $t5, SAVE_T5($k0)
sw $t6, SAVE_T6($k0)
sw $t7, SAVE_T7($k0)
sw $t8, SAVE_T8($k0)
sw $t9, SAVE_T9($k0)
2009-05-22 23:48:49 +03:00
sw $s0, SAVE_S0($k0)
sw $s1, SAVE_S1($k0)
sw $s2, SAVE_S2($k0)
sw $s3, SAVE_S3($k0)
sw $s4, SAVE_S4($k0)
sw $s5, SAVE_S5($k0)
sw $s6, SAVE_S6($k0)
sw $s7, SAVE_S7($k0)
2009-05-14 21:31:47 +03:00
mfhi $v0
mflo $v1
2009-05-19 00:18:23 +03:00
sw $v0, SAVE_HI($k0)
sw $v1, SAVE_LO($k0)
2009-05-25 01:31:35 +03:00
mfc0 $k1, $CP0_EPC
2009-05-19 00:18:23 +03:00
sw $k1, SAVE_PC($k0)
2009-05-11 01:28:12 +03:00
2009-05-22 23:48:49 +03:00
lw $gp, -0xd84($zero)
2009-05-14 21:31:47 +03:00
la $sp, kernel_stack + KERNEL_STACK_SIZE
2009-07-04 17:21:28 +03:00
#ifndef NDEBUG
// Allow interrupts to set EPC and friends.
mfc0 $k0, $CP0_STATUS
andi $k0, $k0, 0xff00
mtc0 $k0, $CP0_STATUS
#endif
2009-05-14 21:31:47 +03:00
move $t9, $ra
la $ra, kernel_exit
jr $t9
2009-05-23 21:55:31 +03:00
nop
2009-05-22 23:48:49 +03:00
.globl thread0
.globl thread1
.globl thread2
.balign 0x1000
2009-05-23 21:55:31 +03:00
thread0:
2009-06-22 17:13:00 +03:00
.incbin "lcd"
2009-05-22 23:48:49 +03:00
.balign 0x1000
2009-05-23 21:55:31 +03:00
thread1:
2009-06-22 17:13:00 +03:00
.incbin "keyboard"
2009-05-22 23:48:49 +03:00
thread2: