📄 opcodes.c
字号:
OP(cop1Op){ int retval = ExecuteC1Instruction(P, instr); if (retval != C1_SUCCESS) { ASSERT(retval == C1_CONTINUE); return FAILURE; } return SUCCESS;}OP(cop1xOp){ int immediate = IMMED(instr); uint rt = RT(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; } if (!(statusReg.s32.ts_cu1)) { CauseReg causeReg; causeReg.tc_data = P->CP0[C0_CAUSE]; causeReg.s32.tc_ce = 1; P->CP0[C0_CAUSE] = causeReg.tc_data; EXCEPTION(P, EXC_CPU); return FAILURE; } switch (FUNC(instr)) { case lwxc1_op: { Reg32_s data; VA vAddr; Reg base = P->R[RS(instr)]; vAddr = base + P->R[RT(instr)]; if (vAddr & 0x00000003) { RECORD_EXCEPTION(P, EXC_RADE, E_VEC, vAddr, P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]); return FAILURE; } if (MipsyReadMem(vAddr, &data, WORD_SZ, NO_FLAVOR) != SUCCESS) { if (P->cpuStatus != cpu_running) { P->stalledInst = instr; STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum)); } return FAILURE; } else { IntReg(rt) = data; break; } } case ldxc1_op: { Reg64 data; VA vAddr; Reg base = P->R[RS(instr)]; vAddr = base + P->R[RT(instr)]; if (vAddr & 0x00000007) { RECORD_EXCEPTION(P, EXC_RADE, E_VEC, vAddr, P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]); return FAILURE; } if (MipsyReadMem(vAddr, &data, DOUBLE_SZ, NO_FLAVOR) != SUCCESS) { if (P->cpuStatus != cpu_running) { P->stalledInst = instr; STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum)); } return FAILURE; } else { DoubleReg(rt) = *((double *)&data); break; } } case swxc1_op: { VA vAddr; Reg base = P->R[RS(instr)]; uint data = IntReg(rt); vAddr = base + P->R[RT(instr)]; if (vAddr & 0x00000003) { RECORD_EXCEPTION(P, EXC_WADE, E_VEC, vAddr, P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]); return FAILURE; } else { if (MipsyWriteMem(vAddr, &data, WORD_SZ, NO_FLAVOR) != SUCCESS) { if (P->cpuStatus != cpu_running) { P->stalledInst = instr; STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum)); } return FAILURE; } } break; } case sdxc1_op: { VA vAddr; Reg base = P->R[RS(instr)]; uint64 data = LongLongReg(rt); vAddr = base + P->R[RT(instr)]; if (vAddr & 0x00000007) { RECORD_EXCEPTION(P, EXC_WADE, E_VEC, vAddr, P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]); return FAILURE; } else { if (MipsyWriteMem(vAddr, &data, DOUBLE_SZ, NO_FLAVOR) != SUCCESS) { if (P->cpuStatus != cpu_running) { P->stalledInst = instr; STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum)); } return FAILURE; } } break; } case pfetch_op: { VA vAddr; Reg base = P->R[RS(instr)]; uint hint = RD(instr); Result ret; vAddr = (base + P->R[RT(instr)]); ret = Prefetch(P,vAddr, hint); if (ret == STALL) { P->cpuStatus = cpu_stalled; P->stalledInst = instr; STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum)); return FAILURE; } break; } default: retval = ExecuteC1Instruction(P, instr); if (retval != C1_SUCCESS) { ASSERT(retval == C1_CONTINUE); return FAILURE; } break; } return SUCCESS;}OP(cop2Op){ CPUWarning("COP2 (MDMX) instruction at PC %#llx\n", (Reg64)P->PC); return ExecuteMDMXInstruction(P, instr);}OP(undefOp){ 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;}/***************************************************************** * S P E C O P C O D E S *****************************************************************/OP(addOp){ Reg32_s result32; uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; result32 = (Reg32_s) contents_rs + (Reg32_s)contents_rt; if (ARITH_OVFL32 (result32, (Reg32_s)contents_rs, (Reg32_s)contents_rt)) { EXCEPTION(P, EXC_OV); return FAILURE; } /* Don't write this if there was an exception */ P->R[rd] = result32; return SUCCESS;}OP(adduOp){ 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_rs + (Reg32_s)contents_rt; return SUCCESS;}OP(andOp){ 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(breakOp) { uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)];#if 0 /* matthewc hack */#define BREAK_CODE(_inst) (((unsigned)_inst >> 16 ) & 0x3ff ) if (IS_KERNEL_MODE(P) || ((IS_SUPERV_MODE(P) && (BREAK_CODE(instr) < 0x99)))) {#endif rd = MipsyDebug(P->myNum, 1); if (rd) { /* this is an alternate path around the end of the loop * if the PC should not increment. The only case that uses * it currently is when a break instruction is hit. * * We also skip the check for post-PC annotations: their * exactly-once semantics means we should execute them * after the reexecution. */#if 0 /* matthewc hack */ CPUWarning("BREAK OP at %#x (rd = %d)\n", P->PC, rd); /* used to be CPUError -- PZ */ FIX_REG_ZERO; INSTRUCTION_DONE_EVENT();#endif return FAILURE; }#if 0 /* matthewc hack */ } else { EXCEPTION(P, EXC_BREAK); return FAILURE; }#endif return SUCCESS;} OP(daddOp){ Reg64_s result64; uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); result64 = contents_rs + contents_rt; if (ARITH_OVFL64 (result64, contents_rs, contents_rt)) { EXCEPTION(P, EXC_OV); return FAILURE; } /* Don't write this if there was an exception */ P->R[rd] = result64; return SUCCESS;}OP(dadduOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); P->R[rd] = contents_rs + contents_rt; return SUCCESS;}OP(ddivOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); if (contents_rt != 0) { P->LO = (Reg_s)contents_rs / (Reg_s)contents_rt; P->HI = (Reg_s)contents_rs % (Reg_s)contents_rt; } return SUCCESS;}OP(ddivuOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); if (contents_rt != 0) { P->LO = (Reg)contents_rs / (Reg)contents_rt; P->HI = (Reg)contents_rs % (Reg)contents_rt; } return SUCCESS;}OP(divOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; if (contents_rt != 0) { P->LO = (Reg32_s)contents_rs / (Reg32_s)contents_rt; P->HI = (Reg32_s)contents_rs % (Reg32_s)contents_rt; } return SUCCESS;}OP(divuOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; if (contents_rt != 0) { P->LO = (Reg32)contents_rs / (Reg32)contents_rt; P->HI = (Reg32)contents_rs % (Reg32)contents_rt; } return SUCCESS;}OP(dmultOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; bool negative = FALSE; CHECK_64BIT_ALLOWED(P); if ((Reg64_s)contents_rs < 0) { negative = TRUE; contents_rs = -contents_rs; } if ((Reg64_s)contents_rt < 0) { negative = !negative; contents_rt = -contents_rt; } LongMultiply64(P,contents_rs,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(dmultuOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); LongMultiply64(P,(Reg64)contents_rs, (Reg64)contents_rt); return SUCCESS;}OP(dsllOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); P->R[rd] = (Reg_s)contents_rt << SHAMT(instr); return SUCCESS;}OP(dsllvOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); P->R[rd] = (Reg_s)contents_rt << (contents_rs & 0x3f); return SUCCESS;}OP(dsll32Op){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); P->R[rd] = (Reg_s)contents_rt << (SHAMT(instr)+32); return SUCCESS;}OP(dsraOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); P->R[rd] = (Reg64_s)contents_rt >> SHAMT(instr); return SUCCESS;}OP(dsravOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); P->R[rd] = (Reg64_s)contents_rt >> (contents_rs & 0x3f); return SUCCESS;}OP(dsra32Op){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); P->R[rd] = (Reg64_s)contents_rt >> (SHAMT(instr)+32); return SUCCESS;}OP(dsrlOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); P->R[rd] = ((Reg64) contents_rt) >> SHAMT(instr); return SUCCESS;}OP(dsrlvOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); P->R[rd] = ((Reg64) contents_rt) >> (contents_rs & 0x3f); return SUCCESS;}OP(dsrl32Op){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); P->R[rd] = ((Reg64) contents_rt) >> (SHAMT(instr)+32); return SUCCESS;}OP(dsubOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; Reg64_s diff; CHECK_64BIT_ALLOWED(P); diff = contents_rs - contents_rt; if (SIGN_BIT64(contents_rs) != SIGN_BIT64(contents_rt) && SIGN_BIT64(contents_rs) != SIGN_BIT64(diff)) { EXCEPTION(P, EXC_OV); return FAILURE; } P->R[rd] = diff; return SUCCESS;}OP(dsubuOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); P->R[rd] = ((Reg64)contents_rs - (Reg64)contents_rt); return SUCCESS;}OP(jalrOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; Reg_s contents_rt = P->R[RT(instr)]; P->R[rd] = P->nPC + 4; P->branchTarget = contents_rs; P->branchStatus = BranchStatus_taken; return SUCCESS;}OP(jrOp){ uint rd = RD(instr); Reg_s contents_rs = P->R[RS(instr)]; P->branchTarget = contents_rs; P->branchStatus = BranchStatus_taken;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -