Line 24... |
Line 24... |
static TLB_Entry tlb[TLB_SIZE];
|
static TLB_Entry tlb[TLB_SIZE];
|
static Word tlbIndex;
|
static Word tlbIndex;
|
static Word tlbEntryHi;
|
static Word tlbEntryHi;
|
static Word tlbEntryLo;
|
static Word tlbEntryLo;
|
static Word mmuBadAddr;
|
static Word mmuBadAddr;
|
|
static Word mmuBadAccs;
|
|
|
|
|
static int assoc(Word page) {
|
static int assoc(Word page) {
|
int n, i;
|
int n, i;
|
|
|
Line 39... |
Line 40... |
}
|
}
|
return n;
|
return n;
|
}
|
}
|
|
|
|
|
static Word v2p(Word vAddr, Bool userMode, Bool writing) {
|
static Word v2p(Word vAddr, Bool userMode, Bool writing, int accsWidth) {
|
Word pAddr;
|
Word pAddr;
|
Word page, offset;
|
Word page, offset;
|
int index;
|
int index;
|
|
|
if (debugUse) {
|
if (debugUse) {
|
cPrintf("**** vAddr = 0x%08X", vAddr);
|
cPrintf("**** vAddr = 0x%08X", vAddr);
|
}
|
}
|
if ((vAddr & 0x80000000) != 0 && userMode) {
|
if ((vAddr & 0x80000000) != 0 && userMode) {
|
/* trying to access a privileged address from user mode */
|
/* trying to access a privileged address from user mode */
|
|
mmuBadAccs = (writing ? MMU_ACCS_WRITE : MMU_ACCS_READ) | accsWidth;
|
mmuBadAddr = vAddr;
|
mmuBadAddr = vAddr;
|
throwException(EXC_PRV_ADDRESS);
|
throwException(EXC_PRV_ADDRESS);
|
}
|
}
|
if ((vAddr & 0xC0000000) == 0xC0000000) {
|
if ((vAddr & 0xC0000000) == 0xC0000000) {
|
/* unmapped address space */
|
/* unmapped address space */
|
Line 65... |
Line 67... |
page = vAddr & PAGE_MASK;
|
page = vAddr & PAGE_MASK;
|
offset = vAddr & OFFSET_MASK;
|
offset = vAddr & OFFSET_MASK;
|
index = assoc(page);
|
index = assoc(page);
|
if (index == -1) {
|
if (index == -1) {
|
/* TLB miss exception */
|
/* TLB miss exception */
|
|
mmuBadAccs = (writing ? MMU_ACCS_WRITE : MMU_ACCS_READ) | accsWidth;
|
mmuBadAddr = vAddr;
|
mmuBadAddr = vAddr;
|
tlbEntryHi = page;
|
tlbEntryHi = page;
|
throwException(EXC_TLB_MISS);
|
throwException(EXC_TLB_MISS);
|
}
|
}
|
if (!tlb[index].valid) {
|
if (!tlb[index].valid) {
|
/* TLB invalid exception */
|
/* TLB invalid exception */
|
|
mmuBadAccs = (writing ? MMU_ACCS_WRITE : MMU_ACCS_READ) | accsWidth;
|
mmuBadAddr = vAddr;
|
mmuBadAddr = vAddr;
|
tlbEntryHi = page;
|
tlbEntryHi = page;
|
throwException(EXC_TLB_INVALID);
|
throwException(EXC_TLB_INVALID);
|
}
|
}
|
if (!tlb[index].write && writing) {
|
if (!tlb[index].write && writing) {
|
/* TLB write exception */
|
/* TLB write exception */
|
|
mmuBadAccs = (writing ? MMU_ACCS_WRITE : MMU_ACCS_READ) | accsWidth;
|
mmuBadAddr = vAddr;
|
mmuBadAddr = vAddr;
|
tlbEntryHi = page;
|
tlbEntryHi = page;
|
throwException(EXC_TLB_WRITE);
|
throwException(EXC_TLB_WRITE);
|
}
|
}
|
pAddr = tlb[index].frame | offset;
|
pAddr = tlb[index].frame | offset;
|
Line 93... |
Line 98... |
|
|
|
|
Word mmuReadWord(Word vAddr, Bool userMode) {
|
Word mmuReadWord(Word vAddr, Bool userMode) {
|
if ((vAddr & 3) != 0) {
|
if ((vAddr & 3) != 0) {
|
/* throw illegal address exception */
|
/* throw illegal address exception */
|
|
mmuBadAccs = MMU_ACCS_READ | MMU_ACCS_WORD;
|
mmuBadAddr = vAddr;
|
mmuBadAddr = vAddr;
|
throwException(EXC_ILL_ADDRESS);
|
throwException(EXC_ILL_ADDRESS);
|
}
|
}
|
return memoryReadWord(v2p(vAddr, userMode, false));
|
return memoryReadWord(v2p(vAddr, userMode, false, MMU_ACCS_WORD));
|
}
|
}
|
|
|
|
|
Half mmuReadHalf(Word vAddr, Bool userMode) {
|
Half mmuReadHalf(Word vAddr, Bool userMode) {
|
if ((vAddr & 1) != 0) {
|
if ((vAddr & 1) != 0) {
|
/* throw illegal address exception */
|
/* throw illegal address exception */
|
|
mmuBadAccs = MMU_ACCS_READ | MMU_ACCS_HALF;
|
mmuBadAddr = vAddr;
|
mmuBadAddr = vAddr;
|
throwException(EXC_ILL_ADDRESS);
|
throwException(EXC_ILL_ADDRESS);
|
}
|
}
|
return memoryReadHalf(v2p(vAddr, userMode, false));
|
return memoryReadHalf(v2p(vAddr, userMode, false, MMU_ACCS_HALF));
|
}
|
}
|
|
|
|
|
Byte mmuReadByte(Word vAddr, Bool userMode) {
|
Byte mmuReadByte(Word vAddr, Bool userMode) {
|
return memoryReadByte(v2p(vAddr, userMode, false));
|
return memoryReadByte(v2p(vAddr, userMode, false, MMU_ACCS_BYTE));
|
}
|
}
|
|
|
|
|
void mmuWriteWord(Word vAddr, Word data, Bool userMode) {
|
void mmuWriteWord(Word vAddr, Word data, Bool userMode) {
|
if ((vAddr & 3) != 0) {
|
if ((vAddr & 3) != 0) {
|
/* throw illegal address exception */
|
/* throw illegal address exception */
|
|
mmuBadAccs = MMU_ACCS_WRITE | MMU_ACCS_WORD;
|
mmuBadAddr = vAddr;
|
mmuBadAddr = vAddr;
|
throwException(EXC_ILL_ADDRESS);
|
throwException(EXC_ILL_ADDRESS);
|
}
|
}
|
memoryWriteWord(v2p(vAddr, userMode, true), data);
|
memoryWriteWord(v2p(vAddr, userMode, true, MMU_ACCS_WORD), data);
|
}
|
}
|
|
|
|
|
void mmuWriteHalf(Word vAddr, Half data, Bool userMode) {
|
void mmuWriteHalf(Word vAddr, Half data, Bool userMode) {
|
if ((vAddr & 1) != 0) {
|
if ((vAddr & 1) != 0) {
|
/* throw illegal address exception */
|
/* throw illegal address exception */
|
|
mmuBadAccs = MMU_ACCS_WRITE | MMU_ACCS_HALF;
|
mmuBadAddr = vAddr;
|
mmuBadAddr = vAddr;
|
throwException(EXC_ILL_ADDRESS);
|
throwException(EXC_ILL_ADDRESS);
|
}
|
}
|
memoryWriteHalf(v2p(vAddr, userMode, true), data);
|
memoryWriteHalf(v2p(vAddr, userMode, true, MMU_ACCS_HALF), data);
|
}
|
}
|
|
|
|
|
void mmuWriteByte(Word vAddr, Byte data, Bool userMode) {
|
void mmuWriteByte(Word vAddr, Byte data, Bool userMode) {
|
memoryWriteByte(v2p(vAddr, userMode, true), data);
|
memoryWriteByte(v2p(vAddr, userMode, true, MMU_ACCS_BYTE), data);
|
}
|
}
|
|
|
|
|
Word mmuGetIndex(void) {
|
Word mmuGetIndex(void) {
|
return tlbIndex;
|
return tlbIndex;
|
Line 180... |
Line 189... |
void mmuSetBadAddr(Word value) {
|
void mmuSetBadAddr(Word value) {
|
mmuBadAddr = value;
|
mmuBadAddr = value;
|
}
|
}
|
|
|
|
|
|
Word mmuGetBadAccs(void) {
|
|
return mmuBadAccs;
|
|
}
|
|
|
|
|
|
void mmuSetBadAccs(Word value) {
|
|
mmuBadAccs = value;
|
|
}
|
|
|
|
|
void mmuTbs(void) {
|
void mmuTbs(void) {
|
int index;
|
int index;
|
|
|
index = assoc(tlbEntryHi & PAGE_MASK);
|
index = assoc(tlbEntryHi & PAGE_MASK);
|
if (index == -1) {
|
if (index == -1) {
|
Line 281... |
Line 300... |
}
|
}
|
tlbIndex = rand() & TLB_MASK;
|
tlbIndex = rand() & TLB_MASK;
|
tlbEntryHi = rand() & PAGE_MASK;
|
tlbEntryHi = rand() & PAGE_MASK;
|
tlbEntryLo = rand() & (PAGE_MASK | TLB_WRITE | TLB_VALID);
|
tlbEntryLo = rand() & (PAGE_MASK | TLB_WRITE | TLB_VALID);
|
mmuBadAddr = rand();
|
mmuBadAddr = rand();
|
|
mmuBadAccs = rand() & MMU_ACCS_MASK;
|
}
|
}
|
|
|
|
|
void mmuInit(void) {
|
void mmuInit(void) {
|
mmuReset();
|
mmuReset();
|