Linux-libre 4.9.135-gnu
[librecmc/linux-libre.git] / arch / sh / kernel / cpu / sh2 / entry.S
1 /*
2  * arch/sh/kernel/cpu/sh2/entry.S
3  *
4  * The SH-2 exception entry
5  *
6  * Copyright (C) 2005-2008 Yoshinori Sato
7  * Copyright (C) 2005  AXE,Inc.
8  *
9  * This file is subject to the terms and conditions of the GNU General Public
10  * License.  See the file "COPYING" in the main directory of this archive
11  * for more details.
12  */
13
14 #include <linux/linkage.h>
15 #include <asm/asm-offsets.h>
16 #include <asm/thread_info.h>
17 #include <cpu/mmu_context.h>
18 #include <asm/unistd.h>
19 #include <asm/errno.h>
20 #include <asm/page.h>
21         
22 /* Offsets to the stack */
23 OFF_R0  =  0            /* Return value. New ABI also arg4 */
24 OFF_R1  =  4            /* New ABI: arg5 */
25 OFF_R2  =  8            /* New ABI: arg6 */
26 OFF_R3  =  12           /* New ABI: syscall_nr */
27 OFF_R4  =  16           /* New ABI: arg0 */
28 OFF_R5  =  20           /* New ABI: arg1 */
29 OFF_R6  =  24           /* New ABI: arg2 */
30 OFF_R7  =  28           /* New ABI: arg3 */
31 OFF_SP  =  (15*4)
32 OFF_PC  =  (16*4)
33 OFF_SR  =  (16*4+2*4)
34 OFF_TRA =  (16*4+6*4)
35
36 #include <asm/entry-macros.S>
37
38 ENTRY(exception_handler)
39         ! stack
40         ! r0 <- point sp
41         ! r1
42         ! pc
43         ! sr
44         ! r0 = temporary
45         ! r1 = vector (pseudo EXPEVT / INTEVT / TRA)
46         mov.l   r2,@-sp
47         mov.l   r3,@-sp
48         cli
49         mov.l   $cpu_mode,r2
50 #ifdef CONFIG_SMP
51         mov.l   $cpuid,r3
52         mov.l   @r3,r3
53         mov.l   @r3,r3
54         shll2   r3
55         add     r3,r2
56 #endif
57         mov.l   @r2,r0
58         mov.l   @(5*4,r15),r3   ! previous SR
59         or      r0,r3           ! set MD
60         tst     r0,r0
61         bf/s    1f              ! previous mode check
62          mov.l  r3,@(5*4,r15)   ! update SR
63         ! switch to kernel mode
64         mov.l   __md_bit,r0
65         mov.l   r0,@r2          ! enter kernel mode
66         mov.l   $current_thread_info,r2
67 #ifdef CONFIG_SMP
68         mov.l   $cpuid,r0
69         mov.l   @r0,r0
70         mov.l   @r0,r0
71         shll2   r0
72         add     r0,r2
73 #endif
74         mov.l   @r2,r2
75         mov     #(THREAD_SIZE >> 8),r0
76         shll8   r0
77         add     r2,r0
78         mov     r15,r2          ! r2 = user stack top
79         mov     r0,r15          ! switch kernel stack
80         mov.l   r1,@-r15        ! TRA
81         sts.l   macl, @-r15
82         sts.l   mach, @-r15
83         stc.l   gbr, @-r15
84         mov.l   @(5*4,r2),r0
85         mov.l   r0,@-r15        ! original SR
86         sts.l   pr,@-r15
87         mov.l   @(4*4,r2),r0
88         mov.l   r0,@-r15        ! original PC
89         mov     r2,r3
90         add     #(4+2)*4,r3     ! rewind r0 - r3 + exception frame
91         mov.l   r3,@-r15        ! original SP
92         mov.l   r14,@-r15
93         mov.l   r13,@-r15
94         mov.l   r12,@-r15
95         mov.l   r11,@-r15
96         mov.l   r10,@-r15
97         mov.l   r9,@-r15
98         mov.l   r8,@-r15
99         mov.l   r7,@-r15
100         mov.l   r6,@-r15
101         mov.l   r5,@-r15
102         mov.l   r4,@-r15
103         mov     r1,r9           ! save TRA
104         mov     r2,r8           ! copy user -> kernel stack
105         mov.l   @(0,r8),r3
106         mov.l   r3,@-r15
107         mov.l   @(4,r8),r2
108         mov.l   r2,@-r15
109         mov.l   @(12,r8),r1
110         mov.l   r1,@-r15
111         mov.l   @(8,r8),r0
112         bra     2f
113          mov.l  r0,@-r15
114 1:
115         ! in kernel exception
116         mov     #(22-4-4-1)*4+4,r0
117         mov     r15,r2
118         sub     r0,r15
119         mov.l   @r2+,r0         ! old R3
120         mov.l   r0,@-r15        
121         mov.l   @r2+,r0         ! old R2
122         mov.l   r0,@-r15        
123         mov.l   @(4,r2),r0      ! old R1
124         mov.l   r0,@-r15        
125         mov.l   @r2,r0          ! old R0
126         mov.l   r0,@-r15
127         add     #8,r2
128         mov.l   @r2+,r3         ! old PC
129         mov.l   @r2+,r0         ! old SR
130         add     #-4,r2          ! exception frame stub (sr)
131         mov.l   r1,@-r2         ! TRA
132         sts.l   macl, @-r2
133         sts.l   mach, @-r2
134         stc.l   gbr, @-r2
135         mov.l   r0,@-r2         ! save old SR
136         sts.l   pr,@-r2
137         mov.l   r3,@-r2         ! save old PC
138         mov     r2,r0
139         add     #8*4,r0
140         mov.l   r0,@-r2         ! save old SP
141         mov.l   r14,@-r2
142         mov.l   r13,@-r2
143         mov.l   r12,@-r2
144         mov.l   r11,@-r2
145         mov.l   r10,@-r2
146         mov.l   r9,@-r2
147         mov.l   r8,@-r2
148         mov.l   r7,@-r2
149         mov.l   r6,@-r2
150         mov.l   r5,@-r2
151         mov.l   r4,@-r2
152         mov     r1,r9
153         mov.l   @(OFF_R0,r15),r0
154         mov.l   @(OFF_R1,r15),r1
155         mov.l   @(OFF_R2,r15),r2
156         mov.l   @(OFF_R3,r15),r3
157 2:
158         mov     #64,r8
159         cmp/hs  r8,r9
160         bt      interrupt_entry ! vec >= 64 is interrupt
161         mov     #31,r8
162         cmp/hs  r8,r9
163         bt      trap_entry      ! 64 > vec >= 31  is trap
164 #ifdef CONFIG_CPU_J2
165         mov     #16,r8
166         cmp/hs  r8,r9
167         bt      interrupt_entry ! 31 > vec >= 16 is interrupt
168 #endif
169
170         mov.l   4f,r8
171         mov     r9,r4
172         shll2   r9
173         add     r9,r8
174         mov.l   @r8,r8          ! exception handler address
175         tst     r8,r8
176         bf      3f
177         mov.l   8f,r8           ! unhandled exception
178 3:
179         mov.l   5f,r10
180         jmp     @r8
181          lds    r10,pr
182
183 interrupt_entry:
184         mov     r9,r4
185         mov     r15,r5
186         mov.l   6f,r9
187         mov.l   7f,r8
188         jmp     @r8
189          lds    r9,pr
190
191         .align  2
192 4:      .long   exception_handling_table
193 5:      .long   ret_from_exception
194 6:      .long   ret_from_irq
195 7:      .long   do_IRQ
196 8:      .long   exception_error
197
198 trap_entry:
199         mov     #0x30,r8
200         cmp/ge  r8,r9           ! vector 0x1f-0x2f is systemcall
201         bt      1f
202         mov     #0x1f,r9        ! convert to unified SH2/3/4 trap number
203 1:      
204         shll2   r9                      ! TRA
205         bra     system_call     ! jump common systemcall entry
206          mov    r9,r8
207         
208 #if defined(CONFIG_SH_STANDARD_BIOS)
209         /* Unwind the stack and jmp to the debug entry */
210 ENTRY(sh_bios_handler)
211         mov     r15,r0
212         add     #(22-4)*4-4,r0
213         ldc.l   @r0+,gbr
214         lds.l   @r0+,mach
215         lds.l   @r0+,macl
216         mov     r15,r0
217         mov.l   @(OFF_SP,r0),r1
218         mov     #OFF_SR,r2
219         mov.l   @(r0,r2),r3
220         mov.l   r3,@-r1
221         mov     #OFF_SP,r2
222         mov.l   @(r0,r2),r3
223         mov.l   r3,@-r1
224         mov     r15,r0
225         add     #(22-4)*4-8,r0
226         mov.l   1f,r2
227         mov.l   @r2,r2
228         stc     sr,r3
229         mov.l   r2,@r0
230         mov.l   r3,@(4,r0)
231         mov.l   r1,@(8,r0)      
232         mov.l   @r15+, r0
233         mov.l   @r15+, r1
234         mov.l   @r15+, r2
235         mov.l   @r15+, r3
236         mov.l   @r15+, r4
237         mov.l   @r15+, r5
238         mov.l   @r15+, r6
239         mov.l   @r15+, r7
240         mov.l   @r15+, r8
241         mov.l   @r15+, r9
242         mov.l   @r15+, r10
243         mov.l   @r15+, r11
244         mov.l   @r15+, r12
245         mov.l   @r15+, r13
246         mov.l   @r15+, r14
247         add     #8,r15
248         lds.l   @r15+, pr
249         mov.l   @r15+,r15
250         rte
251          nop
252         .align  2
253 1:      .long   gdb_vbr_vector
254 #endif /* CONFIG_SH_STANDARD_BIOS */
255
256 ENTRY(address_error_trap_handler)
257         mov     r15,r4                          ! regs
258         mov     #OFF_PC,r0
259         mov.l   @(r0,r15),r6                    ! pc
260         mov.l   1f,r0
261         jmp     @r0
262          mov    #0,r5                           ! writeaccess is unknown
263
264         .align  2
265 1:      .long   do_address_error
266
267 restore_all:
268         stc     sr,r0
269         or      #0xf0,r0
270         ldc     r0,sr                           ! all interrupt block (same BL = 1)
271         ! restore special register
272         ! overlap exception frame
273         mov     r15,r0
274         add     #17*4,r0
275         lds.l   @r0+,pr
276         add     #4,r0
277         ldc.l   @r0+,gbr
278         lds.l   @r0+,mach
279         lds.l   @r0+,macl
280         mov     r15,r0
281         mov.l   $cpu_mode,r2
282 #ifdef CONFIG_SMP
283         mov.l   $cpuid,r3
284         mov.l   @r3,r3
285         mov.l   @r3,r3
286         shll2   r3
287         add     r3,r2
288 #endif
289         mov     #OFF_SR,r3
290         mov.l   @(r0,r3),r1
291         mov.l   __md_bit,r3
292         and     r1,r3                           ! copy MD bit
293         mov.l   r3,@r2
294         shll2   r1                              ! clear MD bit
295         shlr2   r1
296         mov.l   @(OFF_SP,r0),r2
297         add     #-8,r2
298         mov.l   r2,@(OFF_SP,r0)                 ! point exception frame top
299         mov.l   r1,@(4,r2)                      ! set sr
300         mov     #OFF_PC,r3
301         mov.l   @(r0,r3),r1
302         mov.l   r1,@r2                          ! set pc
303         get_current_thread_info r0, r1
304         mov.l   $current_thread_info,r1
305 #ifdef CONFIG_SMP
306         mov.l   $cpuid,r3
307         mov.l   @r3,r3
308         mov.l   @r3,r3
309         shll2   r3
310         add     r3,r1
311 #endif
312         mov.l   r0,@r1
313         mov.l   @r15+,r0
314         mov.l   @r15+,r1
315         mov.l   @r15+,r2
316         mov.l   @r15+,r3
317         mov.l   @r15+,r4
318         mov.l   @r15+,r5
319         mov.l   @r15+,r6
320         mov.l   @r15+,r7
321         mov.l   @r15+,r8
322         mov.l   @r15+,r9
323         mov.l   @r15+,r10
324         mov.l   @r15+,r11
325         mov.l   @r15+,r12
326         mov.l   @r15+,r13
327         mov.l   @r15+,r14
328         mov.l   @r15,r15
329         rte
330          nop
331
332         .align 2
333 __md_bit:
334         .long   0x40000000
335 $current_thread_info:
336         .long   __current_thread_info
337 $cpu_mode:      
338         .long   __cpu_mode
339 #ifdef CONFIG_SMP
340 $cpuid:
341         .long sh2_cpuid_addr
342 #endif
343                 
344 ! common exception handler
345 #include "../../entry-common.S"
346
347 #ifdef CONFIG_NR_CPUS
348 #define NR_CPUS CONFIG_NR_CPUS
349 #else
350 #define NR_CPUS 1
351 #endif
352         
353         .data
354 ! cpu operation mode 
355 ! bit30 = MD (compatible SH3/4)
356 __cpu_mode:
357         .rept   NR_CPUS
358         .long   0x40000000
359         .endr
360
361 #ifdef CONFIG_SMP
362 .global sh2_cpuid_addr
363 sh2_cpuid_addr:
364         .long   dummy_cpuid
365 dummy_cpuid:
366         .long   0
367 #endif
368                 
369         .section        .bss
370 __current_thread_info:
371         .rept   NR_CPUS
372         .long   0
373         .endr
374
375 ENTRY(exception_handling_table)
376         .space  4*32