diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2011-09-06 03:55:51 +0400 |
---|---|---|
committer | Blue Swirl <blauwirbel@gmail.com> | 2011-09-10 16:57:40 +0000 |
commit | 97836ceed39bb1be9a72c9d7c122657d569731d9 (patch) | |
tree | c4fffbc9a31700a6276d0570021e1e88c73a2e43 /target-xtensa/helper.c | |
parent | f3df4c04d83b7f2f319ca8025c895b74aa7eab8d (diff) |
target-xtensa: implement relocatable vectors
See ISA, 4.4.3 for details.
Vector addresses recorded in core configuration are absolute values that
correspond to default VECBASE value.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Diffstat (limited to 'target-xtensa/helper.c')
-rw-r--r-- | target-xtensa/helper.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c index c24a38a99a..dacb379221 100644 --- a/target-xtensa/helper.c +++ b/target-xtensa/helper.c @@ -41,6 +41,7 @@ void cpu_reset(CPUXtensaState *env) env->sregs[LITBASE] &= ~1; env->sregs[PS] = xtensa_option_enabled(env->config, XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10; + env->sregs[VECBASE] = env->config->vecbase; env->pending_irq_level = 0; } @@ -54,6 +55,7 @@ static const XtensaConfig core_config[] = { .nareg = 64, .ndepc = 1, .excm_level = 16, + .vecbase = 0x5fff8400, .exception_vector = { [EXC_RESET] = 0x5fff8000, [EXC_WINDOW_OVERFLOW4] = 0x5fff8400, @@ -140,6 +142,16 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) return addr; } +static uint32_t relocated_vector(CPUState *env, uint32_t vector) +{ + if (xtensa_option_enabled(env->config, + XTENSA_OPTION_RELOCATABLE_VECTOR)) { + return vector - env->config->vecbase + env->sregs[VECBASE]; + } else { + return vector; + } +} + /*! * Handle penging IRQ. * For the high priority interrupt jump to the corresponding interrupt vector. @@ -160,7 +172,8 @@ static void handle_interrupt(CPUState *env) env->sregs[EPS2 + level - 2] = env->sregs[PS]; env->sregs[PS] = (env->sregs[PS] & ~PS_INTLEVEL) | level | PS_EXCM; - env->pc = env->config->interrupt_vector[level]; + env->pc = relocated_vector(env, + env->config->interrupt_vector[level]); } else { env->sregs[EXCCAUSE] = LEVEL1_INTERRUPT_CAUSE; @@ -212,7 +225,8 @@ void do_interrupt(CPUState *env) __func__, env->exception_index, env->pc, env->regs[0], env->sregs[PS], env->sregs[CCOUNT]); if (env->config->exception_vector[env->exception_index]) { - env->pc = env->config->exception_vector[env->exception_index]; + env->pc = relocated_vector(env, + env->config->exception_vector[env->exception_index]); env->exception_taken = 1; } else { qemu_log("%s(pc = %08x) bad exception_index: %d\n", |