1/*
2 * Copyright (c) 2019-2020 Cobham Gaisler AB
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7/*
8 * This file contains standard handlers for the SPARC V8 window overflow and
9 * underflow traps. It also implements the handler for SPARC-ABI
10 * "Flush windows" which is used for example by longjmp() and C++ exceptions.
11 */
12
13#include <toolchain.h>
14#include <linker/sections.h>
15#include <arch/sparc/sparc.h>
16
17GTEXT(__sparc_trap_window_overflow)
18GTEXT(__sparc_trap_window_underflow)
19GTEXT(__sparc_trap_flush_windows)
20
21SECTION_FUNC(TEXT, __sparc_trap_window_overflow)
22	/* Enter the window to be stored. */
23	save
24	/* Save local register set. */
25	std	%l0, [%sp + 0x00]
26	std	%l2, [%sp + 0x08]
27	std	%l4, [%sp + 0x10]
28	rd	%wim, %l3
29	std	%l6, [%sp + 0x18]
30	/* l2 := WIM << (NWIN-1) */
31	sll	%l3, (CONFIG_SPARC_NWIN-1), %l2
32	/* Save input register set. */
33	std	%i0, [%sp + 0x20]
34	/* l3 := WIM >> 1 */
35	srl	%l3, 1, %l3
36	std	%i2, [%sp + 0x28]
37	/* WIM := (WIM >> 1) ^ (WIM << (NWIN-1)) */
38	wr	%l3, %l2, %wim
39	/* NOTE: 3 instruction before restore (delayed write instruction) */
40	std	%i4, [%sp + 0x30]
41	nop
42	std	%i6, [%sp + 0x38]
43	/* Go back to trap window. */
44	restore
45	/* Re-execute save. */
46	jmp	%l1
47	 rett	%l2
48
49SECTION_FUNC(TEXT, __sparc_trap_window_underflow)
50	rd	%wim, %l3
51	/* l4 := WIM << 1 */
52	sll	%l3, 1, %l4
53	/* l5 := WIM >> (NWIN-1) */
54	srl	%l3, (CONFIG_SPARC_NWIN-1), %l5
55	/* WIM := (WIM << 1) ^ (WIM >> (NWIN-1)) */
56	wr	%l4, %l5, %wim
57	/* WIM is implicitly read so nops are needed. */
58	nop
59	nop
60	nop
61
62	/* Enter the window to restore requires two restore instructions. */
63	restore
64	restore
65	ldd	[%sp + 0x00], %l0
66	ldd	[%sp + 0x08], %l2
67	ldd	[%sp + 0x10], %l4
68	ldd	[%sp + 0x18], %l6
69	ldd	[%sp + 0x20], %i0
70	ldd	[%sp + 0x28], %i2
71	ldd	[%sp + 0x30], %i4
72	ldd	[%sp + 0x38], %i6
73	/* Go back to the trap window. */
74	save
75	save
76	/* Re-execute restore. */
77	jmp	%l1
78	 rett	%l2
79
80/*
81 * Handler for SPARC trap 0x83: trap_instruction, defined as "Flush windows" by
82 * SPARC-ABI:
83 *   "By executing a type 3 trap, a process asks the system to flush all its
84 *   register windows to the stack."
85 *
86 * This implementation uses the window overflow trap handler to perform the
87 * actual window flush.
88 *
89 * On entry:
90 * %l0: psr
91 * %l1: pc
92 * %l2: npc
93 */
94SECTION_FUNC(TEXT, __sparc_trap_flush_windows)
95	/* push a few registers which are needed later to the stack */
96	sub	%sp, 0x10, %sp
97	std	%l0, [%sp + 0x40 + 0x00]
98	st	%l2, [%sp + 0x40 + 0x08]
99	st	%g2, [%sp + 0x40 + 0x0c]
100
101	restore
102	/* In window where we trapped from. This window will not be flushed. */
103
104	/* Set highest processor interrupt level and enable traps. */
105	rd	%psr, %g2
106	or	%g2, PSR_PIL, %g2
107	wr	%g2, PSR_ET, %psr
108	nop
109	nop
110
111	/* Execute "save" NWINDOWS-1 times. */
112	set     CONFIG_SPARC_NWIN-2, %g2
1131:
114	save
115	cmp	%g2, %g0
116	bne	1b
117	 sub	%g2, 1, %g2
118
119	/* Execute "restore" NWINDOWS-1 times. */
120	set     CONFIG_SPARC_NWIN-2, %g2
1212:
122	restore
123	cmp	%g2, %g0
124	bne	2b
125	 sub	%g2, 1, %g2
126
127	save
128
129	/* pop registers from stack which are used for the trap return */
130	ldd	[%sp + 0x40 + 0x00], %l0
131	ld	[%sp + 0x40 + 0x08], %l2
132	ld	[%sp + 0x40 + 0x0c], %g2
133	add	%sp, 0x10, %sp
134
135	/* Restore %psr as it was on trap entry. */
136	wr	%l0, %psr
137	nop
138	nop
139	nop
140
141	jmp	%l2
142	 rett	%l2 + 4
143