/* 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; | |
} | |