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