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