source: rtems/c/src/lib/libbsp/powerpc/tqm8xx/irq/irq_asm.S @ 63de714c

4.104.114.95
Last change on this file since 63de714c was 63de714c, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on 09/08/08 at 09:55:39

added new BSP for TQM8xx boards

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