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