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