1 /**
2  * @file
3  * @brief common definitions for the FPU sharing test application
4  */
5 
6 /*
7  * Copyright (c) 2011-2014 Wind River Systems, Inc.
8  *
9  * SPDX-License-Identifier: Apache-2.0
10  */
11 
12 #ifndef _FLOATCONTEXT_H
13 #define _FLOATCONTEXT_H
14 
15 /*
16  * Each architecture must define the following structures (which may be empty):
17  *      'struct fp_volatile_register_set'
18  *      'struct fp_non_volatile_register_set'
19  *
20  * Each architecture must also define the following macros:
21  *      SIZEOF_FP_VOLATILE_REGISTER_SET
22  *      SIZEOF_FP_NON_VOLATILE_REGISTER_SET
23  * Those macros are used as sizeof(<an empty structure>) is compiler specific;
24  * that is, it may evaluate to a non-zero value.
25  *
26  * Each architecture shall also have custom implementations of:
27  *     _load_all_float_registers()
28  *     _load_then_store_all_float_registers()
29  *     _store_all_float_registers()
30  */
31 
32 #if defined(CONFIG_X86)
33 
34 #define FP_OPTION 0
35 
36 /*
37  * In the future, the struct definitions may need to be refined based on the
38  * specific IA-32 processor, but for now only the Pentium4 is supported:
39  *
40  *          8 x 80 bit floating point registers (ST[0] -> ST[7])
41  *          8 x 128 bit XMM registers           (XMM[0] -> XMM[7])
42  *
43  * All these registers are considered volatile across a function invocation.
44  */
45 
46 struct fp_register {
47 	unsigned char reg[10];
48 };
49 
50 struct xmm_register {
51 	unsigned char reg[16];
52 };
53 
54 struct fp_volatile_register_set {
55 	struct xmm_register xmm[8];     /* XMM[0] -> XMM[7] */
56 	struct fp_register st[8];       /* ST[0] -> ST[7] */
57 };
58 
59 struct fp_non_volatile_register_set {
60 	/* No non-volatile floating point registers */
61 };
62 
63 #define SIZEOF_FP_VOLATILE_REGISTER_SET sizeof(struct fp_volatile_register_set)
64 #define SIZEOF_FP_NON_VOLATILE_REGISTER_SET 0
65 
66 #elif defined(CONFIG_ARM)
67 
68 #if defined(CONFIG_VFP_FEATURE_REGS_S64_D32)
69 
70 struct fp_volatile_register_set {
71 	double regs[16]; /* d0..d15 */
72 };
73 
74 struct fp_non_volatile_register_set {
75 	double regs[16]; /*d16..d31 */
76 };
77 
78 #elif defined(CONFIG_ARMV7_M_ARMV8_M_FP) || defined(CONFIG_ARMV7_R_FP) \
79 	|| defined(CONFIG_VFP_FEATURE_REGS_S32_D16)
80 
81 #define FP_OPTION 0
82 
83 /*
84  * Registers s0..s15 are volatile and do not
85  * need to be preserved across function calls.
86  */
87 struct fp_volatile_register_set {
88 	float s[16];
89 };
90 
91 /*
92  * Registers s16..s31 are non-volatile and
93  * need to be preserved across function calls.
94  */
95 struct fp_non_volatile_register_set {
96 	float s[16];
97 };
98 
99 #else
100 
101 struct fp_volatile_register_set {
102 	/* No volatile floating point registers */
103 };
104 
105 struct fp_non_volatile_register_set {
106 	/* No non-volatile floating point registers */
107 };
108 
109 #endif
110 
111 #define SIZEOF_FP_VOLATILE_REGISTER_SET	\
112 	sizeof(struct fp_volatile_register_set)
113 #define SIZEOF_FP_NON_VOLATILE_REGISTER_SET \
114 	sizeof(struct fp_non_volatile_register_set)
115 
116 #elif defined(CONFIG_ARM64)
117 
118 struct fp_volatile_register_set {
119 	__int128 regs[16];	/* q0..q15 */
120 };
121 
122 struct fp_non_volatile_register_set {
123 	__int128 regs[16];	/* q16..q31 */
124 };
125 
126 #define SIZEOF_FP_VOLATILE_REGISTER_SET	\
127 	sizeof(struct fp_volatile_register_set)
128 #define SIZEOF_FP_NON_VOLATILE_REGISTER_SET \
129 	sizeof(struct fp_non_volatile_register_set)
130 
131 #elif defined(CONFIG_ISA_ARCV2)
132 
133 struct fp_volatile_register_set {
134 #ifdef CONFIG_FP_FPU_DA
135 	uint32_t dpfp2h;
136 	uint32_t dpfp2l;
137 	uint32_t dpfp1h;
138 	uint32_t dpfp1l;
139 #endif
140 };
141 
142 struct fp_non_volatile_register_set {
143 	/* No non-volatile floating point registers */
144 };
145 
146 #define SIZEOF_FP_VOLATILE_REGISTER_SET sizeof(struct fp_volatile_register_set)
147 #define SIZEOF_FP_NON_VOLATILE_REGISTER_SET 0
148 
149 #elif defined(CONFIG_RISCV)
150 
151 struct fp_volatile_register_set {
152 #ifdef CONFIG_CPU_HAS_FPU_DOUBLE_PRECISION
153 	uint64_t fp[32];
154 #else
155 	uint32_t fp[32];
156 #endif
157 };
158 
159 struct fp_non_volatile_register_set {
160 	/* No non-volatile floating point registers */
161 };
162 
163 #define SIZEOF_FP_VOLATILE_REGISTER_SET sizeof(struct fp_volatile_register_set)
164 #define SIZEOF_FP_NON_VOLATILE_REGISTER_SET 0
165 
166 #elif defined(CONFIG_SPARC)
167 
168 struct fp_volatile_register_set {
169 	double d[16];
170 };
171 
172 struct fp_non_volatile_register_set {
173 };
174 
175 #define SIZEOF_FP_VOLATILE_REGISTER_SET sizeof(struct fp_volatile_register_set)
176 #define SIZEOF_FP_NON_VOLATILE_REGISTER_SET 0
177 
178 #elif defined(CONFIG_XTENSA)
179 
180 struct fp_volatile_register_set {
181 	/* No volatile floating point registers */
182 };
183 
184 struct fp_non_volatile_register_set {
185 	uint32_t reg[18];     /* FR register file consists of 18 registers of 32 bits */
186 };
187 
188 #define SIZEOF_FP_VOLATILE_REGISTER_SET 0
189 #define SIZEOF_FP_NON_VOLATILE_REGISTER_SET sizeof(struct fp_non_volatile_register_set)
190 
191 #else
192 
193 #error  "Architecture must provide the following definitions:\n"
194 "\t'struct fp_volatile_registers'\n"
195 "\t'struct fp_non_volatile_registers'\n"
196 "\t'SIZEOF_FP_VOLATILE_REGISTER_SET'\n"
197 "\t'SIZEOF_FP_NON_VOLATILE_REGISTER_SET'\n"
198 #endif /* CONFIG_X86 */
199 
200 /* the set of ALL floating point registers */
201 
202 struct fp_register_set {
203 	struct fp_volatile_register_set fp_volatile;
204 	struct fp_non_volatile_register_set fp_non_volatile;
205 };
206 
207 #define SIZEOF_FP_REGISTER_SET \
208 	(SIZEOF_FP_VOLATILE_REGISTER_SET + SIZEOF_FP_NON_VOLATILE_REGISTER_SET)
209 
210 /*
211  * The following constants define the initial byte value used by the background
212  * task, and the thread when loading up the floating point registers.
213  */
214 
215 #define MAIN_FLOAT_REG_CHECK_BYTE ((unsigned char)0xe5)
216 #define FIBER_FLOAT_REG_CHECK_BYTE ((unsigned char)0xf9)
217 
218 #endif /* _FLOATCONTEXT_H */
219