xref: /openbsd/sys/arch/mips64/include/asm.h (revision a6445c1d)
1 /*	$OpenBSD: asm.h,v 1.21 2014/03/14 16:57:21 miod Exp $ */
2 
3 /*
4  * Copyright (c) 2001-2002 Opsycon AB  (www.opsycon.se / www.opsycon.com)
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  */
28 #ifndef _MIPS64_ASM_H_
29 #define _MIPS64_ASM_H_
30 
31 #include <machine/regdef.h>
32 
33 #define	_MIPS_ISA_MIPS1	1	/* R2000/R3000 */
34 #define	_MIPS_ISA_MIPS2	2	/* R4000/R6000 */
35 #define	_MIPS_ISA_MIPS3	3	/* R4000 */
36 #define	_MIPS_ISA_MIPS4	4	/* TFP (R1x000) */
37 
38 #if !defined(ABICALLS) && !defined(_NO_ABICALLS)
39 #define	ABICALLS	.abicalls
40 #endif
41 
42 #if defined(ABICALLS) && !defined(_KERNEL)
43 	ABICALLS
44 #endif
45 
46 #define _C_LABEL(x) x		/* XXX Obsolete but keep for a while */
47 
48 #if !defined(__MIPSEL__) && !defined(__MIPSEB__)
49 #error "__MIPSEL__ or __MIPSEB__ must be defined"
50 #endif
51 /*
52  * Define how to access unaligned data word
53  */
54 #if defined(__MIPSEL__)
55 #define LWLO    lwl
56 #define LWHI    lwr
57 #define	SWLO	swl
58 #define	SWHI	swr
59 #define LDLO    ldl
60 #define LDHI    ldr
61 #define	SDLO	sdl
62 #define	SDHI	sdr
63 #endif
64 #if defined(__MIPSEB__)
65 #define LWLO    lwr
66 #define LWHI    lwl
67 #define	SWLO	swr
68 #define	SWHI	swl
69 #define LDLO    ldr
70 #define LDHI    ldl
71 #define	SDLO	sdr
72 #define	SDHI	sdl
73 #endif
74 
75 /*
76  *  Define programming environment for ABI.
77  */
78 #if defined(ABICALLS) && !defined(_KERNEL) && !defined(_STANDALONE)
79 
80 #ifndef _MIPS_SIM
81 #define _MIPS_SIM 1
82 #define _ABIO32	1
83 #endif
84 #ifndef _MIPS_ISA
85 #define _MIPS_ISA 2
86 #define _MIPS_ISA_MIPS2 2
87 #endif
88 
89 #if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32)
90 #define NARGSAVE	4
91 
92 #define	SETUP_GP		\
93 	.set	noreorder;	\
94 	.cpload	t9;		\
95 	.set	reorder;
96 
97 #define	SAVE_GP(x)		\
98 	.cprestore x
99 
100 #define	SETUP_GP64(gpoff, name)
101 #define	RESTORE_GP64
102 #endif
103 
104 #if (_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32)
105 #define NARGSAVE	0
106 
107 #define	SETUP_GP
108 #define	SAVE_GP(x)
109 #define	SETUP_GP64(gpoff, name)	\
110 	.cpsetup t9, gpoff, name
111 #define	RESTORE_GP64		\
112 	.cpreturn
113 #endif
114 
115 #define	MKFSIZ(narg,locals) (((narg+locals)*REGSZ+31)&(~31))
116 
117 #else /* defined(ABICALLS) && !defined(_KERNEL) */
118 
119 #define	NARGSAVE	4
120 #define	SETUP_GP
121 #define	SAVE_GP(x)
122 
123 #define	ALIGNSZ		16	/* Stack layout alignment */
124 #define	FRAMESZ(sz)	(((sz) + (ALIGNSZ-1)) & ~(ALIGNSZ-1))
125 
126 #endif
127 
128 /*
129  *  Basic register operations based on selected ISA
130  */
131 #if (_MIPS_ISA == _MIPS_ISA_MIPS1 || _MIPS_ISA == _MIPS_ISA_MIPS2)
132 #define REGSZ		4	/* 32 bit mode register size */
133 #define LOGREGSZ	2	/* log rsize */
134 #define	REG_S	sw
135 #define	REG_L	lw
136 #define	CF_SZ		24	/* Call frame size */
137 #define	CF_ARGSZ	16	/* Call frame arg size */
138 #define	CF_RA_OFFS	20	/* Call ra save offset */
139 #endif
140 
141 #if (_MIPS_ISA == _MIPS_ISA_MIPS3 || _MIPS_ISA == _MIPS_ISA_MIPS4)
142 #define REGSZ		8	/* 64 bit mode register size */
143 #define LOGREGSZ	3	/* log rsize */
144 #define	REG_S	sd
145 #define	REG_L	ld
146 #define	CF_SZ		48	/* Call frame size (multiple of ALIGNSZ) */
147 #define	CF_ARGSZ	32	/* Call frame arg size */
148 #define	CF_RA_OFFS	40	/* Call ra save offset */
149 #endif
150 
151 #ifndef __LP64__
152 #define	PTR_L		lw
153 #define	PTR_S		sw
154 #define	PTR_SUB		sub
155 #define	PTR_ADD		add
156 #define	PTR_SUBU	subu
157 #define	PTR_ADDU	addu
158 #define LI		li
159 #define	LA		la
160 #define	PTR_SLL		sll
161 #define	PTR_SRL		srl
162 #define	PTR_VAL		.word
163 #else
164 #define	PTR_L		ld
165 #define	PTR_S		sd
166 #define	PTR_ADD		dadd
167 #define	PTR_SUB		dsub
168 #define	PTR_SUBU	dsubu
169 #define	PTR_ADDU	daddu
170 #define LI		dli
171 #define LA		dla
172 #define	PTR_SLL		dsll
173 #define	PTR_SRL		dsrl
174 #define	PTR_VAL		.dword
175 #endif
176 
177 /*
178  * The following macros are here to benefit the R8000 processor:
179  * - all coprocessor 0 control registers are 64-bit
180  * - the regular nop (sll zero, zero, 0) has the drawback of using the
181  *   shifter, potentially breaking instruction dispatch if occuring after
182  *   another instruction using the shifter.
183  */
184 #ifdef CPU_R8000
185 #define	SSNOP	sll zero, zero, 1		/* ``ssnop'' */
186 #define	NOP	PTR_ADDU zero, zero, zero	/* real nop for R8000 */
187 #define	DMFC0	SSNOP; dmfc0
188 #define	DMTC0	SSNOP; dmtc0
189 #define	MFC0	SSNOP; dmfc0
190 #define	MTC0	SSNOP; dmtc0
191 #define	ERET	eret; mul k0, k0; mflo k0
192 #else
193 #define	NOP	nop
194 #define	DMFC0	dmfc0
195 #define	DMTC0	dmtc0
196 #define	MFC0	mfc0
197 #define	MTC0	mtc0
198 #define	ERET	sync; eret
199 #endif
200 
201 /*
202  * Define -pg profile entry code.
203  */
204 #if defined(XGPROF) || defined(XPROF)
205 #define	MCOUNT			\
206 	PTR_SUBU sp, sp, 64;	\
207 	SAVE_GP(16);		\
208 	sd	ra, 56(sp);	\
209 	sd	gp, 48(sp);	\
210 	.set	noat;		\
211 	.set	noreorder;	\
212 	move	AT, ra;		\
213 	jal	_mcount;	\
214 	PTR_SUBU sp, sp, 16;	\
215 	ld	ra, 56(sp);	\
216 	PTR_ADDU sp, sp, 64;	\
217 	.set reorder;		\
218 	.set	at;
219 #else
220 #define	MCOUNT
221 #endif
222 
223 /*
224  * LEAF(x, fsize)
225  *
226  *	Declare a leaf routine.
227  */
228 #define LEAF(x, fsize)		\
229 	.align	3;		\
230 	.globl x;		\
231 	.ent x, 0;		\
232 x: ;				\
233 	.frame sp, fsize, ra;	\
234 	SETUP_GP		\
235 	MCOUNT
236 
237 #define	ALEAF(x)		\
238 	.globl	x;		\
239 x:
240 
241 /*
242  * NLEAF(x)
243  *
244  *	Declare a non-profiled leaf routine.
245  */
246 #define NLEAF(x, fsize)		\
247 	.align	3;		\
248 	.globl x;		\
249 	.ent x, 0;		\
250 x: ;				\
251 	.frame sp, fsize, ra;	\
252 	SETUP_GP
253 
254 /*
255  * NON_LEAF(x)
256  *
257  *	Declare a non-leaf routine (a routine that makes other C calls).
258  */
259 #define NON_LEAF(x, fsize, retpc) \
260 	.align	3;		\
261 	.globl x;		\
262 	.ent x, 0;		\
263 x: ;				\
264 	.frame sp, fsize, retpc; \
265 	SETUP_GP		\
266 	MCOUNT
267 
268 /*
269  * NNON_LEAF(x)
270  *
271  *	Declare a non-profiled non-leaf routine
272  *	(a routine that makes other C calls).
273  */
274 #define NNON_LEAF(x, fsize, retpc) \
275 	.align	3;		\
276 	.globl x;		\
277 	.ent x, 0;		\
278 x: ;				\
279 	.frame sp, fsize, retpc	\
280 	SETUP_GP
281 
282 /*
283  * END(x)
284  *
285  *	Mark end of a procedure.
286  */
287 #define END(x) \
288 	.end x
289 
290 /*
291  * STRONG_ALIAS, WEAK_ALIAS
292  *	Create a strong or weak alias.
293  */
294 #define STRONG_ALIAS(alias,sym) \
295 	.global alias; alias = sym
296 #define WEAK_ALIAS(alias,sym) \
297 	.weak alias; alias = sym
298 
299 
300 /*
301  * Macros to panic and printf from assembly language.
302  */
303 #define PANIC(msg) \
304 	LA	a0, 9f; \
305 	jal	panic;	\
306 	nop	;	\
307 	MSG(msg)
308 
309 #define	PRINTF(msg) \
310 	LA	a0, 9f; \
311 	jal	printf; \
312 	nop	;	\
313 	MSG(msg)
314 
315 #define	MSG(msg) \
316 	.rdata; \
317 9:	.asciiz	msg; \
318 	.text
319 
320 #define ASMSTR(str) \
321 	.asciiz str; \
322 	.align	3
323 
324 #define	LOAD_XKPHYS(reg, cca) \
325 	li	reg, cca | 0x10; \
326 	dsll	reg, reg, 59
327 
328 #ifdef MULTIPROCESSOR
329 #define GET_CPU_INFO(ci, tmp)	HW_GET_CPU_INFO(ci, tmp)
330 #else  /* MULTIPROCESSOR */
331 #define GET_CPU_INFO(ci, tmp)		\
332 	LA	ci, cpu_info_primary
333 #endif /* MULTIPROCESSOR */
334 
335 /*
336  * Hazards
337  */
338 
339 #ifdef CPU_RM7000
340 /*
341  * Due to a flaw in RM7000 1.x processors a pipeline 'drain' is
342  * required after some mtc0 instructions.
343  * Ten nops in sequence does the trick.
344  */
345 #define	MTC0_HAZARD		NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP
346 #define	MTC0_SR_IE_HAZARD	MTC0_HAZARD
347 /*
348  * The RM7000 needs twice as much nops around tlb* instructions.
349  */
350 #define	TLB_HAZARD		NOP; NOP; NOP; NOP
351 #endif
352 
353 #ifdef CPU_R8000
354 /*
355  * The R8000 needs a lot of care inserting proper superscalar dispatch breaks
356  * to prevent unwanted side-effects or avoid collisions on the internal MiscBus
357  * and the E and W stages of the pipelines.
358  *
359  * The following settings are a bit pessimistic, but better run safely than
360  * not at all.
361  */
362 #define	PRE_MFC0_ADDR_HAZARD	.align 5; SSNOP
363 #define	MFC0_HAZARD		SSNOP
364 #define	MTC0_HAZARD		SSNOP; SSNOP; SSNOP
365 #define	MTC0_SR_IE_HAZARD	MTC0_HAZARD; SSNOP
366 #define	MTC0_SR_CU_HAZARD	MTC0_HAZARD; SSNOP
367 #endif
368 
369 /* Hazard between {d,}mfc0 of COP_0_VADDR */
370 #ifndef	PRE_MFC0_ADDR_HAZARD
371 #define	PRE_MFC0_ADDR_HAZARD	/* nothing */
372 #endif
373 
374 /* Hazard after {d,}mfc0 from any register */
375 #ifndef	MFC0_HAZARD
376 #define	MFC0_HAZARD     	/* nothing */
377 #endif
378 /* Hazard after {d,}mtc0 to any register */
379 #ifndef	MTC0_HAZARD
380 #define	MTC0_HAZARD     	NOP; NOP; NOP; NOP
381 #endif
382 /* Hazard after {d,}mtc0 to COP_0_SR affecting the state of interrupts */
383 #ifndef	MTC0_SR_IE_HAZARD
384 #define	MTC0_SR_IE_HAZARD	MTC0_HAZARD
385 #endif
386 /* Hazard after {d,}mtc0 to COP_0_SR affecting the state of coprocessors */
387 #ifndef	MTC0_SR_CU_HAZARD
388 #define	MTC0_SR_CU_HAZARD	NOP; NOP
389 #endif
390 
391 /* Hazard before and after a tlbp, tlbr, tlbwi or tlbwr instruction */
392 #ifndef	TLB_HAZARD
393 #define	TLB_HAZARD		NOP; NOP
394 #endif
395 
396 #endif /* !_MIPS64_ASM_H_ */
397