📄 decoder.cc
字号:
// Set On Less Than ////////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tslt\t%s, %s, %s", pc, regname[rd(instr)], regname[rs(instr)], regname[rt(instr)]); Int64 x = gpr[rs(instr)]; Int64 y = gpr[rt(instr)]; gpr[rd(instr)] = (x < y); return nothing_special; } case SLTU: { // Set On Less Than Unsigned ///////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tsltu\t%s, %s, %s", pc, regname[rd(instr)], regname[rs(instr)], regname[rt(instr)]); gpr[rd(instr)] = (gpr[rs(instr)] < gpr[rt(instr)]); return nothing_special; } case DADD: { // Doubleword Add //////////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tdadd\t%s, %s, %s", pc, regname[rd(instr)], regname[rs(instr)], regname[rt(instr)]); if (!allow_xinstr()) process_reserved_instruction(); UInt64 x = gpr[rs(instr)]; UInt64 y = gpr[rt(instr)]; UInt64 z = x + y; // Overflow occurs is sign(x) == sign(y) != sign(z). if (bit(x ^ y, 63) == 0 && bit(x ^ z, 63) != 0) process_integer_overflow(); gpr[rd(instr)] = sign_extend<UInt64>(z, 64); return nothing_special; } case DADDU: { // Doubleword Add Unsigned /////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tdaddu\t%s, %s, %s", pc, regname[rd(instr)], regname[rs(instr)], regname[rt(instr)]); if (!allow_xinstr()) process_reserved_instruction(); UInt64 x = gpr[rs(instr)]; UInt64 y = gpr[rt(instr)]; gpr[rd(instr)] = sign_extend<UInt64>(x + y, 64); return nothing_special; } case DSUB: { // Doubleword Subtract /////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tdsub\t%s, %s, %s", pc, regname[rd(instr)], regname[rs(instr)], regname[rt(instr)]); if (!allow_xinstr()) process_reserved_instruction(); Int64 x = zero_extend<UInt64>(gpr[rs(instr)], 64); Int64 y = zero_extend<UInt64>(gpr[rt(instr)], 64); Int64 z = UInt64(x) - UInt64(y); if ((y < 0 && z < x) || (y > 0 && z > x)) process_integer_overflow(); gpr[rd(instr)] = sign_extend<UInt64>(z, 64); return nothing_special; } case DSUBU: { // Doubleword Subtract Unsigned ////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tdsubu\t%s, %s, %s", pc, regname[rd(instr)], regname[rs(instr)], regname[rt(instr)]); if (!allow_xinstr()) process_reserved_instruction(); UInt64 x = zero_extend<UInt64>(gpr[rs(instr)], 64); UInt64 y = zero_extend<UInt64>(gpr[rt(instr)], 64); gpr[rd(instr)] = sign_extend<UInt64>(x - y, 64); return nothing_special; } case TGE: { // Trap If Greater Than Or Equal ///////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\ttge\t%s, %s", pc, regname[rs(instr)], regname[rt(instr)]); Int64 x = gpr[rs(instr)]; Int64 y = gpr[rt(instr)]; if (x >= y) process_trap(); return nothing_special; } case TGEU: { // Trap If Greater Than Or Equal Unsigned //////////////////////// if (trace_level >= print_instructions) log("[%lx]\ttgeu\t%s, %s", pc, regname[rs(instr)], regname[rt(instr)]); if (gpr[rs(instr)] >= gpr[rt(instr)]) process_trap(); return nothing_special; } case TLT: { // Trap If Less Than ///////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\ttlt\t%s, %s", pc, regname[rs(instr)], regname[rt(instr)]); Int64 x = gpr[rs(instr)]; Int64 y = gpr[rt(instr)]; if (x < y) process_trap(); return nothing_special; } case TLTU: { // Trap If Less Than Unsigned //////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\ttltu\t%s, %s", pc, regname[rs(instr)], regname[rt(instr)]); if (gpr[rs(instr)] < gpr[rt(instr)]) process_trap(); return nothing_special; } case TEQ: { // Trap If Equal ///////////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tteq\t%s, %s", pc, regname[rs(instr)], regname[rt(instr)]); if (gpr[rs(instr)] == gpr[rt(instr)]) process_trap(); return nothing_special; } case TNE: { // Trap If Not Equal ///////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\ttne\t%s, %s", pc, regname[rs(instr)], regname[rt(instr)]); if (gpr[rs(instr)] != gpr[rt(instr)]) process_trap(); return nothing_special; } case DSLL: { // Doubleword Shift Left Logical ///////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tdsll\t%s, %s, %d", pc, regname[rd(instr)], regname[rt(instr)], shamt(instr)); if (!allow_xinstr()) process_reserved_instruction(); UInt64 x = gpr[rt(instr)]; int s = shamt(instr); gpr[rd(instr)] = sign_extend<UInt64>(x << s, 64); return nothing_special; } case DSRL: { // Doubleword Shift Right Logical //////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tdsrl\t%s, %s, %d", pc, regname[rd(instr)], regname[rt(instr)], shamt(instr)); if (!allow_xinstr()) process_reserved_instruction(); UInt64 x = zero_extend<UInt64>(gpr[rt(instr)], 64); int s = shamt(instr); gpr[rd(instr)] = sign_extend<UInt64>(x >> s, 64); return nothing_special; } case DSRA: { // Doubleword Shift Right Arithmetic ///////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tdsra\t%s, %s, %d", pc, regname[rd(instr)], regname[rt(instr)], shamt(instr)); if (!allow_xinstr()) process_reserved_instruction(); UInt64 x = gpr[rt(instr)]; int s = shamt(instr); gpr[rd(instr)] = sign_extend<UInt64>(x >> s, 64 - s); return nothing_special; } case DSLL32: { // Doubleword Shift Left Logical + 32 //////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tdsll\t%s, %s, %d", pc, regname[rd(instr)], regname[rt(instr)], shamt(instr) + 32); if (!allow_xinstr()) process_reserved_instruction(); UInt64 x = gpr[rt(instr)]; int s = shamt(instr) + 32; gpr[rd(instr)] = sign_extend<UInt64>(x << s, 64); return nothing_special; } case DSRL32: { // Doubleword Shift Right Logical + 32 /////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tdsrl\t%s, %s, %d", pc, regname[rd(instr)], regname[rt(instr)], shamt(instr) + 32); if (!allow_xinstr()) process_reserved_instruction(); UInt64 x = zero_extend<UInt64>(gpr[rt(instr)], 64); int s = shamt(instr) + 32; gpr[rd(instr)] = sign_extend<UInt64>(x >> s, 64); return nothing_special; } case DSRA32: { // Doubleword Shift Right Arithmetic + 32 //////////////////////// if (trace_level >= print_instructions) log("[%lx]\tdsra\t%s, %s, %d", pc, regname[rd(instr)], regname[rt(instr)], shamt(instr) + 32); if (!allow_xinstr()) process_reserved_instruction(); UInt64 x = gpr[rt(instr)]; int s = shamt(instr) + 32; gpr[rd(instr)] = sign_extend<UInt64>(x >> s, 64 - s); return nothing_special; } default: // Reserved instruction. if (trace_level >= print_instructions) log("[%lx]\t.long\t0x%08x", pc, instr); process_reserved_instruction(); return nothing_special; } } case REGIMM: { // Conditional branches, decoded using the (rt) field. switch (rt(instr)) { case BLTZ: { // Branch On Less Than Zero ////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tbltz\t%s, 0x%016lx", pc, regname[rs(instr)], pc + 4 + (sign_extend<VA>(offset(instr), 16) << 2)); Int64 x = gpr[rs(instr)]; if (x < 0) { VA off = sign_extend<VA>(offset(instr), 16); branch_target = pc + 4 + (off << 2); } else branch_target = pc + 8; if (pipeline == branch_delay) { log("Illegal branch in branch delay slot at: %lx\n", pc); assert(!"Can't handle branch in branch delay slot"); } return branch_delay; } case BGEZ: { // Branch On Greater Than Or Equal To Zero /////////////////////// if (trace_level >= print_instructions) log("[%lx]\tbgez\t%s, 0x%016lx", pc, regname[rs(instr)], pc + 4 + (sign_extend<VA>(offset(instr), 16) << 2)); Int64 x = gpr[rs(instr)]; if (x >= 0) { VA off = sign_extend<VA>(offset(instr), 16); branch_target = pc + 4 + (off << 2); } else branch_target = pc + 8; if (pipeline == branch_delay) { log("Illegal branch in branch delay slot at: %lx\n", pc); assert(!"Can't handle branch in branch delay slot"); } return branch_delay; } case BLTZL: { // Branch On Less Than Zero Likely /////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tbltzl\t%s, 0x%016lx", pc, regname[rs(instr)], pc + 4 + (sign_extend<VA>(offset(instr), 16) << 2)); Int64 x = gpr[rs(instr)]; if (x < 0) { VA off = sign_extend<VA>(offset(instr), 16); branch_target = pc + 4 + (off << 2); if (pipeline == branch_delay) { log("Illegal branch in branch delay slot at: %lx\n", pc); assert(!"Can't handle branch in branch delay slot"); } return branch_delay; } else { // Nullify (skip) the next instruction. pc += 4; return nothing_special; } } case BGEZL: { // Branch On Greater Than Or Equal To Zero Likely //////////////// if (trace_level >= print_instructions) log("[%lx]\tbgezl\t%s, 0x%016lx", pc, regname[rs(instr)], pc + 4 + (sign_extend<VA>(offset(instr), 16) << 2)); Int64 x = gpr[rs(instr)]; if (x >= 0) { VA off = sign_extend<VA>(offset(instr), 16); branch_target = pc + 4 + (off << 2); if (pipeline == branch_delay) { log("Illegal branch in branch delay slot at: %lx\n", pc); assert(!"Can't handle branch in branch delay slot"); } return branch_delay; } else { // Nullify (skip) the next instruction. pc += 4; return nothing_special; } } case TGEI: { // Trap If Greater Than Or Equal Immediate /////////////////////// if (trace_level >= print_instructions) log("[%lx]\ttgei\t%s, 0x%04x", pc, regname[rs(instr)], zero_extend<UInt32>(immediate(instr), 16)); Int64 x = gpr[rs(instr)]; Int64 y = sign_extend<Int64>(immediate(instr), 16); if (x >= y) process_trap(); return nothing_special; } case TGEIU: { // Trap If Greater Than Or Equal Immediate Unsigned ////////////// if (trace_level >= print_instructions) log("[%lx]\ttgeiu\t%s, 0x%04x", pc, regname[rs(instr)], zero_extend<UInt32>(immediate(instr), 16)); UInt64 x = gpr[rs(instr)]; UInt64 y = sign_extend<UInt64>(immediate(instr), 16); if (x >= y) process_trap(); return nothing_special; } case TLTI: { // Trap If Less Than Immediate /////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\ttlti\t%s, 0x%04x", pc, regname[rs(instr)], zero_extend<UInt32>(immediate(instr), 16)); Int64 x = gpr[rs(instr)]; Int64 y = sign_extend<Int64>(immediate(instr), 16); if (x < y) process_trap(); return nothing_special; } case TLTIU: { // Trap If Less Than Immediate Unsigned ////////////////////////// if (trace_level >= print_instructions) log("[%lx]\ttltiu\t%s, 0x%04x", pc, regname[rs(instr)], zero_extend<UInt32>(immediate(instr), 16)); UInt64 x = gpr[rs(instr)]; UInt64 y = sign_extend<UInt64>(immediate(instr), 16); if (x < y) process_trap(); return nothing_special; } case TEQI: { // Trap If Equal Immediate /////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tteqi\t%s, 0x%04x", pc, regname[rs(instr)], zero_extend<UInt32>(immediate(instr), 16)); UInt64 x = gpr[rs(instr)]; UInt64 y = sign_extend<UInt64>(immediate(instr), 16); if (x == y) process_trap(); return nothing_special; } case TNEI: { // Trap If Not Equal Immediate /////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\ttnei\t%s, 0x%04x", pc, regname[rs(instr)], zero_extend<UInt32>(immediate(instr), 16)); UInt64 x = gpr[rs(instr)]; UInt64 y = sign_extend<UInt64>(immediate(instr), 16); if (x != y) process_trap(); return nothing_special; } case BLTZAL: { // Branch On Less Than Zero And Link ///////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tbltzal\t%s, 0x%016lx", pc, regname[rs(instr)], pc + 4 + sign_extend<VA>(offset(instr), 16) << 2); Int64 x = gpr[rs(instr)]; gpr[31] = sign_extend<UInt64>(pc + 8, 64); if (x < 0) { VA off = sign_extend<VA>(offset(instr), 16); branch_target = pc + 4 + (off << 2); } else branch_target = pc + 8; if (pipeline == branch_delay) { log("Illegal branch in branch delay slot at: %lx\n", pc); assert(!"Can't handle branch in branch delay slot"); } return branch_delay; } case BGEZAL: { // Branch On Greater Than Or Equal To Zero And Link ////////////// if (trace_level >= print_instructions) log("[%lx]\tbltzal\t%s, 0x%016lx", pc, regname[rs(instr)], pc + 4 + sign_extend<VA>(offset(instr), 16) << 2); Int64 x = gpr[rs(instr)]; gpr[31] = sign_extend<UInt64>(pc + 8, 64); if (x >= 0) { VA off = sign_extend<VA>(offset(instr), 16); branch_target = pc + 4 + (off << 2); } else branch_target = pc + 8; if (pipeline == branch_delay) { log("Illegal branch in branch delay slot at: %lx\n", pc); assert(!"Can't handle branch in branch delay slot"); } return branch_delay; } case BLTZALL: { // Branch On Less Than Zero And Link Likely ////////////////////// if (trace_level >= print_instructions) log("[%lx]\tbltzall\t%s, 0x%016lx", pc, regname[rs(instr)], pc + 4 + (sign_extend<VA>(offset(instr), 16) << 2)); Int64 x = gpr[rs(instr)]; gpr[31] = sign_extend<UInt64>(pc + 8, 64); if (x < 0) { VA off = sign_extend<VA>(offset(instr), 16); branch_target = pc + 4 + (off << 2); if (pipeline == branch_delay) { log("Illegal branch in branch delay slot at: %lx\n", pc); assert(!"Can't handle branch in branch delay slot"); } return branch_delay; } else { // Nullify (skip) the next instruction. pc += 4; return nothing_special; } } case BGEZALL: { // Branch On Greater Than Or Equal To Zero And Link Likely /////// if (trace_level >= print_instructions) log("[%lx]\tbgezall\t%s, 0x%016lx", pc,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -