RTEMS 5.2
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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>
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
80ppc_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
132ppc_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 */
231TEST_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
291recover_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
318recover_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
395ppc_exc_wrap_\_FLVR:
396
397 /* Push exception frame */
398 stwu r1, -EXCEPTION_FRAME_END(r1)
399
400 .global ppc_exc_wrap_nopush_\_FLVR
401ppc_exc_wrap_nopush_\_FLVR:
402
403 /* Save frame register */
404 stw FRAME_REGISTER, FRAME_OFFSET(r1)
405
406wrap_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
483wrap_stack_switch_\_FLVR:
484
485 mr r1, SCRATCH_REGISTER_0
486
487wrap_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
499wrap_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
557wrap_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
690wrap_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
745wrap_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
824wrap_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
890wrap_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
899wrap_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
911wrap_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
999wrap_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
1087wrap_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
PowerPC Exceptions API.
ppc_exc_handler_t ppc_exc_handler_table[LAST_VALID_EXC+1]
High-level exception handler table.
Definition: ppc_exc_hdl.c:55
void C_exception_handler(BSP_Exception_frame *excPtr)
Default global exception handler.
Definition: ppc_exc_global_handler.c:22
exception_handler_t globalExceptHdl
Global exception handler.
Definition: ppc_exc_hdl.c:52
uint32_t ppc_exc_msr_bits
Bits for MSR update.
Definition: ppc_exc_hdl.c:41
General purpose assembler macros, linker command file support and some inline functions for direct re...
unsigned l
Definition: tte.h:13