Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / arch / sh / kernel / cpu / sh2a / entry.S
1 /* SPDX-License-Identifier: GPL-2.0
2  *
3  * arch/sh/kernel/cpu/sh2a/entry.S
4  *
5  * The SH-2A exception entry
6  *
7  * Copyright (C) 2008 Yoshinori Sato
8  * Based on arch/sh/kernel/cpu/sh2/entry.S
9  */
10
11 #include <linux/linkage.h>
12 #include <asm/asm-offsets.h>
13 #include <asm/thread_info.h>
14 #include <cpu/mmu_context.h>
15 #include <asm/unistd.h>
16 #include <asm/errno.h>
17 #include <asm/page.h>
18         
19 /* Offsets to the stack */
20 OFF_R0  =  0            /* Return value. New ABI also arg4 */
21 OFF_R1  =  4            /* New ABI: arg5 */
22 OFF_R2  =  8            /* New ABI: arg6 */
23 OFF_R3  =  12           /* New ABI: syscall_nr */
24 OFF_R4  =  16           /* New ABI: arg0 */
25 OFF_R5  =  20           /* New ABI: arg1 */
26 OFF_R6  =  24           /* New ABI: arg2 */
27 OFF_R7  =  28           /* New ABI: arg3 */
28 OFF_SP  =  (15*4)
29 OFF_PC  =  (16*4)
30 OFF_SR  =  (16*4+2*4)
31 OFF_TRA =  (16*4+6*4)
32
33 #include <asm/entry-macros.S>
34
35 ENTRY(exception_handler)
36         ! stack
37         ! r0 <- point sp
38         ! r1
39         ! pc
40         ! sr
41         ! r0 = temporary
42         ! r1 = vector (pseudo EXPEVT / INTEVT / TRA)
43         mov.l   r2,@-sp
44         cli
45         mov.l   $cpu_mode,r2
46         bld.b   #6,@(0,r2)      !previus SR.MD
47         bst.b   #6,@(4*4,r15)   !set cpu mode to SR.MD
48         bt      1f
49         ! switch to kernel mode
50         bset.b  #6,@(0,r2)      !set SR.MD
51         mov.l   $current_thread_info,r2
52         mov.l   @r2,r2
53         mov     #(THREAD_SIZE >> 8),r0
54         shll8   r0
55         add     r2,r0           ! r0 = kernel stack tail
56         mov     r15,r2          ! r2 = user stack top
57         mov     r0,r15          ! switch kernel stack
58         mov.l   r1,@-r15        ! TRA
59         sts.l   macl, @-r15
60         sts.l   mach, @-r15
61         stc.l   gbr, @-r15
62         mov.l   @(4*4,r2),r0
63         mov.l   r0,@-r15        ! original SR
64         sts.l   pr,@-r15
65         mov.l   @(3*4,r2),r0
66         mov.l   r0,@-r15        ! original PC
67         mov     r2,r0
68         add     #(3+2)*4,r0     ! rewind r0 - r3 + exception frame
69         lds     r0,pr           ! pr = original SP
70         movmu.l r3,@-r15        ! save regs
71         mov     r2,r8           ! r8 =  previus stack top
72         mov     r1,r9           ! r9 = interrupt vector
73         ! restore previous stack
74         mov.l   @r8+,r2
75         mov.l   @r8+,r0
76         mov.l   @r8+,r1
77         bra     2f
78          movml.l r2,@-r15
79 1:
80         ! in kernel exception
81         mov     r15,r2
82         add     #-((OFF_TRA + 4) - OFF_PC) + 5*4,r15
83         movmu.l r3,@-r15
84         mov     r2,r8           ! r8 = previous stack top
85         mov     r1,r9           ! r9 = interrupt vector
86         ! restore exception frame & regs
87         mov.l   @r8+,r2         ! old R2
88         mov.l   @r8+,r0         ! old R0
89         mov.l   @r8+,r1         ! old R1
90         mov.l   @r8+,r10        ! old PC
91         mov.l   @r8+,r11        ! old SR
92         movml.l r2,@-r15
93         mov.l   r10,@(OFF_PC,r15)
94         mov.l   r11,@(OFF_SR,r15)
95         mov.l   r8,@(OFF_SP,r15)        ! save old sp
96         mov     r15,r8
97         add     #OFF_TRA + 4,r8
98         mov.l   r9,@-r8
99         sts.l   macl,@-r8
100         sts.l   mach,@-r8
101         stc.l   gbr,@-r8
102         add     #-4,r8
103         sts.l   pr,@-r8
104 2:
105         ! dispatch exception / interrupt
106         mov     #64,r8
107         cmp/hs  r8,r9
108         bt      interrupt_entry ! vec >= 64 is interrupt
109         mov     #31,r8
110         cmp/hs  r8,r9
111         bt      trap_entry      ! 64 > vec >= 31  is trap
112
113         mov.l   4f,r8
114         mov     r9,r4
115         shll2   r9
116         add     r9,r8
117         mov.l   @r8,r8          ! exception handler address
118         tst     r8,r8
119         bf      3f
120         mov.l   8f,r8           ! unhandled exception
121 3:
122         mov.l   5f,r10
123         jmp     @r8
124          lds    r10,pr
125
126 interrupt_entry:
127         mov     r9,r4
128         mov     r15,r5
129         mov.l   7f,r8
130         mov.l   6f,r9
131         jmp     @r8
132          lds    r9,pr
133
134         .align  2
135 4:      .long   exception_handling_table
136 5:      .long   ret_from_exception
137 6:      .long   ret_from_irq
138 7:      .long   do_IRQ
139 8:      .long   exception_error
140
141 trap_entry:
142         mov     #0x30,r8
143         cmp/ge  r8,r9           ! vector 0x1f-0x2f is systemcall
144         bt      1f
145         mov     #0x1f,r9        ! convert to unified SH2/3/4 trap number
146 1:      
147         shll2   r9                      ! TRA
148         bra     system_call     ! jump common systemcall entry
149          mov    r9,r8
150         
151 #if defined(CONFIG_SH_STANDARD_BIOS)
152         /* Unwind the stack and jmp to the debug entry */
153 ENTRY(sh_bios_handler)
154         mov     r15,r0
155         add     #(22-4)*4-4,r0
156         ldc.l   @r0+,gbr
157         lds.l   @r0+,mach
158         lds.l   @r0+,macl
159         mov     r15,r0
160         mov.l   @(OFF_SP,r0),r1
161         mov.l   @(OFF_SR,r2),r3
162         mov.l   r3,@-r1
163         mov.l   @(OFF_SP,r2),r3
164         mov.l   r3,@-r1
165         mov     r15,r0
166         add     #(22-4)*4-8,r0
167         mov.l   1f,r2
168         mov.l   @r2,r2
169         stc     sr,r3
170         mov.l   r2,@r0
171         mov.l   r3,@(4,r0)
172         mov.l   r1,@(8,r0)
173         movml.l @r15+,r14
174         add     #8,r15
175         lds.l   @r15+, pr
176         mov.l   @r15+,r15
177         rte
178          nop
179         .align  2
180 1:      .long   gdb_vbr_vector
181 #endif /* CONFIG_SH_STANDARD_BIOS */
182
183 ENTRY(address_error_trap_handler)
184         mov     r15,r4                          ! regs
185         mov.l   @(OFF_PC,r15),r6                ! pc
186         mov.l   1f,r0
187         jmp     @r0
188          mov    #0,r5                           ! writeaccess is unknown
189
190         .align  2
191 1:      .long   do_address_error
192
193 restore_all:
194         stc     sr,r0
195         or      #0xf0,r0
196         ldc     r0,sr                           ! all interrupt block (same BL = 1)
197         ! restore special register
198         ! overlap exception frame
199         mov     r15,r0
200         add     #17*4,r0
201         lds.l   @r0+,pr
202         add     #4,r0
203         ldc.l   @r0+,gbr
204         lds.l   @r0+,mach
205         lds.l   @r0+,macl
206         mov     r15,r0
207         mov.l   $cpu_mode,r2
208         bld.b   #6,@(OFF_SR,r15)
209         bst.b   #6,@(0,r2)                      ! save CPU mode
210         mov.l   @(OFF_SR,r0),r1
211         shll2   r1
212         shlr2   r1                              ! clear MD bit
213         mov.l   @(OFF_SP,r0),r2
214         add     #-8,r2
215         mov.l   r2,@(OFF_SP,r0)                 ! point exception frame top
216         mov.l   r1,@(4,r2)                      ! set sr
217         mov.l   @(OFF_PC,r0),r1
218         mov.l   r1,@r2                          ! set pc
219         get_current_thread_info r0, r1
220         mov.l   $current_thread_info,r1
221         mov.l   r0,@r1
222         movml.l @r15+,r14
223         mov.l   @r15,r15
224         rte
225          nop
226
227         .align 2
228 $current_thread_info:
229         .long   __current_thread_info
230 $cpu_mode:      
231         .long   __cpu_mode
232                 
233 ! common exception handler
234 #include "../../entry-common.S"
235         
236         .data
237 ! cpu operation mode 
238 ! bit30 = MD (compatible SH3/4)
239 __cpu_mode:
240         .long   0x40000000
241                 
242         .section        .bss
243 __current_thread_info:
244         .long   0
245
246 ENTRY(exception_handling_table)
247         .space  4*32