1/*
2 * arch/sh/kernel/cpu/sh2a/entry.S
3 *
4 * The SH-2A exception entry
5 *
6 * Copyright (C) 2008 Yoshinori Sato
7 * Based on arch/sh/kernel/cpu/sh2/entry.S
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 <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	! stack
40	! r0 <- point sp
41	! r1
42	! pc
43	! sr
44	! r0 = temporary
45	! r1 = vector (pseudo EXPEVT / INTEVT / TRA)
46	mov.l	r2,@-sp
47	cli
48	mov.l	$cpu_mode,r2
49	bld.b	#6,@(0,r2)	!previus SR.MD
50	bst.b	#6,@(4*4,r15)	!set cpu mode to SR.MD
51	bt	1f
52	! switch to kernel mode
53	bset.b	#6,@(0,r2)	!set SR.MD
54	mov.l	$current_thread_info,r2
55	mov.l	@r2,r2
56	mov	#(THREAD_SIZE >> 8),r0
57	shll8	r0
58	add	r2,r0		! r0 = kernel stack tail
59	mov	r15,r2		! r2 = user stack top
60	mov	r0,r15		! switch kernel stack
61	mov.l	r1,@-r15	! TRA
62	sts.l	macl, @-r15
63	sts.l	mach, @-r15
64	stc.l	gbr, @-r15
65	mov.l	@(4*4,r2),r0
66	mov.l	r0,@-r15	! original SR
67	sts.l	pr,@-r15
68	mov.l	@(3*4,r2),r0
69	mov.l	r0,@-r15	! original PC
70	mov	r2,r0
71	add	#(3+2)*4,r0	! rewind r0 - r3 + exception frame
72	lds	r0,pr		! pr = original SP
73	movmu.l	r3,@-r15	! save regs
74	mov	r2,r8		! r8 =  previus stack top
75	mov	r1,r9		! r9 = interrupt vector
76	! restore previous stack
77	mov.l	@r8+,r2
78	mov.l	@r8+,r0
79	mov.l	@r8+,r1
80	bra	2f
81	 movml.l r2,@-r15
821:
83	! in kernel exception
84	mov	r15,r2
85	add	#-((OFF_TRA + 4) - OFF_PC) + 5*4,r15
86	movmu.l	r3,@-r15
87	mov	r2,r8		! r8 = previous stack top
88	mov	r1,r9		! r9 = interrupt vector
89	! restore exception frame & regs
90	mov.l	@r8+,r2		! old R2
91	mov.l	@r8+,r0		! old R0
92	mov.l	@r8+,r1		! old R1
93	mov.l	@r8+,r10	! old PC
94	mov.l	@r8+,r11	! old SR
95	movml.l	r2,@-r15
96	mov.l	r10,@(OFF_PC,r15)
97	mov.l	r11,@(OFF_SR,r15)
98	mov.l	r8,@(OFF_SP,r15)	! save old sp
99	mov	r15,r8
100	add	#OFF_TRA + 4,r8
101	mov.l	r9,@-r8
102	sts.l	macl,@-r8
103	sts.l	mach,@-r8
104	stc.l	gbr,@-r8
105	add	#-4,r8
106	sts.l	pr,@-r8
1072:
108	! dispatch exception / interrupt
109	mov	#64,r8
110	cmp/hs	r8,r9
111	bt	interrupt_entry	! vec >= 64 is interrupt
112	mov	#32,r8
113	cmp/hs	r8,r9
114	bt	trap_entry	! 64 > vec >= 32  is trap
115
116	mov.l	4f,r8
117	mov	r9,r4
118	shll2	r9
119	add	r9,r8
120	mov.l	@r8,r8		! exception handler address
121	tst	r8,r8
122	bf	3f
123	mov.l	8f,r8		! unhandled exception
1243:
125	mov.l	5f,r10
126	jmp	@r8
127	 lds	r10,pr
128
129interrupt_entry:
130	mov	r9,r4
131	mov	r15,r5
132	mov.l	7f,r8
133	mov.l	6f,r9
134	jmp	@r8
135	 lds	r9,pr
136
137	.align	2
1384:	.long	exception_handling_table
1395:	.long	ret_from_exception
1406:	.long	ret_from_irq
1417:	.long	do_IRQ
1428:	.long	exception_error
143
144trap_entry:
145	mov	#0x30,r8
146	cmp/ge	r8,r9		! vector 0x20-0x2f is systemcall
147	bt	1f
148	add	#-0x10,r9	! convert SH2 to SH3/4 ABI
1491:
150	shll2	r9			! TRA
151	bra	system_call	! jump common systemcall entry
152	 mov	r9,r8
153
154#if defined(CONFIG_SH_STANDARD_BIOS)
155	/* Unwind the stack and jmp to the debug entry */
156ENTRY(sh_bios_handler)
157	mov	r15,r0
158	add	#(22-4)*4-4,r0
159	ldc.l	@r0+,gbr
160	lds.l	@r0+,mach
161	lds.l	@r0+,macl
162	mov	r15,r0
163	mov.l	@(OFF_SP,r0),r1
164	mov.l	@(OFF_SR,r2),r3
165	mov.l	r3,@-r1
166	mov.l	@(OFF_SP,r2),r3
167	mov.l	r3,@-r1
168	mov	r15,r0
169	add	#(22-4)*4-8,r0
170	mov.l	1f,r2
171	mov.l	@r2,r2
172	stc	sr,r3
173	mov.l	r2,@r0
174	mov.l	r3,@(4,r0)
175	mov.l	r1,@(8,r0)
176	movml.l	@r15+,r14
177	add	#8,r15
178	lds.l	@r15+, pr
179	mov.l	@r15+,r15
180	rte
181	 nop
182	.align	2
1831:	.long	gdb_vbr_vector
184#endif /* CONFIG_SH_STANDARD_BIOS */
185
186ENTRY(address_error_trap_handler)
187	mov	r15,r4				! regs
188	mov.l	@(OFF_PC,r15),r6		! pc
189	mov.l	1f,r0
190	jmp	@r0
191	 mov	#0,r5				! writeaccess is unknown
192
193	.align	2
1941:	.long	do_address_error
195
196restore_all:
197	stc	sr,r0
198	or	#0xf0,r0
199	ldc	r0,sr				! all interrupt block (same BL = 1)
200	! restore special register
201	! overlap exception frame
202	mov	r15,r0
203	add	#17*4,r0
204	lds.l	@r0+,pr
205	add	#4,r0
206	ldc.l	@r0+,gbr
207	lds.l	@r0+,mach
208	lds.l	@r0+,macl
209	mov	r15,r0
210	mov.l	$cpu_mode,r2
211	bld.b	#6,@(OFF_SR,r15)
212	bst.b	#6,@(0,r2)			! save CPU mode
213	mov.l	@(OFF_SR,r0),r1
214	shll2	r1
215	shlr2	r1				! clear MD bit
216	mov.l	@(OFF_SP,r0),r2
217	add	#-8,r2
218	mov.l	r2,@(OFF_SP,r0)			! point exception frame top
219	mov.l	r1,@(4,r2)			! set sr
220	mov.l	@(OFF_PC,r0),r1
221	mov.l	r1,@r2				! set pc
222	get_current_thread_info r0, r1
223	mov.l	$current_thread_info,r1
224	mov.l	r0,@r1
225	movml.l	@r15+,r14
226	mov.l	@r15,r15
227	rte
228	 nop
229
230	.align 2
231$current_thread_info:
232	.long	__current_thread_info
233$cpu_mode:
234	.long	__cpu_mode
235
236! common exception handler
237#include "../../entry-common.S"
238
239	.data
240! cpu operation mode
241! bit30 = MD (compatible SH3/4)
242__cpu_mode:
243	.long	0x40000000
244
245	.section	.bss
246__current_thread_info:
247	.long	0
248
249ENTRY(exception_handling_table)
250	.space	4*32
251