ovlymgr.c revision 1.1.1.1 1 1.1 christos
2 1.1 christos /*
3 1.1 christos * Ovlymgr.c -- Runtime Overlay Manager for the GDB testsuite.
4 1.1 christos */
5 1.1 christos
6 1.1 christos #include "ovlymgr.h"
7 1.1 christos
8 1.1 christos #ifdef __SPU__
9 1.1 christos /* SPU tool chain provides its own overlay manager. */
10 1.1 christos bool
11 1.1 christos OverlayLoad (unsigned long ovlyno)
12 1.1 christos {
13 1.1 christos }
14 1.1 christos bool
15 1.1 christos OverlayUnload (unsigned long ovlyno)
16 1.1 christos {
17 1.1 christos }
18 1.1 christos #else /* __SPU__ */
19 1.1 christos
20 1.1 christos /* Local functions and data: */
21 1.1 christos
22 1.1 christos extern unsigned long _ovly_table[][4];
23 1.1 christos extern unsigned long _novlys __attribute__ ((section (".data")));
24 1.1 christos enum ovly_index { VMA, SIZE, LMA, MAPPED};
25 1.1 christos
26 1.1 christos static void ovly_copy (unsigned long dst, unsigned long src, long size);
27 1.1 christos
28 1.1 christos /* Flush the data and instruction caches at address START for SIZE bytes.
29 1.1 christos Support for each new port must be added here. */
30 1.1 christos /* FIXME: Might be better to have a standard libgloss function that
31 1.1 christos ports provide that we can then use. Use libgloss instead of newlib
32 1.1 christos since libgloss is the one intended to handle low level system issues.
33 1.1 christos I would suggest something like _flush_cache to avoid the user's namespace
34 1.1 christos but not be completely obscure as other things may need this facility. */
35 1.1 christos
36 1.1 christos static void
37 1.1 christos FlushCache (void)
38 1.1 christos {
39 1.1 christos #ifdef __M32R__
40 1.1 christos volatile char *mspr = (char *) 0xfffffff7;
41 1.1 christos *mspr = 1;
42 1.1 christos #endif
43 1.1 christos }
44 1.1 christos
45 1.1 christos /* _ovly_debug_event:
46 1.1 christos * Debuggers may set a breakpoint here, to be notified
47 1.1 christos * when the overlay table has been modified.
48 1.1 christos */
49 1.1 christos static void
50 1.1 christos _ovly_debug_event (void)
51 1.1 christos {
52 1.1 christos }
53 1.1 christos
54 1.1 christos /* OverlayLoad:
55 1.1 christos * Copy the overlay into its runtime region,
56 1.1 christos * and mark the overlay as "mapped".
57 1.1 christos */
58 1.1 christos
59 1.1 christos bool
60 1.1 christos OverlayLoad (unsigned long ovlyno)
61 1.1 christos {
62 1.1 christos unsigned long i;
63 1.1 christos
64 1.1 christos if (ovlyno < 0 || ovlyno >= _novlys)
65 1.1 christos exit (-1); /* fail, bad ovly number */
66 1.1 christos
67 1.1 christos if (_ovly_table[ovlyno][MAPPED])
68 1.1 christos return TRUE; /* this overlay already mapped -- nothing to do! */
69 1.1 christos
70 1.1 christos for (i = 0; i < _novlys; i++)
71 1.1 christos if (i == ovlyno)
72 1.1 christos _ovly_table[i][MAPPED] = 1; /* this one now mapped */
73 1.1 christos else if (_ovly_table[i][VMA] == _ovly_table[ovlyno][VMA])
74 1.1 christos _ovly_table[i][MAPPED] = 0; /* this one now un-mapped */
75 1.1 christos
76 1.1 christos ovly_copy (_ovly_table[ovlyno][VMA],
77 1.1 christos _ovly_table[ovlyno][LMA],
78 1.1 christos _ovly_table[ovlyno][SIZE]);
79 1.1 christos
80 1.1 christos FlushCache ();
81 1.1 christos _ovly_debug_event ();
82 1.1 christos return TRUE;
83 1.1 christos }
84 1.1 christos
85 1.1 christos /* OverlayUnload:
86 1.1 christos * Copy the overlay back into its "load" region.
87 1.1 christos * Does NOT mark overlay as "unmapped", therefore may be called
88 1.1 christos * more than once for the same mapped overlay.
89 1.1 christos */
90 1.1 christos
91 1.1 christos bool
92 1.1 christos OverlayUnload (unsigned long ovlyno)
93 1.1 christos {
94 1.1 christos if (ovlyno < 0 || ovlyno >= _novlys)
95 1.1 christos exit (-1); /* fail, bad ovly number */
96 1.1 christos
97 1.1 christos if (!_ovly_table[ovlyno][MAPPED])
98 1.1 christos exit (-1); /* error, can't copy out a segment that's not "in" */
99 1.1 christos
100 1.1 christos ovly_copy (_ovly_table[ovlyno][LMA],
101 1.1 christos _ovly_table[ovlyno][VMA],
102 1.1 christos _ovly_table[ovlyno][SIZE]);
103 1.1 christos
104 1.1 christos _ovly_debug_event ();
105 1.1 christos return TRUE;
106 1.1 christos }
107 1.1 christos
108 1.1 christos #ifdef __D10V__
109 1.1 christos #define IMAP0 (*(short *)(0xff00))
110 1.1 christos #define IMAP1 (*(short *)(0xff02))
111 1.1 christos #define DMAP (*(short *)(0xff04))
112 1.1 christos
113 1.1 christos static void
114 1.1 christos D10VTranslate (unsigned long logical,
115 1.1 christos short *dmap,
116 1.1 christos unsigned long **addr)
117 1.1 christos {
118 1.1 christos unsigned long physical;
119 1.1 christos unsigned long seg;
120 1.1 christos unsigned long off;
121 1.1 christos
122 1.1 christos /* to access data, we use the following mapping
123 1.1 christos 0x00xxxxxx: Logical data address segment (DMAP translated memory)
124 1.1 christos 0x01xxxxxx: Logical instruction address segment (IMAP translated memory)
125 1.1 christos 0x10xxxxxx: Physical data memory segment (On-chip data memory)
126 1.1 christos 0x11xxxxxx: Physical instruction memory segment (On-chip insn memory)
127 1.1 christos 0x12xxxxxx: Phisical unified memory segment (Unified memory)
128 1.1 christos */
129 1.1 christos
130 1.1 christos /* Addresses must be correctly aligned */
131 1.1 christos if (logical & (sizeof (**addr) - 1))
132 1.1 christos exit (-1);
133 1.1 christos
134 1.1 christos /* If the address is in one of the two logical address spaces, it is
135 1.1 christos first translated into a physical address */
136 1.1 christos seg = (logical >> 24);
137 1.1 christos off = (logical & 0xffffffL);
138 1.1 christos switch (seg)
139 1.1 christos {
140 1.1 christos case 0x00: /* in logical data address segment */
141 1.1 christos if (off <= 0x7fffL)
142 1.1 christos physical = (0x10L << 24) + off;
143 1.1 christos else
144 1.1 christos /* Logical address out side of on-chip segment, not
145 1.1 christos supported */
146 1.1 christos exit (-1);
147 1.1 christos break;
148 1.1 christos case 0x01: /* in logical instruction address segment */
149 1.1 christos {
150 1.1 christos short map;
151 1.1 christos if (off <= 0x1ffffL)
152 1.1 christos map = IMAP0;
153 1.1 christos else if (off <= 0x3ffffL)
154 1.1 christos map = IMAP1;
155 1.1 christos else
156 1.1 christos /* Logical address outside of IMAP[01] segment, not
157 1.1 christos supported */
158 1.1 christos exit (-1);
159 1.1 christos if (map & 0x1000L)
160 1.1 christos {
161 1.1 christos /* Instruction memory */
162 1.1 christos physical = (0x11L << 24) | off;
163 1.1 christos }
164 1.1 christos else
165 1.1 christos {
166 1.1 christos /* Unified memory */
167 1.1 christos physical = ((map & 0x7fL) << 17) + (off & 0x1ffffL);
168 1.1 christos if (physical > 0xffffffL)
169 1.1 christos /* Address outside of unified address segment */
170 1.1 christos exit (-1);
171 1.1 christos physical |= (0x12L << 24);
172 1.1 christos }
173 1.1 christos break;
174 1.1 christos }
175 1.1 christos case 0x10:
176 1.1 christos case 0x11:
177 1.1 christos case 0x12:
178 1.1 christos physical = logical;
179 1.1 christos break;
180 1.1 christos default:
181 1.1 christos exit (-1); /* error */
182 1.1 christos }
183 1.1 christos
184 1.1 christos seg = (physical >> 24);
185 1.1 christos off = (physical & 0xffffffL);
186 1.1 christos switch (seg)
187 1.1 christos {
188 1.1 christos case 0x10: /* dst is a 15 bit offset into the on-chip memory */
189 1.1 christos *dmap = 0;
190 1.1 christos *addr = (long *) (0x0000 + ((short)off & 0x7fff));
191 1.1 christos break;
192 1.1 christos case 0x11: /* dst is an 18-bit offset into the on-chip
193 1.1 christos instruction memory */
194 1.1 christos *dmap = 0x1000L | ((off & 0x3ffffL) >> 14);
195 1.1 christos *addr = (long *) (0x8000 + ((short)off & 0x3fff));
196 1.1 christos break;
197 1.1 christos case 0x12: /* dst is a 24-bit offset into unified memory */
198 1.1 christos *dmap = off >> 14;
199 1.1 christos *addr = (long *) (0x8000 + ((short)off & 0x3fff));
200 1.1 christos break;
201 1.1 christos default:
202 1.1 christos exit (-1); /* error */
203 1.1 christos }
204 1.1 christos }
205 1.1 christos #endif /* __D10V__ */
206 1.1 christos
207 1.1 christos static void
208 1.1 christos ovly_copy (unsigned long dst, unsigned long src, long size)
209 1.1 christos {
210 1.1 christos #ifdef __D10V__
211 1.1 christos unsigned long *s, *d, tmp;
212 1.1 christos short dmap_src, dmap_dst;
213 1.1 christos short dmap_save;
214 1.1 christos
215 1.1 christos /* all section sizes should by multiples of 4 bytes */
216 1.1 christos dmap_save = DMAP;
217 1.1 christos
218 1.1 christos D10VTranslate (src, &dmap_src, &s);
219 1.1 christos D10VTranslate (dst, &dmap_dst, &d);
220 1.1 christos
221 1.1 christos while (size > 0)
222 1.1 christos {
223 1.1 christos /* NB: Transfer 4 byte (long) quantites, problems occure
224 1.1 christos when only two bytes are transfered */
225 1.1 christos DMAP = dmap_src;
226 1.1 christos tmp = *s;
227 1.1 christos DMAP = dmap_dst;
228 1.1 christos *d = tmp;
229 1.1 christos d++;
230 1.1 christos s++;
231 1.1 christos size -= sizeof (tmp);
232 1.1 christos src += sizeof (tmp);
233 1.1 christos dst += sizeof (tmp);
234 1.1 christos if ((src & 0x3fff) == 0)
235 1.1 christos D10VTranslate (src, &dmap_src, &s);
236 1.1 christos if ((dst & 0x3fff) == 0)
237 1.1 christos D10VTranslate (dst, &dmap_dst, &d);
238 1.1 christos }
239 1.1 christos DMAP = dmap_save;
240 1.1 christos #else
241 1.1 christos memcpy ((void *) dst, (void *) src, size);
242 1.1 christos #endif /* D10V */
243 1.1 christos return;
244 1.1 christos }
245 1.1 christos
246 1.1 christos #endif /* __SPU__ */
247