Virtualmips: fix exception vectors.

This commit is contained in:
Serge Vakulenko
2015-10-28 17:21:31 -07:00
parent ce4fbe98b7
commit f2c4d11b74

View File

@@ -29,12 +29,12 @@
#include "mips_cp0.h"
#include "mips_jit.h"
#define GDB_SR 32
#define GDB_LO 33
#define GDB_HI 34
#define GDB_BAD 35
#define GDB_CAUSE 36
#define GDB_PC 37
#define GDB_SR 32
#define GDB_LO 33
#define GDB_HI 34
#define GDB_BAD 35
#define GDB_CAUSE 36
#define GDB_PC 37
/* MIPS general purpose registers names */
char *mips_gpr_reg_names[MIPS64_GPR_NR] = {
@@ -49,6 +49,11 @@ static int cca_cache_status[8] = {
1, 1, 0, 1, 0, 1, 0, 0,
};
/* Exception vectors. */
#define VECTOR_TLB_REFILL 0x000
#define VECTOR_GENERIC 0x180
#define VECTOR_INTERRUPT 0x200
/* Get register index given its name */
int mips_get_reg_index (char *name)
{
@@ -429,21 +434,21 @@ void mips_trigger_exception (cpu_mips_t * cpu, u_int exc_code, int bd_slot)
{
mips_cp0_t *cp0 = &cpu->cp0;
m_uint64_t new_pc;
m_uint32_t old_status = cp0->reg[MIPS_CP0_STATUS];
m_reg_t cause;
/* keep IM, set exception code and bd slot */
cause = cp0->reg[MIPS_CP0_CAUSE];
/* we don't set EPC if EXL is set */
if (!(cp0->reg[MIPS_CP0_STATUS] & MIPS_CP0_STATUS_EXL)) {
/* If EXL is set, neither EPC nor Cause.BD are modified. */
if (! (old_status & MIPS_CP0_STATUS_EXL)) {
cp0->reg[MIPS_CP0_EPC] = cpu->pc | cpu->is_mips16e;
/*Cause BD is not update. MIPS VOLUME V3 P65 */
cause &= ~MIPS_CP0_CAUSE_BD_SLOT; //clear bd
/* Update Cause.BD */
if (bd_slot)
cause |= MIPS_CP0_CAUSE_BD_SLOT;
else
cause &= ~MIPS_CP0_CAUSE_BD_SLOT;
}
cpu->is_mips16e = 0;
@@ -464,45 +469,33 @@ void mips_trigger_exception (cpu_mips_t * cpu, u_int exc_code, int bd_slot)
if (cpu->vm->debug_level > 2) {
printf (" exception %u at %08x\n", exc_code, cpu->pc);
}
/* Compute the vector address. */
if (cp0->reg[MIPS_CP0_STATUS] & MIPS_CP0_STATUS_BEV) {
if ((exc_code == MIPS_CP0_CAUSE_TLB_LOAD)
|| (exc_code == MIPS_CP0_CAUSE_TLB_SAVE)) {
if (cp0->reg[MIPS_CP0_STATUS] & MIPS_CP0_STATUS_EXL)
new_pc = 0xffffffffbfc00380ULL;
else
new_pc = 0xffffffffbfc00200ULL;
} else if (exc_code == MIPS_CP0_CAUSE_INTERRUPT) {
if (cp0->reg[MIPS_CP0_CAUSE] & MIPS_CP0_CAUSE_IV)
new_pc = 0xffffffffbfc00400ULL;
else
new_pc = 0xffffffffbfc00380ULL;
} else
new_pc = 0xffffffffbfc00380ULL;
/* Boot exception vector. */
new_pc = 0xffffffffbfc00200ULL + VECTOR_GENERIC;
} else {
#if SIM_PIC32
/* TODO */
new_pc = cp0->ebase_reg + 0x200;
if (exc_code != MIPS_CP0_CAUSE_INTERRUPT &&
(exc_code != MIPS_CP0_CAUSE_SYSCALL || cpu->vm->debug_level > 0))
print_exception (cpu, exc_code);
#else
if ((exc_code == MIPS_CP0_CAUSE_TLB_LOAD)
|| (exc_code == MIPS_CP0_CAUSE_TLB_SAVE)) {
if (cp0->reg[MIPS_CP0_STATUS] & MIPS_CP0_STATUS_EXL)
new_pc = 0xffffffff80000180ULL;
else
new_pc = 0xffffffff80000000ULL;
} else if (exc_code == MIPS_CP0_CAUSE_INTERRUPT) {
if (cp0->reg[MIPS_CP0_CAUSE] & MIPS_CP0_CAUSE_IV)
new_pc = 0xffffffff80000200ULL;
else
new_pc = 0xffffffff80000180ULL;
} else
new_pc = 0xffffffff80000180ULL;
#endif
/* Use EBase register value. */
new_pc = cp0->ebase_reg + VECTOR_GENERIC;
}
if (! (old_status & MIPS_CP0_STATUS_EXL)) {
if (exc_code == MIPS_CP0_CAUSE_TLB_LOAD ||
exc_code == MIPS_CP0_CAUSE_TLB_SAVE)
{
/* TBL refill: use offset 0. */
new_pc += VECTOR_TLB_REFILL - VECTOR_GENERIC;
} else if (exc_code == MIPS_CP0_CAUSE_INTERRUPT &&
(cp0->reg[MIPS_CP0_CAUSE] & MIPS_CP0_CAUSE_IV))
{
/* Interrupt: use offset 0x200. */
new_pc += VECTOR_INTERRUPT - VECTOR_GENERIC;
}
}
if (exc_code != MIPS_CP0_CAUSE_INTERRUPT &&
(exc_code != MIPS_CP0_CAUSE_SYSCALL || cpu->vm->debug_level > 0))
print_exception (cpu, exc_code);
cpu->pc = (m_va_t) new_pc;