Main Page   Compound List   File List   Compound Members   File Members  

Machine Class Reference

#include <machine.h>

List of all members.

Public Methods

 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

Private Attributes

bool singleStep
int runUntilTime


Constructor & Destructor Documentation

Machine::Machine bool    debug
 

Definition at line 55 of file machine.cc.

References CheckEndian, FALSE, mainMemory, MemorySize, NULL, NumTotalRegs, pageTable, registers, singleStep, 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, NULL, 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, FALSE, runUntilTime, and singleStep.

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, OpString::args, ASSERT, DEBUG, DebugIsEnabled, Instruction::Decode, DelayedLoad, Instruction::extra, FALSE, HiReg, IllegalInstrException, IndexToAddr, LoadReg, LoadValueReg, LoReg, MaxOpcode, Mult, 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, rs, Instruction::rt, rt, SIGN_BIT, OpString::string, SyscallException, TRUE, TypeToReg, 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, exceptionNames, ExceptionType, registers, 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, 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 Debugger, DebugIsEnabled, OneInstruction, runUntilTime, singleStep, 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, NULL, 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 && ((unsigned) 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.

int Machine::runUntilTime [private]
 

Definition at line 188 of file machine.h.

Referenced by Debugger, and Run.

bool Machine::singleStep [private]
 

Definition at line 186 of file machine.h.

Referenced by Debugger, Machine, and Run.

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 Mon Feb 10 09:54:57 2003 for nachos by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002
The University of Southern California does not screen or control the content on this website and thus does not guarantee the accuracy, integrity, or quality of such content. All content on this website is provided by and is the sole responsibility of the person from which such content originated, and such content does not necessarily reflect the opinions of the University administration or the Board of Trustees