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

mipssim.cc

Aller à la documentation de ce fichier.
00001 // mipssim.cc -- simulate a MIPS R2/3000 processor
00002 //
00003 //   This code has been adapted from Ousterhout's MIPSSIM package.
00004 //   Byte ordering is little-endian, so we can be compatible with
00005 //   DEC RISC systems.
00006 //
00007 //   DO NOT CHANGE -- part of the machine emulation
00008 //
00009 // Copyright (c) 1992-1996 The Regents of the University of California.
00010 // All rights reserved.  See copyright.h for copyright notice and limitation 
00011 // of liability and disclaimer of warranty provisions.
00012 
00013 // Simulation fixes done by Peter E Reissner, class of Winter 1994/95 (York)
00014 // I've not been able to test this extensively.
00015 // Ported to newer version of Nachos at Waterloo by Scott Graham (Mar 99).
00016 
00017 
00018 #include "copyright.h"
00019 
00020 #include "debug.h"
00021 #include "machine.h"
00022 #include "mipssim.h"
00023 #include "main.h"
00024 
00025 static void Mult(int a, int b, bool signedArith, int* hiPtr, int* loPtr);
00026 
00027 // The following class defines an instruction, represented in both
00028 //      undecoded binary form
00029 //      decoded to identify
00030 //          operation to do
00031 //          registers to act on
00032 //          any immediate operand value
00033 
00034 class Instruction {
00035   public:
00036     void Decode();      // decode the binary representation of the instruction
00037 
00038     unsigned int value; // binary representation of the instruction
00039 
00040     char opCode;     // Type of instruction.  This is NOT the same as the
00041                      // opcode field from the instruction: see defs in mips.h
00042     char rs, rt, rd; // Three registers from instruction.
00043     int extra;       // Immediate or target or shamt field or offset.
00044                      // Immediates are sign-extended.
00045 };
00046 
00047 //----------------------------------------------------------------------
00048 // Machine::Run
00049 //      Simulate the execution of a user-level program on Nachos.
00050 //      Called by the kernel when the program starts up; never returns.
00051 //
00052 //      This routine is re-entrant, in that it can be called multiple
00053 //      times concurrently -- one for each thread executing user code.
00054 //----------------------------------------------------------------------
00055 
00056 void
00057 Machine::Run()
00058 {
00059     Instruction *instr = new Instruction;  // storage for decoded instruction
00060 
00061     if (debug->IsEnabled('m')) {
00062         cerr << "Starting program in thread: " << kernel->currentThread->getName();
00063         cerr << ", at time: " << kernel->stats->totalTicks << "\n";
00064     }
00065     kernel->interrupt->setStatus(UserMode);
00066     for (;;) {
00067         OneInstruction(instr);
00068         kernel->interrupt->OneTick();
00069         if (singleStep && (runUntilTime <= kernel->stats->totalTicks))
00070           Debugger();
00071     }
00072 }
00073 
00074 
00075 //----------------------------------------------------------------------
00076 // TypeToReg
00077 //      Retrieve the register # referred to in an instruction. 
00078 //----------------------------------------------------------------------
00079 
00080 static int 
00081 TypeToReg(RegType reg, Instruction *instr)
00082 {
00083     switch (reg) {
00084       case RS:
00085         return instr->rs;
00086       case RT:
00087         return instr->rt;
00088       case RD:
00089         return instr->rd;
00090       case EXTRA:
00091         return instr->extra;
00092       default:
00093         return -1;
00094     }
00095 }
00096 
00097 //----------------------------------------------------------------------
00098 // Machine::OneInstruction
00099 //      Execute one instruction from a user-level program
00100 //
00101 //      If there is any kind of exception or interrupt, we invoke the 
00102 //      exception handler, and when it returns, we return to Run(), which
00103 //      will re-invoke us in a loop.  This allows us to
00104 //      re-start the instruction execution from the beginning, in
00105 //      case any of our state has changed.  On a syscall,
00106 //      the OS software must increment the PC so execution begins
00107 //      at the instruction immediately after the syscall. 
00108 //
00109 //      This routine is re-entrant, in that it can be called multiple
00110 //      times concurrently -- one for each thread executing user code.
00111 //      We get re-entrancy by never caching any data -- we always re-start the
00112 //      simulation from scratch each time we are called (or after trapping
00113 //      back to the Nachos kernel on an exception or interrupt), and we always
00114 //      store all data back to the machine registers and memory before
00115 //      leaving.  This allows the Nachos kernel to control our behavior
00116 //      by controlling the contents of memory, the translation table,
00117 //      and the register set.
00118 //----------------------------------------------------------------------
00119 
00120 void
00121 Machine::OneInstruction(Instruction *instr)
00122 {
00123 #ifdef SIM_FIX
00124     int byte;       // described in Kane for LWL,LWR,...
00125 #endif
00126 
00127     int raw;
00128     int nextLoadReg = 0;        
00129     int nextLoadValue = 0;      // record delayed load operation, to apply
00130                                 // in the future
00131 
00132     // Fetch instruction 
00133     if (!ReadMem(registers[PCReg], 4, &raw))
00134         return;                 // exception occurred
00135     instr->value = raw;
00136     instr->Decode();
00137 
00138     if (debug->IsEnabled('m')) {
00139         struct OpString *str = &opStrings[instr->opCode];
00140         char buf[80];
00141 
00142         ASSERT(instr->opCode <= MaxOpcode);
00143         cout << "At PC = " << registers[PCReg];
00144         sprintf(buf, str->format, TypeToReg(str->args[0], instr),
00145              TypeToReg(str->args[1], instr), TypeToReg(str->args[2], instr));
00146         cerr << "\t" << buf << "\n";
00147     }
00148     
00149     // Compute next pc, but don't install in case there's an error or branch.
00150     int pcAfter = registers[NextPCReg] + 4;
00151     int sum, diff, tmp, value;
00152     unsigned int rs, rt, imm;
00153 
00154     // Execute the instruction (cf. Kane's book)
00155     switch (instr->opCode) {
00156         
00157       case OP_ADD:
00158         sum = registers[instr->rs] + registers[instr->rt];
00159         if (!((registers[instr->rs] ^ registers[instr->rt]) & SIGN_BIT) &&
00160             ((registers[instr->rs] ^ sum) & SIGN_BIT)) {
00161             RaiseException(OverflowException, 0);
00162             return;
00163         }
00164         registers[instr->rd] = sum;
00165         break;
00166         
00167       case OP_ADDI:
00168         sum = registers[instr->rs] + instr->extra;
00169         if (!((registers[instr->rs] ^ instr->extra) & SIGN_BIT) &&
00170             ((instr->extra ^ sum) & SIGN_BIT)) {
00171             RaiseException(OverflowException, 0);
00172             return;
00173         }
00174         registers[instr->rt] = sum;
00175         break;
00176         
00177       case OP_ADDIU:
00178         registers[instr->rt] = registers[instr->rs] + instr->extra;
00179         break;
00180         
00181       case OP_ADDU:
00182         registers[instr->rd] = registers[instr->rs] + registers[instr->rt];
00183         break;
00184         
00185       case OP_AND:
00186         registers[instr->rd] = registers[instr->rs] & registers[instr->rt];
00187         break;
00188         
00189       case OP_ANDI:
00190         registers[instr->rt] = registers[instr->rs] & (instr->extra & 0xffff);
00191         break;
00192         
00193       case OP_BEQ:
00194         if (registers[instr->rs] == registers[instr->rt])
00195             pcAfter = registers[NextPCReg] + IndexToAddr(instr->extra);
00196         break;
00197         
00198       case OP_BGEZAL:
00199         registers[R31] = registers[NextPCReg] + 4;
00200       case OP_BGEZ:
00201         if (!(registers[instr->rs] & SIGN_BIT))
00202             pcAfter = registers[NextPCReg] + IndexToAddr(instr->extra);
00203         break;
00204         
00205       case OP_BGTZ:
00206         if (registers[instr->rs] > 0)
00207             pcAfter = registers[NextPCReg] + IndexToAddr(instr->extra);
00208         break;
00209         
00210       case OP_BLEZ:
00211         if (registers[instr->rs] <= 0)
00212             pcAfter = registers[NextPCReg] + IndexToAddr(instr->extra);
00213         break;
00214         
00215       case OP_BLTZAL:
00216         registers[R31] = registers[NextPCReg] + 4;
00217       case OP_BLTZ:
00218         if (registers[instr->rs] & SIGN_BIT)
00219             pcAfter = registers[NextPCReg] + IndexToAddr(instr->extra);
00220         break;
00221         
00222       case OP_BNE:
00223         if (registers[instr->rs] != registers[instr->rt])
00224             pcAfter = registers[NextPCReg] + IndexToAddr(instr->extra);
00225         break;
00226         
00227       case OP_DIV:
00228         if (registers[instr->rt] == 0) {
00229             registers[LoReg] = 0;
00230             registers[HiReg] = 0;
00231         } else {
00232             registers[LoReg] =  registers[instr->rs] / registers[instr->rt];
00233             registers[HiReg] = registers[instr->rs] % registers[instr->rt];
00234         }
00235         break;
00236         
00237       case OP_DIVU:       
00238           rs = (unsigned int) registers[instr->rs];
00239           rt = (unsigned int) registers[instr->rt];
00240           if (rt == 0) {
00241               registers[LoReg] = 0;
00242               registers[HiReg] = 0;
00243           } else {
00244               tmp = rs / rt;
00245               registers[LoReg] = (int) tmp;
00246               tmp = rs % rt;
00247               registers[HiReg] = (int) tmp;
00248           }
00249           break;
00250         
00251       case OP_JAL:
00252         registers[R31] = registers[NextPCReg] + 4;
00253       case OP_J:
00254         pcAfter = (pcAfter & 0xf0000000) | IndexToAddr(instr->extra);
00255         break;
00256         
00257       case OP_JALR:
00258         registers[instr->rd] = registers[NextPCReg] + 4;
00259       case OP_JR:
00260         pcAfter = registers[instr->rs];
00261         break;
00262         
00263       case OP_LB:
00264       case OP_LBU:
00265         tmp = registers[instr->rs] + instr->extra;
00266         if (!ReadMem(tmp, 1, &value))
00267             return;
00268 
00269         if ((value & 0x80) && (instr->opCode == OP_LB))
00270             value |= 0xffffff00;
00271         else
00272             value &= 0xff;
00273         nextLoadReg = instr->rt;
00274         nextLoadValue = value;
00275         break;
00276         
00277       case OP_LH:
00278       case OP_LHU:        
00279         tmp = registers[instr->rs] + instr->extra;
00280         if (tmp & 0x1) {
00281             RaiseException(AddressErrorException, tmp);
00282             return;
00283         }
00284         if (!ReadMem(tmp, 2, &value))
00285             return;
00286 
00287         if ((value & 0x8000) && (instr->opCode == OP_LH))
00288             value |= 0xffff0000;
00289         else
00290             value &= 0xffff;
00291         nextLoadReg = instr->rt;
00292         nextLoadValue = value;
00293         break;
00294         
00295       case OP_LUI:
00296         DEBUG(dbgMach, "Executing: LUI r" << instr->rt << ", " << instr->extra);
00297         registers[instr->rt] = instr->extra << 16;
00298         break;
00299         
00300       case OP_LW:
00301         tmp = registers[instr->rs] + instr->extra;
00302         if (tmp & 0x3) {
00303             RaiseException(AddressErrorException, tmp);
00304             return;
00305         }
00306         if (!ReadMem(tmp, 4, &value))
00307             return;
00308         nextLoadReg = instr->rt;
00309         nextLoadValue = value;
00310         break;
00311         
00312       case OP_LWL:        
00313         tmp = registers[instr->rs] + instr->extra;
00314 
00315 #ifdef SIM_FIX
00316         // The only difference between this code and the BIG ENDIAN code
00317         // is that the ReadMem call is guaranteed an aligned access as it
00318         // should be (Kane's book hides the fact that all memory access
00319         // are done using aligned loads - what the instruction asks for
00320         // is a arbitrary) This is the whole purpose of LWL and LWR etc.
00321         // Then the switch uses  3 - (tmp & 0x3)  instead of (tmp & 0x3)
00322 
00323         byte = tmp & 0x3;
00324         // DEBUG('P', "Addr 0x%X\n",tmp-byte);
00325 
00326         if (!ReadMem(tmp-byte, 4, &value))
00327             return;
00328 #else
00329         // ReadMem assumes all 4 byte requests are aligned on an even 
00330         // word boundary.  Also, the little endian/big endian swap code would
00331         // fail (I think) if the other cases are ever exercised.
00332         ASSERT((tmp & 0x3) == 0);  
00333 
00334         if (!ReadMem(tmp, 4, &value))
00335             return;
00336 #endif
00337 
00338         if (registers[LoadReg] == instr->rt)
00339             nextLoadValue = registers[LoadValueReg];
00340         else
00341             nextLoadValue = registers[instr->rt];
00342 #ifdef SIM_FIX
00343         switch (3 - byte) 
00344 #else
00345         switch (tmp & 0x3)
00346 #endif
00347           {
00348           case 0:
00349             nextLoadValue = value;
00350             break;
00351           case 1:
00352             nextLoadValue = (nextLoadValue & 0xff) | (value << 8);
00353             break;
00354           case 2:
00355             nextLoadValue = (nextLoadValue & 0xffff) | (value << 16);
00356             break;
00357           case 3:
00358             nextLoadValue = (nextLoadValue & 0xffffff) | (value << 24);
00359             break;
00360         }
00361         nextLoadReg = instr->rt;
00362         break;
00363         
00364       case OP_LWR:
00365         tmp = registers[instr->rs] + instr->extra;
00366 
00367 #ifdef SIM_FIX
00368         // The only difference between this code and the BIG ENDIAN code
00369         // is that the ReadMem call is guaranteed an aligned access as it
00370         // should be (Kane's book hides the fact that all memory access
00371         // are done using aligned loads - what the instruction asks 
00372         // for is a arbitrary) This is the whole purpose of LWL and LWR etc.
00373         // Then the switch uses  3 - (tmp & 0x3)  instead of (tmp & 0x3)
00374 
00375         byte = tmp & 0x3;
00376         // DEBUG('P', "Addr 0x%X\n",tmp-byte);
00377 
00378         if (!ReadMem(tmp-byte, 4, &value))
00379             return;
00380 #else
00381         // ReadMem assumes all 4 byte requests are aligned on an even 
00382         // word boundary.  Also, the little endian/big endian swap code would
00383         // fail (I think) if the other cases are ever exercised.
00384         ASSERT((tmp & 0x3) == 0);  
00385 
00386         if (!ReadMem(tmp, 4, &value))
00387             return;
00388 #endif
00389 
00390         if (registers[LoadReg] == instr->rt)
00391             nextLoadValue = registers[LoadValueReg];
00392         else
00393             nextLoadValue = registers[instr->rt];
00394 
00395 #ifdef SIM_FIX
00396         switch (3 - byte) 
00397 #else
00398         switch (tmp & 0x3)
00399 #endif
00400           {
00401           case 0:
00402             nextLoadValue = (nextLoadValue & 0xffffff00) |
00403                 ((value >> 24) & 0xff);
00404             break;
00405           case 1:
00406             nextLoadValue = (nextLoadValue & 0xffff0000) |
00407                 ((value >> 16) & 0xffff);
00408             break;
00409           case 2:
00410             nextLoadValue = (nextLoadValue & 0xff000000)
00411                 | ((value >> 8) & 0xffffff);
00412             break;
00413           case 3:
00414             nextLoadValue = value;
00415             break;
00416         }
00417         nextLoadReg = instr->rt;
00418         break;
00419         
00420       case OP_MFHI:
00421         registers[instr->rd] = registers[HiReg];
00422         break;
00423         
00424       case OP_MFLO:
00425         registers[instr->rd] = registers[LoReg];
00426         break;
00427         
00428       case OP_MTHI:
00429         registers[HiReg] = registers[instr->rs];
00430         break;
00431         
00432       case OP_MTLO:
00433         registers[LoReg] = registers[instr->rs];
00434         break;
00435         
00436       case OP_MULT:
00437         Mult(registers[instr->rs], registers[instr->rt], TRUE,
00438              &registers[HiReg], &registers[LoReg]);
00439         break;
00440         
00441       case OP_MULTU:
00442         Mult(registers[instr->rs], registers[instr->rt], FALSE,
00443              &registers[HiReg], &registers[LoReg]);
00444         break;
00445         
00446       case OP_NOR:
00447         registers[instr->rd] = ~(registers[instr->rs] | registers[instr->rt]);
00448         break;
00449         
00450       case OP_OR:
00451         registers[instr->rd] = registers[instr->rs] | registers[instr->rt];
00452         break;
00453         
00454       case OP_ORI:
00455         registers[instr->rt] = registers[instr->rs] | (instr->extra & 0xffff);
00456         break;
00457         
00458       case OP_SB:
00459         if (!WriteMem((unsigned) 
00460                 (registers[instr->rs] + instr->extra), 1, registers[instr->rt]))
00461             return;
00462         break;
00463         
00464       case OP_SH:
00465         if (!WriteMem((unsigned) 
00466                 (registers[instr->rs] + instr->extra), 2, registers[instr->rt]))
00467             return;
00468         break;
00469         
00470       case OP_SLL:
00471         registers[instr->rd] = registers[instr->rt] << instr->extra;
00472         break;
00473         
00474       case OP_SLLV:
00475         registers[instr->rd] = registers[instr->rt] <<
00476             (registers[instr->rs] & 0x1f);
00477         break;
00478         
00479       case OP_SLT:
00480         if (registers[instr->rs] < registers[instr->rt])
00481             registers[instr->rd] = 1;
00482         else
00483             registers[instr->rd] = 0;
00484         break;
00485         
00486       case OP_SLTI:
00487         if (registers[instr->rs] < instr->extra)
00488             registers[instr->rt] = 1;
00489         else
00490             registers[instr->rt] = 0;
00491         break;
00492         
00493       case OP_SLTIU:      
00494         rs = registers[instr->rs];
00495         imm = instr->extra;
00496         if (rs < imm)
00497             registers[instr->rt] = 1;
00498         else
00499             registers[instr->rt] = 0;
00500         break;
00501         
00502       case OP_SLTU:       
00503         rs = registers[instr->rs];
00504         rt = registers[instr->rt];
00505         if (rs < rt)
00506             registers[instr->rd] = 1;
00507         else
00508             registers[instr->rd] = 0;
00509         break;
00510         
00511       case OP_SRA:
00512         registers[instr->rd] = registers[instr->rt] >> instr->extra;
00513         break;
00514         
00515       case OP_SRAV:
00516         registers[instr->rd] = registers[instr->rt] >>
00517             (registers[instr->rs] & 0x1f);
00518         break;
00519         
00520       case OP_SRL:
00521         tmp = registers[instr->rt];
00522         tmp >>= instr->extra;
00523         registers[instr->rd] = tmp;
00524         break;
00525         
00526       case OP_SRLV:
00527         tmp = registers[instr->rt];
00528         tmp >>= (registers[instr->rs] & 0x1f);
00529         registers[instr->rd] = tmp;
00530         break;
00531         
00532       case OP_SUB:        
00533         diff = registers[instr->rs] - registers[instr->rt];
00534         if (((registers[instr->rs] ^ registers[instr->rt]) & SIGN_BIT) &&
00535             ((registers[instr->rs] ^ diff) & SIGN_BIT)) {
00536             RaiseException(OverflowException, 0);
00537             return;
00538         }
00539         registers[instr->rd] = diff;
00540         break;
00541         
00542       case OP_SUBU:
00543         registers[instr->rd] = registers[instr->rs] - registers[instr->rt];
00544         break;
00545         
00546       case OP_SW:
00547         if (!WriteMem((unsigned) 
00548                 (registers[instr->rs] + instr->extra), 4, registers[instr->rt]))
00549             return;
00550         break;
00551         
00552       case OP_SWL:        
00553         tmp = registers[instr->rs] + instr->extra;
00554 
00555 #ifdef SIM_FIX
00556         // The only difference between this code and the BIG ENDIAN code
00557         // is that the ReadMem call is guaranteed an aligned access as it
00558         // should be (Kane's book hides the fact that all memory access
00559         // are done using aligned loads - what the instruction asks for
00560         // is a arbitrary) This is the whole purpose of LWL and LWR etc.
00561 
00562         byte = tmp & 0x3;
00563         // DEBUG('P', "Addr 0x%X\n",tmp-byte);
00564         if (!ReadMem(tmp-byte, 4, &value))
00565             return;
00566 
00567         // DEBUG('P', "Value 0x%X\n",value);
00568 #else
00569 
00570         // The little endian/big endian swap code would
00571         // fail (I think) if the other cases are ever exercised.
00572         ASSERT((tmp & 0x3) == 0);  
00573 
00574         if (!ReadMem((tmp & ~0x3), 4, &value))
00575             return;
00576 #endif
00577 
00578 #ifdef SIM_FIX
00579         switch( 3 - byte )
00580 #else
00581           switch (tmp & 0x3) 
00582 #endif // SIM_FIX
00583             {
00584           case 0:
00585             value = registers[instr->rt];
00586             break;
00587           case 1:
00588             value = (value & 0xff000000) | ((registers[instr->rt] >> 8) &
00589                                             0xffffff);
00590             break;
00591           case 2:
00592             value = (value & 0xffff0000) | ((registers[instr->rt] >> 16) &
00593                                             0xffff);
00594             break;
00595           case 3:
00596             value = (value & 0xffffff00) | ((registers[instr->rt] >> 24) &
00597                                             0xff);
00598             break;
00599         }
00600 #ifndef SIM_FIX
00601         if (!WriteMem((tmp & ~0x3), 4, value))
00602             return;
00603 #else
00604         // DEBUG('P', "Value 0x%X\n",value);
00605 
00606         if (!WriteMem((tmp - byte), 4, value))
00607             return;
00608 #endif // SIM_FIX
00609         break;
00610         
00611       case OP_SWR:        
00612         tmp = registers[instr->rs] + instr->extra;
00613 
00614 #ifndef SIM_FIX
00615         // The little endian/big endian swap code would
00616         // fail (I think) if the other cases are ever exercised.
00617         ASSERT((tmp & 0x3) == 0);  
00618 
00619         if (!ReadMem((tmp & ~0x3), 4, &value))
00620             return;
00621 #else
00622         // The only difference between this code and the BIG ENDIAN code
00623         // is that the ReadMem call is guaranteed an aligned access as 
00624         // it should be (Kane's book hides the fact that all memory 
00625         // access are done using aligned loads - what the instruction 
00626         // asks for is a arbitrary) This is the whole purpose of LWL 
00627         // and LWR etc.
00628 
00629         byte = tmp & 0x3;
00630         // DEBUG('P', "Addr 0x%X\n",tmp-byte);
00631 
00632         if (!ReadMem(tmp-byte, 4, &value))
00633             return;
00634         // DEBUG('P', "Value 0x%X\n",value);
00635 #endif // SIM_FIX
00636 
00637 #ifndef SIM_FIX
00638         switch (tmp & 0x3) 
00639 #else
00640           switch( 3 - byte ) 
00641 #endif // SIM_FIX
00642             {
00643             case 0:
00644             value = (value & 0xffffff) | (registers[instr->rt] << 24);
00645             break;
00646           case 1:
00647             value = (value & 0xffff) | (registers[instr->rt] << 16);
00648             break;
00649           case 2:
00650             value = (value & 0xff) | (registers[instr->rt] << 8);
00651             break;
00652           case 3:
00653             value = registers[instr->rt];
00654             break;
00655         }
00656 
00657 #ifndef SIM_FIX
00658         if (!WriteMem((tmp & ~0x3), 4, value))
00659             return;
00660 #else
00661         // DEBUG('P', "Value 0x%X\n",value);
00662 
00663         if (!WriteMem((tmp - byte), 4, value))
00664             return;
00665 #endif // SIM_FIX
00666 
00667 
00668         break;
00669         
00670       case OP_SYSCALL:
00671         RaiseException(SyscallException, 0);
00672         return; 
00673         
00674       case OP_XOR:
00675         registers[instr->rd] = registers[instr->rs] ^ registers[instr->rt];
00676         break;
00677         
00678       case OP_XORI:
00679         registers[instr->rt] = registers[instr->rs] ^ (instr->extra & 0xffff);
00680         break;
00681         
00682       case OP_RES:
00683       case OP_UNIMP:
00684         RaiseException(IllegalInstrException, 0);
00685         return;
00686         
00687       default:
00688         ASSERT(FALSE);
00689     }
00690     
00691     // Now we have successfully executed the instruction.
00692     
00693     // Do any delayed load operation
00694     DelayedLoad(nextLoadReg, nextLoadValue);
00695     
00696     // Advance program counters.
00697     registers[PrevPCReg] = registers[PCReg];    // for debugging, in case we
00698                                                 // are jumping into lala-land
00699     registers[PCReg] = registers[NextPCReg];
00700     registers[NextPCReg] = pcAfter;
00701 }
00702 
00703 //----------------------------------------------------------------------
00704 // Machine::DelayedLoad
00705 //      Simulate effects of a delayed load.
00706 //
00707 //      NOTE -- RaiseException/CheckInterrupts must also call DelayedLoad,
00708 //      since any delayed load must get applied before we trap to the kernel.
00709 //----------------------------------------------------------------------
00710 
00711 void
00712 Machine::DelayedLoad(int nextReg, int nextValue)
00713 {
00714     registers[registers[LoadReg]] = registers[LoadValueReg];
00715     registers[LoadReg] = nextReg;
00716     registers[LoadValueReg] = nextValue;
00717     registers[0] = 0;   // and always make sure R0 stays zero.
00718 }
00719 
00720 //----------------------------------------------------------------------
00721 // Instruction::Decode
00722 //      Decode a MIPS instruction 
00723 //----------------------------------------------------------------------
00724 
00725 void
00726 Instruction::Decode()
00727 {
00728     OpInfo *opPtr;
00729     
00730     rs = (value >> 21) & 0x1f;
00731     rt = (value >> 16) & 0x1f;
00732     rd = (value >> 11) & 0x1f;
00733     opPtr = &opTable[(value >> 26) & 0x3f];
00734     opCode = opPtr->opCode;
00735     if (opPtr->format == IFMT) {
00736         extra = value & 0xffff;
00737         if (extra & 0x8000) {
00738            extra |= 0xffff0000;
00739         }
00740     } else if (opPtr->format == RFMT) {
00741         extra = (value >> 6) & 0x1f;
00742     } else {
00743         extra = value & 0x3ffffff;
00744     }
00745     if (opCode == SPECIAL) {
00746         opCode = specialTable[value & 0x3f];
00747     } else if (opCode == BCOND) {
00748         int i = value & 0x1f0000;
00749 
00750         if (i == 0) {
00751             opCode = OP_BLTZ;
00752         } else if (i == 0x10000) {
00753             opCode = OP_BGEZ;
00754         } else if (i == 0x100000) {
00755             opCode = OP_BLTZAL;
00756         } else if (i == 0x110000) {
00757             opCode = OP_BGEZAL;
00758         } else {
00759             opCode = OP_UNIMP;
00760         }
00761     }
00762 }
00763 
00764 //----------------------------------------------------------------------
00765 // Mult
00766 //      Simulate R2000 multiplication.
00767 //      The words at *hiPtr and *loPtr are overwritten with the
00768 //      double-length result of the multiplication.
00769 //----------------------------------------------------------------------
00770 
00771 static void
00772 Mult(int a, int b, bool signedArith, int* hiPtr, int* loPtr)
00773 {
00774     if ((a == 0) || (b == 0)) {
00775         *hiPtr = *loPtr = 0;
00776         return;
00777     }
00778 
00779     // Compute the sign of the result, then make everything positive
00780     // so unsigned computation can be done in the main loop.
00781     bool negative = FALSE;
00782     if (signedArith) {
00783         if (a < 0) {
00784             negative = !negative;
00785             a = -a;
00786         }
00787         if (b < 0) {
00788             negative = !negative;
00789             b = -b;
00790         }
00791     }
00792 
00793     // Compute the result in unsigned arithmetic (check a's bits one at
00794     // a time, and add in a shifted value of b).
00795     unsigned int bLo = b;
00796     unsigned int bHi = 0;
00797     unsigned int lo = 0;
00798     unsigned int hi = 0;
00799     for (int i = 0; i < 32; i++) {
00800         if (a & 1) {
00801             lo += bLo;
00802             if (lo < bLo)  // Carry out of the low bits?
00803                 hi += 1;
00804             hi += bHi;
00805             if ((a & 0xfffffffe) == 0)
00806                 break;
00807         }
00808         bHi <<= 1;
00809         if (bLo & 0x80000000)
00810             bHi |= 1;
00811         
00812         bLo <<= 1;
00813         a >>= 1;
00814     }
00815 
00816     // If the result is supposed to be negative, compute the two's
00817     // complement of the double-word result.
00818     if (negative) {
00819         hi = ~hi;
00820         lo = ~lo;
00821         lo++;
00822         if (lo == 0)
00823             hi++;
00824     }
00825     
00826     *hiPtr = (int) hi;
00827     *loPtr = (int) lo;
00828 }

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