📄 mipssim.cc
字号:
case OP_MFLO: registers[instr->rd] = registers[LoReg]; break; case OP_MTHI: registers[HiReg] = registers[instr->rs]; break; case OP_MTLO: registers[LoReg] = registers[instr->rs]; break; case OP_MULT: Mult(registers[instr->rs], registers[instr->rt], TRUE, ®isters[HiReg], ®isters[LoReg]); break; case OP_MULTU: Mult(registers[instr->rs], registers[instr->rt], FALSE, ®isters[HiReg], ®isters[LoReg]); break; case OP_NOR: registers[instr->rd] = ~(registers[instr->rs] | registers[instr->rt]); break; case OP_OR: registers[instr->rd] = registers[instr->rs] | registers[instr->rs]; break; case OP_ORI: registers[instr->rt] = registers[instr->rs] | (instr->extra & 0xffff); break; case OP_SB: if (!machine->WriteMem((unsigned) (registers[instr->rs] + instr->extra), 1, registers[instr->rt])) return; break; case OP_SH: if (!machine->WriteMem((unsigned) (registers[instr->rs] + instr->extra), 2, registers[instr->rt])) return; break; case OP_SLL: registers[instr->rd] = registers[instr->rt] << instr->extra; break; case OP_SLLV: registers[instr->rd] = registers[instr->rt] << (registers[instr->rs] & 0x1f); break; case OP_SLT: if (registers[instr->rs] < registers[instr->rt]) registers[instr->rd] = 1; else registers[instr->rd] = 0; break; case OP_SLTI: if (registers[instr->rs] < instr->extra) registers[instr->rt] = 1; else registers[instr->rt] = 0; break; case OP_SLTIU: rs = registers[instr->rs]; imm = instr->extra; if (rs < imm) registers[instr->rt] = 1; else registers[instr->rt] = 0; break; case OP_SLTU: rs = registers[instr->rs]; rt = registers[instr->rt]; if (rs < rt) registers[instr->rd] = 1; else registers[instr->rd] = 0; break; case OP_SRA: registers[instr->rd] = registers[instr->rt] >> instr->extra; break; case OP_SRAV: registers[instr->rd] = registers[instr->rt] >> (registers[instr->rs] & 0x1f); break; case OP_SRL: tmp = registers[instr->rt]; tmp >>= instr->extra; registers[instr->rd] = tmp; break; case OP_SRLV: tmp = registers[instr->rt]; tmp >>= (registers[instr->rs] & 0x1f); registers[instr->rd] = tmp; break; case OP_SUB: diff = registers[instr->rs] - registers[instr->rt]; if (((registers[instr->rs] ^ registers[instr->rt]) & SIGN_BIT) && ((registers[instr->rs] ^ diff) & SIGN_BIT)) { RaiseException(OverflowException, 0); return; } registers[instr->rd] = diff; break; case OP_SUBU: registers[instr->rd] = registers[instr->rs] - registers[instr->rt]; break; case OP_SW: if (!machine->WriteMem((unsigned) (registers[instr->rs] + instr->extra), 4, registers[instr->rt])) return; break; case OP_SWL: tmp = registers[instr->rs] + instr->extra; // The little endian/big endian swap code would // fail (I think) if the other cases are ever exercised. ASSERT((tmp & 0x3) == 0); if (!machine->ReadMem((tmp & ~0x3), 4, &value)) return; switch (tmp & 0x3) { case 0: value = registers[instr->rt]; break; case 1: value = (value & 0xff000000) | ((registers[instr->rt] >> 8) & 0xffffff); break; case 2: value = (value & 0xffff0000) | ((registers[instr->rt] >> 16) & 0xffff); break; case 3: value = (value & 0xffffff00) | ((registers[instr->rt] >> 24) & 0xff); break; } if (!machine->WriteMem((tmp & ~0x3), 4, value)) return; break; case OP_SWR: tmp = registers[instr->rs] + instr->extra; // The little endian/big endian swap code would // fail (I think) if the other cases are ever exercised. ASSERT((tmp & 0x3) == 0); if (!machine->ReadMem((tmp & ~0x3), 4, &value)) return; switch (tmp & 0x3) { case 0: value = (value & 0xffffff) | (registers[instr->rt] << 24); break; case 1: value = (value & 0xffff) | (registers[instr->rt] << 16); break; case 2: value = (value & 0xff) | (registers[instr->rt] << 8); break; case 3: value = registers[instr->rt]; break; } if (!machine->WriteMem((tmp & ~0x3), 4, value)) return; break; case OP_SYSCALL: RaiseException(SyscallException, 0); return; case OP_XOR: registers[instr->rd] = registers[instr->rs] ^ registers[instr->rt]; break; case OP_XORI: registers[instr->rt] = registers[instr->rs] ^ (instr->extra & 0xffff); break; case OP_RES: case OP_UNIMP: RaiseException(IllegalInstrException, 0); return; default: ASSERT(FALSE); } // Now we have successfully executed the instruction. // Do any delayed load operation DelayedLoad(nextLoadReg, nextLoadValue); // Advance program counters. registers[PrevPCReg] = registers[PCReg]; // for debugging, in case we // are jumping into lala-land registers[PCReg] = registers[NextPCReg]; registers[NextPCReg] = pcAfter;}//----------------------------------------------------------------------// Machine::DelayedLoad// Simulate effects of a delayed load.//// NOTE -- RaiseException/CheckInterrupts must also call DelayedLoad,// since any delayed load must get applied before we trap to the kernel.//----------------------------------------------------------------------voidMachine::DelayedLoad(int nextReg, int nextValue){ registers[registers[LoadReg]] = registers[LoadValueReg]; registers[LoadReg] = nextReg; registers[LoadValueReg] = nextValue; registers[0] = 0; // and always make sure R0 stays zero.}//----------------------------------------------------------------------// Instruction::Decode// Decode a MIPS instruction //----------------------------------------------------------------------voidInstruction::Decode(){ OpInfo *opPtr; rs = (value >> 21) & 0x1f; rt = (value >> 16) & 0x1f; rd = (value >> 11) & 0x1f; opPtr = &opTable[(value >> 26) & 0x3f]; opCode = opPtr->opCode; if (opPtr->format == IFMT) { extra = value & 0xffff; if (extra & 0x8000) { extra |= 0xffff0000; } } else if (opPtr->format == RFMT) { extra = (value >> 6) & 0x1f; } else { extra = value & 0x3ffffff; } if (opCode == SPECIAL) { opCode = specialTable[value & 0x3f]; } else if (opCode == BCOND) { int i = value & 0x1f0000; if (i == 0) { opCode = OP_BLTZ; } else if (i == 0x10000) { opCode = OP_BGEZ; } else if (i == 0x100000) { opCode = OP_BLTZAL; } else if (i == 0x110000) { opCode = OP_BGEZAL; } else { opCode = OP_UNIMP; } }}//----------------------------------------------------------------------// Mult// Simulate R2000 multiplication.// The words at *hiPtr and *loPtr are overwritten with the// double-length result of the multiplication.//----------------------------------------------------------------------static voidMult(int a, int b, bool signedArith, int* hiPtr, int* loPtr){ if ((a == 0) || (b == 0)) { *hiPtr = *loPtr = 0; return; } // Compute the sign of the result, then make everything positive // so unsigned computation can be done in the main loop. bool negative = FALSE; if (signedArith) { if (a < 0) { negative = !negative; a = -a; } if (b < 0) { negative = !negative; b = -b; } } // Compute the result in unsigned arithmetic (check a's bits one at // a time, and add in a shifted value of b). unsigned int bLo = b; unsigned int bHi = 0; unsigned int lo = 0; unsigned int hi = 0; for (int i = 0; i < 32; i++) { if (a & 1) { lo += bLo; if (lo < bLo) // Carry out of the low bits? hi += 1; hi += bHi; if ((a & 0xfffffffe) == 0) break; } bHi <<= 1; if (bLo & 0x80000000) bHi |= 1; bLo <<= 1; a >>= 1; } // If the result is supposed to be negative, compute the two's // complement of the double-word result. if (negative) { hi = ~hi; lo = ~lo; lo++; if (lo == 0) hi++; } *hiPtr = (int) hi; *loPtr = (int) lo;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -