1 | /* |
---|
2 | * (c) 1999, Eric Valette valette@crf.canon.fr |
---|
3 | * |
---|
4 | * Modified and partially rewritten by Till Straumann, 2007 |
---|
5 | * |
---|
6 | * Modified by Sebastian Huber <sebastian.huber@embedded-brains.de>, 2008. |
---|
7 | * |
---|
8 | * Low-level assembly code for PPC exceptions. |
---|
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 | /* Load macro definitions */ |
---|
16 | #include "ppc_exc_asm_macros.h" |
---|
17 | |
---|
18 | /******************************************************/ |
---|
19 | /* PROLOGUES */ |
---|
20 | /******************************************************/ |
---|
21 | |
---|
22 | /* |
---|
23 | * Expand prologue snippets for classic, ppc405-critical, bookE-critical |
---|
24 | * and E500 machine-check, synchronous and asynchronous exceptions |
---|
25 | */ |
---|
26 | PPC_EXC_MIN_PROLOG_SYNC _NAME=tmpl_std _VEC=0 _PRI=std _FLVR=std |
---|
27 | PPC_EXC_MIN_PROLOG_SYNC _NAME=tmpl_p405_crit _VEC=0 _PRI=crit _FLVR=p405_crit |
---|
28 | PPC_EXC_MIN_PROLOG_SYNC _NAME=tmpl_bookE_crit _VEC=0 _PRI=crit _FLVR=bookE_crit |
---|
29 | PPC_EXC_MIN_PROLOG_SYNC _NAME=tmpl_e500_mchk _VEC=0 _PRI=mchk _FLVR=e500_mchk |
---|
30 | |
---|
31 | PPC_EXC_MIN_PROLOG_ASYNC _NAME=tmpl_std _VEC=0 _PRI=std _FLVR=std |
---|
32 | PPC_EXC_MIN_PROLOG_ASYNC _NAME=tmpl_p405_crit _VEC=0 _PRI=crit _FLVR=p405_crit |
---|
33 | PPC_EXC_MIN_PROLOG_ASYNC _NAME=tmpl_bookE_crit _VEC=0 _PRI=crit _FLVR=bookE_crit |
---|
34 | PPC_EXC_MIN_PROLOG_ASYNC _NAME=tmpl_e500_mchk _VEC=0 _PRI=mchk _FLVR=e500_mchk |
---|
35 | |
---|
36 | .global ppc_exc_min_prolog_size |
---|
37 | ppc_exc_min_prolog_size = 4 * 4 |
---|
38 | |
---|
39 | /* Special prologue for 603e-style CPUs. |
---|
40 | * |
---|
41 | * 603e shadows GPR0..GPR3 for certain exceptions. We must switch |
---|
42 | * that off before we can use the stack pointer. Note that this is |
---|
43 | * ONLY safe if the shadowing is actually active -- otherwise, r1 |
---|
44 | * is destroyed. We deliberately use r1 so problems become obvious |
---|
45 | * if this is misused! |
---|
46 | */ |
---|
47 | .global ppc_exc_tgpr_clr_prolog |
---|
48 | ppc_exc_tgpr_clr_prolog: |
---|
49 | mfmsr r1 |
---|
50 | rlwinm r1,r1,0,15,13 |
---|
51 | mtmsr r1 |
---|
52 | isync |
---|
53 | /* FALL THRU TO 'auto' PROLOG */ |
---|
54 | |
---|
55 | /* Determine vector dynamically/automatically |
---|
56 | * |
---|
57 | * BUT: - only standard exceptions (no critical ones) |
---|
58 | * - vector offset must be on 256 Byte boundary. |
---|
59 | */ |
---|
60 | .global ppc_exc_min_prolog_auto |
---|
61 | ppc_exc_min_prolog_auto: |
---|
62 | stwu r1, -EXCEPTION_FRAME_END(r1) |
---|
63 | stw VECTOR_REGISTER, VECTOR_OFFSET(r1) |
---|
64 | mflr VECTOR_REGISTER |
---|
65 | bla wrap_auto |
---|
66 | |
---|
67 | .global ppc_exc_tgpr_clr_prolog_size |
---|
68 | ppc_exc_tgpr_clr_prolog_size = . - ppc_exc_tgpr_clr_prolog |
---|
69 | |
---|
70 | /** |
---|
71 | * @brief Use vector offsets with 16 byte boundaries. |
---|
72 | * |
---|
73 | * @see ppc_exc_min_prolog_auto(); |
---|
74 | */ |
---|
75 | .global ppc_exc_min_prolog_auto_packed |
---|
76 | ppc_exc_min_prolog_auto_packed: |
---|
77 | stwu r1, -EXCEPTION_FRAME_END(r1) |
---|
78 | stw VECTOR_REGISTER, VECTOR_OFFSET(r1) |
---|
79 | mflr VECTOR_REGISTER |
---|
80 | bla wrap_auto_packed |
---|
81 | |
---|
82 | /* |
---|
83 | * Automatic vector, asynchronous exception; however, |
---|
84 | * automatic vector calculation is less efficient than |
---|
85 | * using an explicit vector in a minimal prolog snippet. |
---|
86 | * The latter method is preferable since there usually |
---|
87 | * are few asynchronous exceptions. |
---|
88 | * |
---|
89 | * For generic exceptions (which are the bulk) using |
---|
90 | * the 'auto' prologue is OK since performance is not |
---|
91 | * really an issue. |
---|
92 | */ |
---|
93 | .global ppc_exc_min_prolog_auto_async |
---|
94 | ppc_exc_min_prolog_auto_async: |
---|
95 | stw r1, ppc_exc_lock_std@sdarel(r13) |
---|
96 | stw VECTOR_REGISTER, ppc_exc_vector_register_std@sdarel(r13) |
---|
97 | mflr VECTOR_REGISTER |
---|
98 | bla wrap_auto_async |
---|
99 | |
---|
100 | /******************************************************/ |
---|
101 | /* WRAPPERS */ |
---|
102 | /******************************************************/ |
---|
103 | |
---|
104 | /* Tag start and end of the wrappers. |
---|
105 | * If exceptions are installed farther removed |
---|
106 | * from the text area than 32M then the wrappers |
---|
107 | * must be moved to an area that is reachable |
---|
108 | * from where the prologues reside. Branches into |
---|
109 | * C-code are far. |
---|
110 | */ |
---|
111 | |
---|
112 | .global __ppc_exc_wrappers_start |
---|
113 | __ppc_exc_wrappers_start = . |
---|
114 | |
---|
115 | /* Expand wrappers for different exception flavors */ |
---|
116 | |
---|
117 | /* Standard/classic powerpc */ |
---|
118 | WRAP _FLVR=std _PRI=std _SRR0=srr0 _SRR1=srr1 _RFI=rfi |
---|
119 | |
---|
120 | /* ppc405 has a critical exception using srr2/srr3 */ |
---|
121 | WRAP _FLVR=p405_crit _PRI=crit _SRR0=srr2 _SRR1=srr3 _RFI=rfci |
---|
122 | |
---|
123 | /* bookE has critical exception using csrr0 cssr1 */ |
---|
124 | WRAP _FLVR=bookE_crit _PRI=crit _SRR0=csrr0 _SRR1=csrr1 _RFI=rfci |
---|
125 | |
---|
126 | /* e500 has machine-check exception using mcsrr0 mcssr1 */ |
---|
127 | WRAP _FLVR=e500_mchk _PRI=mchk _SRR0=mcsrr0 _SRR1=mcsrr1 _RFI=rfmci |
---|
128 | |
---|
129 | /* LR holds vector, VECTOR_REGISTER holds orig. LR */ |
---|
130 | wrap_auto: |
---|
131 | stw FRAME_REGISTER, FRAME_OFFSET(r1) |
---|
132 | |
---|
133 | /* Find address where we jumped from */ |
---|
134 | mflr FRAME_REGISTER |
---|
135 | |
---|
136 | /* Restore LR */ |
---|
137 | mtlr VECTOR_REGISTER |
---|
138 | |
---|
139 | /* Compute vector into R3 */ |
---|
140 | rlwinm VECTOR_REGISTER, FRAME_REGISTER, 24, 26, 31 |
---|
141 | |
---|
142 | /* |
---|
143 | * We're now in almost the same state as if called by |
---|
144 | * min_prolog_std but we must skip saving FRAME_REGISTER |
---|
145 | * since that's done already |
---|
146 | */ |
---|
147 | b wrap_no_save_frame_register_std |
---|
148 | |
---|
149 | /* See: wrap_auto */ |
---|
150 | wrap_auto_packed: |
---|
151 | stw FRAME_REGISTER, FRAME_OFFSET(r1) |
---|
152 | mflr FRAME_REGISTER |
---|
153 | mtlr VECTOR_REGISTER |
---|
154 | rlwinm VECTOR_REGISTER, FRAME_REGISTER, 28, 26, 31 |
---|
155 | b wrap_no_save_frame_register_std |
---|
156 | |
---|
157 | wrap_auto_async: |
---|
158 | stwu r1, -EXCEPTION_FRAME_END(r1) |
---|
159 | stw FRAME_REGISTER, FRAME_OFFSET(r1) |
---|
160 | /* find address where we jumped from */ |
---|
161 | mflr FRAME_REGISTER |
---|
162 | /* restore LR */ |
---|
163 | mtlr VECTOR_REGISTER |
---|
164 | /* set upper bits to indicate that non-volatile |
---|
165 | * registers should not be saved/restored. |
---|
166 | */ |
---|
167 | li VECTOR_REGISTER, 0xffff8000 |
---|
168 | /* compute vector into R3 */ |
---|
169 | rlwimi VECTOR_REGISTER, FRAME_REGISTER, 24, 26, 31 |
---|
170 | /* we're now in almost the same state as if called by |
---|
171 | * min_prolog_std but we must skip saving FRAME_REGISTER |
---|
172 | * since that's done already |
---|
173 | */ |
---|
174 | b wrap_no_save_frame_register_std |
---|
175 | |
---|
176 | .global __ppc_exc_wrappers_end |
---|
177 | __ppc_exc_wrappers_end = . |
---|