Commit | Line | Data |
---|---|---|
e9f53129 AM |
1 | /* Overlay manager for SPU. |
2 | ||
3 | Copyright 2006 Free Software Foundation, Inc. | |
4 | ||
5 | This file is part of GLD, the Gnu Linker. | |
6 | ||
7 | GLD is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GLD is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GLD; see the file COPYING. If not, write to the Free | |
19 | Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA | |
20 | 02110-1301, USA. */ | |
21 | ||
22 | /** | |
23 | * MFC DMA defn's. | |
24 | */ | |
25 | #define MFC_GET_CMD 0x40 | |
26 | #define MFC_MAX_DMA_SIZE 0x4000 | |
27 | #define MFC_TAG_UPDATE_ALL 2 | |
28 | #define MFC_TAG_ID 0 | |
29 | ||
30 | ||
31 | /** | |
32 | * Temporary register allocations. | |
33 | * These are saved/restored here. | |
34 | */ | |
35 | #define tab $75 | |
36 | #define cgbits $75 | |
37 | #define add64 $75 | |
38 | #define ealo $75 | |
39 | #define newmask $75 | |
40 | #define tagstat $75 | |
41 | #define bchn $75 | |
42 | #define rv1 $75 | |
43 | ||
44 | #define off $76 | |
45 | #define off64 $76 | |
46 | #define maxsize $76 | |
47 | #define oldmask $76 | |
48 | #define sz $76 | |
49 | #define lnkr $76 | |
50 | #define rv2 $76 | |
51 | ||
52 | #define cur $77 | |
53 | #define cmp $77 | |
54 | #define buf $77 | |
55 | #define genwi $77 | |
56 | #define tagid $77 | |
57 | #define cmd $77 | |
58 | #define rv3 $77 | |
59 | ||
60 | #define cgshuf $78 | |
61 | ||
62 | #define vma $6 | |
63 | ||
64 | #define map $7 | |
b1e37473 | 65 | #define osize $7 |
e9f53129 AM |
66 | #define cmp2 $7 |
67 | ||
68 | #define ea64 $8 | |
69 | #define retval $8 | |
70 | ||
71 | #ifdef OVLY_IRQ_SAVE | |
72 | #define irqtmp $8 | |
73 | #define irq_stat $9 | |
74 | #endif | |
75 | ||
76 | .extern _ovly_table | |
77 | .extern _ovly_buf_table | |
78 | ||
79 | .text | |
80 | .align 4 | |
81 | __rv_pattern: | |
82 | .word 0x00010203, 0x1c1d1e1f, 0x00010203, 0x10111213 | |
83 | __cg_pattern: | |
84 | .word 0x04050607, 0x80808080, 0x80808080, 0x80808080 | |
85 | ||
86 | /** | |
87 | * __ovly_return - stub for returning from overlay functions. | |
88 | * | |
89 | * inputs: | |
90 | * $lr link register | |
91 | * | |
92 | * outputs: | |
93 | * $78 old partition number, to be reloaded | |
94 | * $79 return address in old partion number | |
95 | */ | |
96 | .global __ovly_return | |
97 | .type __ovly_return, @function | |
98 | ||
99 | .word 0 | |
100 | __ovly_return: | |
101 | shlqbyi $78, $lr, 4 | |
102 | shlqbyi $79, $lr, 8 | |
103 | biz $78, $79 | |
b1e37473 | 104 | .size __ovly_return, . - __ovly_return |
e9f53129 AM |
105 | |
106 | /** | |
107 | * __ovly_load - copy an overlay partion to local store. | |
108 | * | |
109 | * inputs: | |
110 | * $78 partition number to be loaded. | |
111 | * $79 branch target in new partition. | |
112 | * $lr link register, containing return addr. | |
113 | * | |
114 | * outputs: | |
115 | * $lr new link register, returning through __ovly_return. | |
116 | * | |
117 | * Copy a new overlay partition into local store, or return | |
118 | * immediately if the partition is already resident. | |
119 | */ | |
120 | .global __ovly_load | |
121 | .type __ovly_load, @function | |
122 | ||
123 | __ovly_load: | |
124 | /* Save temporary registers to stack. */ | |
125 | stqd $6, -16($sp) | |
126 | stqd $7, -32($sp) | |
127 | stqd $8, -48($sp) | |
128 | ||
129 | #ifdef OVLY_IRQ_SAVE | |
130 | /* Save irq state, then disable interrupts. */ | |
131 | stqd $9, -64($sp) | |
132 | ila irqtmp, __ovly_irq_save | |
133 | rdch irq_stat, $SPU_RdMachStat | |
134 | bid irqtmp | |
135 | __ovly_irq_save: | |
136 | #endif | |
137 | ||
138 | /* Set branch hint to overlay target. */ | |
139 | hbr __ovly_load_ret, $79 | |
140 | ||
141 | /* Get caller's overlay index by back chaining through stack frames. | |
142 | * Loop until end of stack (back chain all-zeros) or | |
143 | * encountered a link register we set here. */ | |
144 | lqd bchn, 0($sp) | |
145 | ila retval, __ovly_return | |
146 | ||
147 | __ovly_backchain_loop: | |
148 | lqd lnkr, 16(bchn) | |
149 | lqd bchn, 0(bchn) | |
150 | ceq cmp, lnkr, retval | |
151 | ceqi cmp2, bchn, 0 | |
152 | or cmp, cmp, cmp2 | |
153 | brz cmp, __ovly_backchain_loop | |
154 | ||
155 | /* If we reached the zero back-chain, then lnkr is bogus. Clear the | |
156 | * part of lnkr that we use later (slot 3). */ | |
157 | rotqbyi cmp2, cmp2, 4 | |
158 | andc lnkr, lnkr, cmp2 | |
159 | ||
160 | /* Set lr = {__ovly_return, prev ovl ndx, caller return adr, callee ovl ndx}. */ | |
161 | lqd rv1, (__rv_pattern-__ovly_return+4)(retval) | |
162 | shufb rv2, retval, lnkr, rv1 | |
163 | shufb rv3, $lr, $78, rv1 | |
164 | fsmbi rv1, 0xff | |
165 | selb $lr, rv2, rv3, rv1 | |
166 | ||
167 | /* Branch to $79 if non-overlay */ | |
168 | brz $78, __ovly_load_restore | |
169 | ||
170 | /* Load values from _ovly_table[$78]. | |
171 | * extern struct { | |
172 | * u32 vma; | |
173 | * u32 size; | |
174 | * u32 file_offset; | |
175 | * u32 buf; | |
176 | * } _ovly_table[]; | |
177 | */ | |
178 | shli off, $78, 4 | |
179 | ila tab, _ovly_table - 16 | |
180 | lqx vma, tab, off | |
181 | rotqbyi buf, vma, 12 | |
182 | ||
183 | /* Load values from _ovly_buf_table[buf]. | |
184 | * extern struct { | |
185 | * u32 mapped; | |
186 | * } _ovly_buf_table[]; | |
187 | */ | |
188 | ila tab, _ovly_buf_table | |
189 | ai off, buf, -1 | |
190 | shli off, off, 2 | |
191 | lqx map, tab, off | |
192 | rotqby cur, map, off | |
193 | ||
194 | /* Branch to $79 now if overlay is already mapped. */ | |
195 | ceq cmp, $78, cur | |
196 | brnz cmp, __ovly_load_restore | |
197 | ||
b1e37473 AM |
198 | /* Marker for profiling code. If we get here, we are about to load |
199 | * a new overlay. | |
200 | */ | |
201 | .global __ovly_load_event | |
202 | .type __ovly_load_event, @function | |
203 | __ovly_load_event: | |
204 | ||
e9f53129 AM |
205 | /* Set _ovly_buf_table[buf].mapped = $78. */ |
206 | cwx genwi, tab, off | |
207 | shufb map, $78, map, genwi | |
208 | stqx map, tab, off | |
209 | ||
210 | /* A new partition needs to be loaded. Prepare for DMA loop. | |
211 | * _EAR_ is the 64b base EA, filled in at run time by the | |
212 | * loader, and indicating the value for SPU executable image start. | |
213 | */ | |
214 | lqd cgshuf, (__cg_pattern-__ovly_return+4)(retval) | |
b1e37473 | 215 | rotqbyi osize, vma, 4 |
e9f53129 AM |
216 | rotqbyi sz, vma, 8 |
217 | lqa ea64, _EAR_ | |
218 | ||
219 | __ovly_xfer_loop: | |
220 | /* 64b add to compute next ea64. */ | |
221 | rotqmbyi off64, sz, -4 | |
222 | cg cgbits, ea64, off64 | |
223 | shufb add64, cgbits, cgbits, cgshuf | |
224 | addx add64, ea64, off64 | |
225 | ori ea64, add64, 0 | |
226 | ||
227 | /* Setup DMA parameters, then issue DMA request. */ | |
228 | rotqbyi ealo, add64, 4 | |
229 | ila maxsize, MFC_MAX_DMA_SIZE | |
b1e37473 AM |
230 | cgt cmp, osize, maxsize |
231 | selb sz, osize, maxsize, cmp | |
e9f53129 AM |
232 | ila tagid, MFC_TAG_ID |
233 | wrch $MFC_LSA, vma | |
234 | wrch $MFC_EAH, ea64 | |
235 | wrch $MFC_EAL, ealo | |
236 | wrch $MFC_Size, sz | |
237 | wrch $MFC_TagId, tagid | |
238 | ila cmd, MFC_GET_CMD | |
239 | wrch $MFC_Cmd, cmd | |
240 | ||
241 | /* Increment vma, decrement size, branch back as needed. */ | |
242 | a vma, vma, sz | |
b1e37473 AM |
243 | sf osize, sz, osize |
244 | brnz osize, __ovly_xfer_loop | |
e9f53129 AM |
245 | |
246 | /* Save app's tagmask, wait for DMA complete, restore mask. */ | |
247 | rdch oldmask, $MFC_RdTagMask | |
248 | #if MFC_TAG_ID < 16 | |
249 | ilh newmask, 1 << MFC_TAG_ID | |
250 | #else | |
251 | ilhu newmask, 1 << (MFC_TAG_ID - 16) | |
252 | #endif | |
253 | wrch $MFC_WrTagMask, newmask | |
254 | ila tagstat, MFC_TAG_UPDATE_ALL | |
255 | wrch $MFC_WrTagUpdate, tagstat | |
256 | rdch tagstat, $MFC_RdTagStat | |
257 | sync | |
258 | wrch $MFC_WrTagMask, oldmask | |
259 | ||
260 | .global _ovly_debug_event | |
261 | .type _ovly_debug_event, @function | |
262 | _ovly_debug_event: | |
263 | /* GDB inserts debugger trap here. */ | |
264 | nop | |
265 | ||
266 | __ovly_load_restore: | |
267 | #ifdef OVLY_IRQ_SAVE | |
268 | /* Conditionally re-enable interrupts. */ | |
269 | andi irq_stat, irq_stat, 1 | |
270 | ila irqtmp, __ovly_irq_restore | |
271 | binze irq_stat, irqtmp | |
272 | __ovly_irq_restore: | |
273 | lqd $9, -64($sp) | |
274 | #endif | |
275 | ||
276 | /* Restore saved registers. */ | |
277 | lqd $8, -48($sp) | |
278 | lqd $7, -32($sp) | |
279 | lqd $6, -16($sp) | |
280 | ||
281 | __ovly_load_ret: | |
282 | /* Branch to target address. */ | |
283 | bi $79 | |
b1e37473 AM |
284 | |
285 | .size __ovly_load, . - __ovly_load |