📄 opcodes.c
字号:
return SUCCESS;}OP(lwOp){ int immediate = IMMED(instr); Reg32_s data; VA vAddr; Reg base = P->R[RS(instr)]; vAddr = SIGN_EXTEND(16, immediate) + base;#ifndef SOLO /* check for unaligned loads of vaddr 3 - * this is a syscall exception left over from base mode days * and can be removed when all the old disks are gone */ if ((vAddr == 3) && (RS(instr) == 0)) { int syscallNum = P->R[REG_V0] - 1000; 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 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 { P->R[RT(instr)] = data; return SUCCESS; }}OP(ldOp){ int immediate = IMMED(instr); uint64 data; VA vAddr; Reg base = P->R[RS(instr)]; CHECK_64BIT_ALLOWED(P); vAddr = SIGN_EXTEND(16, immediate) + base; 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 { P->R[RT(instr)] = data; } return SUCCESS;}OP(ldc2Op){ int immediate = IMMED(instr); /* NOTE: This is not a real "ld" instruction since a real * ld instruction would load a 64bit value into a 64bit * registers. Since our registers are only 32bits we * load into two adjacent registers. * BEWARE: THIS IS A HACK. */ uint64 data; VA vAddr; Reg base = P->R[RS(instr)]; vAddr = SIGN_EXTEND(16, immediate) + base; if (vAddr & 0x00000007) { RECORD_EXCEPTION(P, EXC_RADE, E_VEC, vAddr, P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]); /* EXCEPTION(P->myNum,EXC_RADE); */ 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 { if (SAME_ENDIAN) { P->R[RT(instr)] = ((Reg32_s *)&data)[0]; P->R[RT(instr)+1] = ((Reg32_s *)&data)[1]; } else { P->R[RT(instr)] = ((Reg32_s *)&data)[1]; P->R[RT(instr)+1] = ((Reg32_s *)&data)[0]; } } return SUCCESS;}OP(lwc1Op){ int immediate = IMMED(instr); Reg32_s data; VA vAddr; Reg base = P->R[RS(instr)]; 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 & 0x00000003) { RECORD_EXCEPTION(P, EXC_RADE, E_VEC, vAddr, P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]); /* EXCEPTION(P->myNum,EXC_RADE); */ 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(instr)) = data; return SUCCESS; }}OP(ldc1Op){ int immediate = IMMED(instr); uint64 data; VA vAddr; Reg base = P->R[RS(instr)]; 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) { RECORD_EXCEPTION(P, EXC_RADE, E_VEC, vAddr, P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]); /* EXCEPTION(P->myNum,EXC_RADE); */ 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(instr)) = *((double *)&data); return SUCCESS; }}OP(ldlOp){ int immediate = IMMED(instr); int byte; Reg64 data; VA vAddr; Reg base = P->R[RS(instr)]; Reg contents_rt = P->R[RT(instr)]; CHECK_64BIT_ALLOWED(P); vAddr = SIGN_EXTEND(16, immediate) + base; byte = vAddr & 0x7; vAddr = vAddr & (Reg32_s)0xfffffff8; 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 { /* Big Endian */ switch (byte) { case 0: P->R[RT(instr)] = data; break; case 1: P->R[RT(instr)] = ((data & 0x00ffffffffffffffLL) << 8) | (contents_rt & 0x00000000000000ffLL); break; case 2: P->R[RT(instr)] = ((data & 0x0000ffffffffffffLL) << 16) | (contents_rt & 0x000000000000ffffLL); break; case 3: P->R[RT(instr)] = ((data & 0x000000ffffffffffLL) << 24) | (contents_rt & 0x0000000000ffffffLL); break; case 4: P->R[RT(instr)] = ((data & 0x00000000ffffffffLL) << 32) | (contents_rt & 0x00000000ffffffffLL); break; case 5: P->R[RT(instr)] = ((data & 0x0000000000ffffffLL) << 40) | (contents_rt & 0x000000ffffffffffLL); break; case 6: P->R[RT(instr)] = ((data & 0x000000000000ffffLL) << 48) | (contents_rt & 0x0000ffffffffffffLL); break; case 7: P->R[RT(instr)] = ((data & 0x00000000000000ffLL) << 56) | (contents_rt & 0x00ffffffffffffffLL); break; } } return SUCCESS;}OP(ldrOp){ int immediate = IMMED(instr); Reg64 data; int byte; VA vAddr; Reg contents_rt = P->R[RT(instr)]; Reg base = P->R[RS(instr)]; CHECK_64BIT_ALLOWED(P); vAddr = SIGN_EXTEND(16, immediate) + base; byte = vAddr & 0x7; vAddr = vAddr & (Reg32_s)0xfffffff8; 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 { /* Big Endian */ switch (byte) { case 0: P->R[RT(instr)] = ((data & 0xff00000000000000LL) >> 56) | (contents_rt & 0xffffffffffffff00LL); break; case 1: P->R[RT(instr)] = ((data & 0xffff000000000000LL) >> 48) | (contents_rt & 0xffffffffffff0000LL); break; case 2: P->R[RT(instr)] = ((data & 0xffffff0000000000LL) >> 40) | (contents_rt & 0xffffffffff000000LL); break; case 3: P->R[RT(instr)] = ((data & 0xffffffff00000000LL) >> 32) | (contents_rt & 0xffffffff00000000LL); break; case 4: P->R[RT(instr)] = ((data & 0xffffffffff000000LL) >> 24) | (contents_rt & 0xffffff0000000000LL); break; case 5: P->R[RT(instr)] = ((data & 0xffffffffffff0000LL) >> 16) | (contents_rt & 0xffff000000000000LL); break; case 6: P->R[RT(instr)] = ((data & 0xffffffffffffff00LL) >> 8) | (contents_rt & 0xff00000000000000LL); break; case 7: P->R[RT(instr)] = data; break; } } return SUCCESS;}OP(lwc2Op){ int immediate = IMMED(instr); CPUError("LWC2 operations not implemented\n"); return FAILURE;}OP(lwlOp) { int immediate = IMMED(instr); int byte; Reg32_s data; 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 = vAddr & (Reg32_s)0xfffffffc; 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 { /* Big Endian */ switch (byte) { case 0: P->R[RT(instr)] = data; break; case 1: P->R[RT(instr)] = ((data & 0x00ffffff) << 8) | ((Reg32_s)contents_rt & 0x000000ff); break; case 2: P->R[RT(instr)] = ((data & 0x0000ffff) << 16) | ((Reg32_s)contents_rt & 0x0000ffff); break; case 3: P->R[RT(instr)] = ((data & 0x000000ff) << 24) | ((Reg32_s)contents_rt & 0x00ffffff); break; } } return SUCCESS;}OP(lwrOp) { int immediate = IMMED(instr); Reg32_s data; int byte; VA vAddr; Reg contents_rt = P->R[RT(instr)]; Reg base = P->R[RS(instr)]; vAddr = SIGN_EXTEND(16, immediate) + base; byte = vAddr & 0x3; vAddr = vAddr & (Reg32_s)0xfffffffc; 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 { /* Big Endian */ switch (byte) { case 0: P->R[RT(instr)] = ((data & 0xff000000) >> 24) | ((Reg32_s)contents_rt & 0xffffff00); break; case 1: P->R[RT(instr)] = ((data & 0xffff0000) >> 16) | ((Reg32_s)contents_rt & 0xffff0000); break; case 2: P->R[RT(instr)] = ((data & 0xffffff00) >> 8) | ((Reg32_s)contents_rt & 0xff000000); break; case 3: P->R[RT(instr)] = data; break; } } return SUCCESS;}OP(lwuOp){ int immediate = IMMED(instr); VA vAddr; Reg base = P->R[RS(instr)]; Reg32 data = 0; CHECK_64BIT_ALLOWED(P); vAddr = SIGN_EXTEND(16, immediate) + base; 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 { P->R[RT(instr)] = data; } return SUCCESS;}OP(prefOp){ int immediate = IMMED(instr); VA vAddr; Result tRet; Reg base = P->R[RS(instr)]; uint hint = RT(instr); vAddr = (SIGN_EXTEND(16, immediate) + base); tRet = Prefetch(P,vAddr, hint); if (tRet == STALL) { P->cpuStatus = cpu_stalled; P->stalledInst = instr; STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum)); return FAILURE; } return SUCCESS;} OP(oriOp){ int immediate = IMMED(instr); Reg_s contents_rs = P->R[RS(instr)]; P->R[RT(instr)] = contents_rs | (0x0000ffff & immediate); return SUCCESS;}OP(sbOp){ int immediate = IMMED(instr); VA vAddr; Reg base = P->R[RS(instr)]; byte data = P->R[RT(instr)]; vAddr = SIGN_EXTEND(16, immediate) + base; if (MipsyWriteMem(vAddr, &data, BYTE_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(shOp){ int immediate = IMMED(instr); VA vAddr; Reg base = P->R[RS(instr)]; short data = P->R[RT(instr)]; vAddr = SIGN_EXTEND(16, immediate) + base; if (vAddr & 0x00000001) { EXCEPTION(P,EXC_WADE); return FAILURE; } if (MipsyWriteMem(vAddr, &data, HALF_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(sltiOp){ int immediate = IMMED(instr); Reg_s contents_rs = P->R[RS(instr)]; if (contents_rs < (Reg32_s)SIGN_EXTEND(16, immediate)) { P->R[RT(instr)] = 1; } else { P->R[RT(instr)] = 0; } return SUCCESS;}OP(sltiuOp){ int immediate = IMMED(instr); Reg_s contents_rs = P->R[RS(instr)]; if ((Reg)contents_rs < (Reg)(Reg32_s)SIGN_EXTEND(16, immediate)) { P->R[RT(instr)] = 1; } else { P->R[RT(instr)] = 0; } return SUCCESS;}OP(scOp){ int immediate = IMMED(instr); VA vAddr; bool scSuccess = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -