diff --git a/tools/virtualmips/mips.c b/tools/virtualmips/mips.c index 8bccbf3..9b0aba3 100644 --- a/tools/virtualmips/mips.c +++ b/tools/virtualmips/mips.c @@ -575,7 +575,6 @@ void fastcall mips_exec_soft_fpu (cpu_mips_t * cpu) cp0->reg[MIPS_CP0_CAUSE] |= 0x10000000; //CE=1 mips_trigger_exception (cpu, MIPS_CP0_CAUSE_CP_UNUSABLE, cpu->is_in_bdslot); - } /* Execute ERET instruction */ @@ -624,19 +623,14 @@ void fastcall mips_exec_deret (cpu_mips_t *cpu) /* Execute BREAK instruction */ void fastcall mips_exec_break (cpu_mips_t * cpu, u_int code) { - //mips_dump_regs(cpu); - //printf ("exec break cpu->pc %x\n", cpu->pc); - - /* XXX TODO: Branch Delay slot */ - mips_trigger_exception (cpu, MIPS_CP0_CAUSE_BP, 0); + mips_trigger_exception (cpu, MIPS_CP0_CAUSE_BP, cpu->is_in_bdslot); } /* Trigger a Trap Exception */ void fastcall mips_trigger_trap_exception (cpu_mips_t * cpu) { - /* XXX TODO: Branch Delay slot */ - printf ("MIPS64: TRAP exception, CPU=%p\n", cpu); - mips_trigger_exception (cpu, MIPS_CP0_CAUSE_TRAP, 0); + //printf ("MIPS64: TRAP exception, CPU=%p\n", cpu); + mips_trigger_exception (cpu, MIPS_CP0_CAUSE_TRAP, cpu->is_in_bdslot); } /* Execute SYSCALL instruction */ diff --git a/tools/virtualmips/mips_codetable.c b/tools/virtualmips/mips_codetable.c index 7832a04..91e620e 100644 --- a/tools/virtualmips/mips_codetable.c +++ b/tools/virtualmips/mips_codetable.c @@ -2418,6 +2418,7 @@ static int mips_exec_mips16e(cpu_mips_t* cpu, mips_insn_t instr) cpu->reg_set(cpu, MIPS_GPR_SP, cpu->gpr[MIPS_GPR_SP] + (simm8 << 3)); break; case 4: // SVRS + // TBD!!! handle memory errors better if (instr & 0x80) { // save uint32_t temp = cpu->gpr[MIPS_GPR_SP]; cpu->reg_set(cpu, MIPS_GPR_SP, cpu->gpr[MIPS_GPR_SP] - (imm4 ? imm4 * 8 : 128)); @@ -2722,6 +2723,7 @@ static int mips_exec_mips16e(cpu_mips_t* cpu, mips_insn_t instr) cpu->reg_set(cpu, MIPS_GPR_SP, cpu->gpr[MIPS_GPR_SP] + simm16); break; case 4: { // SVRS + // TBD!!! handle memory errors better uint32_t astatic = 0; uint32_t i, temp; switch (aregs) { diff --git a/tools/virtualmips/mips_fdd.c b/tools/virtualmips/mips_fdd.c index 9109c52..15494aa 100644 --- a/tools/virtualmips/mips_fdd.c +++ b/tools/virtualmips/mips_fdd.c @@ -78,17 +78,27 @@ static int forced_inline mips_exec_memop2 (cpu_mips_t * cpu, int memop, return mips_exec_memop (cpu, memop, vaddr, dst_reg, keep_ll_bit); } +extern void mips_access_special (cpu_mips_t * cpu, m_va_t vaddr, m_uint32_t mask, + u_int op_code, u_int op_type, u_int op_size, m_reg_t * data, u_int * exc); + /* Fetch an instruction */ -static int mips_fetch_instruction_word (cpu_mips_t * cpu, - m_va_t pc, mips_insn_t * insn) +static int mips_fetch_instruction_inner (cpu_mips_t * cpu, + m_va_t pc, mips_insn_t * insn, u_int size) { m_va_t exec_page; m_uint32_t offset; + if (unlikely (pc & (size - 1))) { + u_int exc = 0; + mips_access_special(cpu, pc, MTS_ACC_AE, MIPS_MEMOP_LOOKUP, MTS_READ, size, NULL, &exc); + return (1); + } + exec_page = pc & ~(m_va_t) MIPS_MIN_PAGE_IMASK; if (unlikely (exec_page != cpu->njm_exec_page)) { cpu->njm_exec_ptr = cpu->mem_op_lookup (cpu, exec_page); } + if (cpu->njm_exec_ptr == NULL) { //exception when fetching instruction return (1); @@ -96,6 +106,13 @@ static int mips_fetch_instruction_word (cpu_mips_t * cpu, cpu->njm_exec_page = exec_page; offset = (pc & MIPS_MIN_PAGE_IMASK) >> 2; *insn = vmtoh32 (cpu->njm_exec_ptr[offset]); + if (unlikely (size == 2)) { + if (pc & 2) { + *insn >>= 16; + } else { + *insn &= 0xFFFF; + } + } // printf ("(%08x) %08x\n", pc, *insn); return (0); } @@ -103,35 +120,28 @@ static int mips_fetch_instruction_word (cpu_mips_t * cpu, int mips_fetch_instruction (cpu_mips_t * cpu, m_va_t pc, mips_insn_t * insn) { - int res = mips_fetch_instruction_word(cpu, pc, insn); - cpu->insn_len = 4; - if (unlikely(res)) { - return res; - } + int res; if (unlikely(cpu->is_mips16e)) { - mips_insn_t i; - if (pc & 2) { - i = *insn >> 16; - } else { - i = *insn & 0xFFFF; + res = mips_fetch_instruction_inner(cpu, pc, insn, 2); + if (unlikely(res)) { + return res; } - if (unlikely((i >> 11) == 0x1E || (i >> 11) == 3)) { - /* 4-byte extended instruction or jal(x) */ - if (pc & 2) { - /* 2 more bytes needed */ - res = mips_fetch_instruction_word(cpu, pc + 2, insn); - if (unlikely(res)) { - return res; - } - *insn = (i << 16) | (*insn & 0xFFFF); - } else { - *insn = (*insn << 16) | (*insn >> 16); + if (unlikely((*insn >> 11) == 0x1E || (*insn >> 11) == 3)) { + /* 4-byte extended instruction or jal(x): 2 more bytes needed */ + mips_insn_t i; + res = mips_fetch_instruction_inner(cpu, pc + 2, &i, 2); + if (unlikely(res)) { + return res; } + *insn = (*insn << 16) | i; + cpu->insn_len = 4; } else { /* 2-byte instruction */ - *insn = i; cpu->insn_len = 2; } + } else { + res = mips_fetch_instruction_inner(cpu, pc, insn, 4); + cpu->insn_len = 4; } return res; }