1 /*
2  * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef _FLOAT_REGS_XTENSA_H
8 #define _FLOAT_REGS_XTENSA_H
9 
10 #include <zephyr/toolchain.h>
11 #include "float_context.h"
12 
13 /**
14  *
15  * @brief Load all floating point registers
16  *
17  * This function loads ALL floating point registers pointed to by @a regs.
18  * It is expected that a subsequent call to _store_all_float_registers()
19  * will be issued to dump the floating point registers to memory.
20  *
21  * The format/organization of 'struct fp_register_set'; the generic C test
22  * code (main.c) merely treat the register set as an array of bytes.
23  *
24  * The only requirement is that the arch specific implementations of
25  * _load_all_float_registers() and _store_all_float_registers() agree
26  * on the format.
27  *
28  */
_load_all_float_registers(struct fp_register_set * regs)29 static inline void _load_all_float_registers(struct fp_register_set *regs)
30 {
31 	__asm__ volatile("wfr f0, %0\n" :: "r"(regs->fp_non_volatile.reg[0]));
32 	__asm__ volatile("wfr f1, %0\n" :: "r"(regs->fp_non_volatile.reg[1]));
33 	__asm__ volatile("wfr f2, %0\n" :: "r"(regs->fp_non_volatile.reg[2]));
34 	__asm__ volatile("wfr f3, %0\n" :: "r"(regs->fp_non_volatile.reg[3]));
35 	__asm__ volatile("wfr f4, %0\n" :: "r"(regs->fp_non_volatile.reg[4]));
36 	__asm__ volatile("wfr f5, %0\n" :: "r"(regs->fp_non_volatile.reg[5]));
37 	__asm__ volatile("wfr f6, %0\n" :: "r"(regs->fp_non_volatile.reg[6]));
38 	__asm__ volatile("wfr f7, %0\n" :: "r"(regs->fp_non_volatile.reg[7]));
39 	__asm__ volatile("wfr f8, %0\n" :: "r"(regs->fp_non_volatile.reg[8]));
40 	__asm__ volatile("wfr f9, %0\n" :: "r"(regs->fp_non_volatile.reg[9]));
41 	__asm__ volatile("wfr f10, %0\n" :: "r"(regs->fp_non_volatile.reg[10]));
42 	__asm__ volatile("wfr f11, %0\n" :: "r"(regs->fp_non_volatile.reg[11]));
43 	__asm__ volatile("wfr f12, %0\n" :: "r"(regs->fp_non_volatile.reg[12]));
44 	__asm__ volatile("wfr f13, %0\n" :: "r"(regs->fp_non_volatile.reg[13]));
45 	__asm__ volatile("wfr f14, %0\n" :: "r"(regs->fp_non_volatile.reg[14]));
46 	__asm__ volatile("wfr f15, %0\n" :: "r"(regs->fp_non_volatile.reg[15]));
47 	__asm__ volatile("wur.fsr %0\n" :: "r"(regs->fp_non_volatile.reg[16]));
48 	__asm__ volatile("wur.fcr %0\n" :: "r"(regs->fp_non_volatile.reg[17]));
49 }
50 
51 /**
52  *
53  * @brief Dump all floating point registers to memory
54  *
55  * This function stores ALL floating point registers to the memory buffer
56  * specified by @a regs. It is expected that a previous invocation of
57  * _load_all_float_registers() occurred to load all the floating point
58  * registers from a memory buffer.
59  *
60  */
61 
_store_all_float_registers(struct fp_register_set * regs)62 static inline void _store_all_float_registers(struct fp_register_set *regs)
63 {
64 	__asm__ volatile("rfr %0, f0\n" : "=r"(regs->fp_non_volatile.reg[0]));
65 	__asm__ volatile("rfr %0, f1\n" : "=r"(regs->fp_non_volatile.reg[1]));
66 	__asm__ volatile("rfr %0, f2\n" : "=r"(regs->fp_non_volatile.reg[2]));
67 	__asm__ volatile("rfr %0, f3\n" : "=r"(regs->fp_non_volatile.reg[3]));
68 	__asm__ volatile("rfr %0, f4\n" : "=r"(regs->fp_non_volatile.reg[4]));
69 	__asm__ volatile("rfr %0, f5\n" : "=r"(regs->fp_non_volatile.reg[5]));
70 	__asm__ volatile("rfr %0, f6\n" : "=r"(regs->fp_non_volatile.reg[6]));
71 	__asm__ volatile("rfr %0, f7\n" : "=r"(regs->fp_non_volatile.reg[7]));
72 	__asm__ volatile("rfr %0, f8\n" : "=r"(regs->fp_non_volatile.reg[8]));
73 	__asm__ volatile("rfr %0, f9\n" : "=r"(regs->fp_non_volatile.reg[9]));
74 	__asm__ volatile("rfr %0, f10\n" : "=r"(regs->fp_non_volatile.reg[10]));
75 	__asm__ volatile("rfr %0, f11\n" : "=r"(regs->fp_non_volatile.reg[11]));
76 	__asm__ volatile("rfr %0, f12\n" : "=r"(regs->fp_non_volatile.reg[12]));
77 	__asm__ volatile("rfr %0, f13\n" : "=r"(regs->fp_non_volatile.reg[13]));
78 	__asm__ volatile("rfr %0, f14\n" : "=r"(regs->fp_non_volatile.reg[14]));
79 	__asm__ volatile("rfr %0, f15\n" : "=r"(regs->fp_non_volatile.reg[15]));
80 	__asm__ volatile("rur.fsr %0\n" : "=r"(regs->fp_non_volatile.reg[16]));
81 	__asm__ volatile("rur.fcr %0\n" : "=r"(regs->fp_non_volatile.reg[17]));
82 }
83 
84 /**
85  *
86  * @brief Load then dump all float registers to memory
87  *
88  * This function loads ALL floating point registers from the memory buffer
89  * specified by @a regs, and then stores them back to that buffer.
90  *
91  * This routine is called by a high priority thread prior to calling a primitive
92  * that pends and triggers a co-operative context switch to a low priority
93  * thread.
94  *
95  */
_load_then_store_all_float_registers(struct fp_register_set * regs)96 static inline void _load_then_store_all_float_registers(struct fp_register_set
97 							*regs)
98 {
99 	_load_all_float_registers(regs);
100 	_store_all_float_registers(regs);
101 }
102 
103 #endif /* _FLOAT_REGS_XTENSA_H */
104