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

4.104.114.84.9
Last change on this file since 73cdeb6 was 73cdeb6, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on Jul 4, 2007 at 12:25:49 PM

merged individual exception handler code to a common one.

  • Property mode set to 100644
File size: 9.3 KB
RevLine 
[acc25ee]1/*
[6128a4a]2 *  This file contains the assembly code for the PowerPC
[acc25ee]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
[e831de8]7 *  http://www.rtems.com/license/LICENSE.
[acc25ee]8 *
9 *  Modified to support the MCP750.
10 *  Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
11 *
[ec821af]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.
[384ba756]15 *  Till Straumann <strauman@slac.stanford.edu>, 2005/4:
16 *    - DONT enable FP across ISR since fpregs are not saved!!
17 *      FPU is used by Thread_Dispatch however...
[acc25ee]18 *
19 * $Id$
20 */
[6128a4a]21
[b7768c55]22#include <rtems/asm.h>
[cd35cf9]23#include <rtems/score/cpu.h>
[acc25ee]24#include <bsp/vectors.h>
25#include <libcpu/raw_exception.h>
[6128a4a]26
[acc25ee]27#define SYNC \
28        sync; \
29        isync
[6128a4a]30
[acc25ee]31        .text
[6128a4a]32        .p2align 5
[73cdeb6]33#if defined(ASM_DEC_VECTOR)
[acc25ee]34        PUBLIC_VAR(decrementer_exception_vector_prolog_code)
[6128a4a]35
[acc25ee]36SYM (decrementer_exception_vector_prolog_code):
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)
[6128a4a]46
[acc25ee]47        decrementer_exception_vector_prolog_code_size = . - decrementer_exception_vector_prolog_code
[73cdeb6]48#endif
49
50#if defined(ASM_PIT_VECTOR)
51        PUBLIC_VAR(pit_exception_vector_prolog_code)
52
53SYM (pit_exception_vector_prolog_code):
54        /*
55         * let room for exception frame
56         */
57        stwu    r1, - (EXCEPTION_FRAME_END)(r1)
58        stw     r4, GPR4_OFFSET(r1)
59        li      r4, ASM_PIT_VECTOR
60        ba      shared_raw_irq_code_entry
61
62        PUBLIC_VAR (pit_exception_vector_prolog_code_size)
63
64        pit_exception_vector_prolog_code_size = . - pit_exception_vector_prolog_code
65#endif
66
67#if defined(ASM_FIT_VECTOR)
68        PUBLIC_VAR(fit_exception_vector_prolog_code)
[acc25ee]69
[73cdeb6]70SYM (fit_exception_vector_prolog_code):
71        /*
72         * let room for exception frame
73         */
74        stwu    r1, - (EXCEPTION_FRAME_END)(r1)
75        stw     r4, GPR4_OFFSET(r1)
76        li      r4, ASM_FIT_VECTOR
77        ba      shared_raw_irq_code_entry
78
79        PUBLIC_VAR (fit_exception_vector_prolog_code_size)
80
81        fit_exception_vector_prolog_code_size = . - fit_exception_vector_prolog_code
82#endif
83       
[acc25ee]84        PUBLIC_VAR(external_exception_vector_prolog_code)
[6128a4a]85
[73cdeb6]86#if defined(ASM_EXT_VECTOR)
[acc25ee]87SYM (external_exception_vector_prolog_code):
88        /*
89         * let room for exception frame
90         */
91        stwu    r1, - (EXCEPTION_FRAME_END)(r1)
92        stw     r4, GPR4_OFFSET(r1)
93        li      r4, ASM_EXT_VECTOR
94        ba      shared_raw_irq_code_entry
95
96        PUBLIC_VAR (external_exception_vector_prolog_code_size)
[6128a4a]97
[acc25ee]98        external_exception_vector_prolog_code_size = . - external_exception_vector_prolog_code
[73cdeb6]99#endif
[acc25ee]100
101        PUBLIC_VAR(shared_raw_irq_code_entry)
102        PUBLIC_VAR(C_dispatch_irq_handler)
[6128a4a]103
[acc25ee]104        .p2align 5
105SYM (shared_raw_irq_code_entry):
106        /*
107         * Entry conditions :
108         *      Registers already saved : R1, R4
109         *      R1  :   points to a location with enough room for the
110         *              interrupt frame
111         *      R4  :   vector number
112         */
113        /*
[6128a4a]114         * Save SRR0/SRR1 As soon As possible as it is the minimal needed
[acc25ee]115         * to reenable exception processing
116         */
117        stw     r0, GPR0_OFFSET(r1)
[4f3e4f33]118        /* PPC EABI: R2 is reserved (pointer to short data .sdata2) - we won't touch it
119         * but we still save/restore it, just in case...
120         */
[acc25ee]121        stw     r2, GPR2_OFFSET(r1)
122        stw     r3, GPR3_OFFSET(r1)
[6128a4a]123
[acc25ee]124        mfsrr0  r0
[4f3e4f33]125        mfsrr1  r3
[6128a4a]126
[acc25ee]127        stw     r0, SRR0_FRAME_OFFSET(r1)
[4f3e4f33]128        stw     r3, SRR1_FRAME_OFFSET(r1)
129
[73cdeb6]130#if defined(PPC_MSR_EXC_BITS)
[4f3e4f33]131        mfmsr   r3
[acc25ee]132        /*
133         * Enable data and instruction address translation, exception recovery
134         */
[73cdeb6]135        ori     r3, r3, PPC_MSR_EXC_BITS
[acc25ee]136        mtmsr   r3
[73cdeb6]137#endif
[acc25ee]138        SYNC
139        /*
140         * Push C scratch registers on the current stack. It may
141         * actually be the thread stack or the interrupt stack.
142         * Anyway we have to make it in order to be able to call C/C++
143         * functions. Depending on the nesting interrupt level, we will
144         * switch to the right stack later.
145         */
146        stw     r5, GPR5_OFFSET(r1)
147        stw     r6, GPR6_OFFSET(r1)
148        stw     r7, GPR7_OFFSET(r1)
149        stw     r8, GPR8_OFFSET(r1)
150        stw     r9, GPR9_OFFSET(r1)
151        stw     r10, GPR10_OFFSET(r1)
152        stw     r11, GPR11_OFFSET(r1)
153        stw     r12, GPR12_OFFSET(r1)
154        stw     r13, GPR13_OFFSET(r1)
155
156        mfcr    r5
157        mfctr   r6
158        mfxer   r7
159        mflr    r8
[6128a4a]160
[acc25ee]161        stw     r5,  EXC_CR_OFFSET(r1)
162        stw     r6,  EXC_CTR_OFFSET(r1)
163        stw     r7,  EXC_XER_OFFSET(r1)
164        stw     r8,  EXC_LR_OFFSET(r1)
165
166        /*
167         * Add some non volatile registers to store information
168         * that will be used when returning from C handler
169         */
170        stw     r14, GPR14_OFFSET(r1)
171        stw     r15, GPR15_OFFSET(r1)
172        /*
173         * save current stack pointer location in R14
174         */
175        addi    r14, r1, 0
176        /*
177         * store part of _Thread_Dispatch_disable_level address in R15
178         */
179        addis r15,0, _Thread_Dispatch_disable_level@ha
[ec821af]180#if BROKEN_ISR_NEST_LEVEL
[acc25ee]181        /*
[4f3e4f33]182         * Get current nesting level in R3
[acc25ee]183         */
[4f3e4f33]184        mfspr   r3, SPRG0
[ec821af]185#else
186        /*
187         * Retrieve current nesting level from _ISR_Nest_level
188         */
189        lis             r7, _ISR_Nest_level@ha
190        lwz             r3, _ISR_Nest_level@l(r7)
191#endif
[acc25ee]192        /*
193         * Check if stack switch is necessary
194         */
[4f3e4f33]195        cmpwi   r3,0
[acc25ee]196        bne     nested
197        mfspr   r1, SPRG1
[6128a4a]198
199nested:
200        /*
[4f3e4f33]201         * Start Incrementing nesting level in R3
[acc25ee]202         */
[4f3e4f33]203        addi    r3,r3,1
[acc25ee]204        /*
205         * Start Incrementing _Thread_Dispatch_disable_level R4 = _Thread_Dispatch_disable_level
206         */
207        lwz     r6,_Thread_Dispatch_disable_level@l(r15)
[ec821af]208#if BROKEN_ISR_NEST_LEVEL
[acc25ee]209        /*
[ec821af]210         * Store new nesting level in SPRG0
[acc25ee]211         */
[4f3e4f33]212        mtspr   SPRG0, r3
[ec821af]213#else
214        /* store new nesting level in _ISR_Nest_level */
215        stw             r3, _ISR_Nest_level@l(r7)
216#endif
[6128a4a]217
[acc25ee]218        addi    r6, r6, 1
219        mfmsr   r5
220        /*
221         * store new _Thread_Dispatch_disable_level value
222         */
223        stw     r6, _Thread_Dispatch_disable_level@l(r15)
224        /*
225         * We are now running on the interrupt stack. External and decrementer
226         * exceptions are still disabled. I see no purpose trying to optimize
[6128a4a]227         * further assembler code.
[acc25ee]228         */
229        /*
230         * Call C exception handler for decrementer Interrupt frame is passed just
231         * in case...
232         */
233        addi    r3, r14, 0x8
[5b8eb3f0]234        /* clear CR[6] to make sure no varargs fn callee assumes there are FP args passed */
235        crxor   6,6,6
[acc25ee]236        bl      C_dispatch_irq_handler /* C_dispatch_irq_handler(cpu_interrupt_frame* r3, vector r4) */
237        /*
[6128a4a]238         * start decrementing nesting level. Note : do not test result against 0
[acc25ee]239         * value as an easy exit condition because if interrupt nesting level > 1
240         * then _Thread_Dispatch_disable_level > 1
241         */
[ec821af]242#if BROKEN_ISR_NEST_LEVEL
[4f3e4f33]243        mfspr   r4, SPRG0
[ec821af]244#else
245        lis             r7, _ISR_Nest_level@ha
246        lwz             r4, _ISR_Nest_level@l(r7)
247#endif
[acc25ee]248        /*
249         * start decrementing _Thread_Dispatch_disable_level
250         */
251        lwz     r3,_Thread_Dispatch_disable_level@l(r15)
[4f3e4f33]252        addi    r4, r4, -1      /* Continue decrementing nesting level */
[acc25ee]253        addi    r3, r3, -1      /* Continue decrementing _Thread_Dispatch_disable_level */
[ec821af]254#if BROKEN_ISR_NEST_LEVEL
[4f3e4f33]255        mtspr   SPRG0, r4       /* End decrementing nesting level */
[ec821af]256#else
257        stw             r4, _ISR_Nest_level@l(r7) /* End decrementing nesting level */
258#endif
[acc25ee]259        stw     r3,_Thread_Dispatch_disable_level@l(r15) /* End decrementing _Thread_Dispatch_disable_level */
260        cmpwi   r3, 0
261        /*
[6128a4a]262         * switch back to original stack (done here just optimize registers
[acc25ee]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.
[6128a4a]270         * Interrupt are still disabled. Time to check if scheduler request to
[acc25ee]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
[6128a4a]277
[acc25ee]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
[4f3e4f33]290        /*
291         * compute SP at exception entry
292         */
293        addi    r4, r1, EXCEPTION_FRAME_END
294        /*
295         * store it at the right place
296         */
297        stw     r4, GPR1_OFFSET(r1)
[acc25ee]298        /*
299         * Call High Level signal handling code
300         */
[e06d5aed]301        bl      _ThreadProcessSignalsFromIrq
[acc25ee]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)
[6128a4a]309
[acc25ee]310        mtctr   r31
311        mtxer   r30
312        mtcr    r29
313        mtlr    r28
[6128a4a]314
[acc25ee]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         */
[73cdeb6]322#if defined(PPC_MSR_EXC_BITS)
[acc25ee]323        mfmsr   r3
[73cdeb6]324        xori    r3, r3, PPC_MSR_EXC_BITS
[acc25ee]325        mtmsr   r3
326        SYNC
[73cdeb6]327#endif
[acc25ee]328        /*
329         * Restore rfi related settings
330         */
[6128a4a]331
[acc25ee]332        lwz     r3, SRR1_FRAME_OFFSET(r1)
333        mtsrr1  r3
334        lwz     r3, SRR0_FRAME_OFFSET(r1)
335        mtsrr0  r3
[6128a4a]336
[acc25ee]337        lwz     r3, GPR3_OFFSET(r1)
338        addi    r1,r1, EXCEPTION_FRAME_END
339        SYNC
340        rfi
[6128a4a]341
[acc25ee]342switch:
343        bl      SYM (_Thread_Dispatch)
[6128a4a]344
345easy_exit:
[acc25ee]346        /*
347         * start restoring interrupt frame
348         */
349        lwz     r3,  EXC_CTR_OFFSET(r1)
350        lwz     r4,  EXC_XER_OFFSET(r1)
351        lwz     r5,  EXC_CR_OFFSET(r1)
352        lwz     r6,  EXC_LR_OFFSET(r1)
[6128a4a]353
[acc25ee]354        mtctr   r3
355        mtxer   r4
356        mtcr    r5
357        mtlr    r6
358
359        lwz     r15, GPR15_OFFSET(r1)
360        lwz     r14, GPR14_OFFSET(r1)
361        lwz     r13, GPR13_OFFSET(r1)
362        lwz     r12, GPR12_OFFSET(r1)
363        lwz     r11, GPR11_OFFSET(r1)
364        lwz     r10, GPR10_OFFSET(r1)
365        lwz     r9, GPR9_OFFSET(r1)
366        lwz     r8, GPR8_OFFSET(r1)
367        lwz     r7, GPR7_OFFSET(r1)
368        lwz     r6, GPR6_OFFSET(r1)
369        lwz     r5, GPR5_OFFSET(r1)
370
371        /*
372         * Disable nested exception processing, data and instruction
373         * translation.
374         */
[73cdeb6]375#if defined(PPC_MSR_EXC_BITS)
[acc25ee]376        mfmsr   r3
[73cdeb6]377        xori    r3, r3, PPC_MSR_EXC_BITS
[acc25ee]378        mtmsr   r3
379        SYNC
[73cdeb6]380#endif
[acc25ee]381        /*
382         * Restore rfi related settings
383         */
[6128a4a]384
[acc25ee]385        lwz     r4, SRR1_FRAME_OFFSET(r1)
[4f3e4f33]386        lwz     r3, SRR0_FRAME_OFFSET(r1)
387        lwz     r2, GPR2_OFFSET(r1)
[acc25ee]388        lwz     r0, GPR0_OFFSET(r1)
389
390        mtsrr1  r4
[4f3e4f33]391        mtsrr0  r3
[acc25ee]392        lwz     r4, GPR4_OFFSET(r1)
[4f3e4f33]393        lwz     r3, GPR3_OFFSET(r1)
[acc25ee]394        addi    r1,r1, EXCEPTION_FRAME_END
395        SYNC
396        rfi
Note: See TracBrowser for help on using the repository browser.