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