diff options
author | Edgar E. Iglesias <edgar.iglesias@gmail.com> | 2010-02-15 11:47:34 +0100 |
---|---|---|
committer | Edgar E. Iglesias <edgar.iglesias@gmail.com> | 2010-02-15 11:47:34 +0100 |
commit | 7a9773563c99a86aec454f9e14f7a19ca1f87659 (patch) | |
tree | ce9d6ae49bc17e0652ea2dd0035c360fe009f4a3 /target-cris | |
parent | 95475216f23216683b85c420132849553319eae2 (diff) |
cris: Add v10 style interrupts.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Diffstat (limited to 'target-cris')
-rw-r--r-- | target-cris/helper.c | 68 |
1 files changed, 63 insertions, 5 deletions
diff --git a/target-cris/helper.c b/target-cris/helper.c index ff4f2fe1da..a17a9f0cb5 100644 --- a/target-cris/helper.c +++ b/target-cris/helper.c @@ -87,10 +87,10 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, if (miss) { if (env->exception_index == EXCP_BUSFAULT) - cpu_abort(env, + cpu_abort(env, "CRIS: Illegal recursive bus fault." - "addr=%x rw=%d\n", - address, rw); + "addr=%x rw=%d\n", + address, rw); env->pregs[PR_EDA] = address; env->exception_index = EXCP_BUSFAULT; @@ -116,10 +116,68 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, 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) { int ex_vec = -1; + if (env->pregs[PR_VR] < 32) + return do_interruptv10(env); + D_LOG( "exception index=%d interrupt_req=%d\n", env->exception_index, env->interrupt_request); @@ -184,8 +242,8 @@ void do_interrupt(CPUState *env) /* Now that we are in kernel mode, load the handlers address. */ 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", - __func__, env->pc, ex_vec, + D_LOG("%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]); |