| /* Copyright (C) 1997, 1998, 2002, 2003 Free Software Foundation, Inc. |
| This file is part of the GNU C Library. |
| Contributed by Ralf Baechle <ralf@gnu.org>. |
| |
| The GNU C Library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Lesser General Public |
| License as published by the Free Software Foundation; either |
| version 2.1 of the License, or (at your option) any later version. |
| |
| The GNU C Library is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| Lesser General Public License for more details. |
| |
| You should have received a copy of the GNU Lesser General Public |
| License along with the GNU C Library; if not, write to the Free |
| Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 02111-1307 USA. */ |
| |
| #ifndef _SYS_ASM_H |
| #define _SYS_ASM_H |
| |
| #include <sgidefs.h> |
| |
| #ifndef CAT |
| # ifdef __STDC__ |
| # define __CAT(str1,str2) str1##str2 |
| # else |
| # define __CAT(str1,str2) str1/**/str2 |
| # endif |
| # define CAT(str1,str2) __CAT(str1,str2) |
| #endif |
| |
| /* |
| * Macros to handle different pointer/register sizes for 32/64-bit code |
| * |
| * 64 bit address space isn't used yet, so we may use the R3000 32 bit |
| * defines for now. |
| */ |
| #if (_MIPS_SIM == _MIPS_SIM_ABI32) || (_MIPS_SIM == _MIPS_SIM_NABI32) |
| # define PTR .word |
| # define PTRSIZE 4 |
| # define PTRLOG 2 |
| #elif (_MIPS_SIM == _MIPS_SIM_ABI64) |
| # define PTR .dword |
| # define PTRSIZE 8 |
| # define PTRLOG 3 |
| #endif |
| |
| /* |
| * PIC specific declarations |
| */ |
| #if (_MIPS_SIM == _MIPS_SIM_ABI32) |
| # ifdef __PIC__ |
| # define CPRESTORE(register) \ |
| .cprestore register |
| # define CPLOAD(register) \ |
| .cpload register |
| # else |
| # define CPRESTORE(register) |
| # define CPLOAD(register) |
| # endif |
| |
| # define CPADD(register) \ |
| .cpadd register |
| |
| /* |
| * Set gp when at 1st instruction |
| */ |
| # define SETUP_GP \ |
| .set noreorder; \ |
| .cpload $25; \ |
| .set reorder |
| /* Set gp when not at 1st instruction */ |
| # define SETUP_GPX(r) \ |
| .set noreorder; \ |
| move r, $31; /* Save old ra. */ \ |
| bal 10f; /* Find addr of cpload. */ \ |
| nop; \ |
| 10: \ |
| .cpload $31; \ |
| move $31, r; \ |
| .set reorder |
| # define SETUP_GPX_L(r, l) \ |
| .set noreorder; \ |
| move r, $31; /* Save old ra. */ \ |
| bal l; /* Find addr of cpload. */ \ |
| nop; \ |
| l: \ |
| .cpload $31; \ |
| move $31, r; \ |
| .set reorder |
| # define SAVE_GP(x) \ |
| .cprestore x /* Save gp trigger t9/jalr conversion. */ |
| # define SETUP_GP64(a, b) |
| # define SETUP_GPX64(a, b) |
| # define SETUP_GPX64_L(cp_reg, ra_save, l) |
| # define RESTORE_GP64 |
| # define USE_ALT_CP(a) |
| #else /* (_MIPS_SIM == _MIPS_SIM_ABI64) || (_MIPS_SIM == _MIPS_SIM_NABI32) */ |
| /* |
| * For callee-saved gp calling convention: |
| */ |
| # define SETUP_GP |
| # define SETUP_GPX(r) |
| # define SETUP_GPX_L(r, l) |
| # define SAVE_GP(x) |
| |
| # define SETUP_GP64(gpoffset, proc) \ |
| .cpsetup $25, gpoffset, proc |
| # define SETUP_GPX64(cp_reg, ra_save) \ |
| move ra_save, $31; /* Save old ra. */ \ |
| .set noreorder; \ |
| bal 10f; /* Find addr of .cpsetup. */ \ |
| nop; \ |
| 10: \ |
| .set reorder; \ |
| .cpsetup $31, cp_reg, 10b; \ |
| move $31, ra_save |
| # define SETUP_GPX64_L(cp_reg, ra_save, l) \ |
| move ra_save, $31; /* Save old ra. */ \ |
| .set noreorder; \ |
| bal l; /* Find addr of .cpsetup. */ \ |
| nop; \ |
| l: \ |
| .set reorder; \ |
| .cpsetup $31, cp_reg, l; \ |
| move $31, ra_save |
| # define RESTORE_GP64 \ |
| .cpreturn |
| /* Use alternate register for context pointer. */ |
| # define USE_ALT_CP(reg) \ |
| .cplocal reg |
| #endif /* _MIPS_SIM != _MIPS_SIM_ABI32 */ |
| |
| /* |
| * Stack Frame Definitions |
| */ |
| #if (_MIPS_SIM == _MIPS_SIM_ABI32) |
| # define NARGSAVE 4 /* Space for 4 argument registers must be allocated. */ |
| #endif |
| #if (_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32) |
| # define NARGSAVE 0 /* No caller responsibilities. */ |
| #endif |
| |
| |
| /* |
| * LEAF - declare leaf routine |
| */ |
| #define LEAF(symbol) \ |
| .globl symbol; \ |
| .align 2; \ |
| .type symbol,@function; \ |
| .ent symbol,0; \ |
| symbol: .frame sp,0,ra |
| |
| /* |
| * NESTED - declare nested routine entry point |
| */ |
| #define NESTED(symbol, framesize, rpc) \ |
| .globl symbol; \ |
| .align 2; \ |
| .type symbol,@function; \ |
| .ent symbol,0; \ |
| symbol: .frame sp, framesize, rpc |
| |
| /* |
| * END - mark end of function |
| */ |
| #ifndef END |
| # define END(function) \ |
| .end function; \ |
| .size function,.-function |
| #endif |
| |
| /* |
| * EXPORT - export definition of symbol |
| */ |
| #define EXPORT(symbol) \ |
| .globl symbol; \ |
| symbol: |
| |
| /* |
| * ABS - export absolute symbol |
| */ |
| #define ABS(symbol,value) \ |
| .globl symbol; \ |
| symbol = value |
| |
| #define PANIC(msg) \ |
| .set push; \ |
| .set reorder; \ |
| la a0,8f; \ |
| jal panic; \ |
| 9: b 9b; \ |
| .set pop; \ |
| TEXT(msg) |
| |
| /* |
| * Print formated string |
| */ |
| #define PRINT(string) \ |
| .set push; \ |
| .set reorder; \ |
| la a0,8f; \ |
| jal printk; \ |
| .set pop; \ |
| TEXT(string) |
| |
| #define TEXT(msg) \ |
| .data; \ |
| 8: .asciiz msg; \ |
| .previous; |
| |
| /* |
| * Build text tables |
| */ |
| #define TTABLE(string) \ |
| .text; \ |
| .word 1f; \ |
| .previous; \ |
| .data; \ |
| 1: .asciz string; \ |
| .previous |
| |
| /* |
| * MIPS IV pref instruction. |
| * Use with .set noreorder only! |
| * |
| * MIPS IV implementations are free to treat this as a nop. The R5000 |
| * is one of them. So we should have an option not to use this instruction. |
| */ |
| #if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \ |
| (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64) |
| # define PREF(hint,addr) \ |
| pref hint,addr |
| # define PREFX(hint,addr) \ |
| prefx hint,addr |
| #else |
| # define PREF |
| # define PREFX |
| #endif |
| |
| /* |
| * MIPS ISA IV/V movn/movz instructions and equivalents for older CPUs. |
| */ |
| #if _MIPS_ISA == _MIPS_ISA_MIPS1 |
| # define MOVN(rd,rs,rt) \ |
| .set push; \ |
| .set reorder; \ |
| beqz rt,9f; \ |
| move rd,rs; \ |
| .set pop; \ |
| 9: |
| # define MOVZ(rd,rs,rt) \ |
| .set push; \ |
| .set reorder; \ |
| bnez rt,9f; \ |
| move rd,rt; \ |
| .set pop; \ |
| 9: |
| #endif /* _MIPS_ISA == _MIPS_ISA_MIPS1 */ |
| #if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) |
| # define MOVN(rd,rs,rt) \ |
| .set push; \ |
| .set noreorder; \ |
| bnezl rt,9f; \ |
| move rd,rs; \ |
| .set pop; \ |
| 9: |
| # define MOVZ(rd,rs,rt) \ |
| .set push; \ |
| .set noreorder; \ |
| beqzl rt,9f; \ |
| movz rd,rs; \ |
| .set pop; \ |
| 9: |
| #endif /* (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) */ |
| #if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \ |
| (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64) |
| # define MOVN(rd,rs,rt) \ |
| movn rd,rs,rt |
| # define MOVZ(rd,rs,rt) \ |
| movz rd,rs,rt |
| #endif /* (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) */ |
| |
| /* |
| * Stack alignment |
| */ |
| #if (_MIPS_SIM == _MIPS_SIM_ABI64) || (_MIPS_SIM == _MIPS_SIM_NABI32) |
| # define ALSZ 15 |
| # define ALMASK ~15 |
| #else |
| # define ALSZ 7 |
| # define ALMASK ~7 |
| #endif |
| |
| /* |
| * Size of a register |
| */ |
| #if (_MIPS_SIM == _MIPS_SIM_ABI64) || (_MIPS_SIM == _MIPS_SIM_NABI32) |
| # define SZREG 8 |
| #else |
| # define SZREG 4 |
| #endif |
| |
| /* |
| * Use the following macros in assemblercode to load/store registers, |
| * pointers etc. |
| */ |
| #if (SZREG == 4) |
| # define REG_S sw |
| # define REG_L lw |
| #else |
| # define REG_S sd |
| # define REG_L ld |
| #endif |
| |
| /* |
| * How to add/sub/load/store/shift C int variables. |
| */ |
| #if (_MIPS_SZINT == 32) |
| # define INT_ADD add |
| # define INT_ADDI addi |
| # define INT_ADDU addu |
| # define INT_ADDIU addiu |
| # define INT_SUB add |
| # define INT_SUBI subi |
| # define INT_SUBU subu |
| # define INT_SUBIU subu |
| # define INT_L lw |
| # define INT_S sw |
| #endif |
| |
| #if (_MIPS_SZINT == 64) |
| # define INT_ADD dadd |
| # define INT_ADDI daddi |
| # define INT_ADDU daddu |
| # define INT_ADDIU daddiu |
| # define INT_SUB dadd |
| # define INT_SUBI dsubi |
| # define INT_SUBU dsubu |
| # define INT_SUBIU dsubu |
| # define INT_L ld |
| # define INT_S sd |
| #endif |
| |
| /* |
| * How to add/sub/load/store/shift C long variables. |
| */ |
| #if (_MIPS_SZLONG == 32) |
| # define LONG_ADD add |
| # define LONG_ADDI addi |
| # define LONG_ADDU addu |
| # define LONG_ADDIU addiu |
| # define LONG_SUB add |
| # define LONG_SUBI subi |
| # define LONG_SUBU subu |
| # define LONG_SUBIU subu |
| # define LONG_L lw |
| # define LONG_S sw |
| # define LONG_SLL sll |
| # define LONG_SLLV sllv |
| # define LONG_SRL srl |
| # define LONG_SRLV srlv |
| # define LONG_SRA sra |
| # define LONG_SRAV srav |
| #endif |
| |
| #if (_MIPS_SZLONG == 64) |
| # define LONG_ADD dadd |
| # define LONG_ADDI daddi |
| # define LONG_ADDU daddu |
| # define LONG_ADDIU daddiu |
| # define LONG_SUB dadd |
| # define LONG_SUBI dsubi |
| # define LONG_SUBU dsubu |
| # define LONG_SUBIU dsubu |
| # define LONG_L ld |
| # define LONG_S sd |
| # define LONG_SLL dsll |
| # define LONG_SLLV dsllv |
| # define LONG_SRL dsrl |
| # define LONG_SRLV dsrlv |
| # define LONG_SRA dsra |
| # define LONG_SRAV dsrav |
| #endif |
| |
| /* |
| * How to add/sub/load/store/shift pointers. |
| */ |
| #if (_MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32) |
| # define PTR_ADD add |
| # define PTR_ADDI addi |
| # define PTR_ADDU addu |
| # define PTR_ADDIU addiu |
| # define PTR_SUB add |
| # define PTR_SUBI subi |
| # define PTR_SUBU subu |
| # define PTR_SUBIU subu |
| # define PTR_L lw |
| # define PTR_LA la |
| # define PTR_S sw |
| # 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 |
| #endif |
| |
| #if _MIPS_SIM == _MIPS_SIM_NABI32 |
| # define PTR_ADD add |
| # define PTR_ADDI addi |
| # define PTR_ADDU add /* no u */ |
| # define PTR_ADDIU addi /* no u */ |
| # define PTR_SUB add |
| # define PTR_SUBI subi |
| # define PTR_SUBU sub /* no u */ |
| # define PTR_SUBIU sub /* no u */ |
| # define PTR_L lw |
| # define PTR_LA la |
| # define PTR_S sw |
| # 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 |
| #endif |
| |
| #if (_MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 64 /* o64??? */) \ |
| || _MIPS_SIM == _MIPS_SIM_ABI64 |
| # define PTR_ADD dadd |
| # define PTR_ADDI daddi |
| # define PTR_ADDU daddu |
| # define PTR_ADDIU daddiu |
| # define PTR_SUB dadd |
| # define PTR_SUBI dsubi |
| # define PTR_SUBU dsubu |
| # define PTR_SUBIU dsubu |
| # define PTR_L ld |
| # define PTR_LA dla |
| # define PTR_S sd |
| # 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 |
| #endif |
| |
| /* |
| * Some cp0 registers were extended to 64bit for MIPS III. |
| */ |
| #if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \ |
| (_MIPS_ISA == _MIPS_ISA_MIPS32) |
| # define MFC0 mfc0 |
| # define MTC0 mtc0 |
| #endif |
| #if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \ |
| (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64) |
| # define MFC0 dmfc0 |
| # define MTC0 dmtc0 |
| #endif |
| |
| #endif /* sys/asm.h */ |