diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2011-08-09 11:11:30 +0000 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2011-08-09 11:11:30 +0000 |
commit | 3ee5a2e29b8e96239256130447374eef55d74970 (patch) | |
tree | 5117bde76246c4ed74cde6e324c6325d05bdf27c /cpukit/score/cpu/nios2 | |
parent | 2011-08-09 Sebastian Huber <sebastian.huber@embedded-brains.de> (diff) | |
download | rtems-3ee5a2e29b8e96239256130447374eef55d74970.tar.bz2 |
2011-08-09 Sebastian Huber <sebastian.huber@embedded-brains.de>
* nios2-iic-low-level.S: New file.
* cpu_asm.S: Moved low-level interrupt handling into new file.
* Makefile.am: Reflect change from above.
Diffstat (limited to 'cpukit/score/cpu/nios2')
-rw-r--r-- | cpukit/score/cpu/nios2/ChangeLog | 6 | ||||
-rw-r--r-- | cpukit/score/cpu/nios2/Makefile.am | 5 | ||||
-rw-r--r-- | cpukit/score/cpu/nios2/cpu_asm.S | 299 | ||||
-rw-r--r-- | cpukit/score/cpu/nios2/nios2-iic-low-level.S | 321 |
4 files changed, 331 insertions, 300 deletions
diff --git a/cpukit/score/cpu/nios2/ChangeLog b/cpukit/score/cpu/nios2/ChangeLog index 158de7ebe2..61d1bb4b92 100644 --- a/cpukit/score/cpu/nios2/ChangeLog +++ b/cpukit/score/cpu/nios2/ChangeLog @@ -1,5 +1,11 @@ 2011-08-09 Sebastian Huber <sebastian.huber@embedded-brains.de> + * nios2-iic-low-level.S: New file. + * cpu_asm.S: Moved low-level interrupt handling into new file. + * Makefile.am: Reflect change from above. + +2011-08-09 Sebastian Huber <sebastian.huber@embedded-brains.de> + * cpu_asm.S, rtems/score/cpu.h: There is no need to save the global pointer (gp) in the thread register context since it is a system wide constant and set-up with the C runtime environment. diff --git a/cpukit/score/cpu/nios2/Makefile.am b/cpukit/score/cpu/nios2/Makefile.am index 2004daa2f3..2921813434 100644 --- a/cpukit/score/cpu/nios2/Makefile.am +++ b/cpukit/score/cpu/nios2/Makefile.am @@ -17,7 +17,10 @@ include_rtems_score_HEADERS += rtems/score/cpu_asm.h include_rtems_score_HEADERS += rtems/score/types.h noinst_LIBRARIES = libscorecpu.a -libscorecpu_a_SOURCES = cpu.c irq.c cpu_asm.S +libscorecpu_a_SOURCES = cpu.c \ + irq.c \ + nios2-iic-low-level.S \ + cpu_asm.S libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS) all-local: $(PREINSTALL_FILES) diff --git a/cpukit/score/cpu/nios2/cpu_asm.S b/cpukit/score/cpu/nios2/cpu_asm.S index c0f6a082f1..985e8b3e90 100644 --- a/cpukit/score/cpu/nios2/cpu_asm.S +++ b/cpukit/score/cpu/nios2/cpu_asm.S @@ -83,302 +83,3 @@ _CPU_Context_restore: /* Copy first to second arg, then re-use 2nd half of Context_switch */ mov r5, r4 br _CPU_Context_switch_restore - - -/* ===================================================================== */ - - .globl _exception_vector - -_exception_vector: - - /* - * First, re-wind so we're pointed to the instruction where the exception - * occurred. - */ - - addi ea, ea, -4 - - /* - * Now test to determine the cause of the exception. - */ - - /* TODO: Look at [ea] if there was an unknown/trap instruction */ - - /* If interrupts are globally disabled, it certainly was no interrupt */ - rdctl et, estatus - andi et, et, 1 - beq et, zero, _Exception_Handler - - /* If no interrupts are pending, it was a software exception */ - rdctl et, ipending - beq et, zero, _Exception_Handler - - /* - * Falling through to here means that this was a hardware interrupt. - */ - - br _ISR_Handler - -/* ===================================================================== - * Exception handler: - * Responsible for unimplemented instructions and other software - * exceptions. Not responsible for hardware interrupts. Currently, - * software exceptions are regarded as error conditions, and the - * handling isn't perfect. */ - -_Exception_Handler: - - /* stw et, 108(sp') => stw et, -20(sp) */ - stw et, -20(sp) - mov et, sp - addi sp, sp, -128 - - stw r1, 0(sp) - stw r2, 4(sp) - stw r3, 8(sp) - - rdctl r1, estatus - rdctl r2, ienable - rdctl r3, ipending - - stw r4, 12(sp) - stw r5, 16(sp) - stw r6, 20(sp) - stw r7, 24(sp) - stw r8, 28(sp) - stw r9, 32(sp) - stw r10, 36(sp) - stw r11, 40(sp) - stw r12, 44(sp) - stw r13, 48(sp) - stw r14, 52(sp) - stw r15, 56(sp) - stw r16, 60(sp) - stw r17, 64(sp) - stw r18, 68(sp) - stw r19, 72(sp) - stw r20, 76(sp) - stw r21, 80(sp) - stw r22, 84(sp) - stw r23, 88(sp) - stw gp, 92(sp) - stw fp, 96(sp) - /* sp */ - stw et, 100(sp) - stw ra, 104(sp) - /* stw et, 108(sp) */ - stw ea, 112(sp) - - /* status */ - stw r1, 116(sp) - /* ienable */ - stw r2, 120(sp) - /* ipending */ - stw r3, 124(sp) - - /* - * Restore the global pointer. - */ - - movhi gp, %hiadj(_gp) - addi gp, gp, %lo(_gp) - - /* - * Pass a pointer to the stack frame as the input argument of the - * exception handler (CPU_Exception_frame *). - */ - - mov r4, sp - - /* - * Call the exception handler. - */ - - .extern __Exception_Handler - call __Exception_Handler - -stuck_in_exception: - br stuck_in_exception - - /* - * Restore the saved registers, so that all general purpose registers - * have been restored to their state at the time the interrupt occured. - */ - - ldw r1, 0(sp) - ldw r2, 4(sp) - ldw r3, 8(sp) - ldw r4, 12(sp) - ldw r5, 16(sp) - ldw r6, 20(sp) - ldw r7, 24(sp) - ldw r8, 28(sp) - ldw r9, 32(sp) - ldw r10, 36(sp) - ldw r11, 40(sp) - ldw r12, 44(sp) - ldw r13, 48(sp) - ldw r14, 52(sp) - ldw r15, 56(sp) - ldw r16, 60(sp) - ldw r17, 64(sp) - ldw r18, 68(sp) - ldw r19, 72(sp) - ldw r20, 76(sp) - ldw r21, 80(sp) - ldw r22, 84(sp) - ldw r23, 88(sp) - ldw gp, 92(sp) - ldw fp, 96(sp) - ldw ra, 104(sp) - - /* Disable interrupts */ - wrctl status, r0 - - ldw ea, 112(sp) - ldw et, 116(sp) - - /* FIXME: Enable interrupts after exception processing */ - ori et, et, 1 - wrctl estatus, et - ldw et, 108(sp) - - /* Restore stack pointer */ - ldw sp, 100(sp) - - eret - -/* ===================================================================== */ - - .section .text - -_ISR_Handler: - - /* - * Process an external hardware interrupt. - * - * First, preserve all callee saved registers on - * the stack. (See the Nios2 ABI documentation for details). - * - * Do we really need to save all? - * - * If this is interrupting a task (and not another interrupt), - * everything is saved into the task's stack, thus putting us - * in a situation similar to when the task calls a subroutine - * (and only the CPU_Context_Control subset needs to be changed) - */ - - rdctl et, estatus - - /* Keep this in the same order as CPU_Interrupt_frame: */ - - addi sp, sp, -76 - stw r1, 0(sp) - stw r2, 4(sp) - stw r3, 8(sp) - stw r4, 12(sp) - stw r5, 16(sp) - stw r6, 20(sp) - stw r7, 24(sp) - stw r8, 28(sp) - stw r9, 32(sp) - stw r10, 36(sp) - stw r11, 40(sp) - stw r12, 44(sp) - stw r13, 48(sp) - stw r14, 52(sp) - stw r15, 56(sp) - stw ra, 60(sp) - stw gp, 64(sp) - /* et contains status */ - stw et, 68(sp) - stw ea, 72(sp) - - /* - * Obtain a bitlist of the pending interrupts. - */ - - rdctl et, ipending - - /* - * Restore the global pointer to the expected value. - */ - - movhi gp, %hiadj(_gp) - addi gp, gp, %lo(_gp) - - /* - * Search through the bit list stored in r24(et) to find the first enabled - * bit. The offset of this bit is the index of the interrupt that is - * to be handled. - */ - - mov r4, zero -6: - andi r3, r24, 1 - bne r3, zero, 7f - addi r4, r4, 1 - srli r24, r24, 1 - br 6b -7: - - /* - * Having located the interrupt source, r4 contains the index of the - * interrupt to be handled. r5, the 2nd argument to the function, - * will point to the CPU_Interrupt_frame. - */ - - mov r5, sp - - .extern __ISR_Handler - call __ISR_Handler - - /* - * Now that the interrupt processing is complete, prepare to return to - * the interrupted code. - */ - - /* - * Restore the saved registers, so that all general purpose registers - * have been restored to their state at the time the interrupt occured. - */ - - ldw r1, 0(sp) - ldw r2, 4(sp) - ldw r3, 8(sp) - ldw r4, 12(sp) - ldw r5, 16(sp) - ldw r6, 20(sp) - ldw r7, 24(sp) - ldw r8, 28(sp) - ldw r9, 32(sp) - ldw r10, 36(sp) - ldw r11, 40(sp) - ldw r12, 44(sp) - ldw r13, 48(sp) - ldw r14, 52(sp) - ldw r15, 56(sp) - ldw ra, 60(sp) - ldw gp, 64(sp) - - /* Disable interrupts */ - wrctl status, r0 - - /* Restore the exception registers */ - - /* load saved ea into ea */ - ldw ea, 72(sp) - /* load saved estatus into et */ - ldw et, 68(sp) - /* Always have interrupts enabled when we return from interrupt */ - ori et, et, 1 - wrctl estatus, et - /* Restore the stack pointer */ - addi sp, sp, 76 - - /* - * Return to the interrupted instruction. - */ - eret - - diff --git a/cpukit/score/cpu/nios2/nios2-iic-low-level.S b/cpukit/score/cpu/nios2/nios2-iic-low-level.S new file mode 100644 index 0000000000..7a5d24ca59 --- /dev/null +++ b/cpukit/score/cpu/nios2/nios2-iic-low-level.S @@ -0,0 +1,321 @@ +/* + * $Id$ + * + * This file contains all assembly code for the + * NIOS2 implementation of RTEMS. + * + * Copyright (c) 2006 Kolja Waschk (rtemsdev/ixo.de) + * + * Derived from no_cpu/cpu_asm.S, copyright (c) 1989-1999, + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/asm.h> +#include <rtems/score/cpu_asm.h> + + .set noat + + .globl _exception_vector + +_exception_vector: + + /* + * First, re-wind so we're pointed to the instruction where the exception + * occurred. + */ + + addi ea, ea, -4 + + /* + * Now test to determine the cause of the exception. + */ + + /* TODO: Look at [ea] if there was an unknown/trap instruction */ + + /* If interrupts are globally disabled, it certainly was no interrupt */ + rdctl et, estatus + andi et, et, 1 + beq et, zero, _Exception_Handler + + /* If no interrupts are pending, it was a software exception */ + rdctl et, ipending + beq et, zero, _Exception_Handler + + /* + * Falling through to here means that this was a hardware interrupt. + */ + + br _ISR_Handler + +/* ===================================================================== + * Exception handler: + * Responsible for unimplemented instructions and other software + * exceptions. Not responsible for hardware interrupts. Currently, + * software exceptions are regarded as error conditions, and the + * handling isn't perfect. */ + +_Exception_Handler: + + /* stw et, 108(sp') => stw et, -20(sp) */ + stw et, -20(sp) + mov et, sp + addi sp, sp, -128 + + stw r1, 0(sp) + stw r2, 4(sp) + stw r3, 8(sp) + + rdctl r1, estatus + rdctl r2, ienable + rdctl r3, ipending + + stw r4, 12(sp) + stw r5, 16(sp) + stw r6, 20(sp) + stw r7, 24(sp) + stw r8, 28(sp) + stw r9, 32(sp) + stw r10, 36(sp) + stw r11, 40(sp) + stw r12, 44(sp) + stw r13, 48(sp) + stw r14, 52(sp) + stw r15, 56(sp) + stw r16, 60(sp) + stw r17, 64(sp) + stw r18, 68(sp) + stw r19, 72(sp) + stw r20, 76(sp) + stw r21, 80(sp) + stw r22, 84(sp) + stw r23, 88(sp) + stw gp, 92(sp) + stw fp, 96(sp) + /* sp */ + stw et, 100(sp) + stw ra, 104(sp) + /* stw et, 108(sp) */ + stw ea, 112(sp) + + /* status */ + stw r1, 116(sp) + /* ienable */ + stw r2, 120(sp) + /* ipending */ + stw r3, 124(sp) + + /* + * Restore the global pointer. + */ + + movhi gp, %hiadj(_gp) + addi gp, gp, %lo(_gp) + + /* + * Pass a pointer to the stack frame as the input argument of the + * exception handler (CPU_Exception_frame *). + */ + + mov r4, sp + + /* + * Call the exception handler. + */ + + .extern __Exception_Handler + call __Exception_Handler + +stuck_in_exception: + br stuck_in_exception + + /* + * Restore the saved registers, so that all general purpose registers + * have been restored to their state at the time the interrupt occured. + */ + + ldw r1, 0(sp) + ldw r2, 4(sp) + ldw r3, 8(sp) + ldw r4, 12(sp) + ldw r5, 16(sp) + ldw r6, 20(sp) + ldw r7, 24(sp) + ldw r8, 28(sp) + ldw r9, 32(sp) + ldw r10, 36(sp) + ldw r11, 40(sp) + ldw r12, 44(sp) + ldw r13, 48(sp) + ldw r14, 52(sp) + ldw r15, 56(sp) + ldw r16, 60(sp) + ldw r17, 64(sp) + ldw r18, 68(sp) + ldw r19, 72(sp) + ldw r20, 76(sp) + ldw r21, 80(sp) + ldw r22, 84(sp) + ldw r23, 88(sp) + ldw gp, 92(sp) + ldw fp, 96(sp) + ldw ra, 104(sp) + + /* Disable interrupts */ + wrctl status, r0 + + ldw ea, 112(sp) + ldw et, 116(sp) + + /* FIXME: Enable interrupts after exception processing */ + ori et, et, 1 + wrctl estatus, et + ldw et, 108(sp) + + /* Restore stack pointer */ + ldw sp, 100(sp) + + eret + +/* ===================================================================== */ + + .section .text + +_ISR_Handler: + + /* + * Process an external hardware interrupt. + * + * First, preserve all callee saved registers on + * the stack. (See the Nios2 ABI documentation for details). + * + * Do we really need to save all? + * + * If this is interrupting a task (and not another interrupt), + * everything is saved into the task's stack, thus putting us + * in a situation similar to when the task calls a subroutine + * (and only the CPU_Context_Control subset needs to be changed) + */ + + rdctl et, estatus + + /* Keep this in the same order as CPU_Interrupt_frame: */ + + addi sp, sp, -76 + stw r1, 0(sp) + stw r2, 4(sp) + stw r3, 8(sp) + stw r4, 12(sp) + stw r5, 16(sp) + stw r6, 20(sp) + stw r7, 24(sp) + stw r8, 28(sp) + stw r9, 32(sp) + stw r10, 36(sp) + stw r11, 40(sp) + stw r12, 44(sp) + stw r13, 48(sp) + stw r14, 52(sp) + stw r15, 56(sp) + stw ra, 60(sp) + stw gp, 64(sp) + /* et contains status */ + stw et, 68(sp) + stw ea, 72(sp) + + /* + * Obtain a bitlist of the pending interrupts. + */ + + rdctl et, ipending + + /* + * Restore the global pointer to the expected value. + */ + + movhi gp, %hiadj(_gp) + addi gp, gp, %lo(_gp) + + /* + * Search through the bit list stored in r24(et) to find the first enabled + * bit. The offset of this bit is the index of the interrupt that is + * to be handled. + */ + + mov r4, zero +6: + andi r3, r24, 1 + bne r3, zero, 7f + addi r4, r4, 1 + srli r24, r24, 1 + br 6b +7: + + /* + * Having located the interrupt source, r4 contains the index of the + * interrupt to be handled. r5, the 2nd argument to the function, + * will point to the CPU_Interrupt_frame. + */ + + mov r5, sp + + .extern __ISR_Handler + call __ISR_Handler + + /* + * Now that the interrupt processing is complete, prepare to return to + * the interrupted code. + */ + + /* + * Restore the saved registers, so that all general purpose registers + * have been restored to their state at the time the interrupt occured. + */ + + ldw r1, 0(sp) + ldw r2, 4(sp) + ldw r3, 8(sp) + ldw r4, 12(sp) + ldw r5, 16(sp) + ldw r6, 20(sp) + ldw r7, 24(sp) + ldw r8, 28(sp) + ldw r9, 32(sp) + ldw r10, 36(sp) + ldw r11, 40(sp) + ldw r12, 44(sp) + ldw r13, 48(sp) + ldw r14, 52(sp) + ldw r15, 56(sp) + ldw ra, 60(sp) + ldw gp, 64(sp) + + /* Disable interrupts */ + wrctl status, r0 + + /* Restore the exception registers */ + + /* load saved ea into ea */ + ldw ea, 72(sp) + /* load saved estatus into et */ + ldw et, 68(sp) + /* Always have interrupts enabled when we return from interrupt */ + ori et, et, 1 + wrctl estatus, et + /* Restore the stack pointer */ + addi sp, sp, 76 + + /* + * Return to the interrupted instruction. + */ + eret + + |