From 97836ceed39bb1be9a72c9d7c122657d569731d9 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Tue, 6 Sep 2011 03:55:51 +0400 Subject: [PATCH] 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 Signed-off-by: Blue Swirl --- target-xtensa/cpu.h | 2 ++ target-xtensa/helper.c | 18 ++++++++++++++++-- target-xtensa/translate.c | 1 + 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h index 37f8b7f6d5..c9094e902b 100644 --- a/target-xtensa/cpu.h +++ b/target-xtensa/cpu.h @@ -123,6 +123,7 @@ enum { INTCLEAR = 227, INTENABLE = 228, PS = 230, + VECBASE = 231, EXCCAUSE = 232, CCOUNT = 234, PRID = 235, @@ -219,6 +220,7 @@ typedef struct XtensaConfig { unsigned nareg; int excm_level; int ndepc; + uint32_t vecbase; uint32_t exception_vector[EXC_MAX]; unsigned ninterrupt; unsigned nlevel; 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", diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index d08b0ca66b..bd10ae5568 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -106,6 +106,7 @@ static const char * const sregnames[256] = { [INTCLEAR] = "INTCLEAR", [INTENABLE] = "INTENABLE", [PS] = "PS", + [VECBASE] = "VECBASE", [EXCCAUSE] = "EXCCAUSE", [CCOUNT] = "CCOUNT", [PRID] = "PRID", -- 2.11.4.GIT