source: rtems/c/src/lib/libcpu/powerpc/mpc5xx/irq/irq_asm.S @ f0a90bb

4.104.115
Last change on this file since f0a90bb was f0a90bb, checked in by Joel Sherrill <joel.sherrill@…>, on 03/12/09 at 14:33:14

2009-03-12 Joel Sherrill <joel.sherrill@…>

PR 1385/cpukit

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