source: rtems/c/src/lib/libbsp/powerpc/shared/irq/irq_asm.S @ e79a1947

4.104.114.84.95
Last change on this file since e79a1947 was f05b2ac, checked in by Ralf Corsepius <ralf.corsepius@…>, on 04/21/04 at 16:01:48

Remove duplicate white lines.

  • Property mode set to 100644
File size: 8.3 KB
Line 
1/*
2 *  This file contains the assembly code for the PowerPC
3 *  IRQ veneers for RTEMS.
4 *
5 *  The license and distribution terms for this file may be
6 *  found in found in the file LICENSE in this distribution or at
7 *  http://www.rtems.com/license/LICENSE.
8 *
9 *  Modified to support the MCP750.
10 *  Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
11 *
12 *  Till Straumann <strauman@slac.stanford.edu>, 2003/7:
13 *    - store isr nesting level in _ISR_Nest_level rather than
14 *      SPRG0 - RTEMS relies on that variable.
15 *
16 * $Id$
17 */
18
19#include <rtems/asm.h>
20#include <rtems/score/cpu.h>
21#include <bsp/vectors.h>
22#include <libcpu/raw_exception.h>
23
24#define SYNC \
25        sync; \
26        isync
27
28        .text
29        .p2align 5
30
31        PUBLIC_VAR(decrementer_exception_vector_prolog_code)
32
33SYM (decrementer_exception_vector_prolog_code):
34        /*
35         * let room for exception frame
36         */
37        stwu    r1, - (EXCEPTION_FRAME_END)(r1)
38        stw     r4, GPR4_OFFSET(r1)
39        li      r4, ASM_DEC_VECTOR
40        ba      shared_raw_irq_code_entry
41
42        PUBLIC_VAR (decrementer_exception_vector_prolog_code_size)
43
44        decrementer_exception_vector_prolog_code_size = . - decrementer_exception_vector_prolog_code
45
46        PUBLIC_VAR(external_exception_vector_prolog_code)
47
48SYM (external_exception_vector_prolog_code):
49        /*
50         * let room for exception frame
51         */
52        stwu    r1, - (EXCEPTION_FRAME_END)(r1)
53        stw     r4, GPR4_OFFSET(r1)
54        li      r4, ASM_EXT_VECTOR
55        ba      shared_raw_irq_code_entry
56
57        PUBLIC_VAR (external_exception_vector_prolog_code_size)
58
59        external_exception_vector_prolog_code_size = . - external_exception_vector_prolog_code
60
61        PUBLIC_VAR(shared_raw_irq_code_entry)
62        PUBLIC_VAR(C_dispatch_irq_handler)
63
64        .p2align 5
65SYM (shared_raw_irq_code_entry):
66        /*
67         * Entry conditions :
68         *      Registers already saved : R1, R4
69         *      R1  :   points to a location with enough room for the
70         *              interrupt frame
71         *      R4  :   vector number
72         */
73        /*
74         * Save SRR0/SRR1 As soon As possible as it is the minimal needed
75         * to reenable exception processing
76         */
77        stw     r0, GPR0_OFFSET(r1)
78        /* PPC EABI: R2 is reserved (pointer to short data .sdata2) - we won't touch it
79         * but we still save/restore it, just in case...
80         */
81        stw     r2, GPR2_OFFSET(r1)
82        stw     r3, GPR3_OFFSET(r1)
83
84        mfsrr0  r0
85        mfsrr1  r3
86
87        stw     r0, SRR0_FRAME_OFFSET(r1)
88        stw     r3, SRR1_FRAME_OFFSET(r1)
89
90        mfmsr   r3
91        /*
92         * Enable data and instruction address translation, exception recovery
93     *
94     * also, on CPUs with FP, enable FP so that FP context can be
95     * saved and restored (using FP instructions)
96         */
97#if (PPC_HAS_FPU == 0)
98        ori     r3, r3, MSR_RI | MSR_IR | MSR_DR
99#else
100        ori     r3, r3, MSR_RI | MSR_IR | MSR_DR | MSR_FP
101#endif
102        mtmsr   r3
103        SYNC
104        /*
105         * Push C scratch registers on the current stack. It may
106         * actually be the thread stack or the interrupt stack.
107         * Anyway we have to make it in order to be able to call C/C++
108         * functions. Depending on the nesting interrupt level, we will
109         * switch to the right stack later.
110         */
111        stw     r5, GPR5_OFFSET(r1)
112        stw     r6, GPR6_OFFSET(r1)
113        stw     r7, GPR7_OFFSET(r1)
114        stw     r8, GPR8_OFFSET(r1)
115        stw     r9, GPR9_OFFSET(r1)
116        stw     r10, GPR10_OFFSET(r1)
117        stw     r11, GPR11_OFFSET(r1)
118        stw     r12, GPR12_OFFSET(r1)
119        stw     r13, GPR13_OFFSET(r1)
120
121        mfcr    r5
122        mfctr   r6
123        mfxer   r7
124        mflr    r8
125
126        stw     r5,  EXC_CR_OFFSET(r1)
127        stw     r6,  EXC_CTR_OFFSET(r1)
128        stw     r7,  EXC_XER_OFFSET(r1)
129        stw     r8,  EXC_LR_OFFSET(r1)
130
131        /*
132         * Add some non volatile registers to store information
133         * that will be used when returning from C handler
134         */
135        stw     r14, GPR14_OFFSET(r1)
136        stw     r15, GPR15_OFFSET(r1)
137        /*
138         * save current stack pointer location in R14
139         */
140        addi    r14, r1, 0
141        /*
142         * store part of _Thread_Dispatch_disable_level address in R15
143         */
144        addis r15,0, _Thread_Dispatch_disable_level@ha
145#if BROKEN_ISR_NEST_LEVEL
146        /*
147         * Get current nesting level in R3
148         */
149        mfspr   r3, SPRG0
150#else
151        /*
152         * Retrieve current nesting level from _ISR_Nest_level
153         */
154        lis             r7, _ISR_Nest_level@ha
155        lwz             r3, _ISR_Nest_level@l(r7)
156#endif
157        /*
158         * Check if stack switch is necessary
159         */
160        cmpwi   r3,0
161        bne     nested
162        mfspr   r1, SPRG1
163
164nested:
165        /*
166         * Start Incrementing nesting level in R3
167         */
168        addi    r3,r3,1
169        /*
170         * Start Incrementing _Thread_Dispatch_disable_level R4 = _Thread_Dispatch_disable_level
171         */
172        lwz     r6,_Thread_Dispatch_disable_level@l(r15)
173#if BROKEN_ISR_NEST_LEVEL
174        /*
175         * Store new nesting level in SPRG0
176         */
177        mtspr   SPRG0, r3
178#else
179        /* store new nesting level in _ISR_Nest_level */
180        stw             r3, _ISR_Nest_level@l(r7)
181#endif
182
183        addi    r6, r6, 1
184        mfmsr   r5
185        /*
186         * store new _Thread_Dispatch_disable_level value
187         */
188        stw     r6, _Thread_Dispatch_disable_level@l(r15)
189        /*
190         * We are now running on the interrupt stack. External and decrementer
191         * exceptions are still disabled. I see no purpose trying to optimize
192         * further assembler code.
193         */
194        /*
195         * Call C exception handler for decrementer Interrupt frame is passed just
196         * in case...
197         */
198        addi    r3, r14, 0x8
199        bl      C_dispatch_irq_handler /* C_dispatch_irq_handler(cpu_interrupt_frame* r3, vector r4) */
200        /*
201         * start decrementing nesting level. Note : do not test result against 0
202         * value as an easy exit condition because if interrupt nesting level > 1
203         * then _Thread_Dispatch_disable_level > 1
204         */
205#if BROKEN_ISR_NEST_LEVEL
206        mfspr   r4, SPRG0
207#else
208        lis             r7, _ISR_Nest_level@ha
209        lwz             r4, _ISR_Nest_level@l(r7)
210#endif
211        /*
212         * start decrementing _Thread_Dispatch_disable_level
213         */
214        lwz     r3,_Thread_Dispatch_disable_level@l(r15)
215        addi    r4, r4, -1      /* Continue decrementing nesting level */
216        addi    r3, r3, -1      /* Continue decrementing _Thread_Dispatch_disable_level */
217#if BROKEN_ISR_NEST_LEVEL
218        mtspr   SPRG0, r4       /* End decrementing nesting level */
219#else
220        stw             r4, _ISR_Nest_level@l(r7) /* End decrementing nesting level */
221#endif
222        stw     r3,_Thread_Dispatch_disable_level@l(r15) /* End decrementing _Thread_Dispatch_disable_level */
223        cmpwi   r3, 0
224        /*
225         * switch back to original stack (done here just optimize registers
226         * contention. Could have been done before...)
227         */
228        addi    r1, r14, 0
229        bne     easy_exit /* if (_Thread_Dispatch_disable_level != 0) goto easy_exit */
230        /*
231         * Here we are running again on the thread system stack.
232         * We have interrupt nesting level = _Thread_Dispatch_disable_level = 0.
233         * Interrupt are still disabled. Time to check if scheduler request to
234         * do something with the current thread...
235         */
236        addis   r4, 0, _Context_Switch_necessary@ha
237        lwz     r5, _Context_Switch_necessary@l(r4)
238        cmpwi   r5, 0
239        bne     switch
240
241        addis   r6, 0, _ISR_Signals_to_thread_executing@ha
242        lwz     r7, _ISR_Signals_to_thread_executing@l(r6)
243        cmpwi   r7, 0
244        li      r8, 0
245        beq     easy_exit
246        stw     r8, _ISR_Signals_to_thread_executing@l(r6)
247        /*
248         * going to call _ThreadProcessSignalsFromIrq
249         * Push a complete exception like frame...
250         */
251        stmw    r16, GPR16_OFFSET(r1)
252        addi    r3, r1, 0x8
253        /*
254         * compute SP at exception entry
255         */
256        addi    r4, r1, EXCEPTION_FRAME_END
257        /*
258         * store it at the right place
259         */
260        stw     r4, GPR1_OFFSET(r1)
261        /*
262         * Call High Level signal handling code
263         */
264        bl      _ThreadProcessSignalsFromIrq
265        /*
266         * start restoring exception like frame
267         */
268        lwz     r31,  EXC_CTR_OFFSET(r1)
269        lwz     r30,  EXC_XER_OFFSET(r1)
270        lwz     r29,  EXC_CR_OFFSET(r1)
271        lwz     r28,  EXC_LR_OFFSET(r1)
272
273        mtctr   r31
274        mtxer   r30
275        mtcr    r29
276        mtlr    r28
277
278        lmw     r4, GPR4_OFFSET(r1)
279        lwz     r2, GPR2_OFFSET(r1)
280        lwz     r0, GPR0_OFFSET(r1)
281
282        /*
283         * Disable data and instruction translation. Make path non recoverable...
284         */
285        mfmsr   r3
286        xori    r3, r3, MSR_RI | MSR_IR | MSR_DR
287        mtmsr   r3
288        SYNC
289        /*
290         * Restore rfi related settings
291         */
292
293        lwz     r3, SRR1_FRAME_OFFSET(r1)
294        mtsrr1  r3
295        lwz     r3, SRR0_FRAME_OFFSET(r1)
296        mtsrr0  r3
297
298        lwz     r3, GPR3_OFFSET(r1)
299        addi    r1,r1, EXCEPTION_FRAME_END
300        SYNC
301        rfi
302
303switch:
304        bl      SYM (_Thread_Dispatch)
305
306easy_exit:
307        /*
308         * start restoring interrupt frame
309         */
310        lwz     r3,  EXC_CTR_OFFSET(r1)
311        lwz     r4,  EXC_XER_OFFSET(r1)
312        lwz     r5,  EXC_CR_OFFSET(r1)
313        lwz     r6,  EXC_LR_OFFSET(r1)
314
315        mtctr   r3
316        mtxer   r4
317        mtcr    r5
318        mtlr    r6
319
320        lwz     r15, GPR15_OFFSET(r1)
321        lwz     r14, GPR14_OFFSET(r1)
322        lwz     r13, GPR13_OFFSET(r1)
323        lwz     r12, GPR12_OFFSET(r1)
324        lwz     r11, GPR11_OFFSET(r1)
325        lwz     r10, GPR10_OFFSET(r1)
326        lwz     r9, GPR9_OFFSET(r1)
327        lwz     r8, GPR8_OFFSET(r1)
328        lwz     r7, GPR7_OFFSET(r1)
329        lwz     r6, GPR6_OFFSET(r1)
330        lwz     r5, GPR5_OFFSET(r1)
331
332        /*
333         * Disable nested exception processing, data and instruction
334         * translation.
335         */
336        mfmsr   r3
337        xori    r3, r3, MSR_RI | MSR_IR | MSR_DR
338        mtmsr   r3
339        SYNC
340        /*
341         * Restore rfi related settings
342         */
343
344        lwz     r4, SRR1_FRAME_OFFSET(r1)
345        lwz     r3, SRR0_FRAME_OFFSET(r1)
346        lwz     r2, GPR2_OFFSET(r1)
347        lwz     r0, GPR0_OFFSET(r1)
348
349        mtsrr1  r4
350        mtsrr0  r3
351        lwz     r4, GPR4_OFFSET(r1)
352        lwz     r3, GPR3_OFFSET(r1)
353        addi    r1,r1, EXCEPTION_FRAME_END
354        SYNC
355        rfi
Note: See TracBrowser for help on using the repository browser.