| 1 | /*	$OpenBSD: asm.h,v 1.27 2021/05/01 16:11:10 visa 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 | #define	_MIPS_ISA_MIPS32	32	/* MIPS32 */ |
| 38 | #define	_MIPS_ISA_MIPS64	64	/* MIPS64 */ |
| 39 | |
| 40 | #if !defined(ABICALLS) && !defined(_NO_ABICALLS) |
| 41 | #define	ABICALLS	.abicalls |
| 42 | #endif |
| 43 | |
| 44 | #if defined(ABICALLS) && !defined(_KERNEL) |
| 45 | 	ABICALLS |
| 46 | #endif |
| 47 | |
| 48 | #define _C_LABEL(x) x		/* XXX Obsolete but keep for a while */ |
| 49 | |
| 50 | #if !defined(__MIPSEL__) && !defined(__MIPSEB__) |
| 51 | #error "__MIPSEL__ or __MIPSEB__ must be defined" |
| 52 | #endif |
| 53 | /* |
| 54 | * Define how to access unaligned data word |
| 55 | */ |
| 56 | #if defined(__MIPSEL__) |
| 57 | #define LWLO lwl |
| 58 | #define LWHI lwr |
| 59 | #define	SWLO	swl |
| 60 | #define	SWHI	swr |
| 61 | #define LDLO ldl |
| 62 | #define LDHI ldr |
| 63 | #define	SDLO	sdl |
| 64 | #define	SDHI	sdr |
| 65 | #endif |
| 66 | #if defined(__MIPSEB__) |
| 67 | #define LWLO lwr |
| 68 | #define LWHI lwl |
| 69 | #define	SWLO	swr |
| 70 | #define	SWHI	swl |
| 71 | #define LDLO ldr |
| 72 | #define LDHI ldl |
| 73 | #define	SDLO	sdr |
| 74 | #define	SDHI	sdl |
| 75 | #endif |
| 76 | |
| 77 | /* |
| 78 | * Define programming environment for ABI. |
| 79 | */ |
| 80 | #if defined(ABICALLS) && !defined(_KERNEL) && !defined(_STANDALONE) |
| 81 | |
| 82 | #ifndef _MIPS_SIM |
| 83 | #define _MIPS_SIM 1 |
| 84 | #define _ABIO32	1 |
| 85 | #endif |
| 86 | #ifndef _MIPS_ISA |
| 87 | #define _MIPS_ISA 2 |
| 88 | #define _MIPS_ISA_MIPS2 2 |
| 89 | #endif |
| 90 | |
| 91 | #if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) |
| 92 | #define NARGSAVE	4 |
| 93 | |
| 94 | #define	SETUP_GP		\ |
| 95 | 	.set	noreorder;	\ |
| 96 | 	.cpload	t9;		\ |
| 97 | 	.set	reorder; |
| 98 | |
| 99 | #define	SAVE_GP(x)		\ |
| 100 | 	.cprestore x |
| 101 | |
| 102 | #define	SETUP_GP64(gpoff, name) |
| 103 | #define	RESTORE_GP64 |
| 104 | #endif |
| 105 | |
| 106 | #if (_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32) |
| 107 | #define NARGSAVE	0 |
| 108 | |
| 109 | #define	SETUP_GP |
| 110 | #define	SAVE_GP(x) |
| 111 | #define	SETUP_GP64(gpoff, name)	\ |
| 112 | 	.cpsetup t9, gpoff, name |
| 113 | #define	RESTORE_GP64		\ |
| 114 | 	.cpreturn |
| 115 | #endif |
| 116 | |
| 117 | #define	MKFSIZ(narg,locals) (((narg+locals)*REGSZ+31)&(~31)) |
| 118 | |
| 119 | #else /* defined(ABICALLS) && !defined(_KERNEL) */ |
| 120 | |
| 121 | #define	NARGSAVE	4 |
| 122 | #define	SETUP_GP |
| 123 | #define	SAVE_GP(x) |
| 124 | |
| 125 | #define	ALIGNSZ		16	/* Stack layout alignment */ |
| 126 | #define	FRAMESZ(sz)	(((sz) + (ALIGNSZ-1)) & ~(ALIGNSZ-1)) |
| 127 | |
| 128 | #endif |
| 129 | |
| 130 | /* |
| 131 | * Basic register operations based on selected ISA |
| 132 | */ |
| 133 | #if (_MIPS_ISA == _MIPS_ISA_MIPS1 || _MIPS_ISA == _MIPS_ISA_MIPS2 || \ |
| 134 | _MIPS_ISA == _MIPS_ISA_MIPS32) |
| 135 | #define REGSZ		4	/* 32 bit mode register size */ |
| 136 | #define LOGREGSZ	2	/* log rsize */ |
| 137 | #define	REG_S	sw |
| 138 | #define	REG_L	lw |
| 139 | #define	CF_SZ		24	/* Call frame size */ |
| 140 | #define	CF_ARGSZ	16	/* Call frame arg size */ |
| 141 | #define	CF_RA_OFFS	20	/* Call ra save offset */ |
| 142 | #endif |
| 143 | |
| 144 | #if (_MIPS_ISA == _MIPS_ISA_MIPS3 || _MIPS_ISA == _MIPS_ISA_MIPS4 || \ |
| 145 | _MIPS_ISA == _MIPS_ISA_MIPS64) |
| 146 | #define REGSZ		8	/* 64 bit mode register size */ |
| 147 | #define LOGREGSZ	3	/* log rsize */ |
| 148 | #define	REG_S	sd |
| 149 | #define	REG_L	ld |
| 150 | #define	CF_SZ		48	/* Call frame size (multiple of ALIGNSZ) */ |
| 151 | #define	CF_ARGSZ	32	/* Call frame arg size */ |
| 152 | #define	CF_RA_OFFS	40	/* Call ra save offset */ |
| 153 | #endif |
| 154 | |
| 155 | #ifndef __LP64__ |
| 156 | #define	PTR_L		lw |
| 157 | #define	PTR_S		sw |
| 158 | #define	PTR_SUB		sub |
| 159 | #define	PTR_ADD		add |
| 160 | #define	PTR_SUBU	subu |
| 161 | #define	PTR_ADDU	addu |
| 162 | #define LI		li |
| 163 | #define	LA		la |
| 164 | #define	PTR_SLL		sll |
| 165 | #define	PTR_SRL		srl |
| 166 | #define	PTR_VAL		.word |
| 167 | #else |
| 168 | #define	PTR_L		ld |
| 169 | #define	PTR_S		sd |
| 170 | #define	PTR_ADD		dadd |
| 171 | #define	PTR_SUB		dsub |
| 172 | #define	PTR_SUBU	dsubu |
| 173 | #define	PTR_ADDU	daddu |
| 174 | #define LI		dli |
| 175 | #define LA		dla |
| 176 | #define	PTR_SLL		dsll |
| 177 | #define	PTR_SRL		dsrl |
| 178 | #define	PTR_VAL		.dword |
| 179 | #endif |
| 180 | |
| 181 | #define	NOP	nop |
| 182 | #define	DMFC0	dmfc0 |
| 183 | #define	DMTC0	dmtc0 |
| 184 | #define	MFC0	mfc0 |
| 185 | #define	MTC0	mtc0 |
| 186 | #define	ERET	sync; eret |
| 187 | |
| 188 | /* |
| 189 | * Define -pg profile entry code. |
| 190 | */ |
| 191 | #if defined(XGPROF) || defined(XPROF) |
| 192 | #define	MCOUNT			\ |
| 193 | 	PTR_SUBU sp, sp, 64;	\ |
| 194 | 	SAVE_GP(16);		\ |
| 195 | 	sd	ra, 56(sp);	\ |
| 196 | 	sd	gp, 48(sp);	\ |
| 197 | 	.set	noat;		\ |
| 198 | 	.set	noreorder;	\ |
| 199 | 	move	AT, ra;		\ |
| 200 | 	jal	_mcount;	\ |
| 201 | 	PTR_SUBU sp, sp, 16;	\ |
| 202 | 	ld	ra, 56(sp);	\ |
| 203 | 	PTR_ADDU sp, sp, 64;	\ |
| 204 | 	.set reorder;		\ |
| 205 | 	.set	at; |
| 206 | #else |
| 207 | #define	MCOUNT |
| 208 | #endif |
| 209 | |
| 210 | /* |
| 211 | * LEAF(x, fsize) |
| 212 | * |
| 213 | *	Declare a leaf routine. |
| 214 | */ |
| 215 | #define LEAF(x, fsize)		\ |
| 216 | 	.align	3;		\ |
| 217 | 	.globl x;		\ |
| 218 | 	.ent x, 0;		\ |
| 219 | x: ;				\ |
| 220 | 	.frame sp, fsize, ra;	\ |
| 221 | 	SETUP_GP		\ |
| 222 | 	MCOUNT |
| 223 | |
| 224 | #define	ALEAF(x)		\ |
| 225 | 	.globl	x;		\ |
| 226 | x: |
| 227 | |
| 228 | /* |
| 229 | * NLEAF(x) |
| 230 | * |
| 231 | *	Declare a non-profiled leaf routine. |
| 232 | */ |
| 233 | #define NLEAF(x, fsize)		\ |
| 234 | 	.align	3;		\ |
| 235 | 	.globl x;		\ |
| 236 | 	.ent x, 0;		\ |
| 237 | x: ;				\ |
| 238 | 	.frame sp, fsize, ra;	\ |
| 239 | 	SETUP_GP |
| 240 | |
| 241 | /* |
| 242 | * NON_LEAF(x) |
| 243 | * |
| 244 | *	Declare a non-leaf routine (a routine that makes other C calls). |
| 245 | */ |
| 246 | #define NON_LEAF(x, fsize, retpc) \ |
| 247 | 	.align	3;		\ |
| 248 | 	.globl x;		\ |
| 249 | 	.ent x, 0;		\ |
| 250 | x: ;				\ |
| 251 | 	.frame sp, fsize, retpc; \ |
| 252 | 	SETUP_GP		\ |
| 253 | 	MCOUNT |
| 254 | |
| 255 | /* |
| 256 | * NNON_LEAF(x) |
| 257 | * |
| 258 | *	Declare a non-profiled non-leaf routine |
| 259 | *	(a routine that makes other C calls). |
| 260 | */ |
| 261 | #define NNON_LEAF(x, fsize, retpc) \ |
| 262 | 	.align	3;		\ |
| 263 | 	.globl x;		\ |
| 264 | 	.ent x, 0;		\ |
| 265 | x: ;				\ |
| 266 | 	.frame sp, fsize, retpc	\ |
| 267 | 	SETUP_GP |
| 268 | |
| 269 | /* |
| 270 | * END(x) |
| 271 | * |
| 272 | *	Mark end of a procedure. |
| 273 | */ |
| 274 | #define END(x) \ |
| 275 | 	.end x |
| 276 | |
| 277 | /* |
| 278 | * STRONG_ALIAS, WEAK_ALIAS |
| 279 | *	Create a strong or weak alias. |
| 280 | */ |
| 281 | #define STRONG_ALIAS(alias,sym) \ |
| 282 | 	.global alias; alias = sym |
| 283 | #define WEAK_ALIAS(alias,sym) \ |
| 284 | 	.weak alias; alias = sym |
| 285 | |
| 286 | |
| 287 | /* |
| 288 | * Macros to panic and printf from assembly language. |
| 289 | */ |
| 290 | #define PANIC(msg) \ |
| 291 | 	LA	a0, 9f; \ |
| 292 | 	jal	panic;	\ |
| 293 | 	nop	;	\ |
| 294 | 	MSG(msg) |
| 295 | |
| 296 | #define	PRINTF(msg) \ |
| 297 | 	LA	a0, 9f; \ |
| 298 | 	jal	printf; \ |
| 299 | 	nop	;	\ |
| 300 | 	MSG(msg) |
| 301 | |
| 302 | #define	MSG(msg) \ |
| 303 | 	.rdata; \ |
| 304 | 9:	.asciiz	msg; \ |
| 305 | 	.text |
| 306 | |
| 307 | #define	LOAD_XKPHYS(reg, cca) \ |
| 308 | 	li	reg, cca | 0x10; \ |
| 309 | 	dsll	reg, reg, 59 |
| 310 | |
| 311 | #ifdef MULTIPROCESSOR |
| 312 | #define GET_CPU_INFO(ci, tmp)	HW_GET_CPU_INFO(ci, tmp) |
| 313 | #else /* MULTIPROCESSOR */ |
| 314 | #define GET_CPU_INFO(ci, tmp)		\ |
| 315 | 	LA	ci, cpu_info_primary |
| 316 | #endif /* MULTIPROCESSOR */ |
| 317 | |
| 318 | /* |
| 319 | * Hazards |
| 320 | */ |
| 321 | |
| 322 | #ifdef CPU_OCTEON |
| 323 | /* |
| 324 | * OCTEON clears hazards in hardware. |
| 325 | */ |
| 326 | #define	MFC0_HAZARD		/* nothing */ |
| 327 | #define	MTC0_HAZARD		/* nothing */ |
| 328 | #define	MTC0_SR_IE_HAZARD	/* nothing */ |
| 329 | #define	MTC0_SR_CU_HAZARD	/* nothing */ |
| 330 | #define	TLB_HAZARD		/* nothing */ |
| 331 | #endif |
| 332 | |
| 333 | /* Hazard between {d,}mfc0 of COP_0_VADDR */ |
| 334 | #ifndef	PRE_MFC0_ADDR_HAZARD |
| 335 | #define	PRE_MFC0_ADDR_HAZARD	/* nothing */ |
| 336 | #endif |
| 337 | |
| 338 | /* Hazard after {d,}mfc0 from any register */ |
| 339 | #ifndef	MFC0_HAZARD |
| 340 | #define	MFC0_HAZARD 	/* nothing */ |
| 341 | #endif |
| 342 | /* Hazard after {d,}mtc0 to any register */ |
| 343 | #ifndef	MTC0_HAZARD |
| 344 | #define	MTC0_HAZARD 	NOP; NOP; NOP; NOP |
| 345 | #endif |
| 346 | /* Hazard after {d,}mtc0 to COP_0_SR affecting the state of interrupts */ |
| 347 | #ifndef	MTC0_SR_IE_HAZARD |
| 348 | #define	MTC0_SR_IE_HAZARD	MTC0_HAZARD |
| 349 | #endif |
| 350 | /* Hazard after {d,}mtc0 to COP_0_SR affecting the state of coprocessors */ |
| 351 | #ifndef	MTC0_SR_CU_HAZARD |
| 352 | #define	MTC0_SR_CU_HAZARD	NOP; NOP |
| 353 | #endif |
| 354 | |
| 355 | /* Hazard before and after a tlbp, tlbr, tlbwi or tlbwr instruction */ |
| 356 | #ifndef	TLB_HAZARD |
| 357 | #define	TLB_HAZARD		NOP; NOP |
| 358 | #endif |
| 359 | |
| 360 | #endif /* !_MIPS64_ASM_H_ */ |