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
10extern unsigned long _ovly_table[][4];
11extern unsigned long _novlys __attribute__ ((section (".data")));
12enum ovly_index { VMA, SIZE, LMA, MAPPED};
13
14static 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
24static void
25FlushCache (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
38bool
39OverlayLoad (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
70bool
71OverlayUnload (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
91static void
92D10VTranslate (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
185static void
186ovly_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