1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2023 Oxide Computer Company
14 */
15
16 .file "xsave_asm64.s"
17
18 /*
19 * Test utility routines that we need assembler for. 64-bit addition.
20 */
21
22 #include <sys/asm_linkage.h>
23 #include "xsave_util.h"
24
25 #define GET_FPU_XMM(src, i) \
26 leaq (i * XSU_ZMM_U32 * 4)(src), %rax; \
27 movdqu %xmm##i, (%rax)
28
29 #define GET_FPU_YMM(src, i) \
30 leaq (i * XSU_ZMM_U32 * 4)(src), %rax; \
31 vmovdqu %ymm##i, (%rax)
32
33 #define GET_FPU_ZMM(src, i) \
34 leaq (i * XSU_ZMM_U32 * 4)(src), %rax; \
35 vmovdqu64 %zmm##i, (%rax)
36
37 #define GET_MASK(src, i) \
38 leaq (0x800 + i * 8)(src), %rax; \
39 kmovq %k##i, (%rax)
40
41 /*
42 * void xsu_getfpu(xsu_fpu_t *data, uint32_t type)
43 *
44 * Our job is to get the entire contents of the FPU and save it into our
45 * data structure.
46 */
47 ENTRY(xsu_getfpu)
48 cmpl $XSU_XMM, %esi
49 je get_xmm
50 cmpl $XSU_YMM, %esi
51 je get_ymm
52 cmpl $XSU_ZMM, %esi
53 je get_zmm
54 call abort
55 get_xmm:
56 GET_FPU_XMM(%rdi, 0)
57 GET_FPU_XMM(%rdi, 1)
58 GET_FPU_XMM(%rdi, 2)
59 GET_FPU_XMM(%rdi, 3)
60 GET_FPU_XMM(%rdi, 4)
61 GET_FPU_XMM(%rdi, 5)
62 GET_FPU_XMM(%rdi, 6)
63 GET_FPU_XMM(%rdi, 7)
64 GET_FPU_XMM(%rdi, 8)
65 GET_FPU_XMM(%rdi, 9)
66 GET_FPU_XMM(%rdi, 10)
67 GET_FPU_XMM(%rdi, 11)
68 GET_FPU_XMM(%rdi, 12)
69 GET_FPU_XMM(%rdi, 13)
70 GET_FPU_XMM(%rdi, 14)
71 GET_FPU_XMM(%rdi, 15)
72 jmp get_done
73 get_ymm:
74 GET_FPU_YMM(%rdi, 0)
75 GET_FPU_YMM(%rdi, 1)
76 GET_FPU_YMM(%rdi, 2)
77 GET_FPU_YMM(%rdi, 3)
78 GET_FPU_YMM(%rdi, 4)
79 GET_FPU_YMM(%rdi, 5)
80 GET_FPU_YMM(%rdi, 6)
81 GET_FPU_YMM(%rdi, 7)
82 GET_FPU_YMM(%rdi, 8)
83 GET_FPU_YMM(%rdi, 9)
84 GET_FPU_YMM(%rdi, 10)
85 GET_FPU_YMM(%rdi, 11)
86 GET_FPU_YMM(%rdi, 12)
87 GET_FPU_YMM(%rdi, 13)
88 GET_FPU_YMM(%rdi, 14)
89 GET_FPU_YMM(%rdi, 15)
90 jmp get_done
91 get_zmm:
92 GET_FPU_ZMM(%rdi, 0)
93 GET_FPU_ZMM(%rdi, 1)
94 GET_FPU_ZMM(%rdi, 2)
95 GET_FPU_ZMM(%rdi, 3)
96 GET_FPU_ZMM(%rdi, 4)
97 GET_FPU_ZMM(%rdi, 5)
98 GET_FPU_ZMM(%rdi, 6)
99 GET_FPU_ZMM(%rdi, 7)
100 GET_FPU_ZMM(%rdi, 8)
101 GET_FPU_ZMM(%rdi, 9)
102 GET_FPU_ZMM(%rdi, 10)
103 GET_FPU_ZMM(%rdi, 11)
104 GET_FPU_ZMM(%rdi, 12)
105 GET_FPU_ZMM(%rdi, 13)
106 GET_FPU_ZMM(%rdi, 14)
107 GET_FPU_ZMM(%rdi, 15)
108 GET_FPU_ZMM(%rdi, 16)
109 GET_FPU_ZMM(%rdi, 17)
110 GET_FPU_ZMM(%rdi, 18)
111 GET_FPU_ZMM(%rdi, 19)
112 GET_FPU_ZMM(%rdi, 20)
113 GET_FPU_ZMM(%rdi, 21)
114 GET_FPU_ZMM(%rdi, 22)
115 GET_FPU_ZMM(%rdi, 23)
116 GET_FPU_ZMM(%rdi, 24)
117 GET_FPU_ZMM(%rdi, 25)
118 GET_FPU_ZMM(%rdi, 25)
119 GET_FPU_ZMM(%rdi, 26)
120 GET_FPU_ZMM(%rdi, 27)
121 GET_FPU_ZMM(%rdi, 28)
122 GET_FPU_ZMM(%rdi, 29)
123 GET_FPU_ZMM(%rdi, 30)
124 GET_FPU_ZMM(%rdi, 31)
125 GET_MASK(%rdi, 0)
126 GET_MASK(%rdi, 1)
127 GET_MASK(%rdi, 2)
128 GET_MASK(%rdi, 3)
129 GET_MASK(%rdi, 4)
130 GET_MASK(%rdi, 5)
131 GET_MASK(%rdi, 6)
132 GET_MASK(%rdi, 7)
133 get_done:
134 ret
135 SET_SIZE(xsu_getfpu)
136
137 #define SET_FPU_XMM(src, i) \
138 leaq (i * XSU_ZMM_U32 * 4)(src), %rax; \
139 movdqu (%rax), %xmm##i
140
141 #define SET_FPU_YMM(src, i) \
142 leaq (i * XSU_ZMM_U32 * 4)(src), %rax; \
143 vmovdqu (%rax), %ymm##i
144
145 #define SET_FPU_ZMM(src, i) \
146 leaq (i * XSU_ZMM_U32 * 4)(src), %rax; \
147 vmovdqu64 (%rax), %zmm##i
148
149 #define SET_MASK(src, i) \
150 leaq (0x800 + i * 8)(src), %rax; \
151 kmovq (%rax), %k##i
152
153 /*
154 * void xsu_setfpu(const xsu_fpu_t *data, uint32_t type)
155 *
156 * Our job is to override the contents of the FPU with this structure
157 * that we've been given. The type indicates how much of it to use.
158 */
159 ENTRY(xsu_setfpu)
160 cmpl $XSU_XMM, %esi
161 je set_xmm
162 cmpl $XSU_YMM, %esi
163 je set_ymm
164 cmpl $XSU_ZMM, %esi
165 je set_zmm
166 call abort
167 set_xmm:
168 SET_FPU_XMM(%rdi, 0)
169 SET_FPU_XMM(%rdi, 1)
170 SET_FPU_XMM(%rdi, 2)
171 SET_FPU_XMM(%rdi, 3)
172 SET_FPU_XMM(%rdi, 4)
173 SET_FPU_XMM(%rdi, 5)
174 SET_FPU_XMM(%rdi, 6)
175 SET_FPU_XMM(%rdi, 7)
176 SET_FPU_XMM(%rdi, 8)
177 SET_FPU_XMM(%rdi, 9)
178 SET_FPU_XMM(%rdi, 10)
179 SET_FPU_XMM(%rdi, 11)
180 SET_FPU_XMM(%rdi, 12)
181 SET_FPU_XMM(%rdi, 13)
182 SET_FPU_XMM(%rdi, 14)
183 SET_FPU_XMM(%rdi, 15)
184 jmp set_done
185 set_ymm:
186 SET_FPU_YMM(%rdi, 0)
187 SET_FPU_YMM(%rdi, 1)
188 SET_FPU_YMM(%rdi, 2)
189 SET_FPU_YMM(%rdi, 3)
190 SET_FPU_YMM(%rdi, 4)
191 SET_FPU_YMM(%rdi, 5)
192 SET_FPU_YMM(%rdi, 6)
193 SET_FPU_YMM(%rdi, 7)
194 SET_FPU_YMM(%rdi, 8)
195 SET_FPU_YMM(%rdi, 9)
196 SET_FPU_YMM(%rdi, 10)
197 SET_FPU_YMM(%rdi, 11)
198 SET_FPU_YMM(%rdi, 12)
199 SET_FPU_YMM(%rdi, 13)
200 SET_FPU_YMM(%rdi, 14)
201 SET_FPU_YMM(%rdi, 15)
202 jmp set_done
203 set_zmm:
204 SET_FPU_ZMM(%rdi, 0)
205 SET_FPU_ZMM(%rdi, 1)
206 SET_FPU_ZMM(%rdi, 2)
207 SET_FPU_ZMM(%rdi, 3)
208 SET_FPU_ZMM(%rdi, 4)
209 SET_FPU_ZMM(%rdi, 5)
210 SET_FPU_ZMM(%rdi, 6)
211 SET_FPU_ZMM(%rdi, 7)
212 SET_FPU_ZMM(%rdi, 8)
213 SET_FPU_ZMM(%rdi, 9)
214 SET_FPU_ZMM(%rdi, 10)
215 SET_FPU_ZMM(%rdi, 11)
216 SET_FPU_ZMM(%rdi, 12)
217 SET_FPU_ZMM(%rdi, 13)
218 SET_FPU_ZMM(%rdi, 14)
219 SET_FPU_ZMM(%rdi, 15)
220 SET_FPU_ZMM(%rdi, 16)
221 SET_FPU_ZMM(%rdi, 17)
222 SET_FPU_ZMM(%rdi, 18)
223 SET_FPU_ZMM(%rdi, 19)
224 SET_FPU_ZMM(%rdi, 20)
225 SET_FPU_ZMM(%rdi, 21)
226 SET_FPU_ZMM(%rdi, 22)
227 SET_FPU_ZMM(%rdi, 23)
228 SET_FPU_ZMM(%rdi, 24)
229 SET_FPU_ZMM(%rdi, 25)
230 SET_FPU_ZMM(%rdi, 25)
231 SET_FPU_ZMM(%rdi, 26)
232 SET_FPU_ZMM(%rdi, 27)
233 SET_FPU_ZMM(%rdi, 28)
234 SET_FPU_ZMM(%rdi, 29)
235 SET_FPU_ZMM(%rdi, 30)
236 SET_FPU_ZMM(%rdi, 31)
237 SET_MASK(%rdi, 0)
238 SET_MASK(%rdi, 1)
239 SET_MASK(%rdi, 2)
240 SET_MASK(%rdi, 3)
241 SET_MASK(%rdi, 4)
242 SET_MASK(%rdi, 5)
243 SET_MASK(%rdi, 6)
244 SET_MASK(%rdi, 7)
245 set_done:
246 ret
247 SET_SIZE(xsu_setfpu)