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