168 lines
3.7 KiB
ArmAsm
168 lines
3.7 KiB
ArmAsm
/*
|
|
* Copyright (c) 2019-2020 Cobham Gaisler AB
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/*
|
|
* This file contains standard handlers for the SPARC V8 window overflow and
|
|
* underflow traps. It also implements the handler for SPARC-ABI
|
|
* "Flush windows" which is used for example by longjmp() and C++ exceptions.
|
|
*/
|
|
|
|
#include <zephyr/toolchain.h>
|
|
#include <zephyr/linker/sections.h>
|
|
#include <zephyr/arch/sparc/sparc.h>
|
|
|
|
GTEXT(__sparc_trap_window_overflow)
|
|
GTEXT(__sparc_trap_window_underflow)
|
|
GTEXT(__sparc_trap_flush_windows)
|
|
|
|
SECTION_FUNC(TEXT, __sparc_trap_window_overflow)
|
|
/* Enter the window to be stored. */
|
|
save
|
|
/* Save local register set. */
|
|
std %l0, [%sp + 0x00]
|
|
std %l2, [%sp + 0x08]
|
|
std %l4, [%sp + 0x10]
|
|
rd %wim, %l3
|
|
std %l6, [%sp + 0x18]
|
|
/* l2 := WIM << (NWIN-1) */
|
|
sll %l3, (CONFIG_SPARC_NWIN-1), %l2
|
|
/* Save input register set. */
|
|
std %i0, [%sp + 0x20]
|
|
/* l3 := WIM >> 1 */
|
|
srl %l3, 1, %l3
|
|
std %i2, [%sp + 0x28]
|
|
/* WIM := (WIM >> 1) ^ (WIM << (NWIN-1)) */
|
|
wr %l3, %l2, %wim
|
|
/* NOTE: 3 instruction before restore (delayed write instruction) */
|
|
std %i4, [%sp + 0x30]
|
|
nop
|
|
std %i6, [%sp + 0x38]
|
|
/* Go back to trap window. */
|
|
restore
|
|
/* Re-execute save. */
|
|
jmp %l1
|
|
rett %l2
|
|
|
|
SECTION_FUNC(TEXT, __sparc_trap_window_underflow)
|
|
rd %wim, %l3
|
|
/* l4 := WIM << 1 */
|
|
sll %l3, 1, %l4
|
|
/* l5 := WIM >> (NWIN-1) */
|
|
srl %l3, (CONFIG_SPARC_NWIN-1), %l5
|
|
/* WIM := (WIM << 1) ^ (WIM >> (NWIN-1)) */
|
|
wr %l4, %l5, %wim
|
|
/* WIM is implicitly read so nops are needed. */
|
|
nop
|
|
nop
|
|
nop
|
|
|
|
/* Enter the window to restore requires two restore instructions. */
|
|
restore
|
|
restore
|
|
ldd [%sp + 0x00], %l0
|
|
ldd [%sp + 0x08], %l2
|
|
ldd [%sp + 0x10], %l4
|
|
ldd [%sp + 0x18], %l6
|
|
ldd [%sp + 0x20], %i0
|
|
ldd [%sp + 0x28], %i2
|
|
ldd [%sp + 0x30], %i4
|
|
ldd [%sp + 0x38], %i6
|
|
/* Go back to the trap window. */
|
|
save
|
|
save
|
|
/* Re-execute restore. */
|
|
jmp %l1
|
|
rett %l2
|
|
|
|
/*
|
|
* Handler for SPARC trap 0x83: trap_instruction, defined as "Flush windows" by
|
|
* SPARC-ABI:
|
|
* "By executing a type 3 trap, a process asks the system to flush all its
|
|
* register windows to the stack."
|
|
*
|
|
* On entry:
|
|
* %l0: psr
|
|
* %l1: pc
|
|
* %l2: npc
|
|
*/
|
|
SECTION_FUNC(TEXT, __sparc_trap_flush_windows)
|
|
/* Save global registers used by the routine */
|
|
mov %g3, %l3
|
|
mov %g4, %l4
|
|
mov %g5, %l5
|
|
mov %g1, %l6
|
|
mov %g2, %l7
|
|
|
|
/* Uses g3=psr, g4=1, g2=wim, g1,g5=scratch */
|
|
mov %l0, %g3
|
|
set 1, %g4
|
|
rd %wim, %g2
|
|
|
|
/*
|
|
* We can always restore the previous window. Check if we can restore
|
|
* the window after that.
|
|
*/
|
|
and %l0, PSR_CWP, %g1
|
|
add %g1, 2, %g1
|
|
ba .LcheckNextWindow
|
|
restore
|
|
|
|
/* Flush window to stack */
|
|
.LflushWindow:
|
|
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]
|
|
|
|
/*
|
|
* Check if next window is invalid by comparing
|
|
* (1 << ((cwp + 1) % NWIN)) with WIM
|
|
*/
|
|
.LcheckNextWindow:
|
|
set CONFIG_SPARC_NWIN, %g5
|
|
cmp %g1, %g5
|
|
bge,a .Lnowrap
|
|
sub %g1, %g5, %g1
|
|
.Lnowrap:
|
|
sll %g4, %g1, %g5
|
|
cmp %g5, %g2
|
|
be .LflushWindowDone
|
|
inc %g1
|
|
|
|
/* We need to flush the next window */
|
|
ba .LflushWindow
|
|
restore
|
|
|
|
/*
|
|
* All used windows have been flushed. Set WIM to cause trap for CWP+2.
|
|
* When we return from this trap it will be CWP+1 that will trap, that
|
|
* is, the next restore or rett.
|
|
*/
|
|
.LflushWindowDone:
|
|
/* We can not restore %psr from %l0 because we may be in any window. */
|
|
wr %g3, %psr
|
|
and %g3, PSR_CWP, %g1
|
|
add %g1, 2, %g1
|
|
set CONFIG_SPARC_NWIN, %g5
|
|
/* We are now back in the trap window. */
|
|
cmp %g1, %g5
|
|
bge,a .Lnowrap2
|
|
sub %g1, %g5, %g1
|
|
.Lnowrap2:
|
|
sll %g4, %g1, %g1
|
|
wr %g1, %wim
|
|
mov %l3, %g3
|
|
mov %l4, %g4
|
|
mov %l5, %g5
|
|
mov %l6, %g1
|
|
mov %l7, %g2
|
|
jmp %l2
|
|
rett %l2 + 4
|