1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License.  See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2003 Ralf Baechle
7 */
8#ifndef _ASM_ASMMACRO_H
9#define _ASM_ASMMACRO_H
10
11#include <asm/hazards.h>
12#include <asm/asm-offsets.h>
13#include <asm/msa.h>
14
15#ifdef CONFIG_32BIT
16#include <asm/asmmacro-32.h>
17#endif
18#ifdef CONFIG_64BIT
19#include <asm/asmmacro-64.h>
20#endif
21
22#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
23	.macro	local_irq_enable reg=t0
24	ei
25	irq_enable_hazard
26	.endm
27
28	.macro	local_irq_disable reg=t0
29	di
30	irq_disable_hazard
31	.endm
32#else
33	.macro	local_irq_enable reg=t0
34	mfc0	\reg, CP0_STATUS
35	ori	\reg, \reg, 1
36	mtc0	\reg, CP0_STATUS
37	irq_enable_hazard
38	.endm
39
40	.macro	local_irq_disable reg=t0
41#ifdef CONFIG_PREEMPT
42	lw      \reg, TI_PRE_COUNT($28)
43	addi    \reg, \reg, 1
44	sw      \reg, TI_PRE_COUNT($28)
45#endif
46	mfc0	\reg, CP0_STATUS
47	ori	\reg, \reg, 1
48	xori	\reg, \reg, 1
49	mtc0	\reg, CP0_STATUS
50	irq_disable_hazard
51#ifdef CONFIG_PREEMPT
52	lw      \reg, TI_PRE_COUNT($28)
53	addi    \reg, \reg, -1
54	sw      \reg, TI_PRE_COUNT($28)
55#endif
56	.endm
57#endif /* CONFIG_CPU_MIPSR2 */
58
59	.macro	fpu_save_16even thread tmp=t0
60	.set	push
61	SET_HARDFLOAT
62	cfc1	\tmp, fcr31
63	sdc1	$f0,  THREAD_FPR0(\thread)
64	sdc1	$f2,  THREAD_FPR2(\thread)
65	sdc1	$f4,  THREAD_FPR4(\thread)
66	sdc1	$f6,  THREAD_FPR6(\thread)
67	sdc1	$f8,  THREAD_FPR8(\thread)
68	sdc1	$f10, THREAD_FPR10(\thread)
69	sdc1	$f12, THREAD_FPR12(\thread)
70	sdc1	$f14, THREAD_FPR14(\thread)
71	sdc1	$f16, THREAD_FPR16(\thread)
72	sdc1	$f18, THREAD_FPR18(\thread)
73	sdc1	$f20, THREAD_FPR20(\thread)
74	sdc1	$f22, THREAD_FPR22(\thread)
75	sdc1	$f24, THREAD_FPR24(\thread)
76	sdc1	$f26, THREAD_FPR26(\thread)
77	sdc1	$f28, THREAD_FPR28(\thread)
78	sdc1	$f30, THREAD_FPR30(\thread)
79	sw	\tmp, THREAD_FCR31(\thread)
80	.set	pop
81	.endm
82
83	.macro	fpu_save_16odd thread
84	.set	push
85	.set	mips64r2
86	SET_HARDFLOAT
87	sdc1	$f1,  THREAD_FPR1(\thread)
88	sdc1	$f3,  THREAD_FPR3(\thread)
89	sdc1	$f5,  THREAD_FPR5(\thread)
90	sdc1	$f7,  THREAD_FPR7(\thread)
91	sdc1	$f9,  THREAD_FPR9(\thread)
92	sdc1	$f11, THREAD_FPR11(\thread)
93	sdc1	$f13, THREAD_FPR13(\thread)
94	sdc1	$f15, THREAD_FPR15(\thread)
95	sdc1	$f17, THREAD_FPR17(\thread)
96	sdc1	$f19, THREAD_FPR19(\thread)
97	sdc1	$f21, THREAD_FPR21(\thread)
98	sdc1	$f23, THREAD_FPR23(\thread)
99	sdc1	$f25, THREAD_FPR25(\thread)
100	sdc1	$f27, THREAD_FPR27(\thread)
101	sdc1	$f29, THREAD_FPR29(\thread)
102	sdc1	$f31, THREAD_FPR31(\thread)
103	.set	pop
104	.endm
105
106	.macro	fpu_save_double thread status tmp
107#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
108		defined(CONFIG_CPU_MIPS32_R6)
109	sll	\tmp, \status, 5
110	bgez	\tmp, 10f
111	fpu_save_16odd \thread
11210:
113#endif
114	fpu_save_16even \thread \tmp
115	.endm
116
117	.macro	fpu_restore_16even thread tmp=t0
118	.set	push
119	SET_HARDFLOAT
120	lw	\tmp, THREAD_FCR31(\thread)
121	ldc1	$f0,  THREAD_FPR0(\thread)
122	ldc1	$f2,  THREAD_FPR2(\thread)
123	ldc1	$f4,  THREAD_FPR4(\thread)
124	ldc1	$f6,  THREAD_FPR6(\thread)
125	ldc1	$f8,  THREAD_FPR8(\thread)
126	ldc1	$f10, THREAD_FPR10(\thread)
127	ldc1	$f12, THREAD_FPR12(\thread)
128	ldc1	$f14, THREAD_FPR14(\thread)
129	ldc1	$f16, THREAD_FPR16(\thread)
130	ldc1	$f18, THREAD_FPR18(\thread)
131	ldc1	$f20, THREAD_FPR20(\thread)
132	ldc1	$f22, THREAD_FPR22(\thread)
133	ldc1	$f24, THREAD_FPR24(\thread)
134	ldc1	$f26, THREAD_FPR26(\thread)
135	ldc1	$f28, THREAD_FPR28(\thread)
136	ldc1	$f30, THREAD_FPR30(\thread)
137	ctc1	\tmp, fcr31
138	.endm
139
140	.macro	fpu_restore_16odd thread
141	.set	push
142	.set	mips64r2
143	SET_HARDFLOAT
144	ldc1	$f1,  THREAD_FPR1(\thread)
145	ldc1	$f3,  THREAD_FPR3(\thread)
146	ldc1	$f5,  THREAD_FPR5(\thread)
147	ldc1	$f7,  THREAD_FPR7(\thread)
148	ldc1	$f9,  THREAD_FPR9(\thread)
149	ldc1	$f11, THREAD_FPR11(\thread)
150	ldc1	$f13, THREAD_FPR13(\thread)
151	ldc1	$f15, THREAD_FPR15(\thread)
152	ldc1	$f17, THREAD_FPR17(\thread)
153	ldc1	$f19, THREAD_FPR19(\thread)
154	ldc1	$f21, THREAD_FPR21(\thread)
155	ldc1	$f23, THREAD_FPR23(\thread)
156	ldc1	$f25, THREAD_FPR25(\thread)
157	ldc1	$f27, THREAD_FPR27(\thread)
158	ldc1	$f29, THREAD_FPR29(\thread)
159	ldc1	$f31, THREAD_FPR31(\thread)
160	.set	pop
161	.endm
162
163	.macro	fpu_restore_double thread status tmp
164#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
165		defined(CONFIG_CPU_MIPS32_R6)
166	sll	\tmp, \status, 5
167	bgez	\tmp, 10f				# 16 register mode?
168
169	fpu_restore_16odd \thread
17010:
171#endif
172	fpu_restore_16even \thread \tmp
173	.endm
174
175#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
176	.macro	_EXT	rd, rs, p, s
177	ext	\rd, \rs, \p, \s
178	.endm
179#else /* !CONFIG_CPU_MIPSR2 || !CONFIG_CPU_MIPSR6 */
180	.macro	_EXT	rd, rs, p, s
181	srl	\rd, \rs, \p
182	andi	\rd, \rd, (1 << \s) - 1
183	.endm
184#endif /* !CONFIG_CPU_MIPSR2 || !CONFIG_CPU_MIPSR6 */
185
186/*
187 * Temporary until all gas have MT ASE support
188 */
189	.macro	DMT	reg=0
190	.word	0x41600bc1 | (\reg << 16)
191	.endm
192
193	.macro	EMT	reg=0
194	.word	0x41600be1 | (\reg << 16)
195	.endm
196
197	.macro	DVPE	reg=0
198	.word	0x41600001 | (\reg << 16)
199	.endm
200
201	.macro	EVPE	reg=0
202	.word	0x41600021 | (\reg << 16)
203	.endm
204
205	.macro	MFTR	rt=0, rd=0, u=0, sel=0
206	 .word	0x41000000 | (\rt << 16) | (\rd << 11) | (\u << 5) | (\sel)
207	.endm
208
209	.macro	MTTR	rt=0, rd=0, u=0, sel=0
210	 .word	0x41800000 | (\rt << 16) | (\rd << 11) | (\u << 5) | (\sel)
211	.endm
212
213#ifdef TOOLCHAIN_SUPPORTS_MSA
214	.macro	_cfcmsa	rd, cs
215	.set	push
216	.set	mips32r2
217	.set	msa
218	cfcmsa	\rd, $\cs
219	.set	pop
220	.endm
221
222	.macro	_ctcmsa	cd, rs
223	.set	push
224	.set	mips32r2
225	.set	msa
226	ctcmsa	$\cd, \rs
227	.set	pop
228	.endm
229
230	.macro	ld_d	wd, off, base
231	.set	push
232	.set	mips32r2
233	.set	msa
234	ld.d	$w\wd, \off(\base)
235	.set	pop
236	.endm
237
238	.macro	st_d	wd, off, base
239	.set	push
240	.set	mips32r2
241	.set	msa
242	st.d	$w\wd, \off(\base)
243	.set	pop
244	.endm
245
246	.macro	copy_u_w	ws, n
247	.set	push
248	.set	mips32r2
249	.set	msa
250	copy_u.w $1, $w\ws[\n]
251	.set	pop
252	.endm
253
254	.macro	copy_u_d	ws, n
255	.set	push
256	.set	mips64r2
257	.set	msa
258	copy_u.d $1, $w\ws[\n]
259	.set	pop
260	.endm
261
262	.macro	insert_w	wd, n
263	.set	push
264	.set	mips32r2
265	.set	msa
266	insert.w $w\wd[\n], $1
267	.set	pop
268	.endm
269
270	.macro	insert_d	wd, n
271	.set	push
272	.set	mips64r2
273	.set	msa
274	insert.d $w\wd[\n], $1
275	.set	pop
276	.endm
277#else
278
279#ifdef CONFIG_CPU_MICROMIPS
280#define CFC_MSA_INSN		0x587e0056
281#define CTC_MSA_INSN		0x583e0816
282#define LDD_MSA_INSN		0x58000837
283#define STD_MSA_INSN		0x5800083f
284#define COPY_UW_MSA_INSN	0x58f00056
285#define COPY_UD_MSA_INSN	0x58f80056
286#define INSERT_W_MSA_INSN	0x59300816
287#define INSERT_D_MSA_INSN	0x59380816
288#else
289#define CFC_MSA_INSN		0x787e0059
290#define CTC_MSA_INSN		0x783e0819
291#define LDD_MSA_INSN		0x78000823
292#define STD_MSA_INSN		0x78000827
293#define COPY_UW_MSA_INSN	0x78f00059
294#define COPY_UD_MSA_INSN	0x78f80059
295#define INSERT_W_MSA_INSN	0x79300819
296#define INSERT_D_MSA_INSN	0x79380819
297#endif
298
299	/*
300	 * Temporary until all toolchains in use include MSA support.
301	 */
302	.macro	_cfcmsa	rd, cs
303	.set	push
304	.set	noat
305	SET_HARDFLOAT
306	.insn
307	.word	CFC_MSA_INSN | (\cs << 11)
308	move	\rd, $1
309	.set	pop
310	.endm
311
312	.macro	_ctcmsa	cd, rs
313	.set	push
314	.set	noat
315	SET_HARDFLOAT
316	move	$1, \rs
317	.word	CTC_MSA_INSN | (\cd << 6)
318	.set	pop
319	.endm
320
321	.macro	ld_d	wd, off, base
322	.set	push
323	.set	noat
324	SET_HARDFLOAT
325	addu	$1, \base, \off
326	.word	LDD_MSA_INSN | (\wd << 6)
327	.set	pop
328	.endm
329
330	.macro	st_d	wd, off, base
331	.set	push
332	.set	noat
333	SET_HARDFLOAT
334	addu	$1, \base, \off
335	.word	STD_MSA_INSN | (\wd << 6)
336	.set	pop
337	.endm
338
339	.macro	copy_u_w	ws, n
340	.set	push
341	.set	noat
342	SET_HARDFLOAT
343	.insn
344	.word	COPY_UW_MSA_INSN | (\n << 16) | (\ws << 11)
345	.set	pop
346	.endm
347
348	.macro	copy_u_d	ws, n
349	.set	push
350	.set	noat
351	SET_HARDFLOAT
352	.insn
353	.word	COPY_UD_MSA_INSN | (\n << 16) | (\ws << 11)
354	.set	pop
355	.endm
356
357	.macro	insert_w	wd, n
358	.set	push
359	.set	noat
360	SET_HARDFLOAT
361	.word	INSERT_W_MSA_INSN | (\n << 16) | (\wd << 6)
362	.set	pop
363	.endm
364
365	.macro	insert_d	wd, n
366	.set	push
367	.set	noat
368	SET_HARDFLOAT
369	.word	INSERT_D_MSA_INSN | (\n << 16) | (\wd << 6)
370	.set	pop
371	.endm
372#endif
373
374	.macro	msa_save_all	thread
375	st_d	0, THREAD_FPR0, \thread
376	st_d	1, THREAD_FPR1, \thread
377	st_d	2, THREAD_FPR2, \thread
378	st_d	3, THREAD_FPR3, \thread
379	st_d	4, THREAD_FPR4, \thread
380	st_d	5, THREAD_FPR5, \thread
381	st_d	6, THREAD_FPR6, \thread
382	st_d	7, THREAD_FPR7, \thread
383	st_d	8, THREAD_FPR8, \thread
384	st_d	9, THREAD_FPR9, \thread
385	st_d	10, THREAD_FPR10, \thread
386	st_d	11, THREAD_FPR11, \thread
387	st_d	12, THREAD_FPR12, \thread
388	st_d	13, THREAD_FPR13, \thread
389	st_d	14, THREAD_FPR14, \thread
390	st_d	15, THREAD_FPR15, \thread
391	st_d	16, THREAD_FPR16, \thread
392	st_d	17, THREAD_FPR17, \thread
393	st_d	18, THREAD_FPR18, \thread
394	st_d	19, THREAD_FPR19, \thread
395	st_d	20, THREAD_FPR20, \thread
396	st_d	21, THREAD_FPR21, \thread
397	st_d	22, THREAD_FPR22, \thread
398	st_d	23, THREAD_FPR23, \thread
399	st_d	24, THREAD_FPR24, \thread
400	st_d	25, THREAD_FPR25, \thread
401	st_d	26, THREAD_FPR26, \thread
402	st_d	27, THREAD_FPR27, \thread
403	st_d	28, THREAD_FPR28, \thread
404	st_d	29, THREAD_FPR29, \thread
405	st_d	30, THREAD_FPR30, \thread
406	st_d	31, THREAD_FPR31, \thread
407	.set	push
408	.set	noat
409	SET_HARDFLOAT
410	_cfcmsa	$1, MSA_CSR
411	sw	$1, THREAD_MSA_CSR(\thread)
412	.set	pop
413	.endm
414
415	.macro	msa_restore_all	thread
416	.set	push
417	.set	noat
418	SET_HARDFLOAT
419	lw	$1, THREAD_MSA_CSR(\thread)
420	_ctcmsa	MSA_CSR, $1
421	.set	pop
422	ld_d	0, THREAD_FPR0, \thread
423	ld_d	1, THREAD_FPR1, \thread
424	ld_d	2, THREAD_FPR2, \thread
425	ld_d	3, THREAD_FPR3, \thread
426	ld_d	4, THREAD_FPR4, \thread
427	ld_d	5, THREAD_FPR5, \thread
428	ld_d	6, THREAD_FPR6, \thread
429	ld_d	7, THREAD_FPR7, \thread
430	ld_d	8, THREAD_FPR8, \thread
431	ld_d	9, THREAD_FPR9, \thread
432	ld_d	10, THREAD_FPR10, \thread
433	ld_d	11, THREAD_FPR11, \thread
434	ld_d	12, THREAD_FPR12, \thread
435	ld_d	13, THREAD_FPR13, \thread
436	ld_d	14, THREAD_FPR14, \thread
437	ld_d	15, THREAD_FPR15, \thread
438	ld_d	16, THREAD_FPR16, \thread
439	ld_d	17, THREAD_FPR17, \thread
440	ld_d	18, THREAD_FPR18, \thread
441	ld_d	19, THREAD_FPR19, \thread
442	ld_d	20, THREAD_FPR20, \thread
443	ld_d	21, THREAD_FPR21, \thread
444	ld_d	22, THREAD_FPR22, \thread
445	ld_d	23, THREAD_FPR23, \thread
446	ld_d	24, THREAD_FPR24, \thread
447	ld_d	25, THREAD_FPR25, \thread
448	ld_d	26, THREAD_FPR26, \thread
449	ld_d	27, THREAD_FPR27, \thread
450	ld_d	28, THREAD_FPR28, \thread
451	ld_d	29, THREAD_FPR29, \thread
452	ld_d	30, THREAD_FPR30, \thread
453	ld_d	31, THREAD_FPR31, \thread
454	.endm
455
456	.macro	msa_init_upper wd
457#ifdef CONFIG_64BIT
458	insert_d \wd, 1
459#else
460	insert_w \wd, 2
461	insert_w \wd, 3
462#endif
463	.endm
464
465	.macro	msa_init_all_upper
466	.set	push
467	.set	noat
468	SET_HARDFLOAT
469	not	$1, zero
470	msa_init_upper	0
471	msa_init_upper	1
472	msa_init_upper	2
473	msa_init_upper	3
474	msa_init_upper	4
475	msa_init_upper	5
476	msa_init_upper	6
477	msa_init_upper	7
478	msa_init_upper	8
479	msa_init_upper	9
480	msa_init_upper	10
481	msa_init_upper	11
482	msa_init_upper	12
483	msa_init_upper	13
484	msa_init_upper	14
485	msa_init_upper	15
486	msa_init_upper	16
487	msa_init_upper	17
488	msa_init_upper	18
489	msa_init_upper	19
490	msa_init_upper	20
491	msa_init_upper	21
492	msa_init_upper	22
493	msa_init_upper	23
494	msa_init_upper	24
495	msa_init_upper	25
496	msa_init_upper	26
497	msa_init_upper	27
498	msa_init_upper	28
499	msa_init_upper	29
500	msa_init_upper	30
501	msa_init_upper	31
502	.set	pop
503	.endm
504
505#endif /* _ASM_ASMMACRO_H */
506