00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00028
00029
00030
00031
00032
00033
00034 class Instruction {
00035 public:
00036 void Decode();
00037
00038 unsigned int value;
00039
00040 char opCode;
00041
00042 char rs, rt, rd;
00043 int extra;
00044
00045 };
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 void
00057 Machine::Run()
00058 {
00059 Instruction *instr = new 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
00077
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
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 void
00121 Machine::OneInstruction(Instruction *instr)
00122 {
00123 #ifdef SIM_FIX
00124 int byte;
00125 #endif
00126
00127 int raw;
00128 int nextLoadReg = 0;
00129 int nextLoadValue = 0;
00130
00131
00132
00133 if (!ReadMem(registers[PCReg], 4, &raw))
00134 return;
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
00150 int pcAfter = registers[NextPCReg] + 4;
00151 int sum, diff, tmp, value;
00152 unsigned int rs, rt, imm;
00153
00154
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
00317
00318
00319
00320
00321
00322
00323 byte = tmp & 0x3;
00324
00325
00326 if (!ReadMem(tmp-byte, 4, &value))
00327 return;
00328 #else
00329
00330
00331
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
00369
00370
00371
00372
00373
00374
00375 byte = tmp & 0x3;
00376
00377
00378 if (!ReadMem(tmp-byte, 4, &value))
00379 return;
00380 #else
00381
00382
00383
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 ®isters[HiReg], ®isters[LoReg]);
00439 break;
00440
00441 case OP_MULTU:
00442 Mult(registers[instr->rs], registers[instr->rt], FALSE,
00443 ®isters[HiReg], ®isters[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
00557
00558
00559
00560
00561
00562 byte = tmp & 0x3;
00563
00564 if (!ReadMem(tmp-byte, 4, &value))
00565 return;
00566
00567
00568 #else
00569
00570
00571
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
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
00616
00617 ASSERT((tmp & 0x3) == 0);
00618
00619 if (!ReadMem((tmp & ~0x3), 4, &value))
00620 return;
00621 #else
00622
00623
00624
00625
00626
00627
00628
00629 byte = tmp & 0x3;
00630
00631
00632 if (!ReadMem(tmp-byte, 4, &value))
00633 return;
00634
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
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
00692
00693
00694 DelayedLoad(nextLoadReg, nextLoadValue);
00695
00696
00697 registers[PrevPCReg] = registers[PCReg];
00698
00699 registers[PCReg] = registers[NextPCReg];
00700 registers[NextPCReg] = pcAfter;
00701 }
00702
00703
00704
00705
00706
00707
00708
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;
00718 }
00719
00720
00721
00722
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
00766
00767
00768
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
00780
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
00794
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)
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
00817
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 }