1/* SPDX-License-Identifier: GPL-2.0
2 *
3 * arch/sh/kernel/cpu/sh2a/entry.S
4 *
5 * The SH-2A exception entry
6 *
7 * Copyright (C) 2008 Yoshinori Sato
8 * Based on arch/sh/kernel/cpu/sh2/entry.S
9 */
10
11#include <linux/linkage.h>
12#include <asm/asm-offsets.h>
13#include <asm/thread_info.h>
14#include <cpu/mmu_context.h>
15#include <asm/unistd.h>
16#include <asm/errno.h>
17#include <asm/page.h>
18
19/* Offsets to the stack */
20OFF_R0  =  0		/* Return value. New ABI also arg4 */
21OFF_R1  =  4     	/* New ABI: arg5 */
22OFF_R2  =  8     	/* New ABI: arg6 */
23OFF_R3  =  12     	/* New ABI: syscall_nr */
24OFF_R4  =  16     	/* New ABI: arg0 */
25OFF_R5  =  20     	/* New ABI: arg1 */
26OFF_R6  =  24     	/* New ABI: arg2 */
27OFF_R7  =  28     	/* New ABI: arg3 */
28OFF_SP	=  (15*4)
29OFF_PC  =  (16*4)
30OFF_SR	=  (16*4+2*4)
31OFF_TRA	=  (16*4+6*4)
32
33#include <asm/entry-macros.S>
34
35ENTRY(exception_handler)
36	! stack
37	! r0 <- point sp
38	! r1
39	! pc
40	! sr
41	! r0 = temporary
42	! r1 = vector (pseudo EXPEVT / INTEVT / TRA)
43	mov.l	r2,@-sp
44	cli
45	mov.l	$cpu_mode,r2
46	bld.b	#6,@(0,r2)	!previus SR.MD
47	bst.b	#6,@(4*4,r15)	!set cpu mode to SR.MD
48	bt	1f
49	! switch to kernel mode
50	bset.b	#6,@(0,r2)	!set SR.MD
51	mov.l	$current_thread_info,r2
52	mov.l	@r2,r2
53	mov	#(THREAD_SIZE >> 8),r0
54	shll8	r0
55	add	r2,r0		! r0 = kernel stack tail
56	mov	r15,r2		! r2 = user stack top
57	mov	r0,r15		! switch kernel stack
58	mov.l	r1,@-r15	! TRA
59	sts.l	macl, @-r15
60	sts.l	mach, @-r15
61	stc.l	gbr, @-r15
62	mov.l	@(4*4,r2),r0
63	mov.l	r0,@-r15	! original SR
64	sts.l	pr,@-r15
65	mov.l	@(3*4,r2),r0
66	mov.l	r0,@-r15	! original PC
67	mov	r2,r0
68	add	#(3+2)*4,r0	! rewind r0 - r3 + exception frame
69	lds	r0,pr		! pr = original SP
70	movmu.l	r3,@-r15	! save regs
71	mov	r2,r8		! r8 =  previus stack top
72	mov	r1,r9		! r9 = interrupt vector
73	! restore previous stack
74	mov.l	@r8+,r2
75	mov.l	@r8+,r0
76	mov.l	@r8+,r1
77	bra	2f
78	 movml.l r2,@-r15
791:
80	! in kernel exception
81	mov	r15,r2
82	add	#-((OFF_TRA + 4) - OFF_PC) + 5*4,r15
83	movmu.l	r3,@-r15
84	mov	r2,r8		! r8 = previous stack top
85	mov	r1,r9		! r9 = interrupt vector
86	! restore exception frame & regs
87	mov.l	@r8+,r2		! old R2
88	mov.l	@r8+,r0		! old R0
89	mov.l	@r8+,r1		! old R1
90	mov.l	@r8+,r10	! old PC
91	mov.l	@r8+,r11	! old SR
92	movml.l	r2,@-r15
93	mov.l	r10,@(OFF_PC,r15)
94	mov.l	r11,@(OFF_SR,r15)
95	mov.l	r8,@(OFF_SP,r15)	! save old sp
96	mov	r15,r8
97	add	#OFF_TRA + 4,r8
98	mov.l	r9,@-r8
99	sts.l	macl,@-r8
100	sts.l	mach,@-r8
101	stc.l	gbr,@-r8
102	add	#-4,r8
103	sts.l	pr,@-r8
1042:
105	! dispatch exception / interrupt
106	mov	#64,r8
107	cmp/hs	r8,r9
108	bt	interrupt_entry	! vec >= 64 is interrupt
109	mov	#31,r8
110	cmp/hs	r8,r9
111	bt	trap_entry	! 64 > vec >= 31  is trap
112
113	mov.l	4f,r8
114	mov	r9,r4
115	shll2	r9
116	add	r9,r8
117	mov.l	@r8,r8		! exception handler address
118	tst	r8,r8
119	bf	3f
120	mov.l	8f,r8		! unhandled exception
1213:
122	mov.l	5f,r10
123	jmp	@r8
124	 lds	r10,pr
125
126interrupt_entry:
127	mov	r9,r4
128	mov	r15,r5
129	mov.l	7f,r8
130	mov.l	6f,r9
131	jmp	@r8
132	 lds	r9,pr
133
134	.align	2
1354:	.long	exception_handling_table
1365:	.long	ret_from_exception
1376:	.long	ret_from_irq
1387:	.long	do_IRQ
1398:	.long	exception_error
140
141trap_entry:
142	mov	#0x30,r8
143	cmp/ge	r8,r9		! vector 0x1f-0x2f is systemcall
144	bt	1f
145	mov     #0x1f,r9	! convert to unified SH2/3/4 trap number
1461:
147	shll2	r9			! TRA
148	bra	system_call	! jump common systemcall entry
149	 mov	r9,r8
150
151#if defined(CONFIG_SH_STANDARD_BIOS)
152	/* Unwind the stack and jmp to the debug entry */
153ENTRY(sh_bios_handler)
154	mov	r15,r0
155	add	#(22-4)*4-4,r0
156	ldc.l	@r0+,gbr
157	lds.l	@r0+,mach
158	lds.l	@r0+,macl
159	mov	r15,r0
160	mov.l	@(OFF_SP,r0),r1
161	mov.l	@(OFF_SR,r2),r3
162	mov.l	r3,@-r1
163	mov.l	@(OFF_SP,r2),r3
164	mov.l	r3,@-r1
165	mov	r15,r0
166	add	#(22-4)*4-8,r0
167	mov.l	1f,r2
168	mov.l	@r2,r2
169	stc	sr,r3
170	mov.l	r2,@r0
171	mov.l	r3,@(4,r0)
172	mov.l	r1,@(8,r0)
173	movml.l	@r15+,r14
174	add	#8,r15
175	lds.l	@r15+, pr
176	mov.l	@r15+,r15
177	rte
178	 nop
179	.align	2
1801:	.long	gdb_vbr_vector
181#endif /* CONFIG_SH_STANDARD_BIOS */
182
183ENTRY(address_error_trap_handler)
184	mov	r15,r4				! regs
185	mov.l	@(OFF_PC,r15),r6		! pc
186	mov.l	1f,r0
187	jmp	@r0
188	 mov	#0,r5				! writeaccess is unknown
189
190	.align	2
1911:	.long	do_address_error
192
193restore_all:
194	stc	sr,r0
195	or	#0xf0,r0
196	ldc	r0,sr				! all interrupt block (same BL = 1)
197	! restore special register
198	! overlap exception frame
199	mov	r15,r0
200	add	#17*4,r0
201	lds.l	@r0+,pr
202	add	#4,r0
203	ldc.l	@r0+,gbr
204	lds.l	@r0+,mach
205	lds.l	@r0+,macl
206	mov	r15,r0
207	mov.l	$cpu_mode,r2
208	bld.b	#6,@(OFF_SR,r15)
209	bst.b	#6,@(0,r2)			! save CPU mode
210	mov.l	@(OFF_SR,r0),r1
211	shll2	r1
212	shlr2	r1				! clear MD bit
213	mov.l	@(OFF_SP,r0),r2
214	add	#-8,r2
215	mov.l	r2,@(OFF_SP,r0)			! point exception frame top
216	mov.l	r1,@(4,r2)			! set sr
217	mov.l	@(OFF_PC,r0),r1
218	mov.l	r1,@r2				! set pc
219	get_current_thread_info r0, r1
220	mov.l	$current_thread_info,r1
221	mov.l	r0,@r1
222	movml.l	@r15+,r14
223	mov.l	@r15,r15
224	rte
225	 nop
226
227	.align 2
228$current_thread_info:
229	.long	__current_thread_info
230$cpu_mode:
231	.long	__cpu_mode
232
233! common exception handler
234#include "../../entry-common.S"
235
236	.data
237! cpu operation mode
238! bit30 = MD (compatible SH3/4)
239__cpu_mode:
240	.long	0x40000000
241
242	.section	.bss
243__current_thread_info:
244	.long	0
245
246ENTRY(exception_handling_table)
247	.space	4*32
248