Ytshih/hw2
This commit is contained in:
@@ -85,38 +85,38 @@ ShortToMachine(unsigned short shortword) { return ShortToHost(shortword); }
|
||||
bool
|
||||
Machine::ReadMem(int addr, int size, int *value)
|
||||
{
|
||||
int data;
|
||||
ExceptionType exception;
|
||||
int physicalAddress;
|
||||
|
||||
DEBUG(dbgAddr, "Reading VA " << addr << ", size " << size);
|
||||
|
||||
exception = Translate(addr, &physicalAddress, size, FALSE);
|
||||
if (exception != NoException) {
|
||||
RaiseException(exception, addr);
|
||||
return FALSE;
|
||||
}
|
||||
switch (size) {
|
||||
case 1:
|
||||
data = mainMemory[physicalAddress];
|
||||
*value = data;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
data = *(unsigned short *) &mainMemory[physicalAddress];
|
||||
*value = ShortToHost(data);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
data = *(unsigned int *) &mainMemory[physicalAddress];
|
||||
*value = WordToHost(data);
|
||||
break;
|
||||
int data;
|
||||
ExceptionType exception;
|
||||
int physicalAddress;
|
||||
|
||||
default: ASSERT(FALSE);
|
||||
}
|
||||
|
||||
DEBUG(dbgAddr, "\tvalue read = " << *value);
|
||||
return (TRUE);
|
||||
DEBUG(dbgAddr, "Reading VA " << addr << ", size " << size);
|
||||
|
||||
exception = Translate(addr, &physicalAddress, size, FALSE);
|
||||
if (exception != NoException) {
|
||||
RaiseException(exception, addr);
|
||||
return FALSE;
|
||||
}
|
||||
switch (size) {
|
||||
case 1:
|
||||
data = mainMemory[physicalAddress];
|
||||
*value = data;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
data = *(unsigned short *) &mainMemory[physicalAddress];
|
||||
*value = ShortToHost(data);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
data = *(unsigned int *) &mainMemory[physicalAddress];
|
||||
*value = WordToHost(data);
|
||||
break;
|
||||
|
||||
default: ASSERT(FALSE);
|
||||
}
|
||||
|
||||
DEBUG(dbgAddr, "\tvalue read = " << *value);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@@ -135,35 +135,35 @@ Machine::ReadMem(int addr, int size, int *value)
|
||||
bool
|
||||
Machine::WriteMem(int addr, int size, int value)
|
||||
{
|
||||
ExceptionType exception;
|
||||
int physicalAddress;
|
||||
|
||||
DEBUG(dbgAddr, "Writing VA " << addr << ", size " << size << ", value " << value);
|
||||
ExceptionType exception;
|
||||
int physicalAddress;
|
||||
|
||||
exception = Translate(addr, &physicalAddress, size, TRUE);
|
||||
if (exception != NoException) {
|
||||
RaiseException(exception, addr);
|
||||
return FALSE;
|
||||
}
|
||||
switch (size) {
|
||||
case 1:
|
||||
mainMemory[physicalAddress] = (unsigned char) (value & 0xff);
|
||||
break;
|
||||
DEBUG(dbgAddr, "Writing VA " << addr << ", size " << size << ", value " << value);
|
||||
|
||||
case 2:
|
||||
*(unsigned short *) &mainMemory[physicalAddress]
|
||||
= ShortToMachine((unsigned short) (value & 0xffff));
|
||||
break;
|
||||
|
||||
case 4:
|
||||
*(unsigned int *) &mainMemory[physicalAddress]
|
||||
= WordToMachine((unsigned int) value);
|
||||
break;
|
||||
|
||||
default: ASSERT(FALSE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
exception = Translate(addr, &physicalAddress, size, TRUE);
|
||||
if (exception != NoException) {
|
||||
RaiseException(exception, addr);
|
||||
return FALSE;
|
||||
}
|
||||
switch (size) {
|
||||
case 1:
|
||||
mainMemory[physicalAddress] = (unsigned char) (value & 0xff);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
*(unsigned short *) &mainMemory[physicalAddress]
|
||||
= ShortToMachine((unsigned short) (value & 0xffff));
|
||||
break;
|
||||
|
||||
case 4:
|
||||
*(unsigned int *) &mainMemory[physicalAddress]
|
||||
= WordToMachine((unsigned int) value);
|
||||
break;
|
||||
|
||||
default: ASSERT(FALSE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@@ -184,67 +184,75 @@ Machine::WriteMem(int addr, int size, int value)
|
||||
ExceptionType
|
||||
Machine::Translate(int virtAddr, int* physAddr, int size, bool writing)
|
||||
{
|
||||
int i;
|
||||
unsigned int vpn, offset;
|
||||
TranslationEntry *entry;
|
||||
unsigned int pageFrame;
|
||||
int i;
|
||||
unsigned int vpn, offset;
|
||||
TranslationEntry *entry;
|
||||
unsigned int pageFrame;
|
||||
|
||||
DEBUG(dbgAddr, "\tTranslate " << virtAddr << (writing ? " , write" : " , read"));
|
||||
DEBUG(dbgAddr, "\tTranslate " << virtAddr << (writing ? " , write" : " , read"));
|
||||
|
||||
// check for alignment errors
|
||||
if (((size == 4) && (virtAddr & 0x3)) || ((size == 2) && (virtAddr & 0x1))){
|
||||
DEBUG(dbgAddr, "Alignment problem at " << virtAddr << ", size " << size);
|
||||
return AddressErrorException;
|
||||
// check for alignment errors
|
||||
if (((size == 4) && (virtAddr & 0x3)) || ((size == 2) && (virtAddr & 0x1))){
|
||||
DEBUG(dbgAddr, "Alignment problem at " << virtAddr << ", size " << size);
|
||||
return AddressErrorException;
|
||||
}
|
||||
// we must have either a TLB or a page table, but not both!
|
||||
ASSERT(tlb == NULL || pageTable == NULL);
|
||||
ASSERT(tlb != NULL || pageTable != NULL);
|
||||
|
||||
// calculate the virtual page number, and offset within the page,
|
||||
// from the virtual address
|
||||
vpn = (unsigned) virtAddr / PageSize;
|
||||
offset = (unsigned) virtAddr % PageSize;
|
||||
|
||||
if (tlb == NULL) { // => page table => vpn is index into table
|
||||
if (vpn >= pageTableSize) {
|
||||
DEBUG(dbgAddr, "Illegal virtual page # " << virtAddr);
|
||||
DEBUG(dbgAddr, "vpn, pageTableSize, NumPhysPages: " << vpn << ' ' << pageTableSize << ' ' << NumPhysPages);
|
||||
return AddressErrorException;
|
||||
} else if (!pageTable[vpn].valid) {
|
||||
DEBUG(dbgAddr, "Invalid virtual page # " << virtAddr);
|
||||
return PageFaultException;
|
||||
}
|
||||
// we must have either a TLB or a page table, but not both!
|
||||
ASSERT(tlb == NULL || pageTable == NULL);
|
||||
ASSERT(tlb != NULL || pageTable != NULL);
|
||||
|
||||
// calculate the virtual page number, and offset within the page,
|
||||
// from the virtual address
|
||||
vpn = (unsigned) virtAddr / PageSize;
|
||||
offset = (unsigned) virtAddr % PageSize;
|
||||
|
||||
if (tlb == NULL) { // => page table => vpn is index into table
|
||||
if (vpn >= pageTableSize) {
|
||||
DEBUG(dbgAddr, "Illegal virtual page # " << virtAddr);
|
||||
return AddressErrorException;
|
||||
} else if (!pageTable[vpn].valid) {
|
||||
DEBUG(dbgAddr, "Invalid virtual page # " << virtAddr);
|
||||
return PageFaultException;
|
||||
}
|
||||
entry = &pageTable[vpn];
|
||||
} else {
|
||||
for (entry = NULL, i = 0; i < TLBSize; i++)
|
||||
if (tlb[i].valid && (tlb[i].virtualPage == ((int)vpn))) {
|
||||
entry = &tlb[i]; // FOUND!
|
||||
break;
|
||||
}
|
||||
if (entry == NULL) { // not found
|
||||
DEBUG(dbgAddr, "Invalid TLB entry for this virtual page!");
|
||||
return PageFaultException; // really, this is a TLB fault,
|
||||
// the page may be in memory,
|
||||
// but not in the TLB
|
||||
}
|
||||
entry = &pageTable[vpn];
|
||||
} else {
|
||||
for (entry = NULL, i = 0; i < TLBSize; i++)
|
||||
if (tlb[i].valid && (tlb[i].virtualPage == ((int)vpn))) {
|
||||
entry = &tlb[i]; // FOUND!
|
||||
break;
|
||||
}
|
||||
if (entry == NULL) { // not found
|
||||
DEBUG(dbgAddr, "Invalid TLB entry for this virtual page!");
|
||||
return PageFaultException; // really, this is a TLB fault,
|
||||
// the page may be in memory,
|
||||
// but not in the TLB
|
||||
}
|
||||
}
|
||||
|
||||
if (entry->readOnly && writing) { // trying to write to a read-only page
|
||||
DEBUG(dbgAddr, "Write to read-only page at " << virtAddr);
|
||||
return ReadOnlyException;
|
||||
if (entry->readOnly && writing) { // trying to write to a read-only page
|
||||
DEBUG(dbgAddr, "Write to read-only page at " << virtAddr);
|
||||
return ReadOnlyException;
|
||||
}
|
||||
pageFrame = entry->physicalPage;
|
||||
if (pageFrame == -1) {
|
||||
pageFrame = entry->physicalPage = kernel->frameTable->Allocate();
|
||||
if (pageFrame == -1) {
|
||||
DEBUG(dbgAddr, "Memory Limit exceeded");
|
||||
return MemoryLimitException;
|
||||
}
|
||||
pageFrame = entry->physicalPage;
|
||||
}
|
||||
|
||||
// if the pageFrame is too big, there is something really wrong!
|
||||
// An invalid translation was loaded into the page table or TLB.
|
||||
if (pageFrame >= NumPhysPages) {
|
||||
DEBUG(dbgAddr, "Illegal pageframe " << pageFrame);
|
||||
return BusErrorException;
|
||||
}
|
||||
entry->use = TRUE; // set the use, dirty bits
|
||||
if (writing)
|
||||
entry->dirty = TRUE;
|
||||
*physAddr = pageFrame * PageSize + offset;
|
||||
ASSERT((*physAddr >= 0) && ((*physAddr + size) <= MemorySize));
|
||||
DEBUG(dbgAddr, "phys addr = " << *physAddr);
|
||||
return NoException;
|
||||
// if the pageFrame is too big, there is something really wrong!
|
||||
// An invalid translation was loaded into the page table or TLB.
|
||||
if (pageFrame >= NumPhysPages) {
|
||||
DEBUG(dbgAddr, "Illegal pageframe " << pageFrame);
|
||||
return BusErrorException;
|
||||
}
|
||||
entry->use = TRUE; // set the use, dirty bits
|
||||
if (writing)
|
||||
entry->dirty = TRUE;
|
||||
*physAddr = pageFrame * PageSize + offset;
|
||||
ASSERT((*physAddr >= 0) && ((*physAddr + size) <= MemorySize));
|
||||
DEBUG(dbgAddr, "phys addr = " << *physAddr);
|
||||
return NoException;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user