Merge git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-2.6] / arch / h8300 / platform / h8300h / entry.S
1 /* -*- mode: asm -*-
2  *
3  *  linux/arch/h8300/platform/h8300h/entry.S
4  *
5  *  Yoshinori Sato <ysato@users.sourceforge.jp>
6  *  David McCullough <davidm@snapgear.com>
7  *
8  */
9
10 /*
11  *  entry.S
12  *  include exception/interrupt gateway
13  *          system call entry
14  */
15
16 #include <linux/sys.h>
17 #include <linux/config.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         .h8300h
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         orc     #0x10,ccr
35         btst    #4,r0l
36         bne     5f
37
38         mov.l   sp,@SYMBOL_NAME(sw_usp)         /* user mode */
39         mov.l   @sp,er0
40         mov.l   @SYMBOL_NAME(sw_ksp),sp
41         sub.l   #(LRET-LORIG),sp                /* allocate LORIG - LRET */ 
42         mov.l   er0,@-sp
43         mov.l   er1,@-sp
44         mov.l   @SYMBOL_NAME(sw_usp),er0
45         mov.l   @(8:16,er0),er1                 /* copy the RET addr */
46         mov.l   er1,@(LRET-LER1:16,sp)
47
48         mov.w   e1,r1                           /* e1 highbyte = ccr */
49         and     #0xef,r1h                       /* mask mode? flag */
50         sub.w   r0,r0
51         mov.b   r1h,r0l
52         mov.w   r0,@(LCCR-LER1:16,sp)           /* copy ccr */
53         mov.l   @(LORIG-LER1:16,sp),er0
54         mov.l   er0,@(LER0-LER1:16,sp)          /* copy ER0 */
55         bra     6f
56 5:
57         mov.l   @sp,er0                         /* kernel mode */
58         subs    #2,sp                           /* dummy ccr */
59         mov.l   er0,@-sp
60         mov.l   er1,@-sp
61         mov.w   @(LRET-LER1:16,sp),r1           /* copy old ccr */
62         mov.b   r1h,r1l
63         mov.b   #0,r1h
64         mov.w   r1,@(LCCR-LER1:16,sp)           /* set ccr */
65 6:
66         mov.l   er2,@-sp
67         mov.l   er3,@-sp
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         mov.l   @sp+,er3
78         mov.l   @sp+,er2
79         mov.w   @(LCCR-LER1:16,sp),r0           /* check kernel mode */
80         btst    #4,r0l
81         bne     7f
82
83         orc     #0x80,ccr
84         mov.l   @SYMBOL_NAME(sw_usp),er0
85         mov.l   @(LER0-LER1:16,sp),er1          /* restore ER0 */
86         mov.l   er1,@er0
87         mov.w   @(LCCR-LER1:16,sp),r1           /* restore the RET addr */
88         mov.b   r1l,r1h
89         mov.b   @(LRET+1-LER1:16,sp),r1l
90         mov.w   r1,e1
91         mov.w   @(LRET+2-LER1:16,sp),r1
92         mov.l   er1,@(8:16,er0)
93
94         mov.l   @sp+,er1
95         add.l   #(LRET-LER1),sp                 /* remove LORIG - LRET */ 
96         mov.l   sp,@SYMBOL_NAME(sw_ksp)
97         mov.l   er0,sp
98         bra     8f
99 7:
100         mov.l   @sp+,er1
101         adds    #4,sp
102         adds    #2,sp
103 8:
104         mov.l   @sp+,er0
105         adds    #4,sp                           /* remove the sw created LVEC */
106         rte
107         .endm
108         
109 .globl SYMBOL_NAME(system_call)
110 .globl SYMBOL_NAME(ret_from_exception)
111 .globl SYMBOL_NAME(ret_from_fork)
112 .globl SYMBOL_NAME(ret_from_interrupt)
113 .globl SYMBOL_NAME(interrupt_redirect_table)
114 .globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp)
115 .globl SYMBOL_NAME(resume)
116 .globl SYMBOL_NAME(interrupt_redirect_table)
117 .globl SYMBOL_NAME(interrupt_entry)
118 .globl SYMBOL_NAME(system_call)
119 .globl SYMBOL_NAME(trace_break)
120
121 #if defined(CONFIG_ROMKERNEL)
122 INTERRUPTS = 64         
123         .section .int_redirect,"ax"
124 SYMBOL_NAME_LABEL(interrupt_redirect_table)
125         .rept   7
126         .long   0
127         .endr
128         jsr     @SYMBOL_NAME(interrupt_entry)   /* NMI */
129         jmp     @SYMBOL_NAME(system_call)       /* TRAPA #0 (System call) */
130         .long   0
131         .long   0
132         jmp     @SYMBOL_NAME(trace_break)       /* TRAPA #3 (breakpoint) */
133         .rept   INTERRUPTS-12
134         jsr     @SYMBOL_NAME(interrupt_entry)
135         .endr
136 #endif
137 #if defined(CONFIG_RAMKERNEL)
138 .globl SYMBOL_NAME(interrupt_redirect_table)
139         .section .bss
140 SYMBOL_NAME_LABEL(interrupt_redirect_table)
141         .space  4
142 #endif
143
144         .section .text
145         .align  2
146 SYMBOL_NAME_LABEL(interrupt_entry)
147         SAVE_ALL
148         mov.w   @(LCCR,sp),r0
149         btst    #4,r0l
150         bne     1f
151         mov.l   @SYMBOL_NAME(sw_usp),er0
152         mov.l   @(4:16,er0),er0
153         bra     2f
154 1:
155         mov.l   @(LVEC,sp),er0
156 2:
157 #if defined(CONFIG_ROMKERNEL)
158         sub.l   #SYMBOL_NAME(interrupt_redirect_table),er0
159 #endif
160 #if defined(CONFIG_RAMKERNEL)
161         mov.l   @SYMBOL_NAME(interrupt_redirect_table),er1
162         sub.l   er1,er0
163 #endif
164         shlr.l  er0
165         shlr.l  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)
173 1:
174         jmp     @SYMBOL_NAME(ret_from_interrupt)
175         
176 SYMBOL_NAME_LABEL(system_call)
177         subs    #4,sp                           /* dummy LVEC */
178         SAVE_ALL
179         mov.w   @(LCCR:16,sp),r1
180         bset    #4,r1l
181         ldc     r1l,ccr
182         mov.l   er0,er4
183         mov.l   #-ENOSYS,er0
184         mov.l   er0,@(LER0:16,sp)
185
186         /* save top of frame */
187         mov.l   sp,er0
188         jsr     @SYMBOL_NAME(set_esp0)
189         cmp.l   #NR_syscalls,er4
190         bcc     SYMBOL_NAME(ret_from_exception):16
191         shll.l  er4
192         shll.l  er4
193         mov.l   #SYMBOL_NAME(sys_call_table),er0
194         add.l   er4,er0
195         mov.l   @er0,er4
196         beq     SYMBOL_NAME(ret_from_exception):16      
197         mov.l   sp,er2
198         and.w   #0xe000,r2
199         mov.b   @((TASK_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
200         btst    #(TIF_SYSCALL_TRACE & 7),r2l
201         bne     1f
202         mov.l   @(LER1:16,sp),er0
203         mov.l   @(LER2:16,sp),er1
204         mov.l   @(LER3:16,sp),er2
205         jsr     @er4
206         mov.l   er0,@(LER0:16,sp)               /* save the return value */
207 #if defined(CONFIG_SYSCALL_PRINT)
208         jsr     @SYMBOL_NAME(syscall_print)
209 #endif
210         bra     SYMBOL_NAME(ret_from_exception):8
211 1:
212         jsr     SYMBOL_NAME(syscall_trace)
213         mov.l   @(LER1:16,sp),er0
214         mov.l   @(LER2:16,sp),er1
215         mov.l   @(LER3:16,sp),er2
216         jsr     @er4
217         mov.l   er0,@(LER0:16,sp)               /* save the return value */
218         jsr     @SYMBOL_NAME(syscall_trace)
219         bra     SYMBOL_NAME(ret_from_exception):8
220
221 SYMBOL_NAME_LABEL(ret_from_fork)
222         mov.l   er2,er0
223         jsr     @SYMBOL_NAME(schedule_tail)
224         bra     SYMBOL_NAME(ret_from_exception):8
225
226 SYMBOL_NAME_LABEL(reschedule)
227         /* save top of frame */
228         mov.l   sp,er0
229         jsr     @SYMBOL_NAME(set_esp0)
230         jsr     @SYMBOL_NAME(schedule)
231
232 SYMBOL_NAME_LABEL(ret_from_exception)
233 #if defined(CONFIG_PREEMPT)
234         orc     #0x80,ccr
235 #endif
236 SYMBOL_NAME_LABEL(ret_from_interrupt)
237         mov.b   @(LCCR+1:16,sp),r0l
238         btst    #4,r0l                  /* check if returning to kernel */
239         bne     done:8                  /* if so, skip resched, signals */
240         andc    #0x7f,ccr
241         mov.l   sp,er4
242         and.w   #0xe000,r4
243         mov.l   @(TI_FLAGS:16,er4),er1
244         and.l   #_TIF_WORK_MASK,er1
245         beq     done:8
246 1:
247         mov.l   @(TI_FLAGS:16,er4),er1
248         btst    #TIF_NEED_RESCHED,r1l
249         bne     SYMBOL_NAME(reschedule):16
250         mov.l   sp,er0
251         subs    #4,er0                  /* adjust retpc */
252         mov.l   er2,er1
253         jsr     @SYMBOL_NAME(do_signal)
254 #if defined(CONFIG_PREEMPT)
255         bra     done:8                  /* userspace thoru */
256 3:
257         btst    #4,r0l
258         beq     done:8                  /* userspace thoru */
259 4:
260         mov.l   @(TI_PRE_COUNT:16,er4),er1
261         bne     done:8
262         mov.l   @(TI_FLAGS:16,er4),er1
263         btst    #TIF_NEED_RESCHED,r1l
264         beq     done:8
265         mov.b   r0l,r0l
266         bpl     done:8                  /* interrupt off (exception path?) */
267         mov.l   #PREEMPT_ACTIVE,er1
268         mov.l   er1,@(TI_PRE_COUNT:16,er4)
269         andc    #0x7f,ccr
270         jsr     @SYMBOL_NAME(schedule)
271         sub.l   er1,er1
272         mov.l   er1,@(TI_PRE_COUNT:16,er4)
273         orc     #0x80,ccr
274         bra     4b:8
275 #endif
276 done:
277         RESTORE_ALL                     /* Does RTE */
278
279 SYMBOL_NAME_LABEL(resume)
280         /*
281          * Beware - when entering resume, offset of tss is in d1,
282          * prev (the current task) is in a0, next (the new task)
283          * is in a1 and d2.b is non-zero if the mm structure is
284          * shared between the tasks, so don't change these
285          * registers until their contents are no longer needed.
286          */
287
288         /* save sr */
289         sub.w   r3,r3
290         stc     ccr,r3l
291         mov.w   r3,@(THREAD_CCR+2:16,er0)
292
293         /* disable interrupts */
294         orc     #0x80,ccr
295         mov.l   @SYMBOL_NAME(sw_usp),er3
296         mov.l   er3,@(THREAD_USP:16,er0)
297         mov.l   sp,@(THREAD_KSP:16,er0)
298
299         /* Skip address space switching if they are the same. */
300         /* FIXME: what did we hack out of here, this does nothing! */
301
302         mov.l   @(THREAD_USP:16,er1),er0
303         mov.l   er0,@SYMBOL_NAME(sw_usp)
304         mov.l   @(THREAD_KSP:16,er1),sp
305                         
306         /* restore status register */
307         mov.w   @(THREAD_CCR+2:16,er1),r3
308
309         ldc     r3l,ccr
310         rts
311         
312 SYMBOL_NAME_LABEL(trace_break)
313         subs    #4,sp
314         SAVE_ALL
315         sub.l   er1,er1
316         dec.l   #1,er1
317         mov.l   er1,@(LORIG,sp) 
318         mov.l   sp,er0
319         jsr     @SYMBOL_NAME(set_esp0)
320         mov.l   @SYMBOL_NAME(sw_usp),er0
321         mov.l   @er0,er1
322         subs    #2,er1
323         mov.l   er1,@er0        
324         and.w   #0xff,e1
325         mov.l   er1,er0
326         jsr     @SYMBOL_NAME(trace_trap)
327         jmp     @SYMBOL_NAME(ret_from_exception)        
328
329         .section        .bss
330 SYMBOL_NAME_LABEL(sw_ksp)
331         .space  4       
332 SYMBOL_NAME_LABEL(sw_usp)
333         .space  4