00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "copyright.h"
00014
00015 #include "machine.h"
00016 #include "mipssim.h"
00017 #include "system.h"
00018
00019 static void Mult(int a, int b, bool signedArith, int* hiPtr, int* loPtr);
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 void
00031 Machine::Run()
00032 {
00033 Instruction *instr = new 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 }
00046
00047
00048
00049
00050
00051
00052
00053 static int
00054 TypeToReg(RegType reg, Instruction *instr)
00055 {
00056 switch (reg) {
00057 case RS:
00058 return instr->rs;
00059 case RT:
00060 return instr->rt;
00061 case RD:
00062 return instr->rd;
00063 case EXTRA:
00064 return instr->extra;
00065 default:
00066 return -1;
00067 }
00068 }
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 void
00094 Machine::OneInstruction(Instruction *instr)
00095 {
00096 int raw;
00097 int nextLoadReg = 0;
00098 int nextLoadValue = 0;
00099
00100
00101
00102 if (!machine->ReadMem(registers[PCReg], 4, &raw))
00103 return;
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
00118 int pcAfter = registers[NextPCReg] + 4;
00119 int sum, diff, tmp, value;
00120 unsigned int rs, rt, imm;
00121
00122
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
00284
00285
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
00315
00316
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 ®isters[HiReg], ®isters[LoReg]);
00364 break;
00365
00366 case OP_MULTU:
00367 Mult(registers[instr->rs], registers[instr->rt], FALSE,
00368 ®isters[HiReg], ®isters[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
00481
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
00511
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
00556
00557
00558 DelayedLoad(nextLoadReg, nextLoadValue);
00559
00560
00561 registers[PrevPCReg] = registers[PCReg];
00562
00563 registers[PCReg] = registers[NextPCReg];
00564 registers[NextPCReg] = pcAfter;
00565 }
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575 void
00576 Machine::DelayedLoad(int nextReg, int nextValue)
00577 {
00578 registers[registers[LoadReg]] = registers[LoadValueReg];
00579 registers[LoadReg] = nextReg;
00580 registers[LoadValueReg] = nextValue;
00581 registers[0] = 0;
00582 }
00583
00584
00585
00586
00587
00588
00589 void
00590 Instruction::Decode()
00591 {
00592 OpInfo *opPtr;
00593
00594 rs = (value >> 21) & 0x1f;
00595 rt = (value >> 16) & 0x1f;
00596 rd = (value >> 11) & 0x1f;
00597 opPtr = &opTable[(value >> 26) & 0x3f];
00598 opCode = opPtr->opCode;
00599 if (opPtr->format == IFMT) {
00600 extra = value & 0xffff;
00601 if (extra & 0x8000) {
00602 extra |= 0xffff0000;
00603 }
00604 } else if (opPtr->format == RFMT) {
00605 extra = (value >> 6) & 0x1f;
00606 } else {
00607 extra = value & 0x3ffffff;
00608 }
00609 if (opCode == SPECIAL) {
00610 opCode = specialTable[value & 0x3f];
00611 } else if (opCode == BCOND) {
00612 int i = value & 0x1f0000;
00613
00614 if (i == 0) {
00615 opCode = OP_BLTZ;
00616 } else if (i == 0x10000) {
00617 opCode = OP_BGEZ;
00618 } else if (i == 0x100000) {
00619 opCode = OP_BLTZAL;
00620 } else if (i == 0x110000) {
00621 opCode = OP_BGEZAL;
00622 } else {
00623 opCode = OP_UNIMP;
00624 }
00625 }
00626 }
00627
00628
00629
00630
00631
00632
00633
00634
00635 static void
00636 Mult(int a, int b, bool signedArith, int* hiPtr, int* loPtr)
00637 {
00638 if ((a == 0) || (b == 0)) {
00639 *hiPtr = *loPtr = 0;
00640 return;
00641 }
00642
00643
00644
00645 bool negative = FALSE;
00646 if (signedArith) {
00647 if (a < 0) {
00648 negative = !negative;
00649 a = -a;
00650 }
00651 if (b < 0) {
00652 negative = !negative;
00653 b = -b;
00654 }
00655 }
00656
00657
00658
00659 unsigned int bLo = b;
00660 unsigned int bHi = 0;
00661 unsigned int lo = 0;
00662 unsigned int hi = 0;
00663 for (int i = 0; i < 32; i++) {
00664 if (a & 1) {
00665 lo += bLo;
00666 if (lo < bLo)
00667 hi += 1;
00668 hi += bHi;
00669 if ((a & 0xfffffffe) == 0)
00670 break;
00671 }
00672 bHi <<= 1;
00673 if (bLo & 0x80000000)
00674 bHi |= 1;
00675
00676 bLo <<= 1;
00677 a >>= 1;
00678 }
00679
00680
00681
00682 if (negative) {
00683 hi = ~hi;
00684 lo = ~lo;
00685 lo++;
00686 if (lo == 0)
00687 hi++;
00688 }
00689
00690 *hiPtr = (int) hi;
00691 *loPtr = (int) lo;
00692 }
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