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

Last change on this file since 9165349d was 9165349d, checked in by Sebastian Huber <sebastian.huber@…>, on 01/12/21 at 06:13:08

nios2: Use Per_CPU_Control::isr_dispatch_disable

  • Property mode set to 100644
File size: 5.5 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    r9, r16, 1
59        stw     r9, %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 thread dispatch necessary */
65        ldb     r12, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
66
67        /* Load 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         * Restore the thread dispatch disable level.  We must do this before
78         * we return to the normal register set, because otherwise we have
79         * problems if someone deletes or restarts the interrupted thread while
80         * we are in the thread dispatch helper.
81         */
82        stw     r16, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
83
84        /* Is thread dispatch allowed? */
85        bne     r16, zero, no_thread_dispatch
86
87        /* Is thread dispatch necessary? */
88        beq     r12, zero, no_thread_dispatch
89
90        /* Is outermost interrupt? */
91        andhi   r14, r14, 0x3f
92        bne     r14, zero, no_thread_dispatch
93
94        /* Is thread dispatch after ISR allowed? */
95        bne     r13, zero, no_thread_dispatch
96
97        /* Obtain stack frame in normal register set */
98        rdprs   r15, sp, -FRAME_SIZE
99
100        /* Disable thread dispatch after ISR */
101        stw     r12, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
102
103        /* Save context */
104        stw     sstatus, FRAME_OFFSET_STATUS(r15)
105        stw     ea, FRAME_OFFSET_EA(r15)
106
107        /* Set thread dispatch helper address */
108        movhi   ea, %hiadj(thread_dispatch_helper)
109        addi    ea, ea, %lo(thread_dispatch_helper)
110
111        /* Update stack pointer in normal register set */
112        wrprs   sp, r15
113
114no_thread_dispatch:
115
116        /*
117         * Return to thread dispatch helper, interrupted thread or interrupted
118         * lower level interrupt service routine.
119         */
120        eret
121
122thread_dispatch_helper:
123
124        /* This code executes in the context of the interrupted thread */
125
126        /* Save volatile registers */
127        stw     ra, FRAME_OFFSET_RA(sp)
128        stw     at, FRAME_OFFSET_AT(sp)
129        stw     r2, FRAME_OFFSET_R2(sp)
130        stw     r3, FRAME_OFFSET_R3(sp)
131        stw     r4, FRAME_OFFSET_R4(sp)
132        stw     r5, FRAME_OFFSET_R5(sp)
133        stw     r6, FRAME_OFFSET_R6(sp)
134        stw     r7, FRAME_OFFSET_R7(sp)
135        stw     r8, FRAME_OFFSET_R8(sp)
136        stw     r9, FRAME_OFFSET_R9(sp)
137        stw     r10, FRAME_OFFSET_R10(sp)
138        stw     r11, FRAME_OFFSET_R11(sp)
139        stw     r12, FRAME_OFFSET_R12(sp)
140        stw     r13, FRAME_OFFSET_R13(sp)
141        stw     r14, FRAME_OFFSET_R14(sp)
142        stw     r15, FRAME_OFFSET_R15(sp)
143
144do_thread_dispatch:
145
146        call    _Thread_Dispatch
147
148        /* Restore some volatile registers */
149        ldw     ra, FRAME_OFFSET_RA(sp)
150        ldw     at, FRAME_OFFSET_AT(sp)
151        ldw     r2, FRAME_OFFSET_R2(sp)
152        ldw     r3, FRAME_OFFSET_R3(sp)
153        ldw     r4, FRAME_OFFSET_R4(sp)
154        ldw     r5, FRAME_OFFSET_R5(sp)
155        ldw     r6, FRAME_OFFSET_R6(sp)
156        ldw     r7, FRAME_OFFSET_R7(sp)
157        ldw     r8, FRAME_OFFSET_R8(sp)
158        ldw     r9, FRAME_OFFSET_R9(sp)
159        ldw     r10, FRAME_OFFSET_R10(sp)
160        ldw     r11, FRAME_OFFSET_R11(sp)
161        ldw     r12, FRAME_OFFSET_R12(sp)
162
163        /*
164         * Disable interrupts.
165         *
166         * We have the following invariants:
167         *   1. status.RSIE == 0: thread context initialization
168         *   2. status.CRS == 0: thread context initialization
169         *   3. status.PRS: arbitrary
170         *   4. status.IL < interrupt disable IL: else we would not be here
171         *   5. status.IH == 0: thread context initialization
172         *   6. status.U == 0: thread context initialization
173         *   7. status.PIE == 1: thread context initialization
174         * Thus we can use a constant to disable interrupts.
175         */
176        rdctl   r14, status
177        movi    r15, %lo(_Nios2_ISR_Status_interrupts_disabled)
178        wrctl   status, r15
179
180        /* Load thread dispatch necessary */
181        ldb     r13, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
182
183        /* Is thread dispatch necessary? */
184        bne     r13, zero, enable_interrupts_before_thread_dispatch
185
186        /* Enable thread dispatch after ISR */
187        stw     zero, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
188
189        /* Restore remaining volatile register */
190        ldw     r13, FRAME_OFFSET_R13(sp)
191        ldw     r14, FRAME_OFFSET_R14(sp)
192        ldw     r15, FRAME_OFFSET_R15(sp)
193
194        /* Restore context */
195        ldw     et, FRAME_OFFSET_STATUS(sp)
196        ldw     ea, FRAME_OFFSET_EA(sp)
197
198        /* Release stack frame */
199        addi    sp, sp, FRAME_SIZE
200
201        /* Restore context */
202        wrctl   estatus, et
203
204        /* Return to interrupted thread */
205        eret
206
207enable_interrupts_before_thread_dispatch:
208
209        /* Restore status */
210        wrctl   status, r14
211
212        br      do_thread_dispatch
Note: See TracBrowser for help on using the repository browser.