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