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