blob: e9ac058f0c4c71a43818a98e7f7ff9e872c2f806 [file] [log] [blame]
/*
* Copyright (c) 2019-2020 Cobham Gaisler AB
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <toolchain.h>
#include <linker/sections.h>
#include <offsets_short.h>
#include <arch/sparc/sparc.h>
GTEXT(__sparc_trap_fault)
/*
* Fault trap handler
*
* - IU state is saved and restored
*
* On entry:
* %l0: psr (set by trap code)
* %l1: pc
* %l2: npc
* %l6: tbr (set by trap code)
* %fp: %sp of current register window at trap time
*
* This trap handler will trash some of the global registers, which is OK since
* we will not return to where we trapped.
*/
SECTION_FUNC(TEXT, __sparc_trap_fault)
/* We may have trapped into the invalid window. If so, make it valid. */
rd %wim, %g2
srl %g2, %l0, %g3
cmp %g3, 1
bne .Lwodone
nop
/* Do the window overflow. */
sll %g2, (CONFIG_SPARC_NWIN-1), %g3
srl %g2, 1, %g2
or %g2, %g3, %g2
/* Enter window to save. */
save
/* Install new wim calculated above. */
mov %g2, %wim
nop
nop
nop
/* Put registers on the dedicated save area of the ABI stack frame. */
std %l0, [%sp + 0x00]
std %l2, [%sp + 0x08]
std %l4, [%sp + 0x10]
std %l6, [%sp + 0x18]
std %i0, [%sp + 0x20]
std %i2, [%sp + 0x28]
std %i4, [%sp + 0x30]
std %i6, [%sp + 0x38]
/* Leave saved window. */
restore
.Lwodone:
/* Allocate an ABI stack frame and exception stack frame */
sub %fp, 96 + __z_arch_esf_t_SIZEOF, %sp
/*
* %fp: %sp of interrupted task
* %sp: %sp of interrupted task - ABI_frame - esf
*/
/* Fill in the content of the exception stack frame */
st %l1, [%sp + 96 + __z_arch_esf_t_pc_OFFSET]
st %l2, [%sp + 96 + __z_arch_esf_t_npc_OFFSET]
st %l0, [%sp + 96 + __z_arch_esf_t_psr_OFFSET]
st %l6, [%sp + 96 + __z_arch_esf_t_tbr_OFFSET]
st %fp, [%sp + 96 + __z_arch_esf_t_sp_OFFSET]
rd %y, %g1
st %g1, [%sp + 96 + __z_arch_esf_t_y_OFFSET]
/* Enable traps, raise PIL to mask all maskable interrupts. */
or %l0, PSR_PIL, %o0
wr %o0, PSR_ET, %psr
nop
nop
nop
/* Exception stack frame prepared earlier is the first argument. */
call _Fault
add %sp, 96, %o0