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