cris: Add v10 style interrupts.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
This commit is contained in:
Edgar E. Iglesias 2010-02-15 11:47:34 +01:00
parent 95475216f2
commit 7a9773563c

View File

@ -87,10 +87,10 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
if (miss) if (miss)
{ {
if (env->exception_index == EXCP_BUSFAULT) if (env->exception_index == EXCP_BUSFAULT)
cpu_abort(env, cpu_abort(env,
"CRIS: Illegal recursive bus fault." "CRIS: Illegal recursive bus fault."
"addr=%x rw=%d\n", "addr=%x rw=%d\n",
address, rw); address, rw);
env->pregs[PR_EDA] = address; env->pregs[PR_EDA] = address;
env->exception_index = EXCP_BUSFAULT; env->exception_index = EXCP_BUSFAULT;
@ -116,10 +116,68 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
return r; return r;
} }
static void do_interruptv10(CPUState *env)
{
int ex_vec = -1;
D_LOG( "exception index=%d interrupt_req=%d\n",
env->exception_index,
env->interrupt_request);
assert(!(env->pregs[PR_CCS] & PFIX_FLAG));
switch (env->exception_index)
{
case EXCP_BREAK:
/* These exceptions are genereated by the core itself.
ERP should point to the insn following the brk. */
ex_vec = env->trap_vector;
env->pregs[PR_ERP] = env->pc;
break;
case EXCP_NMI:
/* NMI is hardwired to vector zero. */
ex_vec = 0;
env->pregs[PR_CCS] &= ~M_FLAG;
env->pregs[PR_NRP] = env->pc;
break;
case EXCP_BUSFAULT:
assert(0);
break;
default:
/* The interrupt controller gives us the vector. */
ex_vec = env->interrupt_vector;
/* Normal interrupts are taken between
TB's. env->pc is valid here. */
env->pregs[PR_ERP] = env->pc;
break;
}
if (env->pregs[PR_CCS] & U_FLAG) {
/* Swap stack pointers. */
env->pregs[PR_USP] = env->regs[R_SP];
env->regs[R_SP] = env->ksp;
}
/* Now that we are in kernel mode, load the handlers address. */
env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4);
env->locked_irq = 1;
qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
__func__, env->pc, ex_vec,
env->pregs[PR_CCS],
env->pregs[PR_PID],
env->pregs[PR_ERP]);
}
void do_interrupt(CPUState *env) void do_interrupt(CPUState *env)
{ {
int ex_vec = -1; int ex_vec = -1;
if (env->pregs[PR_VR] < 32)
return do_interruptv10(env);
D_LOG( "exception index=%d interrupt_req=%d\n", D_LOG( "exception index=%d interrupt_req=%d\n",
env->exception_index, env->exception_index,
env->interrupt_request); env->interrupt_request);
@ -184,8 +242,8 @@ void do_interrupt(CPUState *env)
/* Now that we are in kernel mode, load the handlers address. */ /* Now that we are in kernel mode, load the handlers address. */
env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4); env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4);
D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n", D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
__func__, env->pc, ex_vec, __func__, env->pc, ex_vec,
env->pregs[PR_CCS], env->pregs[PR_CCS],
env->pregs[PR_PID], env->pregs[PR_PID],
env->pregs[PR_ERP]); env->pregs[PR_ERP]);