[444] | 1 | /* exceptions-asm.S -- exception handling for OpenRISC 1000. |
---|
| 2 | * |
---|
| 3 | * Copyright (c) 2011, 2014 Authors |
---|
| 4 | * |
---|
| 5 | * Contributor Julius Baxter <juliusbaxter@gmail.com> |
---|
| 6 | * Contributor Stefan Wallentowitz <stefan.wallentowitz@tum.de> |
---|
| 7 | * |
---|
| 8 | * The authors hereby grant permission to use, copy, modify, distribute, |
---|
| 9 | * and license this software and its documentation for any purpose, provided |
---|
| 10 | * that existing copyright notices are retained in all copies and that this |
---|
| 11 | * notice is included verbatim in any distributions. No written agreement, |
---|
| 12 | * license, or royalty fee is required for any of the authorized uses. |
---|
| 13 | * Modifications to this software may be copyrighted by their authors |
---|
| 14 | * and need not follow the licensing terms described here, provided that |
---|
| 15 | * the new terms are clearly indicated on the first page of each file where |
---|
| 16 | * they apply. |
---|
| 17 | */ |
---|
| 18 | |
---|
| 19 | #include "include/or1k-asm.h" |
---|
| 20 | #include "include/or1k-sprs.h" |
---|
| 21 | |
---|
| 22 | /* -------------------------------------------------------------------------- */ |
---|
| 23 | /*!Generic exception handler function |
---|
| 24 | */ |
---|
| 25 | /* -------------------------------------------------------------------------- */ |
---|
| 26 | // Warning - this must be the same as specified in crt0.S |
---|
| 27 | #define EXCEPTION_STACK_SIZE 136 |
---|
| 28 | |
---|
| 29 | .extern _or1k_exception_handler_table |
---|
| 30 | .extern _or1k_exception_level |
---|
| 31 | |
---|
| 32 | /* -------------------------------------------------------------------------- */ |
---|
| 33 | /*!Function to call appropriate exception handler |
---|
| 34 | */ |
---|
| 35 | /* -------------------------------------------------------------------------- */ |
---|
| 36 | .section .text |
---|
| 37 | .global _or1k_exception_handler |
---|
| 38 | .type _or1k_exception_handler,@function |
---|
| 39 | |
---|
| 40 | /* |
---|
| 41 | r3 = address of exception vector |
---|
| 42 | r4 = address where exception occurred |
---|
| 43 | */ |
---|
| 44 | |
---|
| 45 | #define GPR_BUF_OFFSET(x) (x << 2) |
---|
| 46 | |
---|
| 47 | _or1k_exception_handler: |
---|
| 48 | /* Store remainder of state (r3,r4 stored in vector entry)*/ |
---|
| 49 | l.sw GPR_BUF_OFFSET(2)(r1),r2 |
---|
| 50 | l.sw GPR_BUF_OFFSET(5)(r1),r5 |
---|
| 51 | l.sw GPR_BUF_OFFSET(6)(r1),r6 |
---|
| 52 | l.sw GPR_BUF_OFFSET(7)(r1),r7 |
---|
| 53 | l.sw GPR_BUF_OFFSET(8)(r1),r8 |
---|
| 54 | l.sw GPR_BUF_OFFSET(9)(r1),r9 |
---|
| 55 | l.sw GPR_BUF_OFFSET(10)(r1),r10 |
---|
| 56 | l.sw GPR_BUF_OFFSET(11)(r1),r11 |
---|
| 57 | l.sw GPR_BUF_OFFSET(12)(r1),r12 |
---|
| 58 | l.sw GPR_BUF_OFFSET(13)(r1),r13 |
---|
| 59 | l.sw GPR_BUF_OFFSET(14)(r1),r14 |
---|
| 60 | l.sw GPR_BUF_OFFSET(15)(r1),r15 |
---|
| 61 | l.sw GPR_BUF_OFFSET(16)(r1),r16 |
---|
| 62 | l.sw GPR_BUF_OFFSET(17)(r1),r17 |
---|
| 63 | l.sw GPR_BUF_OFFSET(18)(r1),r18 |
---|
| 64 | l.sw GPR_BUF_OFFSET(19)(r1),r19 |
---|
| 65 | l.sw GPR_BUF_OFFSET(20)(r1),r20 |
---|
| 66 | l.sw GPR_BUF_OFFSET(21)(r1),r21 |
---|
| 67 | l.sw GPR_BUF_OFFSET(22)(r1),r22 |
---|
| 68 | l.sw GPR_BUF_OFFSET(23)(r1),r23 |
---|
| 69 | l.sw GPR_BUF_OFFSET(24)(r1),r24 |
---|
| 70 | l.sw GPR_BUF_OFFSET(25)(r1),r25 |
---|
| 71 | l.sw GPR_BUF_OFFSET(26)(r1),r26 |
---|
| 72 | l.sw GPR_BUF_OFFSET(27)(r1),r27 |
---|
| 73 | l.sw GPR_BUF_OFFSET(28)(r1),r28 |
---|
| 74 | l.sw GPR_BUF_OFFSET(29)(r1),r29 |
---|
| 75 | l.sw GPR_BUF_OFFSET(30)(r1),r30 |
---|
| 76 | l.sw GPR_BUF_OFFSET(31)(r1),r31 |
---|
| 77 | l.mfspr r14,r0,OR1K_SPR_SYS_EPCR_BASE |
---|
| 78 | l.sw 0x80(r1),r14 |
---|
| 79 | l.mfspr r14,r0,OR1K_SPR_SYS_ESR_BASE |
---|
| 80 | l.sw 0x84(r1),r14 |
---|
| 81 | |
---|
| 82 | /* Replace impure pointer for exception */ |
---|
| 83 | l.movhi r20,hi(_or1k_exception_impure_ptr) |
---|
| 84 | l.ori r20,r20,lo(_or1k_exception_impure_ptr) |
---|
| 85 | #ifdef __OR1K_MULTICORE__ |
---|
| 86 | l.lwz r20,0(r20) |
---|
| 87 | l.mfspr r22,r0,OR1K_SPR_SYS_COREID_ADDR |
---|
| 88 | l.slli r22,r22,2 |
---|
| 89 | l.add r20,r20,r22 |
---|
| 90 | #endif |
---|
| 91 | l.lwz r20,0(r20) |
---|
| 92 | |
---|
| 93 | l.movhi r21,hi(_or1k_current_impure_ptr) |
---|
| 94 | l.ori r21,r21,lo(_or1k_current_impure_ptr) |
---|
| 95 | #ifdef __OR1K_MULTICORE__ |
---|
| 96 | l.lwz r21,0(r21) |
---|
| 97 | l.add r21,r21,r22 |
---|
| 98 | #endif |
---|
| 99 | l.sw 0(r21),r20 |
---|
| 100 | |
---|
| 101 | /* Determine offset in table of exception handler using r3*/ |
---|
| 102 | l.andi r13,r3,0xff00 |
---|
| 103 | l.srli r13,r13,6 |
---|
| 104 | /* Substract 2 words, as we have no vector at 0 and no reset handler */ |
---|
| 105 | l.addi r13,r13,-8 |
---|
| 106 | /* r13 now contains offset in or1k_exception_handler_table for |
---|
| 107 | function |
---|
| 108 | */ |
---|
| 109 | /* Get or1k_exception_handler_table address */ |
---|
| 110 | l.movhi r14,hi(_or1k_exception_handler_table) |
---|
| 111 | l.ori r14,r14,lo(_or1k_exception_handler_table) |
---|
| 112 | #ifdef __OR1K_MULTICORE__ |
---|
| 113 | /* Read the address of the array of cores */ |
---|
| 114 | /* r14 = (*or1k_exception_handler_table) */ |
---|
| 115 | l.lwz r14,0(r14) |
---|
| 116 | /* Generate core offset in array (off = coreid*30*4 = coreid*120) */ |
---|
| 117 | /* r15 = coreid */ |
---|
| 118 | l.mfspr r15,r0,OR1K_SPR_SYS_COREID_ADDR |
---|
| 119 | /* r16 = coreid * 128 */ |
---|
| 120 | l.slli r16,r15,7 |
---|
| 121 | /* r15 = coreid * 8 */ |
---|
| 122 | l.slli r15,r15,3 |
---|
| 123 | /* r15 = coreid*128 - coreid*8 = coreid*120 = off */ |
---|
| 124 | l.sub r15,r16,r15 |
---|
| 125 | /* r14 = (*or1k_exception_handler_table)[coreid] = r14 + off */ |
---|
| 126 | l.add r14,r14,r15 |
---|
| 127 | #endif |
---|
| 128 | /* r14 now contains base of exception handler table */ |
---|
| 129 | /* add offset of exception vector */ |
---|
| 130 | l.add r14,r14,r13 |
---|
| 131 | /* load handler address from table */ |
---|
| 132 | l.lwz r13, 0(r14) |
---|
| 133 | |
---|
| 134 | /* Check to see if this handler has been set yet */ |
---|
| 135 | l.sfne r13,r0 |
---|
| 136 | OR1K_DELAYED_NOP(OR1K_INST(l.bnf exception_exit)) |
---|
| 137 | |
---|
| 138 | /* Call exception handler, copy EPCR to r3 */ |
---|
| 139 | OR1K_DELAYED( |
---|
| 140 | OR1K_INST(l.or r3,r4,r4), |
---|
| 141 | OR1K_INST(l.jalr r13) |
---|
| 142 | ) |
---|
| 143 | |
---|
| 144 | /* Restore impure pointer */ |
---|
| 145 | l.movhi r20,hi(_or1k_impure_ptr) |
---|
| 146 | l.ori r20,r20,lo(_or1k_impure_ptr) |
---|
| 147 | #ifdef __OR1K_MULTICORE__ |
---|
| 148 | l.lwz r20,0(r20) |
---|
| 149 | l.mfspr r22,r0,OR1K_SPR_SYS_COREID_ADDR |
---|
| 150 | l.slli r22,r22,2 |
---|
| 151 | l.add r20,r20,r22 |
---|
| 152 | #endif |
---|
| 153 | l.lwz r20,0(r20) |
---|
| 154 | |
---|
| 155 | l.movhi r21,hi(_or1k_current_impure_ptr) |
---|
| 156 | l.ori r21,r21,lo(_or1k_current_impure_ptr) |
---|
| 157 | #ifdef __OR1K_MULTICORE__ |
---|
| 158 | l.lwz r21,0(r21) |
---|
| 159 | l.add r21,r21,r22 |
---|
| 160 | #endif |
---|
| 161 | l.sw 0(r21),r20 |
---|
| 162 | |
---|
| 163 | /* Decrement the exception nesting level */ |
---|
| 164 | // Load the exception level entry |
---|
| 165 | l.movhi r2,hi(_or1k_exception_level) |
---|
| 166 | l.ori r2,r2,lo(_or1k_exception_level) |
---|
| 167 | #ifdef __OR1K_MULTICORE__ |
---|
| 168 | // In multicore this is the pointer to an array |
---|
| 169 | // Load pointer value |
---|
| 170 | l.lwz r2,0(r2) |
---|
| 171 | // Add word offset of this core's nesting level |
---|
| 172 | l.add r2,r2,r22 |
---|
| 173 | #endif |
---|
| 174 | // Load the nesting level entry |
---|
| 175 | l.lwz r3,0(r2) |
---|
| 176 | // Decrement nesting level |
---|
| 177 | l.addi r3,r3,-1 |
---|
| 178 | // Store back the nesting level |
---|
| 179 | l.sw 0(r2),r3 |
---|
| 180 | |
---|
| 181 | /* Restore state */ |
---|
| 182 | l.lwz r2,0x80(r1) |
---|
| 183 | l.mtspr r0,r2,OR1K_SPR_SYS_EPCR_BASE |
---|
| 184 | |
---|
| 185 | l.lwz r2,0x84(r1) |
---|
| 186 | l.mtspr r0,r2,OR1K_SPR_SYS_ESR_BASE |
---|
| 187 | |
---|
| 188 | l.lwz r2,GPR_BUF_OFFSET(2)(r1) |
---|
| 189 | l.lwz r3,GPR_BUF_OFFSET(3)(r1) |
---|
| 190 | l.lwz r4,GPR_BUF_OFFSET(4)(r1) |
---|
| 191 | l.lwz r5,GPR_BUF_OFFSET(5)(r1) |
---|
| 192 | l.lwz r6,GPR_BUF_OFFSET(6)(r1) |
---|
| 193 | l.lwz r7,GPR_BUF_OFFSET(7)(r1) |
---|
| 194 | l.lwz r8,GPR_BUF_OFFSET(8)(r1) |
---|
| 195 | l.lwz r9,GPR_BUF_OFFSET(9)(r1) |
---|
| 196 | l.lwz r10,GPR_BUF_OFFSET(10)(r1) |
---|
| 197 | l.lwz r11,GPR_BUF_OFFSET(11)(r1) |
---|
| 198 | l.lwz r12,GPR_BUF_OFFSET(12)(r1) |
---|
| 199 | l.lwz r13,GPR_BUF_OFFSET(13)(r1) |
---|
| 200 | l.lwz r14,GPR_BUF_OFFSET(14)(r1) |
---|
| 201 | l.lwz r15,GPR_BUF_OFFSET(15)(r1) |
---|
| 202 | l.lwz r16,GPR_BUF_OFFSET(16)(r1) |
---|
| 203 | l.lwz r17,GPR_BUF_OFFSET(17)(r1) |
---|
| 204 | l.lwz r18,GPR_BUF_OFFSET(18)(r1) |
---|
| 205 | l.lwz r19,GPR_BUF_OFFSET(19)(r1) |
---|
| 206 | l.lwz r20,GPR_BUF_OFFSET(20)(r1) |
---|
| 207 | l.lwz r21,GPR_BUF_OFFSET(21)(r1) |
---|
| 208 | l.lwz r22,GPR_BUF_OFFSET(22)(r1) |
---|
| 209 | l.lwz r23,GPR_BUF_OFFSET(23)(r1) |
---|
| 210 | l.lwz r24,GPR_BUF_OFFSET(24)(r1) |
---|
| 211 | l.lwz r25,GPR_BUF_OFFSET(25)(r1) |
---|
| 212 | l.lwz r26,GPR_BUF_OFFSET(26)(r1) |
---|
| 213 | l.lwz r27,GPR_BUF_OFFSET(27)(r1) |
---|
| 214 | l.lwz r28,GPR_BUF_OFFSET(28)(r1) |
---|
| 215 | l.lwz r29,GPR_BUF_OFFSET(29)(r1) |
---|
| 216 | l.lwz r30,GPR_BUF_OFFSET(30)(r1) |
---|
| 217 | l.lwz r31,GPR_BUF_OFFSET(31)(r1) |
---|
| 218 | |
---|
| 219 | // Restore original stack |
---|
| 220 | l.lwz r1,GPR_BUF_OFFSET(1)(r1) |
---|
| 221 | |
---|
| 222 | l.rfe |
---|
| 223 | l.nop |
---|
| 224 | |
---|
| 225 | exception_exit: |
---|
| 226 | /* Exception handler not set, exit */ |
---|
| 227 | OR1K_DELAYED( |
---|
| 228 | OR1K_INST(l.or r3,r4,r4), |
---|
| 229 | OR1K_INST(l.jal exit) |
---|
| 230 | ) |
---|