source: rtems/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq_asm.S @ d36d3a3

4.104.114.84.95
Last change on this file since d36d3a3 was d36d3a3, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 1, 2002 at 2:21:47 PM

2002-11-01 Andy Dachs <a.dachs@…>

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