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