2cdfc43f10
Change-Id: I1625873b6864584c40984723d82548ad242ee08e
57 lines
2.4 KiB
ArmAsm
57 lines
2.4 KiB
ArmAsm
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2014 by Amaury Pouly
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/* Handling of data abort:
|
|
* the code can register a "longjmp" buffer to restore the context in case of
|
|
* fault */
|
|
.data
|
|
data_abort_jmp_ctx_ptr:
|
|
/* buffer contains in order: cpsr,r4-r11,sp,lr,pc */
|
|
.skip 48 /* = 4 * (cpsr + 11 registers) */
|
|
|
|
.text
|
|
/* Prototype: int set_data_abort_jmp()
|
|
* Return: 1 in case of data abort, 0 otherwise */
|
|
.global set_data_abort_jmp
|
|
set_data_abort_jmp:
|
|
mrs r2, cpsr
|
|
ldr r1, =data_abort_jmp_ctx_ptr
|
|
mov r0, #0
|
|
stmia r1, {r2,r4-r11,sp,lr,pc} /* see PC note below */
|
|
bx lr
|
|
mov r0, #1 /* <-- PC points here in stmia */
|
|
bx lr
|
|
|
|
.global data_abort_handler
|
|
data_abort_handler:
|
|
/* restore everything from context */
|
|
ldr r1, =data_abort_jmp_ctx_ptr
|
|
/* NOTE: we need to restore sp_sys and lr_sys, for this we need the
|
|
* LDM Rn, {}^
|
|
* variant, but we cannot restore PC from it because ^ has a different
|
|
* meaning and won't restore user/sys registers. On top of that, the
|
|
* non-PC ^ variant cannot do the register writeback, so on the PC restore,
|
|
* we reload all registers once again to avoid manually offseting the base
|
|
* register, it will trash sp_abt and lr_abr but those are unused anyway
|
|
* because we do not save the abort address and we don't use an abort stack */
|
|
ldmia r1, {r0,r4-r11,sp,lr}^ /* this variant cannot have writeback (r1!) */
|
|
msr spsr, r0
|
|
ldmia r1, {r0,r4-r11,sp,lr,pc}^ /* reload some registers but we don't care */
|