old-cross-binutils/gdb/testsuite/gdb.base/d10vovly.c
Andrew Cagney b6b48d0313 * gdb.base/d10vovly.c (D10VTranslate): Map IMAP0 to low 128k of
on-chip insn memory and IMAP1 to upper 128k.
        (D10VCopy): Handle memory regions crossing 16k boundaries.
        (D10VCopy): Transfer data in 32 bit chunks.
1998-02-12 05:09:25 +00:00

207 lines
5.2 KiB
C

/*
* Ovlymgr.c -- Runtime Overlay Manager for the Mitsubishi D10V
*/
#include "ovlymgr.h"
/* Local functions and data: */
extern unsigned long _ovly_table[][4], _novlys;
enum ovly_index { VMA, SIZE, LMA, MAPPED };
enum ovly_direction { IN, OUT };
static void D10VCopy (unsigned long dst, unsigned long src, long size);
/* OverlayLoad:
* Copy the overlay into its runtime region,
* and mark the overlay as "mapped".
*/
void
OverlayLoad (int ovlyno)
{
int i;
if (ovlyno < 0 || ovlyno >= _novlys)
exit (-1); /* fail, bad ovly number */
if (_ovly_table[ovlyno][MAPPED])
return; /* this overlay already mapped -- nothing to do! */
for (i = 0; i < _novlys; i++)
if (i == ovlyno)
_ovly_table[i][MAPPED] = 1; /* this one now mapped */
else if (_ovly_table[i][VMA] == _ovly_table[ovlyno][VMA])
_ovly_table[i][MAPPED] = 0; /* this one now un-mapped */
/* copy overlay using D10V DMAP register */
D10VCopy (_ovly_table[ovlyno][VMA], _ovly_table[ovlyno][LMA],
_ovly_table[ovlyno][SIZE]);
}
/* OverlayUnload:
* Copy the overlay back into its "load" region.
* Does NOT mark overlay as "unmapped", therefore may be called
* more than once for the same mapped overlay.
*/
void
OverlayUnload (int ovlyno)
{
if (ovlyno < 0 || ovlyno >= _novlys)
exit (-1); /* fail, bad ovly number */
if (!_ovly_table[ovlyno][MAPPED])
exit (-1); /* error, can't copy out a segment that's not "in" */
D10VCopy (_ovly_table[ovlyno][LMA], _ovly_table[ovlyno][VMA],
_ovly_table[ovlyno][SIZE]);
}
/* D10VCopy:
* Copy a region of memory from src to dest.
* Like memcpy, but can copy anywhere in Universal, Data or Instruction memory.
*/
#define IMAP0 (*(int *)(0xff00))
#define IMAP1 (*(int *)(0xff02))
#define DMAP (*(int *)(0xff04))
static void
D10VTranslate (unsigned long logical,
short *dmap,
unsigned long **addr)
{
unsigned long physical;
unsigned long seg;
unsigned long off;
int err = 0;
/* to access data, we use the following mapping
0x00xxxxxx: Logical data address segment (DMAP translated memory)
0x01xxxxxx: Logical instruction address segment (IMAP translated memory)
0x10xxxxxx: Physical data memory segment (On-chip data memory)
0x11xxxxxx: Physical instruction memory segment (On-chip insn memory)
0x12xxxxxx: Phisical unified memory segment (Unified memory)
*/
/* Addresses must be correctly aligned */
if (logical & (sizeof (**addr) - 1))
exit (-1);
/* If the address is in one of the two logical address spaces, it is
first translated into a physical address */
seg = (logical >> 24);
off = (logical & 0xffffffL);
switch (seg)
{
case 0x00: /* in logical data address segment */
if (off <= 0x7fffL)
physical = (0x10L << 24) + off;
else
/* Logical address out side of on-chip segment, not
supported */
exit (-1);
break;
case 0x01: /* in logical instruction address segment */
{
short map;
if (off <= 0x1ffffL)
map = IMAP0;
else if (off <= 0x3ffffL)
map = IMAP1;
else
/* Logical address outside of IMAP[01] segment, not
supported */
exit (-1);
if (map & 0x1000L)
{
/* Instruction memory */
physical = (0x11L << 24) | off;
}
else
{
/* Unified memory */
physical = ((map & 0x7fL) << 17) + (off & 0x1ffffL);
if (physical > 0xffffffL)
/* Address outside of unified address segment */
exit (-1);
physical |= (0x12L << 24);
}
break;
}
case 0x10:
case 0x11:
case 0x12:
physical = logical;
break;
default:
exit (-1); /* error */
}
seg = (physical >> 24);
off = (physical & 0xffffffL);
switch (seg)
{
case 0x10: /* dst is a 15 bit offset into the on-chip memory */
*dmap = 0;
*addr = (long *) (0x0000 + ((int)off & 0x7fff));
break;
case 0x11: /* dst is an 18-bit offset into the on-chip
instruction memory */
*dmap = 0x1000L | ((off & 0x3ffffL) >> 14);
*addr = (long *) (0x8000 + ((int)off & 0x3fff));
break;
case 0x12: /* dst is a 24-bit offset into unified memory */
*dmap = off >> 14;
*addr = (long *) (0x8000 + ((int)off & 0x3fff));
break;
default:
exit (-1); /* error */
}
#if 0
printf ("D10VTranslate: logical = %08lx, dmap = %04x, addr = %04x\n",
logical, *dmap, *addr);
#endif
}
static void
D10VCopy (unsigned long dst, unsigned long src, long size)
{
unsigned long *s, *d, tmp;
short dmap_src, dmap_dst;
short dmap_save;
#if 0
printf ("D10VCopy: dst = %08lx, src = %08lx, size = %ld\n",
dst, src, size);
#endif
/* all section sizes should by multiples of 4 bytes */
dmap_save = DMAP;
D10VTranslate (src, &dmap_src, &s);
D10VTranslate (dst, &dmap_dst, &d);
while (size > 0)
{
/* NB: Transfer 4 byte (long) quantites, problems occure
when only two bytes are transfered */
DMAP = dmap_src;
tmp = *s;
DMAP = dmap_dst;
*d = tmp;
d++;
s++;
size -= sizeof (tmp);
src += sizeof (tmp);
dst += sizeof (tmp);
if ((src & 0x3fff) == 0)
D10VTranslate (src, &dmap_src, &s);
if ((dst & 0x3fff) == 0)
D10VTranslate (dst, &dmap_dst, &d);
}
DMAP = dmap_save;
}