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