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