summaryrefslogtreecommitdiffstats
path: root/kernel/arch/mips/include/asm/msa.h
blob: af5638b12c756794b72df9adaeee27a828e1ddc7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/*
 * Copyright (C) 2013 Imagination Technologies
 * Author: Paul Burton <paul.burton@imgtec.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 */
#ifndef _ASM_MSA_H
#define _ASM_MSA_H

#include <asm/mipsregs.h>

#ifndef __ASSEMBLY__

extern void _save_msa(struct task_struct *);
extern void _restore_msa(struct task_struct *);
extern void _init_msa_upper(void);

static inline void enable_msa(void)
{
	if (cpu_has_msa) {
		set_c0_config5(MIPS_CONF5_MSAEN);
		enable_fpu_hazard();
	}
}

static inline void disable_msa(void)
{
	if (cpu_has_msa) {
		clear_c0_config5(MIPS_CONF5_MSAEN);
		disable_fpu_hazard();
	}
}

static inline int is_msa_enabled(void)
{
	if (!cpu_has_msa)
		return 0;

	return read_c0_config5() & MIPS_CONF5_MSAEN;
}

static inline int thread_msa_context_live(void)
{
	/*
	 * Check cpu_has_msa only if it's a constant. This will allow the
	 * compiler to optimise out code for CPUs without MSA without adding
	 * an extra redundant check for CPUs with MSA.
	 */
	if (__builtin_constant_p(cpu_has_msa) && !cpu_has_msa)
		return 0;

	return test_thread_flag(TIF_MSA_CTX_LIVE);
}

static inline void save_msa(struct task_struct *t)
{
	if (cpu_has_msa)
		_save_msa(t);
}

static inline void restore_msa(struct task_struct *t)
{
	if (cpu_has_msa)
		_restore_msa(t);
}

#ifdef TOOLCHAIN_SUPPORTS_MSA

#define __BUILD_MSA_CTL_REG(name, cs)				\
static inline unsigned int read_msa_##name(void)		\
{								\
	unsigned int reg;					\
	__asm__ __volatile__(					\
	"	.set	push\n"					\
	"	.set	msa\n"					\
	"	cfcmsa	%0, $" #cs "\n"				\
	"	.set	pop\n"					\
	: "=r"(reg));						\
	return reg;						\
}								\
								\
static inline void write_msa_##name(unsigned int val)		\
{								\
	__asm__ __volatile__(					\
	"	.set	push\n"					\
	"	.set	msa\n"					\
	"	ctcmsa	$" #cs ", %0\n"				\
	"	.set	pop\n"					\
	: : "r"(val));						\
}

#else /* !TOOLCHAIN_SUPPORTS_MSA */

/*
 * Define functions using .word for the c[ft]cmsa instructions in order to
 * allow compilation with toolchains that do not support MSA. Once all
 * toolchains in use support MSA these can be removed.
 */
#ifdef CONFIG_CPU_MICROMIPS
#define CFC_MSA_INSN	0x587e0056
#define CTC_MSA_INSN	0x583e0816
#else
#define CFC_MSA_INSN	0x787e0059
#define CTC_MSA_INSN	0x783e0819
#endif

#define __BUILD_MSA_CTL_REG(name, cs)				\
static inline unsigned int read_msa_##name(void)		\
{								\
	unsigned int reg;					\
	__asm__ __volatile__(					\
	"	.set	push\n"					\
	"	.set	noat\n"					\
	"	.insn\n"					\
	"	.word	%1 | (" #cs " << 11)\n"			\
	"	move	%0, $1\n"				\
	"	.set	pop\n"					\
	: "=r"(reg) : "i"(CFC_MSA_INSN));			\
	return reg;						\
}								\
								\
static inline void write_msa_##name(unsigned int val)		\
{								\
	__asm__ __volatile__(					\
	"	.set	push\n"					\
	"	.set	noat\n"					\
	"	move	$1, %0\n"				\
	"	.insn\n"					\
	"	.word	%1 | (" #cs " << 6)\n"			\
	"	.set	pop\n"					\
	: : "r"(val), "i"(CTC_MSA_INSN));			\
}

#endif /* !TOOLCHAIN_SUPPORTS_MSA */

__BUILD_MSA_CTL_REG(ir, 0)
__BUILD_MSA_CTL_REG(csr, 1)
__BUILD_MSA_CTL_REG(access, 2)
__BUILD_MSA_CTL_REG(save, 3)
__BUILD_MSA_CTL_REG(modify, 4)
__BUILD_MSA_CTL_REG(request, 5)
__BUILD_MSA_CTL_REG(map, 6)
__BUILD_MSA_CTL_REG(unmap, 7)

#endif /* !__ASSEMBLY__ */

#define MSA_IR		0
#define MSA_CSR		1
#define MSA_ACCESS	2
#define MSA_SAVE	3
#define MSA_MODIFY	4
#define MSA_REQUEST	5
#define MSA_MAP		6
#define MSA_UNMAP	7

/* MSA Implementation Register (MSAIR) */
#define MSA_IR_REVB		0
#define MSA_IR_REVF		(_ULCAST_(0xff) << MSA_IR_REVB)
#define MSA_IR_PROCB		8
#define MSA_IR_PROCF		(_ULCAST_(0xff) << MSA_IR_PROCB)
#define MSA_IR_WRPB		16
#define MSA_IR_WRPF		(_ULCAST_(0x1) << MSA_IR_WRPB)

/* MSA Control & Status Register (MSACSR) */
#define MSA_CSR_RMB		0
#define MSA_CSR_RMF		(_ULCAST_(0x3) << MSA_CSR_RMB)
#define MSA_CSR_RM_NEAREST	0
#define MSA_CSR_RM_TO_ZERO	1
#define MSA_CSR_RM_TO_POS	2
#define MSA_CSR_RM_TO_NEG	3
#define MSA_CSR_FLAGSB		2
#define MSA_CSR_FLAGSF		(_ULCAST_(0x1f) << MSA_CSR_FLAGSB)
#define MSA_CSR_FLAGS_IB	2
#define MSA_CSR_FLAGS_IF	(_ULCAST_(0x1) << MSA_CSR_FLAGS_IB)
#define MSA_CSR_FLAGS_UB	3
#define MSA_CSR_FLAGS_UF	(_ULCAST_(0x1) << MSA_CSR_FLAGS_UB)
#define MSA_CSR_FLAGS_OB	4
#define MSA_CSR_FLAGS_OF	(_ULCAST_(0x1) << MSA_CSR_FLAGS_OB)
#define MSA_CSR_FLAGS_ZB	5
#define MSA_CSR_FLAGS_ZF	(_ULCAST_(0x1) << MSA_CSR_FLAGS_ZB)
#define MSA_CSR_FLAGS_VB	6
#define MSA_CSR_FLAGS_VF	(_ULCAST_(0x1) << MSA_CSR_FLAGS_VB)
#define MSA_CSR_ENABLESB	7
#define MSA_CSR_ENABLESF	(_ULCAST_(0x1f) << MSA_CSR_ENABLESB)
#define MSA_CSR_ENABLES_IB	7
#define MSA_CSR_ENABLES_IF	(_ULCAST_(0x1) << MSA_CSR_ENABLES_IB)
#define MSA_CSR_ENABLES_UB	8
#define MSA_CSR_ENABLES_UF	(_ULCAST_(0x1) << MSA_CSR_ENABLES_UB)
#define MSA_CSR_ENABLES_OB	9
#define MSA_CSR_ENABLES_OF	(_ULCAST_(0x1) << MSA_CSR_ENABLES_OB)
#define MSA_CSR_ENABLES_ZB	10
#define MSA_CSR_ENABLES_ZF	(_ULCAST_(0x1) << MSA_CSR_ENABLES_ZB)
#define MSA_CSR_ENABLES_VB	11
#define MSA_CSR_ENABLES_VF	(_ULCAST_(0x1) << MSA_CSR_ENABLES_VB)
#define MSA_CSR_CAUSEB		12
#define MSA_CSR_CAUSEF		(_ULCAST_(0x3f) << MSA_CSR_CAUSEB)
#define MSA_CSR_CAUSE_IB	12
#define MSA_CSR_CAUSE_IF	(_ULCAST_(0x1) << MSA_CSR_CAUSE_IB)
#define MSA_CSR_CAUSE_UB	13
#define MSA_CSR_CAUSE_UF	(_ULCAST_(0x1) << MSA_CSR_CAUSE_UB)
#define MSA_CSR_CAUSE_OB	14
#define MSA_CSR_CAUSE_OF	(_ULCAST_(0x1) << MSA_CSR_CAUSE_OB)
#define MSA_CSR_CAUSE_ZB	15
#define MSA_CSR_CAUSE_ZF	(_ULCAST_(0x1) << MSA_CSR_CAUSE_ZB)
#define MSA_CSR_CAUSE_VB	16
#define MSA_CSR_CAUSE_VF	(_ULCAST_(0x1) << MSA_CSR_CAUSE_VB)
#define MSA_CSR_CAUSE_EB	17
#define MSA_CSR_CAUSE_EF	(_ULCAST_(0x1) << MSA_CSR_CAUSE_EB)
#define MSA_CSR_NXB		18
#define MSA_CSR_NXF		(_ULCAST_(0x1) << MSA_CSR_NXB)
#define MSA_CSR_FSB		24
#define MSA_CSR_FSF		(_ULCAST_(0x1) << MSA_CSR_FSB)

#endif /* _ASM_MSA_H */