| /* | |
| * This file is subject to the terms and conditions of the GNU General Public | |
| * License. See the file "COPYING" in the main directory of this archive | |
| * for more details. | |
| * | |
| * Copyright (C) 1995, 1996, 1997, 1999, 2001 by Ralf Baechle | |
| * Copyright (C) 1999 by Silicon Graphics, Inc. | |
| * Copyright (C) 2001 MIPS Technologies, Inc. | |
| * Copyright (C) 2002 Maciej W. Rozycki | |
| * | |
| * Some useful macros for MIPS assembler code | |
| * | |
| * Some of the routines below contain useless nops that will be optimized | |
| * away by gas in -O mode. These nops are however required to fill delay | |
| * slots in noreorder mode. | |
| */ | |
| #ifndef __ASM_ASM_H | |
| #define __ASM_ASM_H | |
| #include <asm/sgidefs.h> | |
| #include <asm/asm-eva.h> | |
| #include <asm/isa-rev.h> | |
| #ifndef __VDSO__ | |
| /* | |
| * Emit CFI data in .debug_frame sections, not .eh_frame sections. | |
| * We don't do DWARF unwinding at runtime, so only the offline DWARF | |
| * information is useful to anyone. Note we should change this if we | |
| * ever decide to enable DWARF unwinding at runtime. | |
| */ | |
| #define CFI_SECTIONS .cfi_sections .debug_frame | |
| #else | |
| /* | |
| * For the vDSO, emit both runtime unwind information and debug | |
| * symbols for the .dbg file. | |
| */ | |
| #define CFI_SECTIONS | |
| #endif | |
| #ifdef __ASSEMBLER__ | |
| /* | |
| * LEAF - declare leaf routine | |
| */ | |
| #define LEAF(symbol) \ | |
| CFI_SECTIONS; \ | |
| .globl symbol; \ | |
| .align 2; \ | |
| .type symbol, @function; \ | |
| .ent symbol, 0; \ | |
| symbol: .frame sp, 0, ra; \ | |
| .cfi_startproc; \ | |
| .insn | |
| /* | |
| * NESTED - declare nested routine entry point | |
| */ | |
| #define NESTED(symbol, framesize, rpc) \ | |
| CFI_SECTIONS; \ | |
| .globl symbol; \ | |
| .align 2; \ | |
| .type symbol, @function; \ | |
| .ent symbol, 0; \ | |
| symbol: .frame sp, framesize, rpc; \ | |
| .cfi_startproc; \ | |
| .insn | |
| /* | |
| * END - mark end of function | |
| */ | |
| #define END(function) \ | |
| .cfi_endproc; \ | |
| .end function; \ | |
| .size function, .-function | |
| /* | |
| * EXPORT - export definition of symbol | |
| */ | |
| #define EXPORT(symbol) \ | |
| .globl symbol; \ | |
| symbol: | |
| /* | |
| * FEXPORT - export definition of a function symbol | |
| */ | |
| #define FEXPORT(symbol) \ | |
| .globl symbol; \ | |
| .type symbol, @function; \ | |
| symbol: .insn | |
| /* | |
| * ABS - export absolute symbol | |
| */ | |
| #define ABS(symbol,value) \ | |
| .globl symbol; \ | |
| symbol = value | |
| #define TEXT(msg) \ | |
| .pushsection .data; \ | |
| 8: .asciiz msg; \ | |
| .popsection; | |
| #define ASM_PANIC(msg) \ | |
| .set push; \ | |
| .set reorder; \ | |
| PTR_LA a0, 8f; \ | |
| jal panic; \ | |
| 9: b 9b; \ | |
| .set pop; \ | |
| TEXT(msg) | |
| /* | |
| * Print formatted string | |
| */ | |
| #ifdef CONFIG_PRINTK | |
| #define ASM_PRINT(string) \ | |
| .set push; \ | |
| .set reorder; \ | |
| PTR_LA a0, 8f; \ | |
| jal _printk; \ | |
| .set pop; \ | |
| TEXT(string) | |
| #else | |
| #define ASM_PRINT(string) | |
| #endif | |
| #endif /* __ASSEMBLER__ */ | |
| /* | |
| * Stack alignment | |
| */ | |
| #if (_MIPS_SIM == _MIPS_SIM_ABI32) | |
| #define ALSZ 7 | |
| #define ALMASK ~7 | |
| #endif | |
| #if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) | |
| #define ALSZ 15 | |
| #define ALMASK ~15 | |
| #endif | |
| /* | |
| * Macros to handle different pointer/register sizes for 32/64-bit code | |
| */ | |
| /* | |
| * Size of a register | |
| */ | |
| #ifdef __mips64 | |
| #define SZREG 8 | |
| #else | |
| #define SZREG 4 | |
| #endif | |
| /* | |
| * Use the following macros in assemblercode to load/store registers, | |
| * pointers etc. | |
| */ | |
| #if (_MIPS_SIM == _MIPS_SIM_ABI32) | |
| #define REG_S sw | |
| #define REG_L lw | |
| #define REG_SUBU subu | |
| #define REG_ADDU addu | |
| #endif | |
| #if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) | |
| #define REG_S sd | |
| #define REG_L ld | |
| #define REG_SUBU dsubu | |
| #define REG_ADDU daddu | |
| #endif | |
| /* | |
| * How to add/sub/load/store/shift C int variables. | |
| */ | |
| #if (_MIPS_SZINT == 32) | |
| #define INT_ADD add | |
| #define INT_ADDU addu | |
| #define INT_ADDI addi | |
| #define INT_ADDIU addiu | |
| #define INT_SUB sub | |
| #define INT_SUBU subu | |
| #define INT_L lw | |
| #define INT_S sw | |
| #define INT_SLL sll | |
| #define INT_SLLV sllv | |
| #define INT_SRL srl | |
| #define INT_SRLV srlv | |
| #define INT_SRA sra | |
| #define INT_SRAV srav | |
| #endif | |
| #if (_MIPS_SZINT == 64) | |
| #define INT_ADD dadd | |
| #define INT_ADDU daddu | |
| #define INT_ADDI daddi | |
| #define INT_ADDIU daddiu | |
| #define INT_SUB dsub | |
| #define INT_SUBU dsubu | |
| #define INT_L ld | |
| #define INT_S sd | |
| #define INT_SLL dsll | |
| #define INT_SLLV dsllv | |
| #define INT_SRL dsrl | |
| #define INT_SRLV dsrlv | |
| #define INT_SRA dsra | |
| #define INT_SRAV dsrav | |
| #endif | |
| /* | |
| * How to add/sub/load/store/shift C long variables. | |
| */ | |
| #if (_MIPS_SZLONG == 32) | |
| #define LONG_ADD add | |
| #define LONG_ADDU addu | |
| #define LONG_ADDI addi | |
| #define LONG_ADDIU addiu | |
| #define LONG_SUB sub | |
| #define LONG_SUBU subu | |
| #define LONG_L lw | |
| #define LONG_LL ll | |
| #define LONG_SC sc | |
| #define LONG_S sw | |
| #define LONG_SP swp | |
| #define LONG_SLL sll | |
| #define LONG_SLLV sllv | |
| #define LONG_SRL srl | |
| #define LONG_SRLV srlv | |
| #define LONG_SRA sra | |
| #define LONG_SRAV srav | |
| #define LONG_INS ins | |
| #define LONG_EXT ext | |
| #ifdef __ASSEMBLER__ | |
| #define LONG .word | |
| #endif | |
| #define LONGSIZE 4 | |
| #define LONGMASK 3 | |
| #define LONGLOG 2 | |
| #endif | |
| #if (_MIPS_SZLONG == 64) | |
| #define LONG_ADD dadd | |
| #define LONG_ADDU daddu | |
| #define LONG_ADDI daddi | |
| #define LONG_ADDIU daddiu | |
| #define LONG_SUB dsub | |
| #define LONG_SUBU dsubu | |
| #define LONG_L ld | |
| #define LONG_LL lld | |
| #define LONG_SC scd | |
| #define LONG_S sd | |
| #define LONG_SP sdp | |
| #define LONG_SLL dsll | |
| #define LONG_SLLV dsllv | |
| #define LONG_SRL dsrl | |
| #define LONG_SRLV dsrlv | |
| #define LONG_SRA dsra | |
| #define LONG_SRAV dsrav | |
| #define LONG_INS dins | |
| #define LONG_EXT dext | |
| #ifdef __ASSEMBLER__ | |
| #define LONG .dword | |
| #endif | |
| #define LONGSIZE 8 | |
| #define LONGMASK 7 | |
| #define LONGLOG 3 | |
| #endif | |
| /* | |
| * How to add/sub/load/store/shift pointers. | |
| */ | |
| #if (_MIPS_SZPTR == 32) | |
| #define PTR_ADD add | |
| #define PTR_ADDU addu | |
| #define PTR_ADDI addi | |
| #define PTR_ADDIU addiu | |
| #define PTR_SUB sub | |
| #define PTR_SUBU subu | |
| #define PTR_L lw | |
| #define PTR_S sw | |
| #define PTR_LA la | |
| #define PTR_LI li | |
| #define PTR_SLL sll | |
| #define PTR_SLLV sllv | |
| #define PTR_SRL srl | |
| #define PTR_SRLV srlv | |
| #define PTR_SRA sra | |
| #define PTR_SRAV srav | |
| #define PTR_SCALESHIFT 2 | |
| #define PTR_WD .word | |
| #define PTRSIZE 4 | |
| #define PTRLOG 2 | |
| #endif | |
| #if (_MIPS_SZPTR == 64) | |
| #define PTR_ADD dadd | |
| #define PTR_ADDU daddu | |
| #define PTR_ADDI daddi | |
| #define PTR_ADDIU daddiu | |
| #define PTR_SUB dsub | |
| #define PTR_SUBU dsubu | |
| #define PTR_L ld | |
| #define PTR_S sd | |
| #define PTR_LA dla | |
| #define PTR_LI dli | |
| #define PTR_SLL dsll | |
| #define PTR_SLLV dsllv | |
| #define PTR_SRL dsrl | |
| #define PTR_SRLV dsrlv | |
| #define PTR_SRA dsra | |
| #define PTR_SRAV dsrav | |
| #define PTR_SCALESHIFT 3 | |
| #define PTR_WD .dword | |
| #define PTRSIZE 8 | |
| #define PTRLOG 3 | |
| #endif | |
| /* | |
| * Some cp0 registers were extended to 64bit for MIPS III. | |
| */ | |
| #if (_MIPS_SIM == _MIPS_SIM_ABI32) | |
| #define MFC0 mfc0 | |
| #define MTC0 mtc0 | |
| #endif | |
| #if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) | |
| #define MFC0 dmfc0 | |
| #define MTC0 dmtc0 | |
| #endif | |
| #define SSNOP sll zero, zero, 1 | |
| /* | |
| * Using a branch-likely instruction to check the result of an sc instruction | |
| * works around a bug present in R10000 CPUs prior to revision 3.0 that could | |
| * cause ll-sc sequences to execute non-atomically. | |
| */ | |
| #ifdef CONFIG_WAR_R10000_LLSC | |
| # define SC_BEQZ beqzl | |
| #elif !defined(CONFIG_CC_HAS_BROKEN_INLINE_COMPAT_BRANCH) && MIPS_ISA_REV >= 6 | |
| # define SC_BEQZ beqzc | |
| #else | |
| # define SC_BEQZ beqz | |
| #endif | |
| #ifdef CONFIG_SGI_IP28 | |
| /* Inhibit speculative stores to volatile (e.g.DMA) or invalid addresses. */ | |
| #include <asm/cacheops.h> | |
| #define R10KCBARRIER(addr) cache Cache_Barrier, addr; | |
| #else | |
| #define R10KCBARRIER(addr) | |
| #endif | |
| #endif /* __ASM_ASM_H */ |