xref: /linux/arch/s390/include/asm/fpu-insn.h (revision 37346951)
1fd2527f2SHeiko Carstens /* SPDX-License-Identifier: GPL-2.0 */
2fd2527f2SHeiko Carstens /*
3fd2527f2SHeiko Carstens  * Support for Floating Point and Vector Instructions
4fd2527f2SHeiko Carstens  *
5fd2527f2SHeiko Carstens  */
6fd2527f2SHeiko Carstens 
7fd2527f2SHeiko Carstens #ifndef __ASM_S390_FPU_INSN_H
8fd2527f2SHeiko Carstens #define __ASM_S390_FPU_INSN_H
9fd2527f2SHeiko Carstens 
10fd2527f2SHeiko Carstens #include <asm/fpu-insn-asm.h>
11fd2527f2SHeiko Carstens 
12fd2527f2SHeiko Carstens #ifndef __ASSEMBLY__
13fd2527f2SHeiko Carstens 
1413a8a519SHeiko Carstens #include <linux/instrumented.h>
15fd2527f2SHeiko Carstens #include <asm/asm-extable.h>
16fd2527f2SHeiko Carstens 
17fd2527f2SHeiko Carstens asm(".include \"asm/fpu-insn-asm.h\"\n");
18fd2527f2SHeiko Carstens 
19045bad08SHeiko Carstens /*
20045bad08SHeiko Carstens  * Various small helper functions, which can and should be used within
21045bad08SHeiko Carstens  * kernel fpu code sections. Each function represents only one floating
22045bad08SHeiko Carstens  * point or vector instruction (except for helper functions which require
23045bad08SHeiko Carstens  * exception handling).
24045bad08SHeiko Carstens  *
25045bad08SHeiko Carstens  * This allows to use floating point and vector instructions like C
26045bad08SHeiko Carstens  * functions, which has the advantage that all supporting code, like
27045bad08SHeiko Carstens  * e.g. loops, can be written in easy to read C code.
28045bad08SHeiko Carstens  *
29045bad08SHeiko Carstens  * Each of the helper functions provides support for code instrumentation,
30045bad08SHeiko Carstens  * like e.g. KASAN. Therefore instrumentation is also covered automatically
31045bad08SHeiko Carstens  * when using these functions.
32045bad08SHeiko Carstens  *
33045bad08SHeiko Carstens  * In order to ensure that code generated with the helper functions stays
34045bad08SHeiko Carstens  * within kernel fpu sections, which are guarded with kernel_fpu_begin()
35045bad08SHeiko Carstens  * and kernel_fpu_end() calls, each function has a mandatory "memory"
36045bad08SHeiko Carstens  * barrier.
37045bad08SHeiko Carstens  */
38045bad08SHeiko Carstens 
fpu_cefbr(u8 f1,s32 val)39ea8b75d2SHeiko Carstens static __always_inline void fpu_cefbr(u8 f1, s32 val)
40ea8b75d2SHeiko Carstens {
41ea8b75d2SHeiko Carstens 	asm volatile("cefbr	%[f1],%[val]\n"
42ea8b75d2SHeiko Carstens 		     :
43ea8b75d2SHeiko Carstens 		     : [f1] "I" (f1), [val] "d" (val)
44ea8b75d2SHeiko Carstens 		     : "memory");
45ea8b75d2SHeiko Carstens }
46ea8b75d2SHeiko Carstens 
fpu_cgebr(u8 f2,u8 mode)47ea8b75d2SHeiko Carstens static __always_inline unsigned long fpu_cgebr(u8 f2, u8 mode)
48ea8b75d2SHeiko Carstens {
49ea8b75d2SHeiko Carstens 	unsigned long val;
50ea8b75d2SHeiko Carstens 
51ea8b75d2SHeiko Carstens 	asm volatile("cgebr	%[val],%[mode],%[f2]\n"
52ea8b75d2SHeiko Carstens 		     : [val] "=d" (val)
53ea8b75d2SHeiko Carstens 		     : [f2] "I" (f2), [mode] "I" (mode)
54ea8b75d2SHeiko Carstens 		     : "memory");
55ea8b75d2SHeiko Carstens 	return val;
56ea8b75d2SHeiko Carstens }
57ea8b75d2SHeiko Carstens 
fpu_debr(u8 f1,u8 f2)58ea8b75d2SHeiko Carstens static __always_inline void fpu_debr(u8 f1, u8 f2)
59ea8b75d2SHeiko Carstens {
60ea8b75d2SHeiko Carstens 	asm volatile("debr	%[f1],%[f2]\n"
61ea8b75d2SHeiko Carstens 		     :
62ea8b75d2SHeiko Carstens 		     : [f1] "I" (f1), [f2] "I" (f2)
63ea8b75d2SHeiko Carstens 		     : "memory");
64ea8b75d2SHeiko Carstens }
65ea8b75d2SHeiko Carstens 
fpu_ld(unsigned short fpr,freg_t * reg)6688d8136aSHeiko Carstens static __always_inline void fpu_ld(unsigned short fpr, freg_t *reg)
6788d8136aSHeiko Carstens {
6888d8136aSHeiko Carstens 	instrument_read(reg, sizeof(*reg));
6988d8136aSHeiko Carstens 	asm volatile("ld	 %[fpr],%[reg]\n"
7088d8136aSHeiko Carstens 		     :
7188d8136aSHeiko Carstens 		     : [fpr] "I" (fpr), [reg] "Q" (reg->ui)
7288d8136aSHeiko Carstens 		     : "memory");
7388d8136aSHeiko Carstens }
7488d8136aSHeiko Carstens 
fpu_ldgr(u8 f1,u32 val)75ea8b75d2SHeiko Carstens static __always_inline void fpu_ldgr(u8 f1, u32 val)
76ea8b75d2SHeiko Carstens {
77ea8b75d2SHeiko Carstens 	asm volatile("ldgr	%[f1],%[val]\n"
78ea8b75d2SHeiko Carstens 		     :
79ea8b75d2SHeiko Carstens 		     : [f1] "I" (f1), [val] "d" (val)
80ea8b75d2SHeiko Carstens 		     : "memory");
81ea8b75d2SHeiko Carstens }
82ea8b75d2SHeiko Carstens 
fpu_lfpc(unsigned int * fpc)83f4e3de75SHeiko Carstens static __always_inline void fpu_lfpc(unsigned int *fpc)
84f4e3de75SHeiko Carstens {
85f4e3de75SHeiko Carstens 	instrument_read(fpc, sizeof(*fpc));
86f4e3de75SHeiko Carstens 	asm volatile("lfpc	%[fpc]"
87f4e3de75SHeiko Carstens 		     :
88f4e3de75SHeiko Carstens 		     : [fpc] "Q" (*fpc)
89f4e3de75SHeiko Carstens 		     : "memory");
90f4e3de75SHeiko Carstens }
91f4e3de75SHeiko Carstens 
92fd2527f2SHeiko Carstens /**
9313a8a519SHeiko Carstens  * fpu_lfpc_safe - Load floating point control register safely.
94fd2527f2SHeiko Carstens  * @fpc: new value for floating point control register
95fd2527f2SHeiko Carstens  *
9613a8a519SHeiko Carstens  * Load floating point control register. This may lead to an exception,
97fd2527f2SHeiko Carstens  * since a saved value may have been modified by user space (ptrace,
98fd2527f2SHeiko Carstens  * signal return, kvm registers) to an invalid value. In such a case
99fd2527f2SHeiko Carstens  * set the floating point control register to zero.
100fd2527f2SHeiko Carstens  */
fpu_lfpc_safe(unsigned int * fpc)10113a8a519SHeiko Carstens static inline void fpu_lfpc_safe(unsigned int *fpc)
102fd2527f2SHeiko Carstens {
10313a8a519SHeiko Carstens 	u32 tmp;
10413a8a519SHeiko Carstens 
10513a8a519SHeiko Carstens 	instrument_read(fpc, sizeof(*fpc));
106fd2527f2SHeiko Carstens 	asm volatile("\n"
10713a8a519SHeiko Carstens 		"0:	lfpc	%[fpc]\n"
108fd2527f2SHeiko Carstens 		"1:	nopr	%%r7\n"
109fd2527f2SHeiko Carstens 		".pushsection .fixup, \"ax\"\n"
11013a8a519SHeiko Carstens 		"2:	lghi	%[tmp],0\n"
11113a8a519SHeiko Carstens 		"	sfpc	%[tmp]\n"
11213a8a519SHeiko Carstens 		"	jg	1b\n"
113fd2527f2SHeiko Carstens 		".popsection\n"
114fd2527f2SHeiko Carstens 		EX_TABLE(1b, 2b)
11513a8a519SHeiko Carstens 		: [tmp] "=d" (tmp)
11613a8a519SHeiko Carstens 		: [fpc] "Q" (*fpc)
11713a8a519SHeiko Carstens 		: "memory");
118fd2527f2SHeiko Carstens }
119fd2527f2SHeiko Carstens 
fpu_std(unsigned short fpr,freg_t * reg)12088d8136aSHeiko Carstens static __always_inline void fpu_std(unsigned short fpr, freg_t *reg)
12188d8136aSHeiko Carstens {
12288d8136aSHeiko Carstens 	instrument_write(reg, sizeof(*reg));
12388d8136aSHeiko Carstens 	asm volatile("std	 %[fpr],%[reg]\n"
12488d8136aSHeiko Carstens 		     : [reg] "=Q" (reg->ui)
12588d8136aSHeiko Carstens 		     : [fpr] "I" (fpr)
12688d8136aSHeiko Carstens 		     : "memory");
12788d8136aSHeiko Carstens }
12888d8136aSHeiko Carstens 
fpu_sfpc(unsigned int fpc)129f4e3de75SHeiko Carstens static __always_inline void fpu_sfpc(unsigned int fpc)
130f4e3de75SHeiko Carstens {
131f4e3de75SHeiko Carstens 	asm volatile("sfpc	%[fpc]"
132f4e3de75SHeiko Carstens 		     :
133f4e3de75SHeiko Carstens 		     : [fpc] "d" (fpc)
134f4e3de75SHeiko Carstens 		     : "memory");
135f4e3de75SHeiko Carstens }
136f4e3de75SHeiko Carstens 
fpu_stfpc(unsigned int * fpc)137f4e3de75SHeiko Carstens static __always_inline void fpu_stfpc(unsigned int *fpc)
138f4e3de75SHeiko Carstens {
139f4e3de75SHeiko Carstens 	instrument_write(fpc, sizeof(*fpc));
140f4e3de75SHeiko Carstens 	asm volatile("stfpc	%[fpc]"
141f4e3de75SHeiko Carstens 		     : [fpc] "=Q" (*fpc)
142f4e3de75SHeiko Carstens 		     :
143f4e3de75SHeiko Carstens 		     : "memory");
144f4e3de75SHeiko Carstens }
145f4e3de75SHeiko Carstens 
fpu_vab(u8 v1,u8 v2,u8 v3)146c8dde11dSHeiko Carstens static __always_inline void fpu_vab(u8 v1, u8 v2, u8 v3)
147c8dde11dSHeiko Carstens {
148c8dde11dSHeiko Carstens 	asm volatile("VAB	%[v1],%[v2],%[v3]"
149c8dde11dSHeiko Carstens 		     :
150c8dde11dSHeiko Carstens 		     : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3)
151c8dde11dSHeiko Carstens 		     : "memory");
152c8dde11dSHeiko Carstens }
153c8dde11dSHeiko Carstens 
fpu_vcksm(u8 v1,u8 v2,u8 v3)154cb2a1dd5SHeiko Carstens static __always_inline void fpu_vcksm(u8 v1, u8 v2, u8 v3)
155cb2a1dd5SHeiko Carstens {
156cb2a1dd5SHeiko Carstens 	asm volatile("VCKSM	%[v1],%[v2],%[v3]"
157cb2a1dd5SHeiko Carstens 		     :
158cb2a1dd5SHeiko Carstens 		     : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3)
159cb2a1dd5SHeiko Carstens 		     : "memory");
160cb2a1dd5SHeiko Carstens }
161cb2a1dd5SHeiko Carstens 
fpu_vesravb(u8 v1,u8 v2,u8 v3)162c8dde11dSHeiko Carstens static __always_inline void fpu_vesravb(u8 v1, u8 v2, u8 v3)
163c8dde11dSHeiko Carstens {
164c8dde11dSHeiko Carstens 	asm volatile("VESRAVB	%[v1],%[v2],%[v3]"
165c8dde11dSHeiko Carstens 		     :
166c8dde11dSHeiko Carstens 		     : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3)
167c8dde11dSHeiko Carstens 		     : "memory");
168c8dde11dSHeiko Carstens }
169c8dde11dSHeiko Carstens 
fpu_vgfmag(u8 v1,u8 v2,u8 v3,u8 v4)170*37346951SHeiko Carstens static __always_inline void fpu_vgfmag(u8 v1, u8 v2, u8 v3, u8 v4)
171*37346951SHeiko Carstens {
172*37346951SHeiko Carstens 	asm volatile("VGFMAG	%[v1],%[v2],%[v3],%[v4]"
173*37346951SHeiko Carstens 		     :
174*37346951SHeiko Carstens 		     : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3), [v4] "I" (v4)
175*37346951SHeiko Carstens 		     : "memory");
176*37346951SHeiko Carstens }
177*37346951SHeiko Carstens 
fpu_vgfmg(u8 v1,u8 v2,u8 v3)178*37346951SHeiko Carstens static __always_inline void fpu_vgfmg(u8 v1, u8 v2, u8 v3)
179*37346951SHeiko Carstens {
180*37346951SHeiko Carstens 	asm volatile("VGFMG	%[v1],%[v2],%[v3]"
181*37346951SHeiko Carstens 		     :
182*37346951SHeiko Carstens 		     : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3)
183*37346951SHeiko Carstens 		     : "memory");
184*37346951SHeiko Carstens }
185*37346951SHeiko Carstens 
186cb2a1dd5SHeiko Carstens #ifdef CONFIG_CC_IS_CLANG
187cb2a1dd5SHeiko Carstens 
fpu_vl(u8 v1,const void * vxr)188cb2a1dd5SHeiko Carstens static __always_inline void fpu_vl(u8 v1, const void *vxr)
189cb2a1dd5SHeiko Carstens {
190cb2a1dd5SHeiko Carstens 	instrument_read(vxr, sizeof(__vector128));
191cb2a1dd5SHeiko Carstens 	asm volatile("\n"
192cb2a1dd5SHeiko Carstens 		"	la	1,%[vxr]\n"
193cb2a1dd5SHeiko Carstens 		"	VL	%[v1],0,,1\n"
194cb2a1dd5SHeiko Carstens 		:
195cb2a1dd5SHeiko Carstens 		: [vxr] "R" (*(__vector128 *)vxr),
196cb2a1dd5SHeiko Carstens 		  [v1] "I" (v1)
197cb2a1dd5SHeiko Carstens 		: "memory", "1");
198cb2a1dd5SHeiko Carstens }
199cb2a1dd5SHeiko Carstens 
200cb2a1dd5SHeiko Carstens #else /* CONFIG_CC_IS_CLANG */
201cb2a1dd5SHeiko Carstens 
fpu_vl(u8 v1,const void * vxr)202cb2a1dd5SHeiko Carstens static __always_inline void fpu_vl(u8 v1, const void *vxr)
203cb2a1dd5SHeiko Carstens {
204cb2a1dd5SHeiko Carstens 	instrument_read(vxr, sizeof(__vector128));
205cb2a1dd5SHeiko Carstens 	asm volatile("VL	%[v1],%O[vxr],,%R[vxr]\n"
206cb2a1dd5SHeiko Carstens 		     :
207cb2a1dd5SHeiko Carstens 		     : [vxr] "Q" (*(__vector128 *)vxr),
208cb2a1dd5SHeiko Carstens 		       [v1] "I" (v1)
209cb2a1dd5SHeiko Carstens 		     : "memory");
210cb2a1dd5SHeiko Carstens }
211cb2a1dd5SHeiko Carstens 
212cb2a1dd5SHeiko Carstens #endif /* CONFIG_CC_IS_CLANG */
213cb2a1dd5SHeiko Carstens 
fpu_vleib(u8 v,s16 val,u8 index)214*37346951SHeiko Carstens static __always_inline void fpu_vleib(u8 v, s16 val, u8 index)
215*37346951SHeiko Carstens {
216*37346951SHeiko Carstens 	asm volatile("VLEIB	%[v],%[val],%[index]"
217*37346951SHeiko Carstens 		     :
218*37346951SHeiko Carstens 		     : [v] "I" (v), [val] "K" (val), [index] "I" (index)
219*37346951SHeiko Carstens 		     : "memory");
220*37346951SHeiko Carstens }
221*37346951SHeiko Carstens 
fpu_vleig(u8 v,s16 val,u8 index)222*37346951SHeiko Carstens static __always_inline void fpu_vleig(u8 v, s16 val, u8 index)
223*37346951SHeiko Carstens {
224*37346951SHeiko Carstens 	asm volatile("VLEIG	%[v],%[val],%[index]"
225*37346951SHeiko Carstens 		     :
226*37346951SHeiko Carstens 		     : [v] "I" (v), [val] "K" (val), [index] "I" (index)
227*37346951SHeiko Carstens 		     : "memory");
228*37346951SHeiko Carstens }
229*37346951SHeiko Carstens 
fpu_vlgvf(u8 v,u16 index)230cb2a1dd5SHeiko Carstens static __always_inline u64 fpu_vlgvf(u8 v, u16 index)
231cb2a1dd5SHeiko Carstens {
232cb2a1dd5SHeiko Carstens 	u64 val;
233cb2a1dd5SHeiko Carstens 
234cb2a1dd5SHeiko Carstens 	asm volatile("VLGVF	%[val],%[v],%[index]"
235cb2a1dd5SHeiko Carstens 		     : [val] "=d" (val)
236cb2a1dd5SHeiko Carstens 		     : [v] "I" (v), [index] "L" (index)
237cb2a1dd5SHeiko Carstens 		     : "memory");
238cb2a1dd5SHeiko Carstens 	return val;
239cb2a1dd5SHeiko Carstens }
240cb2a1dd5SHeiko Carstens 
241cb2a1dd5SHeiko Carstens #ifdef CONFIG_CC_IS_CLANG
242cb2a1dd5SHeiko Carstens 
fpu_vll(u8 v1,u32 index,const void * vxr)243cb2a1dd5SHeiko Carstens static __always_inline void fpu_vll(u8 v1, u32 index, const void *vxr)
244cb2a1dd5SHeiko Carstens {
245cb2a1dd5SHeiko Carstens 	unsigned int size;
246cb2a1dd5SHeiko Carstens 
247cb2a1dd5SHeiko Carstens 	size = min(index + 1, sizeof(__vector128));
248cb2a1dd5SHeiko Carstens 	instrument_read(vxr, size);
249cb2a1dd5SHeiko Carstens 	asm volatile("\n"
250cb2a1dd5SHeiko Carstens 		"	la	1,%[vxr]\n"
251cb2a1dd5SHeiko Carstens 		"	VLL	%[v1],%[index],0,1\n"
252cb2a1dd5SHeiko Carstens 		:
253cb2a1dd5SHeiko Carstens 		: [vxr] "R" (*(u8 *)vxr),
254cb2a1dd5SHeiko Carstens 		  [index] "d" (index),
255cb2a1dd5SHeiko Carstens 		  [v1] "I" (v1)
256cb2a1dd5SHeiko Carstens 		: "memory", "1");
257cb2a1dd5SHeiko Carstens }
258cb2a1dd5SHeiko Carstens 
259cb2a1dd5SHeiko Carstens #else /* CONFIG_CC_IS_CLANG */
260cb2a1dd5SHeiko Carstens 
fpu_vll(u8 v1,u32 index,const void * vxr)261cb2a1dd5SHeiko Carstens static __always_inline void fpu_vll(u8 v1, u32 index, const void *vxr)
262cb2a1dd5SHeiko Carstens {
263cb2a1dd5SHeiko Carstens 	unsigned int size;
264cb2a1dd5SHeiko Carstens 
265cb2a1dd5SHeiko Carstens 	size = min(index + 1, sizeof(__vector128));
266cb2a1dd5SHeiko Carstens 	instrument_read(vxr, size);
267cb2a1dd5SHeiko Carstens 	asm volatile("VLL	%[v1],%[index],%O[vxr],%R[vxr]\n"
268cb2a1dd5SHeiko Carstens 		     :
269cb2a1dd5SHeiko Carstens 		     : [vxr] "Q" (*(u8 *)vxr),
270cb2a1dd5SHeiko Carstens 		       [index] "d" (index),
271cb2a1dd5SHeiko Carstens 		       [v1] "I" (v1)
272cb2a1dd5SHeiko Carstens 		     : "memory");
273cb2a1dd5SHeiko Carstens }
274cb2a1dd5SHeiko Carstens 
275cb2a1dd5SHeiko Carstens #endif /* CONFIG_CC_IS_CLANG */
276cb2a1dd5SHeiko Carstens 
2773a5866a0SHeiko Carstens #ifdef CONFIG_CC_IS_CLANG
2783a5866a0SHeiko Carstens 
279cad8c3abSHeiko Carstens #define fpu_vlm(_v1, _v3, _vxrs)					\
280cad8c3abSHeiko Carstens ({									\
2813a5866a0SHeiko Carstens 	unsigned int size = ((_v3) - (_v1) + 1) * sizeof(__vector128);	\
2823a5866a0SHeiko Carstens 	struct {							\
2833a5866a0SHeiko Carstens 		__vector128 _v[(_v3) - (_v1) + 1];			\
2843a5866a0SHeiko Carstens 	} *_v = (void *)(_vxrs);					\
2853a5866a0SHeiko Carstens 									\
2863a5866a0SHeiko Carstens 	instrument_read(_v, size);					\
2873a5866a0SHeiko Carstens 	asm volatile("\n"						\
2883a5866a0SHeiko Carstens 		"	la	1,%[vxrs]\n"				\
2893a5866a0SHeiko Carstens 		"	VLM	%[v1],%[v3],0,1\n"			\
2903a5866a0SHeiko Carstens 		:							\
2913a5866a0SHeiko Carstens 		: [vxrs] "R" (*_v),					\
2923a5866a0SHeiko Carstens 		  [v1] "I" (_v1), [v3] "I" (_v3)			\
2933a5866a0SHeiko Carstens 		: "memory", "1");					\
294cad8c3abSHeiko Carstens 	(_v3) - (_v1) + 1;						\
295cad8c3abSHeiko Carstens })
2963a5866a0SHeiko Carstens 
2973a5866a0SHeiko Carstens #else /* CONFIG_CC_IS_CLANG */
2983a5866a0SHeiko Carstens 
299cad8c3abSHeiko Carstens #define fpu_vlm(_v1, _v3, _vxrs)					\
300cad8c3abSHeiko Carstens ({									\
3013a5866a0SHeiko Carstens 	unsigned int size = ((_v3) - (_v1) + 1) * sizeof(__vector128);	\
3023a5866a0SHeiko Carstens 	struct {							\
3033a5866a0SHeiko Carstens 		__vector128 _v[(_v3) - (_v1) + 1];			\
3043a5866a0SHeiko Carstens 	} *_v = (void *)(_vxrs);					\
3053a5866a0SHeiko Carstens 									\
3063a5866a0SHeiko Carstens 	instrument_read(_v, size);					\
3073a5866a0SHeiko Carstens 	asm volatile("VLM	%[v1],%[v3],%O[vxrs],%R[vxrs]\n"	\
3083a5866a0SHeiko Carstens 		     :							\
3093a5866a0SHeiko Carstens 		     : [vxrs] "Q" (*_v),				\
3103a5866a0SHeiko Carstens 		       [v1] "I" (_v1), [v3] "I" (_v3)			\
3113a5866a0SHeiko Carstens 		     : "memory");					\
312cad8c3abSHeiko Carstens 	(_v3) - (_v1) + 1;						\
313cad8c3abSHeiko Carstens })
3143a5866a0SHeiko Carstens 
3153a5866a0SHeiko Carstens #endif /* CONFIG_CC_IS_CLANG */
3163a5866a0SHeiko Carstens 
fpu_vlr(u8 v1,u8 v2)317c8dde11dSHeiko Carstens static __always_inline void fpu_vlr(u8 v1, u8 v2)
318c8dde11dSHeiko Carstens {
319c8dde11dSHeiko Carstens 	asm volatile("VLR	%[v1],%[v2]"
320c8dde11dSHeiko Carstens 		     :
321c8dde11dSHeiko Carstens 		     : [v1] "I" (v1), [v2] "I" (v2)
322c8dde11dSHeiko Carstens 		     : "memory");
323c8dde11dSHeiko Carstens }
324c8dde11dSHeiko Carstens 
fpu_vlvgf(u8 v,u32 val,u16 index)325cb2a1dd5SHeiko Carstens static __always_inline void fpu_vlvgf(u8 v, u32 val, u16 index)
326cb2a1dd5SHeiko Carstens {
327cb2a1dd5SHeiko Carstens 	asm volatile("VLVGF	%[v],%[val],%[index]"
328cb2a1dd5SHeiko Carstens 		     :
329cb2a1dd5SHeiko Carstens 		     : [v] "I" (v), [val] "d" (val), [index] "L" (index)
330cb2a1dd5SHeiko Carstens 		     : "memory");
331cb2a1dd5SHeiko Carstens }
332cb2a1dd5SHeiko Carstens 
fpu_vn(u8 v1,u8 v2,u8 v3)333c8dde11dSHeiko Carstens static __always_inline void fpu_vn(u8 v1, u8 v2, u8 v3)
334c8dde11dSHeiko Carstens {
335c8dde11dSHeiko Carstens 	asm volatile("VN	%[v1],%[v2],%[v3]"
336c8dde11dSHeiko Carstens 		     :
337c8dde11dSHeiko Carstens 		     : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3)
338c8dde11dSHeiko Carstens 		     : "memory");
339c8dde11dSHeiko Carstens }
340c8dde11dSHeiko Carstens 
fpu_vperm(u8 v1,u8 v2,u8 v3,u8 v4)341*37346951SHeiko Carstens static __always_inline void fpu_vperm(u8 v1, u8 v2, u8 v3, u8 v4)
342*37346951SHeiko Carstens {
343*37346951SHeiko Carstens 	asm volatile("VPERM	%[v1],%[v2],%[v3],%[v4]"
344*37346951SHeiko Carstens 		     :
345*37346951SHeiko Carstens 		     : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3), [v4] "I" (v4)
346*37346951SHeiko Carstens 		     : "memory");
347*37346951SHeiko Carstens }
348*37346951SHeiko Carstens 
fpu_vrepib(u8 v1,s16 i2)349c8dde11dSHeiko Carstens static __always_inline void fpu_vrepib(u8 v1, s16 i2)
350c8dde11dSHeiko Carstens {
351c8dde11dSHeiko Carstens 	asm volatile("VREPIB	%[v1],%[i2]"
352c8dde11dSHeiko Carstens 		     :
353c8dde11dSHeiko Carstens 		     : [v1] "I" (v1), [i2] "K" (i2)
354c8dde11dSHeiko Carstens 		     : "memory");
355c8dde11dSHeiko Carstens }
356c8dde11dSHeiko Carstens 
fpu_vsrlb(u8 v1,u8 v2,u8 v3)357*37346951SHeiko Carstens static __always_inline void fpu_vsrlb(u8 v1, u8 v2, u8 v3)
358*37346951SHeiko Carstens {
359*37346951SHeiko Carstens 	asm volatile("VSRLB	%[v1],%[v2],%[v3]"
360*37346951SHeiko Carstens 		     :
361*37346951SHeiko Carstens 		     : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3)
362*37346951SHeiko Carstens 		     : "memory");
363*37346951SHeiko Carstens }
364*37346951SHeiko Carstens 
3653a5866a0SHeiko Carstens #ifdef CONFIG_CC_IS_CLANG
3663a5866a0SHeiko Carstens 
fpu_vst(u8 v1,const void * vxr)367dcd3e1deSHeiko Carstens static __always_inline void fpu_vst(u8 v1, const void *vxr)
368dcd3e1deSHeiko Carstens {
369dcd3e1deSHeiko Carstens 	instrument_write(vxr, sizeof(__vector128));
370dcd3e1deSHeiko Carstens 	asm volatile("\n"
371dcd3e1deSHeiko Carstens 		"	la	1,%[vxr]\n"
372dcd3e1deSHeiko Carstens 		"	VST	%[v1],0,,1\n"
373dcd3e1deSHeiko Carstens 		: [vxr] "=R" (*(__vector128 *)vxr)
374dcd3e1deSHeiko Carstens 		: [v1] "I" (v1)
375dcd3e1deSHeiko Carstens 		: "memory", "1");
376dcd3e1deSHeiko Carstens }
377dcd3e1deSHeiko Carstens 
378dcd3e1deSHeiko Carstens #else /* CONFIG_CC_IS_CLANG */
379dcd3e1deSHeiko Carstens 
fpu_vst(u8 v1,const void * vxr)380dcd3e1deSHeiko Carstens static __always_inline void fpu_vst(u8 v1, const void *vxr)
381dcd3e1deSHeiko Carstens {
382dcd3e1deSHeiko Carstens 	instrument_write(vxr, sizeof(__vector128));
383dcd3e1deSHeiko Carstens 	asm volatile("VST	%[v1],%O[vxr],,%R[vxr]\n"
384dcd3e1deSHeiko Carstens 		     : [vxr] "=Q" (*(__vector128 *)vxr)
385dcd3e1deSHeiko Carstens 		     : [v1] "I" (v1)
386dcd3e1deSHeiko Carstens 		     : "memory");
387dcd3e1deSHeiko Carstens }
388dcd3e1deSHeiko Carstens 
389dcd3e1deSHeiko Carstens #endif /* CONFIG_CC_IS_CLANG */
390dcd3e1deSHeiko Carstens 
391dcd3e1deSHeiko Carstens #ifdef CONFIG_CC_IS_CLANG
392dcd3e1deSHeiko Carstens 
fpu_vstl(u8 v1,u32 index,const void * vxr)393dcd3e1deSHeiko Carstens static __always_inline void fpu_vstl(u8 v1, u32 index, const void *vxr)
394dcd3e1deSHeiko Carstens {
395dcd3e1deSHeiko Carstens 	unsigned int size;
396dcd3e1deSHeiko Carstens 
397dcd3e1deSHeiko Carstens 	size = min(index + 1, sizeof(__vector128));
398dcd3e1deSHeiko Carstens 	instrument_write(vxr, size);
399dcd3e1deSHeiko Carstens 	asm volatile("\n"
400dcd3e1deSHeiko Carstens 		"	la	1,%[vxr]\n"
401dcd3e1deSHeiko Carstens 		"	VSTL	%[v1],%[index],0,1\n"
402dcd3e1deSHeiko Carstens 		: [vxr] "=R" (*(u8 *)vxr)
403dcd3e1deSHeiko Carstens 		: [index] "d" (index), [v1] "I" (v1)
404dcd3e1deSHeiko Carstens 		: "memory", "1");
405dcd3e1deSHeiko Carstens }
406dcd3e1deSHeiko Carstens 
407dcd3e1deSHeiko Carstens #else /* CONFIG_CC_IS_CLANG */
408dcd3e1deSHeiko Carstens 
fpu_vstl(u8 v1,u32 index,const void * vxr)409dcd3e1deSHeiko Carstens static __always_inline void fpu_vstl(u8 v1, u32 index, const void *vxr)
410dcd3e1deSHeiko Carstens {
411dcd3e1deSHeiko Carstens 	unsigned int size;
412dcd3e1deSHeiko Carstens 
413dcd3e1deSHeiko Carstens 	size = min(index + 1, sizeof(__vector128));
414dcd3e1deSHeiko Carstens 	instrument_write(vxr, size);
415dcd3e1deSHeiko Carstens 	asm volatile("VSTL	%[v1],%[index],%O[vxr],%R[vxr]\n"
416dcd3e1deSHeiko Carstens 		     : [vxr] "=Q" (*(u8 *)vxr)
417dcd3e1deSHeiko Carstens 		     : [index] "d" (index), [v1] "I" (v1)
418dcd3e1deSHeiko Carstens 		     : "memory");
419dcd3e1deSHeiko Carstens }
420dcd3e1deSHeiko Carstens 
421dcd3e1deSHeiko Carstens #endif /* CONFIG_CC_IS_CLANG */
422dcd3e1deSHeiko Carstens 
423dcd3e1deSHeiko Carstens #ifdef CONFIG_CC_IS_CLANG
424dcd3e1deSHeiko Carstens 
425cad8c3abSHeiko Carstens #define fpu_vstm(_v1, _v3, _vxrs)					\
426cad8c3abSHeiko Carstens ({									\
4273a5866a0SHeiko Carstens 	unsigned int size = ((_v3) - (_v1) + 1) * sizeof(__vector128);	\
4283a5866a0SHeiko Carstens 	struct {							\
4293a5866a0SHeiko Carstens 		__vector128 _v[(_v3) - (_v1) + 1];			\
4303a5866a0SHeiko Carstens 	} *_v = (void *)(_vxrs);					\
4313a5866a0SHeiko Carstens 									\
4323a5866a0SHeiko Carstens 	instrument_write(_v, size);					\
4333a5866a0SHeiko Carstens 	asm volatile("\n"						\
4343a5866a0SHeiko Carstens 		"	la	1,%[vxrs]\n"				\
4353a5866a0SHeiko Carstens 		"	VSTM	%[v1],%[v3],0,1\n"			\
4363a5866a0SHeiko Carstens 		: [vxrs] "=R" (*_v)					\
4373a5866a0SHeiko Carstens 		: [v1] "I" (_v1), [v3] "I" (_v3)			\
4383a5866a0SHeiko Carstens 		: "memory", "1");					\
439cad8c3abSHeiko Carstens 	(_v3) - (_v1) + 1;						\
440cad8c3abSHeiko Carstens })
4413a5866a0SHeiko Carstens 
4423a5866a0SHeiko Carstens #else /* CONFIG_CC_IS_CLANG */
4433a5866a0SHeiko Carstens 
444cad8c3abSHeiko Carstens #define fpu_vstm(_v1, _v3, _vxrs)					\
445cad8c3abSHeiko Carstens ({									\
4463a5866a0SHeiko Carstens 	unsigned int size = ((_v3) - (_v1) + 1) * sizeof(__vector128);	\
4473a5866a0SHeiko Carstens 	struct {							\
4483a5866a0SHeiko Carstens 		__vector128 _v[(_v3) - (_v1) + 1];			\
4493a5866a0SHeiko Carstens 	} *_v = (void *)(_vxrs);					\
4503a5866a0SHeiko Carstens 									\
4513a5866a0SHeiko Carstens 	instrument_write(_v, size);					\
4523a5866a0SHeiko Carstens 	asm volatile("VSTM	%[v1],%[v3],%O[vxrs],%R[vxrs]\n"	\
4533a5866a0SHeiko Carstens 		     : [vxrs] "=Q" (*_v)				\
4543a5866a0SHeiko Carstens 		     : [v1] "I" (_v1), [v3] "I" (_v3)			\
4553a5866a0SHeiko Carstens 		     : "memory");					\
456cad8c3abSHeiko Carstens 	(_v3) - (_v1) + 1;						\
457cad8c3abSHeiko Carstens })
4583a5866a0SHeiko Carstens 
4593a5866a0SHeiko Carstens #endif /* CONFIG_CC_IS_CLANG */
4603a5866a0SHeiko Carstens 
fpu_vupllf(u8 v1,u8 v2)461*37346951SHeiko Carstens static __always_inline void fpu_vupllf(u8 v1, u8 v2)
462*37346951SHeiko Carstens {
463*37346951SHeiko Carstens 	asm volatile("VUPLLF	%[v1],%[v2]"
464*37346951SHeiko Carstens 		     :
465*37346951SHeiko Carstens 		     : [v1] "I" (v1), [v2] "I" (v2)
466*37346951SHeiko Carstens 		     : "memory");
467*37346951SHeiko Carstens }
468*37346951SHeiko Carstens 
fpu_vx(u8 v1,u8 v2,u8 v3)469c8dde11dSHeiko Carstens static __always_inline void fpu_vx(u8 v1, u8 v2, u8 v3)
470c8dde11dSHeiko Carstens {
471c8dde11dSHeiko Carstens 	asm volatile("VX	%[v1],%[v2],%[v3]"
472c8dde11dSHeiko Carstens 		     :
473c8dde11dSHeiko Carstens 		     : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3)
474c8dde11dSHeiko Carstens 		     : "memory");
475c8dde11dSHeiko Carstens }
476c8dde11dSHeiko Carstens 
fpu_vzero(u8 v)477cb2a1dd5SHeiko Carstens static __always_inline void fpu_vzero(u8 v)
478cb2a1dd5SHeiko Carstens {
479cb2a1dd5SHeiko Carstens 	asm volatile("VZERO	%[v]"
480cb2a1dd5SHeiko Carstens 		     :
481cb2a1dd5SHeiko Carstens 		     : [v] "I" (v)
482cb2a1dd5SHeiko Carstens 		     : "memory");
483cb2a1dd5SHeiko Carstens }
484cb2a1dd5SHeiko Carstens 
485fd2527f2SHeiko Carstens #endif /* __ASSEMBLY__ */
486fd2527f2SHeiko Carstens #endif	/* __ASM_S390_FPU_INSN_H */
487