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