xref: /openbmc/linux/arch/sh/kernel/cpu/sh2/entry.S (revision a1e58bbd)
1/*
2 * arch/sh/kernel/cpu/sh2/entry.S
3 *
4 * The SH-2 exception entry
5 *
6 * Copyright (C) 2005,2006 Yoshinori Sato
7 * Copyright (C) 2005  AXE,Inc.
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License.  See the file "COPYING" in the main directory of this archive
11 * for more details.
12 */
13
14#include <linux/linkage.h>
15#include <asm/asm-offsets.h>
16#include <asm/thread_info.h>
17#include <asm/cpu/mmu_context.h>
18#include <asm/unistd.h>
19#include <asm/errno.h>
20#include <asm/page.h>
21
22/* Offsets to the stack */
23OFF_R0  =  0		/* Return value. New ABI also arg4 */
24OFF_R1  =  4     	/* New ABI: arg5 */
25OFF_R2  =  8     	/* New ABI: arg6 */
26OFF_R3  =  12     	/* New ABI: syscall_nr */
27OFF_R4  =  16     	/* New ABI: arg0 */
28OFF_R5  =  20     	/* New ABI: arg1 */
29OFF_R6  =  24     	/* New ABI: arg2 */
30OFF_R7  =  28     	/* New ABI: arg3 */
31OFF_SP	=  (15*4)
32OFF_PC  =  (16*4)
33OFF_SR	=  (16*4+2*4)
34OFF_TRA	=  (16*4+6*4)
35
36#include <asm/entry-macros.S>
37
38ENTRY(exception_handler)
39	! already saved r0/r1
40	mov.l	r2,@-sp
41	mov.l	r3,@-sp
42	mov	r0,r1
43	cli
44	mov.l	$cpu_mode,r2
45	mov.l	@r2,r0
46	mov.l	@(5*4,r15),r3	! previous SR
47	shll2	r3		! set "S" flag
48	rotl	r0		! T <- "S" flag
49	rotl	r0		! "S" flag is LSB
50	rotcr	r3		! T -> r3:b30
51	shlr	r3
52	shlr	r0
53	bt/s	1f
54	 mov.l	r3,@(5*4,r15)	! copy cpu mode to SR
55	! switch to kernel mode
56	mov	#1,r0
57	rotr	r0
58	rotr	r0
59	mov.l	r0,@r2		! enter kernel mode
60	mov.l	$current_thread_info,r2
61	mov.l	@r2,r2
62	mov	#0x20,r0
63	shll8	r0
64	add	r2,r0
65	mov	r15,r2		! r2 = user stack top
66	mov	r0,r15		! switch kernel stack
67	add	#-4,r15		! dummy
68	mov.l	r1,@-r15	! TRA
69	sts.l	macl, @-r15
70	sts.l	mach, @-r15
71	stc.l	gbr, @-r15
72	mov.l	@(4*4,r2),r0
73	mov.l	@(5*4,r2),r1
74	mov.l	r1,@-r15	! original SR
75	sts.l	pr,@-r15
76	mov.l	r0,@-r15	! original PC
77	mov	r2,r3
78	add	#(4+2)*4,r3	! rewind r0 - r3 + exception frame
79	mov.l	r3,@-r15	! original SP
80	mov.l	r14,@-r15
81	mov.l	r13,@-r15
82	mov.l	r12,@-r15
83	mov.l	r11,@-r15
84	mov.l	r10,@-r15
85	mov.l	r9,@-r15
86	mov.l	r8,@-r15
87	mov.l	r7,@-r15
88	mov.l	r6,@-r15
89	mov.l	r5,@-r15
90	mov.l	r4,@-r15
91	mov	r2,r8		! copy user -> kernel stack
92	mov.l	@r8+,r3
93	mov.l	r3,@-r15
94	mov.l	@r8+,r2
95	mov.l	r2,@-r15
96	mov.l	@r8+,r1
97	mov.l	r1,@-r15
98	mov.l	@r8+,r0
99	bra	2f
100	 mov.l	r0,@-r15
1011:
102	! in kernel exception
103	mov	#(22-4-4-1)*4+4,r0
104	mov	r15,r2
105	sub	r0,r15
106	mov.l	@r2+,r0		! old R3
107	mov.l	r0,@-r15
108	mov.l	@r2+,r0		! old R2
109	mov.l	r0,@-r15
110	mov.l	@r2+,r0		! old R1
111	mov.l	r0,@-r15
112	mov.l	@r2+,r0		! old R0
113	mov.l	r0,@-r15
114	mov.l	@r2+,r3		! old PC
115	mov.l	@r2+,r0		! old SR
116	add	#-4,r2		! exception frame stub (sr)
117	mov.l	r1,@-r2		! TRA
118	sts.l	macl, @-r2
119	sts.l	mach, @-r2
120	stc.l	gbr, @-r2
121	mov.l	r0,@-r2		! save old SR
122	sts.l	pr,@-r2
123	mov.l	r3,@-r2		! save old PC
124	mov	r2,r0
125	add	#8*4,r0
126	mov.l	r0,@-r2		! save old SP
127	mov.l	r14,@-r2
128	mov.l	r13,@-r2
129	mov.l	r12,@-r2
130	mov.l	r11,@-r2
131	mov.l	r10,@-r2
132	mov.l	r9,@-r2
133	mov.l	r8,@-r2
134	mov.l	r7,@-r2
135	mov.l	r6,@-r2
136	mov.l	r5,@-r2
137	mov.l	r4,@-r2
138	mov.l	@(OFF_R0,r15),r0
139	mov.l	@(OFF_R1,r15),r1
140	mov.l	@(OFF_R2,r15),r2
141	mov.l	@(OFF_R3,r15),r3
1422:
143	mov	#OFF_TRA,r8
144	add	r15,r8
145	mov.l	@r8,r9
146	mov	#64,r8
147	cmp/hs	r8,r9
148	bt	interrupt_entry	! vec >= 64 is interrupt
149	mov	#32,r8
150	cmp/hs	r8,r9
151	bt	trap_entry	! 64 > vec >= 32  is trap
152
153#if defined(CONFIG_SH_FPU)
154	mov     #13,r8
155	cmp/eq  r8,r9
156	bt      10f             ! fpu
157	nop
158#endif
159
160	mov.l	4f,r8
161	mov	r9,r4
162	shll2	r9
163	add	r9,r8
164	mov.l	@r8,r8
165	mov	#0,r9
166	cmp/eq	r9,r8
167	bf	3f
168	mov.l	8f,r8		! unhandled exception
169#if defined(CONFIG_SH_FPU)
17010:
171	mov.l	9f, r8		! unhandled exception
172#endif
1733:
174	mov.l	5f,r10
175	jmp	@r8
176	 lds	r10,pr
177
178interrupt_entry:
179	mov	r9,r4
180	mov	r15,r5
181	mov.l	6f,r9
182	mov.l	7f,r8
183	jmp	@r8
184	 lds	r9,pr
185
186	.align	2
1874:	.long	exception_handling_table
1885:	.long	ret_from_exception
1896:	.long	ret_from_irq
1907:	.long	do_IRQ
1918:	.long	do_exception_error
192#ifdef CONFIG_SH_FPU
1939:	.long	fpu_error_trap_handler
194#endif
195
196trap_entry:
197	mov	#0x30,r8
198	cmp/ge	r8,r9		! vector 0x20-0x2f is systemcall
199	bt	1f
200	add	#-0x10,r9	! convert SH2 to SH3/4 ABI
2011:
202	shll2	r9			! TRA
203	mov	#OFF_TRA,r8
204	add	r15,r8
205	mov.l	r9,@r8
206	mov	r9,r8
207#ifdef CONFIG_TRACE_IRQFLAGS
208	mov.l	2f, r9
209	jsr	@r9
210	 nop
211#endif
212	sti
213	bra	system_call
214	 nop
215
216	.align	2
217#ifdef CONFIG_TRACE_IRQFLAGS
2182:	.long	trace_hardirqs_on
219#endif
220
221#if defined(CONFIG_SH_STANDARD_BIOS)
222	/* Unwind the stack and jmp to the debug entry */
223ENTRY(sh_bios_handler)
224	mov	r15,r0
225	add	#(22-4)*4-4,r0
226	ldc.l	@r0+,gbr
227	lds.l	@r0+,mach
228	lds.l	@r0+,macl
229	mov	r15,r0
230	mov.l	@(OFF_SP,r0),r1
231	mov	#OFF_SR,r2
232	mov.l	@(r0,r2),r3
233	mov.l	r3,@-r1
234	mov	#OFF_SP,r2
235	mov.l	@(r0,r2),r3
236	mov.l	r3,@-r1
237	mov	r15,r0
238	add	#(22-4)*4-8,r0
239	mov.l	1f,r2
240	mov.l	@r2,r2
241	stc	sr,r3
242	mov.l	r2,@r0
243	mov.l	r3,@r0
244	mov.l	r1,@(8,r0)
245	mov.l	@r15+, r0
246	mov.l	@r15+, r1
247	mov.l	@r15+, r2
248	mov.l	@r15+, r3
249	mov.l	@r15+, r4
250	mov.l	@r15+, r5
251	mov.l	@r15+, r6
252	mov.l	@r15+, r7
253	mov.l	@r15+, r8
254	mov.l	@r15+, r9
255	mov.l	@r15+, r10
256	mov.l	@r15+, r11
257	mov.l	@r15+, r12
258	mov.l	@r15+, r13
259	mov.l	@r15+, r14
260	add	#8,r15
261	lds.l	@r15+, pr
262	rte
263	 mov.l	@r15+,r15
264	.align	2
2651:	.long	gdb_vbr_vector
266#endif /* CONFIG_SH_STANDARD_BIOS */
267
268ENTRY(address_error_trap_handler)
269	mov	r15,r4				! regs
270	mov	#OFF_PC,r0
271	mov.l	@(r0,r15),r6			! pc
272	mov.l	1f,r0
273	jmp	@r0
274	 mov	#0,r5				! writeaccess is unknown
275	.align	2
276
2771:	.long	do_address_error
278
279restore_all:
280	cli
281#ifdef CONFIG_TRACE_IRQFLAGS
282	mov.l	1f, r0
283	jsr	@r0
284	 nop
285#endif
286	mov	r15,r0
287	mov.l	$cpu_mode,r2
288	mov	#OFF_SR,r3
289	mov.l	@(r0,r3),r1
290	mov.l	r1,@r2
291	shll2	r1				! clear MD bit
292	shlr2	r1
293	mov.l	@(OFF_SP,r0),r2
294	add	#-8,r2
295	mov.l	r2,@(OFF_SP,r0)			! point exception frame top
296	mov.l	r1,@(4,r2)			! set sr
297	mov	#OFF_PC,r3
298	mov.l	@(r0,r3),r1
299	mov.l	r1,@r2				! set pc
300	add	#4*16+4,r0
301	lds.l	@r0+,pr
302	add	#4,r0				! skip sr
303	ldc.l	@r0+,gbr
304	lds.l	@r0+,mach
305	lds.l	@r0+,macl
306	get_current_thread_info r0, r1
307	mov.l	$current_thread_info,r1
308	mov.l	r0,@r1
309	mov.l	@r15+,r0
310	mov.l	@r15+,r1
311	mov.l	@r15+,r2
312	mov.l	@r15+,r3
313	mov.l	@r15+,r4
314	mov.l	@r15+,r5
315	mov.l	@r15+,r6
316	mov.l	@r15+,r7
317	mov.l	@r15+,r8
318	mov.l	@r15+,r9
319	mov.l	@r15+,r10
320	mov.l	@r15+,r11
321	mov.l	@r15+,r12
322	mov.l	@r15+,r13
323	mov.l	@r15+,r14
324	mov.l	@r15,r15
325	rte
326	 nop
327
328	.align 2
329#ifdef CONFIG_TRACE_IRQFLAGS
3301:     .long   trace_hardirqs_off
331#endif
332$current_thread_info:
333	.long	__current_thread_info
334$cpu_mode:
335	.long	__cpu_mode
336
337! common exception handler
338#include "../../entry-common.S"
339
340	.data
341! cpu operation mode
342! bit30 = MD (compatible SH3/4)
343__cpu_mode:
344	.long	0x40000000
345
346	.section	.bss
347__current_thread_info:
348	.long	0
349
350ENTRY(exception_handling_table)
351	.space	4*32
352