source: rtems/cpukit/score/cpu/nios2/nios2-eic-il-low-level.S

Last change on this file was bcef89f2, checked in by Sebastian Huber <sebastian.huber@…>, on 05/19/23 at 06:18:25

Update company name

The embedded brains GmbH & Co. KG is the legal successor of embedded
brains GmbH.

  • Property mode set to 100644
File size: 7.4 KB
RevLine 
[4b5e64a]1/* SPDX-License-Identifier: BSD-2-Clause */
2
[9f1412b9]3/*
[bcef89f2]4 * Copyright (C) 2011, 2015 embedded brains GmbH & Co. KG
[9f1412b9]5 *
[4b5e64a]6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
[9f1412b9]26 */
27
28#include <rtems/score/percpu.h>
29#include <rtems/score/nios2-utility.h>
30
31#define FRAME_OFFSET_RA 0
32#define FRAME_OFFSET_AT 4
33#define FRAME_OFFSET_R2 8
34#define FRAME_OFFSET_R3 12
35#define FRAME_OFFSET_R4 16
36#define FRAME_OFFSET_R5 20
37#define FRAME_OFFSET_R6 24
38#define FRAME_OFFSET_R7 28
39#define FRAME_OFFSET_R8 32
40#define FRAME_OFFSET_R9 36
41#define FRAME_OFFSET_R10 40
42#define FRAME_OFFSET_R11 44
43#define FRAME_OFFSET_R12 48
44#define FRAME_OFFSET_R13 52
45#define FRAME_OFFSET_R14 56
46#define FRAME_OFFSET_R15 60
47#define FRAME_OFFSET_STATUS 64
48#define FRAME_OFFSET_EA  68
49
50#define FRAME_SIZE (FRAME_OFFSET_EA + 4)
51
52        .set    noat
[99a1f122]53        .set    nobreak
[9f1412b9]54        .section        .text
55
56        .extern _Per_CPU_Information
57        .extern _Nios2_ISR_Status_interrupts_disabled
58
[51e59d5]59        .globl  _Nios2_ISR_Dispatch_with_shadow_register_set
[9f1412b9]60
[51e59d5]61_Nios2_ISR_Dispatch_with_shadow_register_set:
[9f1412b9]62
63        /* Load thread dispatch disable level */
[98c95d1]64        ldw     r16, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
[9f1412b9]65
[51e59d5]66        /* Read status */
67        rdctl   r18, status
68
[9f1412b9]69        /* Load high level handler address and argument */
70        ldw     r8, 4(et)
71        ldw     r4, 8(et)
72
73        /* Increment and store thread dispatch disable level */
[19acb3b]74        addi    r17, r16, 1
75        stw     r17, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
[9f1412b9]76
[51e59d5]77        /*
78         * Enable higher level interrupts.  This is safe since status.RSIE is
79         * always 0 and thread dispatching is disabled right above.  Higher
80         * priority interrupts shall not share shadow register sets with lower
81         * priority interrupts.
82         */
83        ori     r5, r18, 1
84        wrctl   status, r5
85
[9f1412b9]86        /* Call high level handler with argument */
87        callr   r8
88
[19acb3b]89        /* Load the thread dispatch necessary indicator */
[9f1412b9]90        ldb     r12, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
91
[19acb3b]92        /* Load the thread dispatch after ISR disable indicator */
[9165349d]93        ldw     r13, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
[9f1412b9]94
95        /* Fix return address */
96        subi    ea, ea, 4
97
98        /*
[19acb3b]99         * If the current thread dispatch disable level (r17) is one, then
100         * negate the thread dispatch necessary indicator, otherwise the value
101         * is irrelevant.  Or it with the previous thread dispatch disable
102         * level value (r16).  The r15 which will be used as a status to
103         * determine if a thread dispatch is necessary and allowed.
[9f1412b9]104         */
[19acb3b]105        xor     r12, r17, r12
106        or      r15, r12, r16
[9f1412b9]107
[19acb3b]108        /*
[51e59d5]109         * Get the previous register set from r18.  If it is zero, then this is
[19acb3b]110         * the outermost interrupt.  Or it to the thread dispatch status (r15).
111         */
[51e59d5]112        andhi   r12, r18, 0x3f
[19acb3b]113        or      r15, r12, r15
[9f1412b9]114
[19acb3b]115        /*
116         * Or the thread dispatch after ISR disable indicator (r13) to the
117         * thread dispatch status (r15).
118         */
119        or      r15, r13, r15
[9f1412b9]120
[19acb3b]121        /* Is a thread dispatch necessary and allowed? */
122        bne     r15, zero, no_thread_dispatch
[9f1412b9]123
124        /* Obtain stack frame in normal register set */
125        rdprs   r15, sp, -FRAME_SIZE
126
[9165349d]127        /* Disable thread dispatch after ISR */
[19acb3b]128        stw     r17, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
[9f1412b9]129
130        /* Save context */
131        stw     sstatus, FRAME_OFFSET_STATUS(r15)
132        stw     ea, FRAME_OFFSET_EA(r15)
133
134        /* Set thread dispatch helper address */
135        movhi   ea, %hiadj(thread_dispatch_helper)
136        addi    ea, ea, %lo(thread_dispatch_helper)
137
138        /* Update stack pointer in normal register set */
139        wrprs   sp, r15
140
[19acb3b]141        /* Jump to thread dispatch helper */
142        eret
143
[9f1412b9]144no_thread_dispatch:
145
[19acb3b]146        /* Restore the thread dispatch disable level */
147        stw     r16, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
148
149        /* Return to interrupted context */
[9f1412b9]150        eret
151
152thread_dispatch_helper:
153
154        /* This code executes in the context of the interrupted thread */
155
156        /* Save volatile registers */
157        stw     ra, FRAME_OFFSET_RA(sp)
158        stw     at, FRAME_OFFSET_AT(sp)
159        stw     r2, FRAME_OFFSET_R2(sp)
160        stw     r3, FRAME_OFFSET_R3(sp)
161        stw     r4, FRAME_OFFSET_R4(sp)
162        stw     r5, FRAME_OFFSET_R5(sp)
163        stw     r6, FRAME_OFFSET_R6(sp)
164        stw     r7, FRAME_OFFSET_R7(sp)
165        stw     r8, FRAME_OFFSET_R8(sp)
166        stw     r9, FRAME_OFFSET_R9(sp)
167        stw     r10, FRAME_OFFSET_R10(sp)
168        stw     r11, FRAME_OFFSET_R11(sp)
169        stw     r12, FRAME_OFFSET_R12(sp)
170        stw     r13, FRAME_OFFSET_R13(sp)
171        stw     r14, FRAME_OFFSET_R14(sp)
172        stw     r15, FRAME_OFFSET_R15(sp)
173
[19acb3b]174        /*
175         * Disable interrupts (1).
176         *
177         * We have the following invariants:
178         *   1. status.RSIE == 0: thread context initialization
179         *   2. status.CRS == 0: thread context initialization
180         *   3. status.PRS: arbitrary
181         *   4. status.IL < interrupt disable IL: else we would not be here
182         *   5. status.IH == 0: thread context initialization
183         *   6. status.U == 0: thread context initialization
184         *   7. status.PIE == 1: thread context initialization
185         * Thus we can use a constant to disable interrupts.
186         */
187        movi    r5, %lo(_Nios2_ISR_Status_interrupts_disabled)
188        wrctl   status, r5
189
[9f1412b9]190do_thread_dispatch:
191
[19acb3b]192        addi    r4, gp, %gprel(_Per_CPU_Information)
193        call    _Thread_Do_dispatch
[9f1412b9]194
195        /* Restore some volatile registers */
196        ldw     ra, FRAME_OFFSET_RA(sp)
197        ldw     at, FRAME_OFFSET_AT(sp)
198        ldw     r2, FRAME_OFFSET_R2(sp)
199        ldw     r3, FRAME_OFFSET_R3(sp)
200        ldw     r4, FRAME_OFFSET_R4(sp)
201        ldw     r5, FRAME_OFFSET_R5(sp)
202        ldw     r6, FRAME_OFFSET_R6(sp)
203        ldw     r7, FRAME_OFFSET_R7(sp)
204        ldw     r8, FRAME_OFFSET_R8(sp)
205        ldw     r9, FRAME_OFFSET_R9(sp)
206        ldw     r10, FRAME_OFFSET_R10(sp)
207        ldw     r11, FRAME_OFFSET_R11(sp)
208        ldw     r12, FRAME_OFFSET_R12(sp)
209
[19acb3b]210        /* Disable interrupts, see (1) */
[9f1412b9]211        rdctl   r14, status
212        movi    r15, %lo(_Nios2_ISR_Status_interrupts_disabled)
213        wrctl   status, r15
214
215        /* Load thread dispatch necessary */
[0cce75e]216        ldb     r13, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
[9f1412b9]217
218        /* Is thread dispatch necessary? */
[19acb3b]219        bne     r13, zero, prepare_thread_dispatch
[9f1412b9]220
[9165349d]221        /* Enable thread dispatch after ISR */
222        stw     zero, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
[9f1412b9]223
224        /* Restore remaining volatile register */
[0cce75e]225        ldw     r13, FRAME_OFFSET_R13(sp)
[9f1412b9]226        ldw     r14, FRAME_OFFSET_R14(sp)
227        ldw     r15, FRAME_OFFSET_R15(sp)
228
229        /* Restore context */
230        ldw     et, FRAME_OFFSET_STATUS(sp)
231        ldw     ea, FRAME_OFFSET_EA(sp)
232
233        /* Release stack frame */
234        addi    sp, sp, FRAME_SIZE
235
236        /* Restore context */
237        wrctl   estatus, et
238
239        /* Return to interrupted thread */
240        eret
241
[19acb3b]242prepare_thread_dispatch:
243
244        /* Disable thread dispatching */
245        movi    r4, 1
246        stw     r4, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
247        stw     r4, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
[9f1412b9]248
[19acb3b]249        /* Set interrupt level argument for _Thread_Do_dispatch() */
250        mov     r5, r15
[9f1412b9]251
252        br      do_thread_dispatch
Note: See TracBrowser for help on using the repository browser.