source: rtems/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_async_normal.S @ 5c7bfcf

Last change on this file since 5c7bfcf was 5c7bfcf, checked in by Sebastian Huber <sebastian.huber@…>, on Nov 11, 2015 at 10:49:45 AM

Fix interrupt epilogue for ARMv7-AR and PowerPC

  • Property mode set to 100644
File size: 15.6 KB
Line 
1/*
2 * Copyright (c) 2011-2015 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#include <bspopts.h>
16#include <rtems/score/percpu.h>
17#include <bsp/vectors.h>
18
19#define VECTOR_REGISTER r4
20#define SELF_CPU_REGISTER r5
21#define ISR_NEST_REGISTER r6
22#define DISPATCH_LEVEL_REGISTER r7
23#define HANDLER_REGISTER r8
24#define SCRATCH_0_REGISTER r0
25#define SCRATCH_1_REGISTER r3
26#define SCRATCH_2_REGISTER r9
27#define SCRATCH_3_REGISTER r10
28#define SCRATCH_4_REGISTER r11
29#define SCRATCH_5_REGISTER r12
30#define FRAME_REGISTER r14
31
32#define VECTOR_OFFSET GPR4_OFFSET
33#define SELF_CPU_OFFSET GPR5_OFFSET
34#define ISR_NEST_OFFSET GPR6_OFFSET
35#define DISPATCH_LEVEL_OFFSET GPR7_OFFSET
36#define HANDLER_OFFSET GPR8_OFFSET
37#define SCRATCH_0_OFFSET GPR0_OFFSET
38#define SCRATCH_1_OFFSET GPR3_OFFSET
39#define SCRATCH_2_OFFSET GPR9_OFFSET
40#define SCRATCH_3_OFFSET GPR10_OFFSET
41#define SCRATCH_4_OFFSET GPR11_OFFSET
42#define SCRATCH_5_OFFSET GPR12_OFFSET
43
44/*
45 * The register 2 slot is free, since this is the read-only small data anchor.
46 */
47#define FRAME_OFFSET GPR2_OFFSET
48
49#ifdef RTEMS_PROFILING
50/*
51 * The PPC_EXC_MINIMAL_FRAME_SIZE is enough to store this additional register.
52 */
53#define ENTRY_INSTANT_REGISTER r15
54#define ENTRY_INSTANT_OFFSET GPR13_OFFSET
55
56.macro GET_TIME_BASE REG
57#ifdef ppc8540
58        mfspr   \REG, TBRL
59#else /* ppc8540 */
60        mftb    \REG
61#endif /* ppc8540 */
62.endm
63#endif /* RTEMS_PROFILING */
64
65#ifdef PPC_EXC_CONFIG_USE_FIXED_HANDLER
66        .global bsp_interrupt_dispatch
67#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
68
69        .global ppc_exc_min_prolog_async_tmpl_normal
70        .global ppc_exc_wrap_async_normal
71
72ppc_exc_min_prolog_async_tmpl_normal:
73
74        stwu    r1, -PPC_EXC_MINIMAL_FRAME_SIZE(r1)
75
76#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
77        stw     VECTOR_REGISTER, PPC_EXC_VECTOR_PROLOGUE_OFFSET(r1)
78        li      VECTOR_REGISTER, 0xffff8000
79#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
80
81        /*
82         * We store the absolute branch target address here.  It will be used
83         * to generate the branch operation in ppc_exc_make_prologue().
84         */
85        .int    ppc_exc_wrap_async_normal
86
87ppc_exc_wrap_async_normal:
88
89#ifdef RTEMS_PROFILING
90        /* Save non-volatile ENTRY_INSTANT_REGISTER */
91        stw     ENTRY_INSTANT_REGISTER, ENTRY_INSTANT_OFFSET(r1)
92
93        /* Get entry instant */
94        GET_TIME_BASE   ENTRY_INSTANT_REGISTER
95#endif /* RTEMS_PROFILING */
96
97        /* Save non-volatile FRAME_REGISTER */
98        stw     FRAME_REGISTER, FRAME_OFFSET(r1)
99
100#ifdef __SPE__
101        /* Enable SPE */
102        mfmsr   FRAME_REGISTER
103        oris    FRAME_REGISTER, FRAME_REGISTER, MSR_SPE >> 16
104        mtmsr   FRAME_REGISTER
105        isync
106#endif
107
108#if defined(PPC_MULTILIB_FPU) || defined(PPC_MULTILIB_ALTIVEC)
109        /* Enable FPU and/or AltiVec */
110        mfmsr   FRAME_REGISTER
111#ifdef PPC_MULTILIB_FPU
112        ori     FRAME_REGISTER, FRAME_REGISTER, MSR_FP
113#endif
114#ifdef PPC_MULTILIB_ALTIVEC
115        oris    FRAME_REGISTER, FRAME_REGISTER, MSR_VE >> 16
116#endif
117        mtmsr   FRAME_REGISTER
118        isync
119#endif
120
121        /* Move frame pointer to non-volatile FRAME_REGISTER */
122        mr      FRAME_REGISTER, r1
123
124        /* Load ISR nest level and thread dispatch disable level */
125        PPC_GPR_STORE   SELF_CPU_REGISTER, SELF_CPU_OFFSET(r1)
126        GET_SELF_CPU_CONTROL    SELF_CPU_REGISTER
127        PPC_GPR_STORE   ISR_NEST_REGISTER, ISR_NEST_OFFSET(r1)
128        lwz     ISR_NEST_REGISTER, PER_CPU_ISR_NEST_LEVEL(SELF_CPU_REGISTER)
129        PPC_GPR_STORE   DISPATCH_LEVEL_REGISTER, DISPATCH_LEVEL_OFFSET(r1)
130        lwz     DISPATCH_LEVEL_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SELF_CPU_REGISTER)
131
132        PPC_GPR_STORE   SCRATCH_0_REGISTER, SCRATCH_0_OFFSET(r1)
133
134#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
135#ifdef __SPE__
136        /*
137         * Save high order part of VECTOR_REGISTER here.  The low order part
138         * was saved in the minimal prologue.
139         */
140        evmergehi       SCRATCH_0_REGISTER, SCRATCH_0_REGISTER, VECTOR_REGISTER
141        stw     SCRATCH_0_REGISTER, VECTOR_OFFSET(r1)
142#endif
143#else /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
144        /* The vector register has no special purpose in this case */
145        PPC_GPR_STORE   VECTOR_REGISTER, VECTOR_OFFSET(r1)
146#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
147
148        PPC_GPR_STORE   HANDLER_REGISTER, HANDLER_OFFSET(r1)
149
150#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
151        /*
152         * Load the handler address.  Get the handler table index from the
153         * vector number.  We have to discard the exception type.  Take only
154         * the least significant five bits (= LAST_VALID_EXC + 1) from the
155         * vector register.  Multiply by four (= size of function pointer).
156         */
157        rlwinm  SCRATCH_0_REGISTER, VECTOR_REGISTER, 2, 25, 29
158        lis     HANDLER_REGISTER, ppc_exc_handler_table@h
159        ori     HANDLER_REGISTER, HANDLER_REGISTER, ppc_exc_handler_table@l
160        lwzx    HANDLER_REGISTER, HANDLER_REGISTER, SCRATCH_0_REGISTER
161#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
162
163        PPC_GPR_STORE   SCRATCH_1_REGISTER, SCRATCH_1_OFFSET(r1)
164        PPC_GPR_STORE   SCRATCH_2_REGISTER, SCRATCH_2_OFFSET(r1)
165        PPC_GPR_STORE   SCRATCH_3_REGISTER, SCRATCH_3_OFFSET(r1)
166        PPC_GPR_STORE   SCRATCH_4_REGISTER, SCRATCH_4_OFFSET(r1)
167        PPC_GPR_STORE   SCRATCH_5_REGISTER, SCRATCH_5_OFFSET(r1)
168
169        /* Save SRR0, SRR1, CR, CTR, XER, and LR */
170        mfsrr0  SCRATCH_0_REGISTER
171        mfsrr1  SCRATCH_1_REGISTER
172        mfcr    SCRATCH_2_REGISTER
173        mfctr   SCRATCH_3_REGISTER
174        mfxer   SCRATCH_4_REGISTER
175        mflr    SCRATCH_5_REGISTER
176        stw     SCRATCH_0_REGISTER, SRR0_FRAME_OFFSET(r1)
177        stw     SCRATCH_1_REGISTER, SRR1_FRAME_OFFSET(r1)
178        stw     SCRATCH_2_REGISTER, EXC_CR_OFFSET(r1)
179        stw     SCRATCH_3_REGISTER, EXC_CTR_OFFSET(r1)
180        stw     SCRATCH_4_REGISTER, EXC_XER_OFFSET(r1)
181        stw     SCRATCH_5_REGISTER, EXC_LR_OFFSET(r1)
182
183#ifdef __SPE__
184        /* Save SPEFSCR and ACC */
185        mfspr   SCRATCH_0_REGISTER, FSL_EIS_SPEFSCR
186        evxor   SCRATCH_1_REGISTER, SCRATCH_1_REGISTER, SCRATCH_1_REGISTER
187        evmwumiaa       SCRATCH_1_REGISTER, SCRATCH_1_REGISTER, SCRATCH_1_REGISTER
188        stw     SCRATCH_0_REGISTER, PPC_EXC_SPEFSCR_OFFSET(r1)
189        evstdd  SCRATCH_1_REGISTER, PPC_EXC_ACC_OFFSET(r1)
190#endif
191
192#ifdef PPC_MULTILIB_ALTIVEC
193        /* Save volatile AltiVec context */
194        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(0)
195        stvx    v0, r1, SCRATCH_0_REGISTER
196        mfvscr  v0
197        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(1)
198        stvx    v1, r1, SCRATCH_0_REGISTER
199        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(2)
200        stvx    v2, r1, SCRATCH_0_REGISTER
201        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(3)
202        stvx    v3, r1, SCRATCH_0_REGISTER
203        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(4)
204        stvx    v4, r1, SCRATCH_0_REGISTER
205        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(5)
206        stvx    v5, r1, SCRATCH_0_REGISTER
207        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(6)
208        stvx    v6, r1, SCRATCH_0_REGISTER
209        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(7)
210        stvx    v7, r1, SCRATCH_0_REGISTER
211        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(8)
212        stvx    v8, r1, SCRATCH_0_REGISTER
213        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(9)
214        stvx    v9, r1, SCRATCH_0_REGISTER
215        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(10)
216        stvx    v10, r1, SCRATCH_0_REGISTER
217        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(11)
218        stvx    v11, r1, SCRATCH_0_REGISTER
219        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(12)
220        stvx    v12, r1, SCRATCH_0_REGISTER
221        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(13)
222        stvx    v13, r1, SCRATCH_0_REGISTER
223        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(14)
224        stvx    v14, r1, SCRATCH_0_REGISTER
225        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(15)
226        stvx    v15, r1, SCRATCH_0_REGISTER
227        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(16)
228        stvx    v16, r1, SCRATCH_0_REGISTER
229        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(17)
230        stvx    v17, r1, SCRATCH_0_REGISTER
231        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(18)
232        stvx    v18, r1, SCRATCH_0_REGISTER
233        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(19)
234        stvx    v19, r1, SCRATCH_0_REGISTER
235        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VSCR_OFFSET
236        stvewx  v0, r1, SCRATCH_0_REGISTER
237#endif
238
239#ifdef PPC_MULTILIB_FPU
240        /* Save volatile FPU context */
241        stfd    f0, PPC_EXC_MIN_FR_OFFSET(0)(r1)
242        mffs    f0
243        stfd    f1, PPC_EXC_MIN_FR_OFFSET(1)(r1)
244        stfd    f2, PPC_EXC_MIN_FR_OFFSET(2)(r1)
245        stfd    f3, PPC_EXC_MIN_FR_OFFSET(3)(r1)
246        stfd    f4, PPC_EXC_MIN_FR_OFFSET(4)(r1)
247        stfd    f5, PPC_EXC_MIN_FR_OFFSET(5)(r1)
248        stfd    f6, PPC_EXC_MIN_FR_OFFSET(6)(r1)
249        stfd    f7, PPC_EXC_MIN_FR_OFFSET(7)(r1)
250        stfd    f8, PPC_EXC_MIN_FR_OFFSET(8)(r1)
251        stfd    f9, PPC_EXC_MIN_FR_OFFSET(9)(r1)
252        stfd    f10, PPC_EXC_MIN_FR_OFFSET(10)(r1)
253        stfd    f11, PPC_EXC_MIN_FR_OFFSET(11)(r1)
254        stfd    f12, PPC_EXC_MIN_FR_OFFSET(12)(r1)
255        stfd    f13, PPC_EXC_MIN_FR_OFFSET(13)(r1)
256        stfd    f0, PPC_EXC_MIN_FPSCR_OFFSET(r1)
257#endif
258
259        /* Increment ISR nest level and thread dispatch disable level */
260        cmpwi   ISR_NEST_REGISTER, 0
261        addi    ISR_NEST_REGISTER, ISR_NEST_REGISTER, 1
262        addi    DISPATCH_LEVEL_REGISTER, DISPATCH_LEVEL_REGISTER, 1
263        stw     ISR_NEST_REGISTER, PER_CPU_ISR_NEST_LEVEL(SELF_CPU_REGISTER)
264        stw     DISPATCH_LEVEL_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SELF_CPU_REGISTER)
265
266        /* Switch stack if necessary */
267        mfspr   SCRATCH_0_REGISTER, SPRG1
268        iselgt  r1, r1, SCRATCH_0_REGISTER
269
270#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
271        /*
272         * Call high level exception handler.
273         *
274         * First parameter = exception frame pointer + FRAME_LINK_SPACE
275         * Second parameter = vector number (r4 is the VECTOR_REGISTER)
276         */
277        addi    r3, FRAME_REGISTER, FRAME_LINK_SPACE
278        rlwinm  VECTOR_REGISTER, VECTOR_REGISTER, 0, 27, 31
279        mtctr   HANDLER_REGISTER
280        bctrl
281#else /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
282        /* Call fixed high level handler */
283        bl      bsp_interrupt_dispatch
284#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
285
286        /* Load ISR nest level and thread dispatch disable level */
287        GET_SELF_CPU_CONTROL    SELF_CPU_REGISTER
288        lwz     ISR_NEST_REGISTER, PER_CPU_ISR_NEST_LEVEL(SELF_CPU_REGISTER)
289        lwz     DISPATCH_LEVEL_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SELF_CPU_REGISTER)
290
291        /*
292         * Switch back to original stack (FRAME_REGISTER == r1 if we are still
293         * on the IRQ stack) and restore FRAME_REGISTER.
294         */
295        mr      r1, FRAME_REGISTER
296        lwz     FRAME_REGISTER, FRAME_OFFSET(r1)
297
298        /* Decrement ISR nest level and thread dispatch disable level */
299#ifdef RTEMS_PROFILING
300        subic.  ISR_NEST_REGISTER, ISR_NEST_REGISTER, 1
301        subi    DISPATCH_LEVEL_REGISTER, DISPATCH_LEVEL_REGISTER, 1
302        cmpwi   cr2, DISPATCH_LEVEL_REGISTER, 0
303#else /* RTEMS_PROFILING */
304        subi    ISR_NEST_REGISTER, ISR_NEST_REGISTER, 1
305        subic.  DISPATCH_LEVEL_REGISTER, DISPATCH_LEVEL_REGISTER, 1
306#endif /* RTEMS_PROFILING */
307        stw     ISR_NEST_REGISTER, PER_CPU_ISR_NEST_LEVEL(SELF_CPU_REGISTER)
308        stw     DISPATCH_LEVEL_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SELF_CPU_REGISTER)
309
310#ifdef RTEMS_PROFILING
311        /* Store profiling data if necessary */
312        bne     profiling_done
313        mr      r3, SELF_CPU_REGISTER
314        mr      r4, ENTRY_INSTANT_REGISTER
315        GET_TIME_BASE   r5
316        bl      _Profiling_Outer_most_interrupt_entry_and_exit
317profiling_done:
318#endif /* RTEMS_PROFILING */
319
320        /* Call thread dispatcher if necessary */
321#ifdef RTEMS_PROFILING
322        bne     cr2, thread_dispatching_done
323#else /* RTEMS_PROFILING */
324        bne     thread_dispatching_done
325#endif /* RTEMS_PROFILING */
326        bl      _Thread_Dispatch
327thread_dispatching_done:
328
329#ifdef PPC_MULTILIB_ALTIVEC
330        /* Restore volatile AltiVec context */
331        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VSCR_OFFSET
332        lvewx   v0, r1, SCRATCH_0_REGISTER
333        mtvscr  v0
334        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(0)
335        lvx     v0, r1, SCRATCH_0_REGISTER
336        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(1)
337        lvx     v1, r1, SCRATCH_0_REGISTER
338        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(2)
339        lvx     v2, r1, SCRATCH_0_REGISTER
340        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(3)
341        lvx     v3, r1, SCRATCH_0_REGISTER
342        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(4)
343        lvx     v4, r1, SCRATCH_0_REGISTER
344        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(5)
345        lvx     v5, r1, SCRATCH_0_REGISTER
346        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(6)
347        lvx     v6, r1, SCRATCH_0_REGISTER
348        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(7)
349        lvx     v7, r1, SCRATCH_0_REGISTER
350        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(8)
351        lvx     v8, r1, SCRATCH_0_REGISTER
352        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(9)
353        lvx     v9, r1, SCRATCH_0_REGISTER
354        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(10)
355        lvx     v10, r1, SCRATCH_0_REGISTER
356        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(11)
357        lvx     v11, r1, SCRATCH_0_REGISTER
358        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(12)
359        lvx     v12, r1, SCRATCH_0_REGISTER
360        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(13)
361        lvx     v13, r1, SCRATCH_0_REGISTER
362        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(14)
363        lvx     v14, r1, SCRATCH_0_REGISTER
364        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(15)
365        lvx     v15, r1, SCRATCH_0_REGISTER
366        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(16)
367        lvx     v16, r1, SCRATCH_0_REGISTER
368        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(17)
369        lvx     v17, r1, SCRATCH_0_REGISTER
370        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(18)
371        lvx     v18, r1, SCRATCH_0_REGISTER
372        li      SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(19)
373        lvx     v19, r1, SCRATCH_0_REGISTER
374#endif
375
376#ifdef PPC_MULTILIB_FPU
377        /* Restore volatile FPU context */
378        lfd     f0, PPC_EXC_MIN_FPSCR_OFFSET(r1)
379        mtfsf   0xff, f0
380        lfd     f0, PPC_EXC_MIN_FR_OFFSET(0)(r1)
381        lfd     f1, PPC_EXC_MIN_FR_OFFSET(1)(r1)
382        lfd     f2, PPC_EXC_MIN_FR_OFFSET(2)(r1)
383        lfd     f3, PPC_EXC_MIN_FR_OFFSET(3)(r1)
384        lfd     f4, PPC_EXC_MIN_FR_OFFSET(4)(r1)
385        lfd     f5, PPC_EXC_MIN_FR_OFFSET(5)(r1)
386        lfd     f6, PPC_EXC_MIN_FR_OFFSET(6)(r1)
387        lfd     f7, PPC_EXC_MIN_FR_OFFSET(7)(r1)
388        lfd     f8, PPC_EXC_MIN_FR_OFFSET(8)(r1)
389        lfd     f9, PPC_EXC_MIN_FR_OFFSET(9)(r1)
390        lfd     f10, PPC_EXC_MIN_FR_OFFSET(10)(r1)
391        lfd     f11, PPC_EXC_MIN_FR_OFFSET(11)(r1)
392        lfd     f12, PPC_EXC_MIN_FR_OFFSET(12)(r1)
393        lfd     f13, PPC_EXC_MIN_FR_OFFSET(13)(r1)
394#endif
395
396#ifdef __SPE__
397        /* Load SPEFSCR and ACC */
398        lwz     DISPATCH_LEVEL_REGISTER, PPC_EXC_SPEFSCR_OFFSET(r1)
399        evldd   HANDLER_REGISTER, PPC_EXC_ACC_OFFSET(r1)
400#endif
401
402        /*
403         * We must clear reservations here, since otherwise compare-and-swap
404         * atomic operations with interrupts enabled may yield wrong results.
405         * A compare-and-swap atomic operation is generated by the compiler
406         * like this:
407         *
408         *   .L1:
409         *     lwarx  r9, r0, r3
410         *     cmpw   r9, r4
411         *     bne-   .L2
412         *     stwcx. r5, r0, r3
413         *     bne-   .L1
414         *   .L2:
415         *
416         * Consider the following scenario.  A thread is interrupted right
417         * before the stwcx.  The interrupt updates the value using a
418         * compare-and-swap sequence.  Everything is fine up to this point.
419         * The interrupt performs now a compare-and-swap sequence which fails
420         * with a branch to .L2.  The current processor has now a reservation.
421         * The interrupt returns without further stwcx.  The thread updates the
422         * value using the unrelated reservation of the interrupt.
423         */
424        li      SCRATCH_0_REGISTER, FRAME_OFFSET
425        stwcx.  SCRATCH_0_REGISTER, r1, SCRATCH_0_REGISTER
426
427        /* Load SRR0, SRR1, CR, CTR, XER, and LR */
428        lwz     SCRATCH_0_REGISTER, SRR0_FRAME_OFFSET(r1)
429        lwz     SCRATCH_1_REGISTER, SRR1_FRAME_OFFSET(r1)
430        lwz     SCRATCH_2_REGISTER, EXC_CR_OFFSET(r1)
431        lwz     SCRATCH_3_REGISTER, EXC_CTR_OFFSET(r1)
432        lwz     SCRATCH_4_REGISTER, EXC_XER_OFFSET(r1)
433        lwz     SCRATCH_5_REGISTER, EXC_LR_OFFSET(r1)
434
435        PPC_GPR_LOAD    VECTOR_REGISTER, VECTOR_OFFSET(r1)
436        PPC_GPR_LOAD    SELF_CPU_REGISTER, SELF_CPU_OFFSET(r1)
437        PPC_GPR_LOAD    ISR_NEST_REGISTER, ISR_NEST_OFFSET(r1)
438
439#ifdef __SPE__
440        /* Restore SPEFSCR */
441        mtspr   FSL_EIS_SPEFSCR, DISPATCH_LEVEL_REGISTER
442#endif
443        PPC_GPR_LOAD    DISPATCH_LEVEL_REGISTER, DISPATCH_LEVEL_OFFSET(r1)
444
445#ifdef __SPE__
446        /* Restore ACC */
447        evmra   HANDLER_REGISTER, HANDLER_REGISTER
448#endif
449        PPC_GPR_LOAD    HANDLER_REGISTER, HANDLER_OFFSET(r1)
450
451        /* Restore SRR0, SRR1, CR, CTR, XER, and LR */
452        mtsrr0  SCRATCH_0_REGISTER
453        PPC_GPR_LOAD    SCRATCH_0_REGISTER, SCRATCH_0_OFFSET(r1)
454        mtsrr1  SCRATCH_1_REGISTER
455        PPC_GPR_LOAD    SCRATCH_1_REGISTER, SCRATCH_1_OFFSET(r1)
456        mtcr    SCRATCH_2_REGISTER
457        PPC_GPR_LOAD    SCRATCH_2_REGISTER, SCRATCH_2_OFFSET(r1)
458        mtctr   SCRATCH_3_REGISTER
459        PPC_GPR_LOAD    SCRATCH_3_REGISTER, SCRATCH_3_OFFSET(r1)
460        mtxer   SCRATCH_4_REGISTER
461        PPC_GPR_LOAD    SCRATCH_4_REGISTER, SCRATCH_4_OFFSET(r1)
462        mtlr    SCRATCH_5_REGISTER
463        PPC_GPR_LOAD    SCRATCH_5_REGISTER, SCRATCH_5_OFFSET(r1)
464
465#ifdef RTEMS_PROFILING
466        /* Restore ENTRY_INSTANT_REGISTER */
467        lwz     ENTRY_INSTANT_REGISTER, ENTRY_INSTANT_OFFSET(r1)
468#endif /* RTEMS_PROFILING */
469
470        /* Pop stack */
471        addi    r1, r1, PPC_EXC_MINIMAL_FRAME_SIZE
472
473        /* Return */
474        rfi
475
476/* Symbol provided for debugging and tracing */
477ppc_exc_wrap_async_normal_end:
Note: See TracBrowser for help on using the repository browser.