1 /* 2 * Handler routines. 3 * 4 * Copyright (C) 2008 by Maurus Cuelenaere 5 * Copyright (C) 2015 Paul Boddie <paul@boddie.org.uk> 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 .text 22 .extern irq_handle 23 .extern irq_counter 24 .globl _exc_stack 25 .globl real_exception_handler 26 .set noreorder 27 .set noat 28 29 #define C0_STATUS $12 30 #define C0_CAUSE $13 31 #define C0_EPC $14 32 #define C0_CONFIG $16 33 #define C0_ERROREPC $30 34 #define S_CauseExcCode 2 35 #define M_CauseExcCode (0x1f << S_CauseExcCode) 36 37 _exc_stack: 38 .word 0 39 40 real_exception_handler: 41 addiu $sp, -0x88 /* multiple of 8 */ 42 sw $ra, 0($sp) 43 sw $fp, 4($sp) 44 sw $gp, 8($sp) 45 sw $t9, 0xC($sp) 46 sw $t8, 0x10($sp) 47 sw $s7, 0x14($sp) 48 sw $s6, 0x18($sp) 49 sw $s5, 0x1C($sp) 50 sw $s4, 0x20($sp) 51 sw $s3, 0x24($sp) 52 sw $s2, 0x28($sp) 53 sw $s1, 0x2C($sp) 54 sw $s0, 0x30($sp) 55 sw $t7, 0x34($sp) 56 sw $t6, 0x38($sp) 57 sw $t5, 0x3C($sp) 58 sw $t4, 0x40($sp) 59 sw $t3, 0x44($sp) 60 sw $t2, 0x48($sp) 61 sw $t1, 0x4C($sp) 62 sw $t0, 0x50($sp) 63 sw $a3, 0x54($sp) 64 sw $a2, 0x58($sp) 65 sw $a1, 0x5C($sp) 66 sw $a0, 0x60($sp) 67 sw $v1, 0x64($sp) 68 sw $v0, 0x68($sp) 69 sw $1, 0x6C($sp) 70 mflo $k0 71 nop 72 sw $k0, 0x70($sp) 73 mfhi $k0 74 nop 75 sw $k0, 0x74($sp) 76 mfc0 $k0, C0_STATUS 77 sll $zero, 1 78 sll $zero, 1 79 sll $zero, 1 80 sll $zero, 1 81 sw $k0, 0x78($sp) 82 mfc0 $k0, C0_EPC 83 sll $zero, 1 84 sll $zero, 1 85 sll $zero, 1 86 sll $zero, 1 87 sw $k0, 0x7C($sp) 88 mfc0 $k0, C0_ERROREPC 89 sll $zero, 1 90 sll $zero, 1 91 sll $zero, 1 92 sll $zero, 1 93 sw $k0, 0x80($sp) 94 95 li $k1, M_CauseExcCode 96 mfc0 $k0, C0_CAUSE 97 and $k0, $k1 98 beq $zero, $k0, _int 99 nop 100 j _exception 101 nop 102 103 _int: 104 /* Initialise the kernel stack. */ 105 106 la $k1, _exc_stack 107 lw $k0, 0($k1) 108 sw $sp, 0($k0) 109 addiu $k0, -4 110 move $sp, $k0 111 112 /* Initialise the globals pointer. */ 113 114 lui $gp, %hi(_GLOBAL_OFFSET_TABLE_) 115 ori $gp, $gp, %lo(_GLOBAL_OFFSET_TABLE_) 116 117 /* Test with counter. */ 118 119 la $t0, irq_counter 120 lw $t1, 0($t0) 121 addiu $t1, $t1, 1 122 sw $t1, 0($t0) 123 124 /* Invoke the handler. */ 125 126 jal irq_handle 127 nop 128 129 /* Restore the user stack. */ 130 131 addiu $sp, 4 132 lw $sp, 0($sp) 133 134 j _exception_return 135 nop 136 137 _exception: 138 j _exception_return 139 nop 140 141 _exception_return: 142 lw $ra, 0($sp) 143 lw $fp, 4($sp) 144 lw $gp, 8($sp) 145 lw $t9, 0xC($sp) 146 lw $t8, 0x10($sp) 147 lw $s7, 0x14($sp) 148 lw $s6, 0x18($sp) 149 lw $s5, 0x1C($sp) 150 lw $s4, 0x20($sp) 151 lw $s3, 0x24($sp) 152 lw $s2, 0x28($sp) 153 lw $s1, 0x2C($sp) 154 lw $s0, 0x30($sp) 155 lw $t7, 0x34($sp) 156 lw $t6, 0x38($sp) 157 lw $t5, 0x3C($sp) 158 lw $t4, 0x40($sp) 159 lw $t3, 0x44($sp) 160 lw $t2, 0x48($sp) 161 lw $t1, 0x4C($sp) 162 lw $t0, 0x50($sp) 163 lw $a3, 0x54($sp) 164 lw $a2, 0x58($sp) 165 lw $a1, 0x5C($sp) 166 lw $a0, 0x60($sp) 167 lw $v1, 0x64($sp) 168 lw $v0, 0x68($sp) 169 lw $1, 0x6C($sp) 170 lw $k0, 0x70($sp) 171 mtlo $k0 172 nop 173 lw $k0, 0x74($sp) 174 mthi $k0 175 nop 176 lw $k0, 0x78($sp) 177 mtc0 $k0, C0_STATUS 178 nop 179 sll $zero, 1 180 sll $zero, 1 181 sll $zero, 1 182 sll $zero, 1 183 lw $k0, 0x7C($sp) 184 mtc0 $k0, C0_EPC 185 nop 186 sll $zero, 1 187 sll $zero, 1 188 sll $zero, 1 189 sll $zero, 1 190 lw $k0, 0x80($sp) 191 mtc0 $k0, C0_ERROREPC 192 nop 193 sll $zero, 1 194 sll $zero, 1 195 sll $zero, 1 196 sll $zero, 1 197 addiu $sp, 0x88 /* multiple of 8 */ 198 eret 199 nop 200 201 .set reorder 202 .set at