source: rtems/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_asm.S @ 1e7cbc5

4.104.114.84.95
Last change on this file since 1e7cbc5 was 1e7cbc5, checked in by Joel Sherrill <joel.sherrill@…>, on 09/04/03 at 18:52:26

2003-09-04 Joel Sherrill <joel@…>

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