📄 opcodes.c
字号:
Reg base = P->R[RS(instr)]; Result ret; uint data = P->R[RT(instr)]; vAddr = SIGN_EXTEND(16, immediate) + base; if (vAddr & 0x00000003) { EXCEPTION(P,EXC_WADE); return FAILURE; } if (UNCACHED_LL_SC) { if (P->LLbit) { /* This is a successful SC */ scSuccess = TRUE; numLLactive--; LLAddrs[P->myNum] = (PA) -1; } } ret = MipsyWriteMem(vAddr, &data, WORD_SZ, SC_FLAVOR); if (ret == STALL) { if (P->cpuStatus != cpu_running) { P->stalledInst = instr; STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum)); STATS_SET(P->myNum, syncStallStart, MipsyReadTime(P->myNum)); } return FAILURE; } else if (ret == FAILURE || ret == BUSERROR) { STATS_SET(P->myNum, syncStallStart, MipsyReadTime(P->myNum)); return FAILURE; } P->LLbit = 0; P->R[RT(instr)] = (ret == SUCCESS) ? 1 : 0; if (UNCACHED_LL_SC) { if (scSuccess) { P->R[RT(instr)] = 1; } else { P->R[RT(instr)] = 0; } } STATS_INC(P->myNum, syncStats.scs, 1); if (P->R[RT(instr)] == 0) { STATS_INC(P->myNum, syncStats.scFailed, 1); } STATS_ADD_INTERVAL(P->myNum, syncStats.scStallTime, syncStallStart); return SUCCESS;}OP(scdOp){ int immediate = IMMED(instr); VA vAddr; bool scSuccess = FALSE; Reg base = P->R[RS(instr)]; Result ret; uint64 data; CHECK_64BIT_ALLOWED(P); vAddr = SIGN_EXTEND(16, immediate) + base; if (vAddr & 0x00000007) { EXCEPTION(P,EXC_WADE); return FAILURE; } if (UNCACHED_LL_SC) { if (P->LLbit) { /* This is a successful SC */ scSuccess = TRUE; numLLactive--; LLAddrs[P->myNum] = (PA) -1; } } data = P->R[RT(instr)]; ret = MipsyWriteMem(vAddr, &data, DOUBLE_SZ, SC_FLAVOR); if (ret == STALL) { if (P->cpuStatus != cpu_running) { P->stalledInst = instr; STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum)); STATS_SET(P->myNum, syncStallStart, MipsyReadTime(P->myNum)); } return FAILURE; } else if (ret == FAILURE || ret == BUSERROR) { STATS_SET(P->myNum, syncStallStart, MipsyReadTime(P->myNum)); return FAILURE; } P->LLbit = 0; P->R[RT(instr)] = (ret == SUCCESS) ? 1 : 0; if (UNCACHED_LL_SC) { if (scSuccess) { P->R[RT(instr)] = 1; } else { P->R[RT(instr)] = 0; } } STATS_INC(P->myNum, syncStats.scs, 1); if (P->R[RT(instr)] == 0) { STATS_INC(P->myNum, syncStats.scFailed, 1); } STATS_ADD_INTERVAL(P->myNum, syncStats.scStallTime, syncStallStart); return SUCCESS;}OP(swOp){ int immediate = IMMED(instr); VA vAddr; Reg base = P->R[RS(instr)]; uint data = P->R[RT(instr)]; vAddr = SIGN_EXTEND(16, immediate) + base; if (vAddr & 0x00000003) { EXCEPTION(P,EXC_WADE); return FAILURE; } 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; } return SUCCESS;}OP(sdOp){ int immediate = IMMED(instr); VA vAddr; Reg base = P->R[RS(instr)]; uint64 data = 0; CHECK_64BIT_ALLOWED(P); vAddr = SIGN_EXTEND(16, immediate) + base; if (vAddr & 0x00000007) { EXCEPTION(P,EXC_WADE); return FAILURE; } else { data = P->R[RT(instr)]; 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; } } return SUCCESS;}OP(sdc2Op){ int immediate = IMMED(instr); /* * This instruction is different from the real machine. * see note under ld_op for details. */ VA vAddr; Reg base = P->R[RS(instr)]; uint64 data; vAddr = SIGN_EXTEND(16, immediate) + base; if (vAddr & 0x00000007) { EXCEPTION(P,EXC_WADE); return FAILURE; } if (SAME_ENDIAN) { ((uint *)&data)[0] = P->R[RT(instr)]; ((uint *)&data)[1] = P->R[RT(instr)+1]; } else { ((uint *)&data)[1] = P->R[RT(instr)]; ((uint *)&data)[0] = P->R[RT(instr)+1]; } 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; } return SUCCESS;}OP(sdc1Op){ int immediate = IMMED(instr); VA vAddr; Reg base = P->R[RS(instr)]; uint64 data = 0; StatusReg statusReg; statusReg.ts_data = P->CP0[C0_SR]; 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; } vAddr = SIGN_EXTEND(16, immediate) + base; if (vAddr & 0x00000007) { EXCEPTION(P,EXC_WADE); return FAILURE; } else { *((double *)&data) = DoubleReg(RT(instr)); 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; } } return SUCCESS;}OP(sdlOp){ int immediate = IMMED(instr); Reg64 data; int byte; VA vAddr; Reg base = P->R[RS(instr)]; Reg64 contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); vAddr = SIGN_EXTEND(16, immediate) + base; byte = vAddr & 0x7; vAddr &= (Reg32_s)~0x7; if (MipsyReadMem(vAddr, &data, DOUBLE_SZ, GETX_FLAVOR) != SUCCESS) { if (P->cpuStatus != cpu_running) { P->stalledInst = instr; STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum)); } return FAILURE; } else { /* Big Endian */ switch (byte) { case 0: data = contents_rt; break; case 1: data = (data & 0xff00000000000000LL) | (contents_rt >> 8 & 0x00ffffffffffffffLL); break; case 2: data = (data & 0xffff000000000000LL) | (contents_rt >> 16 & 0x0000ffffffffffffLL); break; case 3: data = (data & 0xffffff0000000000LL) | (contents_rt >> 24 & 0x000000ffffffffffLL); break; case 4: data = (data & 0xffffffff00000000LL) | (contents_rt >> 32 & 0x00000000ffffffffLL); break; case 5: data = (data & 0xffffffffff000000LL) | (contents_rt >> 40 & 0x0000000000ffffffLL); break; case 6: data = (data & 0xffffffffffff0000LL) | (contents_rt >> 48 & 0x000000000000ffffLL); break; case 7: data = (data & 0xffffffffffffff00LL) | (contents_rt >> 56 & 0x00000000000000ffLL); break; } 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; } } return SUCCESS;}OP(sdrOp){ int immediate = IMMED(instr); Reg64 data; uint byte; VA vAddr; Reg base = P->R[RS(instr)]; Reg64 contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); vAddr = SIGN_EXTEND(16, immediate) + base; byte = vAddr & 0x7; vAddr &= (Reg32_s)~0x7; if (MipsyReadMem(vAddr, &data, DOUBLE_SZ, GETX_FLAVOR) != SUCCESS) { if (P->cpuStatus != cpu_running) { P->stalledInst = instr; STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum)); } return FAILURE; } else { /* Big Endian */ switch (byte) { case 0: data = ((contents_rt << 56) & 0xff00000000000000LL) | (data & 0x00ffffffffffffffLL); break; case 1: data = ((contents_rt << 48) & 0xffff000000000000LL) | (data & 0x0000ffffffffffffLL); break; case 2: data = ((contents_rt << 40) & 0xffffff0000000000LL) | (data & 0x000000ffffffffffLL); break; case 3: data = ((contents_rt << 32) & 0xffffffff00000000LL) | (data & 0x00000000ffffffffLL); break; case 4: data = ((contents_rt << 24) & 0xffffffffff000000LL) | (data & 0x0000000000ffffffLL); break; case 5: data = ((contents_rt << 16) & 0xffffffffffff0000LL) | (data & 0x000000000000ffffLL); break; case 6: data = ((contents_rt << 8) & 0xffffffffffffff00LL) | (data & 0x00000000000000ffLL); break; case 7: data = contents_rt; break; } 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; } } return SUCCESS;}OP(swc1Op){ int immediate = IMMED(instr); VA vAddr; Reg base = P->R[RS(instr)]; StatusReg statusReg; uint data = IntReg(RT(instr)); statusReg.ts_data = P->CP0[C0_SR]; 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; } vAddr = SIGN_EXTEND(16, immediate) + base; if (vAddr & 0x00000003) { EXCEPTION(P,EXC_WADE); 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; } } return SUCCESS;}OP(swc2Op){ int immediate = IMMED(instr); CPUError("SWCx not implemented!\n"); return FAILURE;}OP(swlOp){ int immediate = IMMED(instr); Reg32_s data; int byte; VA vAddr; Reg base = P->R[RS(instr)]; Reg contents_rt = P->R[RT(instr)]; vAddr = SIGN_EXTEND(16, immediate) + base; byte = vAddr & 0x3; vAddr &= (Reg32_s)~0x3; if (MipsyReadMem(vAddr, &data, WORD_SZ, GETX_FLAVOR) != SUCCESS) { if (P->cpuStatus != cpu_running) { P->stalledInst = instr; STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum)); } return FAILURE; } else { /* Big Endian */ switch (byte) { case 0: data = contents_rt; break; case 1: data = (data & 0xff000000) | (contents_rt >> 8 & 0xffffff); break; case 2: data = (data & 0xffff0000) | (contents_rt >> 16 & 0xffff); break; case 3: data = (data & 0xffffff00) | (contents_rt >> 24 & 0xff); break; } 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; } } return SUCCESS;}OP(swrOp){ int immediate = IMMED(instr); Reg32_s data; uint byte; VA vAddr; Reg base = P->R[RS(instr)]; Reg contents_rt = P->R[RT(instr)]; vAddr = SIGN_EXTEND(16, immediate) + base; byte = vAddr & 0x3; vAddr &= (Reg32_s)~0x3; if (MipsyReadMem(vAddr, &data, WORD_SZ, GETX_FLAVOR) != SUCCESS) { if (P->cpuStatus != cpu_running) { P->stalledInst = instr; STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum)); } return FAILURE; } else { /* Big Endian */ switch (byte) { case 0: data = ((contents_rt << 24) & 0xff000000) | (data & 0xffffff); break; case 1: data = ((contents_rt << 16) & 0xffff0000) | (data & 0xffff); break; case 2: data = ((contents_rt << 8) & 0xffffff00) | (data & 0xff) ; break; case 3: data = contents_rt; break; } 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; } } return SUCCESS;}OP(xoriOp){ int immediate = IMMED(instr); Reg_s contents_rs = P->R[RS(instr)]; P->R[RT(instr)] = contents_rs ^ (0x0000ffff & immediate); return SUCCESS;}OP(cop0Op){ int immediate = IMMED(instr); int retval = 0; VA pcVal = P->PC; retval = ExecuteC0Instruction(P, instr); if (retval != C0_SUCCESS) { if (retval == C0_ILLEGAL_INST) { CPUWarning("Illegal inst at %#llx on CPU %d RA %#llx\n", (Reg64)P->PC, P->myNum, (Reg64)P->R[REG_RA]); ASSERT(0); EXCEPTION(P, EXC_II); } ASSERT(retval == C0_CONTINUE); return FAILURE; } return SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -