/* memory.c -- code for opening real memory
 * copyright (c) 1984  American Information Systems Corporation
 *  Daniel Steinberg
 *  March, 1984
 *
 */

#include "monitor.h"
#include "3200mmu.h"

mrdbyte (addr, map)
	unsigned addr;
	int map;
{
	register char *i;

	if ((int)(i = (char*) mem_addr(addr,map)) == -1)  /* map to physical */
		return(0);		/* invalid address */

	return ((*i) & 0xff);		/* return byte value */
}

mrdword (addr, map)
	unsigned addr;
	int map;
{
	register short *i;

	if ((int)(i = (short*) mem_addr(addr,map)) == -1) /* map to physical */
		return(0);		/* invalid address */

	return ((*i) & 0xffff);		/* return word value */
}

mrdquad (addr, map)
	unsigned addr;
	int map;
{
	register int *i;

	if ((int)(i = (int*) mem_addr(addr,map)) == -1)	/* map to physical */
		return(0);		/* invalid address */

	return (*i);		/* return quad value */
}

mwrtmbyte (addr, map, val)
	unsigned addr;
	int map;
	unsigned val;
{
	register char *i;

	if ((int)(i = (char*) mem_addr(addr,map)) == -1)  /* map to physical */
		return(0);		/* invalid address */

	return ((*i) = (char)(val & 0xff));		/* return byte value */
}

mwrtmword (addr, map, val)
	unsigned addr;
	int map;
	unsigned val;
{
	register short *i;

	if ((int)(i = (short*) mem_addr(addr,map)) == -1) /* map to physical */
		return(0);		/* invalid address */

	return ((*i) = (short)(val & 0xffff));		/* return word value */
}

mwrtmquad (addr, map, val)
	unsigned addr;
	int map;
	unsigned val;
{
	register int *i;

	if ((int)(i = (int*) mem_addr(addr,map)) == -1)	/* map to physical */
		return(0);		/* invalid address */

	return ((*i) = val);		/* return quad value */
}


mem_addr (addr, map)
	unsigned addr;
	int map;
{
	register unsigned p0, p1, p2;
	int ptb;

#define U(x) ((unsigned*) (x))

	switch (map)
		{
	case PHYS:
		return (addr);		/* address is already physical */
	
	case T_SUPER:
		ptb = p0 = env->mmu.ptb0; /* set to point to first page table */
		break;
	
	case T_USER:
		ptb = p0 = env->mmu.ptb1; /* set to point to first page table */
		break;
		}

	p0 += ((addr & INDEX1) >> ISHFT1);	/* get first level ptr */
	if (!((p1 = * U(p0)) & VALID))
		{
		printf(" <level 1 ptb error: %x / %x> ",
				p0, p1);
		return(-1);
		}
						/* got 2nd level base */
	p1 &= PFN;
	p1 += ((addr & INDEX2) >> ISHFT2);	/* get second ptr */
	if (!((p2 = * U(p1)) & VALID))
		{
		printf(" <level 2 ptb error: %x @ %x / %x> ",
				p0, p1, p2);
		return(-1);
		}

	p2 &= PFN;				/* get frame number */
	p2 += (addr & OFFSET);
	return(p2);				/* return address */
}




getmap ()

/* getmap () -- Return a code corresponding to the target task's mapping
 *
 *	return:	PHYS		task was running physical
 *		V_SUPER		task was using PTB0
 *		V_USER		task was using PTB1
 */
{
	if (*savpsr & PSR_U)	/* if task was running at user mode */
		{
		if (env->msr & MSR_TU)	/* if translation enabled */
			{
			if (env->msr & MSR_DS)		/* if dual space */
				return(T_USER);		/* user mapping */
			else
				return(T_SUPER);	/* user / super */
			}
		}
	else			/* if task was at supervisor mode */
		{
		if (env->msr & MSR_TS)	/* if translation enabled */
			return(T_SUPER);
		}
	return(PHYS);		/* no translation enabled */
}

