00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "copyright.h"
00011 #include "machine.h"
00012 #include "main.h"
00013
00014
00015
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
00023
00024
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
00049
00050
00051
00052
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
00080
00081
00082
00083 Machine::~Machine()
00084 {
00085 delete [] mainMemory;
00086 if (tlb != NULL)
00087 delete [] tlb;
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097
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);
00107 kernel->interrupt->setStatus(SystemMode);
00108 ExceptionHandler(which);
00109 kernel->interrupt->setStatus(UserMode);
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
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
00132
00133 cout << kernel->stats->totalTicks << ">";
00134
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
00163
00164 buf[0] = cin.get();
00165 }
00166 delete [] buf;
00167 }
00168
00169
00170
00171
00172
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
00209
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