RTEMS  5.1
ppc_exc_asm_macros.h
1 /*
2  * (c) 1999, Eric Valette valette@crf.canon.fr
3  *
4  * Modified and partially rewritten by Till Straumann, 2007-2008
5  *
6  * Modified by Sebastian Huber <sebastian.huber@embedded-brains.de>, 2008-2012.
7  *
8  * Low-level assembly code for PPC exceptions (macros).
9  *
10  * This file was written with the goal to eliminate
11  * ALL #ifdef <cpu_flavor> conditionals -- please do not
12  * reintroduce such statements.
13  */
14 
15 #include <bspopts.h>
16 #include <bsp/vectors.h>
17 #include <libcpu/powerpc-utility.h>
18 
19 #define LT(cr) ((cr)*4+0)
20 #define GT(cr) ((cr)*4+1)
21 #define EQ(cr) ((cr)*4+2)
22 
23 /* Opcode of 'stw r1, off(r13)' */
24 #define STW_R1_R13(off) ((((36<<10)|(r1<<5)|(r13))<<16) | ((off)&0xffff))
25 
26 #define FRAME_REGISTER r14
27 #define VECTOR_REGISTER r4
28 #define SCRATCH_REGISTER_0 r5
29 #define SCRATCH_REGISTER_1 r6
30 #define SCRATCH_REGISTER_2 r7
31 
32 #define FRAME_OFFSET( r) GPR14_OFFSET( r)
33 #define VECTOR_OFFSET( r) GPR4_OFFSET( r)
34 #define SCRATCH_REGISTER_0_OFFSET( r) GPR5_OFFSET( r)
35 #define SCRATCH_REGISTER_1_OFFSET( r) GPR6_OFFSET( r)
36 #define SCRATCH_REGISTER_2_OFFSET( r) GPR7_OFFSET( r)
37 
38 #define CR_TYPE 2
39 #define CR_MSR 3
40 #define CR_LOCK 4
41 
42  /*
43  * Minimal prologue snippets:
44  *
45  * Rationale: on some PPCs the vector offsets are spaced
46  * as closely as 16 bytes.
47  *
48  * If we deal with asynchronous exceptions ('interrupts')
49  * then we can use 4 instructions to
50  * 1. atomically write lock to indicate ISR is in progress
51  * (we cannot atomically increase the Thread_Dispatch_disable_level,
52  * see README)
53  * 2. save a register in special area
54  * 3. load register with vector info
55  * 4. branch
56  *
57  * If we deal with a synchronous exception (no stack switch
58  * nor dispatch-disabling necessary) then it's easier:
59  * 1. push stack frame
60  * 2. save register on stack
61  * 3. load register with vector info
62  * 4. branch
63  *
64  */
65 
66 /*
67  *****************************************************************************
68  * MACRO: PPC_EXC_MIN_PROLOG_ASYNC
69  *****************************************************************************
70  * USES: VECTOR_REGISTER
71  * ON EXIT: Vector in VECTOR_REGISTER
72  *
73  * NOTES: VECTOR_REGISTER saved in special variable
74  * 'ppc_exc_vector_register_\_PRI'.
75  *
76  */
77  .macro PPC_EXC_MIN_PROLOG_ASYNC _NAME _VEC _PRI _FLVR
78 
79  .global ppc_exc_min_prolog_async_\_NAME
80 ppc_exc_min_prolog_async_\_NAME:
81  /* Atomically write lock variable in 1st instruction with non-zero
82  * value (r1 is always nonzero; r13 could also be used)
83  *
84  * NOTE: raising an exception and executing this first instruction
85  * of the exception handler is apparently NOT atomic, i.e., a
86  * low-priority IRQ could set the PC to this location and a
87  * critical IRQ could intervene just at this point.
88  *
89  * We check against this pathological case by checking the
90  * opcode/instruction at the interrupted PC for matching
91  *
92  * stw r1, ppc_exc_lock_XXX@sdarel(r13)
93  *
94  * ASSUMPTION:
95  * 1) ALL 'asynchronous' exceptions (which disable thread-
96  * dispatching) execute THIS 'magical' instruction
97  * FIRST.
98  * 2) This instruction (including the address offset)
99  * is not used anywhere else (probably a safe assumption).
100  */
101  stw r1, ppc_exc_lock_\_PRI@sdarel(r13)
102  /* We have no stack frame yet; store VECTOR_REGISTER in special area;
103  * a higher-priority (critical) interrupt uses a different area
104  * (hence the different prologue snippets) (\PRI)
105  */
106  stw VECTOR_REGISTER, ppc_exc_vector_register_\_PRI@sdarel(r13)
107  /* Load vector.
108  */
109  li VECTOR_REGISTER, ( \_VEC | 0xffff8000 )
110 
111  /*
112  * We store the absolute branch target address here. It will be used
113  * to generate the branch operation in ppc_exc_make_prologue().
114  */
115  .int ppc_exc_wrap_\_FLVR
116 
117  .endm
118 
119 /*
120  *****************************************************************************
121  * MACRO: PPC_EXC_MIN_PROLOG_SYNC
122  *****************************************************************************
123  * USES: VECTOR_REGISTER
124  * ON EXIT: vector in VECTOR_REGISTER
125  *
126  * NOTES: exception stack frame pushed; VECTOR_REGISTER saved in frame
127  *
128  */
129  .macro PPC_EXC_MIN_PROLOG_SYNC _NAME _VEC _PRI _FLVR
130 
131  .global ppc_exc_min_prolog_sync_\_NAME
132 ppc_exc_min_prolog_sync_\_NAME:
133  stwu r1, -EXCEPTION_FRAME_END(r1)
134  stw VECTOR_REGISTER, VECTOR_OFFSET(r1)
135  li VECTOR_REGISTER, \_VEC
136 
137  /*
138  * We store the absolute branch target address here. It will be used
139  * to generate the branch operation in ppc_exc_make_prologue().
140  */
141  .int ppc_exc_wrap_nopush_\_FLVR
142 
143  .endm
144 
145 /*
146  *****************************************************************************
147  * MACRO: TEST_1ST_OPCODE_crit
148  *****************************************************************************
149  *
150  * USES: REG, cr0
151  * ON EXIT: REG available (contains *pc - STW_R1_R13(0)),
152  * return value in cr0.
153  *
154  * test opcode interrupted by critical (asynchronous) exception; set CR_LOCK if
155  *
156  * *SRR0 == 'stw r1, ppc_exc_lock_std@sdarel(r13)'
157  *
158  */
159  .macro TEST_1ST_OPCODE_crit _REG
160 
161  lwz \_REG, SRR0_FRAME_OFFSET(FRAME_REGISTER)
162  lwz \_REG, 0(\_REG)
163  /* opcode now in REG */
164 
165  /* subtract upper 16bits of 'stw r1, 0(r13)' instruction */
166  subis \_REG, \_REG, STW_R1_R13(0)@h
167  /*
168  * if what's left compares against the 'ppc_exc_lock_std@sdarel'
169  * address offset then we have a match...
170  */
171  cmplwi cr0, \_REG, ppc_exc_lock_std@sdarel
172 
173  .endm
174 
175 /*
176  *****************************************************************************
177  * MACRO: TEST_LOCK_std
178  *****************************************************************************
179  *
180  * USES: CR_LOCK
181  * ON EXIT: CR_LOCK is set (indicates no lower-priority locks are engaged)
182  *
183  */
184  .macro TEST_LOCK_std _FLVR
185  /* 'std' is lowest level, i.e., can not be locked -> EQ(CR_LOCK) = 1 */
186  creqv EQ(CR_LOCK), EQ(CR_LOCK), EQ(CR_LOCK)
187  .endm
188 
189 /*
190  ******************************************************************************
191  * MACRO: TEST_LOCK_crit
192  ******************************************************************************
193  *
194  * USES: CR_LOCK, cr0, SCRATCH_REGISTER_0, SCRATCH_REGISTER_1
195  * ON EXIT: cr0, SCRATCH_REGISTER_0, SCRATCH_REGISTER_1 available,
196  * returns result in CR_LOCK.
197  *
198  * critical-exception wrapper has to check 'std' lock:
199  *
200  * Return CR_LOCK = ( (interrupt_mask & MSR_CE) != 0
201  && ppc_lock_std == 0
202  * && * SRR0 != <write std lock instruction> )
203  *
204  */
205  .macro TEST_LOCK_crit _FLVR
206  /* If MSR_CE is not in the IRQ mask then we must never allow
207  * thread-dispatching!
208  */
209  GET_INTERRUPT_MASK mask=SCRATCH_REGISTER_1
210  /* EQ(cr0) = ((interrupt_mask & MSR_CE) == 0) */
211  andis. SCRATCH_REGISTER_1, SCRATCH_REGISTER_1, MSR_CE@h
212  beq TEST_LOCK_crit_done_\_FLVR
213 
214  /* STD interrupt could have been interrupted before executing the 1st
215  * instruction which sets the lock; check this case by looking at the
216  * opcode present at the interrupted PC location.
217  */
218  TEST_1ST_OPCODE_crit _REG=SCRATCH_REGISTER_0
219  /*
220  * At this point cr0 is set if
221  *
222  * *(PC) == 'stw r1, ppc_exc_lock_std@sdarel(r13)'
223  *
224  */
225 
226  /* check lock */
227  lwz SCRATCH_REGISTER_1, ppc_exc_lock_std@sdarel(r13)
228  cmplwi CR_LOCK, SCRATCH_REGISTER_1, 0
229 
230  /* set EQ(CR_LOCK) to result */
231 TEST_LOCK_crit_done_\_FLVR:
232  /* If we end up here because the interrupt mask did not contain
233  * MSR_CE then cr0 is set and therefore the value of CR_LOCK
234  * does not matter since x && !1 == 0:
235  *
236  * if ( (interrupt_mask & MSR_CE) == 0 ) {
237  * EQ(CR_LOCK) = EQ(CR_LOCK) && ! ((interrupt_mask & MSR_CE) == 0)
238  * } else {
239  * EQ(CR_LOCK) = (ppc_exc_lock_std == 0) && ! (*pc == <write std lock instruction>)
240  * }
241  */
242  crandc EQ(CR_LOCK), EQ(CR_LOCK), EQ(cr0)
243 
244  .endm
245 
246 /*
247  ******************************************************************************
248  * MACRO: TEST_LOCK_mchk
249  ******************************************************************************
250  *
251  * USES: CR_LOCK
252  * ON EXIT: CR_LOCK is cleared.
253  *
254  * We never want to disable machine-check exceptions to avoid a checkstop. This
255  * means that we cannot use enabling/disabling this type of exception for
256  * protection of critical OS data structures. Therefore, calling OS primitives
257  * from a machine-check handler is ILLEGAL. Since machine-checks can happen
258  * anytime it is not legal to perform a context switch (since the exception
259  * could hit a IRQ protected section of code). We simply let this test return
260  * 0 so that ppc_exc_wrapup is never called after handling a machine-check.
261  */
262  .macro TEST_LOCK_mchk _SRR0 _FLVR
263 
264  crxor EQ(CR_LOCK), EQ(CR_LOCK), EQ(CR_LOCK)
265 
266  .endm
267 
268 /*
269  ******************************************************************************
270  * MACRO: RECOVER_CHECK_\PRI
271  ******************************************************************************
272  *
273  * USES: cr0, SCRATCH_REGISTER_0, SCRATCH_REGISTER_1
274  * ON EXIT: cr0, SCRATCH_REGISTER_0, SCRATCH_REGISTER_1 available
275  *
276  * Checks if the exception is recoverable for exceptions which need such a
277  * test.
278  */
279 
280 /* Standard*/
281  .macro RECOVER_CHECK_std _FLVR
282 
283 #ifndef PPC_EXC_CONFIG_BOOKE_ONLY
284 
285  /* Check if exception is recoverable */
286  lwz SCRATCH_REGISTER_0, SRR1_FRAME_OFFSET(FRAME_REGISTER)
287  lwz SCRATCH_REGISTER_1, ppc_exc_msr_bits@sdarel(r13)
288  xor SCRATCH_REGISTER_1, SCRATCH_REGISTER_1, SCRATCH_REGISTER_0
289  andi. SCRATCH_REGISTER_0, SCRATCH_REGISTER_1, MSR_RI
290 
291 recover_check_twiddle_std_\_FLVR:
292 
293  /* Not recoverable? */
294  bne recover_check_twiddle_std_\_FLVR
295 
296 #endif /* PPC_EXC_CONFIG_BOOKE_ONLY */
297 
298  .endm
299 
300 /* Critical */
301  .macro RECOVER_CHECK_crit _FLVR
302 
303  /* Nothing to do */
304 
305  .endm
306 
307 /* Machine check */
308  .macro RECOVER_CHECK_mchk _FLVR
309 
310 #ifndef PPC_EXC_CONFIG_BOOKE_ONLY
311 
312  /* Check if exception is recoverable */
313  lwz SCRATCH_REGISTER_0, SRR1_FRAME_OFFSET(FRAME_REGISTER)
314  lwz SCRATCH_REGISTER_1, ppc_exc_msr_bits@sdarel(r13)
315  xor SCRATCH_REGISTER_1, SCRATCH_REGISTER_1, SCRATCH_REGISTER_0
316  andi. SCRATCH_REGISTER_0, SCRATCH_REGISTER_1, MSR_RI
317 
318 recover_check_twiddle_mchk_\_FLVR:
319 
320  /* Not recoverable? */
321  bne recover_check_twiddle_mchk_\_FLVR
322 
323 #endif /* PPC_EXC_CONFIG_BOOKE_ONLY */
324 
325  .endm
326 
327 /*
328  ******************************************************************************
329  * MACRO: WRAP
330  ******************************************************************************
331  *
332  * Minimal prologue snippets jump into WRAP which calls the high level
333  * exception handler. We must have this macro instantiated for each possible
334  * flavor of exception so that we use the proper lock variable, SRR register
335  * pair and RFI instruction.
336  *
337  * We have two types of exceptions: synchronous and asynchronous (= interrupt
338  * like). The type is encoded in the vector register (= VECTOR_REGISTER). For
339  * interrupt like exceptions the MSB in the vector register is set. The
340  * exception type is kept in the comparison register CR_TYPE. Normal
341  * exceptions (MSB is clear) use the task stack and a context switch may happen
342  * at any time. The interrupt like exceptions disable thread dispatching and
343  * switch to the interrupt stack (base address is in SPRG1).
344  *
345  * +
346  * |
347  * | Minimal prologue
348  * |
349  * +
350  * |
351  * | o Setup frame pointer
352  * | o Save basic registers
353  * | o Determine exception type:
354  * | synchronous or asynchronous
355  * |
356  * +-----+
357  * Synchronous exceptions: | | Asynchronous exceptions:
358  * | |
359  * Save non-volatile registers | | o Increment thread dispatch
360  * | | disable level
361  * | | o Increment ISR nest level
362  * | | o Clear lock
363  * | | o Switch stack if necessary
364  * | |
365  * +---->+
366  * |
367  * | o Save volatile registers
368  * | o Change MSR if necessary
369  * | o Call high level handler
370  * | o Call global handler if necessary
371  * | o Check if exception is recoverable
372  * |
373  * +-----+
374  * Synchronous exceptions: | | Asynchronous exceptions:
375  * | |
376  * Restore non-volatile registers | | o Decrement ISR nest level
377  * | | o Switch stack
378  * | | o Decrement thread dispatch
379  * | | disable level
380  * | | o Test lock
381  * | | o May do a context switch
382  * | |
383  * +---->+
384  * |
385  * | o Restore MSR if necessary
386  * | o Restore volatile registers
387  * | o Restore frame pointer
388  * | o Return
389  * |
390  * +
391  */
392  .macro WRAP _FLVR _PRI _SRR0 _SRR1 _RFI
393 
394  .global ppc_exc_wrap_\_FLVR
395 ppc_exc_wrap_\_FLVR:
396 
397  /* Push exception frame */
398  stwu r1, -EXCEPTION_FRAME_END(r1)
399 
400  .global ppc_exc_wrap_nopush_\_FLVR
401 ppc_exc_wrap_nopush_\_FLVR:
402 
403  /* Save frame register */
404  stw FRAME_REGISTER, FRAME_OFFSET(r1)
405 
406 wrap_no_save_frame_register_\_FLVR:
407 
408  /*
409  * We save at first only some scratch registers
410  * and the CR. We use a non-volatile register
411  * for the exception frame pointer (= FRAME_REGISTER).
412  */
413 
414  /* Move frame address in non-volatile FRAME_REGISTER */
415  mr FRAME_REGISTER, r1
416 
417  /* Save scratch registers */
418  stw SCRATCH_REGISTER_0, SCRATCH_REGISTER_0_OFFSET(FRAME_REGISTER)
419  stw SCRATCH_REGISTER_1, SCRATCH_REGISTER_1_OFFSET(FRAME_REGISTER)
420  stw SCRATCH_REGISTER_2, SCRATCH_REGISTER_2_OFFSET(FRAME_REGISTER)
421 
422  /* Save CR */
423  mfcr SCRATCH_REGISTER_0
424  stw SCRATCH_REGISTER_0, EXC_CR_OFFSET(FRAME_REGISTER)
425 
426  /* Check exception type and remember it in non-volatile CR_TYPE */
427  cmpwi CR_TYPE, VECTOR_REGISTER, 0
428 
429 #if defined(PPC_MULTILIB_FPU) || defined(PPC_MULTILIB_ALTIVEC)
430  /* Enable FPU and/or AltiVec */
431  mfmsr SCRATCH_REGISTER_0
432 #ifdef PPC_MULTILIB_FPU
433  ori SCRATCH_REGISTER_0, SCRATCH_REGISTER_0, MSR_FP
434 #endif
435 #ifdef PPC_MULTILIB_ALTIVEC
436  oris SCRATCH_REGISTER_0, SCRATCH_REGISTER_0, MSR_VE >> 16
437 #endif
438  mtmsr SCRATCH_REGISTER_0
439  isync
440 #endif
441 
442  /*
443  * Depending on the exception type we do now save the non-volatile
444  * registers or disable thread dispatching and switch to the ISR stack.
445  */
446 
447  /* Branch for synchronous exceptions */
448  bge CR_TYPE, wrap_save_non_volatile_regs_\_FLVR
449 
450  /*
451  * Increment the thread dispatch disable level in case a higher
452  * priority exception occurs we don't want it to run the scheduler. It
453  * is safe to increment this without disabling higher priority
454  * exceptions since those will see that we wrote the lock anyways.
455  */
456 
457  /* Increment ISR nest level and thread dispatch disable level */
458  GET_SELF_CPU_CONTROL SCRATCH_REGISTER_2
459  lwz SCRATCH_REGISTER_0, PER_CPU_ISR_NEST_LEVEL@l(SCRATCH_REGISTER_2)
460  lwz SCRATCH_REGISTER_1, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SCRATCH_REGISTER_2)
461  addi SCRATCH_REGISTER_0, SCRATCH_REGISTER_0, 1
462  addi SCRATCH_REGISTER_1, SCRATCH_REGISTER_1, 1
463  stw SCRATCH_REGISTER_0, PER_CPU_ISR_NEST_LEVEL@l(SCRATCH_REGISTER_2)
464  stw SCRATCH_REGISTER_1, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SCRATCH_REGISTER_2)
465 
466  /*
467  * No higher-priority exception occurring after this point
468  * can cause a context switch.
469  */
470 
471  /* Clear lock */
472  li SCRATCH_REGISTER_0, 0
473  stw SCRATCH_REGISTER_0, ppc_exc_lock_\_PRI@sdarel(r13)
474 
475  /* Switch stack if necessary */
476  mfspr SCRATCH_REGISTER_0, SPRG1
477  cmpw SCRATCH_REGISTER_0, r1
478  blt wrap_stack_switch_\_FLVR
479  mfspr SCRATCH_REGISTER_1, SPRG2
480  cmpw SCRATCH_REGISTER_1, r1
481  blt wrap_stack_switch_done_\_FLVR
482 
483 wrap_stack_switch_\_FLVR:
484 
485  mr r1, SCRATCH_REGISTER_0
486 
487 wrap_stack_switch_done_\_FLVR:
488 
489  /*
490  * Load the pristine VECTOR_REGISTER from a special location for
491  * asynchronous exceptions. The synchronous exceptions save the
492  * VECTOR_REGISTER in their minimal prologue.
493  */
494  lwz SCRATCH_REGISTER_2, ppc_exc_vector_register_\_PRI@sdarel(r13)
495 
496  /* Save pristine vector register */
497  stw SCRATCH_REGISTER_2, VECTOR_OFFSET(FRAME_REGISTER)
498 
499 wrap_disable_thread_dispatching_done_\_FLVR:
500 
501  /*
502  * We now have SCRATCH_REGISTER_0, SCRATCH_REGISTER_1,
503  * SCRATCH_REGISTER_2 and CR available. VECTOR_REGISTER still holds
504  * the vector (and exception type). FRAME_REGISTER is a pointer to the
505  * exception frame (always on the stack of the interrupted context).
506  * r1 is the stack pointer, either on the task stack or on the ISR
507  * stack. CR_TYPE holds the exception type.
508  */
509 
510  /* Save SRR0 */
511  mfspr SCRATCH_REGISTER_0, \_SRR0
512  stw SCRATCH_REGISTER_0, SRR0_FRAME_OFFSET(FRAME_REGISTER)
513 
514  /* Save SRR1 */
515  mfspr SCRATCH_REGISTER_0, \_SRR1
516  stw SCRATCH_REGISTER_0, SRR1_FRAME_OFFSET(FRAME_REGISTER)
517 
518  /* Save CTR */
519  mfctr SCRATCH_REGISTER_0
520  stw SCRATCH_REGISTER_0, EXC_CTR_OFFSET(FRAME_REGISTER)
521 
522  /* Save XER */
523  mfxer SCRATCH_REGISTER_0
524  stw SCRATCH_REGISTER_0, EXC_XER_OFFSET(FRAME_REGISTER)
525 
526  /* Save LR */
527  mflr SCRATCH_REGISTER_0
528  stw SCRATCH_REGISTER_0, EXC_LR_OFFSET(FRAME_REGISTER)
529 
530  /* Save volatile registers */
531  stw r0, GPR0_OFFSET(FRAME_REGISTER)
532  stw r3, GPR3_OFFSET(FRAME_REGISTER)
533  stw r8, GPR8_OFFSET(FRAME_REGISTER)
534  stw r9, GPR9_OFFSET(FRAME_REGISTER)
535  stw r10, GPR10_OFFSET(FRAME_REGISTER)
536  stw r11, GPR11_OFFSET(FRAME_REGISTER)
537  stw r12, GPR12_OFFSET(FRAME_REGISTER)
538 
539  /* Save read-only small data area anchor (EABI) */
540  stw r2, GPR2_OFFSET(FRAME_REGISTER)
541 
542  /* Save vector number and exception type */
543  stw VECTOR_REGISTER, EXCEPTION_NUMBER_OFFSET(FRAME_REGISTER)
544 
545 #ifndef PPC_EXC_CONFIG_BOOKE_ONLY
546 
547  /* Load MSR bit mask */
548  lwz SCRATCH_REGISTER_0, ppc_exc_msr_bits@sdarel(r13)
549 
550  /*
551  * Change the MSR if necessary (MMU, RI),
552  * remember decision in non-volatile CR_MSR
553  */
554  cmpwi CR_MSR, SCRATCH_REGISTER_0, 0
555  bne CR_MSR, wrap_change_msr_\_FLVR
556 
557 wrap_change_msr_done_\_FLVR:
558 
559 #endif /* PPC_EXC_CONFIG_BOOKE_ONLY */
560 
561 #if defined(__ALTIVEC__) && !defined(PPC_MULTILIB_ALTIVEC)
562  LA SCRATCH_REGISTER_0, _CPU_save_altivec_volatile
563  mtctr SCRATCH_REGISTER_0
564  addi r3, FRAME_REGISTER, EXC_VEC_OFFSET
565  bctrl
566  /*
567  * Establish defaults for vrsave and vscr
568  */
569  li SCRATCH_REGISTER_0, 0
570  mtvrsave SCRATCH_REGISTER_0
571  /*
572  * Use java/c9x mode; clear saturation bit
573  */
574  vxor 0, 0, 0
575  mtvscr 0
576  /*
577  * Reload VECTOR_REGISTER
578  */
579  lwz VECTOR_REGISTER, EXCEPTION_NUMBER_OFFSET(FRAME_REGISTER)
580 #endif
581 
582 #ifdef PPC_MULTILIB_ALTIVEC
583  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(0)
584  stvx v0, FRAME_REGISTER, SCRATCH_REGISTER_0
585  mfvscr v0
586  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(1)
587  stvx v1, FRAME_REGISTER, SCRATCH_REGISTER_0
588  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(2)
589  stvx v2, FRAME_REGISTER, SCRATCH_REGISTER_0
590  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(3)
591  stvx v3, FRAME_REGISTER, SCRATCH_REGISTER_0
592  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(4)
593  stvx v4, FRAME_REGISTER, SCRATCH_REGISTER_0
594  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(5)
595  stvx v5, FRAME_REGISTER, SCRATCH_REGISTER_0
596  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(6)
597  stvx v6, FRAME_REGISTER, SCRATCH_REGISTER_0
598  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(7)
599  stvx v7, FRAME_REGISTER, SCRATCH_REGISTER_0
600  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(8)
601  stvx v8, FRAME_REGISTER, SCRATCH_REGISTER_0
602  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(9)
603  stvx v9, FRAME_REGISTER, SCRATCH_REGISTER_0
604  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(0)
605  stvx v10, FRAME_REGISTER, SCRATCH_REGISTER_0
606  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(11)
607  stvx v11, FRAME_REGISTER, SCRATCH_REGISTER_0
608  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(12)
609  stvx v12, FRAME_REGISTER, SCRATCH_REGISTER_0
610  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(13)
611  stvx v13, FRAME_REGISTER, SCRATCH_REGISTER_0
612  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(14)
613  stvx v14, FRAME_REGISTER, SCRATCH_REGISTER_0
614  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(15)
615  stvx v15, FRAME_REGISTER, SCRATCH_REGISTER_0
616  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(16)
617  stvx v16, FRAME_REGISTER, SCRATCH_REGISTER_0
618  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(17)
619  stvx v17, FRAME_REGISTER, SCRATCH_REGISTER_0
620  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(18)
621  stvx v18, FRAME_REGISTER, SCRATCH_REGISTER_0
622  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(19)
623  stvx v19, FRAME_REGISTER, SCRATCH_REGISTER_0
624  li SCRATCH_REGISTER_0, PPC_EXC_VSCR_OFFSET
625  stvewx v0, r1, SCRATCH_REGISTER_0
626 #endif
627 
628 #ifdef PPC_MULTILIB_FPU
629  stfd f0, PPC_EXC_FR_OFFSET(0)(FRAME_REGISTER)
630  mffs f0
631  stfd f1, PPC_EXC_FR_OFFSET(1)(FRAME_REGISTER)
632  stfd f2, PPC_EXC_FR_OFFSET(2)(FRAME_REGISTER)
633  stfd f3, PPC_EXC_FR_OFFSET(3)(FRAME_REGISTER)
634  stfd f4, PPC_EXC_FR_OFFSET(4)(FRAME_REGISTER)
635  stfd f5, PPC_EXC_FR_OFFSET(5)(FRAME_REGISTER)
636  stfd f6, PPC_EXC_FR_OFFSET(6)(FRAME_REGISTER)
637  stfd f7, PPC_EXC_FR_OFFSET(7)(FRAME_REGISTER)
638  stfd f8, PPC_EXC_FR_OFFSET(8)(FRAME_REGISTER)
639  stfd f9, PPC_EXC_FR_OFFSET(9)(FRAME_REGISTER)
640  stfd f10, PPC_EXC_FR_OFFSET(10)(FRAME_REGISTER)
641  stfd f11, PPC_EXC_FR_OFFSET(11)(FRAME_REGISTER)
642  stfd f12, PPC_EXC_FR_OFFSET(12)(FRAME_REGISTER)
643  stfd f13, PPC_EXC_FR_OFFSET(13)(FRAME_REGISTER)
644  stfd f0, PPC_EXC_FPSCR_OFFSET(FRAME_REGISTER)
645 #endif
646 
647  /*
648  * Call high level exception handler
649  */
650 
651  /*
652  * Get the handler table index from the vector number. We have to
653  * discard the exception type. Take only the least significant five
654  * bits (= LAST_VALID_EXC + 1) from the vector register. Multiply by
655  * four (= size of function pointer).
656  */
657  rlwinm SCRATCH_REGISTER_1, VECTOR_REGISTER, 2, 25, 29
658 
659  /* Load handler table address */
660  LA SCRATCH_REGISTER_0, ppc_exc_handler_table
661 
662  /* Load handler address */
663  lwzx SCRATCH_REGISTER_0, SCRATCH_REGISTER_0, SCRATCH_REGISTER_1
664 
665  /*
666  * First parameter = exception frame pointer + FRAME_LINK_SPACE
667  *
668  * We add FRAME_LINK_SPACE to the frame pointer because the high level
669  * handler expects a BSP_Exception_frame structure.
670  */
671  addi r3, FRAME_REGISTER, FRAME_LINK_SPACE
672 
673  /*
674  * Second parameter = vector number (r4 is the VECTOR_REGISTER)
675  *
676  * Discard the exception type and store the vector number
677  * in the vector register. Take only the least significant
678  * five bits (= LAST_VALID_EXC + 1).
679  */
680  rlwinm VECTOR_REGISTER, VECTOR_REGISTER, 0, 27, 31
681 
682  /* Call handler */
683  mtctr SCRATCH_REGISTER_0
684  bctrl
685 
686  /* Check return value and call global handler if necessary */
687  cmpwi r3, 0
688  bne wrap_call_global_handler_\_FLVR
689 
690 wrap_handler_done_\_FLVR:
691 
692  /* Check if exception is recoverable */
693  RECOVER_CHECK_\_PRI _FLVR=\_FLVR
694 
695  /*
696  * Depending on the exception type we do now restore the non-volatile
697  * registers or enable thread dispatching and switch back from the ISR
698  * stack.
699  */
700 
701  /* Branch for synchronous exceptions */
702  bge CR_TYPE, wrap_restore_non_volatile_regs_\_FLVR
703 
704  /*
705  * Switch back to original stack (FRAME_REGISTER == r1 if we are still
706  * on the IRQ stack).
707  */
708  mr r1, FRAME_REGISTER
709 
710  /*
711  * Check thread dispatch disable level AND lower priority locks (in
712  * CR_LOCK): ONLY if the thread dispatch disable level == 0 AND no lock
713  * is set then call ppc_exc_wrapup() which may do a context switch. We
714  * can skip TEST_LOCK, because it has no side effects.
715  */
716 
717  /* Decrement ISR nest level and thread dispatch disable level */
718  GET_SELF_CPU_CONTROL SCRATCH_REGISTER_2
719  lwz SCRATCH_REGISTER_0, PER_CPU_ISR_NEST_LEVEL@l(SCRATCH_REGISTER_2)
720  lwz SCRATCH_REGISTER_1, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SCRATCH_REGISTER_2)
721  subi SCRATCH_REGISTER_0, SCRATCH_REGISTER_0, 1
722  subic. SCRATCH_REGISTER_1, SCRATCH_REGISTER_1, 1
723  stw SCRATCH_REGISTER_0, PER_CPU_ISR_NEST_LEVEL@l(SCRATCH_REGISTER_2)
724  stw SCRATCH_REGISTER_1, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SCRATCH_REGISTER_2)
725 
726  /* Branch to skip thread dispatching */
727  bne wrap_thread_dispatching_done_\_FLVR
728 
729  /* Test lower-priority locks (result in non-volatile CR_LOCK) */
730  TEST_LOCK_\_PRI _FLVR=\_FLVR
731 
732  /* Branch to skip thread dispatching */
733  bne CR_LOCK, wrap_thread_dispatching_done_\_FLVR
734 
735  /* Load address of ppc_exc_wrapup() */
736  LA SCRATCH_REGISTER_0, ppc_exc_wrapup
737 
738  /* First parameter = exception frame pointer + FRAME_LINK_SPACE */
739  addi r3, FRAME_REGISTER, FRAME_LINK_SPACE
740 
741  /* Call ppc_exc_wrapup() */
742  mtctr SCRATCH_REGISTER_0
743  bctrl
744 
745 wrap_thread_dispatching_done_\_FLVR:
746 
747 #if defined(__ALTIVEC__) && !defined(PPC_MULTILIB_ALTIVEC)
748  LA SCRATCH_REGISTER_0, _CPU_load_altivec_volatile
749  mtctr SCRATCH_REGISTER_0
750  addi r3, FRAME_REGISTER, EXC_VEC_OFFSET
751  bctrl
752 #endif
753 
754 #ifdef PPC_MULTILIB_ALTIVEC
755  li SCRATCH_REGISTER_0, PPC_EXC_MIN_VSCR_OFFSET
756  lvewx v0, r1, SCRATCH_REGISTER_0
757  mtvscr v0
758  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(0)
759  lvx v0, FRAME_REGISTER, SCRATCH_REGISTER_0
760  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(1)
761  lvx v1, FRAME_REGISTER, SCRATCH_REGISTER_0
762  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(2)
763  lvx v2, FRAME_REGISTER, SCRATCH_REGISTER_0
764  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(3)
765  lvx v3, FRAME_REGISTER, SCRATCH_REGISTER_0
766  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(4)
767  lvx v4, FRAME_REGISTER, SCRATCH_REGISTER_0
768  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(5)
769  lvx v5, FRAME_REGISTER, SCRATCH_REGISTER_0
770  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(6)
771  lvx v6, FRAME_REGISTER, SCRATCH_REGISTER_0
772  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(7)
773  lvx v7, FRAME_REGISTER, SCRATCH_REGISTER_0
774  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(8)
775  lvx v8, FRAME_REGISTER, SCRATCH_REGISTER_0
776  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(9)
777  lvx v9, FRAME_REGISTER, SCRATCH_REGISTER_0
778  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(0)
779  lvx v10, FRAME_REGISTER, SCRATCH_REGISTER_0
780  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(11)
781  lvx v11, FRAME_REGISTER, SCRATCH_REGISTER_0
782  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(12)
783  lvx v12, FRAME_REGISTER, SCRATCH_REGISTER_0
784  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(13)
785  lvx v13, FRAME_REGISTER, SCRATCH_REGISTER_0
786  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(14)
787  lvx v14, FRAME_REGISTER, SCRATCH_REGISTER_0
788  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(15)
789  lvx v15, FRAME_REGISTER, SCRATCH_REGISTER_0
790  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(16)
791  lvx v16, FRAME_REGISTER, SCRATCH_REGISTER_0
792  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(17)
793  lvx v17, FRAME_REGISTER, SCRATCH_REGISTER_0
794  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(18)
795  lvx v18, FRAME_REGISTER, SCRATCH_REGISTER_0
796  li SCRATCH_REGISTER_0, PPC_EXC_VR_OFFSET(19)
797  lvx v19, FRAME_REGISTER, SCRATCH_REGISTER_0
798 #endif
799 
800 #ifdef PPC_MULTILIB_FPU
801  lfd f0, PPC_EXC_FPSCR_OFFSET(FRAME_REGISTER)
802  mtfsf 0xff, f0
803  lfd f0, PPC_EXC_FR_OFFSET(0)(FRAME_REGISTER)
804  lfd f1, PPC_EXC_FR_OFFSET(1)(FRAME_REGISTER)
805  lfd f2, PPC_EXC_FR_OFFSET(2)(FRAME_REGISTER)
806  lfd f3, PPC_EXC_FR_OFFSET(3)(FRAME_REGISTER)
807  lfd f4, PPC_EXC_FR_OFFSET(4)(FRAME_REGISTER)
808  lfd f5, PPC_EXC_FR_OFFSET(5)(FRAME_REGISTER)
809  lfd f6, PPC_EXC_FR_OFFSET(6)(FRAME_REGISTER)
810  lfd f7, PPC_EXC_FR_OFFSET(7)(FRAME_REGISTER)
811  lfd f8, PPC_EXC_FR_OFFSET(8)(FRAME_REGISTER)
812  lfd f9, PPC_EXC_FR_OFFSET(9)(FRAME_REGISTER)
813  lfd f10, PPC_EXC_FR_OFFSET(10)(FRAME_REGISTER)
814  lfd f11, PPC_EXC_FR_OFFSET(11)(FRAME_REGISTER)
815  lfd f12, PPC_EXC_FR_OFFSET(12)(FRAME_REGISTER)
816  lfd f13, PPC_EXC_FR_OFFSET(13)(FRAME_REGISTER)
817 #endif
818 
819 #ifndef PPC_EXC_CONFIG_BOOKE_ONLY
820 
821  /* Restore MSR? */
822  bne CR_MSR, wrap_restore_msr_\_FLVR
823 
824 wrap_restore_msr_done_\_FLVR:
825 
826 #endif /* PPC_EXC_CONFIG_BOOKE_ONLY */
827 
828  /*
829  * At this point r1 is a valid exception frame pointer and
830  * FRAME_REGISTER is no longer needed.
831  */
832 
833  /* Restore frame register */
834  lwz FRAME_REGISTER, FRAME_OFFSET(r1)
835 
836  /* Restore XER and CTR */
837  lwz SCRATCH_REGISTER_0, EXC_XER_OFFSET(r1)
838  lwz SCRATCH_REGISTER_1, EXC_CTR_OFFSET(r1)
839  mtxer SCRATCH_REGISTER_0
840  mtctr SCRATCH_REGISTER_1
841 
842  /* Restore CR and LR */
843  lwz SCRATCH_REGISTER_0, EXC_CR_OFFSET(r1)
844  lwz SCRATCH_REGISTER_1, EXC_LR_OFFSET(r1)
845  mtcr SCRATCH_REGISTER_0
846  mtlr SCRATCH_REGISTER_1
847 
848  /* Restore volatile registers */
849  lwz r0, GPR0_OFFSET(r1)
850  lwz r3, GPR3_OFFSET(r1)
851  lwz r8, GPR8_OFFSET(r1)
852  lwz r9, GPR9_OFFSET(r1)
853  lwz r10, GPR10_OFFSET(r1)
854  lwz r11, GPR11_OFFSET(r1)
855  lwz r12, GPR12_OFFSET(r1)
856 
857  /* Restore read-only small data area anchor (EABI) */
858  lwz r2, GPR2_OFFSET(r1)
859 
860  /* Restore vector register */
861  lwz VECTOR_REGISTER, VECTOR_OFFSET(r1)
862 
863  /*
864  * Disable all asynchronous exceptions which can do a thread dispatch.
865  * See README.
866  */
867  INTERRUPT_DISABLE SCRATCH_REGISTER_1, SCRATCH_REGISTER_0
868 
869  /* Restore scratch registers and SRRs */
870  lwz SCRATCH_REGISTER_0, SRR0_FRAME_OFFSET(r1)
871  lwz SCRATCH_REGISTER_1, SRR1_FRAME_OFFSET(r1)
872  lwz SCRATCH_REGISTER_2, SCRATCH_REGISTER_2_OFFSET(r1)
873  mtspr \_SRR0, SCRATCH_REGISTER_0
874  lwz SCRATCH_REGISTER_0, SCRATCH_REGISTER_0_OFFSET(r1)
875  mtspr \_SRR1, SCRATCH_REGISTER_1
876  lwz SCRATCH_REGISTER_1, SCRATCH_REGISTER_1_OFFSET(r1)
877 
878  /*
879  * We restore r1 from the frame rather than just popping (adding to
880  * current r1) since the exception handler might have done strange
881  * things (e.g. a debugger moving and relocating the stack).
882  */
883  lwz r1, 0(r1)
884 
885  /* Return */
886  \_RFI
887 
888 #ifndef PPC_EXC_CONFIG_BOOKE_ONLY
889 
890 wrap_change_msr_\_FLVR:
891 
892  mfmsr SCRATCH_REGISTER_1
893  or SCRATCH_REGISTER_1, SCRATCH_REGISTER_1, SCRATCH_REGISTER_0
894  mtmsr SCRATCH_REGISTER_1
895  msync
896  isync
897  b wrap_change_msr_done_\_FLVR
898 
899 wrap_restore_msr_\_FLVR:
900 
901  lwz SCRATCH_REGISTER_0, ppc_exc_msr_bits@sdarel(r13)
902  mfmsr SCRATCH_REGISTER_1
903  andc SCRATCH_REGISTER_1, SCRATCH_REGISTER_1, SCRATCH_REGISTER_0
904  mtmsr SCRATCH_REGISTER_1
905  msync
906  isync
907  b wrap_restore_msr_done_\_FLVR
908 
909 #endif /* PPC_EXC_CONFIG_BOOKE_ONLY */
910 
911 wrap_save_non_volatile_regs_\_FLVR:
912 
913  /* Load pristine stack pointer */
914  lwz SCRATCH_REGISTER_1, 0(FRAME_REGISTER)
915 
916  /* Save small data area anchor (SYSV) */
917  stw r13, GPR13_OFFSET(FRAME_REGISTER)
918 
919  /* Save pristine stack pointer */
920  stw SCRATCH_REGISTER_1, GPR1_OFFSET(FRAME_REGISTER)
921 
922  /* r14 is the FRAME_REGISTER and will be saved elsewhere */
923 
924  /* Save non-volatile registers r15 .. r31 */
925 #ifndef __SPE__
926  stmw r15, GPR15_OFFSET(FRAME_REGISTER)
927 #else
928  stw r15, GPR15_OFFSET(FRAME_REGISTER)
929  stw r16, GPR16_OFFSET(FRAME_REGISTER)
930  stw r17, GPR17_OFFSET(FRAME_REGISTER)
931  stw r18, GPR18_OFFSET(FRAME_REGISTER)
932  stw r19, GPR19_OFFSET(FRAME_REGISTER)
933  stw r20, GPR20_OFFSET(FRAME_REGISTER)
934  stw r21, GPR21_OFFSET(FRAME_REGISTER)
935  stw r22, GPR22_OFFSET(FRAME_REGISTER)
936  stw r23, GPR23_OFFSET(FRAME_REGISTER)
937  stw r24, GPR24_OFFSET(FRAME_REGISTER)
938  stw r25, GPR25_OFFSET(FRAME_REGISTER)
939  stw r26, GPR26_OFFSET(FRAME_REGISTER)
940  stw r27, GPR27_OFFSET(FRAME_REGISTER)
941  stw r28, GPR28_OFFSET(FRAME_REGISTER)
942  stw r29, GPR29_OFFSET(FRAME_REGISTER)
943  stw r30, GPR30_OFFSET(FRAME_REGISTER)
944  stw r31, GPR31_OFFSET(FRAME_REGISTER)
945 #endif
946 
947 #ifdef PPC_MULTILIB_ALTIVEC
948  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(20)
949  stvx v20, FRAME_REGISTER, SCRATCH_REGISTER_1
950  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(21)
951  stvx v21, FRAME_REGISTER, SCRATCH_REGISTER_1
952  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(22)
953  stvx v22, FRAME_REGISTER, SCRATCH_REGISTER_1
954  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(23)
955  stvx v23, FRAME_REGISTER, SCRATCH_REGISTER_1
956  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(24)
957  stvx v24, FRAME_REGISTER, SCRATCH_REGISTER_1
958  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(25)
959  stvx v25, FRAME_REGISTER, SCRATCH_REGISTER_1
960  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(26)
961  stvx v26, FRAME_REGISTER, SCRATCH_REGISTER_1
962  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(27)
963  stvx v27, FRAME_REGISTER, SCRATCH_REGISTER_1
964  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(28)
965  stvx v28, FRAME_REGISTER, SCRATCH_REGISTER_1
966  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(29)
967  stvx v29, FRAME_REGISTER, SCRATCH_REGISTER_1
968  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(30)
969  stvx v30, FRAME_REGISTER, SCRATCH_REGISTER_1
970  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(31)
971  stvx v31, FRAME_REGISTER, SCRATCH_REGISTER_1
972  mfvrsave SCRATCH_REGISTER_1
973  stw SCRATCH_REGISTER_1, PPC_EXC_VRSAVE_OFFSET(FRAME_REGISTER)
974 #endif
975 
976 #ifdef PPC_MULTILIB_FPU
977  stfd f14, PPC_EXC_FR_OFFSET(14)(FRAME_REGISTER)
978  stfd f15, PPC_EXC_FR_OFFSET(15)(FRAME_REGISTER)
979  stfd f16, PPC_EXC_FR_OFFSET(16)(FRAME_REGISTER)
980  stfd f17, PPC_EXC_FR_OFFSET(17)(FRAME_REGISTER)
981  stfd f18, PPC_EXC_FR_OFFSET(18)(FRAME_REGISTER)
982  stfd f19, PPC_EXC_FR_OFFSET(19)(FRAME_REGISTER)
983  stfd f20, PPC_EXC_FR_OFFSET(20)(FRAME_REGISTER)
984  stfd f21, PPC_EXC_FR_OFFSET(21)(FRAME_REGISTER)
985  stfd f22, PPC_EXC_FR_OFFSET(22)(FRAME_REGISTER)
986  stfd f23, PPC_EXC_FR_OFFSET(23)(FRAME_REGISTER)
987  stfd f24, PPC_EXC_FR_OFFSET(24)(FRAME_REGISTER)
988  stfd f25, PPC_EXC_FR_OFFSET(25)(FRAME_REGISTER)
989  stfd f26, PPC_EXC_FR_OFFSET(26)(FRAME_REGISTER)
990  stfd f27, PPC_EXC_FR_OFFSET(27)(FRAME_REGISTER)
991  stfd f28, PPC_EXC_FR_OFFSET(28)(FRAME_REGISTER)
992  stfd f29, PPC_EXC_FR_OFFSET(29)(FRAME_REGISTER)
993  stfd f30, PPC_EXC_FR_OFFSET(30)(FRAME_REGISTER)
994  stfd f31, PPC_EXC_FR_OFFSET(31)(FRAME_REGISTER)
995 #endif
996 
997  b wrap_disable_thread_dispatching_done_\_FLVR
998 
999 wrap_restore_non_volatile_regs_\_FLVR:
1000 
1001  /* Load stack pointer */
1002  lwz SCRATCH_REGISTER_0, GPR1_OFFSET(r1)
1003 
1004  /* Restore small data area anchor (SYSV) */
1005  lwz r13, GPR13_OFFSET(r1)
1006 
1007  /* r14 is the FRAME_REGISTER and will be restored elsewhere */
1008 
1009  /* Restore non-volatile registers r15 .. r31 */
1010 #ifndef __SPE__
1011  lmw r15, GPR15_OFFSET(r1)
1012 #else
1013  lwz r15, GPR15_OFFSET(FRAME_REGISTER)
1014  lwz r16, GPR16_OFFSET(FRAME_REGISTER)
1015  lwz r17, GPR17_OFFSET(FRAME_REGISTER)
1016  lwz r18, GPR18_OFFSET(FRAME_REGISTER)
1017  lwz r19, GPR19_OFFSET(FRAME_REGISTER)
1018  lwz r20, GPR20_OFFSET(FRAME_REGISTER)
1019  lwz r21, GPR21_OFFSET(FRAME_REGISTER)
1020  lwz r22, GPR22_OFFSET(FRAME_REGISTER)
1021  lwz r23, GPR23_OFFSET(FRAME_REGISTER)
1022  lwz r24, GPR24_OFFSET(FRAME_REGISTER)
1023  lwz r25, GPR25_OFFSET(FRAME_REGISTER)
1024  lwz r26, GPR26_OFFSET(FRAME_REGISTER)
1025  lwz r27, GPR27_OFFSET(FRAME_REGISTER)
1026  lwz r28, GPR28_OFFSET(FRAME_REGISTER)
1027  lwz r29, GPR29_OFFSET(FRAME_REGISTER)
1028  lwz r30, GPR30_OFFSET(FRAME_REGISTER)
1029  lwz r31, GPR31_OFFSET(FRAME_REGISTER)
1030 #endif
1031 
1032  /* Restore stack pointer */
1033  stw SCRATCH_REGISTER_0, 0(r1)
1034 
1035 #ifdef PPC_MULTILIB_ALTIVEC
1036  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(20)
1037  lvx v20, FRAME_REGISTER, SCRATCH_REGISTER_1
1038  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(21)
1039  lvx v21, FRAME_REGISTER, SCRATCH_REGISTER_1
1040  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(22)
1041  lvx v22, FRAME_REGISTER, SCRATCH_REGISTER_1
1042  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(23)
1043  lvx v23, FRAME_REGISTER, SCRATCH_REGISTER_1
1044  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(24)
1045  lvx v24, FRAME_REGISTER, SCRATCH_REGISTER_1
1046  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(25)
1047  lvx v25, FRAME_REGISTER, SCRATCH_REGISTER_1
1048  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(26)
1049  lvx v26, FRAME_REGISTER, SCRATCH_REGISTER_1
1050  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(27)
1051  lvx v27, FRAME_REGISTER, SCRATCH_REGISTER_1
1052  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(28)
1053  lvx v28, FRAME_REGISTER, SCRATCH_REGISTER_1
1054  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(29)
1055  lvx v29, FRAME_REGISTER, SCRATCH_REGISTER_1
1056  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(30)
1057  lvx v30, FRAME_REGISTER, SCRATCH_REGISTER_1
1058  li SCRATCH_REGISTER_1, PPC_EXC_VR_OFFSET(31)
1059  lvx v31, FRAME_REGISTER, SCRATCH_REGISTER_1
1060  lwz SCRATCH_REGISTER_1, PPC_EXC_VRSAVE_OFFSET(FRAME_REGISTER)
1061  mtvrsave SCRATCH_REGISTER_1
1062 #endif
1063 
1064 #ifdef PPC_MULTILIB_FPU
1065  lfd f14, PPC_EXC_FR_OFFSET(14)(FRAME_REGISTER)
1066  lfd f15, PPC_EXC_FR_OFFSET(15)(FRAME_REGISTER)
1067  lfd f16, PPC_EXC_FR_OFFSET(16)(FRAME_REGISTER)
1068  lfd f17, PPC_EXC_FR_OFFSET(17)(FRAME_REGISTER)
1069  lfd f18, PPC_EXC_FR_OFFSET(18)(FRAME_REGISTER)
1070  lfd f19, PPC_EXC_FR_OFFSET(19)(FRAME_REGISTER)
1071  lfd f20, PPC_EXC_FR_OFFSET(20)(FRAME_REGISTER)
1072  lfd f21, PPC_EXC_FR_OFFSET(21)(FRAME_REGISTER)
1073  lfd f22, PPC_EXC_FR_OFFSET(22)(FRAME_REGISTER)
1074  lfd f23, PPC_EXC_FR_OFFSET(23)(FRAME_REGISTER)
1075  lfd f24, PPC_EXC_FR_OFFSET(24)(FRAME_REGISTER)
1076  lfd f25, PPC_EXC_FR_OFFSET(25)(FRAME_REGISTER)
1077  lfd f26, PPC_EXC_FR_OFFSET(26)(FRAME_REGISTER)
1078  lfd f27, PPC_EXC_FR_OFFSET(27)(FRAME_REGISTER)
1079  lfd f28, PPC_EXC_FR_OFFSET(28)(FRAME_REGISTER)
1080  lfd f29, PPC_EXC_FR_OFFSET(29)(FRAME_REGISTER)
1081  lfd f30, PPC_EXC_FR_OFFSET(30)(FRAME_REGISTER)
1082  lfd f31, PPC_EXC_FR_OFFSET(31)(FRAME_REGISTER)
1083 #endif
1084 
1085  b wrap_thread_dispatching_done_\_FLVR
1086 
1087 wrap_call_global_handler_\_FLVR:
1088 
1089  /* First parameter = exception frame pointer + FRAME_LINK_SPACE */
1090  addi r3, FRAME_REGISTER, FRAME_LINK_SPACE
1091 
1092 #ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
1093 
1094  /* Load global handler address */
1095  LW SCRATCH_REGISTER_0, globalExceptHdl
1096 
1097  /* Check address */
1098  cmpwi SCRATCH_REGISTER_0, 0
1099  beq wrap_handler_done_\_FLVR
1100 
1101  /* Call global handler */
1102  mtctr SCRATCH_REGISTER_0
1103  bctrl
1104 
1105 #else /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
1106 
1107  /* Call fixed global handler */
1109 
1110 #endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
1111 
1112  b wrap_handler_done_\_FLVR
1113 
1114  .endm
exception_handler_t globalExceptHdl
Global exception handler.
Definition: ppc_exc_hdl.c:52
PowerPC Exceptions API.
General purpose assembler macros, linker command file support and some inline functions for direct re...
uint32_t ppc_exc_msr_bits
Bits for MSR update.
Definition: ppc_exc_hdl.c:41
void C_exception_handler(BSP_Exception_frame *excPtr)
Default global exception handler.
Definition: ppc_exc_global_handler.c:22
ppc_exc_handler_t ppc_exc_handler_table[LAST_VALID_EXC+1]
High-level exception handler table.
Definition: ppc_exc_hdl.c:55
unsigned l
Definition: tte.h:86