h8300 generic irq
[linux-3.10.git] / arch / h8300 / platform / h8s / entry.S
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
58 5:
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)
67 6:      
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
102 7:
103         mov.l   @sp+,er1
104         adds    #4,sp
105         adds    #2,sp
106 8:
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                 
122 INTERRUPTS = 128
123 #if defined(CONFIG_ROMKERNEL)
124         .section .int_redirect,"ax"
125 SYMBOL_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
141 SYMBOL_NAME_LABEL(interrupt_redirect_table)
142         .space  4
143 #endif
144         
145         .section .text
146         .align  2
147 SYMBOL_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
155 1:
156         mov.l   @(LVEC:16,sp),er0
157 2:
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)
173 1:
174         jmp     @SYMBOL_NAME(ret_from_exception)
175
176 SYMBOL_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
208 1:
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
218 SYMBOL_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
223 SYMBOL_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
229 SYMBOL_NAME_LABEL(ret_from_exception)
230 #if defined(CONFIG_PREEMPT)
231         orc     #0x80,ccr
232 #endif
233 SYMBOL_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
243 1:
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 */
253 3:
254         btst    #4,r0l
255         beq     done:8                  /* userspace thoru */
256 4:
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
273 done:
274         RESTORE_ALL                     /* Does RTE */
275
276 SYMBOL_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         /* FIXME: what did we hack out of here, this does nothing! */
297
298         mov.l   @(THREAD_USP:16,er1),er0
299         mov.l   er0,@SYMBOL_NAME(sw_usp)
300         mov.l   @(THREAD_KSP:16,er1),sp
301                         
302         /* restore status register */
303         mov.w   @(THREAD_CCR+2:16,er1),r3
304
305         ldc     r3l,ccr
306         ldc     r3h,exr
307
308         rts
309
310 SYMBOL_NAME_LABEL(trace_break)
311         subs    #4,sp                   /* dummy LVEC */
312         SAVE_ALL
313         sub.l   er1,er1
314         dec.l   #1,er1
315         mov.l   er1,@(LORIG,sp) 
316         mov.l   sp,er0
317         jsr     @SYMBOL_NAME(set_esp0)
318         mov.l   @SYMBOL_NAME(sw_usp),er0
319         mov.l   @er0,er1
320         subs    #2,er1
321         mov.l   er1,@er0        
322         and.w   #0xff,e1
323         mov.l   er1,er0
324         jsr     @SYMBOL_NAME(trace_trap)
325         jmp     @SYMBOL_NAME(ret_from_exception)        
326
327         .section        .bss
328 SYMBOL_NAME_LABEL(sw_ksp)
329         .space  4       
330 SYMBOL_NAME_LABEL(sw_usp)
331         .space  4