Main Page   Compound List   File List   Compound Members   File Members  

machine.cc

Go to the documentation of this file.
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-1993 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 "system.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('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 }
00112 
00113 //----------------------------------------------------------------------
00114 // Machine::Debugger
00115 //      Primitive debugger for user programs.  Note that we can't use
00116 //      gdb to debug user programs, since gdb doesn't run on top of Nachos.
00117 //      It could, but you'd have to implement *a lot* more system calls
00118 //      to get it to work!
00119 //
00120 //      So just allow single-stepping, and printing the contents of memory.
00121 //----------------------------------------------------------------------
00122 
00123 void Machine::Debugger()
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 }
00156  
00157 //----------------------------------------------------------------------
00158 // Machine::DumpState
00159 //      Print the user program's CPU state.  We might print the contents
00160 //      of memory, but that seemed like overkill.
00161 //----------------------------------------------------------------------
00162 
00163 void
00164 Machine::DumpState()
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 }
00196 
00197 //----------------------------------------------------------------------
00198 // Machine::ReadRegister/WriteRegister
00199 //      Fetch or write the contents of a user program register.
00200 //----------------------------------------------------------------------
00201 
00202 int Machine::ReadRegister(int num)
00203     {
00204         ASSERT((num >= 0) && (num < NumTotalRegs));
00205         return registers[num];
00206     }
00207 
00208 void Machine::WriteRegister(int num, int value)
00209     {
00210         ASSERT((num >= 0) && (num < NumTotalRegs));
00211         // DEBUG('m', "WriteRegister %d, value %d\n", num, value);
00212         registers[num] = value;
00213     }
00214 

Generated on Mon Feb 10 09:54:45 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