1 /* 2 * Copyright (C) 1995, 1996, 1997, 1999, 2001 by Ralf Baechle 3 * Copyright (C) 1999 by Silicon Graphics, Inc. 4 * Copyright (C) 2001 MIPS Technologies, Inc. 5 * Copyright (C) 2002 Maciej W. Rozycki 6 * 7 * Some useful macros for MIPS assembler code 8 * 9 * Some of the routines below contain useless nops that will be optimized 10 * away by gas in -O mode. These nops are however required to fill delay 11 * slots in noreorder mode. 12 * 13 * SPDX-License-Identifier: GPL-2.0 14 */ 15 #ifndef __ASM_ASM_H 16 #define __ASM_ASM_H 17 18 #include <asm/sgidefs.h> 19 20 #ifndef CAT 21 #ifdef __STDC__ 22 #define __CAT(str1, str2) str1##str2 23 #else 24 #define __CAT(str1, str2) str1/**/str2 25 #endif 26 #define CAT(str1, str2) __CAT(str1, str2) 27 #endif 28 29 /* 30 * PIC specific declarations 31 * Not used for the kernel but here seems to be the right place. 32 */ 33 #ifdef __PIC__ 34 #define CPRESTORE(register) \ 35 .cprestore register 36 #define CPADD(register) \ 37 .cpadd register 38 #define CPLOAD(register) \ 39 .cpload register 40 #else 41 #define CPRESTORE(register) 42 #define CPADD(register) 43 #define CPLOAD(register) 44 #endif 45 46 #define ENTRY(symbol) \ 47 .globl symbol; \ 48 .type symbol, @function; \ 49 .ent symbol, 0; \ 50 symbol: 51 52 /* 53 * LEAF - declare leaf routine 54 */ 55 #define LEAF(symbol) \ 56 .globl symbol; \ 57 .align 2; \ 58 .type symbol, @function; \ 59 .ent symbol, 0; \ 60 .section .text.symbol, "x"; \ 61 symbol: .frame sp, 0, ra 62 63 /* 64 * NESTED - declare nested routine entry point 65 */ 66 #define NESTED(symbol, framesize, rpc) \ 67 .globl symbol; \ 68 .align 2; \ 69 .type symbol, @function; \ 70 .ent symbol, 0; \ 71 .section .text.symbol, "x"; \ 72 symbol: .frame sp, framesize, rpc 73 74 /* 75 * END - mark end of function 76 */ 77 #define END(function) \ 78 .end function; \ 79 .size function, .-function 80 81 /* 82 * EXPORT - export definition of symbol 83 */ 84 #define EXPORT(symbol) \ 85 .globl symbol; \ 86 symbol: 87 88 /* 89 * FEXPORT - export definition of a function symbol 90 */ 91 #define FEXPORT(symbol) \ 92 .globl symbol; \ 93 .type symbol, @function; \ 94 symbol: 95 96 /* 97 * ABS - export absolute symbol 98 */ 99 #define ABS(symbol,value) \ 100 .globl symbol; \ 101 symbol = value 102 103 #define PANIC(msg) \ 104 .set push; \ 105 .set reorder; \ 106 PTR_LA a0, 8f; \ 107 jal panic; \ 108 9: b 9b; \ 109 .set pop; \ 110 TEXT(msg) 111 112 /* 113 * Print formatted string 114 */ 115 #ifdef CONFIG_PRINTK 116 #define PRINT(string) \ 117 .set push; \ 118 .set reorder; \ 119 PTR_LA a0, 8f; \ 120 jal printk; \ 121 .set pop; \ 122 TEXT(string) 123 #else 124 #define PRINT(string) 125 #endif 126 127 #define TEXT(msg) \ 128 .pushsection .data; \ 129 8: .asciiz msg; \ 130 .popsection; 131 132 /* 133 * Build text tables 134 */ 135 #define TTABLE(string) \ 136 .pushsection .text; \ 137 .word 1f; \ 138 .popsection \ 139 .pushsection .data; \ 140 1: .asciiz string; \ 141 .popsection 142 143 /* 144 * MIPS IV pref instruction. 145 * Use with .set noreorder only! 146 * 147 * MIPS IV implementations are free to treat this as a nop. The R5000 148 * is one of them. So we should have an option not to use this instruction. 149 */ 150 #ifdef CONFIG_CPU_HAS_PREFETCH 151 152 #define PREF(hint, addr) \ 153 .set push; \ 154 .set arch=r5000; \ 155 pref hint, addr; \ 156 .set pop 157 158 #define PREFE(hint, addr) \ 159 .set push; \ 160 .set mips0; \ 161 .set eva; \ 162 prefe hint, addr; \ 163 .set pop 164 165 #define PREFX(hint, addr) \ 166 .set push; \ 167 .set arch=r5000; \ 168 prefx hint, addr; \ 169 .set pop 170 171 #else /* !CONFIG_CPU_HAS_PREFETCH */ 172 173 #define PREF(hint, addr) 174 #define PREFE(hint, addr) 175 #define PREFX(hint, addr) 176 177 #endif /* !CONFIG_CPU_HAS_PREFETCH */ 178 179 /* 180 * MIPS ISA IV/V movn/movz instructions and equivalents for older CPUs. 181 */ 182 #if (_MIPS_ISA == _MIPS_ISA_MIPS1) 183 #define MOVN(rd, rs, rt) \ 184 .set push; \ 185 .set reorder; \ 186 beqz rt, 9f; \ 187 move rd, rs; \ 188 .set pop; \ 189 9: 190 #define MOVZ(rd, rs, rt) \ 191 .set push; \ 192 .set reorder; \ 193 bnez rt, 9f; \ 194 move rd, rs; \ 195 .set pop; \ 196 9: 197 #endif /* _MIPS_ISA == _MIPS_ISA_MIPS1 */ 198 #if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) 199 #define MOVN(rd, rs, rt) \ 200 .set push; \ 201 .set noreorder; \ 202 bnezl rt, 9f; \ 203 move rd, rs; \ 204 .set pop; \ 205 9: 206 #define MOVZ(rd, rs, rt) \ 207 .set push; \ 208 .set noreorder; \ 209 beqzl rt, 9f; \ 210 move rd, rs; \ 211 .set pop; \ 212 9: 213 #endif /* (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) */ 214 #if (_MIPS_ISA == _MIPS_ISA_MIPS4 ) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \ 215 (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64) 216 #define MOVN(rd, rs, rt) \ 217 movn rd, rs, rt 218 #define MOVZ(rd, rs, rt) \ 219 movz rd, rs, rt 220 #endif /* MIPS IV, MIPS V, MIPS32 or MIPS64 */ 221 222 /* 223 * Stack alignment 224 */ 225 #if (_MIPS_SIM == _MIPS_SIM_ABI32) 226 #define ALSZ 7 227 #define ALMASK ~7 228 #endif 229 #if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) 230 #define ALSZ 15 231 #define ALMASK ~15 232 #endif 233 234 /* 235 * Macros to handle different pointer/register sizes for 32/64-bit code 236 */ 237 238 /* 239 * Size of a register 240 */ 241 #ifdef __mips64 242 #define SZREG 8 243 #else 244 #define SZREG 4 245 #endif 246 247 /* 248 * Use the following macros in assemblercode to load/store registers, 249 * pointers etc. 250 */ 251 #if (_MIPS_SIM == _MIPS_SIM_ABI32) 252 #define REG_S sw 253 #define REG_L lw 254 #define REG_SUBU subu 255 #define REG_ADDU addu 256 #endif 257 #if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) 258 #define REG_S sd 259 #define REG_L ld 260 #define REG_SUBU dsubu 261 #define REG_ADDU daddu 262 #endif 263 264 /* 265 * How to add/sub/load/store/shift C int variables. 266 */ 267 #if (_MIPS_SZINT == 32) 268 #define INT_ADD add 269 #define INT_ADDU addu 270 #define INT_ADDI addi 271 #define INT_ADDIU addiu 272 #define INT_SUB sub 273 #define INT_SUBU subu 274 #define INT_L lw 275 #define INT_S sw 276 #define INT_SLL sll 277 #define INT_SLLV sllv 278 #define INT_SRL srl 279 #define INT_SRLV srlv 280 #define INT_SRA sra 281 #define INT_SRAV srav 282 #endif 283 284 #if (_MIPS_SZINT == 64) 285 #define INT_ADD dadd 286 #define INT_ADDU daddu 287 #define INT_ADDI daddi 288 #define INT_ADDIU daddiu 289 #define INT_SUB dsub 290 #define INT_SUBU dsubu 291 #define INT_L ld 292 #define INT_S sd 293 #define INT_SLL dsll 294 #define INT_SLLV dsllv 295 #define INT_SRL dsrl 296 #define INT_SRLV dsrlv 297 #define INT_SRA dsra 298 #define INT_SRAV dsrav 299 #endif 300 301 /* 302 * How to add/sub/load/store/shift C long variables. 303 */ 304 #if (_MIPS_SZLONG == 32) 305 #define LONG_ADD add 306 #define LONG_ADDU addu 307 #define LONG_ADDI addi 308 #define LONG_ADDIU addiu 309 #define LONG_SUB sub 310 #define LONG_SUBU subu 311 #define LONG_L lw 312 #define LONG_S sw 313 #define LONG_SP swp 314 #define LONG_SLL sll 315 #define LONG_SLLV sllv 316 #define LONG_SRL srl 317 #define LONG_SRLV srlv 318 #define LONG_SRA sra 319 #define LONG_SRAV srav 320 321 #define LONG .word 322 #define LONGSIZE 4 323 #define LONGMASK 3 324 #define LONGLOG 2 325 #endif 326 327 #if (_MIPS_SZLONG == 64) 328 #define LONG_ADD dadd 329 #define LONG_ADDU daddu 330 #define LONG_ADDI daddi 331 #define LONG_ADDIU daddiu 332 #define LONG_SUB dsub 333 #define LONG_SUBU dsubu 334 #define LONG_L ld 335 #define LONG_S sd 336 #define LONG_SP sdp 337 #define LONG_SLL dsll 338 #define LONG_SLLV dsllv 339 #define LONG_SRL dsrl 340 #define LONG_SRLV dsrlv 341 #define LONG_SRA dsra 342 #define LONG_SRAV dsrav 343 344 #define LONG .dword 345 #define LONGSIZE 8 346 #define LONGMASK 7 347 #define LONGLOG 3 348 #endif 349 350 /* 351 * How to add/sub/load/store/shift pointers. 352 */ 353 #if (_MIPS_SZPTR == 32) 354 #define PTR_ADD add 355 #define PTR_ADDU addu 356 #define PTR_ADDI addi 357 #define PTR_ADDIU addiu 358 #define PTR_SUB sub 359 #define PTR_SUBU subu 360 #define PTR_L lw 361 #define PTR_S sw 362 #define PTR_LA la 363 #define PTR_LI li 364 #define PTR_SLL sll 365 #define PTR_SLLV sllv 366 #define PTR_SRL srl 367 #define PTR_SRLV srlv 368 #define PTR_SRA sra 369 #define PTR_SRAV srav 370 371 #define PTR_SCALESHIFT 2 372 373 #define PTR .word 374 #define PTRSIZE 4 375 #define PTRLOG 2 376 #endif 377 378 #if (_MIPS_SZPTR == 64) 379 #define PTR_ADD dadd 380 #define PTR_ADDU daddu 381 #define PTR_ADDI daddi 382 #define PTR_ADDIU daddiu 383 #define PTR_SUB dsub 384 #define PTR_SUBU dsubu 385 #define PTR_L ld 386 #define PTR_S sd 387 #define PTR_LA dla 388 #define PTR_LI dli 389 #define PTR_SLL dsll 390 #define PTR_SLLV dsllv 391 #define PTR_SRL dsrl 392 #define PTR_SRLV dsrlv 393 #define PTR_SRA dsra 394 #define PTR_SRAV dsrav 395 396 #define PTR_SCALESHIFT 3 397 398 #define PTR .dword 399 #define PTRSIZE 8 400 #define PTRLOG 3 401 #endif 402 403 /* 404 * Some cp0 registers were extended to 64bit for MIPS III. 405 */ 406 #if (_MIPS_SIM == _MIPS_SIM_ABI32) 407 #define MFC0 mfc0 408 #define MTC0 mtc0 409 #endif 410 #if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) 411 #define MFC0 dmfc0 412 #define MTC0 dmtc0 413 #endif 414 415 #define SSNOP sll zero, zero, 1 416 417 #ifdef CONFIG_SGI_IP28 418 /* Inhibit speculative stores to volatile (e.g.DMA) or invalid addresses. */ 419 #include <asm/cacheops.h> 420 #define R10KCBARRIER(addr) cache CACHE_BARRIER, addr; 421 #else 422 #define R10KCBARRIER(addr) 423 #endif 424 425 #endif /* __ASM_ASM_H */ 426