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