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