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