mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-11 09:45:29 +00:00
armv7m: Extract "exception taken" code into functions
Extract the code from the tail end of arm_v7m_do_interrupt() which enters the exception handler into a pair of utility functions v7m_exception_taken() and v7m_push_stack(), which correspond roughly to the pseudocode PushStack() and ExceptionTaken(). This also requires us to move the arm_v7m_load_vector() utility routine up so we can call it. Handling illegal exception returns has some cases where we want to take a UsageFault either on an existing stack frame or with a new stack frame but with a specific LR value, so we want to be able to call these without having to go via arm_v7m_cpu_do_interrupt(). Backports commit 39ae2474e337247e5930e8be783b689adc9f6215 from qemu
This commit is contained in:
parent
5b9f53bd27
commit
0736054d6d
|
@ -5327,6 +5327,73 @@ static void switch_v7m_sp(CPUARMState *env, bool new_spsel)
|
|||
}
|
||||
}
|
||||
|
||||
static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
|
||||
{
|
||||
CPUState *cs = CPU(cpu);
|
||||
CPUARMState *env = &cpu->env;
|
||||
MemTxResult result;
|
||||
hwaddr vec = env->v7m.vecbase + env->v7m.exception * 4;
|
||||
uint32_t addr;
|
||||
|
||||
addr = address_space_ldl(cs->as, vec,
|
||||
MEMTXATTRS_UNSPECIFIED, &result);
|
||||
if (result != MEMTX_OK) {
|
||||
/* Architecturally this should cause a HardFault setting HSFR.VECTTBL,
|
||||
* which would then be immediately followed by our failing to load
|
||||
* the entry vector for that HardFault, which is a Lockup case.
|
||||
* Since we don't model Lockup, we just report this guest error
|
||||
* via cpu_abort().
|
||||
*/
|
||||
cpu_abort(cs, "Failed to read from exception vector table "
|
||||
"entry %08x\n", (unsigned)vec);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr)
|
||||
{
|
||||
/* Do the "take the exception" parts of exception entry,
|
||||
* but not the pushing of state to the stack. This is
|
||||
* similar to the pseudocode ExceptionTaken() function.
|
||||
*/
|
||||
CPUARMState *env = &cpu->env;
|
||||
uint32_t addr;
|
||||
|
||||
// Unicorn: commented out
|
||||
//armv7m_nvic_acknowledge_irq(env->nvic);
|
||||
switch_v7m_sp(env, 0);
|
||||
/* Clear IT bits */
|
||||
env->condexec_bits = 0;
|
||||
env->regs[14] = lr;
|
||||
addr = arm_v7m_load_vector(cpu);
|
||||
env->regs[15] = addr & 0xfffffffe;
|
||||
env->thumb = addr & 1;
|
||||
}
|
||||
|
||||
static void v7m_push_stack(ARMCPU *cpu)
|
||||
{
|
||||
/* Do the "set up stack frame" part of exception entry,
|
||||
* similar to pseudocode PushStack().
|
||||
*/
|
||||
CPUARMState *env = &cpu->env;
|
||||
uint32_t xpsr = xpsr_read(env);
|
||||
|
||||
/* Align stack pointer if the guest wants that */
|
||||
if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
|
||||
env->regs[13] -= 4;
|
||||
xpsr |= 0x200;
|
||||
}
|
||||
/* Switch to the handler mode. */
|
||||
v7m_push(env, xpsr);
|
||||
v7m_push(env, env->regs[15]);
|
||||
v7m_push(env, env->regs[14]);
|
||||
v7m_push(env, env->regs[12]);
|
||||
v7m_push(env, env->regs[3]);
|
||||
v7m_push(env, env->regs[2]);
|
||||
v7m_push(env, env->regs[1]);
|
||||
v7m_push(env, env->regs[0]);
|
||||
}
|
||||
|
||||
static void do_v7m_exception_exit(CPUARMState *env)
|
||||
{
|
||||
uint32_t type;
|
||||
|
@ -5410,37 +5477,11 @@ static void arm_log_exception(int idx)
|
|||
}
|
||||
}
|
||||
|
||||
static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
|
||||
|
||||
{
|
||||
CPUState *cs = CPU(cpu);
|
||||
CPUARMState *env = &cpu->env;
|
||||
MemTxResult result;
|
||||
hwaddr vec = env->v7m.vecbase + env->v7m.exception * 4;
|
||||
uint32_t addr;
|
||||
|
||||
addr = address_space_ldl(cs->as, vec,
|
||||
MEMTXATTRS_UNSPECIFIED, &result);
|
||||
if (result != MEMTX_OK) {
|
||||
/* Architecturally this should cause a HardFault setting HSFR.VECTTBL,
|
||||
* which would then be immediately followed by our failing to load
|
||||
* the entry vector for that HardFault, which is a Lockup case.
|
||||
* Since we don't model Lockup, we just report this guest error
|
||||
* via cpu_abort().
|
||||
*/
|
||||
cpu_abort(cs, "Failed to read from exception vector table "
|
||||
"entry %08x\n", (unsigned)vec);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
void arm_v7m_cpu_do_interrupt(CPUState *cs)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(cs->uc, cs);
|
||||
CPUARMState *env = cs->env_ptr;
|
||||
uint32_t xpsr = xpsr_read(env);
|
||||
uint32_t lr;
|
||||
uint32_t addr;
|
||||
|
||||
arm_log_exception(cs->exception_index);
|
||||
|
||||
|
@ -5541,32 +5582,9 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
|
|||
return; /* Never happens. Keep compiler happy. */
|
||||
}
|
||||
|
||||
// Unicorn: commented out
|
||||
//armv7m_nvic_acknowledge_irq(env->nvic);
|
||||
|
||||
v7m_push_stack(cpu);
|
||||
v7m_exception_taken(cpu, lr);
|
||||
qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
|
||||
|
||||
/* Align stack pointer if the guest wants that */
|
||||
if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
|
||||
env->regs[13] -= 4;
|
||||
xpsr |= 0x200;
|
||||
}
|
||||
/* Switch to the handler mode. */
|
||||
v7m_push(env, xpsr);
|
||||
v7m_push(env, env->regs[15]);
|
||||
v7m_push(env, env->regs[14]);
|
||||
v7m_push(env, env->regs[12]);
|
||||
v7m_push(env, env->regs[3]);
|
||||
v7m_push(env, env->regs[2]);
|
||||
v7m_push(env, env->regs[1]);
|
||||
v7m_push(env, env->regs[0]);
|
||||
switch_v7m_sp(env, 0);
|
||||
/* Clear IT bits */
|
||||
env->condexec_bits = 0;
|
||||
env->regs[14] = lr;
|
||||
addr = arm_v7m_load_vector(cpu);
|
||||
env->regs[15] = addr & 0xfffffffe;
|
||||
env->thumb = addr & 1;
|
||||
}
|
||||
|
||||
/* Function used to synchronize QEMU's AArch64 register set with AArch32
|
||||
|
|
Loading…
Reference in a new issue