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
55get_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
73get_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
91get_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)
133get_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
167set_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
185set_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
203set_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)
245set_done:
246	ret
247	SET_SIZE(xsu_setfpu)
248