1/* -*- mode: asm -*-
2 *
3 *  linux/arch/h8300/platform/h8s/entry.S
4 *
5 *  Yoshinori Sato <ysato@users.sourceforge.jp>
6 *
7 *	fairly heavy changes to fix syscall args and signal processing
8 *	by David McCullough <davidm@snapgear.com>
9 */
10
11/*
12 *  entry.S
13 *  include exception/interrupt gateway
14 *          system call entry
15 */
16
17#include <linux/sys.h>
18#include <asm/unistd.h>
19#include <asm/setup.h>
20#include <asm/segment.h>
21#include <asm/linkage.h>
22#include <asm/asm-offsets.h>
23#include <asm/thread_info.h>
24#include <asm/errno.h>
25
26	.h8300s
27
28/* CPU context save/restore macros. */
29
30	.macro	SAVE_ALL
31	mov.l	er0,@-sp
32
33	stc	ccr,r0l				/* check kernel mode */
34	btst	#4,r0l
35	bne	5f
36
37	/* user mode */
38	mov.l	sp,@SYMBOL_NAME(sw_usp)
39	mov.l	@sp,er0				/* restore saved er0 */
40	orc	#0x10,ccr			/* switch kernel stack */
41	mov.l	@SYMBOL_NAME(sw_ksp),sp
42	sub.l	#(LRET-LORIG),sp		/* allocate LORIG - LRET */
43	stm.l	er0-er3,@-sp
44	mov.l	@SYMBOL_NAME(sw_usp),er0
45	mov.l	@(10:16,er0),er1		/* copy the RET addr */
46	mov.l	er1,@(LRET-LER3:16,sp)
47	mov.w	@(8:16,er0),r1
48	mov.w	r1,@(LEXR-LER3:16,sp)		/* copy EXR */
49
50	mov.w	e1,r1				/* e1 highbyte = ccr */
51	and	#0xef,r1h			/* mask mode? flag */
52	sub.w	r0,r0
53	mov.b	r1h,r0l
54	mov.w	r0,@(LCCR-LER3:16,sp)		/* copy ccr */
55	mov.l	@(LORIG-LER3:16,sp),er0
56	mov.l	er0,@(LER0-LER3:16,sp)		/* copy ER0 */
57	bra	6f
585:
59	/* kernel mode */
60	mov.l	@sp,er0				/* restore saved er0 */
61	subs	#2,sp				/* set dummy ccr */
62	stm.l	er0-er3,@-sp
63	mov.w	@(LRET-LER3:16,sp),r1		/* copy old ccr */
64	mov.b	r1h,r1l
65	mov.b	#0,r1h
66	mov.w	r1,@(LCCR-LER3:16,sp)
676:
68	mov.l	er6,@-sp			/* syscall arg #6 */
69	mov.l	er5,@-sp			/* syscall arg #5 */
70	mov.l	er4,@-sp			/* syscall arg #4 */
71	.endm
72
73	.macro	RESTORE_ALL
74	mov.l	@sp+,er4
75	mov.l	@sp+,er5
76	mov.l	@sp+,er6
77	ldm.l	@sp+,er2-er3
78	mov.w	@(LCCR-LER1:16,sp),r0		/* check kernel mode */
79	btst	#4,r0l
80	bne	7f
81
82	orc	#0x80,ccr
83	mov.l	@SYMBOL_NAME(sw_usp),er0
84	mov.l	@(LER0-LER1:16,sp),er1		/* restore ER0 */
85	mov.l	er1,@er0
86	mov.w	@(LEXR-LER1:16,sp),r1		/* restore EXR */
87	mov.b	r1l,r1h
88	mov.w	r1,@(8:16,er0)
89	mov.w	@(LCCR-LER1:16,sp),r1		/* restore the RET addr */
90	mov.b	r1l,r1h
91	mov.b	@(LRET+1-LER1:16,sp),r1l
92	mov.w	r1,e1
93	mov.w	@(LRET+2-LER1:16,sp),r1
94	mov.l	er1,@(10:16,er0)
95
96	mov.l	@sp+,er1
97	add.l	#(LRET-LER1),sp			/* remove LORIG - LRET */
98	mov.l	sp,@SYMBOL_NAME(sw_ksp)
99	andc	#0xef,ccr			/* switch to user mode */
100	mov.l	er0,sp
101	bra	8f
1027:
103	mov.l	@sp+,er1
104	adds	#4,sp
105	adds	#2,sp
1068:
107	mov.l	@sp+,er0
108	adds	#4,sp				/* remove the sw created LVEC */
109	rte
110	.endm
111
112.globl SYMBOL_NAME(system_call)
113.globl SYMBOL_NAME(ret_from_exception)
114.globl SYMBOL_NAME(ret_from_fork)
115.globl SYMBOL_NAME(ret_from_interrupt)
116.globl SYMBOL_NAME(interrupt_redirect_table)
117.globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp)
118.globl SYMBOL_NAME(resume)
119.globl SYMBOL_NAME(trace_break)
120.globl SYMBOL_NAME(interrupt_entry)
121
122INTERRUPTS = 128
123#if defined(CONFIG_ROMKERNEL)
124	.section .int_redirect,"ax"
125SYMBOL_NAME_LABEL(interrupt_redirect_table)
126	.rept	7
127	.long	0
128	.endr
129	jsr	@SYMBOL_NAME(interrupt_entry)	/* NMI */
130	jmp	@SYMBOL_NAME(system_call)	/* TRAPA #0 (System call) */
131	.long	0
132	.long	0
133	jmp	@SYMBOL_NAME(trace_break)	/* TRAPA #3 (breakpoint) */
134	.rept	INTERRUPTS-12
135	jsr	@SYMBOL_NAME(interrupt_entry)
136	.endr
137#endif
138#if defined(CONFIG_RAMKERNEL)
139.globl SYMBOL_NAME(interrupt_redirect_table)
140	.section .bss
141SYMBOL_NAME_LABEL(interrupt_redirect_table)
142	.space	4
143#endif
144
145	.section .text
146	.align	2
147SYMBOL_NAME_LABEL(interrupt_entry)
148	SAVE_ALL
149	mov.w	@(LCCR,sp),r0
150	btst	#4,r0l
151	bne	1f
152	mov.l	@SYMBOL_NAME(sw_usp),er0
153	mov.l	@(4:16,er0),er0
154	bra	2f
1551:
156	mov.l	@(LVEC:16,sp),er0
1572:
158#if defined(CONFIG_ROMKERNEL)
159	sub.l	#SYMBOL_NAME(interrupt_redirect_table),er0
160#endif
161#if defined(CONFIG_RAMKERNEL)
162	mov.l	@SYMBOL_NAME(interrupt_redirect_table),er1
163	sub.l	er1,er0
164#endif
165	shlr.l	#2,er0
166	dec.l	#1,er0
167	mov.l	sp,er1
168	subs	#4,er1				/* adjust ret_pc */
169	jsr	@SYMBOL_NAME(process_int)
170	mov.l	@SYMBOL_NAME(irq_stat)+CPUSTAT_SOFTIRQ_PENDING,er0
171	beq	1f
172	jsr	@SYMBOL_NAME(do_softirq)
1731:
174	jmp	@SYMBOL_NAME(ret_from_exception)
175
176SYMBOL_NAME_LABEL(system_call)
177	subs	#4,sp				/* dummy LVEC */
178	SAVE_ALL
179	mov.l	er0,er4
180	mov.l	#-ENOSYS,er0
181	mov.l	er0,@(LER0:16,sp)
182
183	/* save top of frame */
184	mov.l	sp,er0
185	jsr	@SYMBOL_NAME(set_esp0)
186	cmp.l	#NR_syscalls,er4
187	bcc	SYMBOL_NAME(ret_from_exception):16
188	shll.l	#2,er4
189	mov.l	#SYMBOL_NAME(sys_call_table),er0
190	add.l	er4,er0
191	mov.l	@er0,er0
192	mov.l	er0,er4
193	beq	SYMBOL_NAME(ret_from_exception):16
194	mov.l	sp,er2
195	and.w	#0xe000,r2
196	mov.b	@((TASK_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
197	btst	#(TIF_SYSCALL_TRACE & 7),r2l
198	mov.l	@(LER1:16,sp),er0
199	mov.l	@(LER2:16,sp),er1
200	mov.l	@(LER3:16,sp),er2
201	andc	#0x7f,ccr
202	jsr	@er4
203	mov.l	er0,@(LER0:16,sp)			/* save the return value */
204#if defined(CONFIG_SYSCALL_PRINT)
205	jsr	@SYMBOL_NAME(syscall_print)
206#endif
207	bra	SYMBOL_NAME(ret_from_exception):8
2081:
209	jsr	SYMBOL_NAME(syscall_trace)
210	mov.l	@(LER1:16,sp),er0
211	mov.l	@(LER2:16,sp),er1
212	mov.l	@(LER3:16,sp),er2
213	jsr	@er4
214	mov.l	er0,@(LER0:16,sp)		/* save the return value */
215	jsr	@SYMBOL_NAME(syscall_trace)
216	bra	SYMBOL_NAME(ret_from_exception):8
217
218SYMBOL_NAME_LABEL(ret_from_fork)
219	mov.l	er2,er0
220	jsr	@SYMBOL_NAME(schedule_tail)
221	bra	SYMBOL_NAME(ret_from_exception):8
222
223SYMBOL_NAME_LABEL(reschedule)
224	/* save top of frame */
225	mov.l	sp,er0
226	jsr	@SYMBOL_NAME(set_esp0)
227	jsr	@SYMBOL_NAME(schedule)
228
229SYMBOL_NAME_LABEL(ret_from_exception)
230#if defined(CONFIG_PREEMPT)
231	orc	#0x80,ccr
232#endif
233SYMBOL_NAME_LABEL(ret_from_interrupt)
234	mov.b	@(LCCR+1:16,sp),r0l
235	btst	#4,r0l			/* check if returning to kernel */
236	bne	done:8			/* if so, skip resched, signals */
237	andc	#0x7f,ccr
238	mov.l	sp,er4
239	and.w	#0xe000,r4
240	mov.l	@(TI_FLAGS:16,er4),er1
241	and.l	#_TIF_WORK_MASK,er1
242	beq	done:8
2431:
244	mov.l	@(TI_FLAGS:16,er4),er1
245	btst	#TIF_NEED_RESCHED,r1l
246	bne	SYMBOL_NAME(reschedule):16
247	mov.l	sp,er0
248	subs	#4,er0			/* adjust retpc */
249	mov.l	er2,er1
250	jsr	@SYMBOL_NAME(do_signal)
251#if defined(CONFIG_PREEMPT)
252	bra	done:8			/* userspace thoru */
2533:
254	btst	#4,r0l
255	beq	done:8			/* userspace thoru */
2564:
257	mov.l	@(TI_PRE_COUNT:16,er4),er1
258	bne	done:8
259	mov.l	@(TI_FLAGS:16,er4),er1
260	btst	#TIF_NEED_RESCHED,r1l
261	beq	done:8
262	mov.b	r0l,r0l
263	bpl	done:8			/* interrupt off (exception path?) */
264	mov.l	#PREEMPT_ACTIVE,er1
265	mov.l	er1,@(TI_PRE_COUNT:16,er4)
266	andc	#0x7f,ccr
267	jsr	@SYMBOL_NAME(schedule)
268	sub.l	er1,er1
269	mov.l	er1,@(TI_PRE_COUNT:16,er4)
270	orc	#0x80,ccr
271	bra	4b:8
272#endif
273done:
274	RESTORE_ALL			/* Does RTE */
275
276SYMBOL_NAME_LABEL(resume)
277	/*
278	 *	er0 = prev
279	 *	er1 = next
280	 *	return last in er2
281	 */
282
283	/* save sr */
284	sub.w	r3,r3
285	stc	ccr,r3l
286	stc	exr,r3h
287	mov.w	r3,@(THREAD_CCR+2:16,er0)
288
289	/* disable interrupts */
290	orc	#0x80,ccr
291	mov.l	@SYMBOL_NAME(sw_usp),er3
292	mov.l	er3,@(THREAD_USP:16,er0)
293	mov.l	sp,@(THREAD_KSP:16,er0)
294
295	/* Skip address space switching if they are the same. */
296
297	mov.l	@(THREAD_USP:16,er1),er0
298	mov.l	er0,@SYMBOL_NAME(sw_usp)
299	mov.l	@(THREAD_KSP:16,er1),sp
300
301	/* restore status register */
302	mov.w	@(THREAD_CCR+2:16,er1),r3
303
304	ldc	r3l,ccr
305	ldc	r3h,exr
306
307	rts
308
309SYMBOL_NAME_LABEL(trace_break)
310	subs	#4,sp			/* dummy LVEC */
311	SAVE_ALL
312	sub.l	er1,er1
313	dec.l	#1,er1
314	mov.l	er1,@(LORIG,sp)
315	mov.l	sp,er0
316	jsr	@SYMBOL_NAME(set_esp0)
317	mov.l	@SYMBOL_NAME(sw_usp),er0
318	mov.l	@er0,er1
319	subs	#2,er1
320	mov.l	er1,@er0
321	and.w	#0xff,e1
322	mov.l	er1,er0
323	jsr	@SYMBOL_NAME(trace_trap)
324	jmp	@SYMBOL_NAME(ret_from_exception)
325
326	.section	.bss
327SYMBOL_NAME_LABEL(sw_ksp)
328	.space	4
329SYMBOL_NAME_LABEL(sw_usp)
330	.space	4
331