1 /**
2 * @file
3 * @brief Intel x86 GCC specific floating point register macros
4 */
5
6 /*
7 * Copyright (c) 2015, Wind River Systems, Inc.
8 *
9 * SPDX-License-Identifier: Apache-2.0
10 */
11
12 #ifndef _FLOAT_REGS_X86_GCC_H
13 #define _FLOAT_REGS_X86_GCC_H
14
15 #if !defined(__GNUC__) || !defined(CONFIG_X86)
16 #error __FILE__ goes only with x86 GCC
17 #endif
18
19 #include <zephyr/toolchain.h>
20 #include "float_context.h"
21
22 /**
23 *
24 * @brief Load all floating point registers
25 *
26 * This function loads ALL floating point registers pointed to by @a regs.
27 * It is expected that a subsequent call to _store_all_float_registers()
28 * will be issued to dump the floating point registers to memory.
29 *
30 * The format/organization of 'struct fp_register_set'; the generic C test
31 * code (main.c) merely treat the register set as an array of bytes.
32 *
33 * The only requirement is that the arch specific implementations of
34 * _load_all_float_registers(), _store_all_float_registers() and
35 * _load_then_store_all_float_registers() agree on the format.
36 *
37 */
38
_load_all_float_registers(struct fp_register_set * regs)39 static inline void _load_all_float_registers(struct fp_register_set *regs)
40 {
41 __asm__ volatile (
42 "movdqu 0(%0), %%xmm0\n\t;"
43 "movdqu 16(%0), %%xmm1\n\t;"
44 "movdqu 32(%0), %%xmm2\n\t;"
45 "movdqu 48(%0), %%xmm3\n\t;"
46 "movdqu 64(%0), %%xmm4\n\t;"
47 "movdqu 80(%0), %%xmm5\n\t;"
48 "movdqu 96(%0), %%xmm6\n\t;"
49 "movdqu 112(%0), %%xmm7\n\t;"
50
51 "fldt 128(%0)\n\t;"
52 "fldt 138(%0)\n\t;"
53 "fldt 148(%0)\n\t;"
54 "fldt 158(%0)\n\t;"
55 "fldt 168(%0)\n\t;"
56 "fldt 178(%0)\n\t;"
57 "fldt 188(%0)\n\t;"
58 "fldt 198(%0)\n\t;"
59
60 : : "r" (regs)
61 );
62 }
63
64
65 /**
66 *
67 * @brief Load then dump all float registers to memory
68 *
69 * This function loads ALL floating point registers from the memory buffer
70 * specified by @a regs, and then stores them back to that buffer.
71 *
72 * This routine is called by a high priority thread prior to calling a primitive
73 * that pends and triggers a co-operative context switch to a low priority
74 * thread. Because the kernel doesn't save floating point context for
75 * co-operative context switches, the x87 FPU register stack must be put back
76 * in an empty state before the switch occurs in case the next task to perform
77 * floating point operations was also co-operatively switched out and simply
78 * inherits the existing x87 FPU state (expecting the stack to be empty).
79 *
80 */
81
82 static inline void
_load_then_store_all_float_registers(struct fp_register_set * regs)83 _load_then_store_all_float_registers(struct fp_register_set *regs)
84 {
85 __asm__ volatile (
86 "movdqu 0(%0), %%xmm0\n\t;"
87 "movdqu 16(%0), %%xmm1\n\t;"
88 "movdqu 32(%0), %%xmm2\n\t;"
89 "movdqu 48(%0), %%xmm3\n\t;"
90 "movdqu 64(%0), %%xmm4\n\t;"
91 "movdqu 80(%0), %%xmm5\n\t;"
92 "movdqu 96(%0), %%xmm6\n\t;"
93 "movdqu 112(%0), %%xmm7\n\t;"
94
95 "fldt 128(%0)\n\t;"
96 "fldt 138(%0)\n\t;"
97 "fldt 148(%0)\n\t;"
98 "fldt 158(%0)\n\t;"
99 "fldt 168(%0)\n\t;"
100 "fldt 178(%0)\n\t;"
101 "fldt 188(%0)\n\t;"
102 "fldt 198(%0)\n\t;"
103
104 /* pop the x87 FPU registers back to memory */
105
106 "fstpt 198(%0)\n\t;"
107 "fstpt 188(%0)\n\t;"
108 "fstpt 178(%0)\n\t;"
109 "fstpt 168(%0)\n\t;"
110 "fstpt 158(%0)\n\t;"
111 "fstpt 148(%0)\n\t;"
112 "fstpt 138(%0)\n\t;"
113 "fstpt 128(%0)\n\t;"
114
115 : : "r" (regs)
116 );
117 }
118
119
120 /**
121 *
122 * @brief Dump all floating point registers to memory
123 *
124 * This function stores ALL floating point registers to the memory buffer
125 * specified by @a regs. It is expected that a previous invocation of
126 * _load_all_float_registers() occurred to load all the floating point
127 * registers from a memory buffer.
128 *
129 */
130
_store_all_float_registers(struct fp_register_set * regs)131 static inline void _store_all_float_registers(struct fp_register_set *regs)
132 {
133 __asm__ volatile (
134 "movdqu %%xmm0, 0(%0)\n\t;"
135 "movdqu %%xmm1, 16(%0)\n\t;"
136 "movdqu %%xmm2, 32(%0)\n\t;"
137 "movdqu %%xmm3, 48(%0)\n\t;"
138 "movdqu %%xmm4, 64(%0)\n\t;"
139 "movdqu %%xmm5, 80(%0)\n\t;"
140 "movdqu %%xmm6, 96(%0)\n\t;"
141 "movdqu %%xmm7, 112(%0)\n\t;"
142
143 "fstpt 198(%0)\n\t;"
144 "fstpt 188(%0)\n\t;"
145 "fstpt 178(%0)\n\t;"
146 "fstpt 168(%0)\n\t;"
147 "fstpt 158(%0)\n\t;"
148 "fstpt 148(%0)\n\t;"
149 "fstpt 138(%0)\n\t;"
150 "fstpt 128(%0)\n\t;"
151
152 : : "r" (regs) : "memory"
153 );
154 }
155 #endif /* _FLOAT_REGS_X86_GCC_H */
156