cris: Add v10 style interrupts.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
This commit is contained in:
parent
95475216f2
commit
7a9773563c
@ -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]);
|
||||||
|
Loading…
Reference in New Issue
Block a user