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

Last change on this file since 19acb3b was 19acb3b, checked in by Sebastian Huber <sebastian.huber@…>, on Jan 12, 2021 at 9:31:27 AM

nios2: Optimize ISR dispatch variant

Use _Thread_Do_dispatch() in
_Nios2_ISR_Dispatch_with_shadow_non_preemptive().

  • Property mode set to 100644
File size: 6.1 KB
Line 
1/*
2 * Copyright (c) 2011-2015 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#include <rtems/score/percpu.h>
16#include <rtems/score/nios2-utility.h>
17
18#define FRAME_OFFSET_RA 0
19#define FRAME_OFFSET_AT 4
20#define FRAME_OFFSET_R2 8
21#define FRAME_OFFSET_R3 12
22#define FRAME_OFFSET_R4 16
23#define FRAME_OFFSET_R5 20
24#define FRAME_OFFSET_R6 24
25#define FRAME_OFFSET_R7 28
26#define FRAME_OFFSET_R8 32
27#define FRAME_OFFSET_R9 36
28#define FRAME_OFFSET_R10 40
29#define FRAME_OFFSET_R11 44
30#define FRAME_OFFSET_R12 48
31#define FRAME_OFFSET_R13 52
32#define FRAME_OFFSET_R14 56
33#define FRAME_OFFSET_R15 60
34#define FRAME_OFFSET_STATUS 64
35#define FRAME_OFFSET_EA  68
36
37#define FRAME_SIZE (FRAME_OFFSET_EA + 4)
38
39        .set    noat
40        .set    nobreak
41        .section        .text
42
43        .extern _Per_CPU_Information
44        .extern _Nios2_ISR_Status_interrupts_disabled
45
46        .globl  _Nios2_ISR_Dispatch_with_shadow_non_preemptive
47
48_Nios2_ISR_Dispatch_with_shadow_non_preemptive:
49
50        /* Load thread dispatch disable level */
51        ldw     r16, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
52
53        /* Load high level handler address and argument */
54        ldw     r8, 4(et)
55        ldw     r4, 8(et)
56
57        /* Increment and store thread dispatch disable level */
58        addi    r17, r16, 1
59        stw     r17, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
60
61        /* Call high level handler with argument */
62        callr   r8
63
64        /* Load the thread dispatch necessary indicator */
65        ldb     r12, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
66
67        /* Load the thread dispatch after ISR disable indicator */
68        ldw     r13, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
69
70        /* Read status */
71        rdctl   r14, status
72
73        /* Fix return address */
74        subi    ea, ea, 4
75
76        /*
77         * If the current thread dispatch disable level (r17) is one, then
78         * negate the thread dispatch necessary indicator, otherwise the value
79         * is irrelevant.  Or it with the previous thread dispatch disable
80         * level value (r16).  The r15 which will be used as a status to
81         * determine if a thread dispatch is necessary and allowed.
82         */
83        xor     r12, r17, r12
84        or      r15, r12, r16
85
86        /*
87         * Get the previous register set from r14.  If it is zero, then this is
88         * the outermost interrupt.  Or it to the thread dispatch status (r15).
89         */
90        andhi   r12, r14, 0x3f
91        or      r15, r12, r15
92
93        /*
94         * Or the thread dispatch after ISR disable indicator (r13) to the
95         * thread dispatch status (r15).
96         */
97        or      r15, r13, r15
98
99        /* Is a thread dispatch necessary and allowed? */
100        bne     r15, zero, no_thread_dispatch
101
102        /* Obtain stack frame in normal register set */
103        rdprs   r15, sp, -FRAME_SIZE
104
105        /* Disable thread dispatch after ISR */
106        stw     r17, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
107
108        /* Save context */
109        stw     sstatus, FRAME_OFFSET_STATUS(r15)
110        stw     ea, FRAME_OFFSET_EA(r15)
111
112        /* Set thread dispatch helper address */
113        movhi   ea, %hiadj(thread_dispatch_helper)
114        addi    ea, ea, %lo(thread_dispatch_helper)
115
116        /* Update stack pointer in normal register set */
117        wrprs   sp, r15
118
119        /* Jump to thread dispatch helper */
120        eret
121
122no_thread_dispatch:
123
124        /* Restore the thread dispatch disable level */
125        stw     r16, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
126
127        /* Return to interrupted context */
128        eret
129
130thread_dispatch_helper:
131
132        /* This code executes in the context of the interrupted thread */
133
134        /* Save volatile registers */
135        stw     ra, FRAME_OFFSET_RA(sp)
136        stw     at, FRAME_OFFSET_AT(sp)
137        stw     r2, FRAME_OFFSET_R2(sp)
138        stw     r3, FRAME_OFFSET_R3(sp)
139        stw     r4, FRAME_OFFSET_R4(sp)
140        stw     r5, FRAME_OFFSET_R5(sp)
141        stw     r6, FRAME_OFFSET_R6(sp)
142        stw     r7, FRAME_OFFSET_R7(sp)
143        stw     r8, FRAME_OFFSET_R8(sp)
144        stw     r9, FRAME_OFFSET_R9(sp)
145        stw     r10, FRAME_OFFSET_R10(sp)
146        stw     r11, FRAME_OFFSET_R11(sp)
147        stw     r12, FRAME_OFFSET_R12(sp)
148        stw     r13, FRAME_OFFSET_R13(sp)
149        stw     r14, FRAME_OFFSET_R14(sp)
150        stw     r15, FRAME_OFFSET_R15(sp)
151
152        /*
153         * Disable interrupts (1).
154         *
155         * We have the following invariants:
156         *   1. status.RSIE == 0: thread context initialization
157         *   2. status.CRS == 0: thread context initialization
158         *   3. status.PRS: arbitrary
159         *   4. status.IL < interrupt disable IL: else we would not be here
160         *   5. status.IH == 0: thread context initialization
161         *   6. status.U == 0: thread context initialization
162         *   7. status.PIE == 1: thread context initialization
163         * Thus we can use a constant to disable interrupts.
164         */
165        movi    r5, %lo(_Nios2_ISR_Status_interrupts_disabled)
166        wrctl   status, r5
167
168do_thread_dispatch:
169
170        addi    r4, gp, %gprel(_Per_CPU_Information)
171        call    _Thread_Do_dispatch
172
173        /* Restore some volatile registers */
174        ldw     ra, FRAME_OFFSET_RA(sp)
175        ldw     at, FRAME_OFFSET_AT(sp)
176        ldw     r2, FRAME_OFFSET_R2(sp)
177        ldw     r3, FRAME_OFFSET_R3(sp)
178        ldw     r4, FRAME_OFFSET_R4(sp)
179        ldw     r5, FRAME_OFFSET_R5(sp)
180        ldw     r6, FRAME_OFFSET_R6(sp)
181        ldw     r7, FRAME_OFFSET_R7(sp)
182        ldw     r8, FRAME_OFFSET_R8(sp)
183        ldw     r9, FRAME_OFFSET_R9(sp)
184        ldw     r10, FRAME_OFFSET_R10(sp)
185        ldw     r11, FRAME_OFFSET_R11(sp)
186        ldw     r12, FRAME_OFFSET_R12(sp)
187
188        /* Disable interrupts, see (1) */
189        rdctl   r14, status
190        movi    r15, %lo(_Nios2_ISR_Status_interrupts_disabled)
191        wrctl   status, r15
192
193        /* Load thread dispatch necessary */
194        ldb     r13, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
195
196        /* Is thread dispatch necessary? */
197        bne     r13, zero, prepare_thread_dispatch
198
199        /* Enable thread dispatch after ISR */
200        stw     zero, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
201
202        /* Restore remaining volatile register */
203        ldw     r13, FRAME_OFFSET_R13(sp)
204        ldw     r14, FRAME_OFFSET_R14(sp)
205        ldw     r15, FRAME_OFFSET_R15(sp)
206
207        /* Restore context */
208        ldw     et, FRAME_OFFSET_STATUS(sp)
209        ldw     ea, FRAME_OFFSET_EA(sp)
210
211        /* Release stack frame */
212        addi    sp, sp, FRAME_SIZE
213
214        /* Restore context */
215        wrctl   estatus, et
216
217        /* Return to interrupted thread */
218        eret
219
220prepare_thread_dispatch:
221
222        /* Disable thread dispatching */
223        movi    r4, 1
224        stw     r4, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
225        stw     r4, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
226
227        /* Set interrupt level argument for _Thread_Do_dispatch() */
228        mov     r5, r15
229
230        br      do_thread_dispatch
Note: See TracBrowser for help on using the repository browser.