1 /* Overlay manager for SPU.
3 Copyright 2006, 2007 Free Software Foundation, Inc.
5 This file is part of GLD, the Gnu Linker.
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)
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.
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
25 #define MFC_GET_CMD 0x40
26 #define MFC_MAX_DMA_SIZE 0x4000
27 #define MFC_TAG_UPDATE_ALL 2
32 * Temporary register allocations.
33 * These are saved/restored here.
77 .extern _ovly_buf_table
81 .type __rv_pattern, @object
82 .size __rv_pattern, 16
84 .word 0x00010203, 0x1c1d1e1f, 0x00010203, 0x10111213
85 .type __cg_pattern, @object
86 .size __cg_pattern, 16
88 .word 0x04050607, 0x80808080, 0x80808080, 0x80808080
91 * __ovly_return - stub for returning from overlay functions.
97 * $78 old partition number, to be reloaded
98 * $79 return address in old partion number
100 .global __ovly_return
101 .type __ovly_return, @function
108 .size __ovly_return, . - __ovly_return
111 * __ovly_load - copy an overlay partion to local store.
114 * $78 partition number to be loaded.
115 * $79 branch target in new partition.
116 * $lr link register, containing return addr.
119 * $lr new link register, returning through __ovly_return.
121 * Copy a new overlay partition into local store, or return
122 * immediately if the partition is already resident.
125 .type __ovly_load, @function
128 /* Save temporary registers to stack. */
134 /* Save irq state, then disable interrupts. */
136 ila irqtmp, __ovly_irq_save
137 rdch irq_stat, $SPU_RdMachStat
142 /* Set branch hint to overlay target. */
143 hbr __ovly_load_ret, $79
145 /* Get caller's overlay index by back chaining through stack frames.
146 * Loop until end of stack (back chain all-zeros) or
147 * encountered a link register we set here. */
149 ila retval, __ovly_return
151 __ovly_backchain_loop:
154 ceq cmp, lnkr, retval
157 brz cmp, __ovly_backchain_loop
159 /* If we reached the zero back-chain, then lnkr is bogus. Clear the
160 * part of lnkr that we use later (slot 3). */
161 rotqbyi cmp2, cmp2, 4
162 andc lnkr, lnkr, cmp2
164 /* Set lr = {__ovly_return, prev ovl ndx, caller return adr, callee ovl ndx}. */
165 lqd rv1, (__rv_pattern-__ovly_return+4)(retval)
166 shufb rv2, retval, lnkr, rv1
167 shufb rv3, $lr, $78, rv1
169 selb $lr, rv2, rv3, rv1
171 /* Branch to $79 if non-overlay */
172 brz $78, __ovly_load_restore
174 /* Load values from _ovly_table[$78].
183 ila tab, _ovly_table - 16
187 /* Load values from _ovly_buf_table[buf].
190 * } _ovly_buf_table[];
192 ila tab, _ovly_buf_table
198 /* Branch to $79 now if overlay is already mapped. */
200 brnz cmp, __ovly_load_restore
202 /* Marker for profiling code. If we get here, we are about to load
205 .global __ovly_load_event
206 .type __ovly_load_event, @function
209 /* Set _ovly_buf_table[buf].mapped = $78. */
211 shufb map, $78, map, genwi
214 /* A new partition needs to be loaded. Prepare for DMA loop.
215 * _EAR_ is the 64b base EA, filled in at run time by the
216 * loader, and indicating the value for SPU executable image start.
218 lqd cgshuf, (__cg_pattern-__ovly_return+4)(retval)
219 rotqbyi osize, vma, 4
224 /* 64b add to compute next ea64. */
225 rotqmbyi off64, sz, -4
226 cg cgbits, ea64, off64
227 shufb add64, cgbits, cgbits, cgshuf
228 addx add64, ea64, off64
231 /* Setup DMA parameters, then issue DMA request. */
232 rotqbyi ealo, add64, 4
233 ila maxsize, MFC_MAX_DMA_SIZE
234 cgt cmp, osize, maxsize
235 selb sz, osize, maxsize, cmp
236 ila tagid, MFC_TAG_ID
241 wrch $MFC_TagId, tagid
245 /* Increment vma, decrement size, branch back as needed. */
248 brnz osize, __ovly_xfer_loop
250 /* Save app's tagmask, wait for DMA complete, restore mask. */
251 rdch oldmask, $MFC_RdTagMask
253 ilh newmask, 1 << MFC_TAG_ID
255 ilhu newmask, 1 << (MFC_TAG_ID - 16)
257 wrch $MFC_WrTagMask, newmask
258 ila tagstat, MFC_TAG_UPDATE_ALL
259 wrch $MFC_WrTagUpdate, tagstat
260 rdch tagstat, $MFC_RdTagStat
262 wrch $MFC_WrTagMask, oldmask
264 .global _ovly_debug_event
265 .type _ovly_debug_event, @function
267 /* GDB inserts debugger trap here. */
272 /* Conditionally re-enable interrupts. */
273 andi irq_stat, irq_stat, 1
274 ila irqtmp, __ovly_irq_restore
275 binze irq_stat, irqtmp
280 /* Restore saved registers. */
286 /* Branch to target address. */
289 .size __ovly_load, . - __ovly_load