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

Last change on this file since 255fe43 was 255fe43, checked in by Joel Sherrill <joel@…>, on 03/01/22 at 20:40:44

cpukit/: Scripted embedded brains header file clean up

Updates #4625.

  • Property mode set to 100644
File size: 7.5 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/*
4 * Copyright (c) 2011-2015 embedded brains GmbH.  All rights reserved.
5 *
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.
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
53        .set    nobreak
54        .section        .text
55
56        .extern _Per_CPU_Information
57        .extern _Nios2_ISR_Status_interrupts_disabled
58
59        .globl  _Nios2_ISR_Dispatch_with_shadow_register_set
60
61_Nios2_ISR_Dispatch_with_shadow_register_set:
62
63        /* Load thread dispatch disable level */
64        ldw     r16, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
65
66        /* Read status */
67        rdctl   r18, status
68
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 */
74        addi    r17, r16, 1
75        stw     r17, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
76
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
86        /* Call high level handler with argument */
87        callr   r8
88
89        /* Load the thread dispatch necessary indicator */
90        ldb     r12, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
91
92        /* Load the thread dispatch after ISR disable indicator */
93        ldw     r13, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
94
95        /* Fix return address */
96        subi    ea, ea, 4
97
98        /*
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.
104         */
105        xor     r12, r17, r12
106        or      r15, r12, r16
107
108        /*
109         * Get the previous register set from r18.  If it is zero, then this is
110         * the outermost interrupt.  Or it to the thread dispatch status (r15).
111         */
112        andhi   r12, r18, 0x3f
113        or      r15, r12, r15
114
115        /*
116         * Or the thread dispatch after ISR disable indicator (r13) to the
117         * thread dispatch status (r15).
118         */
119        or      r15, r13, r15
120
121        /* Is a thread dispatch necessary and allowed? */
122        bne     r15, zero, no_thread_dispatch
123
124        /* Obtain stack frame in normal register set */
125        rdprs   r15, sp, -FRAME_SIZE
126
127        /* Disable thread dispatch after ISR */
128        stw     r17, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
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
141        /* Jump to thread dispatch helper */
142        eret
143
144no_thread_dispatch:
145
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 */
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
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
190do_thread_dispatch:
191
192        addi    r4, gp, %gprel(_Per_CPU_Information)
193        call    _Thread_Do_dispatch
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
210        /* Disable interrupts, see (1) */
211        rdctl   r14, status
212        movi    r15, %lo(_Nios2_ISR_Status_interrupts_disabled)
213        wrctl   status, r15
214
215        /* Load thread dispatch necessary */
216        ldb     r13, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
217
218        /* Is thread dispatch necessary? */
219        bne     r13, zero, prepare_thread_dispatch
220
221        /* Enable thread dispatch after ISR */
222        stw     zero, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
223
224        /* Restore remaining volatile register */
225        ldw     r13, FRAME_OFFSET_R13(sp)
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
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)
248
249        /* Set interrupt level argument for _Thread_Do_dispatch() */
250        mov     r5, r15
251
252        br      do_thread_dispatch
Note: See TracBrowser for help on using the repository browser.