53d82a41e7cb859492c610b820572fda003cb89f
[deliverable/binutils-gdb.git] / ld / emultempl / spu_ovl.S
1 /* Overlay manager for SPU.
2
3 Copyright 2006, 2007 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
65 #define osize $7
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
104 .size __ovly_return, . - __ovly_return
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
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
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)
215 rotqbyi osize, vma, 4
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
230 cgt cmp, osize, maxsize
231 selb sz, osize, maxsize, cmp
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
243 sf osize, sz, osize
244 brnz osize, __ovly_xfer_loop
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
284
285 .size __ovly_load, . - __ovly_load
This page took 0.05807 seconds and 4 git commands to generate.