![]() |
|
|||
File indexing completed on 2025-05-11 08:24:25
0001 /* SPDX-License-Identifier: BSD-2-Clause */ 0002 0003 /* 0004 * This file contains all assembly code for the 0005 * NIOS2 implementation of RTEMS. 0006 * 0007 * Copyright (c) 2006 Kolja Waschk (rtemsdev/ixo.de) 0008 * 0009 * Derived from no_cpu/cpu_asm.S, copyright (c) 1989-1999, 0010 * On-Line Applications Research Corporation (OAR). 0011 * 0012 * Redistribution and use in source and binary forms, with or without 0013 * modification, are permitted provided that the following conditions 0014 * are met: 0015 * 1. Redistributions of source code must retain the above copyright 0016 * notice, this list of conditions and the following disclaimer. 0017 * 2. Redistributions in binary form must reproduce the above copyright 0018 * notice, this list of conditions and the following disclaimer in the 0019 * documentation and/or other materials provided with the distribution. 0020 * 0021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 0022 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 0023 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 0024 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 0025 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 0026 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 0027 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 0028 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 0029 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 0030 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 0031 * POSSIBILITY OF SUCH DAMAGE. 0032 * 0033 */ 0034 0035 #ifdef HAVE_CONFIG_H 0036 #include "config.h" 0037 #endif 0038 0039 #include <rtems/asm.h> 0040 #include <rtems/score/cpu_asm.h> 0041 0042 .set noat 0043 0044 .globl _exception_vector 0045 0046 _exception_vector: 0047 0048 /* 0049 * First, re-wind so we're pointed to the instruction where the exception 0050 * occurred. 0051 */ 0052 0053 addi ea, ea, -4 0054 0055 /* 0056 * Now test to determine the cause of the exception. 0057 */ 0058 0059 /* TODO: Look at [ea] if there was an unknown/trap instruction */ 0060 0061 /* If interrupts are globally disabled, it certainly was no interrupt */ 0062 rdctl et, estatus 0063 andi et, et, 1 0064 beq et, zero, _Exception_Handler 0065 0066 /* If no interrupts are pending, it was a software exception */ 0067 rdctl et, ipending 0068 beq et, zero, _Exception_Handler 0069 0070 /* 0071 * Falling through to here means that this was a hardware interrupt. 0072 */ 0073 0074 br _ISR_Handler 0075 0076 /* ===================================================================== 0077 * Exception handler: 0078 * Responsible for unimplemented instructions and other software 0079 * exceptions. Not responsible for hardware interrupts. Currently, 0080 * software exceptions are regarded as error conditions, and the 0081 * handling isn't perfect. */ 0082 0083 _Exception_Handler: 0084 0085 /* stw et, 108(sp') => stw et, -20(sp) */ 0086 stw et, -20(sp) 0087 mov et, sp 0088 addi sp, sp, -128 0089 0090 stw r1, 0(sp) 0091 stw r2, 4(sp) 0092 stw r3, 8(sp) 0093 0094 rdctl r1, estatus 0095 rdctl r2, ienable 0096 rdctl r3, ipending 0097 0098 stw r4, 12(sp) 0099 stw r5, 16(sp) 0100 stw r6, 20(sp) 0101 stw r7, 24(sp) 0102 stw r8, 28(sp) 0103 stw r9, 32(sp) 0104 stw r10, 36(sp) 0105 stw r11, 40(sp) 0106 stw r12, 44(sp) 0107 stw r13, 48(sp) 0108 stw r14, 52(sp) 0109 stw r15, 56(sp) 0110 stw r16, 60(sp) 0111 stw r17, 64(sp) 0112 stw r18, 68(sp) 0113 stw r19, 72(sp) 0114 stw r20, 76(sp) 0115 stw r21, 80(sp) 0116 stw r22, 84(sp) 0117 stw r23, 88(sp) 0118 stw gp, 92(sp) 0119 stw fp, 96(sp) 0120 /* sp */ 0121 stw et, 100(sp) 0122 stw ra, 104(sp) 0123 /* stw et, 108(sp) */ 0124 stw ea, 112(sp) 0125 0126 /* status */ 0127 stw r1, 116(sp) 0128 /* ienable */ 0129 stw r2, 120(sp) 0130 /* ipending */ 0131 stw r3, 124(sp) 0132 0133 /* 0134 * Restore the global pointer. 0135 */ 0136 0137 movhi gp, %hiadj(_gp) 0138 addi gp, gp, %lo(_gp) 0139 0140 /* 0141 * Pass a pointer to the stack frame as the input argument of the 0142 * exception handler (CPU_Exception_frame *). 0143 */ 0144 0145 mov r4, sp 0146 0147 /* 0148 * Call the exception handler. 0149 */ 0150 0151 .extern __Exception_Handler 0152 call __Exception_Handler 0153 0154 stuck_in_exception: 0155 br stuck_in_exception 0156 0157 /* 0158 * Restore the saved registers, so that all general purpose registers 0159 * have been restored to their state at the time the interrupt occurred. 0160 */ 0161 0162 ldw r1, 0(sp) 0163 ldw r2, 4(sp) 0164 ldw r3, 8(sp) 0165 ldw r4, 12(sp) 0166 ldw r5, 16(sp) 0167 ldw r6, 20(sp) 0168 ldw r7, 24(sp) 0169 ldw r8, 28(sp) 0170 ldw r9, 32(sp) 0171 ldw r10, 36(sp) 0172 ldw r11, 40(sp) 0173 ldw r12, 44(sp) 0174 ldw r13, 48(sp) 0175 ldw r14, 52(sp) 0176 ldw r15, 56(sp) 0177 ldw r16, 60(sp) 0178 ldw r17, 64(sp) 0179 ldw r18, 68(sp) 0180 ldw r19, 72(sp) 0181 ldw r20, 76(sp) 0182 ldw r21, 80(sp) 0183 ldw r22, 84(sp) 0184 ldw r23, 88(sp) 0185 ldw gp, 92(sp) 0186 ldw fp, 96(sp) 0187 ldw ra, 104(sp) 0188 0189 /* Disable interrupts */ 0190 wrctl status, r0 0191 0192 ldw ea, 112(sp) 0193 ldw et, 116(sp) 0194 0195 /* FIXME: Enable interrupts after exception processing */ 0196 ori et, et, 1 0197 wrctl estatus, et 0198 ldw et, 108(sp) 0199 0200 /* Restore stack pointer */ 0201 ldw sp, 100(sp) 0202 0203 eret 0204 0205 /* ===================================================================== */ 0206 0207 .section .text 0208 0209 _ISR_Handler: 0210 0211 /* 0212 * Process an external hardware interrupt. 0213 * 0214 * First, preserve all callee saved registers on 0215 * the stack. (See the Nios2 ABI documentation for details). 0216 * 0217 * Do we really need to save all? 0218 * 0219 * If this is interrupting a task (and not another interrupt), 0220 * everything is saved into the task's stack, thus putting us 0221 * in a situation similar to when the task calls a subroutine 0222 * (and only the CPU_Context_Control subset needs to be changed) 0223 */ 0224 0225 rdctl et, estatus 0226 0227 /* Keep this in the same order as CPU_Interrupt_frame: */ 0228 0229 addi sp, sp, -76 0230 stw r1, 0(sp) 0231 stw r2, 4(sp) 0232 stw r3, 8(sp) 0233 stw r4, 12(sp) 0234 stw r5, 16(sp) 0235 stw r6, 20(sp) 0236 stw r7, 24(sp) 0237 stw r8, 28(sp) 0238 stw r9, 32(sp) 0239 stw r10, 36(sp) 0240 stw r11, 40(sp) 0241 stw r12, 44(sp) 0242 stw r13, 48(sp) 0243 stw r14, 52(sp) 0244 stw r15, 56(sp) 0245 stw ra, 60(sp) 0246 stw gp, 64(sp) 0247 /* et contains status */ 0248 stw et, 68(sp) 0249 stw ea, 72(sp) 0250 0251 #if REMOVED_BY_CCJ 0252 /* 0253 * Obtain a bitlist of the pending interrupts. 0254 */ 0255 0256 rdctl et, ipending 0257 0258 /* 0259 * Restore the global pointer to the expected value. 0260 */ 0261 0262 movhi gp, %hiadj(_gp) 0263 addi gp, gp, %lo(_gp) 0264 0265 /* 0266 * Search through the bit list stored in r24(et) to find the first enabled 0267 * bit. The offset of this bit is the index of the interrupt that is 0268 * to be handled. 0269 */ 0270 0271 mov r4, zero 0272 6: 0273 andi r3, r24, 1 0274 bne r3, zero, 7f 0275 addi r4, r4, 1 0276 srli r24, r24, 1 0277 br 6b 0278 7: 0279 0280 /* 0281 * Having located the interrupt source, r4 contains the index of the 0282 * interrupt to be handled. r5, the 2nd argument to the function, 0283 * will point to the CPU_Interrupt_frame. 0284 */ 0285 0286 mov r5, sp 0287 #endif 0288 0289 .extern __ISR_Handler 0290 call __ISR_Handler 0291 0292 /* 0293 * Now that the interrupt processing is complete, prepare to return to 0294 * the interrupted code. 0295 */ 0296 0297 /* 0298 * Restore the saved registers, so that all general purpose registers 0299 * have been restored to their state at the time the interrupt occurred. 0300 */ 0301 0302 ldw r1, 0(sp) 0303 ldw r2, 4(sp) 0304 ldw r3, 8(sp) 0305 ldw r4, 12(sp) 0306 ldw r5, 16(sp) 0307 ldw r6, 20(sp) 0308 ldw r7, 24(sp) 0309 ldw r8, 28(sp) 0310 ldw r9, 32(sp) 0311 ldw r10, 36(sp) 0312 ldw r11, 40(sp) 0313 ldw r12, 44(sp) 0314 ldw r13, 48(sp) 0315 ldw r14, 52(sp) 0316 ldw r15, 56(sp) 0317 ldw ra, 60(sp) 0318 ldw gp, 64(sp) 0319 0320 /* Disable interrupts */ 0321 wrctl status, r0 0322 0323 /* Restore the exception registers */ 0324 0325 /* load saved ea into ea */ 0326 ldw ea, 72(sp) 0327 /* load saved estatus into et */ 0328 ldw et, 68(sp) 0329 /* Always have interrupts enabled when we return from interrupt */ 0330 ori et, et, 1 0331 wrctl estatus, et 0332 /* Restore the stack pointer */ 0333 addi sp, sp, 76 0334 0335 /* 0336 * Return to the interrupted instruction. 0337 */ 0338 eret 0339 0340
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |