summaryrefslogtreecommitdiff
path: root/libcpu/risc-v/common/include/asm.h
blob: 500247a57e47e2dc2a50be5ec3cd81bb4a31720d (plain)
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
/*
 * Copyright (c) 2006-2025 RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-02-02     lizhirui     first version
 * 2021-02-11     lizhirui     fixed gp save/store bug
 * 2021-11-18     JasonHu      add fpu registers save/restore
 * 2022-10-22     Shell        Support kernel mode RVV
 * 2025-04-20     GuEe-GUI     Merge 64I and 32I/E
 */

#ifndef __ASM_H__
#define __ASM_H__

#include <rtconfig.h>

#include <csr.h>
#include <stack.h>

#ifdef __GNUC__
.macro LOAD_GLOBAL_POINTER
.option push
.option norelax
    la      gp, __global_pointer$
.option pop
.endm

.macro XRET
#ifdef ARCH_RISCV_M_MODE
    mret
#else
    sret
#endif
.endm

.macro PUSH reg
    addi    sp, sp, -SZREG
    REG_S   \reg, 0(sp)
.endm

.macro POP reg
    REG_L   \reg, 0(sp)
    addi    sp, sp, SZREG
.endm

.macro OPEN_INTERRUPT
    csrsi   CSR_STATUS, 2
.endm

.macro CLOSE_INTERRUPT
    csrci   CSR_STATUS, 2
.endm

.macro SAVE_ALL
#ifdef ARCH_RISCV_FPU
    /* Reserve float registers */
    addi    sp, sp, -CTX_FPU_REG_NR * SZREG
#endif
#ifdef ARCH_RISCV_VECTOR
    /* Reserve float registers */
    addi    sp, sp, -CTX_VECTOR_REG_NR * SZREG
#endif

    /* Save general registers */
    addi    sp, sp, -CTX_GENERAL_REG_NR * SZREG
    REG_S   x1,   1 * SZREG(sp)

    csrr    x1, CSR_STATUS
    REG_S   x1, FRAME_OFF_XSTATUS(sp)

    csrr    x1, CSR_CAUSE
    REG_S   x1, FRAME_OFF_XCAUSE(sp)

    csrr    x1, CSR_EPC
    REG_S   x1,   0 * SZREG(sp)

    REG_S   x3,   4 * SZREG(sp)
    REG_S   x4,   5 * SZREG(sp)
    REG_S   x5,   6 * SZREG(sp)
    REG_S   x6,   7 * SZREG(sp)
    REG_S   x7,   8 * SZREG(sp)
    REG_S   x8,   9 * SZREG(sp)
    REG_S   x9,  10 * SZREG(sp)
    REG_S   x10, 11 * SZREG(sp)
    REG_S   x11, 12 * SZREG(sp)
    REG_S   x12, 13 * SZREG(sp)
    REG_S   x13, 14 * SZREG(sp)
    REG_S   x14, 15 * SZREG(sp)
    REG_S   x15, 16 * SZREG(sp)
#ifndef ARCH_RISCV_32E
    REG_S   x16, 17 * SZREG(sp)
    REG_S   x17, 18 * SZREG(sp)
    REG_S   x18, 19 * SZREG(sp)
    REG_S   x19, 20 * SZREG(sp)
    REG_S   x20, 21 * SZREG(sp)
    REG_S   x21, 22 * SZREG(sp)
    REG_S   x22, 23 * SZREG(sp)
    REG_S   x23, 24 * SZREG(sp)
    REG_S   x24, 25 * SZREG(sp)
    REG_S   x25, 26 * SZREG(sp)
    REG_S   x26, 27 * SZREG(sp)
    REG_S   x27, 28 * SZREG(sp)
    REG_S   x28, 29 * SZREG(sp)
    REG_S   x29, 30 * SZREG(sp)
    REG_S   x30, 31 * SZREG(sp)
    REG_S   x31, 32 * SZREG(sp)
#endif /* !ARCH_RISCV_32E */
    csrr    t0, CSR_SCRATCH
    REG_S   t0, FRAME_OFF_SP(sp)

#ifdef ARCH_RISCV_FPU
    /* Backup sp and adjust sp to save float registers */
    mv      t1, sp
    addi    t1, t1, CTX_GENERAL_REG_NR * SZREG

    li      t0, SR_FS
    csrs    CSR_STATUS, t0
    CTX_FREG_S  f0,  FPU_CTX_F0_OFF(t1)
    CTX_FREG_S  f1,  FPU_CTX_F1_OFF(t1)
    CTX_FREG_S  f2,  FPU_CTX_F2_OFF(t1)
    CTX_FREG_S  f3,  FPU_CTX_F3_OFF(t1)
    CTX_FREG_S  f4,  FPU_CTX_F4_OFF(t1)
    CTX_FREG_S  f5,  FPU_CTX_F5_OFF(t1)
    CTX_FREG_S  f6,  FPU_CTX_F6_OFF(t1)
    CTX_FREG_S  f7,  FPU_CTX_F7_OFF(t1)
    CTX_FREG_S  f8,  FPU_CTX_F8_OFF(t1)
    CTX_FREG_S  f9,  FPU_CTX_F9_OFF(t1)
    CTX_FREG_S  f10, FPU_CTX_F10_OFF(t1)
    CTX_FREG_S  f11, FPU_CTX_F11_OFF(t1)
    CTX_FREG_S  f12, FPU_CTX_F12_OFF(t1)
    CTX_FREG_S  f13, FPU_CTX_F13_OFF(t1)
    CTX_FREG_S  f14, FPU_CTX_F14_OFF(t1)
    CTX_FREG_S  f15, FPU_CTX_F15_OFF(t1)
    CTX_FREG_S  f16, FPU_CTX_F16_OFF(t1)
    CTX_FREG_S  f17, FPU_CTX_F17_OFF(t1)
    CTX_FREG_S  f18, FPU_CTX_F18_OFF(t1)
    CTX_FREG_S  f19, FPU_CTX_F19_OFF(t1)
    CTX_FREG_S  f20, FPU_CTX_F20_OFF(t1)
    CTX_FREG_S  f21, FPU_CTX_F21_OFF(t1)
    CTX_FREG_S  f22, FPU_CTX_F22_OFF(t1)
    CTX_FREG_S  f23, FPU_CTX_F23_OFF(t1)
    CTX_FREG_S  f24, FPU_CTX_F24_OFF(t1)
    CTX_FREG_S  f25, FPU_CTX_F25_OFF(t1)
    CTX_FREG_S  f26, FPU_CTX_F26_OFF(t1)
    CTX_FREG_S  f27, FPU_CTX_F27_OFF(t1)
    CTX_FREG_S  f28, FPU_CTX_F28_OFF(t1)
    CTX_FREG_S  f29, FPU_CTX_F29_OFF(t1)
    CTX_FREG_S  f30, FPU_CTX_F30_OFF(t1)
    CTX_FREG_S  f31, FPU_CTX_F31_OFF(t1)

    /* Clean FS domain */
    csrc    CSR_STATUS, t0

    /* Clean status would clr sr_sd; */
    li      t0, SR_FS_CLEAN
    csrs    CSR_STATUS, t0

#endif /* ARCH_RISCV_FPU */

#ifdef ARCH_RISCV_VECTOR
    csrr    t0, CSR_STATUS
    andi    t0, t0, SR_VS
    beqz    t0, 0f

    /* push vector frame */
    addi    t1, sp, (CTX_GENERAL_REG_NR + CTX_FPU_REG_NR) * SZREG

    SAVE_VECTOR t1
0:
#endif /* ARCH_RISCV_VECTOR */
.endm

.macro RESTORE_TP offset
#if !defined(RT_USING_SMP)
    REG_L   tp, \offset(sp)
#elif defined(ARCH_MM_MMU) && !defined(ARCH_RISCV_M_MODE)
    /* Bare SMP uses tp as a hart-local CPU ID, including interrupt returns. */
    la      t0, rt_hw_arch_vaddr_width
    lbu     t0, 0(t0)
    beqz    t0, .Lkeep_tp\@
    REG_L   tp, \offset(sp)
.Lkeep_tp\@:
#endif
.endm

.macro RESTORE_ALL
#ifdef ARCH_RISCV_VECTOR
    /* Skip on close */
    REG_L   t0, FRAME_OFF_XSTATUS(sp)
    /* Cannot use vector on initial */
    andi    t0, t0, SR_VS_CLEAN
    beqz    t0, 0f

    /* Restore vector frame */
    addi    t1, sp, (CTX_GENERAL_REG_NR + CTX_FPU_REG_NR) * SZREG

    RESTORE_VECTOR t1
0:
#endif /* ARCH_RISCV_VECTOR */

#ifdef ARCH_RISCV_FPU
    /* Restore float register  */
    addi    t2, sp, CTX_GENERAL_REG_NR * SZREG

    li      t0, SR_FS
    csrs    CSR_STATUS, t0
    CTX_FREG_L  f0,  FPU_CTX_F0_OFF(t2)
    CTX_FREG_L  f1,  FPU_CTX_F1_OFF(t2)
    CTX_FREG_L  f2,  FPU_CTX_F2_OFF(t2)
    CTX_FREG_L  f3,  FPU_CTX_F3_OFF(t2)
    CTX_FREG_L  f4,  FPU_CTX_F4_OFF(t2)
    CTX_FREG_L  f5,  FPU_CTX_F5_OFF(t2)
    CTX_FREG_L  f6,  FPU_CTX_F6_OFF(t2)
    CTX_FREG_L  f7,  FPU_CTX_F7_OFF(t2)
    CTX_FREG_L  f8,  FPU_CTX_F8_OFF(t2)
    CTX_FREG_L  f9,  FPU_CTX_F9_OFF(t2)
    CTX_FREG_L  f10, FPU_CTX_F10_OFF(t2)
    CTX_FREG_L  f11, FPU_CTX_F11_OFF(t2)
    CTX_FREG_L  f12, FPU_CTX_F12_OFF(t2)
    CTX_FREG_L  f13, FPU_CTX_F13_OFF(t2)
    CTX_FREG_L  f14, FPU_CTX_F14_OFF(t2)
    CTX_FREG_L  f15, FPU_CTX_F15_OFF(t2)
    CTX_FREG_L  f16, FPU_CTX_F16_OFF(t2)
    CTX_FREG_L  f17, FPU_CTX_F17_OFF(t2)
    CTX_FREG_L  f18, FPU_CTX_F18_OFF(t2)
    CTX_FREG_L  f19, FPU_CTX_F19_OFF(t2)
    CTX_FREG_L  f20, FPU_CTX_F20_OFF(t2)
    CTX_FREG_L  f21, FPU_CTX_F21_OFF(t2)
    CTX_FREG_L  f22, FPU_CTX_F22_OFF(t2)
    CTX_FREG_L  f23, FPU_CTX_F23_OFF(t2)
    CTX_FREG_L  f24, FPU_CTX_F24_OFF(t2)
    CTX_FREG_L  f25, FPU_CTX_F25_OFF(t2)
    CTX_FREG_L  f26, FPU_CTX_F26_OFF(t2)
    CTX_FREG_L  f27, FPU_CTX_F27_OFF(t2)
    CTX_FREG_L  f28, FPU_CTX_F28_OFF(t2)
    CTX_FREG_L  f29, FPU_CTX_F29_OFF(t2)
    CTX_FREG_L  f30, FPU_CTX_F30_OFF(t2)
    CTX_FREG_L  f31, FPU_CTX_F31_OFF(t2)

    /* Clean FS domain */
    csrc    CSR_STATUS, t0

    /* Clean status would clr sr_sd; */
    li      t0, SR_FS_CLEAN
    csrs    CSR_STATUS, t0

#endif /* ARCH_RISCV_FPU */

    /* Restore general register */
#ifndef ARCH_RISCV_USING_IRQ_STACK
    addi    t0, sp, CTX_ALL_REG_NR * SZREG
    csrw    CSR_SCRATCH, t0
#endif

    /* resw ra to CSR_EPC */
    REG_L   x1,   0 * SZREG(sp)
    csrw    CSR_EPC, x1

    REG_L   x1,   2 * SZREG(sp)
    csrw    CSR_STATUS, x1

    REG_L   x1,   1 * SZREG(sp)

    REG_L   x3,   4 * SZREG(sp)
    RESTORE_TP (5 * SZREG)
    REG_L   x5,   6 * SZREG(sp)
    REG_L   x6,   7 * SZREG(sp)
    REG_L   x7,   8 * SZREG(sp)
    REG_L   x8,   9 * SZREG(sp)
    REG_L   x9,  10 * SZREG(sp)
    REG_L   x10, 11 * SZREG(sp)
    REG_L   x11, 12 * SZREG(sp)
    REG_L   x12, 13 * SZREG(sp)
    REG_L   x13, 14 * SZREG(sp)
    REG_L   x14, 15 * SZREG(sp)
    REG_L   x15, 16 * SZREG(sp)
#ifndef ARCH_RISCV_32E
    REG_L   x16, 17 * SZREG(sp)
    REG_L   x17, 18 * SZREG(sp)
    REG_L   x18, 19 * SZREG(sp)
    REG_L   x19, 20 * SZREG(sp)
    REG_L   x20, 21 * SZREG(sp)
    REG_L   x21, 22 * SZREG(sp)
    REG_L   x22, 23 * SZREG(sp)
    REG_L   x23, 24 * SZREG(sp)
    REG_L   x24, 25 * SZREG(sp)
    REG_L   x25, 26 * SZREG(sp)
    REG_L   x26, 27 * SZREG(sp)
    REG_L   x27, 28 * SZREG(sp)
    REG_L   x28, 29 * SZREG(sp)
    REG_L   x29, 30 * SZREG(sp)
    REG_L   x30, 31 * SZREG(sp)
    REG_L   x31, 32 * SZREG(sp)
#endif /* !ARCH_RISCV_32E */

    /* Restore user sp */
    REG_L   sp, FRAME_OFF_SP(sp)
.endm
#endif /* __GNUC__ */

#endif /* __ASM_H__ */