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) 1995, 1996, 1997 by Ralf Baechle
7 * Copyright (C) 2002  Maciej W. Rozycki
8 *
9 * Some useful macros for MIPS assembler code
10 *
11 * Some of the routines below contain useless nops that will be optimized
12 * away by gas in -O mode. These nops are however required to fill delay
13 * slots in noreorder mode.
14 */
15#ifndef	__ASM_ASM_H
16#define	__ASM_ASM_H
17
18#include <linux/config.h>
19#include <asm/sgidefs.h>
20
21#ifndef CAT
22#ifdef __STDC__
23#define __CAT(str1,str2) str1##str2
24#else
25#define __CAT(str1,str2) str1/**/str2
26#endif
27#define CAT(str1,str2) __CAT(str1,str2)
28#endif
29
30/*
31 * PIC specific declarations
32 * Not used for the kernel but here seems to be the right place.
33 */
34#ifdef __PIC__
35#define CPRESTORE(register)                             \
36		.cprestore register
37#define CPADD(register)                                 \
38		.cpadd	register
39#define CPLOAD(register)                                \
40		.cpload	register
41#else
42#define CPRESTORE(register)
43#define CPADD(register)
44#define CPLOAD(register)
45#endif
46
47/*
48 * LEAF - declare leaf routine
49 */
50#define	LEAF(symbol)                                    \
51		.globl	symbol;                         \
52		.align	2;                              \
53		.type	symbol,@function;               \
54		.ent	symbol,0;                       \
55symbol:		.frame	sp,0,ra
56
57/*
58 * NESTED - declare nested routine entry point
59 */
60#define	NESTED(symbol, framesize, rpc)                  \
61		.globl	symbol;                         \
62		.align	2;                              \
63		.type	symbol,@function;               \
64		.ent	symbol,0;                       \
65symbol:		.frame	sp, framesize, rpc
66
67/*
68 * END - mark end of function
69 */
70#define	END(function)                                   \
71		.end	function;		        \
72		.size	function,.-function
73
74/*
75 * EXPORT - export definition of symbol
76 */
77#define EXPORT(symbol)					\
78		.globl	symbol;                         \
79symbol:
80
81/*
82 * FEXPORT - export definition of a function symbol
83 */
84#define FEXPORT(symbol)					\
85		.globl	symbol;				\
86		.type	symbol,@function;		\
87symbol:
88
89/*
90 * ABS - export absolute symbol
91 */
92#define	ABS(symbol,value)                               \
93		.globl	symbol;                         \
94symbol		=	value
95
96#define	PANIC(msg)                                      \
97		.set	push;				\
98		.set	reorder;                        \
99		PTR_LA	a0,8f;                          \
100		jal	panic;                          \
1019:		b	9b;                             \
102		.set	pop;				\
103		TEXT(msg)
104
105/*
106 * Print formatted string
107 */
108#define PRINT(string)                                   \
109		.set	push;				\
110		.set	reorder;                        \
111		PTR_LA	a0,8f;                          \
112		jal	printk;                         \
113		.set	pop;				\
114		TEXT(string)
115
116#define	TEXT(msg)                                       \
117		.pushsection .data;			\
1188:		.asciiz	msg;                            \
119		.popsection;
120
121/*
122 * Build text tables
123 */
124#define TTABLE(string)                                  \
125		.pushsection .text;			\
126		.word	1f;                             \
127		.popsection				\
128		.pushsection .data;			\
1291:		.asciiz	string;                         \
130		.popsection
131
132/*
133 * MIPS IV pref instruction.
134 * Use with .set noreorder only!
135 *
136 * MIPS IV implementations are free to treat this as a nop.  The R5000
137 * is one of them.  So we should have an option not to use this instruction.
138 */
139#if CONFIG_CPU_HAS_PREFETCH
140
141#define PREF(hint,addr)                                 \
142		.set	push;				\
143		.set	mips4;				\
144		pref	hint,addr;			\
145		.set	pop
146
147#define PREFX(hint,addr)                                \
148		.set	push;				\
149		.set	mips4;				\
150		prefx	hint,addr;			\
151		.set	pop
152
153#else /* !CONFIG_CPU_HAS_PREFETCH */
154
155#define PREF(hint,addr)
156#define PREFX(hint,addr)
157
158#endif /* !CONFIG_CPU_HAS_PREFETCH */
159
160/*
161 * MIPS ISA IV/V movn/movz instructions and equivalents for older CPUs.
162 */
163#if _MIPS_ISA == _MIPS_ISA_MIPS1
164#define MOVN(rd,rs,rt)                                  \
165		.set	push;				\
166		.set	reorder;			\
167		beqz	rt,9f;                          \
168		move	rd,rs;                          \
169		.set	pop;				\
1709:
171#define MOVZ(rd,rs,rt)                                  \
172		.set	push;				\
173		.set	reorder;			\
174		bnez	rt,9f;                          \
175		move	rd,rs;                          \
176		.set	pop;				\
1779:
178#endif /* _MIPS_ISA == _MIPS_ISA_MIPS1 */
179#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3)
180#define MOVN(rd,rs,rt)                                  \
181		.set	push;				\
182		.set	noreorder;			\
183		bnezl	rt,9f;                          \
184		 move	rd,rs;                          \
185		.set	pop;				\
1869:
187#define MOVZ(rd,rs,rt)                                  \
188		.set	push;				\
189		.set	noreorder;			\
190		beqzl	rt,9f;                          \
191		 move	rd,rs;                          \
192		.set	pop;				\
1939:
194#endif /* (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) */
195#if (_MIPS_ISA == _MIPS_ISA_MIPS4 ) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \
196    (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
197#define MOVN(rd,rs,rt)                                  \
198		movn	rd,rs,rt
199#define MOVZ(rd,rs,rt)                                  \
200		movz	rd,rs,rt
201#endif /* MIPS IV, MIPS V, MIPS32 or MIPS64 */
202
203/*
204 * Stack alignment
205 */
206#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \
207    (_MIPS_ISA == _MIPS_ISA_MIPS32)
208#define ALSZ	7
209#define ALMASK	~7
210#endif
211#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
212    (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
213#define ALSZ	15
214#define ALMASK	~15
215#endif
216
217/*
218 * Macros to handle different pointer/register sizes for 32/64-bit code
219 */
220
221/*
222 * Size of a register
223 */
224#ifdef __mips64
225#define SZREG	8
226#else
227#define SZREG	4
228#endif
229
230/*
231 * Use the following macros in assemblercode to load/store registers,
232 * pointers etc.
233 */
234#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \
235    (_MIPS_ISA == _MIPS_ISA_MIPS32)
236#define REG_S		sw
237#define REG_L		lw
238#define REG_SUBU	subu
239#define REG_ADDU	addu
240#endif
241#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
242    (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
243#define REG_S		sd
244#define REG_L		ld
245#define REG_SUBU	dsubu
246#define REG_ADDU	daddu
247#endif
248
249/*
250 * How to add/sub/load/store/shift C int variables.
251 */
252#if _MIPS_SZINT == 32
253#define INT_ADD		add
254#define INT_ADDU	addu
255#define INT_ADDI	addi
256#define INT_ADDIU	addiu
257#define INT_SUB		sub
258#define INT_SUBU	subu
259#define INT_L		lw
260#define INT_S		sw
261#define INT_SLL		sll
262#define INT_SLLV	sllv
263#define INT_SRL		srl
264#define INT_SRLV	srlv
265#define INT_SRA		sra
266#define INT_SRAV	srav
267#endif
268
269#if _MIPS_SZINT == 64
270#define INT_ADD		dadd
271#define INT_ADDU	daddu
272#define INT_ADDI	daddi
273#define INT_ADDIU	daddiu
274#define INT_SUB		dsub
275#define INT_SUBU	dsubu
276#define INT_L		ld
277#define INT_S		sd
278#define INT_SLL		dsll
279#define INT_SLLV	dsllv
280#define INT_SRL		dsrl
281#define INT_SRLV	dsrlv
282#define INT_SRA		dsra
283#define INT_SRAV	dsrav
284#endif
285
286/*
287 * How to add/sub/load/store/shift C long variables.
288 */
289#if _MIPS_SZLONG == 32
290#define LONG_ADD	add
291#define LONG_ADDU	addu
292#define LONG_ADDI	addi
293#define LONG_ADDIU	addiu
294#define LONG_SUB	sub
295#define LONG_SUBU	subu
296#define LONG_L		lw
297#define LONG_S		sw
298#define LONG_SLL	sll
299#define LONG_SLLV	sllv
300#define LONG_SRL	srl
301#define LONG_SRLV	srlv
302#define LONG_SRA	sra
303#define LONG_SRAV	srav
304#endif
305
306#if _MIPS_SZLONG == 64
307#define LONG_ADD	dadd
308#define LONG_ADDU	daddu
309#define LONG_ADDI	daddi
310#define LONG_ADDIU	daddiu
311#define LONG_SUB	dsub
312#define LONG_SUBU	dsubu
313#define LONG_L		ld
314#define LONG_S		sd
315#define LONG_SLL	dsll
316#define LONG_SLLV	dsllv
317#define LONG_SRL	dsrl
318#define LONG_SRLV	dsrlv
319#define LONG_SRA	dsra
320#define LONG_SRAV	dsrav
321#endif
322
323/*
324 * How to add/sub/load/store/shift pointers.
325 */
326#if _MIPS_SZPTR == 32
327#define PTR_ADD		add
328#define PTR_ADDU	addu
329#define PTR_ADDI	addi
330#define PTR_ADDIU	addiu
331#define PTR_SUB		sub
332#define PTR_SUBU	subu
333#define PTR_L		lw
334#define PTR_S		sw
335#define PTR_LA		la
336#define PTR_SLL		sll
337#define PTR_SLLV	sllv
338#define PTR_SRL		srl
339#define PTR_SRLV	srlv
340#define PTR_SRA		sra
341#define PTR_SRAV	srav
342
343#define PTR_SCALESHIFT	2
344
345#define PTR		.word
346#define PTRSIZE		4
347#define PTRLOG		2
348#endif
349
350#if _MIPS_SZPTR == 64
351#define PTR_ADD		dadd
352#define PTR_ADDU	daddu
353#define PTR_ADDI	daddi
354#define PTR_ADDIU	daddiu
355#define PTR_SUB		dsub
356#define PTR_SUBU	dsubu
357#define PTR_L		ld
358#define PTR_S		sd
359#define PTR_LA		dla
360#define PTR_SLL		dsll
361#define PTR_SLLV	dsllv
362#define PTR_SRL		dsrl
363#define PTR_SRLV	dsrlv
364#define PTR_SRA		dsra
365#define PTR_SRAV	dsrav
366
367#define PTR_SCALESHIFT	3
368
369#define PTR		.dword
370#define PTRSIZE		8
371#define PTRLOG		3
372#endif
373
374/*
375 * Some cp0 registers were extended to 64bit for MIPS III.
376 */
377#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \
378    (_MIPS_ISA == _MIPS_ISA_MIPS32)
379#define MFC0		mfc0
380#define MTC0		mtc0
381#endif
382#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
383    (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
384#define MFC0		dmfc0
385#define MTC0		dmtc0
386#endif
387
388#define SSNOP		sll zero,zero,1
389
390/*
391 * mips32/64 has some extra CP0 register selected by the low bits of
392 * the mfc0/mtc0 instruction. Note that dst and src CANNOT have '$'
393 * signs in them.
394 */
395#define MFC0_SEL(dst, src, sel)\
396	  	.word (0x40000000 | ((dst)<<16) | ((src)<<11) | (sel))
397
398
399#define MTC0_SEL(dst, src, sel)\
400	  	.word (0x40800000 | ((dst)<<16) | ((src)<<11) | (sel))
401
402#endif /* __ASM_ASM_H */
403