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