diff --git a/src/cpu/mips3/cop0.cpp b/src/cpu/mips3/cop0.cpp index fc455fb28..f3862e89d 100644 --- a/src/cpu/mips3/cop0.cpp +++ b/src/cpu/mips3/cop0.cpp @@ -41,6 +41,10 @@ void mips3::cop0_execute(uint32_t opcode) // MFC case 0x00: if (RTNUM) { + if (RDNUM == COP0_Count) { + RT = (uint32_t) ((m_state.total_cycles - m_state.reset_cycle) / 2); + return; + } RT = CR(RDNUM); } break; @@ -48,6 +52,9 @@ void mips3::cop0_execute(uint32_t opcode) // MTC case 0x04: m_state.cpr[0][RDNUM] = RT; + if (RDNUM == COP0_Count) { + m_state.reset_cycle = m_state.total_cycles - ((uint64_t)(uint32_t)RT * 2); + } break; // TLBWI diff --git a/src/cpu/mips3/mips3.cpp b/src/cpu/mips3/mips3.cpp index 42e1c561f..a71ae39bb 100644 --- a/src/cpu/mips3/mips3.cpp +++ b/src/cpu/mips3/mips3.cpp @@ -3,6 +3,13 @@ * Copyright (c) 2015, Marcos Medeiros * Licensed under BSD 3-clause. */ +/* + * TODO: + * Fix TLB emulation + * COP1 FR0 opcodes + * Exceptions!!! + **/ + //#include #include #include @@ -90,6 +97,7 @@ uint32_t mips3::translate(addr_t addr, addr_t *out) } +#if MIPS3_ENABLE_BREAKPOINTS void mips3::bp_insert(addr_t address) { @@ -106,25 +114,30 @@ inline bool mips3::check_breakpoint() return (m_breakpoints.find(m_state.pc) != m_breakpoints.end()); } +#endif + bool mips3::run(int cycles, bool skip_bps) { m_counter = 0; + int last_icounter = 0; // endereço efetivo addr_t eaddr = 0; +#if MIPS3_ENABLE_BREAKPOINTS if (!skip_bps && check_breakpoint()) return true; +#endif while (m_counter < cycles) { if (translate(m_state.pc, &eaddr)) { - /* ocorreu algum erro */ + /* TODO: handle exceptions */ } m_prev_pc = m_state.pc; uint32_t opcode = mem::read_word(eaddr); - // A instrução que precede um branch/jump sempre é executada + // We always execute delay slot if (m_delay_slot) { m_state.pc = m_next_pc; m_delay_slot = false; @@ -133,6 +146,8 @@ bool mips3::run(int cycles, bool skip_bps) m_state.pc += 4; } + last_icounter = m_counter; + switch (opcode >> 26) { // SPECIAL @@ -418,13 +433,13 @@ bool mips3::run(int cycles, bool skip_bps) break; } - // Increment COP0 Count - m_state.cpr[0][COP0_Count] += 20; m_counter++; + m_state.total_cycles += m_counter - last_icounter; +#if MIPS3_ENABLE_BREAKPOINTS if (!skip_bps && check_breakpoint()) return true; +#endif } - m_state.total_cycles += m_counter; return false; } diff --git a/src/cpu/mips3/mips3.h b/src/cpu/mips3/mips3.h index 395210868..f9c803b39 100644 --- a/src/cpu/mips3/mips3.h +++ b/src/cpu/mips3/mips3.h @@ -5,6 +5,8 @@ #ifndef MIPS3_H #define MIPS3_H +#define MIPS3_ENABLE_BREAKPOINTS 0 + #include "mips3_common.h" #include @@ -107,14 +109,18 @@ public: uint32_t translate(addr_t addr, addr_t *out); const int m_tlb_entries; +#if MIPS3_ENABLE_BREAKPOINTS void bp_insert(addr_t address); void bp_remove(addr_t address); +#endif private: int m_counter; addr_t tlb_translate(addr_t address); +#if MIPS3_ENABLE_BREAKPOINTS unordered_set m_breakpoints; bool check_breakpoint(); +#endif void tlb_init(); void tlb_flush(); void cop0_reset(); diff --git a/src/cpu/mips3/x64/mips3_x64_cop0.h b/src/cpu/mips3/x64/mips3_x64_cop0.h index a7fe9ed83..cc587fc98 100644 --- a/src/cpu/mips3/x64/mips3_x64_cop0.h +++ b/src/cpu/mips3/x64/mips3_x64_cop0.h @@ -24,19 +24,18 @@ bool mips3_x64::compile_cop0(uint32_t opcode) case 0x00: if (RTNUM) { switch (RDNUM) { - // Hack: (total_cycles - reset_cycle) * 16 + case COP0_Count: m_block_icounter += 250; - //sub(r15, 250); mov(rax, TOTAL_x); sub(rax, RSTCYC_x); shr(rax, 1); + and_(eax, ~0); mov(RT_x, rax); return false; case COP0_Cause: m_block_icounter += 250; - //sub(r15, 250); break; } mov(rax, COP0_x(RDNUM)); @@ -44,6 +43,17 @@ bool mips3_x64::compile_cop0(uint32_t opcode) mov(RT_x, rax); } break; + // MTC0 rd, rt + case 0x04: + if (RDNUM == COP0_Count) { + mov(rax, RT_x); + mov(COP0_x(COP0_Count), rax); + mov(rcx, TOTAL_x); + shl(eax, 1); + sub(rcx, rax); + mov(RSTCYC_q, rax); + return false; + } default: fallback(opcode, &mips3::cop0_execute); break;