📄 decoder.cc
字号:
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; } } default: // Reserved instruction. if (trace_level >= print_instructions) log("[%lx]\t.long\t0x%08x", pc, instr); process_reserved_instruction(); return nothing_special; } } case J: { // Jump ////////////////////////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tj\t0x%016lx", pc, clear_bits(pc + 4, 27, 0) | (target(instr) << 2)); VA msb = clear_bits(pc + 4, 27, 0); branch_target = msb | (target(instr) << 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; } case JAL: { // Jump And Link ///////////////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tjal\t0x%016lx", pc, clear_bits(pc + 4, 27, 0) | (target(instr) << 2)); gpr[31] = sign_extend<UInt64>(pc + 8, 64); VA msb = clear_bits(pc + 4, 27, 0); branch_target = msb | (target(instr) << 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; } case BEQ: { // Branch On Equal /////////////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tbeq\t%s, %s, 0x%016lx", pc, regname[rs(instr)], regname[rt(instr)], pc + 4 + (sign_extend<Int64>(offset(instr), 16) << 2)); if (gpr[rs(instr)] == gpr[rt(instr)]) { 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 BNE: { // Branch On Not Equal /////////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tbne\t%s, %s, 0x%016lx", pc, regname[rs(instr)], regname[rt(instr)], pc + 4 + (sign_extend<Int64>(offset(instr), 16) << 2)); if (gpr[rs(instr)] != gpr[rt(instr)]) { 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 BLEZ: { // Branch On Less Than Or Equal To Zero ////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tblez\t%s, 0x%016lx", pc, regname[rs(instr)], pc + 4 + (sign_extend<Int64>(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 BGTZ: { // Branch On Greater Than Zero /////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tbgtz\t%s, 0x%016lx", pc, regname[rs(instr)], pc + 4 + (sign_extend<Int64>(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 ADDI: { // Add Immediate ///////////////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\taddi\t%s, %s, 0x%04x", pc, regname[rt(instr)], regname[rs(instr)], zero_extend<UInt32>(immediate(instr), 16)); UInt32 x = gpr[rs(instr)]; UInt32 y = sign_extend<UInt32>(immediate(instr), 16); UInt32 z = x + y; // Overflow occurs is sign(x) == sign(y) != sign(z). if (bit(x ^ y, 31) == 0 && bit(x ^ z, 31) != 0) process_integer_overflow(); gpr[rt(instr)] = sign_extend<UInt64>(z, 32); return nothing_special; } case ADDIU: { // Add Immediate Unsigned //////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\taddiu\t%s, %s, 0x%04x", pc, regname[rt(instr)], regname[rs(instr)], zero_extend<UInt32>(immediate(instr), 16)); UInt32 x = gpr[rs(instr)]; UInt32 y = sign_extend<UInt32>(immediate(instr), 16); gpr[rt(instr)] = sign_extend<UInt64>(x + y, 32); return nothing_special; } case SLTI: { // Set On Less Than Immediate //////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tslti\t%s, %s, 0x%04x", pc, regname[rt(instr)], regname[rs(instr)], zero_extend<UInt32>(immediate(instr), 16)); Int64 x = gpr[rs(instr)]; Int64 y = sign_extend<Int64>(immediate(instr), 16); gpr[rt(instr)] = (x < y); return nothing_special; } case SLTIU: { // Set On Less Than Immediate Unsigned /////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tsltiu\t%s, %s, 0x%04x", pc, regname[rt(instr)], regname[rs(instr)], zero_extend<UInt32>(immediate(instr), 16)); UInt64 x = gpr[rs(instr)]; UInt64 y = sign_extend<UInt64>(immediate(instr), 16); gpr[rt(instr)] = (x < y); return nothing_special; } case ANDI: { // And Immediate ///////////////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tandi\t%s, %s, 0x%04x", pc, regname[rt(instr)], regname[rs(instr)], zero_extend<UInt32>(immediate(instr), 16)); UInt16 x = gpr[rs(instr)]; UInt16 imm = zero_extend<UInt64>(immediate(instr), 16); gpr[rt(instr)] = zero_extend<UInt64>(x & imm, 16); return nothing_special; } case ORI: { // Or Immediate ////////////////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tori\t%s, %s, 0x%04x", pc, regname[rt(instr)], regname[rs(instr)], zero_extend<UInt32>(immediate(instr), 16)); UInt64 x = gpr[rs(instr)]; UInt64 imm = zero_extend<UInt64>(immediate(instr), 16); gpr[rt(instr)] = x | imm; return nothing_special; } case XORI: { // Exclusive Or Immediate //////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\txori\t%s, %s, 0x%04x", pc, regname[rt(instr)], regname[rs(instr)], zero_extend<UInt32>(immediate(instr), 16)); UInt64 x = gpr[rs(instr)]; UInt64 imm = zero_extend<UInt64>(immediate(instr), 16); gpr[rt(instr)] = x ^ imm; return nothing_special; } case LUI: { // Load Upper Immediate ////////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tlui\t%s, 0x%04x", pc, regname[rt(instr)], zero_extend<UInt32>(immediate(instr), 32)); UInt32 imm = immediate(instr); gpr[rt(instr)] = sign_extend<UInt64>(imm << 16, 32); return nothing_special; } case COP0: { // Coprocessor 0 Operation /////////////////////////////////////////// if (trace_level >= print_instructions) { if (bit(instr, 25)) { switch (funct(instr)) { case TLBR: log("[%lx]\ttlbr", pc); break; case TLBWI: log("[%lx]\ttlbwi", pc); break; case TLBWR: log("[%lx]\ttlbwr", pc); break; case TLBP: log("[%lx]\ttlbp", pc); break; case ERET: log("[%lx]\teret", pc); break; case WAIT: log("[%lx]\twait", pc); break; default: log("[%lx]\t.long\t0x%08x // cop0", pc, instr); } } else { switch (rs(instr)) { case MFCz: log("[%lx]\tmfc0\t%s, %d", pc, regname[rt(instr)], rd(instr)); break; case DMFCz: log("[%lx]\tdmfc0\t%s, %d", pc, regname[rt(instr)], rd(instr)); break; case CFCz: log("[%lx]\t.long\t0x%08x // cfc0", pc, instr); break; case MTCz: log("[%lx]\tmtc0\t%s, %d", pc, regname[rt(instr)], rd(instr)); break; case DMTCz: log("[%lx]\tdmtc0\t%s, %d", pc, regname[rt(instr)], rd(instr)); break; case CTCz: log("[%lx]\t.long\t0x%08x // ctc0", pc, instr); break; case BCz: log("[%lx]\t.long\t0x%08x // bc0", pc, instr); break; default: log("[%lx]\t.long\t0x%08x // cop0", pc, instr); } } } return decode_cop0(instr); } case COP1: { // Coprocessor 1 Operation /////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\t.long\t0x%08x // cop1", pc, instr); return decode_cop1(instr); } case COP2: { // Coprocessor 2 Operation /////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\t.long\t0x%08x // cop2", pc, instr); process_reserved_instruction(); return nothing_special; } case BEQL: { // Branch On Equal Likely //////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tbeql\t%s, %s, 0x%016lx", pc, regname[rs(instr)], regname[rt(instr)], pc + 4 + (sign_extend<VA>(offset(instr), 16) << 2)); if (gpr[rs(instr)] == gpr[rt(instr)]) { 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 BNEL: { // Branch On Not Equal Likely //////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tbnel\t%s, %s, 0x%016lx", pc, regname[rs(instr)], regname[rt(instr)], pc + 4 + (sign_extend<VA>(offset(instr), 16) << 2)); if (gpr[rs(instr)] != gpr[rt(instr)]) { 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 BLEZL: { // Branch On Less Than Or Equal To Zero Likely /////////////////////// if (trace_level >= print_instructions) log("[%lx]\tblezl\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 BGTZL: { // Branch On Greater Than Zero Likely //////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tbgtzl\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 DADDI: { // Doubleword Add Immediate ////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tdaddi\t%s, %s, 0x%04x", pc, regname[rt(instr)], regname[rs(instr)], zero_extend<Int32>(immediate(instr), 16)); if (!allow_xinstr()) process_reserved_instruction(); UInt64 x = gpr[rs(instr)]; UInt64 y = sign_extend<UInt64>(immediate(instr), 16); 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[rt(instr)] = sign_extend<UInt64>(z, 64); return nothing_special; } case DADDIU: { // Doubleword Add Immediate Unsigned ///////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tdaddiu\t%s, %s, 0x%04x", pc, regname[rt(instr)], regname[rs(instr)], sign_extend<Int32>(immediate(instr), 16)); if (!allow_xinstr()) process_reserved_instruction(); UInt64 x = gpr[rs(instr)]; UInt64 y = sign_extend<UInt64>(immediate(instr), 16); gpr[rt(instr)] = sign_extend<UInt64>(x + y, 64); return nothing_special; } case LDL: { // Load Doubleword Left ////////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tldl\t%s, %d(%s)", pc, regname[rt(instr)], sign_extend<Int32>(offset(instr), 16), regname[base(instr)]); if (!allow_xinstr()) process_reserved_instruction(); if (sync_bit) sync(); VA va = sign_extend<VA>(offset(instr), 16) + gpr[base(instr)]; // WARNING: see the comment in unaligned.cc. PA pa = translate_vaddr(va, data_load); UInt64 mem = load<doubleword>(round_down(va, 8), round_down(pa, 8)); UInt64 reg = gpr[rt(instr)]; int syscmd = bits(va, 2, 0); if (!big_endian_cpu()) syscmd ^= bitmask(2, 0); reg = set_bits(reg, mem, 63, syscmd * 8); gpr[rt(instr)] = sign_extend<UInt64>(reg, 64); return nothing_special; } case LDR: { // Load Doubleword Right ///////////////////////////////////////////// if (trace_level >= print_instructions) log("[%lx]\tldr\t%s, %d(%s)", pc, regname[rt(instr)], sign_extend<Int32>(offset(instr), 16), regname[base(instr)]); if (!allow_xinstr()) process_reserved_instruction(); if (sync_bit) sync(); VA va = sign_extend<VA>(offset(instr), 16) + gpr[base(instr)]; // WARNING: see the comment in unaligned.cc. PA pa = translate_vaddr(va, data_load); UInt64 mem = load<doubleword>(round_down(va, 8), round_down(pa, 8)); UInt64 reg = gpr[rt(instr)]; int syscmd = bits(va, 2, 0); if (big_endian_cpu())
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -