File: /usr/src/linux/include/asm-mips/asm.h
1 /*
2 * include/asm-mips/asm.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
9 *
10 * Some useful macros for MIPS assembler code
11 *
12 * Some of the routines below contain useless nops that will be optimized
13 * away by gas in -O mode. These nops are however required to fill delay
14 * slots in noreorder mode.
15 */
16 #ifndef __ASM_ASM_H
17 #define __ASM_ASM_H
18
19 #include <asm/sgidefs.h>
20
21 #ifndef CAT
22 #ifdef __STDC__
23 #define __CAT(str1,str2) str1##str2
24 #else
25 #define __CAT(str1,str2) str1/**/str2
26 #endif
27 #define CAT(str1,str2) __CAT(str1,str2)
28 #endif
29
30 /*
31 * Macros to handle different pointer/register sizes for 32/64-bit code
32 *
33 * 64 bit address space isn't used yet, so we may use the R3000 32 bit
34 * defines for now.
35 */
36 #define PTR .word
37 #define PTRSIZE 4
38 #define PTRLOG 2
39
40 /*
41 * PIC specific declarations
42 * Not used for the kernel but here seems to be the right place.
43 */
44 #ifdef __PIC__
45 #define CPRESTORE(register) \
46 .cprestore register
47 #define CPADD(register) \
48 .cpadd register
49 #define CPLOAD(register) \
50 .cpload register
51 #else
52 #define CPRESTORE(register)
53 #define CPADD(register)
54 #define CPLOAD(register)
55 #endif
56
57 /*
58 * LEAF - declare leaf routine
59 */
60 #define LEAF(symbol) \
61 .globl symbol; \
62 .align 2; \
63 .type symbol,@function; \
64 .ent symbol,0; \
65 symbol: .frame sp,0,ra
66
67 /*
68 * NESTED - declare nested routine entry point
69 */
70 #define NESTED(symbol, framesize, rpc) \
71 .globl symbol; \
72 .align 2; \
73 .type symbol,@function; \
74 .ent symbol,0; \
75 symbol: .frame sp, framesize, rpc
76
77 /*
78 * END - mark end of function
79 */
80 #define END(function) \
81 .end function; \
82 .size function,.-function
83
84 /*
85 * EXPORT - export definition of symbol
86 */
87 #define EXPORT(symbol) \
88 .globl symbol; \
89 symbol:
90
91 /*
92 * FEXPORT - export definition of a function symbol
93 */
94 #define FEXPORT(symbol) \
95 .globl symbol; \
96 .type symbol,@function; \
97 symbol:
98
99 /*
100 * ABS - export absolute symbol
101 */
102 #define ABS(symbol,value) \
103 .globl symbol; \
104 symbol = value
105
106 #define PANIC(msg) \
107 .set push; \
108 .set reorder; \
109 la a0,8f; \
110 jal panic; \
111 9: b 9b; \
112 .set pop; \
113 TEXT(msg)
114
115 /*
116 * Print formatted string
117 */
118 #define PRINT(string) \
119 .set push; \
120 .set reorder; \
121 la a0,8f; \
122 jal printk; \
123 .set pop; \
124 TEXT(string)
125
126 #define TEXT(msg) \
127 .data; \
128 8: .asciiz msg; \
129 .previous;
130
131 /*
132 * Build text tables
133 */
134 #define TTABLE(string) \
135 .text; \
136 .word 1f; \
137 .previous; \
138 .data; \
139 1: .asciz string; \
140 .previous
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 #if (_MIPS_ISA == _MIPS_ISA_MIPS4 ) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \
150 (_MIPS_ISA == _MIPS_ISA_MIPS64)
151 #define PREF(hint,addr) \
152 pref hint,addr
153 #define PREFX(hint,addr) \
154 prefx hint,addr
155 #else
156 #define PREF
157 #define PREFX
158 #endif
159
160 /*
161 * MIPS ISA IV/V movn/movz instructions and equivalents for older CPUs.
162 */
163 #if (_MIPS_ISA == _MIPS_ISA_MIPS1)
164 #define MOVN(rd,rs,rt) \
165 .set push; \
166 .set noreorder; \
167 beqz rt,9f; \
168 move rd,rs; \
169 .set pop; \
170 9:
171 #define MOVZ(rd,rs,rt) \
172 .set push; \
173 .set noreorder; \
174 bnez rt,9f; \
175 move rd,rt; \
176 .set pop; \
177 9:
178 #endif /* _MIPS_ISA == _MIPS_ISA_MIPS1 */
179 #if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3)
180 #define MOVN(rd,rs,rt) \
181 .set push; \
182 .set noreorder; \
183 bnezl rt,9f; \
184 move rd,rs; \
185 .set pop; \
186 9:
187 #define MOVZ(rd,rs,rt) \
188 .set push; \
189 .set noreorder; \
190 beqzl rt,9f; \
191 movz rd,rs; \
192 .set pop; \
193 9:
194 #endif /* (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) */
195 #if (_MIPS_ISA == _MIPS_ISA_MIPS4 ) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \
196 (_MIPS_ISA == _MIPS_ISA_MIPS64)
197 #define MOVN(rd,rs,rt) \
198 movn rd,rs,rt
199 #define MOVZ(rd,rs,rt) \
200 movz rd,rs,rt
201 #endif /* MIPS IV, MIPS V or MIPS64 */
202
203 /*
204 * Stack alignment
205 */
206 #if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \
207 (_MIPS_ISA == _MIPS_ISA_MIPS32)
208 #define ALSZ 7
209 #define ALMASK ~7
210 #endif
211 #if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
212 (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
213 #define ALSZ 15
214 #define ALMASK ~15
215 #endif
216
217 /*
218 * Size of a register
219 */
220 #ifdef __mips64
221 #define SZREG 8
222 #else
223 #define SZREG 4
224 #endif
225
226 /*
227 * Use the following macros in assemblercode to load/store registers,
228 * pointers etc.
229 */
230 #if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \
231 (_MIPS_ISA == _MIPS_ISA_MIPS32)
232 #define REG_S sw
233 #define REG_L lw
234 #define PTR_SUBU subu
235 #define PTR_ADDU addu
236 #endif
237 #if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
238 (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
239 #define REG_S sd
240 #define REG_L ld
241 /* We still live in a 32 bit address space ... */
242 #define PTR_SUBU subu
243 #define PTR_ADDU addu
244 #endif
245
246 /*
247 * How to add/sub/load/store/shift C int variables.
248 */
249 #if (_MIPS_SZINT == 32)
250 #define INT_ADD add
251 #define INT_ADDI addi
252 #define INT_ADDU addu
253 #define INT_ADDIU addiu
254 #define INT_SUB add
255 #define INT_SUBI subi
256 #define INT_SUBU subu
257 #define INT_SUBIU subu
258 #define INT_L lw
259 #define INT_S sw
260 #define LONG_SLL sll
261 #define LONG_SLLV sllv
262 #define LONG_SRL srl
263 #define LONG_SRLV srlv
264 #define LONG_SRA sra
265 #define LONG_SRAV srav
266 #endif
267
268 #if (_MIPS_SZINT == 64)
269 #define INT_ADD dadd
270 #define INT_ADDI daddi
271 #define INT_ADDU daddu
272 #define INT_ADDIU daddiu
273 #define INT_SUB dadd
274 #define INT_SUBI dsubi
275 #define INT_SUBU dsubu
276 #define INT_SUBIU dsubu
277 #define INT_L ld
278 #define INT_S sd
279 #define LONG_SLL dsll
280 #define LONG_SLLV dsllv
281 #define LONG_SRL dsrl
282 #define LONG_SRLV dsrlv
283 #define LONG_SRA dsra
284 #define LONG_SRAV dsrav
285 #endif
286
287 /*
288 * How to add/sub/load/store/shift C long variables.
289 */
290 #if (_MIPS_SZLONG == 32)
291 #define LONG_ADD add
292 #define LONG_ADDI addi
293 #define LONG_ADDU addu
294 #define LONG_ADDIU addiu
295 #define LONG_SUB add
296 #define LONG_SUBI subi
297 #define LONG_SUBU subu
298 #define LONG_SUBIU subu
299 #define LONG_L lw
300 #define LONG_S sw
301 #define LONG_SLL sll
302 #define LONG_SLLV sllv
303 #define LONG_SRL srl
304 #define LONG_SRLV srlv
305 #define LONG_SRA sra
306 #define LONG_SRAV srav
307 #endif
308
309 #if (_MIPS_SZLONG == 64)
310 #define LONG_ADD dadd
311 #define LONG_ADDI daddi
312 #define LONG_ADDU daddu
313 #define LONG_ADDIU daddiu
314 #define LONG_SUB dadd
315 #define LONG_SUBI dsubi
316 #define LONG_SUBU dsubu
317 #define LONG_SUBIU dsubu
318 #define LONG_L ld
319 #define LONG_S sd
320 #define LONG_SLL dsll
321 #define LONG_SLLV dsllv
322 #define LONG_SRL dsrl
323 #define LONG_SRLV dsrlv
324 #define LONG_SRA dsra
325 #define LONG_SRAV dsrav
326 #endif
327
328 /*
329 * How to add/sub/load/store/shift pointers.
330 */
331 #if (_MIPS_SZLONG == 32)
332 #define PTR_ADD add
333 #define PTR_ADDI addi
334 #define PTR_ADDU addu
335 #define PTR_ADDIU addiu
336 #define PTR_SUB add
337 #define PTR_SUBI subi
338 #define PTR_SUBU subu
339 #define PTR_SUBIU subu
340 #define PTR_L lw
341 #define PTR_S sw
342 #define PTR_SLL sll
343 #define PTR_SLLV sllv
344 #define PTR_SRL srl
345 #define PTR_SRLV srlv
346 #define PTR_SRA sra
347 #define PTR_SRAV srav
348
349 #define PTR_SCALESHIFT 2
350 #endif
351
352 #if (_MIPS_SZLONG == 64)
353 #define PTR_ADD dadd
354 #define PTR_ADDI daddi
355 #define PTR_ADDU daddu
356 #define PTR_ADDIU daddiu
357 #define PTR_SUB dadd
358 #define PTR_SUBI dsubi
359 #define PTR_SUBU dsubu
360 #define PTR_SUBIU dsubu
361 #define PTR_L ld
362 #define PTR_S sd
363 #define PTR_SLL dsll
364 #define PTR_SLLV dsllv
365 #define PTR_SRL dsrl
366 #define PTR_SRLV dsrlv
367 #define PTR_SRA dsra
368 #define PTR_SRAV dsrav
369
370 #define PTR_SCALESHIFT 3
371 #endif
372
373 /*
374 * Some cp0 registers were extended to 64bit for MIPS III.
375 */
376 #if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \
377 (_MIPS_ISA == _MIPS_ISA_MIPS32)
378 #define MFC0 mfc0
379 #define MTC0 mtc0
380 #endif
381 #if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
382 (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
383 #define MFC0 dmfc0
384 #define MTC0 dmtc0
385 #endif
386
387 #endif /* __ASM_ASM_H */
388