NMSIS-Core  Version 1.2.0
NMSIS-Core support for Nuclei processor-based devices
core_feature_fpu.h
1 /*
2  * Copyright (c) 2019 Nuclei Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Licensed under the Apache License, Version 2.0 (the License); you may
7  * not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 #ifndef __CORE_FEATURE_FPU_H__
19 #define __CORE_FEATURE_FPU_H__
20 
24 /*
25  * FPU Feature Configuration Macro:
26  * 1. __FPU_PRESENT: Define whether Floating Point Unit(FPU) is present or not
27  * * 0: Not present
28  * * 1: Single precision FPU present, __RISCV_FLEN == 32
29  * * 2: Double precision FPU present, __RISCV_FLEN == 64
30  */
31 #ifdef __cplusplus
32  extern "C" {
33 #endif
34 
35 #include "core_feature_base.h"
36 
37 /* ===== FPU Operations ===== */
55 #if defined(__FPU_PRESENT) && (__FPU_PRESENT > 0)
56 
57 #if __FPU_PRESENT == 1
58 
59  #define __RISCV_FLEN 32
60 #elif __FPU_PRESENT == 2
61  #define __RISCV_FLEN 64
62 #else
63  #define __RISCV_FLEN __riscv_flen
64 #endif /* __FPU_PRESENT == 1 */
65 
67 #define __get_FCSR() __RV_CSR_READ(CSR_FCSR)
68 
69 #define __set_FCSR(val) __RV_CSR_WRITE(CSR_FCSR, (val))
70 
71 #define __get_FRM() __RV_CSR_READ(CSR_FRM)
72 
73 #define __set_FRM(val) __RV_CSR_WRITE(CSR_FRM, (val))
74 
75 #define __get_FFLAGS() __RV_CSR_READ(CSR_FFLAGS)
76 
77 #define __set_FFLAGS(val) __RV_CSR_WRITE(CSR_FFLAGS, (val))
78 
80 #define __enable_FPU() { __RV_CSR_CLEAR(CSR_MSTATUS, MSTATUS_FS); \
81  __RV_CSR_SET(CSR_MSTATUS, MSTATUS_FS_INITIAL); \
82  }
83 
90 #define __disable_FPU() __RV_CSR_CLEAR(CSR_MSTATUS, MSTATUS_FS)
91 
92 
107 #define __RV_FLW(freg, addr, ofs) \
108  ({ \
109  rv_csr_t __addr = (rv_csr_t)(addr); \
110  __ASM volatile("flw " STRINGIFY(freg) ", %0(%1) " \
111  : : "I"(ofs), "r"(__addr) \
112  : "memory"); \
113  })
114 
128 #define __RV_FSW(freg, addr, ofs) \
129  ({ \
130  rv_csr_t __addr = (rv_csr_t)(addr); \
131  __ASM volatile("fsw " STRINGIFY(freg) ", %0(%1) " \
132  : : "I"(ofs), "r"(__addr) \
133  : "memory"); \
134  })
135 
151 #define __RV_FLD(freg, addr, ofs) \
152  ({ \
153  rv_csr_t __addr = (rv_csr_t)(addr); \
154  __ASM volatile("fld " STRINGIFY(freg) ", %0(%1) " \
155  : : "I"(ofs), "r"(__addr) \
156  : "memory"); \
157  })
158 
174 #define __RV_FSD(freg, addr, ofs) \
175  ({ \
176  rv_csr_t __addr = (rv_csr_t)(addr); \
177  __ASM volatile("fsd " STRINGIFY(freg) ", %0(%1) " \
178  : : "I"(ofs), "r"(__addr) \
179  : "memory"); \
180  })
181 
206 #if __FPU_PRESENT == 1
207 #define __RV_FLOAD __RV_FLW
208 #define __RV_FSTORE __RV_FSW
209 
210 typedef uint32_t rv_fpu_t;
211 #elif __FPU_PRESENT == 2
212 #define __RV_FLOAD __RV_FLD
213 #define __RV_FSTORE __RV_FSD
214 
215 typedef uint64_t rv_fpu_t;
216 #endif /* __FPU_PRESENT == 2 */
217 
247 #define SAVE_FPU_CONTEXT() \
248  rv_fpu_t __fpu_context[20]; \
249  __RV_FSTORE(FREG(0), __fpu_context, 0 << LOG_FPREGBYTES); \
250  __RV_FSTORE(FREG(1), __fpu_context, 1 << LOG_FPREGBYTES); \
251  __RV_FSTORE(FREG(2), __fpu_context, 2 << LOG_FPREGBYTES); \
252  __RV_FSTORE(FREG(3), __fpu_context, 3 << LOG_FPREGBYTES); \
253  __RV_FSTORE(FREG(4), __fpu_context, 4 << LOG_FPREGBYTES); \
254  __RV_FSTORE(FREG(5), __fpu_context, 5 << LOG_FPREGBYTES); \
255  __RV_FSTORE(FREG(6), __fpu_context, 6 << LOG_FPREGBYTES); \
256  __RV_FSTORE(FREG(7), __fpu_context, 7 << LOG_FPREGBYTES); \
257  __RV_FSTORE(FREG(10), __fpu_context, 8 << LOG_FPREGBYTES); \
258  __RV_FSTORE(FREG(11), __fpu_context, 9 << LOG_FPREGBYTES); \
259  __RV_FSTORE(FREG(12), __fpu_context, 10 << LOG_FPREGBYTES); \
260  __RV_FSTORE(FREG(13), __fpu_context, 11 << LOG_FPREGBYTES); \
261  __RV_FSTORE(FREG(14), __fpu_context, 12 << LOG_FPREGBYTES); \
262  __RV_FSTORE(FREG(15), __fpu_context, 13 << LOG_FPREGBYTES); \
263  __RV_FSTORE(FREG(16), __fpu_context, 14 << LOG_FPREGBYTES); \
264  __RV_FSTORE(FREG(17), __fpu_context, 15 << LOG_FPREGBYTES); \
265  __RV_FSTORE(FREG(28), __fpu_context, 16 << LOG_FPREGBYTES); \
266  __RV_FSTORE(FREG(29), __fpu_context, 17 << LOG_FPREGBYTES); \
267  __RV_FSTORE(FREG(30), __fpu_context, 18 << LOG_FPREGBYTES); \
268  __RV_FSTORE(FREG(31), __fpu_context, 19 << LOG_FPREGBYTES);
269 
278 #define RESTORE_FPU_CONTEXT() \
279  __RV_FLOAD(FREG(0), __fpu_context, 0 << LOG_FPREGBYTES); \
280  __RV_FLOAD(FREG(1), __fpu_context, 1 << LOG_FPREGBYTES); \
281  __RV_FLOAD(FREG(2), __fpu_context, 2 << LOG_FPREGBYTES); \
282  __RV_FLOAD(FREG(3), __fpu_context, 3 << LOG_FPREGBYTES); \
283  __RV_FLOAD(FREG(4), __fpu_context, 4 << LOG_FPREGBYTES); \
284  __RV_FLOAD(FREG(5), __fpu_context, 5 << LOG_FPREGBYTES); \
285  __RV_FLOAD(FREG(6), __fpu_context, 6 << LOG_FPREGBYTES); \
286  __RV_FLOAD(FREG(7), __fpu_context, 7 << LOG_FPREGBYTES); \
287  __RV_FLOAD(FREG(10), __fpu_context, 8 << LOG_FPREGBYTES); \
288  __RV_FLOAD(FREG(11), __fpu_context, 9 << LOG_FPREGBYTES); \
289  __RV_FLOAD(FREG(12), __fpu_context, 10 << LOG_FPREGBYTES); \
290  __RV_FLOAD(FREG(13), __fpu_context, 11 << LOG_FPREGBYTES); \
291  __RV_FLOAD(FREG(14), __fpu_context, 12 << LOG_FPREGBYTES); \
292  __RV_FLOAD(FREG(15), __fpu_context, 13 << LOG_FPREGBYTES); \
293  __RV_FLOAD(FREG(16), __fpu_context, 14 << LOG_FPREGBYTES); \
294  __RV_FLOAD(FREG(17), __fpu_context, 15 << LOG_FPREGBYTES); \
295  __RV_FLOAD(FREG(28), __fpu_context, 16 << LOG_FPREGBYTES); \
296  __RV_FLOAD(FREG(29), __fpu_context, 17 << LOG_FPREGBYTES); \
297  __RV_FLOAD(FREG(30), __fpu_context, 18 << LOG_FPREGBYTES); \
298  __RV_FLOAD(FREG(31), __fpu_context, 19 << LOG_FPREGBYTES);
299 #else
300 #define SAVE_FPU_CONTEXT()
301 #define RESTORE_FPU_CONTEXT()
302 #endif /* __FPU_PRESENT > 0 */
303  /* End of Doxygen Group NMSIS_Core_FPU_Functions */
304 
305 #ifdef __cplusplus
306 }
307 #endif
308 #endif /* __CORE_FEATURE_FPU_H__ */
rv_fpu_t
uint64_t rv_fpu_t
Type of FPU register, depends on the FLEN defined in RISC-V.
Definition: core_feature_fpu.h:215