Page principale | Hiérarchie des classes | Liste des classes | Répertoires | Liste des fichiers | Membres de classe | Membres de fichier

machine.cc

Aller à la documentation de ce fichier.
00001 // machine.cc 
00002 //      Routines for simulating the execution of user programs.
00003 //
00004 //  DO NOT CHANGE -- part of the machine emulation
00005 //
00006 // Copyright (c) 1992-1996 The Regents of the University of California.
00007 // All rights reserved.  See copyright.h for copyright notice and limitation 
00008 // of liability and disclaimer of warranty provisions.
00009 
00010 #include "copyright.h"
00011 #include "machine.h"
00012 #include "main.h"
00013 
00014 // Textual names of the exceptions that can be generated by user program
00015 // execution, for debugging.
00016 static char* exceptionNames[] = { "no exception", "syscall", 
00017                                 "page fault/no TLB entry", "page read only",
00018                                 "bus error", "address error", "overflow",
00019                                 "illegal instruction" };
00020 
00021 //----------------------------------------------------------------------
00022 // CheckEndian
00023 //      Check to be sure that the host really uses the format it says it 
00024 //      does, for storing the bytes of an integer.  Stop on error.
00025 //----------------------------------------------------------------------
00026 
00027 static
00028 void CheckEndian()
00029 {
00030     union checkit {
00031         char charword[4];
00032         unsigned int intword;
00033     } check;
00034 
00035     check.charword[0] = 1;
00036     check.charword[1] = 2;
00037     check.charword[2] = 3;
00038     check.charword[3] = 4;
00039 
00040 #ifdef HOST_IS_BIG_ENDIAN
00041     ASSERT (check.intword == 0x01020304);
00042 #else
00043     ASSERT (check.intword == 0x04030201);
00044 #endif
00045 }
00046 
00047 //----------------------------------------------------------------------
00048 // Machine::Machine
00049 //      Initialize the simulation of user program execution.
00050 //
00051 //      "debug" -- if TRUE, drop into the debugger after each user instruction
00052 //              is executed.
00053 //----------------------------------------------------------------------
00054 
00055 Machine::Machine(bool debug)
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 }
00077 
00078 //----------------------------------------------------------------------
00079 // Machine::~Machine
00080 //      De-allocate the data structures used to simulate user program execution.
00081 //----------------------------------------------------------------------
00082 
00083 Machine::~Machine()
00084 {
00085     delete [] mainMemory;
00086     if (tlb != NULL)
00087         delete [] tlb;
00088 }
00089 
00090 //----------------------------------------------------------------------
00091 // Machine::RaiseException
00092 //      Transfer control to the Nachos kernel from user mode, because
00093 //      the user program either invoked a system call, or some exception
00094 //      occured (such as the address translation failed).
00095 //
00096 //      "which" -- the cause of the kernel trap
00097 //      "badVaddr" -- the virtual address causing the trap, if appropriate
00098 //----------------------------------------------------------------------
00099 
00100 void
00101 Machine::RaiseException(ExceptionType which, int badVAddr)
00102 {
00103     DEBUG(dbgMach, "Exception: " << exceptionNames[which]);
00104     
00105     registers[BadVAddrReg] = badVAddr;
00106     DelayedLoad(0, 0);                  // finish anything in progress
00107     kernel->interrupt->setStatus(SystemMode);
00108     ExceptionHandler(which);            // interrupts are enabled at this point
00109     kernel->interrupt->setStatus(UserMode);
00110 }
00111 
00112 //----------------------------------------------------------------------
00113 // Machine::Debugger
00114 //      Primitive debugger for user programs.  Note that we can't use
00115 //      gdb to debug user programs, since gdb doesn't run on top of Nachos.
00116 //      It could, but you'd have to implement *a lot* more system calls
00117 //      to get it to work!
00118 //
00119 //      So just allow single-stepping, and printing the contents of memory.
00120 //----------------------------------------------------------------------
00121 
00122 void Machine::Debugger()
00123 {
00124     char *buf = new char[80];
00125     int num;
00126     bool done = FALSE;
00127 
00128     kernel->interrupt->DumpState();
00129     DumpState();
00130     while (!done) {
00131       // read commands until we should proceed with more execution
00132       // prompt for input, giving current simulation time in the prompt
00133       cout << kernel->stats->totalTicks << ">";
00134       // read one line of input (80 chars max)
00135       cin.get(buf, 80);
00136       if (sscanf(buf, "%d", &num) == 1) {
00137         runUntilTime = num;
00138         done = TRUE;
00139       }
00140       else {
00141         runUntilTime = 0;
00142         switch (*buf) {
00143         case '\0':
00144           done = TRUE;
00145           break;
00146         case 'c':
00147           singleStep = FALSE;
00148           done = TRUE;
00149           break;
00150         case '?':
00151           cout << "Machine commands:\n";
00152           cout << "    <return>  execute one instruction\n";
00153           cout << "    <number>  run until the given timer tick\n";
00154           cout << "    c         run until completion\n";
00155           cout << "    ?         print help message\n";
00156           break;
00157         default:
00158           cout << "Unknown command: " << buf << "\n";
00159           cout << "Type ? for help.\n";
00160         }
00161       }
00162       // consume the newline delimiter, which does not get
00163       // eaten by cin.get(buf,80) above.
00164       buf[0] = cin.get();
00165     }
00166     delete [] buf;
00167 }
00168  
00169 //----------------------------------------------------------------------
00170 // Machine::DumpState
00171 //      Print the user program's CPU state.  We might print the contents
00172 //      of memory, but that seemed like overkill.
00173 //----------------------------------------------------------------------
00174 
00175 void
00176 Machine::DumpState()
00177 {
00178     int i;
00179     
00180     cout << "Machine registers:\n";
00181     for (i = 0; i < NumGPRegs; i++) {
00182         switch (i) {
00183           case StackReg:
00184             cerr << "\tSP(" << i << "):\t" << registers[i];
00185             break;
00186             
00187           case RetAddrReg:
00188             cerr << "\tRA(" << i << "):\t" << registers[i];
00189             break;
00190           
00191           default:
00192             cerr<< "\t" << i << ":\t" << registers[i];
00193             break;
00194         }
00195         if ((i % 4) == 3) { cout << "\n"; }
00196     }
00197     
00198     cerr << "\tHi:\t" << registers[HiReg];
00199     cerr << "\tLo:\t" << registers[LoReg];
00200     cerr << "\tPC:\t" << registers[PCReg];
00201     cerr << "\tNextPC:\t" << registers[NextPCReg];
00202     cerr << "\tPrevPC:\t" << registers[PrevPCReg];
00203     cerr << "\tLoad:\t" << registers[LoadReg];
00204     cerr << "\tLoadV:\t" << registers[LoadValueReg] << "\n";
00205 }
00206 
00207 //----------------------------------------------------------------------
00208 // Machine::ReadRegister/WriteRegister
00209 //      Fetch or write the contents of a user program register.
00210 //----------------------------------------------------------------------
00211 
00212 int 
00213 Machine::ReadRegister(int num)
00214 {
00215     ASSERT((num >= 0) && (num < NumTotalRegs));
00216     return registers[num];
00217 }
00218 
00219 void 
00220 Machine::WriteRegister(int num, int value)
00221 {
00222     ASSERT((num >= 0) && (num < NumTotalRegs));
00223     registers[num] = value;
00224 }
00225 

Généré le Sun Jan 15 00:44:24 2006 pour Architecture Cible de NachOS : par  doxygen 1.4.4