📄 opcodes.c
字号:
return SUCCESS;}OP(mfhiOp){ uint rd = RD(instr); P->R[rd] = P->HI; return SUCCESS;}OP(mfloOp){ uint rd = RD(instr); P->R[rd] = P->LO; return SUCCESS;}OP(movcOp){ uint rd = RD(instr); int retval = 0; StatusReg statusReg; /* Need to make sure xx is enable if not in kernel mode */ statusReg.ts_data = P->CP0[C0_SR]; if (IS_USER_MODE(P) && !(statusReg.s32.ts_xx)) { EXCEPTION(P, EXC_II); return FAILURE; } retval = ExecuteC1Instruction(P, instr); if (retval != C1_SUCCESS) { ASSERT(retval == C1_CONTINUE); return FAILURE; } return SUCCESS; }OP(movnOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; StatusReg statusReg; /* Need to make sure xx is enable if not in kernel mode */ statusReg.ts_data = P->CP0[C0_SR]; if (IS_USER_MODE(P) && !(statusReg.s32.ts_xx)) { EXCEPTION(P, EXC_II); return FAILURE; } if (contents_rt != 0) { P->R[rd] = contents_rs; } return SUCCESS; }OP(movzOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; StatusReg statusReg; /* Need to make sure xx is enable if not in kernel mode */ statusReg.ts_data = P->CP0[C0_SR]; if (IS_USER_MODE(P) && !(statusReg.s32.ts_xx)) { EXCEPTION(P, EXC_II); return FAILURE; } if (contents_rt == 0) { P->R[rd] = contents_rs; } return SUCCESS; }OP(mthiOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; P->HI = contents_rs; return SUCCESS;}OP(mtloOp){ Reg_s contents_rs = P->R[RS(instr)]; P->LO = contents_rs; return SUCCESS;}OP(multOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; bool negative = FALSE; if (contents_rs < 0) { negative = TRUE; contents_rs = -contents_rs; } if (contents_rt < 0) { negative = !negative; contents_rt = -contents_rt; } LongMultiply32(P,(Reg32)contents_rs, (Reg32)contents_rt); if (negative) { P->LO = ~P->LO; P->HI = ~P->HI; P->LO += 1; if (P->LO == 0) P->HI += 1; } return SUCCESS;}OP(multuOp){ Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; LongMultiply32(P,(Reg32)contents_rs, (Reg32)contents_rt); return SUCCESS;}OP(norOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; P->R[rd] = ~ (contents_rs | contents_rt); return SUCCESS;}OP(orOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; P->R[rd] = contents_rs | contents_rt; return SUCCESS;}OP(sllOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; P->R[rd] = (Reg32_s)contents_rt << SHAMT(instr); return SUCCESS;}OP(sllvOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; P->R[rd] = (Reg32_s)contents_rt << (contents_rs & 0x1f); return SUCCESS;}OP(sltOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; if (contents_rs < contents_rt) P->R[rd] = 1; else P->R[rd] = 0; return SUCCESS;}OP(sltuOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; if ((Reg) contents_rs < (Reg) contents_rt) P->R[rd] = 1; else P->R[rd] = 0; return SUCCESS;}OP(sraOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; P->R[rd] = (Reg32_s)contents_rt >> SHAMT(instr); return SUCCESS;}OP(sravOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; P->R[rd] = (Reg32_s)contents_rt >> (contents_rs & 0x1f); return SUCCESS;}OP(srlOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; P->R[rd] = (Reg32_s)(((Reg32) contents_rt) >> SHAMT(instr)); return SUCCESS;}OP(srlvOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; P->R[rd] = (Reg32_s)((Reg32) contents_rt >> (contents_rs & 0x1f)); return SUCCESS;}OP(subOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; Reg32_s diff; diff = (Reg32_s)contents_rs - (Reg32_s)contents_rt; if (SIGN_BIT32(contents_rs) != SIGN_BIT32(contents_rt) && SIGN_BIT32(contents_rs) != SIGN_BIT32(diff)) { EXCEPTION(P, EXC_OV); return FAILURE; } P->R[rd] = diff; return SUCCESS;}OP(subuOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; P->R[rd] = (Reg32_s)((Reg32) contents_rs - (Reg32) contents_rt); return SUCCESS;}OP(syncOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; if (SKIP_CACHES(P)) { CPUPrint("Sync called at %#x with caches off\n", P->PC); } else { Result ret = MemRefSync(P->myNum); if (ret == STALL) { if (STATS_VALUE(P->myNum, syncOpStallStart) == 0) { STATS_SET(P->myNum, syncOpStallStart, MipsyReadTime(P->myNum)); } P->stalledInst = instr; /* Retry on the next cycle */ return FAILURE; } } /* A sync has now completed */ STATS_INC(P->myNum, syncOps, 1); STATS_ADD_INTERVAL(P->myNum, syncOpStallTime, syncOpStallStart); return SUCCESS;}OP(syscallOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; /* This value is added to system calls to avoid conflicts with BSD */#define SYSVoffset 1000 int syscallNum = P->R[REG_V0] - SYSVoffset; #ifdef SOLO if (syscallNum == 1) { CPUWarning("Exit syscall hit\n"); MipsyExit(BASE);#ifdef notdef return FAILURE; /* MipsyRun will return to "main" in SOLO */#endif } else { /* Let the underlying OS handle the system call */ if (SoloEmulateSyscall(P->myNum,syscallNum) == STALL) { if (P->cpuStatus != cpu_running) { P->stalledInst = instr; STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum)); SIM_DEBUG(('o', "Syscall stalled\n")); } return FAILURE; /* If system call emulation is not complete, we need to restart this instruction after the stall comes back!! */ } } SIM_DEBUG(('o', "Syscall %s by CPU %d\n", syscallName[syscallNum], P->myNum)); STATS_INC(P->myNum, numSyscalls, 1); STATS_INC(P->myNum, syscallCount[syscallNum], 1); return SUCCESS;#else STATS_INC(P->myNum, numSyscalls, 1); if ((syscallNum < MAX_SYSCALL) && (syscallNum >= 0)) { STATS_INC(P->myNum, syscallCount[syscallNum], 1); } EXCEPTION(P, EXC_SYSCALL); return FAILURE;#endif}OP(teqOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; if (contents_rs == contents_rt) { EXCEPTION(P, EXC_TRAP); return FAILURE; } return SUCCESS;}OP(tgeOp){ Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; if (contents_rs >= contents_rt) { EXCEPTION(P, EXC_TRAP); return FAILURE; } return SUCCESS;}OP(tgeuOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; if ((Reg)contents_rs >= (Reg)contents_rt) { EXCEPTION(P, EXC_TRAP); return FAILURE; } return SUCCESS;}OP(tltOp){ Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; if (contents_rs < contents_rt) { EXCEPTION(P, EXC_TRAP); return FAILURE; } return SUCCESS;}OP(tltuOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; if ((Reg)contents_rs < (Reg)contents_rt) { EXCEPTION(P, EXC_TRAP); return FAILURE; } return SUCCESS;}OP(tneOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; if (contents_rs != contents_rt) { EXCEPTION(P, EXC_TRAP); return FAILURE; } return SUCCESS;}OP(xorOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; P->R[rd] = contents_rs ^ contents_rt; return SUCCESS;}OP(unknownSpecOp) { CPUWarning("Illegal inst at %#llx on CPU %d RA %#llx\n", (Reg64)P->PC, P->myNum, (Reg64)P->R[REG_RA]); EXCEPTION(P, EXC_II); return FAILURE;}/***************************************************************** * B C O N D O P C O D E S *****************************************************************/OP(bgezOp){ Reg_s contents_rs = P->R[RS(instr)]; int immediate = IMMED(instr); Reg32_s offset = SIGN_EXTEND32(18, (immediate << 2)); if (!(SIGN_BIT(contents_rs))) { P->branchTarget = P->nPC + offset; P->branchStatus = BranchStatus_taken; } else { P->branchStatus = BranchStatus_nottaken; } return SUCCESS;} OP(bgezlOp){ Reg_s contents_rs = P->R[RS(instr)]; int immediate = IMMED(instr); Reg32_s offset = SIGN_EXTEND32(18, (immediate << 2)); if (!(SIGN_BIT(contents_rs))) { P->branchTarget = P->nPC + offset; P->branchStatus = BranchStatus_taken; } else { /* Skip instruction in delay slot */ P->nPC = P->nPC + 4; } return SUCCESS;} OP(bgezalOp){ Reg_s contents_rs = P->R[RS(instr)]; int immediate = IMMED(instr); Reg32_s offset = SIGN_EXTEND32(18, (immediate << 2)); P->R[REG_RA] = P->nPC + 4; if (!(SIGN_BIT(contents_rs))) { P->branchTarget = P->nPC + offset; P->branchStatus = BranchStatus_taken; } else { P->branchStatus = BranchStatus_nottaken; } return SUCCESS;} OP(bgezallOp){ Reg_s contents_rs = P->R[RS(instr)]; int immediate = IMMED(instr); Reg32_s offset = SIGN_EXTEND32(18, (immediate << 2)); P->R[REG_RA] = P->nPC + 4; if (!(SIGN_BIT(contents_rs))) { P->branchTarget = P->nPC + offset; P->branchStatus = BranchStatus_taken; } else { /* Skip instruction in delay slot */ P->nPC = P->nPC + 4; } return SUCCESS;} OP(bltzOp){ Reg_s contents_rs = P->R[RS(instr)]; int immediate = IMMED(instr); Reg32_s offset = SIGN_EXTEND32(18, (immediate << 2)); if (SIGN_BIT(contents_rs)) { P->branchTarget = P->nPC + offset; P->branchStatus = BranchStatus_taken; } else { P->branchStatus = BranchStatus_nottaken; } return SUCCESS;} OP(bltzlOp){ Reg_s contents_rs = P->R[RS(instr)]; int immediate = IMMED(instr); Reg32_s offset = SIGN_EXTEND32(18, (immediate << 2)); if (SIGN_BIT(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -