Main Page | Alphabetical List | Class List | File List | Class Members | File Members

Machine Class Reference

#include <machine.h>

List of all members.

Public Member Functions

 Machine (bool debug)
 ~Machine ()
void Run ()
int ReadRegister (int num)
void WriteRegister (int num, int value)
void OneInstruction (Instruction *instr)
void DelayedLoad (int nextReg, int nextVal)
bool ReadMem (int addr, int size, int *value)
bool WriteMem (int addr, int size, int value)
ExceptionType Translate (int virtAddr, int *physAddr, int size, bool writing)
void RaiseException (ExceptionType which, int badVAddr)
void Debugger ()
void DumpState ()

Public Attributes

char * mainMemory
int registers [NumTotalRegs]
TranslationEntrytlb
TranslationEntrypageTable
unsigned int pageTableSize


Constructor & Destructor Documentation

Machine::Machine bool  debug  ) 
 

Definition at line 55 of file machine.cc.

References FALSE, mainMemory, MemorySize, NumTotalRegs, pageTable, registers, tlb, TLBSize, and TranslationEntry::valid.

00056 { 00057 int i; 00058 00059 for (i = 0; i < NumTotalRegs; i++) 00060 registers[i] = 0; 00061 mainMemory = new char[MemorySize]; 00062 for (i = 0; i < MemorySize; i++) 00063 mainMemory[i] = 0; 00064 #ifdef USE_TLB 00065 tlb = new TranslationEntry[TLBSize]; 00066 for (i = 0; i < TLBSize; i++) 00067 tlb[i].valid = FALSE; 00068 pageTable = NULL; 00069 #else // use linear page table 00070 tlb = NULL; 00071 pageTable = NULL; 00072 #endif 00073 00074 singleStep = debug; 00075 CheckEndian(); 00076 }

Machine::~Machine  ) 
 

Definition at line 83 of file machine.cc.

References mainMemory, and tlb.

00084 { 00085 delete [] mainMemory; 00086 if (tlb != NULL) 00087 delete [] tlb; 00088 }


Member Function Documentation

void Machine::Debugger  ) 
 

Definition at line 123 of file machine.cc.

References DumpState(), Interrupt::DumpState(), FALSE, interrupt, stats, and Statistics::totalTicks.

Referenced by Run().

00124 { 00125 char *buf = new char[80]; 00126 int num; 00127 00128 interrupt->DumpState(); 00129 DumpState(); 00130 printf("%d> ", stats->totalTicks); 00131 fflush(stdout); 00132 fgets(buf, 80, stdin); 00133 if (sscanf(buf, "%d", &num) == 1) 00134 runUntilTime = num; 00135 else { 00136 runUntilTime = 0; 00137 switch (*buf) { 00138 case '\n': 00139 break; 00140 00141 case 'c': 00142 singleStep = FALSE; 00143 break; 00144 00145 case '?': 00146 printf("Machine commands:\n"); 00147 printf(" <return> execute one instruction\n"); 00148 printf(" <number> run until the given timer tick\n"); 00149 printf(" c run until completion\n"); 00150 printf(" ? print help message\n"); 00151 break; 00152 } 00153 } 00154 delete [] buf; 00155 }

void Machine::DelayedLoad int  nextReg,
int  nextVal
 

Definition at line 576 of file mipssim.cc.

References LoadReg, LoadValueReg, and registers.

Referenced by OneInstruction(), and RaiseException().

00577 { 00578 registers[registers[LoadReg]] = registers[LoadValueReg]; 00579 registers[LoadReg] = nextReg; 00580 registers[LoadValueReg] = nextValue; 00581 registers[0] = 0; // and always make sure R0 stays zero. 00582 }

void Machine::DumpState  ) 
 

Definition at line 164 of file machine.cc.

References HiReg, LoadReg, LoadValueReg, LoReg, NextPCReg, NumGPRegs, PCReg, PrevPCReg, registers, RetAddrReg, and StackReg.

Referenced by Debugger().

00165 { 00166 int i; 00167 00168 printf("Machine registers:\n"); 00169 for (i = 0; i < NumGPRegs; i++) 00170 switch (i) { 00171 case StackReg: 00172 printf("\tSP(%d):\t0x%x%s", i, registers[i], 00173 ((i % 4) == 3) ? "\n" : ""); 00174 break; 00175 00176 case RetAddrReg: 00177 printf("\tRA(%d):\t0x%x%s", i, registers[i], 00178 ((i % 4) == 3) ? "\n" : ""); 00179 break; 00180 00181 default: 00182 printf("\t%d:\t0x%x%s", i, registers[i], 00183 ((i % 4) == 3) ? "\n" : ""); 00184 break; 00185 } 00186 00187 printf("\tHi:\t0x%x", registers[HiReg]); 00188 printf("\tLo:\t0x%x\n", registers[LoReg]); 00189 printf("\tPC:\t0x%x", registers[PCReg]); 00190 printf("\tNextPC:\t0x%x", registers[NextPCReg]); 00191 printf("\tPrevPC:\t0x%x\n", registers[PrevPCReg]); 00192 printf("\tLoad:\t0x%x", registers[LoadReg]); 00193 printf("\tLoadV:\t0x%x\n", registers[LoadValueReg]); 00194 printf("\n"); 00195 }

void Machine::OneInstruction Instruction instr  ) 
 

Definition at line 94 of file mipssim.cc.

References AddressErrorException, ASSERT, DEBUG(), DebugIsEnabled(), Instruction::Decode(), DelayedLoad(), Instruction::extra, FALSE, HiReg, IllegalInstrException, IndexToAddr, LoadReg, LoadValueReg, LoReg, MaxOpcode, NextPCReg, OP_ADD, OP_ADDI, OP_ADDIU, OP_ADDU, OP_AND, OP_ANDI, OP_BEQ, OP_BGEZ, OP_BGEZAL, OP_BGTZ, OP_BLEZ, OP_BLTZ, OP_BLTZAL, OP_BNE, OP_DIV, OP_DIVU, OP_J, OP_JAL, OP_JALR, OP_JR, OP_LB, OP_LBU, OP_LH, OP_LHU, OP_LUI, OP_LW, OP_LWL, OP_LWR, OP_MFHI, OP_MFLO, OP_MTHI, OP_MTLO, OP_MULT, OP_MULTU, OP_NOR, OP_OR, OP_ORI, OP_RES, OP_SB, OP_SH, OP_SLL, OP_SLLV, OP_SLT, OP_SLTI, OP_SLTIU, OP_SLTU, OP_SRA, OP_SRAV, OP_SRL, OP_SRLV, OP_SUB, OP_SUBU, OP_SW, OP_SWL, OP_SWR, OP_SYSCALL, OP_UNIMP, OP_XOR, OP_XORI, Instruction::opCode, OverflowException, PCReg, PrevPCReg, R31, RaiseException(), Instruction::rd, registers, Instruction::rs, Instruction::rt, SIGN_BIT, SyscallException, TRUE, and Instruction::value.

Referenced by Run().

00095 { 00096 int raw; 00097 int nextLoadReg = 0; 00098 int nextLoadValue = 0; // record delayed load operation, to apply 00099 // in the future 00100 00101 // Fetch instruction 00102 if (!machine->ReadMem(registers[PCReg], 4, &raw)) 00103 return; // exception occurred 00104 instr->value = raw; 00105 instr->Decode(); 00106 00107 if (DebugIsEnabled('m')) { 00108 struct OpString *str = &opStrings[instr->opCode]; 00109 00110 ASSERT(instr->opCode <= MaxOpcode); 00111 printf("At PC = 0x%x: ", registers[PCReg]); 00112 printf(str->string, TypeToReg(str->args[0], instr), 00113 TypeToReg(str->args[1], instr), TypeToReg(str->args[2], instr)); 00114 printf("\n"); 00115 } 00116 00117 // Compute next pc, but don't install in case there's an error or branch. 00118 int pcAfter = registers[NextPCReg] + 4; 00119 int sum, diff, tmp, value; 00120 unsigned int rs, rt, imm; 00121 00122 // Execute the instruction (cf. Kane's book) 00123 switch (instr->opCode) { 00124 00125 case OP_ADD: 00126 sum = registers[instr->rs] + registers[instr->rt]; 00127 if (!((registers[instr->rs] ^ registers[instr->rt]) & SIGN_BIT) && 00128 ((registers[instr->rs] ^ sum) & SIGN_BIT)) { 00129 RaiseException(OverflowException, 0); 00130 return; 00131 } 00132 registers[instr->rd] = sum; 00133 break; 00134 00135 case OP_ADDI: 00136 sum = registers[instr->rs] + instr->extra; 00137 if (!((registers[instr->rs] ^ instr->extra) & SIGN_BIT) && 00138 ((instr->extra ^ sum) & SIGN_BIT)) { 00139 RaiseException(OverflowException, 0); 00140 return; 00141 } 00142 registers[instr->rt] = sum; 00143 break; 00144 00145 case OP_ADDIU: 00146 registers[instr->rt] = registers[instr->rs] + instr->extra; 00147 break; 00148 00149 case OP_ADDU: 00150 registers[instr->rd] = registers[instr->rs] + registers[instr->rt]; 00151 break; 00152 00153 case OP_AND: 00154 registers[instr->rd] = registers[instr->rs] & registers[instr->rt]; 00155 break; 00156 00157 case OP_ANDI: 00158 registers[instr->rt] = registers[instr->rs] & (instr->extra & 0xffff); 00159 break; 00160 00161 case OP_BEQ: 00162 if (registers[instr->rs] == registers[instr->rt]) 00163 pcAfter = registers[NextPCReg] + IndexToAddr(instr->extra); 00164 break; 00165 00166 case OP_BGEZAL: 00167 registers[R31] = registers[NextPCReg] + 4; 00168 case OP_BGEZ: 00169 if (!(registers[instr->rs] & SIGN_BIT)) 00170 pcAfter = registers[NextPCReg] + IndexToAddr(instr->extra); 00171 break; 00172 00173 case OP_BGTZ: 00174 if (registers[instr->rs] > 0) 00175 pcAfter = registers[NextPCReg] + IndexToAddr(instr->extra); 00176 break; 00177 00178 case OP_BLEZ: 00179 if (registers[instr->rs] <= 0) 00180 pcAfter = registers[NextPCReg] + IndexToAddr(instr->extra); 00181 break; 00182 00183 case OP_BLTZAL: 00184 registers[R31] = registers[NextPCReg] + 4; 00185 case OP_BLTZ: 00186 if (registers[instr->rs] & SIGN_BIT) 00187 pcAfter = registers[NextPCReg] + IndexToAddr(instr->extra); 00188 break; 00189 00190 case OP_BNE: 00191 if (registers[instr->rs] != registers[instr->rt]) 00192 pcAfter = registers[NextPCReg] + IndexToAddr(instr->extra); 00193 break; 00194 00195 case OP_DIV: 00196 if (registers[instr->rt] == 0) { 00197 registers[LoReg] = 0; 00198 registers[HiReg] = 0; 00199 } else { 00200 registers[LoReg] = registers[instr->rs] / registers[instr->rt]; 00201 registers[HiReg] = registers[instr->rs] % registers[instr->rt]; 00202 } 00203 break; 00204 00205 case OP_DIVU: 00206 rs = (unsigned int) registers[instr->rs]; 00207 rt = (unsigned int) registers[instr->rt]; 00208 if (rt == 0) { 00209 registers[LoReg] = 0; 00210 registers[HiReg] = 0; 00211 } else { 00212 tmp = rs / rt; 00213 registers[LoReg] = (int) tmp; 00214 tmp = rs % rt; 00215 registers[HiReg] = (int) tmp; 00216 } 00217 break; 00218 00219 case OP_JAL: 00220 registers[R31] = registers[NextPCReg] + 4; 00221 case OP_J: 00222 pcAfter = (pcAfter & 0xf0000000) | IndexToAddr(instr->extra); 00223 break; 00224 00225 case OP_JALR: 00226 registers[instr->rd] = registers[NextPCReg] + 4; 00227 case OP_JR: 00228 pcAfter = registers[instr->rs]; 00229 break; 00230 00231 case OP_LB: 00232 case OP_LBU: 00233 tmp = registers[instr->rs] + instr->extra; 00234 if (!machine->ReadMem(tmp, 1, &value)) 00235 return; 00236 00237 if ((value & 0x80) && (instr->opCode == OP_LB)) 00238 value |= 0xffffff00; 00239 else 00240 value &= 0xff; 00241 nextLoadReg = instr->rt; 00242 nextLoadValue = value; 00243 break; 00244 00245 case OP_LH: 00246 case OP_LHU: 00247 tmp = registers[instr->rs] + instr->extra; 00248 if (tmp & 0x1) { 00249 RaiseException(AddressErrorException, tmp); 00250 return; 00251 } 00252 if (!machine->ReadMem(tmp, 2, &value)) 00253 return; 00254 00255 if ((value & 0x8000) && (instr->opCode == OP_LH)) 00256 value |= 0xffff0000; 00257 else 00258 value &= 0xffff; 00259 nextLoadReg = instr->rt; 00260 nextLoadValue = value; 00261 break; 00262 00263 case OP_LUI: 00264 DEBUG('m', "Executing: LUI r%d,%d\n", instr->rt, instr->extra); 00265 registers[instr->rt] = instr->extra << 16; 00266 break; 00267 00268 case OP_LW: 00269 tmp = registers[instr->rs] + instr->extra; 00270 if (tmp & 0x3) { 00271 RaiseException(AddressErrorException, tmp); 00272 return; 00273 } 00274 if (!machine->ReadMem(tmp, 4, &value)) 00275 return; 00276 nextLoadReg = instr->rt; 00277 nextLoadValue = value; 00278 break; 00279 00280 case OP_LWL: 00281 tmp = registers[instr->rs] + instr->extra; 00282 00283 // ReadMem assumes all 4 byte requests are aligned on an even 00284 // word boundary. Also, the little endian/big endian swap code would 00285 // fail (I think) if the other cases are ever exercised. 00286 ASSERT((tmp & 0x3) == 0); 00287 00288 if (!machine->ReadMem(tmp, 4, &value)) 00289 return; 00290 if (registers[LoadReg] == instr->rt) 00291 nextLoadValue = registers[LoadValueReg]; 00292 else 00293 nextLoadValue = registers[instr->rt]; 00294 switch (tmp & 0x3) { 00295 case 0: 00296 nextLoadValue = value; 00297 break; 00298 case 1: 00299 nextLoadValue = (nextLoadValue & 0xff) | (value << 8); 00300 break; 00301 case 2: 00302 nextLoadValue = (nextLoadValue & 0xffff) | (value << 16); 00303 break; 00304 case 3: 00305 nextLoadValue = (nextLoadValue & 0xffffff) | (value << 24); 00306 break; 00307 } 00308 nextLoadReg = instr->rt; 00309 break; 00310 00311 case OP_LWR: 00312 tmp = registers[instr->rs] + instr->extra; 00313 00314 // ReadMem assumes all 4 byte requests are aligned on an even 00315 // word boundary. Also, the little endian/big endian swap code would 00316 // fail (I think) if the other cases are ever exercised. 00317 ASSERT((tmp & 0x3) == 0); 00318 00319 if (!machine->ReadMem(tmp, 4, &value)) 00320 return; 00321 if (registers[LoadReg] == instr->rt) 00322 nextLoadValue = registers[LoadValueReg]; 00323 else 00324 nextLoadValue = registers[instr->rt]; 00325 switch (tmp & 0x3) { 00326 case 0: 00327 nextLoadValue = (nextLoadValue & 0xffffff00) | 00328 ((value >> 24) & 0xff); 00329 break; 00330 case 1: 00331 nextLoadValue = (nextLoadValue & 0xffff0000) | 00332 ((value >> 16) & 0xffff); 00333 break; 00334 case 2: 00335 nextLoadValue = (nextLoadValue & 0xff000000) 00336 | ((value >> 8) & 0xffffff); 00337 break; 00338 case 3: 00339 nextLoadValue = value; 00340 break; 00341 } 00342 nextLoadReg = instr->rt; 00343 break; 00344 00345 case OP_MFHI: 00346 registers[instr->rd] = registers[HiReg]; 00347 break; 00348 00349 case OP_MFLO: 00350 registers[instr->rd] = registers[LoReg]; 00351 break; 00352 00353 case OP_MTHI: 00354 registers[HiReg] = registers[instr->rs]; 00355 break; 00356 00357 case OP_MTLO: 00358 registers[LoReg] = registers[instr->rs]; 00359 break; 00360 00361 case OP_MULT: 00362 Mult(registers[instr->rs], registers[instr->rt], TRUE, 00363 &registers[HiReg], &registers[LoReg]); 00364 break; 00365 00366 case OP_MULTU: 00367 Mult(registers[instr->rs], registers[instr->rt], FALSE, 00368 &registers[HiReg], &registers[LoReg]); 00369 break; 00370 00371 case OP_NOR: 00372 registers[instr->rd] = ~(registers[instr->rs] | registers[instr->rt]); 00373 break; 00374 00375 case OP_OR: 00376 registers[instr->rd] = registers[instr->rs] | registers[instr->rs]; 00377 break; 00378 00379 case OP_ORI: 00380 registers[instr->rt] = registers[instr->rs] | (instr->extra & 0xffff); 00381 break; 00382 00383 case OP_SB: 00384 if (!machine->WriteMem((unsigned) 00385 (registers[instr->rs] + instr->extra), 1, registers[instr->rt])) 00386 return; 00387 break; 00388 00389 case OP_SH: 00390 if (!machine->WriteMem((unsigned) 00391 (registers[instr->rs] + instr->extra), 2, registers[instr->rt])) 00392 return; 00393 break; 00394 00395 case OP_SLL: 00396 registers[instr->rd] = registers[instr->rt] << instr->extra; 00397 break; 00398 00399 case OP_SLLV: 00400 registers[instr->rd] = registers[instr->rt] << 00401 (registers[instr->rs] & 0x1f); 00402 break; 00403 00404 case OP_SLT: 00405 if (registers[instr->rs] < registers[instr->rt]) 00406 registers[instr->rd] = 1; 00407 else 00408 registers[instr->rd] = 0; 00409 break; 00410 00411 case OP_SLTI: 00412 if (registers[instr->rs] < instr->extra) 00413 registers[instr->rt] = 1; 00414 else 00415 registers[instr->rt] = 0; 00416 break; 00417 00418 case OP_SLTIU: 00419 rs = registers[instr->rs]; 00420 imm = instr->extra; 00421 if (rs < imm) 00422 registers[instr->rt] = 1; 00423 else 00424 registers[instr->rt] = 0; 00425 break; 00426 00427 case OP_SLTU: 00428 rs = registers[instr->rs]; 00429 rt = registers[instr->rt]; 00430 if (rs < rt) 00431 registers[instr->rd] = 1; 00432 else 00433 registers[instr->rd] = 0; 00434 break; 00435 00436 case OP_SRA: 00437 registers[instr->rd] = registers[instr->rt] >> instr->extra; 00438 break; 00439 00440 case OP_SRAV: 00441 registers[instr->rd] = registers[instr->rt] >> 00442 (registers[instr->rs] & 0x1f); 00443 break; 00444 00445 case OP_SRL: 00446 tmp = registers[instr->rt]; 00447 tmp >>= instr->extra; 00448 registers[instr->rd] = tmp; 00449 break; 00450 00451 case OP_SRLV: 00452 tmp = registers[instr->rt]; 00453 tmp >>= (registers[instr->rs] & 0x1f); 00454 registers[instr->rd] = tmp; 00455 break; 00456 00457 case OP_SUB: 00458 diff = registers[instr->rs] - registers[instr->rt]; 00459 if (((registers[instr->rs] ^ registers[instr->rt]) & SIGN_BIT) && 00460 ((registers[instr->rs] ^ diff) & SIGN_BIT)) { 00461 RaiseException(OverflowException, 0); 00462 return; 00463 } 00464 registers[instr->rd] = diff; 00465 break; 00466 00467 case OP_SUBU: 00468 registers[instr->rd] = registers[instr->rs] - registers[instr->rt]; 00469 break; 00470 00471 case OP_SW: 00472 if (!machine->WriteMem((unsigned) 00473 (registers[instr->rs] + instr->extra), 4, registers[instr->rt])) 00474 return; 00475 break; 00476 00477 case OP_SWL: 00478 tmp = registers[instr->rs] + instr->extra; 00479 00480 // The little endian/big endian swap code would 00481 // fail (I think) if the other cases are ever exercised. 00482 ASSERT((tmp & 0x3) == 0); 00483 00484 if (!machine->ReadMem((tmp & ~0x3), 4, &value)) 00485 return; 00486 switch (tmp & 0x3) { 00487 case 0: 00488 value = registers[instr->rt]; 00489 break; 00490 case 1: 00491 value = (value & 0xff000000) | ((registers[instr->rt] >> 8) & 00492 0xffffff); 00493 break; 00494 case 2: 00495 value = (value & 0xffff0000) | ((registers[instr->rt] >> 16) & 00496 0xffff); 00497 break; 00498 case 3: 00499 value = (value & 0xffffff00) | ((registers[instr->rt] >> 24) & 00500 0xff); 00501 break; 00502 } 00503 if (!machine->WriteMem((tmp & ~0x3), 4, value)) 00504 return; 00505 break; 00506 00507 case OP_SWR: 00508 tmp = registers[instr->rs] + instr->extra; 00509 00510 // The little endian/big endian swap code would 00511 // fail (I think) if the other cases are ever exercised. 00512 ASSERT((tmp & 0x3) == 0); 00513 00514 if (!machine->ReadMem((tmp & ~0x3), 4, &value)) 00515 return; 00516 switch (tmp & 0x3) { 00517 case 0: 00518 value = (value & 0xffffff) | (registers[instr->rt] << 24); 00519 break; 00520 case 1: 00521 value = (value & 0xffff) | (registers[instr->rt] << 16); 00522 break; 00523 case 2: 00524 value = (value & 0xff) | (registers[instr->rt] << 8); 00525 break; 00526 case 3: 00527 value = registers[instr->rt]; 00528 break; 00529 } 00530 if (!machine->WriteMem((tmp & ~0x3), 4, value)) 00531 return; 00532 break; 00533 00534 case OP_SYSCALL: 00535 RaiseException(SyscallException, 0); 00536 return; 00537 00538 case OP_XOR: 00539 registers[instr->rd] = registers[instr->rs] ^ registers[instr->rt]; 00540 break; 00541 00542 case OP_XORI: 00543 registers[instr->rt] = registers[instr->rs] ^ (instr->extra & 0xffff); 00544 break; 00545 00546 case OP_RES: 00547 case OP_UNIMP: 00548 RaiseException(IllegalInstrException, 0); 00549 return; 00550 00551 default: 00552 ASSERT(FALSE); 00553 } 00554 00555 // Now we have successfully executed the instruction. 00556 00557 // Do any delayed load operation 00558 DelayedLoad(nextLoadReg, nextLoadValue); 00559 00560 // Advance program counters. 00561 registers[PrevPCReg] = registers[PCReg]; // for debugging, in case we 00562 // are jumping into lala-land 00563 registers[PCReg] = registers[NextPCReg]; 00564 registers[NextPCReg] = pcAfter; 00565 }

void Machine::RaiseException ExceptionType  which,
int  badVAddr
 

Definition at line 101 of file machine.cc.

References BadVAddrReg, DEBUG(), DelayedLoad(), ExceptionHandler(), interrupt, registers, Interrupt::setStatus(), SystemMode, and UserMode.

Referenced by OneInstruction().

00102 { 00103 DEBUG('m', "Exception: %s\n", exceptionNames[which]); 00104 00105 // ASSERT(interrupt->getStatus() == UserMode); 00106 registers[BadVAddrReg] = badVAddr; 00107 DelayedLoad(0, 0); // finish anything in progress 00108 interrupt->setStatus(SystemMode); 00109 ExceptionHandler(which); // interrupts are enabled at this point 00110 interrupt->setStatus(UserMode); 00111 }

bool Machine::ReadMem int  addr,
int  size,
int *  value
 

Definition at line 88 of file translate.cc.

References ASSERT, DEBUG(), ExceptionType, FALSE, NoException, ShortToHost(), Translate(), TRUE, and WordToHost().

00089 { 00090 int data; 00091 ExceptionType exception; 00092 int physicalAddress; 00093 00094 DEBUG('a', "Reading VA 0x%x, size %d\n", addr, size); 00095 00096 exception = Translate(addr, &physicalAddress, size, FALSE); 00097 if (exception != NoException) { 00098 machine->RaiseException(exception, addr); 00099 return FALSE; 00100 } 00101 switch (size) { 00102 case 1: 00103 data = machine->mainMemory[physicalAddress]; 00104 *value = data; 00105 break; 00106 00107 case 2: 00108 data = *(unsigned short *) &machine->mainMemory[physicalAddress]; 00109 *value = ShortToHost(data); 00110 break; 00111 00112 case 4: 00113 data = *(unsigned int *) &machine->mainMemory[physicalAddress]; 00114 *value = WordToHost(data); 00115 break; 00116 00117 default: ASSERT(FALSE); 00118 } 00119 00120 DEBUG('a', "\tvalue read = %8.8x\n", *value); 00121 return (TRUE); 00122 }

int Machine::ReadRegister int  num  ) 
 

Definition at line 202 of file machine.cc.

References ASSERT, NumTotalRegs, and registers.

00203 { 00204 ASSERT((num >= 0) && (num < NumTotalRegs)); 00205 return registers[num]; 00206 }

void Machine::Run  ) 
 

Definition at line 31 of file mipssim.cc.

References currentThread, Debugger(), DebugIsEnabled(), Thread::getName(), interrupt, OneInstruction(), Interrupt::OneTick(), Interrupt::setStatus(), stats, Statistics::totalTicks, and UserMode.

00032 { 00033 Instruction *instr = new Instruction; // storage for decoded instruction 00034 00035 if(DebugIsEnabled('m')) 00036 printf("Starting thread \"%s\" at time %d\n", 00037 currentThread->getName(), stats->totalTicks); 00038 interrupt->setStatus(UserMode); 00039 for (;;) { 00040 OneInstruction(instr); 00041 interrupt->OneTick(); 00042 if (singleStep && (runUntilTime <= stats->totalTicks)) 00043 Debugger(); 00044 } 00045 }

ExceptionType Machine::Translate int  virtAddr,
int *  physAddr,
int  size,
bool  writing
 

Definition at line 187 of file translate.cc.

References AddressErrorException, ASSERT, BusErrorException, DEBUG(), TranslationEntry::dirty, MemorySize, NoException, NumPhysPages, PageFaultException, PageSize, pageTable, pageTableSize, TranslationEntry::physicalPage, TranslationEntry::readOnly, ReadOnlyException, tlb, TLBSize, TRUE, TranslationEntry::use, TranslationEntry::valid, and TranslationEntry::virtualPage.

Referenced by ReadMem(), and WriteMem().

00188 { 00189 int i; 00190 unsigned int vpn, offset; 00191 TranslationEntry *entry; 00192 unsigned int pageFrame; 00193 00194 DEBUG('a', "\tTranslate 0x%x, %s: ", virtAddr, writing ? "write" : "read"); 00195 00196 // check for alignment errors 00197 if (((size == 4) && (virtAddr & 0x3)) || ((size == 2) && (virtAddr & 0x1))){ 00198 DEBUG('a', "alignment problem at %d, size %d!\n", virtAddr, size); 00199 return AddressErrorException; 00200 } 00201 00202 // we must have either a TLB or a page table, but not both! 00203 ASSERT(tlb == NULL || pageTable == NULL); 00204 ASSERT(tlb != NULL || pageTable != NULL); 00205 00206 // calculate the virtual page number, and offset within the page, 00207 // from the virtual address 00208 vpn = (unsigned) virtAddr / PageSize; 00209 offset = (unsigned) virtAddr % PageSize; 00210 00211 if (tlb == NULL) { // => page table => vpn is index into table 00212 if (vpn >= pageTableSize) { 00213 DEBUG('a', "virtual page # %d too large for page table size %d!\n", 00214 virtAddr, pageTableSize); 00215 return AddressErrorException; 00216 } else if (!pageTable[vpn].valid) { 00217 DEBUG('a', "virtual page # %d too large for page table size %d!\n", 00218 virtAddr, pageTableSize); 00219 return PageFaultException; 00220 } 00221 entry = &pageTable[vpn]; 00222 } else { 00223 for (entry = NULL, i = 0; i < TLBSize; i++) 00224 if (tlb[i].valid && (tlb[i].virtualPage == vpn)) { 00225 entry = &tlb[i]; // FOUND! 00226 break; 00227 } 00228 if (entry == NULL) { // not found 00229 DEBUG('a', "*** no valid TLB entry found for this virtual page!\n"); 00230 return PageFaultException; // really, this is a TLB fault, 00231 // the page may be in memory, 00232 // but not in the TLB 00233 } 00234 } 00235 00236 if (entry->readOnly && writing) { // trying to write to a read-only page 00237 DEBUG('a', "%d mapped read-only at %d in TLB!\n", virtAddr, i); 00238 return ReadOnlyException; 00239 } 00240 pageFrame = entry->physicalPage; 00241 00242 // if the pageFrame is too big, there is something really wrong! 00243 // An invalid translation was loaded into the page table or TLB. 00244 if (pageFrame >= NumPhysPages) { 00245 DEBUG('a', "*** frame %d > %d!\n", pageFrame, NumPhysPages); 00246 return BusErrorException; 00247 } 00248 entry->use = TRUE; // set the use, dirty bits 00249 if (writing) 00250 entry->dirty = TRUE; 00251 *physAddr = pageFrame * PageSize + offset; 00252 ASSERT((*physAddr >= 0) && ((*physAddr + size) <= MemorySize)); 00253 DEBUG('a', "phys addr = 0x%x\n", *physAddr); 00254 return NoException; 00255 }

bool Machine::WriteMem int  addr,
int  size,
int  value
 

Definition at line 138 of file translate.cc.

References ASSERT, DEBUG(), ExceptionType, FALSE, NoException, ShortToMachine(), Translate(), TRUE, and WordToMachine().

00139 { 00140 ExceptionType exception; 00141 int physicalAddress; 00142 00143 DEBUG('a', "Writing VA 0x%x, size %d, value 0x%x\n", addr, size, value); 00144 00145 exception = Translate(addr, &physicalAddress, size, TRUE); 00146 if (exception != NoException) { 00147 machine->RaiseException(exception, addr); 00148 return FALSE; 00149 } 00150 switch (size) { 00151 case 1: 00152 machine->mainMemory[physicalAddress] = (unsigned char) (value & 0xff); 00153 break; 00154 00155 case 2: 00156 *(unsigned short *) &machine->mainMemory[physicalAddress] 00157 = ShortToMachine((unsigned short) (value & 0xffff)); 00158 break; 00159 00160 case 4: 00161 *(unsigned int *) &machine->mainMemory[physicalAddress] 00162 = WordToMachine((unsigned int) value); 00163 break; 00164 00165 default: ASSERT(FALSE); 00166 } 00167 00168 return TRUE; 00169 }

void Machine::WriteRegister int  num,
int  value
 

Definition at line 208 of file machine.cc.

References ASSERT, NumTotalRegs, and registers.

00209 { 00210 ASSERT((num >= 0) && (num < NumTotalRegs)); 00211 // DEBUG('m', "WriteRegister %d, value %d\n", num, value); 00212 registers[num] = value; 00213 }


Member Data Documentation

char* Machine::mainMemory
 

Definition at line 156 of file machine.h.

Referenced by Machine(), and ~Machine().

TranslationEntry* Machine::pageTable
 

Definition at line 182 of file machine.h.

Referenced by Machine(), and Translate().

unsigned int Machine::pageTableSize
 

Definition at line 183 of file machine.h.

Referenced by Translate().

int Machine::registers[NumTotalRegs]
 

Definition at line 158 of file machine.h.

Referenced by DelayedLoad(), DumpState(), Machine(), OneInstruction(), RaiseException(), ReadRegister(), and WriteRegister().

TranslationEntry* Machine::tlb
 

Definition at line 179 of file machine.h.

Referenced by Machine(), Translate(), and ~Machine().


The documentation for this class was generated from the following files:
Generated on Thu Sep 16 12:33:48 2004 for NachOS by doxygen 1.3.8