📄 cp0.cc
字号:
#include "instr.hh"#include "koala.hh"// Access to the System Coprocessor registers.UInt64Koala::read_cp0(int n) const{ switch (n) { case Random: { return get_random(); } case Count: { return cp0[Count] + ((now - count_seed) / 2); } case Cause: { return cp0[Cause] | (events & bitmask(Cause_IP_Last, Cause_IP_First)); } default: assert(n >= 0 && n <= 31); return cp0[n]; }}voidKoala::write_cp0(int n, UInt64 x){ switch (n) { case Index: { cp0[Index] = zero_extend<UInt64>(clear_bits(x, 30, 6), 32); break; } case Random: { break; } case EntryLo0: { cp0[EntryLo0] = clear_bits(x, 63, 30); break; } case EntryLo1: { cp0[EntryLo1] = clear_bits(x, 63, 30); break; } case Context: { cp0[Context] = clear_bits(x, 3, 0); break; } case PageMask: { cp0[PageMask] = x & bitmask(24, 13); break; } case Wired: { random_seed = now; cp0[Wired] = clear_bits(x, 63, 6) < tlb_size ? clear_bits(x, 63, 6) : tlb_size - 1; break; } case BadVAddr: { break; } case Count: { count_seed = now; cp0[Count] = zero_extend<UInt64>(x, 32); set_timer(); break; } case EntryHi: { asid = bits(x, 7, 0); cp0[EntryHi] = x & (bitmask(63, 62) | bitmask(vaddr_width - 1, 13) | bitmask(7, 0)); break; } case Compare: { cp0[Compare] = zero_extend<UInt64>(x, 32); events = clear_bit(events, 7 + Cause_IP_First); set_timer(); break; } case SR: { cp0[SR] = x & ~(bitmask(27) | bitmask(24, 23) | bitmask(21) | bitmask(19)); leave_kernel_mode(); break; } case Cause: { events |= x & bitmask(Cause_IP1, Cause_IP0); break; } case EPC: { cp0[EPC] = x; break; } case PRId: { break; } case Config: { cp0[Config] = set_bits(cp0[Config], x, 2, 0); break; } case LLAddr: { cp0[LLAddr] = zero_extend<UInt64>(x, 32); break; } case WatchLo: { break; } case WatchHi: { break; } case XContext: { cp0[XContext] = clear_bits(x, 3, 0); break; } case ECC: { cp0[ECC] = clear_bits(x, 63, 8); break; } case CacheErr: { break; } case TagLo: { cp0[TagLo] = zero_extend<UInt64>(clear_bit(x, 1), 32); break; } case TagHi: { break; } case ErrorEPC: { cp0[ErrorEPC] = x; break; } default: // bogus (ignored) assert(n >= 0 && n <= 31); }}intKoala::decode_cop0(Instr instr){ // CP0 is usable in kernel more or when the CU bit in SR is set. if (!(mode & kmode) && !bit(cp0[SR], SR_CU0)) process_coprocessor_unusable(0); // Only COP0, DMFC0, DMTC0, MFC0 and MTC0 make sense, although the R4K // manuals say nothing about handling the others. if (bit(instr, 25)) { switch (funct(instr)) { case TLBR: { // Read Indexed TLB Entry //////////////////////////////////////// TLBEntry* e = &tlb[bits(cp0[Index], 5, 0)]; cp0[PageMask] = clear_bits(~e->mask, 12, 0); cp0[EntryHi] = clear_bits(e->hi | bits(e->asid, 7, 0), 61, 40); cp0[EntryLo1] = e->lo[1]; cp0[EntryLo0] = e->lo[0]; return nothing_special; } case TLBWI: { // Write Indexed TLB Entry /////////////////////////////////////// set_tlb_entry(bits(cp0[Index], 5, 0)); return nothing_special; } case TLBWR: { // Write Random TLB Entry //////////////////////////////////////// set_tlb_entry(get_random()); return nothing_special; } case TLBP: { // Probe TLB For Matching Entry ////////////////////////////////// VA va = cp0[EntryHi]; //if (vaddr_region(va) == 3) // va = set_bits(va, 61, 40); TLBEntry* e = probe_tlb(va); cp0[Index] = (e) ? e->index : bitmask(31); return nothing_special; } case ERET: { // Exception Return ////////////////////////////////////////////// if (bit(cp0[SR], SR_ERL)) { pc = cp0[ErrorEPC] - 4; cp0[SR] = clear_bit(cp0[SR], SR_ERL); } else { pc = cp0[EPC] - 4; cp0[SR] = clear_bit(cp0[SR], SR_EXL); } leave_kernel_mode(); ll_bit = false; return nothing_special; } case WAIT: { // Wait ////////////////////////////////////////////////////////// // This is implemented by busy-waiting for an interrupt. It's of // course wrong in that the CP0 Random and CP0 Count are affected, // but, right now, I don't care. pc -= 4; return nothing_special; } default: // bogus: do nothing return nothing_special; } } else { switch (rs(instr)) { case MFCz: { // Move From System Control Coprocessor ////////////////////////// gpr[rt(instr)] = sign_extend<UInt64>(read_cp0(rd(instr)), 32); return nothing_special; } case DMFCz: { // Doubleword Move From System Control Coprocessor /////////////// gpr[rt(instr)] = sign_extend<UInt64>(read_cp0(rd(instr)), 64); return nothing_special; } case CFCz: { // Move Control From Coprocessor ///////////////////////////////// return nothing_special; } case MTCz: { // Move To System Control Coprocessor //////////////////////////// write_cp0(rd(instr), sign_extend<UInt64>(gpr[rt(instr)], 32)); return nothing_special; } case DMTCz: { // Doubleword Move To System Control Coprocessor ///////////////// write_cp0(rd(instr), gpr[rt(instr)]); return nothing_special; } case CTCz: { // Move Control To Coprocessor /////////////////////////////////// return nothing_special; } case BCz: { // Branch On Coprocessor Condition /////////////////////////////// switch (rt(instr)) { case BCzF: case BCzT: case BCzFL: case BCzTL: return nothing_special; default: process_reserved_instruction(); } } default: process_reserved_instruction(); } } return nothing_special;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -