These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / arch / mips / include / asm / msa.h
1 /*
2  * Copyright (C) 2013 Imagination Technologies
3  * Author: Paul Burton <paul.burton@imgtec.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 #ifdef TOOLCHAIN_SUPPORTS_MSA
151
152 #define __BUILD_MSA_CTL_REG(name, cs)                           \
153 static inline unsigned int read_msa_##name(void)                \
154 {                                                               \
155         unsigned int reg;                                       \
156         __asm__ __volatile__(                                   \
157         "       .set    push\n"                                 \
158         "       .set    msa\n"                                  \
159         "       cfcmsa  %0, $" #cs "\n"                         \
160         "       .set    pop\n"                                  \
161         : "=r"(reg));                                           \
162         return reg;                                             \
163 }                                                               \
164                                                                 \
165 static inline void write_msa_##name(unsigned int val)           \
166 {                                                               \
167         __asm__ __volatile__(                                   \
168         "       .set    push\n"                                 \
169         "       .set    msa\n"                                  \
170         "       ctcmsa  $" #cs ", %0\n"                         \
171         "       .set    pop\n"                                  \
172         : : "r"(val));                                          \
173 }
174
175 #else /* !TOOLCHAIN_SUPPORTS_MSA */
176
177 /*
178  * Define functions using .word for the c[ft]cmsa instructions in order to
179  * allow compilation with toolchains that do not support MSA. Once all
180  * toolchains in use support MSA these can be removed.
181  */
182 #ifdef CONFIG_CPU_MICROMIPS
183 #define CFC_MSA_INSN    0x587e0056
184 #define CTC_MSA_INSN    0x583e0816
185 #else
186 #define CFC_MSA_INSN    0x787e0059
187 #define CTC_MSA_INSN    0x783e0819
188 #endif
189
190 #define __BUILD_MSA_CTL_REG(name, cs)                           \
191 static inline unsigned int read_msa_##name(void)                \
192 {                                                               \
193         unsigned int reg;                                       \
194         __asm__ __volatile__(                                   \
195         "       .set    push\n"                                 \
196         "       .set    noat\n"                                 \
197         "       .insn\n"                                        \
198         "       .word   %1 | (" #cs " << 11)\n"                 \
199         "       move    %0, $1\n"                               \
200         "       .set    pop\n"                                  \
201         : "=r"(reg) : "i"(CFC_MSA_INSN));                       \
202         return reg;                                             \
203 }                                                               \
204                                                                 \
205 static inline void write_msa_##name(unsigned int val)           \
206 {                                                               \
207         __asm__ __volatile__(                                   \
208         "       .set    push\n"                                 \
209         "       .set    noat\n"                                 \
210         "       move    $1, %0\n"                               \
211         "       .insn\n"                                        \
212         "       .word   %1 | (" #cs " << 6)\n"                  \
213         "       .set    pop\n"                                  \
214         : : "r"(val), "i"(CTC_MSA_INSN));                       \
215 }
216
217 #endif /* !TOOLCHAIN_SUPPORTS_MSA */
218
219 __BUILD_MSA_CTL_REG(ir, 0)
220 __BUILD_MSA_CTL_REG(csr, 1)
221 __BUILD_MSA_CTL_REG(access, 2)
222 __BUILD_MSA_CTL_REG(save, 3)
223 __BUILD_MSA_CTL_REG(modify, 4)
224 __BUILD_MSA_CTL_REG(request, 5)
225 __BUILD_MSA_CTL_REG(map, 6)
226 __BUILD_MSA_CTL_REG(unmap, 7)
227
228 #endif /* !__ASSEMBLY__ */
229
230 #define MSA_IR          0
231 #define MSA_CSR         1
232 #define MSA_ACCESS      2
233 #define MSA_SAVE        3
234 #define MSA_MODIFY      4
235 #define MSA_REQUEST     5
236 #define MSA_MAP         6
237 #define MSA_UNMAP       7
238
239 /* MSA Implementation Register (MSAIR) */
240 #define MSA_IR_REVB             0
241 #define MSA_IR_REVF             (_ULCAST_(0xff) << MSA_IR_REVB)
242 #define MSA_IR_PROCB            8
243 #define MSA_IR_PROCF            (_ULCAST_(0xff) << MSA_IR_PROCB)
244 #define MSA_IR_WRPB             16
245 #define MSA_IR_WRPF             (_ULCAST_(0x1) << MSA_IR_WRPB)
246
247 /* MSA Control & Status Register (MSACSR) */
248 #define MSA_CSR_RMB             0
249 #define MSA_CSR_RMF             (_ULCAST_(0x3) << MSA_CSR_RMB)
250 #define MSA_CSR_RM_NEAREST      0
251 #define MSA_CSR_RM_TO_ZERO      1
252 #define MSA_CSR_RM_TO_POS       2
253 #define MSA_CSR_RM_TO_NEG       3
254 #define MSA_CSR_FLAGSB          2
255 #define MSA_CSR_FLAGSF          (_ULCAST_(0x1f) << MSA_CSR_FLAGSB)
256 #define MSA_CSR_FLAGS_IB        2
257 #define MSA_CSR_FLAGS_IF        (_ULCAST_(0x1) << MSA_CSR_FLAGS_IB)
258 #define MSA_CSR_FLAGS_UB        3
259 #define MSA_CSR_FLAGS_UF        (_ULCAST_(0x1) << MSA_CSR_FLAGS_UB)
260 #define MSA_CSR_FLAGS_OB        4
261 #define MSA_CSR_FLAGS_OF        (_ULCAST_(0x1) << MSA_CSR_FLAGS_OB)
262 #define MSA_CSR_FLAGS_ZB        5
263 #define MSA_CSR_FLAGS_ZF        (_ULCAST_(0x1) << MSA_CSR_FLAGS_ZB)
264 #define MSA_CSR_FLAGS_VB        6
265 #define MSA_CSR_FLAGS_VF        (_ULCAST_(0x1) << MSA_CSR_FLAGS_VB)
266 #define MSA_CSR_ENABLESB        7
267 #define MSA_CSR_ENABLESF        (_ULCAST_(0x1f) << MSA_CSR_ENABLESB)
268 #define MSA_CSR_ENABLES_IB      7
269 #define MSA_CSR_ENABLES_IF      (_ULCAST_(0x1) << MSA_CSR_ENABLES_IB)
270 #define MSA_CSR_ENABLES_UB      8
271 #define MSA_CSR_ENABLES_UF      (_ULCAST_(0x1) << MSA_CSR_ENABLES_UB)
272 #define MSA_CSR_ENABLES_OB      9
273 #define MSA_CSR_ENABLES_OF      (_ULCAST_(0x1) << MSA_CSR_ENABLES_OB)
274 #define MSA_CSR_ENABLES_ZB      10
275 #define MSA_CSR_ENABLES_ZF      (_ULCAST_(0x1) << MSA_CSR_ENABLES_ZB)
276 #define MSA_CSR_ENABLES_VB      11
277 #define MSA_CSR_ENABLES_VF      (_ULCAST_(0x1) << MSA_CSR_ENABLES_VB)
278 #define MSA_CSR_CAUSEB          12
279 #define MSA_CSR_CAUSEF          (_ULCAST_(0x3f) << MSA_CSR_CAUSEB)
280 #define MSA_CSR_CAUSE_IB        12
281 #define MSA_CSR_CAUSE_IF        (_ULCAST_(0x1) << MSA_CSR_CAUSE_IB)
282 #define MSA_CSR_CAUSE_UB        13
283 #define MSA_CSR_CAUSE_UF        (_ULCAST_(0x1) << MSA_CSR_CAUSE_UB)
284 #define MSA_CSR_CAUSE_OB        14
285 #define MSA_CSR_CAUSE_OF        (_ULCAST_(0x1) << MSA_CSR_CAUSE_OB)
286 #define MSA_CSR_CAUSE_ZB        15
287 #define MSA_CSR_CAUSE_ZF        (_ULCAST_(0x1) << MSA_CSR_CAUSE_ZB)
288 #define MSA_CSR_CAUSE_VB        16
289 #define MSA_CSR_CAUSE_VF        (_ULCAST_(0x1) << MSA_CSR_CAUSE_VB)
290 #define MSA_CSR_CAUSE_EB        17
291 #define MSA_CSR_CAUSE_EF        (_ULCAST_(0x1) << MSA_CSR_CAUSE_EB)
292 #define MSA_CSR_NXB             18
293 #define MSA_CSR_NXF             (_ULCAST_(0x1) << MSA_CSR_NXB)
294 #define MSA_CSR_FSB             24
295 #define MSA_CSR_FSF             (_ULCAST_(0x1) << MSA_CSR_FSB)
296
297 #endif /* _ASM_MSA_H */