1 /* Copyright (C) 1997, 1998, 2002, 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ralf Baechle <ralf@gnu.org>.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18 
19 #ifndef _SYS_ASM_H
20 #define _SYS_ASM_H
21 
22 #include <sgidefs.h>
23 
24 #ifndef CAT
25 # ifdef __STDC__
26 #  define __CAT(str1,str2) str1##str2
27 # else
28 #  define __CAT(str1,str2) str1/**/str2
29 # endif
30 # define CAT(str1,str2) __CAT(str1,str2)
31 #endif
32 
33 /*
34  * Macros to handle different pointer/register sizes for 32/64-bit code
35  *
36  * 64 bit address space isn't used yet, so we may use the R3000 32 bit
37  * defines for now.
38  */
39 #if (_MIPS_SIM == _MIPS_SIM_ABI32) || (_MIPS_SIM == _MIPS_SIM_NABI32)
40 # define PTR .word
41 # define PTRSIZE 4
42 # define PTRLOG 2
43 #elif (_MIPS_SIM == _MIPS_SIM_ABI64)
44 # define PTR .dword
45 # define PTRSIZE 8
46 # define PTRLOG 3
47 #endif
48 
49 /*
50  * PIC specific declarations
51  */
52 #if (_MIPS_SIM == _MIPS_SIM_ABI32)
53 # ifdef __PIC__
54 #  define CPRESTORE(register) \
55 		.cprestore register
56 #  define CPLOAD(register) \
57 		.cpload register
58 # else
59 #  define CPRESTORE(register)
60 #  define CPLOAD(register)
61 # endif
62 
63 # define CPADD(register) \
64 		.cpadd	register
65 
66 /*
67  * Set gp when at 1st instruction
68  */
69 # define SETUP_GP					\
70 		.set noreorder;				\
71 		.cpload $25;				\
72 		.set reorder
73 /* Set gp when not at 1st instruction */
74 # define SETUP_GPX(r)					\
75 		.set noreorder;				\
76 		move r, $31;	 /* Save old ra.  */	\
77 		bal 10f; /* Find addr of cpload.  */	\
78 		nop;					\
79 10:							\
80 		.cpload $31;				\
81 		move $31, r;				\
82 		.set reorder
83 # define SETUP_GPX_L(r, l)				\
84 		.set noreorder;				\
85 		move r, $31;	 /* Save old ra.  */	\
86 		bal l;   /* Find addr of cpload.  */	\
87 		nop;					\
88 l:							\
89 		.cpload $31;				\
90 		move $31, r;				\
91 		.set reorder
92 # define SAVE_GP(x) \
93 		.cprestore x /* Save gp trigger t9/jalr conversion.	 */
94 # define SETUP_GP64(a, b)
95 # define SETUP_GPX64(a, b)
96 # define SETUP_GPX64_L(cp_reg, ra_save, l)
97 # define RESTORE_GP64
98 # define USE_ALT_CP(a)
99 # define L(label) $L ## label
100 #else /* (_MIPS_SIM == _MIPS_SIM_ABI64) || (_MIPS_SIM == _MIPS_SIM_NABI32) */
101 /*
102  * For callee-saved gp calling convention:
103  */
104 # define SETUP_GP
105 # define SETUP_GPX(r)
106 # define SETUP_GPX_L(r, l)
107 # define SAVE_GP(x)
108 
109 # define SETUP_GP64(gpoffset, proc) \
110 		.cpsetup $25, gpoffset, proc
111 # define SETUP_GPX64(cp_reg, ra_save)			\
112 		move ra_save, $31; /* Save old ra.  */	\
113 		.set noreorder;				\
114 		bal 10f; /* Find addr of .cpsetup.  */	\
115 		nop;					\
116 10:							\
117 		.set reorder;				\
118 		.cpsetup $31, cp_reg, 10b;		\
119 		move $31, ra_save
120 # define SETUP_GPX64_L(cp_reg, ra_save, l)  \
121 		move ra_save, $31; /* Save old ra.  */	\
122 		.set noreorder;				\
123 		bal l;   /* Find addr of .cpsetup.  */	\
124 		nop;					\
125 l:							\
126 		.set reorder;				\
127 		.cpsetup $31, cp_reg, l;		\
128 		move $31, ra_save
129 # define RESTORE_GP64 \
130 		.cpreturn
131 /* Use alternate register for context pointer.  */
132 # define USE_ALT_CP(reg)	\
133 		.cplocal reg
134 # define L(label) .L ## label
135 #endif /* _MIPS_SIM != _MIPS_SIM_ABI32 */
136 
137 /*
138  * Stack Frame Definitions
139  */
140 #if (_MIPS_SIM == _MIPS_SIM_ABI32)
141 # define NARGSAVE 4 /* Space for 4 argument registers must be allocated.  */
142 #endif
143 #if (_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32)
144 # define NARGSAVE 0 /* No caller responsibilities.  */
145 #endif
146 
147 
148 /*
149  * LEAF - declare leaf routine
150  */
151 #define	LEAF(symbol)                                    \
152 		.globl	symbol;                         \
153 		.align	2;                              \
154 		.type	symbol,@function;               \
155 		.ent	symbol,0;                       \
156 symbol:		.frame	sp,0,ra
157 
158 /*
159  * NESTED - declare nested routine entry point
160  */
161 #define	NESTED(symbol, framesize, rpc)                  \
162 		.globl	symbol;                         \
163 		.align	2;                              \
164 		.type	symbol,@function;               \
165 		.ent	symbol,0;                       \
166 symbol:		.frame	sp, framesize, rpc
167 
168 /*
169  * END - mark end of function
170  */
171 #ifndef END
172 # define END(function)                                   \
173 		.end	function;		        \
174 		.size	function,.-function
175 #endif
176 
177 /*
178  * EXPORT - export definition of symbol
179  */
180 #define	EXPORT(symbol)                                  \
181 		.globl	symbol;                         \
182 symbol:
183 
184 /*
185  * ABS - export absolute symbol
186  */
187 #define	ABS(symbol,value)                               \
188 		.globl	symbol;                         \
189 symbol		=	value
190 
191 #define	PANIC(msg)                                      \
192 		.set	push;				\
193 		.set	reorder;                        \
194 		la	a0,8f;                          \
195 		jal	panic;                          \
196 9:		b	9b;                             \
197 		.set	pop;				\
198 		TEXT(msg)
199 
200 /*
201  * Print formated string
202  */
203 #define PRINT(string)                                   \
204 		.set	push;				\
205 		.set	reorder;                        \
206 		la	a0,8f;                          \
207 		jal	printk;                         \
208 		.set	pop;				\
209 		TEXT(string)
210 
211 #define	TEXT(msg)                                       \
212 		.data;                                  \
213 8:		.asciiz	msg;                            \
214 		.previous;
215 
216 /*
217  * Build text tables
218  */
219 #define TTABLE(string)                                  \
220 		.text;                                  \
221 		.word	1f;                             \
222 		.previous;                              \
223 		.data;                                  \
224 1:		.asciz	string;                         \
225 		.previous
226 
227 /*
228  * MIPS IV pref instruction.
229  * Use with .set noreorder only!
230  *
231  * MIPS IV implementations are free to treat this as a nop.  The R5000
232  * is one of them.  So we should have an option not to use this instruction.
233  */
234 #if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \
235     (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
236 # define PREF(hint,addr)                                 \
237 		pref	hint,addr
238 # define PREFX(hint,addr)                                \
239 		prefx	hint,addr
240 #else
241 # define PREF
242 # define PREFX
243 #endif
244 
245 /*
246  * MIPS ISA IV/V movn/movz instructions and equivalents for older CPUs.
247  */
248 #if _MIPS_ISA == _MIPS_ISA_MIPS1
249 # define MOVN(rd,rs,rt)					\
250 		.set	push;				\
251 		.set	reorder;			\
252 		beqz	rt,9f;				\
253 		move	rd,rs;				\
254 		.set	pop;				\
255 9:
256 # define MOVZ(rd,rs,rt)					\
257 		.set	push;				\
258 		.set	reorder;			\
259 		bnez	rt,9f;				\
260 		move	rd,rt;				\
261 		.set	pop;				\
262 9:
263 #endif /* _MIPS_ISA == _MIPS_ISA_MIPS1 */
264 #if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3)
265 # define MOVN(rd,rs,rt)					\
266 		.set	push;				\
267 		.set	noreorder;			\
268 		bnezl	rt,9f;				\
269 		move	rd,rs;				\
270 		.set	pop;				\
271 9:
272 # define MOVZ(rd,rs,rt)					\
273 		.set	push;				\
274 		.set	noreorder;			\
275 		beqzl	rt,9f;				\
276 		movz	rd,rs;				\
277 		.set	pop;				\
278 9:
279 #endif /* (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) */
280 #if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \
281     (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
282 # define MOVN(rd,rs,rt)					\
283 		movn	rd,rs,rt
284 # define MOVZ(rd,rs,rt)					\
285 		movz	rd,rs,rt
286 #endif /* (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) */
287 
288 /*
289  * Stack alignment
290  */
291 #if (_MIPS_SIM == _MIPS_SIM_ABI64) || (_MIPS_SIM == _MIPS_SIM_NABI32)
292 # define ALSZ	15
293 # define ALMASK	~15
294 #else
295 # define ALSZ	7
296 # define ALMASK	~7
297 #endif
298 
299 /*
300  * Size of a register
301  */
302 #if (_MIPS_SIM == _MIPS_SIM_ABI64) || (_MIPS_SIM == _MIPS_SIM_NABI32)
303 # define SZREG	8
304 #else
305 # define SZREG	4
306 #endif
307 
308 /*
309  * Use the following macros in assemblercode to load/store registers,
310  * pointers etc.
311  */
312 #if (SZREG == 4)
313 # define REG_S sw
314 # define REG_L lw
315 #else
316 # define REG_S sd
317 # define REG_L ld
318 #endif
319 
320 /*
321  * How to add/sub/load/store/shift C int variables.
322  */
323 #if (_MIPS_SZINT == 32)
324 # define INT_ADD	add
325 # define INT_ADDI	addi
326 # define INT_ADDU	addu
327 # define INT_ADDIU	addiu
328 # define INT_SUB	add
329 # define INT_SUBI	subi
330 # define INT_SUBU	subu
331 # define INT_SUBIU	subu
332 # define INT_L		lw
333 # define INT_S		sw
334 #endif
335 
336 #if (_MIPS_SZINT == 64)
337 # define INT_ADD	dadd
338 # define INT_ADDI	daddi
339 # define INT_ADDU	daddu
340 # define INT_ADDIU	daddiu
341 # define INT_SUB	dadd
342 # define INT_SUBI	dsubi
343 # define INT_SUBU	dsubu
344 # define INT_SUBIU	dsubu
345 # define INT_L		ld
346 # define INT_S		sd
347 #endif
348 
349 /*
350  * How to add/sub/load/store/shift C long variables.
351  */
352 #if (_MIPS_SZLONG == 32)
353 # define LONG_ADD	add
354 # define LONG_ADDI	addi
355 # define LONG_ADDU	addu
356 # define LONG_ADDIU	addiu
357 # define LONG_SUB	add
358 # define LONG_SUBI	subi
359 # define LONG_SUBU	subu
360 # define LONG_SUBIU	subu
361 # define LONG_L		lw
362 # define LONG_S		sw
363 # define LONG_SLL	sll
364 # define LONG_SLLV	sllv
365 # define LONG_SRL	srl
366 # define LONG_SRLV	srlv
367 # define LONG_SRA	sra
368 # define LONG_SRAV	srav
369 #endif
370 
371 #if (_MIPS_SZLONG == 64)
372 # define LONG_ADD	dadd
373 # define LONG_ADDI	daddi
374 # define LONG_ADDU	daddu
375 # define LONG_ADDIU	daddiu
376 # define LONG_SUB	dadd
377 # define LONG_SUBI	dsubi
378 # define LONG_SUBU	dsubu
379 # define LONG_SUBIU	dsubu
380 # define LONG_L		ld
381 # define LONG_S		sd
382 # define LONG_SLL	dsll
383 # define LONG_SLLV	dsllv
384 # define LONG_SRL	dsrl
385 # define LONG_SRLV	dsrlv
386 # define LONG_SRA	dsra
387 # define LONG_SRAV	dsrav
388 #endif
389 
390 /*
391  * How to add/sub/load/store/shift pointers.
392  */
393 #if (_MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32)
394 # define PTR_ADD	add
395 # define PTR_ADDI	addi
396 # define PTR_ADDU	addu
397 # define PTR_ADDIU	addiu
398 # define PTR_SUB	add
399 # define PTR_SUBI	subi
400 # define PTR_SUBU	subu
401 # define PTR_SUBIU	subu
402 # define PTR_L		lw
403 # define PTR_LA		la
404 # define PTR_S		sw
405 # define PTR_SLL	sll
406 # define PTR_SLLV	sllv
407 # define PTR_SRL	srl
408 # define PTR_SRLV	srlv
409 # define PTR_SRA	sra
410 # define PTR_SRAV	srav
411 
412 # define PTR_SCALESHIFT	2
413 #endif
414 
415 #if _MIPS_SIM == _MIPS_SIM_NABI32
416 # define PTR_ADD	add
417 # define PTR_ADDI	addi
418 # define PTR_ADDU	add /* no u */
419 # define PTR_ADDIU	addi /* no u */
420 # define PTR_SUB	add
421 # define PTR_SUBI	subi
422 # define PTR_SUBU	sub /* no u */
423 # define PTR_SUBIU	sub /* no u */
424 # define PTR_L		lw
425 # define PTR_LA		la
426 # define PTR_S		sw
427 # define PTR_SLL	sll
428 # define PTR_SLLV	sllv
429 # define PTR_SRL	srl
430 # define PTR_SRLV	srlv
431 # define PTR_SRA	sra
432 # define PTR_SRAV	srav
433 
434 # define PTR_SCALESHIFT	2
435 #endif
436 
437 #if (_MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 64 /* o64??? */) \
438     || _MIPS_SIM == _MIPS_SIM_ABI64
439 # define PTR_ADD	dadd
440 # define PTR_ADDI	daddi
441 # define PTR_ADDU	daddu
442 # define PTR_ADDIU	daddiu
443 # define PTR_SUB	dadd
444 # define PTR_SUBI	dsubi
445 # define PTR_SUBU	dsubu
446 # define PTR_SUBIU	dsubu
447 # define PTR_L		ld
448 # define PTR_LA		dla
449 # define PTR_S		sd
450 # define PTR_SLL	dsll
451 # define PTR_SLLV	dsllv
452 # define PTR_SRL	dsrl
453 # define PTR_SRLV	dsrlv
454 # define PTR_SRA	dsra
455 # define PTR_SRAV	dsrav
456 
457 # define PTR_SCALESHIFT	3
458 #endif
459 
460 /*
461  * Some cp0 registers were extended to 64bit for MIPS III.
462  */
463 #if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \
464     (_MIPS_ISA == _MIPS_ISA_MIPS32)
465 # define MFC0	mfc0
466 # define MTC0	mtc0
467 #endif
468 #if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
469     (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
470 # define MFC0	dmfc0
471 # define MTC0	dmtc0
472 #endif
473 
474 /* The MIPS archtectures do not have a uniform memory model.  Particular
475    platforms may provide additional guarantees - for instance, the R4000
476    LL and SC instructions implicitly perform a SYNC, and the 4K promises
477    strong ordering.
478 
479    However, in the absence of those guarantees, we must assume weak ordering
480    and SYNC explicitly where necessary.
481 
482    Some obsolete MIPS processors may not support the SYNC instruction.  This
483    applies to "true" MIPS I processors; most of the processors which compile
484    using MIPS I implement parts of MIPS II.  */
485 
486 #ifndef MIPS_SYNC
487 # define MIPS_SYNC      sync
488 #endif
489 
490 #endif /* sys/asm.h */
491