📄 cp1.cc
字号:
#include <assert.hh>#include "instr.hh"#include "koala.hh"const char* Koala::condname[16] = { "f", "un", "eq", "ueq", "olt", "ult", "ole", "ule", "sf", "ngle", "seq", "ngl", "lt", "nge", "le", "ngt"};intKoala::decode_cop1_s(Instr instr){ switch (function(instr)) { case FADD: { log("[%lx]\tadd.s\tf%d, f%d, f%d", pc, fd(instr), fs(instr), ft(instr)); float x = convert_from_s(fpr[fs(instr)]); float y = convert_from_s(fpr[ft(instr)]); float z = x + y; fpr[fd(instr)] = convert_to_s(z); return nothing_special; } case TRUNC_W: { log("[%lx]\ttrunc.w.s\tf%d, f%d", pc, fd(instr), fs(instr)); UInt32 x = (UInt32)convert_from_s(fpr[fs(instr)]); fpr[fd(instr)] = x; return nothing_special; } case CVT_W: { log("[%lx]\tcvt.w.s\tf%d, f%d", pc, fd(instr), fs(instr)); UInt32 x = (UInt32)convert_from_s(fpr[fs(instr)]); fpr[fd(instr)] = x; return nothing_special; } default: log("[%lx]\t.long\t0x%08x", pc, instr); assert(TODO); return nothing_special; }}intKoala::decode_cop1_d(Instr instr){ switch (function(instr)) { case FADD: { log("[%lx]\tadd.d\tf%d, f%d, f%d", pc, fd(instr), fs(instr), ft(instr)); double x = convert_from_d(fpr[fs(instr)]); double y = convert_from_d(fpr[ft(instr)]); double z = x + y; fpr[fd(instr)] = convert_to_d(z); return nothing_special; } case FDIV: { log("[%lx]\tdiv.d\tf%d, f%d, f%d", pc, fd(instr), fs(instr), ft(instr)); double x = convert_from_d(fpr[fs(instr)]); double y = convert_from_d(fpr[ft(instr)]); double z = x / y; fpr[fd(instr)] = convert_to_d(z); return nothing_special; } case FMUL: { log("[%lx]\tmul.d\tf%d, f%d, f%d", pc, fd(instr), fs(instr), ft(instr)); double x = convert_from_d(fpr[fs(instr)]); double y = convert_from_d(fpr[ft(instr)]); double z = x * y; fpr[fd(instr)] = convert_to_d(z); return nothing_special; } case C_F: case C_UN: case C_EQ: case C_UEQ: case C_OLT: case C_ULT: case C_OLE: case C_ULE: case C_SF: case C_NGLE: case C_SEQ: case C_NGL: case C_LT: case C_NGE: case C_LE: case C_NGT: { UInt8 cond = bits(instr, 3, 0); log("[%lx]\tc.%s.d\tf%d, f%d", pc, condname[cond], fs(instr), ft(instr)); double x = convert_from_d(fpr[fs(instr)]); double y = convert_from_d(fpr[ft(instr)]); UInt64 result = (bit(cond, 2) && (x < y)) || (bit(cond, 1) && (x == y)); cp1[FCR31] = set_bit(cp1[FCR31], result, FP_C); return nothing_special; } case TRUNC_W: { log("[%lx]\ttrunc.w.d\tf%d, f%d", pc, fd(instr), fs(instr)); UInt32 x = (UInt32)convert_from_d(fpr[fs(instr)]); fpr[fd(instr)] = x; return nothing_special; } case TRUNC_L: { log("[%lx]\ttrunc.l.d\tf%d, f%d", pc, fd(instr), fs(instr)); UInt64 x = (UInt64)convert_from_d(fpr[fs(instr)]); fpr[fd(instr)] = x; return nothing_special; } case CVT_W: { log("[%lx]\tcvt.w.d\tf%d, f%d", pc, fd(instr), fs(instr)); UInt32 x = (UInt32)convert_from_d(fpr[fs(instr)]); fpr[fd(instr)] = x; return nothing_special; } default: log("[%lx]\t.long\t0x%08x", pc, instr); assert(TODO); return nothing_special; }}intKoala::decode_cop1_w(Instr instr){ switch (function(instr)) { case CVT_S: { log("[%lx]\tcvt.s.w\tf%d, f%d", pc, fd(instr), fs(instr)); float x = (float)fpr[fs(instr)]; fpr[fd(instr)] = convert_to_s(x); return nothing_special; } case CVT_D: { log("[%lx]\tcvt.d.w\tf%d, f%d", pc, fd(instr), fs(instr)); double x = (double)fpr[fs(instr)]; fpr[fd(instr)] = convert_to_d(x); return nothing_special; } default: log("[%lx]\t.long\t0x%08x", pc, instr); assert(TODO); return nothing_special; }}intKoala::decode_cop1_l(Instr instr){ log("[%lx]\t.long\t0x%08x", pc, instr); assert(TODO); return nothing_special;}intKoala::decode_cop1(Instr instr){ // CP1 is unusable when the CU bit in SR is clear. if (!bit(cp0[SR], SR_CU1)) process_coprocessor_unusable(1); switch (fmt(instr)) { case S: { decode_cop1_s(instr); break; } case D: { decode_cop1_d(instr); break; } case W: { decode_cop1_w(instr); break; } case L: { decode_cop1_l(instr); break; } case CTCz: { log("[%lx]\tctc1\t%s, f%d", pc, regname[rt(instr)], rd(instr)); if (rd(instr) == 31) cp1[FCR31] = gpr[rt(instr)]; break; } case CFCz: { log("[%lx]\tcfc1\t%s, f%d", pc, regname[rt(instr)], rd(instr)); gpr[rt(instr)] = cp1[rd(instr)]; break; } case MFCz: // FIXME case DMFCz: { log("[%lx]\tmfc1\t%s, f%d", pc, regname[rt(instr)], rd(instr)); gpr[rt(instr)] = fpr[rd(instr)]; break; } case MTCz: // FIXME case DMTCz: { log("[%lx]\tmtc1\t%s, f%d", pc, regname[rt(instr)], rd(instr)); fpr[rd(instr)] = gpr[rt(instr)]; break; } case BCz: { bool cond = bit(rt(instr), 0); bool likely = bit(rt(instr), 1); UInt64 target = pc + 4 + (sign_extend<VA>(offset(instr), 16) << 2); log("[%lx]\tbc1%c%s\t%s, 0x%016lx", pc, cond ? 't' : 'f', likely ? "l" : "", regname[rs(instr)], target); if (bit(cp1[FCR31], FP_C) == cond) { branch_target = target; return branch_delay; } else if (likely) { // Nullify (skip) the next instruction. pc += 4; return nothing_special; } else { branch_target = pc + 8; return branch_delay; } break; } default: { log("[%lx]\t.long\t0x%08x", pc, instr); assert(TODO); } } dump_fpr_registers(); return nothing_special;}intKoala::decode_ldc1(Instr instr){ // Load Doubleword To Coprocessor 1 //////////////////////////////////#if 0 if (trace_level >= print_instructions)#endif log("[%lx]\tldc1\tf%d, %d(%s)", pc, 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)]; if (bits(va, 2, 0)) process_address_error(data_load, va); PA pa = translate_vaddr(va, data_load); UInt64 x = load<doubleword>(va, pa); fpr[rt(instr)] = sign_extend<UInt64>(x, 64); dump_fpr_registers(); return nothing_special;}intKoala::decode_lwc1(Instr instr){ // Load Word to Coprocessor 1 ////////////////////////////////////////#if 0 if (trace_level >= print_instructions)#endif log("[%lx]\tlwc1\tf%d, %d(%s)", pc, rt(instr), sign_extend<Int32>(offset(instr), 16), regname[base(instr)]); if (sync_bit) sync(); VA va = sign_extend<VA>(offset(instr), 16) + gpr[base(instr)]; if (bits(va, 1, 0)) process_address_error(data_load, va); PA pa = translate_vaddr(va, data_load); UInt32 x = load<word>(va, pa); fpr[rt(instr)] = sign_extend<UInt64>(x, 32); dump_fpr_registers(); return nothing_special;}intKoala::decode_sdc1(Instr instr){ // Store Doubleword From Coprocessor 1 ///////////////////////////////#if 0 if (trace_level >= print_instructions)#endif log("[%lx]\tsdc1\tf%d, %d(%s)", pc, 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)]; if (bits(va, 2, 0)) process_address_error(data_store, va); PA pa = translate_vaddr(va, data_store); store<doubleword>(fpr[rt(instr)], va, pa); dump_fpr_registers(); return nothing_special;}intKoala::decode_swc1(Instr instr){ // Store Word From Coprocessor 1 /////////////////////////////////////#if 0 if (trace_level >= print_instructions)#endif log("[%lx]\tswc1\tf%d, %d(%s)", pc, rt(instr), sign_extend<Int32>(offset(instr), 16), regname[base(instr)]); if (sync_bit) sync(); VA va = sign_extend<VA>(offset(instr), 16) + gpr[base(instr)]; if (bits(va, 1, 0)) process_address_error(data_store, va); PA pa = translate_vaddr(va, data_store); store<word>(fpr[rt(instr)], va, pa); dump_fpr_registers(); return nothing_special;}voidKoala::dump_fpr_registers() const{ for (int i = 0; i < 32; i += 2) { log("\tf%-2d = %016lx %-2d = %016lx", i, fpr[i], i+1, fpr[i+1]); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -