/************************************************************************************ * This file contains the two entry points in the GIET_VM code: * - the _init entry point (from the boot code) is 0x80000000 * - the _giet entry point (from user applications) is 0x80000180 * => The base address of the segment containing this code MUST be 0x80000000. * * The _giet uses two arrays of functions: * - the _cause_vector[16] array defines the 16 causes to enter the GIET * it is initialized in th exc_handler.c file * - the _syscall_vector[64] array defines the 64 system calls entry points * it is initialised in the sys_handler.c file ***********************************************************************************/ .section .giet, "ax", @progbits /* * INIT entry point (at address 0x80000000) */ .func _init .type _init, %function _init: la $26, _kernel_init jr $26 /* jump to _kernel_init */ .endfunc .size _init, .-_init .space 0x170 /* the _entry function occupies 16 bytes */ /* * GIET Entry point (at address 0x80000180) */ .func _giet .type _giet, %function _giet: mfc0 $27, $13 /* $27 <= Cause register */ andi $27, $27, 0x3c /* $27 <= XCODE*4 */ beq $27, $0, do_jump /* jump if interrupt */ addiu $26, $0, 0x20 beq $27, $26, do_jump /* jump if syscall */ /* * exception: save registers into stack for future display by exception handler */ addiu $27, $29, -38*4 sw $29, (29*4)($27) /* save $29 */ or $29, $27, $0 .set noat sw $1, (1*4)($29) /* save $1 */ .set at sw $2, (2*4)($29) /* save $2 */ sw $3, (3*4)($29) /* save $3 */ sw $4, (4*4)($29) /* save $4 */ sw $5, (5*4)($29) /* save $5 */ sw $6, (6*4)($29) /* save $6 */ sw $7, (7*4)($29) /* save $7 */ sw $8, (8*4)($29) /* save $8 */ sw $9, (9*4)($29) /* save $9 */ sw $10, (10*4)($29) /* save $10 */ sw $11, (11*4)($29) /* save $11 */ sw $12, (12*4)($29) /* save $12 */ sw $13, (13*4)($29) /* save $13 */ sw $14, (14*4)($29) /* save $14 */ sw $15, (15*4)($29) /* save $15 */ sw $16, (16*4)($29) /* save $16 */ sw $17, (17*4)($29) /* save $17 */ sw $18, (18*4)($29) /* save $18 */ sw $19, (19*4)($29) /* save $19 */ sw $20, (20*4)($29) /* save $20 */ sw $21, (21*4)($29) /* save $21 */ sw $22, (22*4)($29) /* save $22 */ sw $23, (23*4)($29) /* save $23 */ sw $24, (24*4)($29) /* save $24 */ sw $25, (25*4)($29) /* save $25 */ sw $28, (28*4)($29) /* save $28 */ sw $30, (30*4)($29) /* save $30 */ sw $31, (31*4)($29) /* save $31 */ mflo $14 /* LO */ mfhi $15 /* HI */ mfc0 $16, $14 /* EPC */ mfc0 $17, $13 /* CR */ mfc0 $18, $12 /* SR */ mfc0 $19, $8 /* BVAR */ sw $14, (35*4)($29) /* save LO */ sw $15, (36*4)($29) /* save HI */ sw $16, (32*4)($29) /* Save EPC */ sw $17, (33*4)($29) /* Save CR */ sw $18, (34*4)($29) /* Save SR */ sw $19, (37*4)($29) /* save BVAR */ or $4, $0, $27 /* $4 <= regs_table */ do_jump: mfc0 $27, $13 /* $27 <= Cause register */ andi $27, $27, 0x3c /* $27 <= XCODE*4 */ la $26, _cause_vector /* $26 <= _cause_vector */ addu $26, $26, $27 /* $26 <= &_cause_vector[XCODE] */ lw $26, 0($26) /* $26 <= _cause_vector[XCODE] */ jr $26 /* Jump to handler indexed by XCODE */ .endfunc .size _giet, .-_giet /* * *** Syscall Handler *** * * A system call is handled as a special function call. * - $2 contains the system call index (< 64). * - $3 is used to store the syscall address * - $4, $5, $6, $7 contain the arguments values. * - The return address (EPC) and the (SR) are saved in the stack. * - Interrupts are enabled before branching to the syscall. * - All syscalls must return to the syscall handler. * - $2, $3, $4, $5, $6, $7 as well as $26 & $27 can be modified. * * In case of undefined system call, an error message displays * the value of EPC on the kernel TTY, and the user program is killed. */ .globl _sys_handler .func _sys_handler .type _sys_handler, %function _sys_handler: addiu $29, $29, -24 /* 2 slots for SR & EPC, 4 slots for args */ mfc0 $27, $14 /* $27 <= EPC */ addiu $27, $27, 4 /* increment EPC for return address */ sw $27, 20($29) /* save EPC in the stack */ mfc0 $27, $12 /* $27 <= SR */ sw $27, 16($29) /* save SR in the stack */ andi $26, $2, 0x3F /* $26 <= syscall index (i < 64) */ sll $26, $26, 2 /* $26 <= index * 4 */ la $27, _syscall_vector /* $27 <= &_syscall_vector[0] */ addu $27, $27, $26 /* $27 <= &_syscall_vector[i] */ lw $3, 0($27) /* $3 <= syscall address */ li $27, 0xFFFFFFED /* Mask for UM & EXL bits */ mfc0 $26, $12 /* $26 <= SR */ and $26, $26, $27 /* UM = 0 / EXL = 0 */ mtc0 $26, $12 /* interrupt enabled */ jalr $3 /* jump to the proper syscall */ mtc0 $0, $12 /* SR <= 0 : interrupt disabled */ lw $26, 16($29) /* $26 <= SR from stack */ mtc0 $26, $12 /* restore SR */ lw $26, 20($29) /* $26 <= EPC from stack */ mtc0 $26, $14 /* restore EPC */ addiu $29, $29, 24 /* restore stack pointer */ eret /* exit GIET */ .endfunc .size _sys_handler, .-_sys_handler /* * *** Interrupt Handler *** * * This simple interrupt handler cannot be interrupted. * * All non persistant registers, such as $1 to $15, and $24 to $25, as well as * register $31 and EPC, are saved in the interrupted program stack, before * calling the Interrupt Service Routine. These registers can be used by the * ISR code. */ .globl _int_handler .func _int_handler .type _int_handler, %function _int_handler: addiu $29, $29, -25*4 /* stack space reservation (21 registers to save and 4 free words to call function) */ .set noat sw $1, 4*4($29) /* save $1 */ .set at sw $2, 5*4($29) /* save $2 */ sw $3, 6*4($29) /* save $3 */ sw $4, 7*4($29) /* save $4 */ sw $5, 8*4($29) /* save $5 */ sw $6, 9*4($29) /* save $6 */ sw $7, 10*4($29) /* save $7 */ sw $8, 11*4($29) /* save $8 */ sw $9, 12*4($29) /* save $9 */ sw $10, 13*4($29) /* save $10 */ sw $11, 14*4($29) /* save $11 */ sw $12, 15*4($29) /* save $12 */ sw $13, 16*4($29) /* save $13 */ sw $14, 17*4($29) /* save $14 */ sw $15, 18*4($29) /* save $15 */ sw $24, 19*4($29) /* save $24 */ sw $25, 20*4($29) /* save $25 */ sw $31, 21*4($29) /* save $31 */ mflo $26 sw $26, 22*4($29) /* save LO */ mfhi $26 sw $26, 23*4($29) /* save HI */ mfc0 $27, $14 sw $27, 24*4($29) /* save EPC */ la $26, _irq_demux jalr $26 /* jump to a C function to find the proper ISR */ restore: .set noat lw $1, 4*4($29) /* restore $1 */ .set at lw $2, 4*5($29) /* restore $2 */ lw $3, 4*6($29) /* restore $3 */ lw $4, 4*7($29) /* restore $4 */ lw $5, 4*8($29) /* restore $5 */ lw $6, 4*9($29) /* restore $6 */ lw $7, 4*10($29) /* restore $7 */ lw $8, 4*11($29) /* restore $8 */ lw $9, 4*12($29) /* restore $9 */ lw $10, 4*13($29) /* restore $10 */ lw $11, 4*14($29) /* restore $11 */ lw $12, 4*15($29) /* restore $12 */ lw $13, 4*16($29) /* restore $13 */ lw $14, 4*17($29) /* restore $14 */ lw $15, 4*18($29) /* restore $15 */ lw $24, 4*19($29) /* restore $24 */ lw $25, 4*20($29) /* restore $25 */ lw $31, 4*21($29) /* restore $31 */ lw $26, 4*22($29) mtlo $26 /* restore LO */ lw $26, 4*23($29) mthi $26 /* restore HI */ lw $27, 4*24($29) /* return address (EPC) */ addiu $29, $29, 25*4 /* restore stack pointer */ mtc0 $27, $14 /* restore EPC */ eret /* exit GIET */ .endfunc .size _int_handler, .-_int_handler