Virtualmips: merge changes from alexfru.

This commit is contained in:
Serge Vakulenko
2015-10-29 18:11:41 -07:00
parent 666f22786f
commit 1a5f550fe1
3 changed files with 39 additions and 33 deletions

View File

@@ -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 */

View File

@@ -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) {

View File

@@ -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;
}