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