1/*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date           Author       Notes
8 * 2023/01/17     WangShun     The first version
9 * 2023/03/19     Flyingcys    Add riscv_32e support
10 * 2023/08/09     HPMicro      Fix the issue t0 was modified unexpectedly before being saved
11 */
12#define __ASSEMBLY__
13#include "cpuport.h"
14
15    .section .text.entry, "ax"
16#if defined(SOC_SERIES_GD32VF103V)
17    .align  6
18#else
19    .align  2
20#endif
21    .global SW_handler
22
23SW_handler:
24    csrci mstatus, 0x8
25#ifdef ARCH_RISCV_FPU
26    addi    sp, sp, -32 * FREGBYTES
27    FSTORE  f0, 0 * FREGBYTES(sp)
28    FSTORE  f1, 1 * FREGBYTES(sp)
29    FSTORE  f2, 2 * FREGBYTES(sp)
30    FSTORE  f3, 3 * FREGBYTES(sp)
31    FSTORE  f4, 4 * FREGBYTES(sp)
32    FSTORE  f5, 5 * FREGBYTES(sp)
33    FSTORE  f6, 6 * FREGBYTES(sp)
34    FSTORE  f7, 7 * FREGBYTES(sp)
35    FSTORE  f8, 8 * FREGBYTES(sp)
36    FSTORE  f9, 9 * FREGBYTES(sp)
37    FSTORE  f10, 10 * FREGBYTES(sp)
38    FSTORE  f11, 11 * FREGBYTES(sp)
39    FSTORE  f12, 12 * FREGBYTES(sp)
40    FSTORE  f13, 13 * FREGBYTES(sp)
41    FSTORE  f14, 14 * FREGBYTES(sp)
42    FSTORE  f15, 15 * FREGBYTES(sp)
43    FSTORE  f16, 16 * FREGBYTES(sp)
44    FSTORE  f17, 17 * FREGBYTES(sp)
45    FSTORE  f18, 18 * FREGBYTES(sp)
46    FSTORE  f19, 19 * FREGBYTES(sp)
47    FSTORE  f20, 20 * FREGBYTES(sp)
48    FSTORE  f21, 21 * FREGBYTES(sp)
49    FSTORE  f22, 22 * FREGBYTES(sp)
50    FSTORE  f23, 23 * FREGBYTES(sp)
51    FSTORE  f24, 24 * FREGBYTES(sp)
52    FSTORE  f25, 25 * FREGBYTES(sp)
53    FSTORE  f26, 26 * FREGBYTES(sp)
54    FSTORE  f27, 27 * FREGBYTES(sp)
55    FSTORE  f28, 28 * FREGBYTES(sp)
56    FSTORE  f29, 29 * FREGBYTES(sp)
57    FSTORE  f30, 30 * FREGBYTES(sp)
58    FSTORE  f31, 31 * FREGBYTES(sp)
59#endif
60    /* save all from thread context */
61#ifndef __riscv_32e
62    addi sp, sp, -32 * REGBYTES
63#else
64    addi sp, sp, -16 * REGBYTES
65#endif
66    STORE x5,   5 * REGBYTES(sp)
67    STORE x1,   1 * REGBYTES(sp)
68    /* Mandatory set the MPIE of mstatus */
69    li    t0,   0x80
70    STORE t0,   2 * REGBYTES(sp)
71    STORE x4,   4 * REGBYTES(sp)
72    STORE x6,   6 * REGBYTES(sp)
73    STORE x7,   7 * REGBYTES(sp)
74    STORE x8,   8 * REGBYTES(sp)
75    STORE x9,   9 * REGBYTES(sp)
76    STORE x10, 10 * REGBYTES(sp)
77    STORE x11, 11 * REGBYTES(sp)
78    STORE x12, 12 * REGBYTES(sp)
79    STORE x13, 13 * REGBYTES(sp)
80    STORE x14, 14 * REGBYTES(sp)
81    STORE x15, 15 * REGBYTES(sp)
82#ifndef __riscv_32e
83    STORE x16, 16 * REGBYTES(sp)
84    STORE x17, 17 * REGBYTES(sp)
85    STORE x18, 18 * REGBYTES(sp)
86    STORE x19, 19 * REGBYTES(sp)
87    STORE x20, 20 * REGBYTES(sp)
88    STORE x21, 21 * REGBYTES(sp)
89    STORE x22, 22 * REGBYTES(sp)
90    STORE x23, 23 * REGBYTES(sp)
91    STORE x24, 24 * REGBYTES(sp)
92    STORE x25, 25 * REGBYTES(sp)
93    STORE x26, 26 * REGBYTES(sp)
94    STORE x27, 27 * REGBYTES(sp)
95    STORE x28, 28 * REGBYTES(sp)
96    STORE x29, 29 * REGBYTES(sp)
97    STORE x30, 30 * REGBYTES(sp)
98    STORE x31, 31 * REGBYTES(sp)
99#endif
100    /* switch to interrupt stack */
101    csrrw sp,mscratch,sp
102    /* interrupt handle */
103    call  rt_interrupt_enter
104    /* Do the work after saving the above */
105    jal   rt_hw_do_after_save_above
106
107    call  rt_interrupt_leave
108    /* switch to from thread stack */
109    csrrw sp,mscratch,sp
110
111    /* Determine whether to trigger scheduling at the interrupt function */
112    la    t0, rt_thread_switch_interrupt_flag
113    lw    t2, 0(t0)
114    beqz  t2, 1f
115    /* clear the flag of rt_thread_switch_interrupt_flag */
116    sw    zero, 0(t0)
117
118    csrr  a0, mepc
119    STORE a0, 0 * REGBYTES(sp)
120
121    la    t0, rt_interrupt_from_thread
122    LOAD  t1, 0(t0)
123    STORE sp, 0(t1)
124
125    la    t0, rt_interrupt_to_thread
126    LOAD  t1, 0(t0)
127    LOAD  sp, 0(t1)
128
129    LOAD  a0,  0 * REGBYTES(sp)
130    csrw  mepc, a0
131
1321:
133    LOAD  x1,   1 * REGBYTES(sp)
134
135    /* Set the mode after MRET */
136    li    t0, 0x1800
137    csrs  mstatus, t0
138    LOAD  t0,   2 * REGBYTES(sp)
139    csrs  mstatus, t0
140
141    LOAD  x4,   4 * REGBYTES(sp)
142    LOAD  x5,   5 * REGBYTES(sp)
143    LOAD  x6,   6 * REGBYTES(sp)
144    LOAD  x7,   7 * REGBYTES(sp)
145    LOAD  x8,   8 * REGBYTES(sp)
146    LOAD  x9,   9 * REGBYTES(sp)
147    LOAD  x10, 10 * REGBYTES(sp)
148    LOAD  x11, 11 * REGBYTES(sp)
149    LOAD  x12, 12 * REGBYTES(sp)
150    LOAD  x13, 13 * REGBYTES(sp)
151    LOAD  x14, 14 * REGBYTES(sp)
152    LOAD  x15, 15 * REGBYTES(sp)
153#ifndef __riscv_32e
154    LOAD  x16, 16 * REGBYTES(sp)
155    LOAD  x17, 17 * REGBYTES(sp)
156    LOAD  x18, 18 * REGBYTES(sp)
157    LOAD  x19, 19 * REGBYTES(sp)
158    LOAD  x20, 20 * REGBYTES(sp)
159    LOAD  x21, 21 * REGBYTES(sp)
160    LOAD  x22, 22 * REGBYTES(sp)
161    LOAD  x23, 23 * REGBYTES(sp)
162    LOAD  x24, 24 * REGBYTES(sp)
163    LOAD  x25, 25 * REGBYTES(sp)
164    LOAD  x26, 26 * REGBYTES(sp)
165    LOAD  x27, 27 * REGBYTES(sp)
166    LOAD  x28, 28 * REGBYTES(sp)
167    LOAD  x29, 29 * REGBYTES(sp)
168    LOAD  x30, 30 * REGBYTES(sp)
169    LOAD  x31, 31 * REGBYTES(sp)
170
171    addi  sp, sp, 32 * REGBYTES
172#else
173    addi  sp, sp, 16 * REGBYTES
174#endif
175
176#ifdef ARCH_RISCV_FPU
177    FLOAD   f0, 0 * FREGBYTES(sp)
178    FLOAD   f1, 1 * FREGBYTES(sp)
179    FLOAD   f2, 2 * FREGBYTES(sp)
180    FLOAD   f3, 3 * FREGBYTES(sp)
181    FLOAD   f4, 4 * FREGBYTES(sp)
182    FLOAD   f5, 5 * FREGBYTES(sp)
183    FLOAD   f6, 6 * FREGBYTES(sp)
184    FLOAD   f7, 7 * FREGBYTES(sp)
185    FLOAD   f8, 8 * FREGBYTES(sp)
186    FLOAD   f9, 9 * FREGBYTES(sp)
187    FLOAD   f10, 10 * FREGBYTES(sp)
188    FLOAD   f11, 11 * FREGBYTES(sp)
189    FLOAD   f12, 12 * FREGBYTES(sp)
190    FLOAD   f13, 13 * FREGBYTES(sp)
191    FLOAD   f14, 14 * FREGBYTES(sp)
192    FLOAD   f15, 15 * FREGBYTES(sp)
193    FLOAD   f16, 16 * FREGBYTES(sp)
194    FLOAD   f17, 17 * FREGBYTES(sp)
195    FLOAD   f18, 18 * FREGBYTES(sp)
196    FLOAD   f19, 19 * FREGBYTES(sp)
197    FLOAD   f20, 20 * FREGBYTES(sp)
198    FLOAD   f21, 21 * FREGBYTES(sp)
199    FLOAD   f22, 22 * FREGBYTES(sp)
200    FLOAD   f23, 23 * FREGBYTES(sp)
201    FLOAD   f24, 24 * FREGBYTES(sp)
202    FLOAD   f25, 25 * FREGBYTES(sp)
203    FLOAD   f26, 26 * FREGBYTES(sp)
204    FLOAD   f27, 27 * FREGBYTES(sp)
205    FLOAD   f28, 28 * FREGBYTES(sp)
206    FLOAD   f29, 29 * FREGBYTES(sp)
207    FLOAD   f30, 30 * FREGBYTES(sp)
208    FLOAD   f31, 31 * FREGBYTES(sp)
209
210    addi    sp, sp, 32 * FREGBYTES
211#endif
212    mret
213
214
215  .section      .text.trap_entry
216  .align 2
217  .weak trap_entry
218  .global trap_entry
219trap_entry:
220#ifdef ARCH_RISCV_FPU
221    addi    sp, sp, -32 * FREGBYTES
222
223    FSTORE  f0, 0 * FREGBYTES(sp)
224    FSTORE  f1, 1 * FREGBYTES(sp)
225    FSTORE  f2, 2 * FREGBYTES(sp)
226    FSTORE  f3, 3 * FREGBYTES(sp)
227    FSTORE  f4, 4 * FREGBYTES(sp)
228    FSTORE  f5, 5 * FREGBYTES(sp)
229    FSTORE  f6, 6 * FREGBYTES(sp)
230    FSTORE  f7, 7 * FREGBYTES(sp)
231    FSTORE  f8, 8 * FREGBYTES(sp)
232    FSTORE  f9, 9 * FREGBYTES(sp)
233    FSTORE  f10, 10 * FREGBYTES(sp)
234    FSTORE  f11, 11 * FREGBYTES(sp)
235    FSTORE  f12, 12 * FREGBYTES(sp)
236    FSTORE  f13, 13 * FREGBYTES(sp)
237    FSTORE  f14, 14 * FREGBYTES(sp)
238    FSTORE  f15, 15 * FREGBYTES(sp)
239    FSTORE  f16, 16 * FREGBYTES(sp)
240    FSTORE  f17, 17 * FREGBYTES(sp)
241    FSTORE  f18, 18 * FREGBYTES(sp)
242    FSTORE  f19, 19 * FREGBYTES(sp)
243    FSTORE  f20, 20 * FREGBYTES(sp)
244    FSTORE  f21, 21 * FREGBYTES(sp)
245    FSTORE  f22, 22 * FREGBYTES(sp)
246    FSTORE  f23, 23 * FREGBYTES(sp)
247    FSTORE  f24, 24 * FREGBYTES(sp)
248    FSTORE  f25, 25 * FREGBYTES(sp)
249    FSTORE  f26, 26 * FREGBYTES(sp)
250    FSTORE  f27, 27 * FREGBYTES(sp)
251    FSTORE  f28, 28 * FREGBYTES(sp)
252    FSTORE  f29, 29 * FREGBYTES(sp)
253    FSTORE  f30, 30 * FREGBYTES(sp)
254    FSTORE  f31, 31 * FREGBYTES(sp)
255
256#endif
257
258    /* save thread context to thread stack */
259#ifndef __riscv_32e
260    addi sp, sp, -32 * REGBYTES
261#else
262    addi sp, sp, -16 * REGBYTES
263#endif
264    STORE x1,   1 * REGBYTES(sp)
265
266    csrr  x1, mstatus
267    STORE x1,   2 * REGBYTES(sp)
268
269    csrr  x1, mepc
270    STORE x1, 0 * REGBYTES(sp)
271
272    STORE x4,   4 * REGBYTES(sp)
273    STORE x5,   5 * REGBYTES(sp)
274    STORE x6,   6 * REGBYTES(sp)
275    STORE x7,   7 * REGBYTES(sp)
276    STORE x8,   8 * REGBYTES(sp)
277    STORE x9,   9 * REGBYTES(sp)
278    STORE x10, 10 * REGBYTES(sp)
279    STORE x11, 11 * REGBYTES(sp)
280    STORE x12, 12 * REGBYTES(sp)
281    STORE x13, 13 * REGBYTES(sp)
282    STORE x14, 14 * REGBYTES(sp)
283    STORE x15, 15 * REGBYTES(sp)
284#ifndef __riscv_32e
285    STORE x16, 16 * REGBYTES(sp)
286    STORE x17, 17 * REGBYTES(sp)
287    STORE x18, 18 * REGBYTES(sp)
288    STORE x19, 19 * REGBYTES(sp)
289    STORE x20, 20 * REGBYTES(sp)
290    STORE x21, 21 * REGBYTES(sp)
291    STORE x22, 22 * REGBYTES(sp)
292    STORE x23, 23 * REGBYTES(sp)
293    STORE x24, 24 * REGBYTES(sp)
294    STORE x25, 25 * REGBYTES(sp)
295    STORE x26, 26 * REGBYTES(sp)
296    STORE x27, 27 * REGBYTES(sp)
297    STORE x28, 28 * REGBYTES(sp)
298    STORE x29, 29 * REGBYTES(sp)
299    STORE x30, 30 * REGBYTES(sp)
300    STORE x31, 31 * REGBYTES(sp)
301#endif
302
303    /* switch to interrupt stack */
304    move  s0, sp
305
306#ifdef RT_USING_SMP
307    /* get cpu id */
308    csrr  t0, mhartid
309
310    /* switch interrupt stack of current cpu */
311    la    sp, __stack_start__
312    addi  t1, t0, 1
313    li    t2, __STACKSIZE__
314    mul   t1, t1, t2
315    add   sp, sp, t1 /* sp = (cpuid + 1) * __STACKSIZE__ + __stack_start__ */
316#endif
317
318    /* handle interrupt */
319    call  rt_interrupt_enter
320    csrr  a0, mcause
321    csrr  a1, mepc
322    mv    a2, s0
323    call  handle_trap
324    call  rt_interrupt_leave
325
326#ifdef RT_USING_SMP
327    /* s0 --> sp */
328    mv  sp, s0
329    mv  a0, s0
330    call rt_scheduler_do_irq_switch
331    tail   rt_hw_context_switch_exit
332
333#else
334
335    /* switch to from_thread stack */
336    move  sp, s0
337
338    /* need to switch new thread */
339    la    s0, rt_thread_switch_interrupt_flag
340    lw    s1, 0(s0)
341    beqz  s1, spurious_interrupt
342    sw    zero, 0(s0)
343
344    la    s0, rt_interrupt_from_thread
345    LOAD  s1, 0(s0)
346    STORE sp, 0(s1)
347
348    la    s0, rt_interrupt_to_thread
349    LOAD  s1, 0(s0)
350    LOAD  sp, 0(s1)
351
352#endif
353
354spurious_interrupt:
355    tail rt_hw_context_switch_exit
356