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  #include <asm/asm-eva.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  		.cfi_startproc;				\
59  		.insn
60  
61  /*
62   * NESTED - declare nested routine entry point
63   */
64  #define NESTED(symbol, framesize, rpc)			\
65  		.globl	symbol;				\
66  		.align	2;				\
67  		.type	symbol, @function;		\
68  		.ent	symbol, 0;			\
69  symbol:		.frame	sp, framesize, rpc;		\
70  		.cfi_startproc;				\
71  		.insn
72  
73  /*
74   * END - mark end of function
75   */
76  #define END(function)					\
77  		.cfi_endproc;				\
78  		.end	function;			\
79  		.size	function, .-function
80  
81  /*
82   * EXPORT - export definition of symbol
83   */
84  #define EXPORT(symbol)					\
85  		.globl	symbol;				\
86  symbol:
87  
88  /*
89   * FEXPORT - export definition of a function symbol
90   */
91  #define FEXPORT(symbol)					\
92  		.globl	symbol;				\
93  		.type	symbol, @function;		\
94  symbol:		.insn
95  
96  /*
97   * ABS - export absolute symbol
98   */
99  #define ABS(symbol,value)				\
100  		.globl	symbol;				\
101  symbol		=	value
102  
103  #define PANIC(msg)					\
104  		.set	push;				\
105  		.set	reorder;			\
106  		PTR_LA	a0, 8f;				 \
107  		jal	panic;				\
108  9:		b	9b;				\
109  		.set	pop;				\
110  		TEXT(msg)
111  
112  /*
113   * Print formatted string
114   */
115  #ifdef CONFIG_PRINTK
116  #define PRINT(string)					\
117  		.set	push;				\
118  		.set	reorder;			\
119  		PTR_LA	a0, 8f;				 \
120  		jal	printk;				\
121  		.set	pop;				\
122  		TEXT(string)
123  #else
124  #define PRINT(string)
125  #endif
126  
127  #define TEXT(msg)					\
128  		.pushsection .data;			\
129  8:		.asciiz msg;				\
130  		.popsection;
131  
132  /*
133   * Build text tables
134   */
135  #define TTABLE(string)					\
136  		.pushsection .text;			\
137  		.word	1f;				\
138  		.popsection				\
139  		.pushsection .data;			\
140  1:		.asciiz string;				\
141  		.popsection
142  
143  /*
144   * MIPS IV pref instruction.
145   * Use with .set noreorder only!
146   *
147   * MIPS IV implementations are free to treat this as a nop.  The R5000
148   * is one of them.  So we should have an option not to use this instruction.
149   */
150  #ifdef CONFIG_CPU_HAS_PREFETCH
151  
152  #define PREF(hint,addr)					\
153  		.set	push;				\
154  		.set	arch=r5000;			\
155  		pref	hint, addr;			\
156  		.set	pop
157  
158  #define PREFE(hint, addr)				\
159  		.set	push;				\
160  		.set	mips0;				\
161  		.set	eva;				\
162  		prefe	hint, addr;			\
163  		.set	pop
164  
165  #define PREFX(hint,addr)				\
166  		.set	push;				\
167  		.set	arch=r5000;			\
168  		prefx	hint, addr;			\
169  		.set	pop
170  
171  #else /* !CONFIG_CPU_HAS_PREFETCH */
172  
173  #define PREF(hint, addr)
174  #define PREFE(hint, addr)
175  #define PREFX(hint, addr)
176  
177  #endif /* !CONFIG_CPU_HAS_PREFETCH */
178  
179  /*
180   * MIPS ISA IV/V movn/movz instructions and equivalents for older CPUs.
181   */
182  #if (_MIPS_ISA == _MIPS_ISA_MIPS1)
183  #define MOVN(rd, rs, rt)				\
184  		.set	push;				\
185  		.set	reorder;			\
186  		beqz	rt, 9f;				\
187  		move	rd, rs;				\
188  		.set	pop;				\
189  9:
190  #define MOVZ(rd, rs, rt)				\
191  		.set	push;				\
192  		.set	reorder;			\
193  		bnez	rt, 9f;				\
194  		move	rd, rs;				\
195  		.set	pop;				\
196  9:
197  #endif /* _MIPS_ISA == _MIPS_ISA_MIPS1 */
198  #if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3)
199  #define MOVN(rd, rs, rt)				\
200  		.set	push;				\
201  		.set	noreorder;			\
202  		bnezl	rt, 9f;				\
203  		 move	rd, rs;				\
204  		.set	pop;				\
205  9:
206  #define MOVZ(rd, rs, rt)				\
207  		.set	push;				\
208  		.set	noreorder;			\
209  		beqzl	rt, 9f;				\
210  		 move	rd, rs;				\
211  		.set	pop;				\
212  9:
213  #endif /* (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) */
214  #if (_MIPS_ISA == _MIPS_ISA_MIPS4 ) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \
215      (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
216  #define MOVN(rd, rs, rt)				\
217  		movn	rd, rs, rt
218  #define MOVZ(rd, rs, rt)				\
219  		movz	rd, rs, rt
220  #endif /* MIPS IV, MIPS V, MIPS32 or MIPS64 */
221  
222  /*
223   * Stack alignment
224   */
225  #if (_MIPS_SIM == _MIPS_SIM_ABI32)
226  #define ALSZ	7
227  #define ALMASK	~7
228  #endif
229  #if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64)
230  #define ALSZ	15
231  #define ALMASK	~15
232  #endif
233  
234  /*
235   * Macros to handle different pointer/register sizes for 32/64-bit code
236   */
237  
238  /*
239   * Size of a register
240   */
241  #ifdef __mips64
242  #define SZREG	8
243  #else
244  #define SZREG	4
245  #endif
246  
247  /*
248   * Use the following macros in assemblercode to load/store registers,
249   * pointers etc.
250   */
251  #if (_MIPS_SIM == _MIPS_SIM_ABI32)
252  #define REG_S		sw
253  #define REG_L		lw
254  #define REG_SUBU	subu
255  #define REG_ADDU	addu
256  #endif
257  #if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64)
258  #define REG_S		sd
259  #define REG_L		ld
260  #define REG_SUBU	dsubu
261  #define REG_ADDU	daddu
262  #endif
263  
264  /*
265   * How to add/sub/load/store/shift C int variables.
266   */
267  #if (_MIPS_SZINT == 32)
268  #define INT_ADD		add
269  #define INT_ADDU	addu
270  #define INT_ADDI	addi
271  #define INT_ADDIU	addiu
272  #define INT_SUB		sub
273  #define INT_SUBU	subu
274  #define INT_L		lw
275  #define INT_S		sw
276  #define INT_SLL		sll
277  #define INT_SLLV	sllv
278  #define INT_SRL		srl
279  #define INT_SRLV	srlv
280  #define INT_SRA		sra
281  #define INT_SRAV	srav
282  #endif
283  
284  #if (_MIPS_SZINT == 64)
285  #define INT_ADD		dadd
286  #define INT_ADDU	daddu
287  #define INT_ADDI	daddi
288  #define INT_ADDIU	daddiu
289  #define INT_SUB		dsub
290  #define INT_SUBU	dsubu
291  #define INT_L		ld
292  #define INT_S		sd
293  #define INT_SLL		dsll
294  #define INT_SLLV	dsllv
295  #define INT_SRL		dsrl
296  #define INT_SRLV	dsrlv
297  #define INT_SRA		dsra
298  #define INT_SRAV	dsrav
299  #endif
300  
301  /*
302   * How to add/sub/load/store/shift C long variables.
303   */
304  #if (_MIPS_SZLONG == 32)
305  #define LONG_ADD	add
306  #define LONG_ADDU	addu
307  #define LONG_ADDI	addi
308  #define LONG_ADDIU	addiu
309  #define LONG_SUB	sub
310  #define LONG_SUBU	subu
311  #define LONG_L		lw
312  #define LONG_S		sw
313  #define LONG_SP		swp
314  #define LONG_SLL	sll
315  #define LONG_SLLV	sllv
316  #define LONG_SRL	srl
317  #define LONG_SRLV	srlv
318  #define LONG_SRA	sra
319  #define LONG_SRAV	srav
320  
321  #define LONG		.word
322  #define LONGSIZE	4
323  #define LONGMASK	3
324  #define LONGLOG		2
325  #endif
326  
327  #if (_MIPS_SZLONG == 64)
328  #define LONG_ADD	dadd
329  #define LONG_ADDU	daddu
330  #define LONG_ADDI	daddi
331  #define LONG_ADDIU	daddiu
332  #define LONG_SUB	dsub
333  #define LONG_SUBU	dsubu
334  #define LONG_L		ld
335  #define LONG_S		sd
336  #define LONG_SP		sdp
337  #define LONG_SLL	dsll
338  #define LONG_SLLV	dsllv
339  #define LONG_SRL	dsrl
340  #define LONG_SRLV	dsrlv
341  #define LONG_SRA	dsra
342  #define LONG_SRAV	dsrav
343  
344  #define LONG		.dword
345  #define LONGSIZE	8
346  #define LONGMASK	7
347  #define LONGLOG		3
348  #endif
349  
350  /*
351   * How to add/sub/load/store/shift pointers.
352   */
353  #if (_MIPS_SZPTR == 32)
354  #define PTR_ADD		add
355  #define PTR_ADDU	addu
356  #define PTR_ADDI	addi
357  #define PTR_ADDIU	addiu
358  #define PTR_SUB		sub
359  #define PTR_SUBU	subu
360  #define PTR_L		lw
361  #define PTR_S		sw
362  #define PTR_LA		la
363  #define PTR_LI		li
364  #define PTR_SLL		sll
365  #define PTR_SLLV	sllv
366  #define PTR_SRL		srl
367  #define PTR_SRLV	srlv
368  #define PTR_SRA		sra
369  #define PTR_SRAV	srav
370  
371  #define PTR_SCALESHIFT	2
372  
373  #define PTR		.word
374  #define PTRSIZE		4
375  #define PTRLOG		2
376  #endif
377  
378  #if (_MIPS_SZPTR == 64)
379  #define PTR_ADD		dadd
380  #define PTR_ADDU	daddu
381  #define PTR_ADDI	daddi
382  #define PTR_ADDIU	daddiu
383  #define PTR_SUB		dsub
384  #define PTR_SUBU	dsubu
385  #define PTR_L		ld
386  #define PTR_S		sd
387  #define PTR_LA		dla
388  #define PTR_LI		dli
389  #define PTR_SLL		dsll
390  #define PTR_SLLV	dsllv
391  #define PTR_SRL		dsrl
392  #define PTR_SRLV	dsrlv
393  #define PTR_SRA		dsra
394  #define PTR_SRAV	dsrav
395  
396  #define PTR_SCALESHIFT	3
397  
398  #define PTR		.dword
399  #define PTRSIZE		8
400  #define PTRLOG		3
401  #endif
402  
403  /*
404   * Some cp0 registers were extended to 64bit for MIPS III.
405   */
406  #if (_MIPS_SIM == _MIPS_SIM_ABI32)
407  #define MFC0		mfc0
408  #define MTC0		mtc0
409  #endif
410  #if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64)
411  #define MFC0		dmfc0
412  #define MTC0		dmtc0
413  #endif
414  
415  #define SSNOP		sll zero, zero, 1
416  
417  #ifdef CONFIG_SGI_IP28
418  /* Inhibit speculative stores to volatile (e.g.DMA) or invalid addresses. */
419  #include <asm/cacheops.h>
420  #define R10KCBARRIER(addr)  cache   Cache_Barrier, addr;
421  #else
422  #define R10KCBARRIER(addr)
423  #endif
424  
425  #endif /* __ASM_ASM_H */
426