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 <zephyr/toolchain.h>
14#include <zephyr/linker/sections.h>
15#include <zephyr/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 * On entry:
87 * %l0: psr
88 * %l1: pc
89 * %l2: npc
90 */
91SECTION_FUNC(TEXT, __sparc_trap_flush_windows)
92	/* Save global registers used by the routine */
93	mov	%g3, %l3
94	mov	%g4, %l4
95	mov	%g5, %l5
96	mov	%g1, %l6
97	mov	%g2, %l7
98
99	/* Uses g3=psr, g4=1, g2=wim, g1,g5=scratch */
100	mov	%l0, %g3
101	set	1, %g4
102	rd	%wim, %g2
103
104	/*
105	 * We can always restore the previous window. Check if we can restore
106	 * the window after that.
107	 */
108	and	%l0, PSR_CWP, %g1
109	add	%g1, 2, %g1
110	ba	.LcheckNextWindow
111	 restore
112
113	/* Flush window to stack */
114.LflushWindow:
115	std	%l0, [%sp + 0x00]
116	std	%l2, [%sp + 0x08]
117	std	%l4, [%sp + 0x10]
118	std	%l6, [%sp + 0x18]
119	std	%i0, [%sp + 0x20]
120	std	%i2, [%sp + 0x28]
121	std	%i4, [%sp + 0x30]
122	std	%i6, [%sp + 0x38]
123
124	/*
125	 * Check if next window is invalid by comparing
126	 * (1 << ((cwp + 1) % NWIN)) with WIM
127	 */
128.LcheckNextWindow:
129	set	CONFIG_SPARC_NWIN, %g5
130	cmp	%g1, %g5
131	bge,a	.Lnowrap
132	 sub	%g1, %g5, %g1
133.Lnowrap:
134	sll	%g4, %g1, %g5
135	cmp	%g5, %g2
136	be	.LflushWindowDone
137	 inc	%g1
138
139	/* We need to flush the next window */
140	ba	.LflushWindow
141	 restore
142
143	/*
144	 * All used windows have been flushed. Set WIM to cause trap for CWP+2.
145	 * When we return from this trap it will be CWP+1 that will trap, that
146	 * is, the next restore or rett.
147	 */
148.LflushWindowDone:
149	/* We can not restore %psr from %l0 because we may be in any window. */
150	wr	%g3, %psr
151	and	%g3, PSR_CWP, %g1
152	add	%g1, 2, %g1
153	set	CONFIG_SPARC_NWIN, %g5
154	/* We are now back in the trap window. */
155	cmp	%g1, %g5
156	bge,a	.Lnowrap2
157	 sub	%g1, %g5, %g1
158.Lnowrap2:
159	sll	%g4, %g1, %g1
160	wr	%g1, %wim
161	mov	%l3, %g3
162	mov	%l4, %g4
163	mov	%l5, %g5
164	mov	%l6, %g1
165	mov	%l7, %g2
166	jmp	%l2
167	 rett	%l2 + 4
168