GNU Linux-libre 4.19.245-gnu1
[releases.git] / arch / mips / include / asm / msa.h
1 /*
2  * Copyright (C) 2013 Imagination Technologies
3  * Author: Paul Burton <paul.burton@mips.com>
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation;  either version 2 of the  License, or (at your
8  * option) any later version.
9  */
10 #ifndef _ASM_MSA_H
11 #define _ASM_MSA_H
12
13 #include <asm/mipsregs.h>
14
15 #ifndef __ASSEMBLY__
16
17 #include <asm/inst.h>
18
19 extern void _save_msa(struct task_struct *);
20 extern void _restore_msa(struct task_struct *);
21 extern void _init_msa_upper(void);
22
23 extern void read_msa_wr_b(unsigned idx, union fpureg *to);
24 extern void read_msa_wr_h(unsigned idx, union fpureg *to);
25 extern void read_msa_wr_w(unsigned idx, union fpureg *to);
26 extern void read_msa_wr_d(unsigned idx, union fpureg *to);
27
28 /**
29  * read_msa_wr() - Read a single MSA vector register
30  * @idx:        The index of the vector register to read
31  * @to:         The FPU register union to store the registers value in
32  * @fmt:        The format of the data in the vector register
33  *
34  * Read the value of MSA vector register idx into the FPU register
35  * union to, using the format fmt.
36  */
37 static inline void read_msa_wr(unsigned idx, union fpureg *to,
38                                enum msa_2b_fmt fmt)
39 {
40         switch (fmt) {
41         case msa_fmt_b:
42                 read_msa_wr_b(idx, to);
43                 break;
44
45         case msa_fmt_h:
46                 read_msa_wr_h(idx, to);
47                 break;
48
49         case msa_fmt_w:
50                 read_msa_wr_w(idx, to);
51                 break;
52
53         case msa_fmt_d:
54                 read_msa_wr_d(idx, to);
55                 break;
56
57         default:
58                 BUG();
59         }
60 }
61
62 extern void write_msa_wr_b(unsigned idx, union fpureg *from);
63 extern void write_msa_wr_h(unsigned idx, union fpureg *from);
64 extern void write_msa_wr_w(unsigned idx, union fpureg *from);
65 extern void write_msa_wr_d(unsigned idx, union fpureg *from);
66
67 /**
68  * write_msa_wr() - Write a single MSA vector register
69  * @idx:        The index of the vector register to write
70  * @from:       The FPU register union to take the registers value from
71  * @fmt:        The format of the data in the vector register
72  *
73  * Write the value from the FPU register union from into MSA vector
74  * register idx, using the format fmt.
75  */
76 static inline void write_msa_wr(unsigned idx, union fpureg *from,
77                                 enum msa_2b_fmt fmt)
78 {
79         switch (fmt) {
80         case msa_fmt_b:
81                 write_msa_wr_b(idx, from);
82                 break;
83
84         case msa_fmt_h:
85                 write_msa_wr_h(idx, from);
86                 break;
87
88         case msa_fmt_w:
89                 write_msa_wr_w(idx, from);
90                 break;
91
92         case msa_fmt_d:
93                 write_msa_wr_d(idx, from);
94                 break;
95
96         default:
97                 BUG();
98         }
99 }
100
101 static inline void enable_msa(void)
102 {
103         if (cpu_has_msa) {
104                 set_c0_config5(MIPS_CONF5_MSAEN);
105                 enable_fpu_hazard();
106         }
107 }
108
109 static inline void disable_msa(void)
110 {
111         if (cpu_has_msa) {
112                 clear_c0_config5(MIPS_CONF5_MSAEN);
113                 disable_fpu_hazard();
114         }
115 }
116
117 static inline int is_msa_enabled(void)
118 {
119         if (!cpu_has_msa)
120                 return 0;
121
122         return read_c0_config5() & MIPS_CONF5_MSAEN;
123 }
124
125 static inline int thread_msa_context_live(void)
126 {
127         /*
128          * Check cpu_has_msa only if it's a constant. This will allow the
129          * compiler to optimise out code for CPUs without MSA without adding
130          * an extra redundant check for CPUs with MSA.
131          */
132         if (__builtin_constant_p(cpu_has_msa) && !cpu_has_msa)
133                 return 0;
134
135         return test_thread_flag(TIF_MSA_CTX_LIVE);
136 }
137
138 static inline void save_msa(struct task_struct *t)
139 {
140         if (cpu_has_msa)
141                 _save_msa(t);
142 }
143
144 static inline void restore_msa(struct task_struct *t)
145 {
146         if (cpu_has_msa)
147                 _restore_msa(t);
148 }
149
150 static inline void init_msa_upper(void)
151 {
152         /*
153          * Check cpu_has_msa only if it's a constant. This will allow the
154          * compiler to optimise out code for CPUs without MSA without adding
155          * an extra redundant check for CPUs with MSA.
156          */
157         if (__builtin_constant_p(cpu_has_msa) && !cpu_has_msa)
158                 return;
159
160         _init_msa_upper();
161 }
162
163 #ifndef TOOLCHAIN_SUPPORTS_MSA
164 /*
165  * Define assembler macros using .word for the c[ft]cmsa instructions in order
166  * to allow compilation with toolchains that do not support MSA. Once all
167  * toolchains in use support MSA these can be removed.
168  */
169 _ASM_MACRO_2R(cfcmsa, rd, cs,
170         _ASM_INSN_IF_MIPS(0x787e0019 | __cs << 11 | __rd << 6)
171         _ASM_INSN32_IF_MM(0x587e0016 | __cs << 11 | __rd << 6));
172 _ASM_MACRO_2R(ctcmsa, cd, rs,
173         _ASM_INSN_IF_MIPS(0x783e0019 | __rs << 11 | __cd << 6)
174         _ASM_INSN32_IF_MM(0x583e0016 | __rs << 11 | __cd << 6));
175 #define _ASM_SET_MSA ""
176 #else /* TOOLCHAIN_SUPPORTS_MSA */
177 #define _ASM_SET_MSA ".set\tfp=64\n\t"                          \
178                      ".set\tmsa\n\t"
179 #endif
180
181 #define __BUILD_MSA_CTL_REG(name, cs)                           \
182 static inline unsigned int read_msa_##name(void)                \
183 {                                                               \
184         unsigned int reg;                                       \
185         __asm__ __volatile__(                                   \
186         "       .set    push\n"                                 \
187         _ASM_SET_MSA                                            \
188         "       cfcmsa  %0, $" #cs "\n"                         \
189         "       .set    pop\n"                                  \
190         : "=r"(reg));                                           \
191         return reg;                                             \
192 }                                                               \
193                                                                 \
194 static inline void write_msa_##name(unsigned int val)           \
195 {                                                               \
196         __asm__ __volatile__(                                   \
197         "       .set    push\n"                                 \
198         _ASM_SET_MSA                                            \
199         "       ctcmsa  $" #cs ", %0\n"                         \
200         "       .set    pop\n"                                  \
201         : : "r"(val));                                          \
202 }
203
204 __BUILD_MSA_CTL_REG(ir, 0)
205 __BUILD_MSA_CTL_REG(csr, 1)
206 __BUILD_MSA_CTL_REG(access, 2)
207 __BUILD_MSA_CTL_REG(save, 3)
208 __BUILD_MSA_CTL_REG(modify, 4)
209 __BUILD_MSA_CTL_REG(request, 5)
210 __BUILD_MSA_CTL_REG(map, 6)
211 __BUILD_MSA_CTL_REG(unmap, 7)
212
213 #endif /* !__ASSEMBLY__ */
214
215 #define MSA_IR          0
216 #define MSA_CSR         1
217 #define MSA_ACCESS      2
218 #define MSA_SAVE        3
219 #define MSA_MODIFY      4
220 #define MSA_REQUEST     5
221 #define MSA_MAP         6
222 #define MSA_UNMAP       7
223
224 /* MSA Implementation Register (MSAIR) */
225 #define MSA_IR_REVB             0
226 #define MSA_IR_REVF             (_ULCAST_(0xff) << MSA_IR_REVB)
227 #define MSA_IR_PROCB            8
228 #define MSA_IR_PROCF            (_ULCAST_(0xff) << MSA_IR_PROCB)
229 #define MSA_IR_WRPB             16
230 #define MSA_IR_WRPF             (_ULCAST_(0x1) << MSA_IR_WRPB)
231
232 /* MSA Control & Status Register (MSACSR) */
233 #define MSA_CSR_RMB             0
234 #define MSA_CSR_RMF             (_ULCAST_(0x3) << MSA_CSR_RMB)
235 #define MSA_CSR_RM_NEAREST      0
236 #define MSA_CSR_RM_TO_ZERO      1
237 #define MSA_CSR_RM_TO_POS       2
238 #define MSA_CSR_RM_TO_NEG       3
239 #define MSA_CSR_FLAGSB          2
240 #define MSA_CSR_FLAGSF          (_ULCAST_(0x1f) << MSA_CSR_FLAGSB)
241 #define MSA_CSR_FLAGS_IB        2
242 #define MSA_CSR_FLAGS_IF        (_ULCAST_(0x1) << MSA_CSR_FLAGS_IB)
243 #define MSA_CSR_FLAGS_UB        3
244 #define MSA_CSR_FLAGS_UF        (_ULCAST_(0x1) << MSA_CSR_FLAGS_UB)
245 #define MSA_CSR_FLAGS_OB        4
246 #define MSA_CSR_FLAGS_OF        (_ULCAST_(0x1) << MSA_CSR_FLAGS_OB)
247 #define MSA_CSR_FLAGS_ZB        5
248 #define MSA_CSR_FLAGS_ZF        (_ULCAST_(0x1) << MSA_CSR_FLAGS_ZB)
249 #define MSA_CSR_FLAGS_VB        6
250 #define MSA_CSR_FLAGS_VF        (_ULCAST_(0x1) << MSA_CSR_FLAGS_VB)
251 #define MSA_CSR_ENABLESB        7
252 #define MSA_CSR_ENABLESF        (_ULCAST_(0x1f) << MSA_CSR_ENABLESB)
253 #define MSA_CSR_ENABLES_IB      7
254 #define MSA_CSR_ENABLES_IF      (_ULCAST_(0x1) << MSA_CSR_ENABLES_IB)
255 #define MSA_CSR_ENABLES_UB      8
256 #define MSA_CSR_ENABLES_UF      (_ULCAST_(0x1) << MSA_CSR_ENABLES_UB)
257 #define MSA_CSR_ENABLES_OB      9
258 #define MSA_CSR_ENABLES_OF      (_ULCAST_(0x1) << MSA_CSR_ENABLES_OB)
259 #define MSA_CSR_ENABLES_ZB      10
260 #define MSA_CSR_ENABLES_ZF      (_ULCAST_(0x1) << MSA_CSR_ENABLES_ZB)
261 #define MSA_CSR_ENABLES_VB      11
262 #define MSA_CSR_ENABLES_VF      (_ULCAST_(0x1) << MSA_CSR_ENABLES_VB)
263 #define MSA_CSR_CAUSEB          12
264 #define MSA_CSR_CAUSEF          (_ULCAST_(0x3f) << MSA_CSR_CAUSEB)
265 #define MSA_CSR_CAUSE_IB        12
266 #define MSA_CSR_CAUSE_IF        (_ULCAST_(0x1) << MSA_CSR_CAUSE_IB)
267 #define MSA_CSR_CAUSE_UB        13
268 #define MSA_CSR_CAUSE_UF        (_ULCAST_(0x1) << MSA_CSR_CAUSE_UB)
269 #define MSA_CSR_CAUSE_OB        14
270 #define MSA_CSR_CAUSE_OF        (_ULCAST_(0x1) << MSA_CSR_CAUSE_OB)
271 #define MSA_CSR_CAUSE_ZB        15
272 #define MSA_CSR_CAUSE_ZF        (_ULCAST_(0x1) << MSA_CSR_CAUSE_ZB)
273 #define MSA_CSR_CAUSE_VB        16
274 #define MSA_CSR_CAUSE_VF        (_ULCAST_(0x1) << MSA_CSR_CAUSE_VB)
275 #define MSA_CSR_CAUSE_EB        17
276 #define MSA_CSR_CAUSE_EF        (_ULCAST_(0x1) << MSA_CSR_CAUSE_EB)
277 #define MSA_CSR_NXB             18
278 #define MSA_CSR_NXF             (_ULCAST_(0x1) << MSA_CSR_NXB)
279 #define MSA_CSR_FSB             24
280 #define MSA_CSR_FSF             (_ULCAST_(0x1) << MSA_CSR_FSB)
281
282 #endif /* _ASM_MSA_H */