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 }