daily update
[external/binutils.git] / gdb / testsuite / gdb.base / d10vovly.c
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