OSDN Git Service

3d1c1b162deb6e1a50013d7dd8ed539604034393
[uclinux-h8/linux.git] / arch / h8300 / kernel / 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 #if defined(CONFIG_CPU_H8300H)
26 #define USERRET 8
27 INTERRUPTS = 64
28         .h8300h
29         .macro  SHLL2 reg
30         shll.l  \reg
31         shll.l  \reg
32         .endm
33         .macro  SHLR2 reg
34         shlr.l  \reg
35         shlr.l  \reg
36         .endm
37         .macro  SAVEREGS
38         mov.l   er0,@-sp
39         mov.l   er1,@-sp
40         mov.l   er2,@-sp
41         mov.l   er3,@-sp
42         .endm
43         .macro  RESTOREREGS
44         mov.l   @sp+,er3
45         mov.l   @sp+,er2
46         .endm
47         .macro  SAVEEXR
48         .endm
49         .macro  RESTOREEXR
50         .endm
51 #endif
52 #if defined(CONFIG_CPU_H8S)
53 #define USERRET 10
54 #define USEREXR 8
55 INTERRUPTS = 128
56         .h8300s
57         .macro  SHLL2 reg
58         shll.l  #2,\reg
59         .endm
60         .macro  SHLR2 reg
61         shlr.l  #2,\reg
62         .endm
63         .macro  SAVEREGS
64         stm.l   er0-er3,@-sp
65         .endm
66         .macro  RESTOREREGS
67         ldm.l   @sp+,er2-er3
68         .endm
69         .macro  SAVEEXR
70         mov.w   @(USEREXR:16,er0),r1
71         mov.w   r1,@(LEXR-LER3:16,sp)           /* copy EXR */
72         .endm
73         .macro  RESTOREEXR
74         mov.w   @(LEXR-LER1:16,sp),r1           /* restore EXR */
75         mov.b   r1l,r1h
76         mov.w   r1,@(USEREXR:16,er0)
77         .endm
78 #endif
79
80
81 /* CPU context save/restore macros. */
82
83         .macro  SAVE_ALL
84         mov.l   er0,@-sp
85         stc     ccr,r0l                         /* check kernel mode */
86         btst    #4,r0l
87         bne     5f
88
89         /* user mode */
90         mov.l   sp,@_sw_usp
91         mov.l   @sp,er0                         /* restore saved er0 */
92         orc     #0x10,ccr                       /* switch kernel stack */
93         mov.l   @_sw_ksp,sp
94         sub.l   #(LRET-LORIG),sp                /* allocate LORIG - LRET */
95         SAVEREGS
96         mov.l   @_sw_usp,er0
97         mov.l   @(USERRET:16,er0),er1           /* copy the RET addr */
98         mov.l   er1,@(LRET-LER3:16,sp)
99         SAVEEXR
100
101         mov.l   @(LORIG-LER3:16,sp),er0
102         mov.l   er0,@(LER0-LER3:16,sp)          /* copy ER0 */
103         mov.w   e1,r1                           /* e1 highbyte = ccr */
104         and     #0xef,r1h                       /* mask mode? flag */
105         bra     6f
106 5:
107         /* kernel mode */
108         mov.l   @sp,er0                         /* restore saved er0 */
109         subs    #2,sp                           /* set dummy ccr */
110         SAVEREGS
111         mov.w   @(LRET-LER3:16,sp),r1           /* copy old ccr */
112 6:
113         mov.b   r1h,r1l
114         mov.b   #0,r1h
115         mov.w   r1,@(LCCR-LER3:16,sp)           /* set ccr */
116         mov.l   er6,@-sp                        /* syscall arg #6 */
117         mov.l   er5,@-sp                        /* syscall arg #5 */
118         mov.l   er4,@-sp                        /* syscall arg #4 */
119         .endm                                   /* r1 = ccr */
120
121         .macro  RESTORE_ALL
122         mov.l   @sp+,er4
123         mov.l   @sp+,er5
124         mov.l   @sp+,er6
125         RESTOREREGS
126         mov.w   @(LCCR-LER1:16,sp),r0           /* check kernel mode */
127         btst    #4,r0l
128         bne     7f
129
130         orc     #0xc0,ccr
131         mov.l   @_sw_usp,er0
132         mov.l   @(LER0-LER1:16,sp),er1          /* restore ER0 */
133         mov.l   er1,@er0
134         RESTOREEXR
135         mov.w   @(LCCR-LER1:16,sp),r1           /* restore the RET addr */
136         mov.b   r1l,r1h
137         mov.b   @(LRET+1-LER1:16,sp),r1l
138         mov.w   r1,e1
139         mov.w   @(LRET+2-LER1:16,sp),r1
140         mov.l   er1,@(USERRET:16,er0)
141
142         mov.l   @sp+,er1
143         add.l   #(LRET-LER1),sp                 /* remove LORIG - LRET */
144         mov.l   sp,@_sw_ksp
145         andc    #0xef,ccr                       /* switch to user mode */
146         mov.l   er0,sp
147         bra     8f
148 7:
149         mov.l   @sp+,er1
150         adds    #4,sp
151         adds    #2,sp
152 8:
153         mov.l   @sp+,er0
154         adds    #4,sp                           /* remove the sw created LVEC */
155         rte
156         .endm
157
158 .globl _system_call
159 .globl ret_from_exception
160 .globl ret_from_fork
161 .globl ret_from_kernel_thread
162 .globl ret_from_interrupt
163 .globl _interrupt_redirect_table
164 .globl _sw_ksp,_sw_usp
165 .globl _resume
166 .globl _interrupt_entry
167 .globl _trace_break
168 .globl _nmi
169
170 #if defined(CONFIG_ROMKERNEL)
171         .section .int_redirect,"ax"
172 _interrupt_redirect_table:
173 #if defined(CONFIG_CPU_H8300H)
174         .rept   7
175         .long   0
176         .endr
177 #endif
178 #if defined(CONFIG_CPU_H8S)
179         .rept   5
180         .long   0
181         .endr
182         jmp     @_trace_break
183         .long   0
184 #endif
185
186         jsr     @_interrupt_entry               /* NMI */
187         jmp     @_system_call                   /* TRAPA #0 (System call) */
188         .long   0
189         .long   0
190         jmp     @_trace_break                   /* TRAPA #3 (breakpoint) */
191         .rept   INTERRUPTS-12
192         jsr     @_interrupt_entry
193         .endr
194 #endif
195 #if defined(CONFIG_RAMKERNEL)
196 .globl _interrupt_redirect_table
197         .section .bss
198 _interrupt_redirect_table:
199         .space  4
200 #endif
201
202         .section .text
203         .align  2
204 _interrupt_entry:
205         SAVE_ALL
206         mov.l   sp,er0
207         add.l   #LVEC,er0
208         btst    #4,r1l
209         bne     1f
210         /* user LVEC */
211         mov.l   @_sw_usp,er0
212         adds    #4,er0
213 1:
214         mov.l   @er0,er0                        /* LVEC address */
215 #if defined(CONFIG_ROMKERNEL)
216         sub.l   #_interrupt_redirect_table,er0
217 #endif
218 #if defined(CONFIG_RAMKERNEL)
219         mov.l   @_interrupt_redirect_table,er1
220         sub.l   er1,er0
221 #endif
222         SHLR2   er0
223         dec.l   #1,er0
224         mov.l   sp,er1
225         subs    #4,er1                          /* adjust ret_pc */
226 #if defined(CONFIG_CPU_H8S)
227         orc     #7,exr
228 #endif
229         jsr     @do_IRQ
230         jmp     @ret_from_interrupt
231
232 _system_call:
233         subs    #4,sp                           /* dummy LVEC */
234         SAVE_ALL
235         andc    #0xbf,ccr
236         mov.l   er0,er4
237
238         /* save top of frame */
239         mov.l   sp,er0
240         jsr     @set_esp0
241         mov.l   sp,er2
242         and.w   #0xe000,r2
243         mov.b   @((TI_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
244         btst    #(TIF_SYSCALL_TRACE & 7),r2l
245         beq     1f
246         jsr     @do_syscall_trace
247 1:
248         cmp.l   #__NR_syscalls,er4
249         bcc     badsys
250         SHLL2   er4
251         mov.l   #_sys_call_table,er0
252         add.l   er4,er0
253         mov.l   @er0,er4
254         beq     ret_from_exception:16
255         mov.l   @(LER1:16,sp),er0
256         mov.l   @(LER2:16,sp),er1
257         mov.l   @(LER3:16,sp),er2
258         jsr     @er4
259         mov.l   er0,@(LER0:16,sp)               /* save the return value */
260         mov.l   sp,er2
261         and.w   #0xe000,r2
262         mov.b   @((TI_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
263         btst    #(TIF_SYSCALL_TRACE & 7),r2l
264         beq     2f
265         jsr     @do_syscall_trace
266 2:
267         orc     #0xc0,ccr
268         bra     resume_userspace
269
270 badsys:
271         mov.l   #-ENOSYS,er0
272         mov.l   er0,@(LER0:16,sp)
273         bra     resume_userspace
274
275 #if !defined(CONFIG_PREEMPT)
276 #define resume_kernel restore_all
277 #endif
278
279 ret_from_exception:
280 #if defined(CONFIG_PREEMPT)
281         orc     #0xc0,ccr
282 #endif
283 ret_from_interrupt:
284         mov.b   @(LCCR+1:16,sp),r0l
285         btst    #4,r0l
286 #if defined(CONFIG_PREEMPT)
287         bne     resume_kernel:16        /* return from kernel */
288 #else
289         bne     restore_all:16          /* return from kernel */
290 #endif
291 resume_userspace:
292         andc    #0xbf,ccr
293         mov.l   sp,er4
294         and.w   #0xe000,r4              /* er4 <- current thread info */
295         mov.l   @(TI_FLAGS:16,er4),er1
296         and.l   #_TIF_WORK_MASK,er1
297         beq     restore_all:8
298 work_pending:
299         btst    #TIF_NEED_RESCHED,r1l
300         bne     work_resched:8
301         /* work notifysig */
302         mov.l   sp,er0
303         subs    #4,er0                  /* er0: pt_regs */
304         jsr     @do_notify_resume
305         bra     restore_all:8
306 work_resched:
307         mov.l   sp,er0
308         jsr     @set_esp0
309         jsr     @schedule
310         bra     resume_userspace:8
311 restore_all:
312         RESTORE_ALL                     /* Does RTE */
313
314 #if defined(CONFIG_PREEMPT)
315 resume_kernel:
316         mov.l   @(TI_PRE_COUNT:16,er4),er0
317         bne     restore_all:8
318 need_resched:
319         mov.l   @(TI_FLAGS:16,er4),er0
320         btst    #TIF_NEED_RESCHED,r0l
321         beq     restore_all:8
322         mov.b   @(LCCR+1:16,sp),r0l     /* Interrupt Enabled? */
323         bmi     restore_all:8
324         mov.l   sp,er0
325         jsr     @set_esp0
326         jsr     @preempt_schedule_irq
327         bra     need_resched:8
328 #endif
329
330 ret_from_fork:
331         mov.l   er2,er0
332         jsr     @schedule_tail
333         jmp     @ret_from_exception
334
335 ret_from_kernel_thread:
336         mov.l   er2,er0
337         jsr     @schedule_tail
338         mov.l   @(LER4:16,sp),er0
339         mov.l   @(LER5:16,sp),er1
340         jsr     @er1
341         jmp     @ret_from_exception
342
343 _resume:
344         /*
345          * Beware - when entering resume, offset of tss is in d1,
346          * prev (the current task) is in a0, next (the new task)
347          * is in a1 and d2.b is non-zero if the mm structure is
348          * shared between the tasks, so don't change these
349          * registers until their contents are no longer needed.
350          */
351
352         /* save sr */
353         sub.w   r3,r3
354         stc     ccr,r3l
355         mov.w   r3,@(THREAD_CCR+2:16,er0)
356
357         /* disable interrupts */
358         orc     #0xc0,ccr
359         mov.l   @_sw_usp,er3
360         mov.l   er3,@(THREAD_USP:16,er0)
361         mov.l   sp,@(THREAD_KSP:16,er0)
362
363         /* Skip address space switching if they are the same. */
364         /* FIXME: what did we hack out of here, this does nothing! */
365
366         mov.l   @(THREAD_USP:16,er1),er0
367         mov.l   er0,@_sw_usp
368         mov.l   @(THREAD_KSP:16,er1),sp
369
370         /* restore status register */
371         mov.w   @(THREAD_CCR+2:16,er1),r3
372
373         ldc     r3l,ccr
374         rts
375
376 _trace_break:
377         subs    #4,sp
378         SAVE_ALL
379         sub.l   er1,er1
380         dec.l   #1,er1
381         mov.l   er1,@(LORIG,sp)
382         mov.l   sp,er0
383         jsr     @set_esp0
384         mov.l   @_sw_usp,er0
385         mov.l   @er0,er1
386         mov.w   @(-2:16,er1),r2
387         cmp.w   #0x5730,r2
388         beq     1f
389         subs    #2,er1
390         mov.l   er1,@er0
391 1:
392         and.w   #0xff,e1
393         mov.l   er1,er0
394         jsr     @trace_trap
395         jmp     @ret_from_exception
396
397 _nmi:
398         subs    #4, sp
399         mov.l   er0, @-sp
400         mov.l   @_interrupt_redirect_table, er0
401         add.l   #8*4, er0
402         mov.l   er0, @(4,sp)
403         mov.l   @sp+, er0
404         jmp     @_interrupt_entry
405
406         .section        .bss
407 _sw_ksp:
408         .space  4
409 _sw_usp:
410         .space  4
411
412         .end