00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 #include "copyright.h"
00033 #include "main.h"
00034 
00035 
00036 
00037 
00038 
00039 unsigned int
00040 WordToHost(unsigned int word) {
00041 #ifdef HOST_IS_BIG_ENDIAN
00042          register unsigned long result;
00043          result = (word >> 24) & 0x000000ff;
00044          result |= (word >> 8) & 0x0000ff00;
00045          result |= (word << 8) & 0x00ff0000;
00046          result |= (word << 24) & 0xff000000;
00047          return result;
00048 #else 
00049          return word;
00050 #endif 
00051 }
00052 
00053 unsigned short
00054 ShortToHost(unsigned short shortword) {
00055 #ifdef HOST_IS_BIG_ENDIAN
00056          register unsigned short result;
00057          result = (shortword << 8) & 0xff00;
00058          result |= (shortword >> 8) & 0x00ff;
00059          return result;
00060 #else 
00061          return shortword;
00062 #endif 
00063 }
00064 
00065 unsigned int
00066 WordToMachine(unsigned int word) { return WordToHost(word); }
00067 
00068 unsigned short
00069 ShortToMachine(unsigned short shortword) { return ShortToHost(shortword); }
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 bool
00086 Machine::ReadMem(int addr, int size, int *value)
00087 {
00088     int data;
00089     ExceptionType exception;
00090     int physicalAddress;
00091     
00092     DEBUG(dbgAddr, "Reading VA " << addr << ", size " << size);
00093     
00094     exception = Translate(addr, &physicalAddress, size, FALSE);
00095     if (exception != NoException) {
00096         RaiseException(exception, addr);
00097         return FALSE;
00098     }
00099     switch (size) {
00100       case 1:
00101         data = mainMemory[physicalAddress];
00102         *value = data;
00103         break;
00104         
00105       case 2:
00106         data = *(unsigned short *) &mainMemory[physicalAddress];
00107         *value = ShortToHost(data);
00108         break;
00109         
00110       case 4:
00111         data = *(unsigned int *) &mainMemory[physicalAddress];
00112         *value = WordToHost(data);
00113         break;
00114 
00115       default: ASSERT(FALSE);
00116     }
00117     
00118     DEBUG(dbgAddr, "\tvalue read = " << *value);
00119     return (TRUE);
00120 }
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 bool
00136 Machine::WriteMem(int addr, int size, int value)
00137 {
00138     ExceptionType exception;
00139     int physicalAddress;
00140      
00141     DEBUG(dbgAddr, "Writing VA " << addr << ", size " << size << ", value " << value);
00142 
00143     exception = Translate(addr, &physicalAddress, size, TRUE);
00144     if (exception != NoException) {
00145         RaiseException(exception, addr);
00146         return FALSE;
00147     }
00148     switch (size) {
00149       case 1:
00150         mainMemory[physicalAddress] = (unsigned char) (value & 0xff);
00151         break;
00152 
00153       case 2:
00154         *(unsigned short *) &mainMemory[physicalAddress]
00155                 = ShortToMachine((unsigned short) (value & 0xffff));
00156         break;
00157       
00158       case 4:
00159         *(unsigned int *) &mainMemory[physicalAddress]
00160                 = WordToMachine((unsigned int) value);
00161         break;
00162         
00163       default: ASSERT(FALSE);
00164     }
00165     
00166     return TRUE;
00167 }
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183 
00184 ExceptionType
00185 Machine::Translate(int virtAddr, int* physAddr, int size, bool writing)
00186 {
00187     int i;
00188     unsigned int vpn, offset;
00189     TranslationEntry *entry;
00190     unsigned int pageFrame;
00191 
00192     DEBUG(dbgAddr, "\tTranslate " << virtAddr << (writing ? " , write" : " , read"));
00193 
00194 
00195     if (((size == 4) && (virtAddr & 0x3)) || ((size == 2) && (virtAddr & 0x1))){
00196         DEBUG(dbgAddr, "Alignment problem at " << virtAddr << ", size " << size);
00197         return AddressErrorException;
00198     }
00199     
00200     
00201     ASSERT(tlb == NULL || pageTable == NULL);   
00202     ASSERT(tlb != NULL || pageTable != NULL);   
00203 
00204 
00205 
00206     vpn = (unsigned) virtAddr / PageSize;
00207     offset = (unsigned) virtAddr % PageSize;
00208     
00209     if (tlb == NULL) {          
00210         if (vpn >= pageTableSize) {
00211             DEBUG(dbgAddr, "Illegal virtual page # " << virtAddr);
00212             return AddressErrorException;
00213         } else if (!pageTable[vpn].valid) {
00214             DEBUG(dbgAddr, "Invalid virtual page # " << virtAddr);
00215             return PageFaultException;
00216         }
00217         entry = &pageTable[vpn];
00218     } else {
00219         for (entry = NULL, i = 0; i < TLBSize; i++)
00220             if (tlb[i].valid && (tlb[i].virtualPage == ((int)vpn))) {
00221                 entry = &tlb[i];                        
00222                 break;
00223             }
00224         if (entry == NULL) {                            
00225             DEBUG(dbgAddr, "Invalid TLB entry for this virtual page!");
00226             return PageFaultException;          
00227                                                 
00228                                                 
00229         }
00230     }
00231 
00232     if (entry->readOnly && writing) {   
00233         DEBUG(dbgAddr, "Write to read-only page at " << virtAddr);
00234         return ReadOnlyException;
00235     }
00236     pageFrame = entry->physicalPage;
00237 
00238     
00239     
00240     if (pageFrame >= NumPhysPages) { 
00241         DEBUG(dbgAddr, "Illegal pageframe " << pageFrame);
00242         return BusErrorException;
00243     }
00244     entry->use = TRUE;          
00245     if (writing)
00246         entry->dirty = TRUE;
00247     *physAddr = pageFrame * PageSize + offset;
00248     ASSERT((*physAddr >= 0) && ((*physAddr + size) <= MemorySize));
00249     DEBUG(dbgAddr, "phys addr = " << *physAddr);
00250     return NoException;
00251 }