308 lines
8.1 KiB
C
308 lines
8.1 KiB
C
/* alpha_mmu.c - Alpha memory management simulator
|
|
|
|
Copyright (c) 2003-2006, Robert M Supnik
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
|
copy of this software and associated documentation files (the "Software"),
|
|
to deal in the Software without restriction, including without limitation
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
|
Software is furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name of Robert M Supnik shall not be
|
|
used in advertising or otherwise to promote the sale, use or other dealings
|
|
in this Software without prior written authorization from Robert M Supnik.
|
|
|
|
This module contains the routines for
|
|
|
|
ReadB,W,L,Q - read aligned virtual
|
|
ReadAccL,Q - read aligned virtual, special access check
|
|
ReadPB,W,L,Q - read aligned physical
|
|
WriteB,W,L,Q - write aligned virtual
|
|
WriteAccL,Q - write aligned virtual, special access check
|
|
WritePB,W,L,Q - write aligned physical
|
|
|
|
The TLB is organized for optimum lookups and is broken up into three fields:
|
|
|
|
tag VA<42:13> for an 8KB page system
|
|
pte PTE<31:0>, <31:16> are zero; FOE, FOR, FOW stored inverted
|
|
pfn PFN<31:0> left shifted by page size
|
|
|
|
The inversion of FOE, FOR, FOW means that all checked bits must be one
|
|
for a reference to proceed.
|
|
|
|
All Alpha implementations provide support for a 43b superpage for Unix,
|
|
and a 32b superpage for NT:
|
|
|
|
43b superpage 0xFFFFFC0000000000:0xFFFFFDFFFFFFFFFF
|
|
32b superpage 0xFFFFFFFF80000000:0xFFFFFFFFBFFFFFFF
|
|
*/
|
|
|
|
#include "alpha_defs.h"
|
|
|
|
extern t_uint64 trans_i (t_uint64 va);
|
|
extern t_uint64 trans_d (t_uint64 va, uint32 acc);
|
|
|
|
extern t_uint64 *M;
|
|
extern t_uint64 p1;
|
|
extern uint32 pal_mode, dmapen;
|
|
extern uint32 cm_eacc, cm_racc, cm_wacc;
|
|
extern jmp_buf save_env;
|
|
extern UNIT cpu_unit;
|
|
|
|
/* Read virtual aligned
|
|
|
|
Inputs:
|
|
va = virtual address
|
|
Output:
|
|
returned data, right justified
|
|
*/
|
|
|
|
t_uint64 ReadB (t_uint64 va)
|
|
{
|
|
t_uint64 pa;
|
|
|
|
if (dmapen) pa = trans_d (va, cm_racc); /* mapping on? */
|
|
else pa = va;
|
|
return ReadPB (pa);
|
|
}
|
|
|
|
t_uint64 ReadW (t_uint64 va)
|
|
{
|
|
t_uint64 pa;
|
|
|
|
if (va & 1) ABORT1 (va, EXC_ALIGN); /* must be W aligned */
|
|
if (dmapen) pa = trans_d (va, cm_racc); /* mapping on? */
|
|
else pa = va;
|
|
return ReadPW (pa);
|
|
}
|
|
|
|
t_uint64 ReadL (t_uint64 va)
|
|
{
|
|
t_uint64 pa;
|
|
|
|
if (va & 3) ABORT1 (va, EXC_ALIGN); /* must be L aligned */
|
|
if (dmapen) pa = trans_d (va, cm_racc); /* mapping on? */
|
|
else pa = va;
|
|
return ReadPL (pa);
|
|
}
|
|
|
|
t_uint64 ReadQ (t_uint64 va)
|
|
{
|
|
t_uint64 pa;
|
|
|
|
if (va & 7) ABORT1 (va, EXC_ALIGN); /* must be Q aligned */
|
|
if (dmapen) pa = trans_d (va, cm_racc); /* mapping on? */
|
|
else pa = va;
|
|
return ReadPQ (pa);
|
|
}
|
|
|
|
/* Read with generalized access controls - used by PALcode */
|
|
|
|
t_uint64 ReadAccL (t_uint64 va, uint32 acc)
|
|
{
|
|
t_uint64 pa;
|
|
|
|
if (va & 3) ABORT1 (va, EXC_ALIGN); /* must be L aligned */
|
|
if (dmapen) pa = trans_d (va, acc); /* mapping on? */
|
|
else pa = va;
|
|
return ReadPL (pa);
|
|
}
|
|
|
|
t_uint64 ReadAccQ (t_uint64 va, uint32 acc)
|
|
{
|
|
t_uint64 pa;
|
|
|
|
if (va & 7) ABORT1 (va, EXC_ALIGN); /* must be Q aligned */
|
|
if (dmapen) pa = trans_d (va, acc); /* mapping on? */
|
|
else pa = va;
|
|
return ReadPQ (pa);
|
|
}
|
|
|
|
/* Read instruction */
|
|
|
|
uint32 ReadI (t_uint64 va)
|
|
{
|
|
t_uint64 pa;
|
|
|
|
if (!pal_mode) pa = trans_i (va); /* mapping on? */
|
|
else pa = va;
|
|
return (uint32) ReadPL (pa);
|
|
}
|
|
|
|
/* Write virtual aligned
|
|
|
|
Inputs:
|
|
va = virtual address
|
|
val = data to be written, right justified in 32b or 64b
|
|
Output:
|
|
none
|
|
*/
|
|
|
|
void WriteB (t_uint64 va, t_uint64 dat)
|
|
{
|
|
t_uint64 pa;
|
|
|
|
if (dmapen) pa = trans_d (va, cm_wacc); /* mapping on? */
|
|
else pa = va;
|
|
WritePB (pa, dat);
|
|
return;
|
|
}
|
|
|
|
void WriteW (t_uint64 va, t_uint64 dat)
|
|
{
|
|
t_uint64 pa;
|
|
|
|
if (va & 1) ABORT1 (va, EXC_ALIGN); /* must be W aligned */
|
|
if (dmapen) pa = trans_d (va, cm_wacc); /* mapping on? */
|
|
else pa = va;
|
|
WritePW (pa, dat);
|
|
return;
|
|
}
|
|
|
|
void WriteL (t_uint64 va, t_uint64 dat)
|
|
{
|
|
t_uint64 pa;
|
|
|
|
if (va & 3) ABORT1 (va, EXC_ALIGN); /* must be L aligned */
|
|
if (dmapen) pa = trans_d (va, cm_wacc); /* mapping on? */
|
|
else pa = va;
|
|
WritePL (pa, dat);
|
|
return;
|
|
}
|
|
|
|
void WriteQ (t_uint64 va, t_uint64 dat)
|
|
{
|
|
t_uint64 pa;
|
|
|
|
if (va & 7) ABORT1 (va, EXC_ALIGN); /* must be Q aligned */
|
|
if (dmapen) pa = trans_d (va, cm_wacc); /* mapping on? */
|
|
else pa = va;
|
|
WritePQ (pa, dat);
|
|
return;
|
|
}
|
|
|
|
/* Write with generalized access controls - used by PALcode */
|
|
|
|
void WriteAccL (t_uint64 va, t_uint64 dat, uint32 acc)
|
|
{
|
|
t_uint64 pa;
|
|
|
|
if (va & 3) ABORT1 (va, EXC_ALIGN); /* must be L aligned */
|
|
if (dmapen) pa = trans_d (va, acc); /* mapping on? */
|
|
else pa = va;
|
|
WritePL (pa, dat);
|
|
return;
|
|
}
|
|
|
|
void WriteAccQ (t_uint64 va, t_uint64 dat, uint32 acc)
|
|
{
|
|
t_uint64 pa;
|
|
|
|
if (va & 7) ABORT1 (va, EXC_ALIGN); /* must be Q aligned */
|
|
if (dmapen) pa = trans_d (va, acc); /* mapping on? */
|
|
else pa = va;
|
|
WritePQ (pa, dat);
|
|
return;
|
|
}
|
|
|
|
/* Read and write physical aligned - access point to I/O */
|
|
|
|
INLINE t_uint64 ReadPB (t_uint64 pa)
|
|
{
|
|
t_uint64 val;
|
|
|
|
if (ADDR_IS_MEM (pa)) {
|
|
uint32 bo = ((uint32) pa) & 07;
|
|
return (((M[pa >> 3] >> (bo << 3))) & M8);
|
|
}
|
|
if (ReadIO (pa, &val, L_BYTE)) return val;
|
|
return 0;
|
|
}
|
|
|
|
INLINE t_uint64 ReadPW (t_uint64 pa)
|
|
{
|
|
t_uint64 val;
|
|
|
|
if (ADDR_IS_MEM (pa)) {
|
|
uint32 bo = ((uint32) pa) & 06;
|
|
return (((M[pa >> 3] >> (bo << 3))) & M16);
|
|
}
|
|
if (ReadIO (pa, &val, L_WORD)) return val;
|
|
return 0;
|
|
}
|
|
|
|
INLINE t_uint64 ReadPL (t_uint64 pa)
|
|
{
|
|
t_uint64 val;
|
|
|
|
if (ADDR_IS_MEM (pa)) {
|
|
if (pa & 4) return (((M[pa >> 3] >> 32)) & M32);
|
|
return ((M[pa >> 3]) & M32);
|
|
}
|
|
if (ReadIO (pa, &val, L_LONG)) return val;
|
|
return 0;
|
|
}
|
|
|
|
INLINE t_uint64 ReadPQ (t_uint64 pa)
|
|
{
|
|
t_uint64 val;
|
|
|
|
if (ADDR_IS_MEM (pa)) return M[pa >> 3];
|
|
if (ReadIO (pa, &val, L_QUAD)) return val;
|
|
return 0;
|
|
}
|
|
|
|
INLINE void WritePB (t_uint64 pa, t_uint64 dat)
|
|
{
|
|
dat = dat & M8;
|
|
if (ADDR_IS_MEM (pa)) {
|
|
uint32 bo = ((uint32) pa) & 07;
|
|
M[pa >> 3] = (M[pa >> 3] & ~(((t_uint64) M8) << (bo << 3))) |
|
|
(dat << (bo << 3));
|
|
}
|
|
else WriteIO (pa, dat, L_BYTE);
|
|
return;
|
|
}
|
|
|
|
INLINE void WritePW (t_uint64 pa, t_uint64 dat)
|
|
{
|
|
dat = dat & M16;
|
|
if (ADDR_IS_MEM (pa)) {
|
|
uint32 bo = ((uint32) pa) & 07;
|
|
M[pa >> 3] = (M[pa >> 3] & ~(((t_uint64) M16) << (bo << 3))) |
|
|
(dat << (bo << 3));
|
|
}
|
|
else WriteIO (pa, dat, L_WORD);
|
|
return;
|
|
}
|
|
|
|
INLINE void WritePL (t_uint64 pa, t_uint64 dat)
|
|
{
|
|
dat = dat & M32;
|
|
if (ADDR_IS_MEM (pa)) {
|
|
if (pa & 4) M[pa >> 3] = (M[pa >> 3] & M32) |
|
|
(dat << 32);
|
|
else M[pa >> 3] = (M[pa >> 3] & ~((t_uint64) M32)) | dat;
|
|
}
|
|
else WriteIO (pa, dat, L_LONG);
|
|
return;
|
|
}
|
|
|
|
INLINE void WritePQ (t_uint64 pa, t_uint64 dat)
|
|
{
|
|
if (ADDR_IS_MEM (pa)) M[pa >> 3] = dat;
|
|
else WriteIO (pa, dat, L_QUAD);
|
|
return;
|
|
}
|
|
|