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