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 #include <asm/isa-rev.h>
23 
24 #ifndef __VDSO__
25 /*
26  * Emit CFI data in .debug_frame sections, not .eh_frame sections.
27  * We don't do DWARF unwinding at runtime, so only the offline DWARF
28  * information is useful to anyone. Note we should change this if we
29  * ever decide to enable DWARF unwinding at runtime.
30  */
31 #define CFI_SECTIONS	.cfi_sections .debug_frame
32 #else
33  /*
34   * For the vDSO, emit both runtime unwind information and debug
35   * symbols for the .dbg file.
36   */
37 #define CFI_SECTIONS
38 #endif
39 
40 /*
41  * LEAF - declare leaf routine
42  */
43 #define LEAF(symbol)					\
44 		CFI_SECTIONS;				\
45 		.globl	symbol;				\
46 		.align	2;				\
47 		.type	symbol, @function;		\
48 		.ent	symbol, 0;			\
49 symbol:		.frame	sp, 0, ra;			\
50 		.cfi_startproc;				\
51 		.insn
52 
53 /*
54  * NESTED - declare nested routine entry point
55  */
56 #define NESTED(symbol, framesize, rpc)			\
57 		CFI_SECTIONS;				\
58 		.globl	symbol;				\
59 		.align	2;				\
60 		.type	symbol, @function;		\
61 		.ent	symbol, 0;			\
62 symbol:		.frame	sp, framesize, rpc;		\
63 		.cfi_startproc;				\
64 		.insn
65 
66 /*
67  * END - mark end of function
68  */
69 #define END(function)					\
70 		.cfi_endproc;				\
71 		.end	function;			\
72 		.size	function, .-function
73 
74 /*
75  * EXPORT - export definition of symbol
76  */
77 #define EXPORT(symbol)					\
78 		.globl	symbol;				\
79 symbol:
80 
81 /*
82  * FEXPORT - export definition of a function symbol
83  */
84 #define FEXPORT(symbol)					\
85 		.globl	symbol;				\
86 		.type	symbol, @function;		\
87 symbol:		.insn
88 
89 /*
90  * ABS - export absolute symbol
91  */
92 #define ABS(symbol,value)				\
93 		.globl	symbol;				\
94 symbol		=	value
95 
96 #define TEXT(msg)					\
97 		.pushsection .data;			\
98 8:		.asciiz msg;				\
99 		.popsection;
100 
101 #define ASM_PANIC(msg)					\
102 		.set	push;				\
103 		.set	reorder;			\
104 		PTR_LA	a0, 8f;				\
105 		jal	panic;				\
106 9:		b	9b;				\
107 		.set	pop;				\
108 		TEXT(msg)
109 
110 /*
111  * Print formatted string
112  */
113 #ifdef CONFIG_PRINTK
114 #define ASM_PRINT(string)				\
115 		.set	push;				\
116 		.set	reorder;			\
117 		PTR_LA	a0, 8f;				\
118 		jal	_printk;			\
119 		.set	pop;				\
120 		TEXT(string)
121 #else
122 #define ASM_PRINT(string)
123 #endif
124 
125 /*
126  * Stack alignment
127  */
128 #if (_MIPS_SIM == _MIPS_SIM_ABI32)
129 #define ALSZ	7
130 #define ALMASK	~7
131 #endif
132 #if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64)
133 #define ALSZ	15
134 #define ALMASK	~15
135 #endif
136 
137 /*
138  * Macros to handle different pointer/register sizes for 32/64-bit code
139  */
140 
141 /*
142  * Size of a register
143  */
144 #ifdef __mips64
145 #define SZREG	8
146 #else
147 #define SZREG	4
148 #endif
149 
150 /*
151  * Use the following macros in assemblercode to load/store registers,
152  * pointers etc.
153  */
154 #if (_MIPS_SIM == _MIPS_SIM_ABI32)
155 #define REG_S		sw
156 #define REG_L		lw
157 #define REG_SUBU	subu
158 #define REG_ADDU	addu
159 #endif
160 #if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64)
161 #define REG_S		sd
162 #define REG_L		ld
163 #define REG_SUBU	dsubu
164 #define REG_ADDU	daddu
165 #endif
166 
167 /*
168  * How to add/sub/load/store/shift C int variables.
169  */
170 #if (_MIPS_SZINT == 32)
171 #define INT_ADD		add
172 #define INT_ADDU	addu
173 #define INT_ADDI	addi
174 #define INT_ADDIU	addiu
175 #define INT_SUB		sub
176 #define INT_SUBU	subu
177 #define INT_L		lw
178 #define INT_S		sw
179 #define INT_SLL		sll
180 #define INT_SLLV	sllv
181 #define INT_SRL		srl
182 #define INT_SRLV	srlv
183 #define INT_SRA		sra
184 #define INT_SRAV	srav
185 #endif
186 
187 #if (_MIPS_SZINT == 64)
188 #define INT_ADD		dadd
189 #define INT_ADDU	daddu
190 #define INT_ADDI	daddi
191 #define INT_ADDIU	daddiu
192 #define INT_SUB		dsub
193 #define INT_SUBU	dsubu
194 #define INT_L		ld
195 #define INT_S		sd
196 #define INT_SLL		dsll
197 #define INT_SLLV	dsllv
198 #define INT_SRL		dsrl
199 #define INT_SRLV	dsrlv
200 #define INT_SRA		dsra
201 #define INT_SRAV	dsrav
202 #endif
203 
204 /*
205  * How to add/sub/load/store/shift C long variables.
206  */
207 #if (_MIPS_SZLONG == 32)
208 #define LONG_ADD	add
209 #define LONG_ADDU	addu
210 #define LONG_ADDI	addi
211 #define LONG_ADDIU	addiu
212 #define LONG_SUB	sub
213 #define LONG_SUBU	subu
214 #define LONG_L		lw
215 #define LONG_LL		ll
216 #define LONG_SC		sc
217 #define LONG_S		sw
218 #define LONG_SP		swp
219 #define LONG_SLL	sll
220 #define LONG_SLLV	sllv
221 #define LONG_SRL	srl
222 #define LONG_SRLV	srlv
223 #define LONG_SRA	sra
224 #define LONG_SRAV	srav
225 #define LONG_INS	ins
226 #define LONG_EXT	ext
227 
228 #ifdef __ASSEMBLY__
229 #define LONG		.word
230 #endif
231 #define LONGSIZE	4
232 #define LONGMASK	3
233 #define LONGLOG		2
234 #endif
235 
236 #if (_MIPS_SZLONG == 64)
237 #define LONG_ADD	dadd
238 #define LONG_ADDU	daddu
239 #define LONG_ADDI	daddi
240 #define LONG_ADDIU	daddiu
241 #define LONG_SUB	dsub
242 #define LONG_SUBU	dsubu
243 #define LONG_L		ld
244 #define LONG_LL		lld
245 #define LONG_SC		scd
246 #define LONG_S		sd
247 #define LONG_SP		sdp
248 #define LONG_SLL	dsll
249 #define LONG_SLLV	dsllv
250 #define LONG_SRL	dsrl
251 #define LONG_SRLV	dsrlv
252 #define LONG_SRA	dsra
253 #define LONG_SRAV	dsrav
254 #define LONG_INS	dins
255 #define LONG_EXT	dext
256 
257 #ifdef __ASSEMBLY__
258 #define LONG		.dword
259 #endif
260 #define LONGSIZE	8
261 #define LONGMASK	7
262 #define LONGLOG		3
263 #endif
264 
265 /*
266  * How to add/sub/load/store/shift pointers.
267  */
268 #if (_MIPS_SZPTR == 32)
269 #define PTR_ADD		add
270 #define PTR_ADDU	addu
271 #define PTR_ADDI	addi
272 #define PTR_ADDIU	addiu
273 #define PTR_SUB		sub
274 #define PTR_SUBU	subu
275 #define PTR_L		lw
276 #define PTR_S		sw
277 #define PTR_LA		la
278 #define PTR_LI		li
279 #define PTR_SLL		sll
280 #define PTR_SLLV	sllv
281 #define PTR_SRL		srl
282 #define PTR_SRLV	srlv
283 #define PTR_SRA		sra
284 #define PTR_SRAV	srav
285 
286 #define PTR_SCALESHIFT	2
287 
288 #define PTR_WD		.word
289 #define PTRSIZE		4
290 #define PTRLOG		2
291 #endif
292 
293 #if (_MIPS_SZPTR == 64)
294 #define PTR_ADD		dadd
295 #define PTR_ADDU	daddu
296 #define PTR_ADDI	daddi
297 #define PTR_ADDIU	daddiu
298 #define PTR_SUB		dsub
299 #define PTR_SUBU	dsubu
300 #define PTR_L		ld
301 #define PTR_S		sd
302 #define PTR_LA		dla
303 #define PTR_LI		dli
304 #define PTR_SLL		dsll
305 #define PTR_SLLV	dsllv
306 #define PTR_SRL		dsrl
307 #define PTR_SRLV	dsrlv
308 #define PTR_SRA		dsra
309 #define PTR_SRAV	dsrav
310 
311 #define PTR_SCALESHIFT	3
312 
313 #define PTR_WD		.dword
314 #define PTRSIZE		8
315 #define PTRLOG		3
316 #endif
317 
318 /*
319  * Some cp0 registers were extended to 64bit for MIPS III.
320  */
321 #if (_MIPS_SIM == _MIPS_SIM_ABI32)
322 #define MFC0		mfc0
323 #define MTC0		mtc0
324 #endif
325 #if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64)
326 #define MFC0		dmfc0
327 #define MTC0		dmtc0
328 #endif
329 
330 #define SSNOP		sll zero, zero, 1
331 
332 /*
333  * Using a branch-likely instruction to check the result of an sc instruction
334  * works around a bug present in R10000 CPUs prior to revision 3.0 that could
335  * cause ll-sc sequences to execute non-atomically.
336  */
337 #ifdef CONFIG_WAR_R10000_LLSC
338 # define SC_BEQZ	beqzl
339 #elif !defined(CONFIG_CC_HAS_BROKEN_INLINE_COMPAT_BRANCH) && MIPS_ISA_REV >= 6
340 # define SC_BEQZ	beqzc
341 #else
342 # define SC_BEQZ	beqz
343 #endif
344 
345 #ifdef CONFIG_SGI_IP28
346 /* Inhibit speculative stores to volatile (e.g.DMA) or invalid addresses. */
347 #include <asm/cacheops.h>
348 #define R10KCBARRIER(addr)  cache   Cache_Barrier, addr;
349 #else
350 #define R10KCBARRIER(addr)
351 #endif
352 
353 #endif /* __ASM_ASM_H */
354