1 /* 2 * Handler routines. 3 * 4 * Copyright (C) 2015 Nicholas FitzRoy-Dale <wzdd.code@lardcave.net> 5 * Copyright (C) 2015, 2016 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 current_registers 24 .extern current_stack_pointer 25 .extern current_task 26 .globl interrupt_handler 27 .globl enter_task 28 .set noreorder 29 .set noat 30 31 interrupt_handler: 32 /* gp should have been set in the entrypoint. */ 33 34 jal save_state 35 nop 36 37 /* Invoke the handler. */ 38 39 jal irq_handle 40 nop 41 42 /* Switch the stack pointer. */ 43 44 la $k0, current_stack_pointer 45 lw $k1, 0($k0) /* &stack_pointers[current_task] */ 46 lw $sp, 0($k1) 47 48 /* Set the current task ASID. */ 49 50 la $k0, current_task 51 lw $k1, 0($k0) 52 mtc0 $k1, $10 /* CP0_ENTRYHI */ 53 nop 54 55 /* Obtain the current task's registers. */ 56 57 j load_and_return 58 nop 59 60 save_state: 61 /* Obtain a store of registers for the current task. */ 62 63 la $k0, current_registers 64 lw $k1, 0($k0) 65 66 sw $at, 4($k1) 67 sw $v0, 8($k1) 68 sw $v1, 12($k1) 69 sw $a0, 16($k1) 70 sw $a1, 20($k1) 71 sw $a2, 24($k1) 72 sw $a3, 28($k1) 73 sw $t0, 32($k1) 74 sw $t1, 36($k1) 75 sw $t2, 40($k1) 76 sw $t3, 44($k1) 77 sw $t4, 48($k1) 78 sw $t5, 52($k1) 79 sw $t6, 56($k1) 80 sw $t7, 60($k1) 81 sw $s0, 64($k1) 82 sw $s1, 68($k1) 83 sw $s2, 72($k1) 84 sw $s3, 76($k1) 85 sw $s4, 80($k1) 86 sw $s5, 84($k1) 87 sw $s6, 88($k1) 88 sw $s7, 92($k1) 89 sw $t8, 96($k1) 90 91 /* t9, gp and ra are already saved */ 92 93 sw $fp, 108($k1) 94 95 mfc0 $k0, $14 /* CP0_EPC */ 96 nop 97 sw $k0, 116($k1) 98 99 mflo $k0 100 sw $k0, 120($k1) 101 mfhi $k0 102 sw $k0, 124($k1) 103 104 jr $ra 105 nop 106 107 load_and_return: 108 /* Obtain a store of registers for the current task. */ 109 110 la $k0, current_registers 111 lw $k1, 0($k0) 112 113 lw $at, 4($k1) 114 lw $v0, 8($k1) 115 lw $v1, 12($k1) 116 lw $a0, 16($k1) 117 lw $a1, 20($k1) 118 lw $a2, 24($k1) 119 lw $a3, 28($k1) 120 lw $t0, 32($k1) 121 lw $t1, 36($k1) 122 lw $t2, 40($k1) 123 lw $t3, 44($k1) 124 lw $t4, 48($k1) 125 lw $t5, 52($k1) 126 lw $t6, 56($k1) 127 lw $t7, 60($k1) 128 lw $s0, 64($k1) 129 lw $s1, 68($k1) 130 lw $s2, 72($k1) 131 lw $s3, 76($k1) 132 lw $s4, 80($k1) 133 lw $s5, 84($k1) 134 lw $s6, 88($k1) 135 lw $s7, 92($k1) 136 lw $t8, 96($k1) 137 lw $t9, 100($k1) 138 lw $gp, 104($k1) 139 lw $fp, 108($k1) 140 lw $ra, 112($k1) 141 142 lw $k0, 116($k1) 143 mtc0 $k0, $14 /* CP0_EPC */ 144 nop 145 146 lw $k0, 120($k1) 147 mtlo $k0 148 lw $k0, 124($k1) 149 mthi $k0 150 151 lui $k0, %hi(_enter_task) 152 ori $k0, $k0, %lo(_enter_task) 153 lw $k1, 0($k0) 154 jr $k1 155 nop 156 157 enter_task: 158 eret 159 nop 160 161 .set reorder 162 .set at